4

I'm building a portfolio page that has a list of different projects (in an unordered list). On page load I want to have each "li" to fade in, one after another. I have achieved this like so:

var eT = 0;     
$('.everything').hide().each(function() {
    $(this).delay(eT).fadeIn('slow');
    eT += 200;
});

The problem I am having is that each li will have a class (or multiple) based on the type of work (web, print, etc) it represents. There is a navigation to the side that will allow you to filter the type of work to display. What I have encountered is that if I click the filters, while the animation is still loading in items, things get really messy.

Here is the template of the work page currently: http://jjaakk.miller-interactive.com/templates/work.html

I have been trying many things, but with limited success. Any thoughts on how to make this work in a more stable manner?

I tried adding .stop() on click, but it has not worked as I intended.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Jonathan Miller
  • 1,786
  • 1
  • 16
  • 26

3 Answers3

4

I think the problem was related to a limitation with jQuery delay(). The following uses standard javascript setTimeout and clearTimeout as suggested by the jQuery delay() api.

<html>
<head>
    <script src="./jquery-ui-1.8.7.custom/js/jquery-1.4.4.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            var timeOuts = new Array();
            var eT=200;
            function myFadeIn(jqObj) {
                jqObj.fadeIn('slow');
            }
            function clearAllTimeouts() {
                for (key in timeOuts) {
                    clearTimeout(timeOuts[key]);
                }
            }
            $('.everything').hide().each(function(index) {
                timeOuts[index] = setTimeout(myFadeIn, index*eT, $(this));
            });
            $('#something').click(function() {
                clearAllTimeouts();
                $('.everything').stop(true,true).hide();
                $('.something').each(function(index) {
                    timeOuts[index] = setTimeout(myFadeIn, index*eT, $(this));
                });
            });
        });
    </script>
    <style type="text/css">
        li.everything {width:40px;height:40px;background:#bbb;display:inline-block}
        li.something {width:80px;height:80px;background:#000;display:inline-block}
    </style>
</head>
<body>
    <button id="something">BLACK</button>
    <ul>
        <li class="everything"></li>
        <li class="everything something"></li>
        <li class="everything"></li>
        <li class="everything something"></li>
        <li class="everything"></li>
        <li class="everything something"></li>
        <li class="everything"></li>
        <li class="everything something"></li>
        <li class="everything"></li>
        <li class="everything something"></li>
    </ul>
</body>
</html>
nhavens
  • 252
  • 1
  • 3
  • 11
  • Thank you! I'll have to analyze this more so I understand all that is going on, but from my initial tests, it seems to be working perfectly! I really truly appreciate the help! – Jonathan Miller Apr 13 '11 at 19:34
3

I know that you said you tried adding the .stop() on click. The following code does exactly that, but works fine for me. If this is not what you are looking for, please explain in the comments.

<html>
<head>
    <script src="/js/jquery-1.4.4.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            var eT=0;
            $('.everything').hide().each(function() {
                $(this).delay(eT).fadeIn('slow');
                eT += 200;
            });
            $('.everything').click(function() {
                $('.everything').stop(true,true).fadeIn();
            });
        });
    </script>
    <style type="text/css">
        li.everything {width:40px;height:40px;background:#bbb;display:inline-block}
    </style>
</head>
<body>
    <ul>
        <li class="everything"></li>
        <li class="everything"></li>
        <li class="everything"></li>
        <li class="everything"></li>
        <li class="everything"></li>
    </ul>
</body>
</html>

Working Demo

xkeshav
  • 53,360
  • 44
  • 177
  • 245
nhavens
  • 252
  • 1
  • 3
  • 11
  • I tested your code and it is not quite what I am intending to do. Yes I want the LI's to load in sequentially. but the click event is on the navigation, not the LI's themselves. I got all of it working. The problem is when you click on one of the filters while the fadein's are still in progress, you get overlapping animations. I want the click to kill the current animation, hide all list items and then display only the ones based on the filter. If you go to: http://jjaakk.miller-interactive.com/templates/work.html and click on the links under "show me" quickly you'll see what I mean. – Jonathan Miller Apr 13 '11 at 15:07
  • Here is my function: `code $('#secondary ul li a').click(function(){ var llid = $(this).attr('id'); var eT= 0; $('.' + llid).each(function(){ $('.everything').hide(); $(this).delay(eT).fadeIn('slow'); eT += 200; }); });` – Jonathan Miller Apr 13 '11 at 15:09
  • I see what you mean about the overlapping animations. I think the issue is related to a limitation with the jquery delay(). See the box just above the Example [here](http://api.jquery.com/delay/). I posted a second answer that uses standard javascript setTimeout and clearTimeout. – nhavens Apr 13 '11 at 19:02
2

Multiple delay by index

 var eT = 0;     
    $('.everything').hide().each(function(index) {
        $(this).delay(eT*index).fadeIn('slow');
        eT += 200;
    });
Hussein
  • 42,480
  • 25
  • 113
  • 143