0

I have a javascript object that looks like this,

var telephones = {
        /*
        "phone" : {
            duration    :   time it takes to animate element in,
            leftIn      :   position of element once on the incoming animation
            leftOut     :   position of element on the outgoing animation
            delay       :   delay between two animations
        }
        */
        "phone1": {
            duration    :   850,
            leftIn      :   "408px",
            leftOut     :   "9999px",
            delay       :   0,
        },
        "phone2" : {
            duration    :   600,
            leftIn      :   "962px",
            leftOut     :   "999px",
            delay       :   setDelay(),
        },
        "phone3" : {
            duration    :   657,
            leftIn      :   "753px",
            leftOut     :   "9999px",
            delay       :   0,
        },
        "phone4" : {
            duration    :   900,
            leftIn      :   "1000px",
            leftOut     :   "9999px",
            delay       :   setDelay(),
        },
        "phone5" : {
            duration    :   1200,
            leftIn      :   "800px",
            leftOut     :   "9999px",
            delay       :   0,
        },
        "phone6" : {
            duration    :   792,
            leftIn      :   "900px",
            leftOut     :   "9999px",
            delay       :   setDelay(),
        },

    };

I am using the above object to try an animate individual elements within a slide, that is already animated via the jquery cycle plugin. I am using the code in the following way,

$('#slideshow').cycle({
    fx: 'scrollHorz',
    before  :   triggerParralex,
    after   :   removeParralex,
    easing  :   'easeOutCubic',
    speed   :   2000
});

so the code above initiates the cycle plugin. And then I am using the before and after callbacks to run 2 more functions, these functions look like this,

function bgChange(curr, next, opts) {
    var background = $(".current").attr('data-background');
    $.backstretch(background, {target: "#backstrectch", centeredY: true, speed: 800});
}

function triggerParralex(curr, next, opts) {
    //move any phones that are in the viewport
    for (var key in telephones) {
        var obj = telephones[key];
        for (var prop in obj) {
            if($(".current ." + key).length) { //does .custom .phone1/2/3/4/5/6 exist if it does we can carry on
                setTimeout(function() {
                    $(".current ." + key).animate({
                        "left"      :   obj["leftOut"],
                        "opacity"   :   0
                    }, obj["duration"]);
                }, obj["delay"]);
            }
        }
    }

    //change the background
    bgChange();

    //remove the current class from the DIV
    $(this).parent().find('section.current').removeClass('current');

}

function removeParralex(curr, next, opts) {

    //give the slide a current class so that we can identify it.
    $(this).addClass('current');

    //animate in any phones that belong to the current slide
    for (var key in telephones) {
        var obj = telephones[key];
        for (var prop in obj) {
            console.log(obj["leftIn"])
            if($(".current ." + key).length) { //does .custom .phone1/2/3/4/5/6 exist if it does we can carry on
                setTimeout(function() {
                    $(".current .phone1").animate({
                        "left"      :   obj["leftIn"],
                        "opacity"   :   1
                    }, obj["duration"]);
                }, obj["delay"]);
            }
        }
    }

}

My problems are the following,

I am trying animate the images that are in my section elements, the section elements are what are already sliding via the cycle plugin, and this to me feels like it is stopping my images being animated at later stage?

The second problem seems to be that while my script will happily find $(".current .phone1") is only seems to add the properties of phone6 from the object, I have made a fiddle.

As you can see from the fiddle the sections with #slideshow are cycling however the images within them are not being animated...why?

Udders
  • 6,914
  • 24
  • 102
  • 194
  • 1
    You are creating a function inside a loop. Please see [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) for an explanation and solution to this problem. – Felix Kling Jul 20 '12 at 14:54
  • Thanks, but can you point where I am creating the function? – Udders Jul 20 '12 at 15:00
  • `setTimeout(function() {....})`... when the callback is executed, `obj` will have the value of the last iteration of the loop. Also, I don't think you want to iterate over each property of the "animation objects" that does not seem to make sense. – Felix Kling Jul 20 '12 at 15:04
  • Thanks, I have read that link you left me, but I dont really understand how to fix my code...any clues? – Udders Jul 20 '12 at 15:06

1 Answers1

0

As Felix Kling said in comment, you have a classical "closure inside loop" problem.

Here's a (classical) solution :

for (var key in telephones) {
    if($(".current ." + key).length) { //does .custom .phone1/2/3/4/5/6 exist if it does we can carry on
        var obj = telephones[key];
        (function(obj){
            setTimeout(function() {
                $(".current .phone1").animate({
                    "left"      :   obj["leftIn"],
                    "opacity"   :   1
                }, obj["duration"]);
            }, obj["delay"]);
        })(obj);
    }
}

The idea is to embbed obj in another closure, isolating it from the loop, and thus preventing its change.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Although the self-invoking function is a closure as well, the important aspect of this solution is that the function is *executed* immediately and therefore resolves the variables at that moment (and not later). – Felix Kling Jul 20 '12 at 15:17
  • Thanks for this fix, I have tried to implement but I am still having troubles, would be so can to edit my fiddle with the fix, so I can see it in action? – Udders Jul 20 '12 at 15:17
  • I edited with some cleaning. There were strange things in the loop. – Denys Séguret Jul 20 '12 at 15:17
  • @dystroy where have you edited? My fiddle? Is there a link to your edits? – Udders Jul 20 '12 at 15:20
  • I edited my answer. But I just illustrated the closure problem and I look at the remaining possible js problems, I don't try to analyze your whole page which uses plugins I don't want to learn (cycle and backstretch at least). – Denys Séguret Jul 20 '12 at 15:23
  • That is fine, the problem lies withing these closures I think, but the new code does not seem to be firing at all. – Udders Jul 20 '12 at 15:25
  • It's hard to test your fiddle as the images are given as relative links and thus not loaded. – Denys Séguret Jul 20 '12 at 15:30