M Jones
M Jones

Reputation:

JQuery .each() callback function doesn't run on each iteration/loop

Here's what should happen.
1. Get the rel attribute of the clicked link
2. For every div with class 'entry':
(i)Get its 'left' position
(ii) Calculate its outer height
(iii)Loop through all instances of 'a.tag_filter'. If it finds the same string in the 'rel' as the one oringinally clicked on then add 1 to 'V' and break out of the loop.
(iv)If 'V' is equal to 0 after the loop we know the same tag isn't present within that '.entry' so fade it out.
(v)Once the fadeout has finished loop through all the '.entry' after the faded out one and get their 'left' values.
(vi)If the left value of the faded entry = the left value of the current '.entry' then reposition it to the new 'top' value.

What is currently happening.
It runs through and fades out all the correct '.entry' elements and only after all of them have faded out does it reposition them remaining '.entry' elements.

After each element is faded out I would like the repositioning loop to run so it essentially positions the remaining elements one at a time rather than all at once.

Heres my code EDIT:

$('a.tag_filter').click(function(e){
        e.preventDefault();
        var selectTag = $(this).attr('rel');

    $('div.spotlight_entry_container_grid').each(function(i){
        var $entry = $(this);
        var tagArray = [];

        $('a.tag_filter', this).each(function(){
            tagArray.push ($(this).attr('rel'));
        }); 

        if($.inArray(selectTag,tagArray) == -1){
            var leftPos = $entry.css("left"); 
                    var topPos = $entry.css("top"); 

            $entry.fadeOut(1000, function(){
                var nextLeftPos;
                            var nextTopPos;

                $('div.spotlight_entry_container_grid:gt('+i+')').each(function(j) {   
                    var $laterEntry = $(this); 
                    nextLeftPos = $laterEntry.css("left");
                                nextTopPos = $laterEntry.css("top");
                    //we need to keep the entries in their columns.
                    //matching left values will do it. No need to animate left values.
                    if(leftPos == nextLeftPos){
                        $laterEntry.animate({ top: topPos});
                    }
                    }); 
            });
        }   
    });
    });

Hopefully that makes sense
Any help would be appreciated! I'm probably doing something crazy but I just can't spot it. Thanks

Upvotes: 1

Views: 5800

Answers (2)

bryan.taylor
bryan.taylor

Reputation: 584

You don't need to cache $(this), jQuery auto caches the this selector for function callbacks.

Upvotes: 0

Russ Cam
Russ Cam

Reputation: 125488

in here

$('a.tag_filter', this).each(function(){
                        var curTag = $(this).attr('rel');
                        if(curTag == selectTag){
                                v++;
                                return false;
                        }
                }); 

returning false inside of $().each() breaks the looping through each element in the wrapped set.

From the documentation

Returning 'false' from within the each function completely stops the loop through all of the elements (this is like using a 'break' with a normal loop). Returning 'true' from within the loop skips to the next iteration (this is like using a 'continue' with a normal loop).

Also, I would recommend caching $(this) inside of each each() in a local variable for performance instead of referencing it several times.

EDIT:

After looking at the code further, I think the following should do it

$('a.tag_filter').click(function(e){

        // prevent the default anchor behaviour
        e.preventDefault();
        var selectTag = $(this).attr('rel');

        $('div.entry').each(function(i){
                var $entry = $(this);                  

                // get an array of the anchor tag rel attributes
                var tagArray = [];
                $('a.tag_filter', this).each(function() {
                        tagArray.push ($(this).attr('rel'));
                });

                // if we can't find the selected tag in the entries tags
                if ($.inArray(selectTag,tagArray) == -1) {        
                    var leftPos = $entry.css("left"); 
                    var topPos = $entry.css("top");                      

                    $entry.fadeOut(1000, function(){
                        var nextLeftPos;
                        var nextTopPos;

                        $('div.entry:gt('+i+')').each(function(j) {             
                            var $laterEntry = $(this); 
                            nextLeftPos = $laterEntry.css("left");
                            nextTopPos = $laterEntry.css("top");
                            // for the first element, set top and left to the faded out element values
                            if (j == 0) {                               
                                $laterEntry.animate({ top: topPos, left: leftPos });
                            }
                            // for later elements in the loop, ste the values to the previous element values
                            else {
                                $laterEntry.animate({ top: nextTopPos, left: nextLeftPos  });
                            }
                        });
                    });                                                                  
                }
         });  



 });

Upvotes: 3

Related Questions