JQuery .each() backwards
Asked Answered
T

12

479

I'm using JQuery to select some elements on a page and then move them around in the DOM. The problem I'm having is I need to select all the elements in the reverse order that JQuery naturally wants to select them. For example:

<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
</ul>

I want to select all the li items and use the .each() command on them but I want to start with Item 5, then Item 4 etc. Is this possible?

Tea answered 8/9, 2009 at 13:24 Comment(0)
T
733
$($("li").get().reverse()).each(function() { /* ... */ });
Tollbooth answered 8/9, 2009 at 13:31 Comment(4)
Should be important to note that the index is not reversed, so if you are only wanting to do the last three, for instance, you cannot expect <li>Item 5</li> to have an index of 0.Jackstraw
to David Andres: may be you forgot to add additional $() before li. I did this mistake and received "undefined func".Brom
@DavidAndres: You missed the .get() which turns the jQuery wrapped array into an ordinary JS array. The JS array has .reverse().Issie
Caution: Array.reverse() both modifies the array in place and returns the reversed array. So this solution actually relies upon $().get() returning a new array, and not a reference to some internal jQuery or DOM array. Probably a safe bet within the confines of this example. Caveat Coder.Creight
N
429

I present you with the cleanest way ever, in the form of the world's smallest jquery plugin:

jQuery.fn.reverse = [].reverse;

Usage:

$('jquery-selectors-go-here').reverse().each(function () {
    //business as usual goes here
});

-All credit to Michael Geary in his post here: http://www.mail-archive.com/[email protected]/msg04261.html

Nelle answered 22/3, 2011 at 2:42 Comment(0)
S
65

You can do

jQuery.fn.reverse = function() {
    return this.pushStack(this.get().reverse(), arguments);
}; 

followed by

$(selector).reverse().each(...) 
Secondrate answered 8/9, 2009 at 13:34 Comment(1)
This approach was originally proposed by John Resig (jQuery developer) on the jQuery mailing list.Solace
B
24

Here are different options for this:

First: without jQuery:

var lis = document.querySelectorAll('ul > li');
var contents = [].map.call(lis, function (li) {
    return li.innerHTML;
}).reverse().forEach(function (content, i) {
    lis[i].innerHTML = content;
});

Demo here

... and with jQuery:

You can use this:

$($("ul > li").get().reverse()).each(function (i) {
    $(this).text( 'Item ' + (++i));
});

Demo here

Another way, using also jQuery with reverse is:

$.fn.reverse = [].reverse;
$("ul > li").reverse().each(function (i) {
    $(this).text( 'Item ' + (++i));
});

This demo here.

One more alternative is to use the length (count of elements matching that selector) and go down from there using the index of each iteration. Then you can use this:

var $li = $("ul > li");
$li.each(function (i) {
    $(this).text( 'Item ' + ($li.length - i));
});

This demo here

One more, kind of related to the one above:

var $li = $("ul > li");
$li.text(function (i) {
    return 'Item ' + ($li.length - i);
});

Demo here

Bugger answered 19/8, 2013 at 18:22 Comment(0)
T
14

I prefer creating a reverse plug-in eg

jQuery.fn.reverse = function(fn) {       
   var i = this.length;

   while(i--) {
       fn.call(this[i], i, this[i])
   }
};

Usage eg:

$('#product-panel > div').reverse(function(i, e) {
    alert(i);
    alert(e);
});
Treadmill answered 21/12, 2010 at 14:3 Comment(2)
I like this idea/code too, but it doesn't return a chainable object (that is reversed) like the higher-voted answers :) Still, definitely a good method for the way it's setupDisquiet
You are right. Not chainable so not a valid plugin. Have improved the code slightly though, moving the decrementer into the condition.Treadmill
U
9

If you don't want to save method into jQuery.fn you can use

[].reverse.call($('li'));
Upandcoming answered 31/3, 2017 at 8:9 Comment(0)
R
5

Needed to do a reverse on $.each so i used Vinay idea:

//jQuery.each(collection, callback) =>
$.each($(collection).get().reverse(), callback func() {});

worked nicely, thanks

Recursion answered 17/6, 2010 at 4:0 Comment(1)
This isn't right; this should just be $.each(collection.reverse(), ...).Schreiber
D
4

You cannot iterate backwards with the jQuery each function, but you can still leverage jQuery syntax.

Try the following:

//get an array of the matching DOM elements   
var liItems = $("ul#myUL li").get();

//iterate through this array in reverse order    
for(var i = liItems.length - 1; i >= 0; --i)
{
  //do Something
}
Dictaphone answered 8/9, 2009 at 13:30 Comment(0)
L
2

I found Array.prototype.reverse unsuccessful with objects, so I made a new jQuery function to use as an alternative: jQuery.eachBack(). It iterates through as the normal jQuery.each() would, and stores each key into an array. It then reverses that array and performs the callback on the original array/object in the order of the reversed keys.

jQuery.eachBack=function (obj, callback) {
    var revKeys=[]; $.each(obj,function(rind,rval){revKeys.push(rind);}); 
    revKeys.reverse();
    $.each(revKeys,function (kind,i){
        if(callback.call(obj[i], i, obj[i]) === false) {    return false;}
    });
    return obj;
}   
jQuery.fn.eachBack=function (callback,args) {
    return jQuery.eachBack(this, callback, args);
}
Longerich answered 9/12, 2015 at 1:14 Comment(0)
B
0

This answer is like JoeChung's answer with the difference that by this code you can just use the container element (ul):

$($("ul").children().get().reverse()).each(function(i, elm) {

    console.log($(elm).text()) 

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
</ul>
Bolus answered 27/6, 2023 at 14:52 Comment(0)
C
-1

You can also try

var arr = [].reverse.call($('li'))
arr.each(function(){ ... })
Cere answered 28/7, 2017 at 12:38 Comment(0)
D
-2

I think u need

.parentsUntill()
Dwell answered 14/2, 2014 at 8:0 Comment(1)
Why do you think that? And how would you use it?Ohare

© 2022 - 2024 — McMap. All rights reserved.