Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort HTML elements by data-attribute [duplicate]

I have the following markup:

<ul>
  <li class="category-item" data-category-group="jeans">Bottoms</li>
  <li class="category-item" data-category-group="tops">Shirt</li>
  <li class="category-item" data-category-group="jeans">Jeans</li>
  <li class="category-item" data-category-group="jeans">Shorts</li>
  <li class="category-item" data-category-group="tops">Hoodie</li>
  <li class="category-item" data-category-group="accesories">Sunglasses</li>
</ul>

The elements can have different group names in the data-category-group attribute. I want to be able to sort the elements so that the elements with the group of jeans will all come after each other in the DOM.

I had an idea to try to solve this by turning the HTML collection into an array and then sort them. But its does not seem to be able to work that way.

Here is my JavaScript:

var categoryItems = document.querySelectorAll("[data-category-group]");
var categoryItemsArray = Array.from(categoryItems)

document.getElementById("demo").innerHTML = categoryItemsArray;

function myFunction() {
    categoryItemsArray.sort();
    document.getElementById("demo").innerHTML = categoryItemsArray;
}

How could this be achieved?

Checkout a codepen here: https://codepen.io/fennefoss/pen/PBGrPZ

like image 521
Mikkel Fennefoss Avatar asked Jul 19 '18 12:07

Mikkel Fennefoss


2 Answers

You should use Array#sort, just pass it a function that checks the data-category-group property (using String#localeCompare()):

var categoryItems = document.querySelectorAll("[data-category-group]");
var categoryItemsArray = Array.from(categoryItems);

let sorted = categoryItemsArray.sort(sorter);

function sorter(a,b) {
    return a.dataset.categoryGroup.localeCompare(b.dataset.categoryGroup); // sorts based on alphabetical order
}

document.querySelector("button").onclick = () => sorted.forEach(e => document.querySelector("#demo").appendChild(e));
<ul id="demo">
  <li class="category-item" data-category-group="jeans">Bottoms</li>
  <li class="category-item" data-category-group="tops">Shirt</li>
  <li class="category-item" data-category-group="jeans">Jeans</li>
  <li class="category-item" data-category-group="jeans">Shorts</li>
  <li class="category-item" data-category-group="tops">Hoodie</li>
  <li class="category-item" data-category-group="accesories">Sunglasses</li>
</ul>


<button>Sort Elements</button>
like image 189
Luca Kiebel Avatar answered Oct 04 '22 06:10

Luca Kiebel


You could do this with sort method on an array and then append back elements to ul.

let ul = document.querySelector("ul");
let li = ul.querySelectorAll("li");

let sorted = Array.from(li).sort((a, b) => {
  return (b.dataset.categoryGroup == 'jeans') - (a.dataset.categoryGroup == 'jeans')
})

ul.innerHTML = "";
sorted.forEach(e => ul.appendChild(e))
<ul>
  <li class="category-item" data-category-group="jeans">Bottoms</li>
  <li class="category-item" data-category-group="tops">Shirt</li>
  <li class="category-item" data-category-group="jeans">Jeans</li>
  <li class="category-item" data-category-group="jeans">Shorts</li>
  <li class="category-item" data-category-group="tops">Hoodie</li>
  <li class="category-item" data-category-group="accesories">Sunglasses</li>
</ul>
like image 20
Nenad Vracar Avatar answered Oct 04 '22 07:10

Nenad Vracar