Invert the order of a jQuery widget list

Asked

Viewed 3,264 times

10

How to reverse the order jQuery iterates an array of elements?

In this case what I would like is to invert the contents of the 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>
  • I would suggest, for the sake of ease of search and greater cohesion with what is being discussed, that the title of this question be changed to "Reverse the order of the elements of a list using jQuery". Of course, it’s just a suggestion.

  • @Frenetic, I agree that can be clearer, thank you. I have made a modification now to be clearer.

3 answers

21


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>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
</ul>

http://jsfiddle.net/Caa97/

Notice that:

  • JQuery objects have no method reverse, it is necessary to lend it to Array.prototype (or any array, as I did above).
  • This solution reverses the order of <li> in the GIFT, and not simply exchange its contents.
  • The above code requires reference or selector pointing to the parent of <li>. The selector I used works for the question’s 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 inverts several lists at once, or nested lists, you need to use loops or .each, as in the Sergio’s response.
  • Right and concise :) +1

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 method re-verse javascript:

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

Demo here

Option C:

using the length (number of elements inside the array) and go subraindo o 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) which allows a return function.

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

Demo here

3

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

Stack

First I need to store the elements in a variable.

var elements = $("li");

In this way the elements are ordered 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 method pop, but it is possible to copy the same behavior using:

elements.splice( ultimo_indice, 1);

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

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 taking it in order 5, 4, 3, 2, 1 and re-insert them, thus changing the order of the elements.


Pop

It is possible to implement the method pop to be used directly on a jQuery object, simply 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 more bland but very efficient method 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 <--
  • I like the simple looping approaches. But aren’t your tests running without HTML? Compare to http://jsperf.com/inverter-sort-of-elements/4

  • Oops! I really forgot to put HTML at test time. I fixed it at the same link.

  • 1

    Ah, so the key to not clutter up everything in jsperf is to use id on the list! I made a mess in revisions 2 and 3 of the test, hehe!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.