Easiest Way to Sort Dom Nodes

Easiest way to sort DOM nodes?

Though there's probably an easier way to do this using a JS Library, here's a working solution using vanilla js.

var list = document.getElementById('mylist');

var items = list.childNodes;
var itemsArr = [];
for (var i in items) {
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]);
}

sorting DOM elements using pure JS

Use Array#sort method with custom sort function.

// get the aprent elementvar parent = document.querySelector('.items');
// get all children element and convert into array// for newer browser you can use `Array.from` instead// of `[].slice.call()`[].slice.call(parent.children) // sort them using custom sort function .sort(function(a, b) { // get text content in .price and return difference return getPrice(a) - getPrice(b); // iterate and append again in new sorted order }).forEach(function(ele) { parent.appendChild(ele); })
// function for getting the price value from the elementfunction getPrice(ele) { // parse the string return Number(ele // get the price element .querySelector('.price') // get text content .textContent // replace all char except digit and dot .replace(/[^\d.]+/g, '')) // or instead of replace use match method to // get price value // .match(/\d*(?:\.\d+)?/)[0] // return 0 if NaN || 0;}
<div class="items">
<div class="item" id="item1"> <h4>name</h4> <img src=""> <p class="price">1</p> </div>
<div class="item" id="item2"> <h4>name</h4> <img src=""> <p class="price">23</p> </div>
<div class="item" id="item4"> <h4>name</h4> <img src=""> <p class="price">3</p> </div></div>

What is the most efficient way to sort DOM elements based on values in an array of objects?

thanks to @NiettheDarkAbsol his answer combined with the following sort functions has led me to a working answer. I use the data attribute to store the last type of sort (asc or desc). I use @NiettheDarkAbsol suggestion to append nodes, but do it twice, the second time with a condition to check for NAs, then move them to the bottom which works as desired. The sorting function now is :

