Q:

Variable in jQuery animation callback causes scope confusion in parent loop

I've seen many answers about using closures in JS but nothing that I could adapt to my situation:
I have many words sprawled randomly across the browser window at various sizes and positions.
This function would shrink them all down to the same size, then position them side-by-side, one after the other, left to right (re-ordering the words into a sentence).
function alignWords() {

    // starting X position
    var x_align = 100;  

    // loop thru each word, shrink its size (ie. font-size) and position them end-to-end on X axis (with 5px spacing)
    $('.other-word').each(function(index, item){
        $(item).toggleClass("other-word-animate");

        console.log("t- x1 = "+ x_align)        // does not increment. Outputs: t- x1 = 100, t- x1 = 100, t- x1 = 100, etc...

        $(item).animate({
            'font-size': $('.main-word').css("font-size").substr(0, $('.main-word').css("font-size").length-2),
            top: $('.main-word').css("top"),
            left: x_align                       // always remains 100, which is wrong
        }, function() {
            x_align += $(this).width() + 5;
            console.log("t- x = "+ x_align);    // increments correctly. Outputs: t- x = 154, t- x = 311, t- x = 316, etc...
        });

    });
}

My incrementing of x_align in the animate() callback is not being reflected in the subsequent loop at left: x_align.
Help much appreciated,

A:

All the callbacks are run long after the animation are started (they're all started at the same time). Your goal isn't 100% clear but you probably want to chain the animation, not run them in parallel like this for example :
var x_align = 100,
    otherWords = $('.other-word'),
    fontSize = $('.main-word').css("font-size").slice(0, -2),
    top = $('.main-word').css("top"),
    i = 0, n = otherWords.length;
(function doOne(){
    if (i++>=n) return;
    otherWords.eq(i).toggleClass("other-word-animate")
    .animate({
        fontSize: fontSize,
        top: top,
        left: x_align
    }, function(){
        x_align += $(this).width() + 5;
        doOne();
    });
})();

