Reputation: 75
I have a problem trying to sort a list with spans within.
Example:
<a href="">Sort by name</a>
<a href="">Sort by year</a>
<a href="">Sort by fruit</a>
<ul>
<li>
<span class="name">Carl</span>
<span class="year">1954</span>
<span class="fruit">Apple</span>
</li>
<li>
<span class="name">Ann</span>
<span class="year">1932</span>
<span class="fruit">Banana</span>
</li>
<li>
<span class="name">Joe</span>
<span class="year">1961</span>
<span class="fruit">Pineapple</span>
</li>
</ul>
So i want to able to sort by these three "categories". Anyone got a suggestion?
Upvotes: 3
Views: 1960
Reputation: 630429
If we change your markup slightly to handle the links better, like this:
<div id="sort">
<a href="#name">Sort by name</a>
<a href="#year">Sort by year</a>
<a href="#fruit">Sort by fruit</a>
</div>
<ul id="things">
You could do a simple toggle 2-way sort like this:
$("#sort a").click(function(e) {
var desc = $(this).hasClass("asc"),
sort = this.hash.substr(1),
list = $("#things");
list.append(list.children().get().sort(function(a, b) {
var aProp = $(a).find("span."+sort).text(),
bProp = $(b).find("span."+sort).text();
return (aProp > bProp ? 1 : aProp < bProp ? -1 : 0) * (desc ? -1 : 1);
}));
$(this).toggleClass("desc", desc)
.toggleClass("asc", !desc)
.siblings().removeClass("asc desc");
e.preventDefault();
});
You can test it out here, there are other approaches of course (and the above can be slimmed down further)...my main point here was to demonstrate with Array.sort()
you can make pretty quick work of this.
Here's a breakdown of what the above does:
#XXX
and get XXX
, that's the class we want to sort on (you could use a data-
attribute here)<li>
s), use .get()
to get the raw array of DOM elements.sort()
that array by:
.append()
the sorted elements back to the list
desc
class, otherwise make it an asc
class, and remove either class from any siblings.If you have a very large number of elements, you'll want to take a different approach like the plugins posted in other answers...they parse the data on updates only and cache the result in objects, so there's less DOM traversal when sorting (which compared to everything else, is expensive).
As an example of how to improve the above (but less readable as an example) would be to select the <span>
elements initially, cutting down on selector and .text()
time, like this:
$("#sort a").click(function(e) {
var desc = $(this).hasClass("asc"),
sort = this.hash.substr(1),
list = $("#things");
$(list.children().detach().find("span."+sort).get().sort(function(a, b) {
var aProp = $.text([a]),
bProp = $.text([b]);
return (aProp > bProp ? 1 : aProp < bProp ? -1 : 0) * (desc ? -1 : 1);
})).parent().appendTo(list);
$(this).toggleClass("desc", desc)
.toggleClass("asc", !desc)
.siblings().removeClass("asc desc");
e.preventDefault();
});
You can test out that version here.
Upvotes: 1
Reputation: 7213
I would suggest to rearrange your data in a table (cause that is what it represents) and then use someting like the JQuery table sorter plugin
Upvotes: 0