Grid XML gallery

I am using Ben Cline’s xml grid gallery. I sliced a single image into 48 thumbs, 6 rows, 8 columns.

The one issue I have is that only 47 thumbs out of the 48 display. The bottom right corner is empty even though there is a 48th image that has loaded. I have pored over the AS but can not figure out why. I did notice in Ben’s example he had an odd number of thumbs, 25 to be exact and his ended with one thumb in the last column.

  // ===============================================================================================================================================

// code by Ben Cline November, 2006 - http://www.bencline.net

// ===============================================================================================================================================

import mx.transitions.Tween;
import mx.transitions.easing.*;
import flash.filters.BlurFilter;

// ===============================================================================================================================================

// +            +            +             VARIABLES            +                +                +                +                +                +

// ===============================================================================================================================================

var path        : String = "photos.xml"; // path used for the xml, but for source code, I've included the xml file
var xmlThumb    : String; // url for the thumbnails
var thumbString    : String = "LOADING THUMBNAILS"; // string called before the first thumbnail is loaded
var dupThumb    : String;
var s            : Number = 0; // spacing between the thumbnails
var rows        : Number = 8; // number of rows
var curr        : Number = 0; // current thumb
var currAn        : Number = 0; // var for counting through the animation sequences
var cols        : Number = 6; // number of columns
var tW            : Number = 50; // thumb width
var tH            : Number = 50; // thumb height
var xP            : Number = 0; // x position
var yP            : Number = 0; // y position
var xR            : Number; // random x position
var yR            : Number; // random y position
var r_w_h        : Number; // random width and height
var tN            : Number; // total nodes from xml
var l            : Number; // bytes loaded
var t            : Number; // bytes total
var percent        : Number; // percent loaded
var tweenRate    : Number = 0.2; // tween rate for the thumbs
var blur        : Number;
var tweenProp    : Number; // tween proportion that will be subtracted from the tween rate
var newBlur        : BlurFilter;
var gridXML        : XML; // xml object
var temp_mc        : MovieClip; // temporary movie clip for loading purposes
var thumbHolder    : MovieClip = this.createEmptyMovieClip("holder_mc", this.getNextHighestDepth()); // movie clip that holds all the thumbnails
var mc            : MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth()); // mc for the loaded images, that will show up when you click something
var thumb        : MovieClip; // movie clip that holds the movie clip that the thumb will be loaded into
var button        : MovieClip; // movie clip that the thumb will be loaded into
var tA            : Array = new Array(); // thumb array, that will be tweened
var mA            : Array = new Array(); // movie clip array that holds the mc's that the thumbs will be loaded into
var xPA            : Array = new Array(); // x position array
var yPA            : Array = new Array(); // y position array
var xRA            : Array = new Array(); // random x position array
var yRA            : Array = new Array(); // random y position array
var r_w_h_array    : Array = new Array(); // random width, height array
var blurArray    : Array = new Array();
var filterArray    : Array = new Array();
var path_a        : Array = new Array(); // path to the file array
var tweenThumb_h: Tween; // tween the thumb height object
var tweenThumb_w: Tween; // tween the thumb width object
var tweenThumb_x: Tween; // tween the thumb x position object
var tweenThumb_y: Tween; // tween the thumb y position object
var tweenThumb_a: Tween; // tween the thumb alpha object
var myTween        : Tween; // tween for blurs
var textFormat    : TextFormat = new TextFormat(); // text format object
var thumbText    : TextField = this.createTextField("thumbText", this.getNextHighestDepth(), -20, -20, 0, 0, 10); // new textfield to show how many thumbnails have been loaded

// ===============================================================================================================================================

// +            +            +             TEXT FORMATTING            +                +                +                +                +                +

// ===============================================================================================================================================

thumbText.antiAliasType = "advanced"; 
textFormat.color = 0x000000;
textFormat.font = "Verdana";
textFormat.size = 10;
thumbText.autoSize = true;
thumbText.border = false;
thumbText.type = "static";
thumbText.multiline = false;
thumbText.text = thumbString;
thumbHolder._x = 20;
thumbHolder._y = thumbText._y+thumbText._height+10;

// ===============================================================================================================================================

// +            +            +             XML ON LOAD            +                +                +                +                +                +

// ===============================================================================================================================================

gridXML = new XML();
gridXML.ignoreWhite = true;
gridXML.load(path);

