Reputation: 310967
Imagine some DOM elements:
<ul id="list">
<li data-index="3">Baz</li>
<li data-index="1">Foo</li>
<li data-index="2">Bar</li>
</ul>
How can these elements be sorted using JavaScript and without jQuery?
Something similar to:
document.getElementById('list').sort(function(li) { return li.dataset.index; });
Upvotes: 6
Views: 4481
Reputation:
You should use the ordering capabilities of flexboxes. This will allow to re-order the elements without moving them around in the DOM. This involves setting the CSS order
property.
See https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes for more details.
Upvotes: 5
Reputation: 288250
Some time ago I wrote this:
function sortChildren(wrap, f, isNum) {
var l = wrap.children.length,
arr = new Array(l);
for(var i=0; i<l; ++i)
arr[i] = [f(wrap.children[i]), wrap.children[i]];
arr.sort(isNum
? function(a,b){ return a[0]-b[0]; }
: function(a,b){ return a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0; }
);
var par = wrap.parentNode,
ref = wrap.nextSibling;
par.removeChild(wrap);
for(var i=0; i<l; ++i) wrap.appendChild(arr[i][1]);
par.insertBefore(wrap, ref);
}
Basically:
First create an array to store the elements with its corresponding value returned by the comparator function.
We could also run the function when sorting, but since DOM interactions are slow, this way we make sure the function will only run once per element.
Then, we sort it using native sort
.
If isNum
argument is truly, we use a sorting function that compares numerically. This is needed if the comparator function returns strings but you want to compare numerically instead of lexicographically.
Now, we remove the wrapper element from the DOM. This way reordering the children will be less expensive (e.g. avoiding repaitings).
Finally we reorder the children, and insert wrapper back in its place.
Run it like
sortChildren(
document.getElementById('list'),
function(li) { return li.dataset.index; },
true
);
or
sortChildren(
document.getElementById('list'),
function(li) { return +li.dataset.index; }
);
Upvotes: 3
Reputation: 104780
<!doctype html>
<html lang="en">
<head>
<meta charset= "utf-8">
<title>sort list</title>
</head>
<body>
<strong>Double click the list to sort by data-index</strong>
<ul id= "list">
<li data-index= "3">Baz</li>
<li data-index= "1">Foo</li>
<li data-index= "2">Bar</li>
</ul>
<script>
document.body.ondblclick=function(){
var A=[], pa= document.getElementById('list');
var itemz= pa.getElementsByTagName('li');
A.slice.call(itemz).sort(function(a, b){
return a.getAttribute('data-index')-b.getAttribute('data-index');
}).forEach(function(next){
pa.appendChild(next);
});
}
</script>
</body>
</html>
Upvotes: 1