Reputation: 6132
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?
Upvotes: 481
Views: 234541
Reputation: 17415
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>
Upvotes: 0
Reputation: 163
You can also try
var arr = [].reverse.call($('li'))
arr.each(function(){ ... })
Upvotes: -1
Reputation: 331
If you don't want to save method into jQuery.fn you can use
[].reverse.call($('li'));
Upvotes: 9
Reputation: 161
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);
}
Upvotes: 2
Reputation: 28837
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;
});
... 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
Upvotes: 25
Reputation: 11444
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);
});
Upvotes: 14
Reputation: 4480
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
Upvotes: 431
Reputation: 59
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
Upvotes: 5
Reputation: 99317
You can do
jQuery.fn.reverse = function() {
return this.pushStack(this.get().reverse(), arguments);
};
followed by
$(selector).reverse().each(...)
Upvotes: 65
Reputation: 31781
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
}
Upvotes: 4