0

I've been trying to use jQuery to have a button function reverse the order of a <ul>.

For some reason the code completely messes up with the styling of the ul when clicked. It might be because of the lazy loader I'm using for the images (qazy.js), but I'm not entirely sure. It just seems to break the <ul>.

You can see the live code here: http://designers.watch/tester.html

You'll see the undesirable effect when you click the 'Reverse Order' button.

The code I use the reverse the <ul> is:

$(document).ready(function(){
    $("#rev").click(function(){
        var list = $("ul li").get().reverse();
        $("ul").empty();
        $.each(list, function(i){
            $("ul").append("<li>"+list[i].innerHTML+"</li>");
        });//each
    });//function
});//ready

The two issues are:

  • The styles get messed up.
  • The lazy loader won't load the images that have been brought to the top of the list from the reverse ordering.

Is there a way that I can fix these issues? Should I use a different lazy loader script?

Thanks in advance to anyone who helps out.

javinladish
  • 907
  • 1
  • 9
  • 18
  • 1
    The original `li`s have a class... Also why aren't you just re-ordering the existing DOM elements instead of building them new? – PeeHaa Dec 27 '14 at 20:14
  • @PeeHaa I'm not sure what you mean by "re-ordering the existing DOM elements instead of building them new". I'm pretty new to Javascript/jQuery and found this code to reverse the `
      ` somewhere online. Are you suggesting that I use other code to reverse the `
        ` order?
    – javinladish Dec 27 '14 at 20:19
  • possible duplicate of [jQuery reversing the order of child elements](http://stackoverflow.com/questions/5347839/jquery-reversing-the-order-of-child-elements) – Aminul Dec 27 '14 at 20:21
  • @javinladish have look at [this](http://stackoverflow.com/a/5347903/610585) answer – Aminul Dec 27 '14 at 20:22
  • never _ever_ use HTML serialisation and deserialisation to manipulate DOM nodes - move the nodes directly. – Alnitak Dec 27 '14 at 21:04

2 Answers2

3

You should never use HTML serialisation just to move elements around the page - as you'll find they lose things such as event handlers, styles, etc.

Just try this, instead:

$('#li-switch').on('click', function() {
  // get reversed array of elements
  var el = $('ul li').get().reverse();

  // re-append them to their parent
  $('ul').append(el);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="li-switch">Click to reverse the order</div>

<ul>
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
  <li>Four</li>
  <li>Five</li>
</ul>

As each node is appended it's automatically removed from its original position in the DOM, and put back in the right place unmodified.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

Your "Reverse Order" doesn't reverse your li's, it is creating new ones and those new ones are different than those old ones - they are missing item class plus you are loosing your schema attributes. This should do the trick in terms of improving what you already have:

$(document).ready(function(){
    $("#rev").click(function(){
        var list = $("ul li").get().reverse();
        $("ul").empty();
        $.each(list, function(i){
            $("ul").append('<li class="item">'+list[i].innerHTML+'</li>');
        });//each
    });//function
});//ready

Check this question for more info about reordering list items: jQuery reversing the order of child elements

Lazy loader is a bigger problem, and I think it would need to be reinitialized after you do the reverese, since your list items and their children are new and don't have lazy loader events attached by the script. If you do reordering right this problem may disappear.

Community
  • 1
  • 1
bwitkowicz
  • 779
  • 6
  • 15
  • Ah, I see. Thank you. I'm not that great with Javascript/jQuery, but I'll try to find some other code to get the job done right. – javinladish Dec 27 '14 at 20:21
  • Just check the link I put into the answer to see how reordering should be done. – bwitkowicz Dec 27 '14 at 20:24
  • Thanks. I actually tried this code and it worked: `var list = $('ul#movies'); var listItems = list.children('li,item'); list.append(listItems.get().reverse());` It even works fine with the lazy loader. How is this code different from yours? – javinladish Dec 27 '14 at 20:29
  • Is one better or more preferred than the other? – javinladish Dec 27 '14 at 20:38
  • My code is just your code with fixed styling issue, but you should not be using it :). What you came out with sounds good, and because you are using get() method you are actually taking entire li with all its attributes (including classes) and events attached to it (even those added by lazy loader). – bwitkowicz Dec 27 '14 at 20:38
  • With the code you provided you shouldn't be experiening any more issues, you are just doing reordering and thats what you want. Your method (from the comment above) is good. – bwitkowicz Dec 27 '14 at 20:40
  • 1
    poor answer - serialisation and deserialisation is _never_ the right answer to DOM manipulation problems. – Alnitak Dec 27 '14 at 21:12
  • Yes, you are right. I just "improved" the code provided by the author and suggested other solution (similar to yours) as mentioned in the link and in the comments. – bwitkowicz Dec 27 '14 at 21:17
  • It's improved, but IMHO only barely. The slightest change to the OP's HTML would require this code to be rewritten, making it brittle and error prone. The elements already have the correct style, they just need to be "moved" within their parent. – Alnitak Dec 27 '14 at 21:24
  • Can't argue with that :) – bwitkowicz Dec 27 '14 at 21:28