1

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,

jcnesci
  • 91
  • 2
  • 10
  • 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. – Denys Séguret Jan 08 '14 at 10:25
  • What do you mean by "x_align does not increment"? I do not see a statement for that?!? – loveNoHate Jan 08 '14 at 10:46
  • @dystroy Yes my problem is that the value assigned to `x_align` in the callback is not reflected in the next each-loop iteration when we use it at `left: x_align`. You're right that it is because things are not properly run in sequence. I'm looking for a way to do that, if you know how, thanks! – jcnesci Jan 08 '14 at 16:59
  • @dollarvar When I say "incrementing" I mean changing its value at `x_align += $(this).width() + 5;`. Sorry for the confusion. I read other posts about how closures can help make my `x_align` maintain it's newly incremented value at every loop, but I couldn't make it work... – jcnesci Jan 08 '14 at 17:01
  • @JCNesci OK, wrote something that should work (untested of course). – Denys Séguret Jan 08 '14 at 17:04

1 Answers1

1

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();
    });
})();
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • @JC Nesci: Does that work? I guess you need something like this http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language. So your first line would be: `var x={align:100};`. In the function you would have to do: `x.align += $(this).width() + 5;`. Check it out ;) – loveNoHate Jan 08 '14 at 17:19
  • @dollarvar That's an interesting side note there. I don't understand your last sentence about `x_align += ...` though. Would be great if you could clarify! Thanks! – jcnesci Jan 09 '14 at 20:31
  • This answer solves my problem about having `x_align`'s value saved properly for every loop. Thanks a lot! I wonder, is there a proper name for this type of pattern? – jcnesci Jan 09 '14 at 20:33
  • I don't know. I make it from time to time, don't know if it's common. It includes an IIFE (I let you google that) but it's named to allow recursion. So I guess you could call that *a recursive named IIFE*... – Denys Séguret Jan 09 '14 at 20:40
  • Note also that if you're deeply interested in ways to handle asynchronicity in JS you might want to learn a little about promises (and I recommend BlueBird.js). But be warned that it's both interesting and hard :) – Denys Séguret Jan 09 '14 at 20:41
  • @jcnesci I thought you needed the x align updated outside of the function, because you asked for updated figure outside of your `.animate()`. This would have had to be "Pass by reference" (Not quite clear how to call it in JavaScript). Hope that helps. – loveNoHate Jan 09 '14 at 21:14