Reputation: 782
I want to sort my JavaScript divs on their child values (span content).
I already found here a sorting algorthm for javascript on this thread: Easiest way to sort DOM nodes?
However it is only for simple list. I want to have a modified version which don't look on the paragraph elements.
HTML
<div class="myclass">
<p class="hide">1</p>
<span>2</span>
</div>
<div class="myclass">
<p class="hide">2</p>
<span>1</span>
</div>
<div class="myclass">
<p class="hide">3</p>
<span>4</span>
</div>
<div class="myclass">
<p class="hide">4</p>
<span>1</span>
</div>
JS
var list = document.getElementById('sortme');
var items = list.childNodes;
var itemsArr = [];
for (var i in items) {
// HERE I need to get to the SPAN Element but how?
if (items[i].nodeType == 1) { // get rid of the whitespace text nodes
itemsArr.push(items[i]);
}
}
itemsArr.sort(function(a, b) {
return a.innerHTML == b.innerHTML
? 0
: (a.innerHTML > b.innerHTML ? 1 : -1);
});
for (i = 0; i < itemsArr.length; ++i) {
list.appendChild(itemsArr[i]);
}
Here's JSFiddle.
Upvotes: 0
Views: 2425
Reputation: 43052
Instead of altering the document order you could use flexboxes and the CSS order: property to change their display order.
Upvotes: 0
Reputation: 106385
Here's one possible approach (demo):
var list = document.getElementById('sortme');
var nodesToSort = list.querySelectorAll('.myclass');
Array.prototype.map.call(nodesToSort, function(node) {
return {
node: node,
relevantText: node.querySelector('span').textContent
};
}).sort(function(a, b) {
return a.relevantText.localeCompare(b.relevantText);
}).forEach(function(item) {
list.appendChild(item.node);
});
As you noticed, there are several changes here.
First, as I said, you don't need to use root.childNodes
, as all the items that should be sorted are easily collected with either querySelectorAll
or getElementsByClassname
method (I choose the former, mainly for consistency reasons). That also makes nodeType
-based filtering redundant.
(actually, it would have been redundant in the link answer too, had the author used children
property instead of childNodes
)
Second, the sorting-helper array now contains not just nodes, but objects; the purpose of this technique - also known as memoization - is to minimize the sheer quantity of DOM queries, enhancing the performance.
(here I have replaced innerHTML
query with textContent
, as you seem to be interested only in text here, ignoring any inline tags within the <span>
. If that's not the case, just replace it back)
Finally, another change from the original: replacing double comparison (first ==
, then >
) with simple string function - localeCompare, specifically designed for, well, comparing the strings.
And, of course, now the whole process is structured as a chain of operations:
... without any need of intermediate variables and stuff.
It's not clear whether the structure is uniform (i.e., do you always want to sort based on <span>
contents). If you just want to sort based on visible text, consider using node.innerText
instead of node.querySelector('span').textContent
. Be aware, however: innerText
, although supported by any modern browser, by definition is a slow, calculated value.
Upvotes: 3