Randomise delay on multiple elements

Hi all, I have written this to make a number of elements pop out slightly on the page, basically to show the user that they require attention. It has a slight delay so that the page loads and then runs.


$(".shown").delay(400).animate({left:'7px'},{duration:200, easing:'swing'})
$(".shown").animate({left:'0px'}, 350)

What I would like is for this to cycle through each element on the page one by one (there could be between 1 and 10) with a slight delay so they don’t move in unison.

But also to randomise this so that so that it doesn’t just appear to work through them in order they appear in the markup.

Hope this makes sense and that it’s doable!

Many thanks

What you’ll want is an array-like collection of the elements you want to be animated.

You can then randomize that collection.

You can then use a function that pops off one of the elements from that random collection and animates that element.

After the animation is completed, you can use the animations callback parameter, to call that same function, until there’s nothing left.

Hi Paul,

Apologies for the delay, I didn’t get an email notification! This sounds great, could you help me write this out? My JS knowledge is very minimal, took me all my might to write that!

Many thanks

What HTML/CSS are you starting from?


<a href="#" class="case"> <img src="images/case3.jpg" alt="" />
		        <p class="shown"><span>&pound;15m extra sales in the first six months</span></p>
		        <p class="hidden"><span>Company name Read more</span></p>
		        </a>

Did you know that it’s invalid for anchors to contain paragraphs, or other block-level elements?

You can use a span though, and set its CSS to display as a block if you want to simulate a paragraph.

Hi Paul, yes I know, I’m using a HTML5 doctype so all is well :slight_smile: Will that effect the JS?

You may find that browsers like IE7 and IE8 may have trouble there.

Hopefully not.

Hi Paul, I’ll change the HTML if I encounter issues in IE. Are you still ok to help me write the JS?

Cheers

Yes, but before I begin I want to start from a test page that shows the effect that you currently have.

What CSS do you use with that HTML, that allows animated effect to occur.
Currently without any styling the effect is denied.

Ok thanks, I’ve attached an example here.

www.mikeebee.com/other/html.zip

Thanks, now where’s that list.

[list=1][]What you’ll want is an array-like collection of the elements you want to be animated.
[
]You can then randomize that collection.
[]You can then use a function that pops off one of the elements from that random collection and animates that element.
[
]After the animation is completed, you can use the animations callback parameter, to call that same function, until there’s nothing left.[/list]

So, first thing - an array-like collection of the elements you want to be animated.

We can make that an actual array.


var shown = $(".shown").toArray();

Step 2 is to randomize them.


shown.sort(function () {
    return (Math.round(Math.random())-0.5);
});

Now we have an array of randomly sorted items.

Step 3, is to use a function that pops off one of the elements from that random collection and animates that element


function performAnimation(arr) {
    var el = arr.pop();
    $(el).animate({left:'7px'}, 300);
    $(el).animate({left:'0px'}, 300);
}
...
performAnimation(shown);

And step 4 is that after the animation is completed, you can use the animations callback parameter, to call that same function, until there’s nothing left.


function performAnimation(arr) {
    var el = arr.pop();
    $(el).animate({left:'7px'}, 300, function () {
        performAnimation(arr);
    });
    $(el).animate({left:'0px'}, 300);
}

Let’s now tidy that up by moving the animate 0 part in to the same callback function, where the this keyword can be used, which also means that we don’t need the el variable anymore.


function performAnimation(arr) {
    $(arr.pop()).animate({left:'7px'}, 300, function () {
        $(this).animate({left:'0px'}, 300);
        performAnimation(arr);
    });
}

We can even tidy up the shown variable and sorting part, so that it now becomes:


performAnimation($(".shown")
    .toArray()
    .sort(function () {
        return (Math.round(Math.random())-0.5);
    })
);

The complete code after all of that is:


function performAnimation(arr) {
    $(arr.pop()).animate({left:'7px'}, 300, function () {
        $(this).animate({left:'0px'}, 300);
        performAnimation(arr);
    });
}
performAnimation($(".shown")
    .toArray()
    .sort(function () {
        return (Math.round(Math.random())-0.5);
    })
);

That’s brilliant thank you! And thanks for the detailed explanation that’s really helpful. Is it possible to delay the first function running after page load as it was before? I tried adding a delay in various places but it didn’t work.

setTimeout can be used for that.


setTimeout(function () {
    ...
}, duration);

In this case it would be:


setTimeout(function () {
    performAnimation($(".shown")
        .toArray()
        .sort(function () {
            return (Math.round(Math.random())-0.5);
        })
    );
}, 400);

Hi, thanks fort getting back to me. That doesn’t appear to be working. I have updated the link to the files with the current script. Could you have a look please?

www.mikeebee.com/other/html.zip

Oh yes, there was a silly mistake in my post, sorry. The function should come first before the duration.

I have now updated my post, and you should find on updating your code that it works as expected.

Thats cracked it! Thanks for all your help.