Looping with .each with delay in Jquery
Asked Answered
L

5

1

I am not good at jQuery so I am not sure if my assumptions are corrent.

I am using the isotope plugin, with which I want to insert elements one by one (and not everything at once) with a slight delay so it will also look like it (for the human eye)

to insert an item with isotope I use

$('#container').isotope( 'insert', $item);

so in order to insert one-by-one I am doing

$("#items_are_here").find('.item').each(function( index ) {
     setTimeout(function() {
            $('#container').isotope( 'insert', $(this));
         },3000);
    });

This however seems that the browser waits for something, and then displays them all at once

If I do

  setTimeout(function() {
   $("#items_are_here").find('.item').each(function( index ) {
          $('#container').isotope( 'insert', $(this));

        }); },3000);

everything works, but not one-by-one..

Is this the right way to do this? or am I over-complicating it?

here is fiddle. In it, there are 2 buttosn - insert all - which finds all .item and inserts them. And insert one-by-one which does the proposed way with delay. As you can see, there is no delay.

Lowndes answered 9/2, 2013 at 9:7 Comment(0)
H
1
    var $items=$("#items_are_here").find('.item');
    var i=-1;
    var delayed=setinterval(function() {
            if (++i<$items.length) $('#container').isotope( 'insert', $items.eq(i));
            else clearInterval(delayed); 
             },3000);

not tested. or

    var $container=$('#container');     
    $.fn.extend({
      onebyone :function ($ctnr,i) {
           if (!i) i = 0;
           var $o=$(this);
           setTimeOut(function() {
                 $ctnr.isotope( 'insert', $o.eq(i)); 
                 if (++i<$o.length) $o.onebyone(i); 
               },3000);
           return this; 
      }
    $("#items_are_here").find('.item').onebyone($container);
Hermann answered 9/2, 2013 at 9:23 Comment(0)
D
2

Because .each() runs pretty instantaneous for each entry, you'll end up with a bunch of timeouts which are more or less the same. So after about 3 seconds, all timeouts expire and the items are added.

To prevent this, you'll to make the timeout dependent on the index of the item. So item 0 will be inserted after 3 seconds, item 1 will be inserted after 6 seconds, etc.

$("#items_are_here").find('.item').each(function( index ) {
  var item = $(this);
  setTimeout(function() {
    $('#container').isotope('insert', item);
  },3000 * (index + 1));
});
Draconian answered 9/2, 2013 at 9:42 Comment(2)
& there you end up with all those timeOut call running simultaneously :/ (eating up all the ram ? i guess depending on number of items...expect turbulence)Hermann
True :) Your answer using setInterval() makes more sense, but that only became clear to me after looking more closely at the code.Draconian
M
1
$("#items_are_here").find('.item').each(function( index ) {
     setTimeout(function() {
            $('#container').isotope( 'insert', $(this));
         },3000);
    });

in the above context, $(this) is the window object, because it's inside setTimeout.

Modify your code to and try:

$("#items_are_here").find('.item').each(function( index ) {
     var item = $(this);
     setTimeout(function(index) {
            $("#container").isotope( 'insert', $(this))
     },index*3000);
    });
Masonry answered 9/2, 2013 at 9:10 Comment(5)
this doesn't give an error, but it doesn't insert it one by oneLowndes
Well, i'm not sure what that isotope is, so i'm editing my answer with a jquery solution.Masonry
It seems that the browser is waiting for something and then renders it all at once..Lowndes
i will attempt to jsfiddle it, hang onLowndes
@NickGinanto try the lastest modified code, that should work fine.Masonry
H
1
    var $items=$("#items_are_here").find('.item');
    var i=-1;
    var delayed=setinterval(function() {
            if (++i<$items.length) $('#container').isotope( 'insert', $items.eq(i));
            else clearInterval(delayed); 
             },3000);

not tested. or

    var $container=$('#container');     
    $.fn.extend({
      onebyone :function ($ctnr,i) {
           if (!i) i = 0;
           var $o=$(this);
           setTimeOut(function() {
                 $ctnr.isotope( 'insert', $o.eq(i)); 
                 if (++i<$o.length) $o.onebyone(i); 
               },3000);
           return this; 
      }
    $("#items_are_here").find('.item').onebyone($container);
Hermann answered 9/2, 2013 at 9:23 Comment(0)
A
0
$("#items_are_here").find('.item').each(function( index ) {
     var item = $(this);
     setTimeout(function(i) {
            $('#container').isotope( 'insert', i );
         },3000);
    });
Atheist answered 9/2, 2013 at 9:13 Comment(0)
S
0

little late but my workaround was: hardcode a class to item like to_animate

the css:

.item.to_animate { opacity:0; display:block; } @keyframes TransitionClass{ 0% { opacity: 0;transform: scale(1.2); } 100% { opacity: 1;transform: scale(1); } } .animatefinish.TransitionClass{ animation-name: umScaleIn; animation-timing-function: cubic-bezier(0.19,1,.22,1); } .animatefinish.TransitionClass{ animation-duration: .8s; }

the snipped for isotope

    `$('#container').isotope( 'appended', $(el) ).after(function() {

      $('.item.to_animate').each(function(i) {
      var el = $(this);

              setTimeout(function() {

              el.addClass('TransitionClass animatefinish');

                  el.removeClass('to_animate')

              }, i * 200);

      });

    });`
Saltine answered 5/6, 2015 at 14:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.