Search code examples
jqueryanimationdelaytiming

jQuery .delay() timing issue, not all the animations have a consistant delay?


I have a simle bit of jQuery code which hides a group of gallery objects when the controls are clicked, and then shows the filtered objects one by one.

The issue is that some of the delays are inconsistent and not evenly timed. The delay increments every time an object begins to fadein to make them appear one by one, but one or two appear at the same time on random occurances?

Heres the code:

$(document).ready(function() {

    var controls = $('#portfolio-nav'); 
    var gallery = $('#gallery');

    $('a', controls).click(function(){

        /* setup variables */
        var nav             = $(this).closest('ul');
        var listItem        = $(this).parent();
        var current         = 'current';
        var classes         = listItem.attr("class").split(/\s/);
        var elementsToShow  = new Array();
        var allElements     = gallery.children();

        /* filter classes to excude .current */
        classes = jQuery.grep(classes, function(value){
            return value != current;
        });
        var sector = classes[classes.length -1];

        /* remove all .current classes */
        nav.children('.current').each(function() {    
            $(this).removeClass('current');
        });

        /* add the .current class to the clicked li */
        $(this).parent().addClass('current');

        /* define which elements to show */
        $(allElements).each(function() {

            var element = $(this);          
            var elementSectors = element.attr("class").split(/\s/);

            if(sector !== 'all'){

                if(jQuery.inArray(sector, elementSectors) !== -1){
                    elementsToShow.push(element);
                }

            } else {
                elementsToShow.push(element);
            }

        });

        /* log the elements */
        //console.log(elementsToShow);

        /* hide/show all the elements */
        animateThem(allElements, elementsToShow);

        /* clear the array for the next click */
        elementsToShow.length = 0;

        return false;
    });

    function animateThem(allElements, elementsToShow){

        $(allElements).fadeOut('fast').delay(200);

        $(elementsToShow).each(function(index) {
            $(this).delay(100*index).fadeIn('normal');
        });

    }

});

Heres a quick snippet of the html:

<nav id="portfolio-nav">
    <ul>
        <li class="all current"><a href="#all">All</a></li>
        <li class="branding"><a href="#branding">Branding</a></li>
    </ul>
</nav>

<div id="gallery">
    <div class="grid-3 media-holder branding">
        ...
    </div>
    <div class="grid-3 media-holder marketing">
        ...
    </div>
</div>

Its probably an easy fix as my jQuery isn't great, but if anyone knows of a reason why this would happen I'd love to know.

Cheers,

Dave

Edit: Had issues with declaring the array elements and was getting an undeclared error...after some tweaking its working as expected (thanks to Dannie Hansen), JSFiddle is below if anyone is interested:

http://jsfiddle.net/daveaspinall/8VKad/9/


Solution

  • Not entirely sure, there could be some sort of timing issue.

    Why don't you give it a try using interval:

    var intCount = 0;
    var interval = setInterval(function () {
        if(typeof elementsToShow[intCount] != undefined) {
             if(elementsToShow[intCount] != "fired") {
                  elementsToShow[intCount].fadeIn('normal');
                  elementsToShow[intCount] = "fired";
                  intCount++;
             }
        } else {
        //End of array, clear the interval
             clearInterval(interval);
        }
    }, 100);
    

    That is how it could be done using an interval to time the events. Give it a try and report back if it worked :)

    Edit1 Edited to fix bug. - (Thanks to Brighty)

    Edit2 Fixed the fadeIn function. Give it a try now.