mc._y = 300;
mc._x = 20;

gridXML.onLoad = setUpGrid;

function setUpGrid():Void {
    tN = gridXML.firstChild.childNodes[0].childNodes.length; // get the total nodes from the xml
    cols = Math.ceil(tN/rows); // divide the number of total nodes by the number of rows set up, rounded up to the nearest integer
    tweenProp = tweenRate/(tN+10); // get the proportion of the tween rate, so we can speed up the tweens of the thumbs in, every time a new thumb is loaded
    thumbText.text = "0 / "+tN+" THUMBNAILS LOADED"; // set up the text, initially there are 0 out of how ever many thumbs there are to be loaded
    for (var i = 0; i<tN; i++) { // okay the fun part, in order to set up a grid layout, we have to have 2 nested for loops, don't ask why...., the first we loop through the total number of nodes
        for (var r = 0; r<rows; r++) { // then we loop through the total number of rows
            for (var c = 0; c<cols; c++) { // lastly we loop through the total number of columns
                thumb = thumbHolder.createEmptyMovieClip("thumb_mc"+i, i); // while looping, we need to create empty movie clips to hold the thumbs, this movie clip will be used as the button
                button = thumb.createEmptyMovieClip("button_mc"+i, i); // this movie clip we will eventually load thumbs into
                xmlThumb = gridXML.firstChild.childNodes[0].childNodes*.attributes.thumb; // get all the urls of the thumbnails
                if (xmlThumb !== undefined) { // make sure that none of the urls are undefined, which basically means there will be undefined urls if there is not
                    // a clean divide of rows by the total number of columns
                    thumb._alpha = 0; // set the initial opacity to zero
                    thumb._visible = false;
                    xP = Math.ceil((s+tW)*r); // okay here we determine our x value on the grid for a thumb, basically we're adding the spacing to the thumb width and then multiplying
                    // that by our current r variable which is whatever r is at this point in time in our loop
                    yP = Math.ceil((s+tH)*c); // this is the same as above only it holds the y value in our grid
                    xR = Math.ceil(Math.random()*Stage.width); // here we get a random x value where we will eventually animate our thumbs from
                    yR = Math.ceil(Math.random()*Stage.height); // this is the same as above only it is the y value
                    blur = Math.random()*Stage.width;
                    r_w_h = Math.ceil(Math.random()*Stage.width); // variable that gives a random width and height to work with
                    tA.push(thumb); // okay, push the thumb movie clip into an array that will be used for animating
                    mA.push(button); // push the button movie clip which remember is an empty movie clip inside the thumb movie clip that we will load our images into
                    xPA.push(xP); // push the x position in the grid to an array
                    yPA.push(yP); // push the y position in the grid to an array
                    xRA.push(xR); // push the x random position into an array
                    yRA.push(yR); // ""    "" y  ""        ""          "" ""  ""
                    r_w_h_array.push(r_w_h); // push the random width and height into an array
                    path_a.push(xmlThumb); // push the urls of thumbs into an array
                    blurArray.push(blur);
                    
                    i++; // okay for this nested to work, we have increment the i value which is the current number we're on of the total nodes
                    if (i == tN-1) { // once i has reach the end
                        loadThumb(path_a[curr], mA[curr]); // load the first node
                        break; // we have to break the for loop as well
                    }
                }
            }
        }
    }
}

// ===============================================================================================================================================

// +            +            +             THUMB LOADER        +                +                +                +                +                +

// ===============================================================================================================================================

// function requires 2 parameters, the url of the thumb, and movie clip we need to load the thumb into
function loadThumb(path_url:String, mc:MovieClip) {
    mc.loadMovie(path_url); // load the thumb into the movie clip
    temp_mc = _root.createEmptyMovieClip("temp_mc", _root.getNextHighestDepth()); // create a temporary movie clip to handle our onEnterFrame event
    temp_mc.onEnterFrame = function() {
        l = mc.getBytesLoaded(); // get the bytes loaded
        t = mc.getBytesTotal(); // get the bytes total
        percent = l/t; // get the percent between the two
        if (percent>=1) { // if the percent is greater to our equal to 1, this means the thumbnail is loaded
            curr++;
            if(curr <= tN-1) {
                loadThumb(path_a[curr], mA[curr]);
                thumbText.text = (curr+1)+" / "+tN+" THUMBNAILS LOADED";
            }
            else {
                thumbText.text = (curr--)+" / "+tN+" THUMBNAILS LOADED";
                animate(tA[currAn], xRA[currAn], xPA[currAn], yRA[currAn], yPA[currAn], r_w_h_array[currAn], blurArray[currAn]);
            }// for a little extra flare, lets animate the thumb into the grid from a random position
             // set up the text properly
            temp_mc.removeMovieClip(); // delete the onEnterFrame event
        }
    };
}

