24

I'm trying to sort an li elements and get an unexpacted result I need to sort it three times to get it correctly,

where have I mistaken? javascript

var sort_by_name = function(a, b) {
    return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase();
}
$this = $("ol#table1");
var list = $this.children();
list.sort(sort_by_name);
console.log(list);
$this.html(list);

HTML

<ol id="table1" style="display: block; ">
   <li class="menu__run">I</li>
   <li class="menu__run">IXX</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li> 
   <li class="menu__run">IXX</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__run">I</li>
   <li class="menu__test">st</li>
   <li class="menu__test">st</li>
   <li class="menu__test">st</li>
</ol>

fiddle example

5 Answers 5

48

There are much better ways to sort.

  1. You need a comparison function that returns the right values: -1, 0, and 1.
  2. localeCompare() is such a comparison function.
  3. You can just move the DOM elements around rather than regenerating the HTML.
  4. You can get the LI elements directly in the original selector.
  5. "#table1" is a more efficient selector than "ol#table1".

I would suggest this:

$("div#btn").click(function() {
    var sort_by_name = function(a, b) {
        return a.innerHTML.toLowerCase().localeCompare(b.innerHTML.toLowerCase());
    }

    var list = $("#table1 > li").get();
    list.sort(sort_by_name);
    for (var i = 0; i < list.length; i++) {
        list[i].parentNode.appendChild(list[i]);
    }
});​

Which you can see work here: http://jsfiddle.net/jfriend00/yqd3w/

Sign up to request clarification or add additional context in comments.

9 Comments

can you make something like this for objects under different <div>s?
@shevski - I'm sure another scenario could be sorted too, but you'd have to show the HTML and describe what you want it sorted by.
I'll put another question for it
You're comparing for human eyes, so you want to ignore all the markup. Rather than .innerHTML, you want to compare .textContent, which looks at purely the textual data that is presented as visible to the user.
@Mike'Pomax'Kamermans - Yep, it's up to the OP exactly what they want to sort on, but .textContent is indeed a good option.
|
8

A custom compareFunction needs to return -1, 0 or 1.

function sort_by_name(a, b) {
    var sa = a.innerHTML.toLowerCase(), sb = b.innerHTML.toLowerCase();
    return sb<sa ? -1 : sb>sa ? 1 : 0;
}

Comments

6
var sort_by_name = function(a, b) {
    return $(a).text().toLowerCase().localeCompare($(b).text().toLowerCase());
}

You can use localeCompare instead to make things more elegant and workable.

See jsfiddle http://jsfiddle.net/Qww87/11/

Comments

2

according to documentation it needs numeric values. more intelligible:

    var sort_by_name = function(a, b) {
         if(a.innerHTML.toLowerCase() < b.innerHTML.toLowerCase()) return -1;
         if(a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase()) return 1;
         return 0;
    }

Comments

0

Use my jquery plugin Sort Content :

   $('ol#table1').sortContent({asc:true})

That's it!

DEMO : http://jsfiddle.net/abdennour/SjWXU/

1 Comment

Your repo is no longer available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.