Invert the order of a list of jQuery elements

9

How to invert the order in which jQuery iterates an array of elements?

In this case what I would like is to invert the contents of items within the array.

For example:

<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
</ul>
    
asked by anonymous 11.12.2013 / 20:53

3 answers

18

In a row:

[].reverse.call($('ul li')).appendTo('ul');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><ul><li>Item1</li><li>Item2</li><li>Item3</li><li>Item4</li><li>Item5</li></ul>

link

Notice that:

  • jQuery objects do not have method reverse , you must lend it to Array.prototype (or any array, as I did above).
  • This solution reverses the order of <li> in the DOM, and does not simply exchange its contents.
  • The code above requires a reference or selector that points to the parent of <li> . The selector I used works for the query HTML, but in more complex cases (multiple lists on the page and / or nested lists) it will be necessary to pass a more specific selector, or reference to the exact DOM node.
  • If you want a code that invests multiple lists at once, or nested lists, you must use loops or .each , as in Sergio's answer .
11.12.2013 / 21:10
6

More options:

Option A:

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

Demo here

Option B

Using the jQuery combination with the reverse strong> of javascript:

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

Demo here

Option C:

using length (number of elements within the array) and subrating the index of each element:

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

Demo here

Option D

... related to the previous one, using the .text () (jQuery ) that allows a return function.

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

Demo here

    
11.12.2013 / 20:53
3

I thought of another way to implement this by treating it as a kind of stack. Example in jsFiddle .

Stack

Firstly I need to save the elements in a variable.

var elements = $("li");

In this way elements are sorted as 1 , 2 , 3 , 4 , 5 . My "stack" looks like this:

    5     <- last in (último a entrar)
---------
    4
---------
    3
---------
    2
---------
    1     <- first in (primeiro a entrar)

Splice

jQuery does not have a pop method, but you can copy the same behavior using:

elements.splice( ultimo_indice, 1);

That is, I get the values of the "stack", since 5 was the last one to enter, it will be the first one to exit.

So I do:

// enquanto houver elementos na pilha, remove e
var e;
while ((e = elements.splice(elements.length - 1, 1)).length)
{
    // re-adiciona o próprio elemento no seu container
    $("ul").append(e[0]);
}

I'm drawing in order 5 , 4 , 3 , 2 , 1 and re-inserting them, thus changing the order of elements.

Pop

It is possible to implement the pop method to be used directly on a jQuery object, so add the method as follows:

!function($) {
    $.fn.pop = function() { return this.splice(this.length - 1, 1)[0]; }
}(jQuery);

And to use in this example:

var elements = $("li");

var e;
while ((e = elements.pop()))
{
    $("ul").append(e);
}

Example in jsFiddle

Direct method

And a simpler method, but one that is very efficient is to go through the elements in reverse order by re-adding them:

var elements = $("li");

for (var i = elements.length - 1; i >= 0; --i)
{
    $("ul").append(elements[i]);
}

Performance

And to complete a performance test: Reversing order of jsPerf elements

Nome                                    op/s
--------------------------------------------
ModoSplice                             7,582
ModoPop                                7,340
ModoDireto                             8,357
ModoReverse /* [].reverse.call */     11,679 <--
    
21.12.2013 / 02:52