function sortingFunction(e, property){

peopleContainer = document.getElementById('peopleContainer');
allPeople = peopleContainer.children;

const peopleElements = {};

[...allPeople].forEach(node=>{
peopleElements[node.id] = node;
});

if(e.target.getAttribute('data-lastSort') === 'desc'){
e.target.setAttribute('data-lastSort','asc')
people.sort(function(a,b){
return a[property] - b[property]
});
}else{
e.target.setAttribute('data-lastSort','desc')
people.sort(function(a,b){
return b[property] - a[property]
});
};

people.forEach(person=>{
const node = peopleElements[person.id];
peopleContainer.append(node);
};

people.forEach(person=>{
if(person[property] === 'NA'){
const node = peopleElements[person.id];
peopleContainer.append(node);
};
});

};

How to sort particular DOM nodes in Javascript?

Since you have a quite strict structure you can come up with a selector which will select all the .organization-code elements after the last .organization-subtitle:

.organization-subtitle:last-of-type ~ .organization-code

From there, it's a simple matter of extracting these elements in DocumentFragment and reappend them sorted after that .organization-subtitle:last-of-type element.

const container = document.querySelector( '.organization-results' );
const limit_selector = ".organization-subtitle:last-of-type"
const items = [ ...container.querySelectorAll( limit_selector + " ~ .organization-code") ]
.sort( (a, b) =>
a.textContent.localeCompare( b.textContent )
);
const frag = document.createDocumentFragment();
frag.append( ...items );

container.querySelector( limit_selector ).after( frag );
<div class="organization-results">
<h2 class="organization-subtitle">B</h2>
<div class="organization-code">
<h3 class="organization-title">Xyz Abc</h3>
</div>
<div class="organization-code">
<h3 class="organization-title">Abc Xyz</h3>
</div>

<h2 class="organization-subtitle">A</h2>
<div class="organization-code">
<h3 class="organization-title">Xyz Abc</h3>
</div>
<div class="organization-code">
<h3 class="organization-title">Abc Xyz</h3>
</div>
<!-- Sort contents after last organization subtitle START -->
<h2 class="organization-subtitle">C</h2>
<div class="organization-code">
<h3 class="organization-title">Pqr Abc</h3>
</div>
<div class="organization-code">
<h3 class="organization-title">Xyz Abc</h3>
</div>
<div class="organization-code">
<h3 class="organization-title">Abc Xyz</h3>
</div>
<div class="organization-code">
<h3 class="organization-title">Tuv Vbu</h3>
</div>
<!-- Sort contents after last organization subtitle END -->
</div>

Easy way to sort DOM?

Here is the code.

<!DOCTYPE html><html>
<head> <title>Sort a HTML Table</title> <style> table { border-spacing: 0; width: 100%; border: 1px solid #ddd; } th, td { text-align: left; padding: 16px; } tr:nth-child(even) { background-color: #f2f2f2 } </style></head>
<body>
<p>Click the button to sort the table, by score:</p> <p><button onclick="sortTable()">Sort</button></p>
<table id="myTable"> <tr> <th>Name</th> <th>score</th> </tr> <tr> <td>Andam</td> <td>1</td> </tr> <tr> <td>Ali</td> <td>2</td> </tr> <tr> <td>Akam</td> <td>3</td> </tr> </table>
<script> function sortTable() { var table = document.getElementById("myTable");; var rows = table.getElementsByTagName("TR"); var currentRow; var nextRow;
for (var i = 1; i < rows.length - 1; i++) { for (var j = 1; j < rows.length - 1; j++) { currentRow = rows[j].getElementsByTagName("TD")[1]; nextRow = rows[j + 1].getElementsByTagName("TD")[1]; if (Number(currentRow.innerHTML) < Number(nextRow.innerHTML)) { rows[j].parentNode.insertBefore(rows[j + 1], rows[j]); } } } } </script>
</body>
</html>

JS sort parent element based on child element

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:

  • organizing the array of items alongside their memoized sorting criteria
  • sorting this array
  • (re)appending the nodes from that array into the list

... 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.

JavaScript : Fastest way to insert DOM element in sort order

I'd go with Option 2. The DOM is just objects in a tree structure, so there's no need for a separate abstract tree other than if you want one. You can associate data directly with the elements via attributes or expando properties (if doing the latter, beware of naming conflicts, pick something very specific to your project) — the latter have the advantage of speed and not being limited to strings.

Searching through a list of DOM elements isn't markedly slow at all, nor is it much work.

Example inserting random numbers in divs within a container div:

var container= document.getElementById("container");
function insertOne() { // Our random number var num = Math.floor(Math.random() * 1000); // Convenient access to child elements var children = Array.prototype.slice.call(container.children); // Find the one we should insert in front of var before = children.find(function(element) { return element.__x__random > num; }); // Create the div var div = document.createElement('div'); div.innerHTML = num; div.__x__random = num; // Insert (if `before` is null, it becomes an append) container.insertBefore(div, before);}
// Do it every 250msvar timer = setInterval(insertOne, 250);
// Stop after 5 secondssetTimeout(function() { clearInterval(timer);}, 5000);
<div id="container"></div>

Sort array containing DOM elements according to their position in the DOM

There is a very useful function called compareDocumentPosition, which returns a number based on where two elements are relative to each other. You can use this in a .sort callback:

yourArray.sort(function(a,b) {
if( a === b) return 0;
if( !a.compareDocumentPosition) {
// support for IE8 and below
return a.sourceIndex - b.sourceIndex;
}
if( a.compareDocumentPosition(b) & 2) {
// b comes before a
return 1;
}
return -1;
});

Javascript: Optimized re-ordering of iFrames like DOM nodes

The snippet seems fine. Though the map is not really needed since HTML elements are passed down by reference. You are not creating new ones so deleting them and then adding them back in is unnecessary work.

As for the amount of swaps, that depends on the amount of elements you have. Though each element only gets reordered once in the DOM. (this happens in the forEach)

The snippet below demonstrates a small working example.

const ul = document.querySelector("ul");
const btn = document.querySelector("button");

btn.addEventListener("click", () => {
[...ul.children]
.sort((x, y) => Math.random() - 0.5) // Create a random order
.forEach((x) => ul.appendChild(x));
});
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>

<button>Reorder</button>


Related Topics



Leave a reply



Submit