// ===============================================================================================================================================

// +            +            +             ENABLE BUTTON STATES        +                +                +                +                +            +

// ===============================================================================================================================================

function enableButtons():Void {
    // okay note that when we need to access all of the thumbs at once and we are outside the initial for loop, we have create another one
    for (var i = 0; i<tN; i++) {
        // this provides the unique identifier to each thumbnail, which is critical for this to work
        var thumb:MovieClip = thumbHolder["thumb_mc"+i];
        dupThumb = gridXML.firstChild.childNodes[0].childNodes*.attributes.thumb;
        thumb.i = i;
        thumb.dupThumb = dupThumb;
        // rollover state
        thumb.onRollOver = function():Void  {
            // okay the way I set this up is when a thumb is rolled over, all of the other thumbs dim out, order to access all the other thumbs
            // we must create another for loop
            for (var i = 0; i<tN; i++) {
                // same as earlier, provides identification for the correct thumb
                var thumb:MovieClip = thumbHolder["thumb_mc"+i];
                // okay this refers to the current thumb being rolled over, and if this is not equal to our identifiers above, lets dim them out
                if (thumb !== this) {
                    new Tween(thumb, "_alpha", Strong.easeOut, thumb._alpha, 50, .5, true); // tween the opacity down of the other thumbs
                }
            }
        };
        // rollout state, same as above, only we tween all the other button alphas back to normal again
        thumb.onRollOut = function():Void  {
            for (var i = 0; i<tN; i++) {
                var thumb:MovieClip = thumbHolder["thumb_mc"+i];
                if (thumb !== this) {
                    new Tween(thumb, "_alpha", Strong.easeOut, thumb._alpha, 100, .5, true);
                }
            }
        };
        
        thumb.onRelease = function():Void {
            mc.loadMovie(this.dupThumb);
        }
    }
}

// ===============================================================================================================================================

// +            +            +             ANIMATE THUMBNAIL        +                +                +                +                +                +

// ===============================================================================================================================================

// function requires 6 parameters, a movie clip, a random x position, an x position in the grid, a random y position, a y position in the grid, and random width/height

function animate(thumbnail:MovieClip, randomX:Number, xPosition:Number, randomY:Number, yPosition:Number, width_height:Number, blurAmount:Number) {
    
    var myTween:Tween = new Tween(thumbnail, "blur", Strong.easeOut, blurAmount, 0, tweenRate, true);
    myTween.onMotionChanged = function() {
        thumbnail.filters = [new BlurFilter(thumbnail.blur, thumbnail.blur, 1)];
    }
    myTween.onMotionFinished = function() {
        new Tween(thumbnail, "blur", Strong.easeOut, blurAmount, 0, tweenRate, true);
    }
    
    
    thumbnail._visible = true;
    
    tweenThumb_w = new Tween(thumbnail, "_width", Strong.easeOut, width_height, tW, tweenRate, true);
    tweenThumb_h = new Tween(thumbnail, "_height", Strong.easeOut, width_height, tH, tweenRate, true);
    // tween the alpha in 
    tweenThumb_a = new Tween(thumbnail, "_alpha", Strong.easeOut, thumbnail._alpha, 100, tweenRate, true);
    // tween the x position from the random one to the one on the grid
    tweenThumb_x = new Tween(thumbnail, "_x", Strong.easeOut, randomX, xPosition, tweenRate, true);
    // tween the y position from the random one to the one on the grid
    tweenThumb_y = new Tween(thumbnail, "_y", Strong.easeOut, randomY, yPosition, tweenRate, true);
    tweenThumb_y.onMotionFinished = function():Void {
        currAn++;
        if(currAn <= tN-1 && path_a[currAn] !== undefined) {
            tweenRate += -(tweenProp);
            animate(tA[currAn], xRA[currAn], xPA[currAn], yRA[currAn], yPA[currAn], r_w_h_array[currAn], blurArray[currAn]);
        }
        else {
            enableButtons();
        }
    }

}