admin管理员组

文章数量:1415145

I have a list of people with job titles sorted by the persons’ first names, like this:

<ul>
  <li data-azsort="smithjohn">
    <a href="#">
      <span class="list-name">John Smith</span>
    </a>
    <span class="list-desc">Professor</span>
  </li>
  ..
  <li data-azsort="barnestom">
    <a href="#">
      <span class="list-name">Tom Barnes</span>
    </a>
    <span class="list-desc">Lecturer</span>
  </li>
</ul>

I’ve added the data-azsort attribute to the <li> element, and I’d like to pop these list elements into an array, and sort based on that data-* attribute (using plain JavaScript).

What would be the best way to sort the list by data-azsort (A-Z), returning the same code? JavaScript only, no jQuery, etc.

I have a list of people with job titles sorted by the persons’ first names, like this:

<ul>
  <li data-azsort="smithjohn">
    <a href="#">
      <span class="list-name">John Smith</span>
    </a>
    <span class="list-desc">Professor</span>
  </li>
  ..
  <li data-azsort="barnestom">
    <a href="#">
      <span class="list-name">Tom Barnes</span>
    </a>
    <span class="list-desc">Lecturer</span>
  </li>
</ul>

I’ve added the data-azsort attribute to the <li> element, and I’d like to pop these list elements into an array, and sort based on that data-* attribute (using plain JavaScript).

What would be the best way to sort the list by data-azsort (A-Z), returning the same code? JavaScript only, no jQuery, etc.

Share Improve this question edited Dec 14, 2015 at 17:04 Sebastian Simon 19.6k8 gold badges61 silver badges84 bronze badges asked Aug 25, 2015 at 8:41 neilneil 1,3062 gold badges12 silver badges21 bronze badges 7
  • so where is problem? what is staff? – Grundy Commented Aug 25, 2015 at 8:43
  • The HTML attribute is data-sortaz in your description you mentioned data-azsort. – Ivanka Todorova Commented Aug 25, 2015 at 8:43
  • you can see Element.getAttribute function – Grundy Commented Aug 25, 2015 at 8:43
  • @IvankaTodorova Thanks, corrected – neil Commented Aug 25, 2015 at 8:46
  • Should this work for only one list or for an arbitrary number of lists? – Sebastian Simon Commented Aug 25, 2015 at 8:53
 |  Show 2 more ments

3 Answers 3

Reset to default 7

This works for any number of lists: it basically gathers all lis in uls that have your attribute, sorts them according to their data-* attribute value and re-appends them to their parent.

Array.from(document.querySelectorAll("ul > li[data-azsort]"))
  .sort(({dataset: {azsort: a}}, {dataset: {azsort: b}}) => a.localeCompare(b)) // To reverse it, use `b.localeCompare(a)`.
  .forEach((item) => item.parentNode.appendChild(item));
<ul>
  <li data-azsort="skeetjon">
    <a href="#"><span class="list-name">Jon Skeet</span></a>
    <span class="list-desc">Stack Overflow user</span>
  </li>
  <li data-azsort="smithjohn">
    <a href="#"><span class="list-name">John Smith</span></a>
    <span class="list-desc">Professor</span>
  </li>
  <li data-azsort="barnestom">
    <a href="#"><span class="list-name">Tom Barnes</span></a>
    <span class="list-desc">Lecturer</span>
  </li>
</ul>
<ul>
  <li data-azsort="smithjohn">
    <a href="#"><span class="list-name">John Smith</span></a>
    <span class="list-desc">Professor</span>
  </li>
  <li data-azsort="barnestom">
    <a href="#"><span class="list-name">Tom Barnes</span></a>
    <span class="list-desc">Lecturer</span>
  </li>
  <li data-azsort="skeetjon">
    <a href="#"><span class="list-name">Jon Skeet</span></a>
    <span class="list-desc">Stack Overflow user</span>
  </li>
</ul>

The funny thing is, it gets all lis in the same array, sorts them all, but in the end figures out which list the li originally belonged to. It’s a pretty simple and straight-forward solution.

If you want to sort elements by a numeric data attribute, then use this sort function instead:

// Presumably, the data-* attribute won’t be called `azsort`. Let’s call it `numsort`.
({dataset: {numsort: a}}, {dataset: {numsort: b}}) => Number(a) - Number(b) // `Number(b) - Number(a)` to reverse the sort.

A slightly longer ECMAScript 5.1 alternative would be:

Array.prototype.slice.call(document.querySelectorAll("ul > li[data-azsort]")).sort(function(a, b) {
  a = a.getAttribute("data-azsort");
  b = b.getAttribute("data-azsort");

  return a.localeCompare(b);
}).forEach(function(node) {
  node.parentNode.appendChild(node);
});

What about getting all of the list items, push them into array which later will be sorted?

var allListElements = document.getElementById("staff").getElementsByTagName("li");
var staff = new Array();
for (i = 0; i < allListElements.length; i++) {
  staff.push(allListElements[i].getAttribute('data-azsort'));
}

staff.sort(function(a, b) {
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
});

//Print

document.write('<h4>Sorted</h4>');
for (i = 0; i < staff.length; i++) { 
  document.write(staff[i] + "<br />");
}
<h4>Input</h4>

<ul id="staff">
  <li data-azsort="smithjohn">
    <a href="#">
      <span class="list-name">John Smith</span>
    </a>
    <span class="list-desc">Professor</span>

  </li>
  <li data-azsort="barnestom">
    <a href="#">
      <span class="list-name">Tom Barnes</span>
    </a>
    <span class="list-desc">Lecturer</span>

  </li>
</ul>

Additionally you can save the index of <li> and reorder the <ul>.

You can pass a parison function to Array.prototype.sort

you should be able to do something like

$items = $('li[data-azsort]');
var pareElem = function (a, b) {
  if (a.attr('data-azsort') > b.attr('data-azsort') {
    return 1;
  } else {
   return -1
  }
};
Array.prototype.sort.apply($items, pareElem);

本文标签: javascriptSorting a list by dataattributeStack Overflow