简体   繁体   English

使用每个项目data-char值以数字和字母顺序对UL进行排序

[英]Sort UL numerically and alphabetically, using each items data-char value

I'm wanting to sort this UL numerically and alphabetically, using each items data-char value. 我想用数字和字母顺序对UL进行排序,使用每个项目的data-char值。

Note: I'm only wanting to sort the parent UL, not the child UL elements. 注意:我只想对父UL进行排序,而不是子UL元素。

<ul>
  <li data-char="w">
    <span>W</span>
    <ul>
      <li>WWWWWWWWWWWWWW</li>
    </ul>
  </li>
  <li data-char="5">
    <span>5</span>
    <ul>
      <li>55555555555555</li>
    </ul>
  </li>
   <li data-char="a">
    <span>A</span>
    <ul>
      <li>AAAAAAAAAAAAAA</li>
    </ul>
  </li>
    <li data-char="1">
    <span>1</span>
    <ul>
      <li>11111111111</li>
    </ul>
  </li>
</ul>

I'm able to accomplish this with jQuery by doing: 通过执行以下操作,我可以通过jQuery完成此任务:

function sortCharLi(a, b) {

    var va = a.dataset.char.toString().charCodeAt(0),
        vb = b.dataset.char.toString().charCodeAt(0);

    // add weight if it's a number
    if (va < 'a'.charCodeAt(0)) va += 100;
    if (vb < 'a'.charCodeAt(0)) vb += 100;

    return vb < va ? 1 : -1;
}

$('ul > li').sort(sortCharLi).appendTo('ul');

But I'm needing to remove the jQuery dependency so that's not an option any more. 但我需要删除jQuery依赖项,因此不再是一个选项。

Any ideas how I may do this without jQuery? 有没有想法如何在没有jQuery的情况下做到这一点?

JSBIN JSBIN

You can get the ul using getElemetsByTagName and children li can be get from the element object using children property. 您可以使用getElemetsByTagName获取ul并且可以使用children属性从元素对象获取子li

 function order(ul) { // get html children elements of li // in case of ul children will be li // ` Array.from` will hell helps to convert them into array var elements = Array.from(ul.children); // sort them with the same code elements.sort(function(a, b) { var va = a.getAttribute('data-char').charCodeAt(0), vb = b.getAttribute('data-char').charCodeAt(0), charCA = 'a'.charCodeAt(0); // add weight if it's a number if (va < charCA) va += 100; if (vb < charCA) vb += 100; // just get the difference and return to sort them return va - vb; }); // append back to update the order // forEach can be used to update since it's in array format elements.forEach(function(ele) { ul.appendChild(ele) }); } // get ul tag from dom and pass as parameter // although you can use id selector or querySelector, etc // it depends up on your need, here you just need to pass the dom reference of `ul` to be sorted order(document.getElementsByTagName('ul')[0]); 
 <ul> <li data-char="w"> <span>W</span> <ul> <li>WWWWWWWWWWWWWW</li> </ul> </li> <li data-char="5"> <span>5</span> <ul> <li>55555555555555</li> </ul> </li> <li data-char="a"> <span>A</span> <ul> <li>AAAAAAAAAAAAAA</li> </ul> </li> <li data-char="1"> <span>1</span> <ul> <li>11111111111</li> </ul> </li> </ul> 


UPDATE : If you want to use them in chain as in jQuery, then extend the prototype 更新:如果你想在链中使用它们,就像在jQuery中一样,那么扩展原型

 NodeList.prototype.sortElements = function(custom) { // if custom sort function passed then sort based on that if (typeof custom === 'function') return [].slice.call(this).sort(custom); // otherwise apply sort method directly return [].slice.call(this).sort(); // you can also use Array.from(this), which only works in latest browsers } Array.prototype.updateOrder = function() { // iterate over array element this.forEach(function(ele) { // append to the parent element ele.parentNode.appendChild(ele); }) } // sort them with the same code function sortFn(a, b) { var va = a.getAttribute('data-char').charCodeAt(0), vb = b.getAttribute('data-char').charCodeAt(0), charCA = 'a'.charCodeAt(0); // add weight if it's a number if (va < charCA) va += 100; if (vb < charCA) vb += 100; // just get the difference and return to sort them return va - vb; } // get li elements which have `data-char` attribute document.querySelectorAll('ul li[data-char]') .sortElements(sortFn) // call sortElements methods we defined with custom sort function .updateOrder(); // call updateOrder to update the order of element 
 <ul> <li data-char="w"> <span>W</span> <ul> <li>WWWWWWWWWWWWWW</li> </ul> </li> <li data-char="5"> <span>5</span> <ul> <li>55555555555555</li> </ul> </li> <li data-char="a"> <span>A</span> <ul> <li>AAAAAAAAAAAAAA</li> </ul> </li> <li data-char="1"> <span>1</span> <ul> <li>11111111111</li> </ul> </li> </ul> 

This function preserves your original sorter method. 此功能保留原始分拣机方法。 The function expects the ul element to be passed: 该函数需要传递ul元素:

function sortThem(ul) {
    var nodes = Array.prototype.slice.call(ul.childNodes).filter(function(el) {
        // Could use QSA with scope depending on browser support here
        return el.tagName === 'LI';
    });

    nodes.sort(function(a, b) {
        var va = a.getAttribute('data-char').charCodeAt(0),
            vb = b.getAttribute('data-char').charCodeAt(0);

        // add weight if it's a number
        if (va < 'a'.charCodeAt(0)) va += 100;
        if (vb < 'a'.charCodeAt(0)) vb += 100;

        return vb < va ? 1 : -1;
    });

    nodes.forEach(function(node) {
        ul.appendChild(node);
    });
}

You may use querySelectorAll for $('ul > li') . 您可以将querySelectorAll用于$('ul > li') Pay attention, the right selector should be $('ul > li[data-char]') because you are inrested only in li tags having the data-char as attribute. 请注意,正确的选择器应该是$('ul > li[data-char]')因为您只对具有data-char属性的li标签感兴趣。

To convert the NodeList returned from querySelectorAll to array you can use Array.from . 要将从querySelectorAll返回的NodeList转换为数组,可以使用Array.from

To substitute the appendTo you may use forEach . 要替换appendTo,您可以使用forEach

So the code could be: 所以代码可以是:

 function sortCharLi(a, b) { var va = a.getAttribute('data-char').charCodeAt(0), vb = b.getAttribute('data-char').charCodeAt(0); // add weight if it's a number if (va < 'a'.charCodeAt(0)) va += 100; if (vb < 'a'.charCodeAt(0)) vb += 100; return vb < va ? 1 : -1; } window.onload = function() { // $('ul > li').sort(sortCharLi).appendTo('ul'); Array.from(document.querySelectorAll('ul > li[data-char]')).sort(sortCharLi).forEach(function(element, index) { element.parentNode.appendChild(element); }); } 
 <ul> <li data-char="w"> <span>W</span> <ul> <li>WWWWWWWWWWWWWW</li> </ul> </li> <li data-char="5"> <span>5</span> <ul> <li>55555555555555</li> </ul> </li> <li data-char="a"> <span>A</span> <ul> <li>AAAAAAAAAAAAAA</li> </ul> </li> <li data-char="1"> <span>1</span> <ul> <li>11111111111</li> </ul> </li> </ul> 

UPDATE A shorter way to convert: 更新更短的转换方式:

$('ul > li[data-char]').sort(sortCharLi).appendTo('ul');

to pure javaScript can be: 到纯javaScript可以是:

document.querySelectorAll('ul > li[data-char]').sort(sortCharLi).replaceWith();

In order to achieve this result the following methods have to be added: 为了达到这个结果,必须添加以下方法:

NodeList.prototype.sort = function(callBack) {
    if (typeof callBack === 'function') {
        return [].slice.call(this).sort(callBack);
    } else {
        return [].slice.call(this).sort();
    }
}

Array.prototype.replaceWith = function() {
    this.forEach(function(element, index) {
        element.parentNode.appendChild(element);
    });
    return this;

} }

In this way there exist the possibility to chain methods like in jQuery: 通过这种方式,有可能链接jQuery中的方法:

 function sortCharLi(a, b) { var va = a.getAttribute('data-char').charCodeAt(0), vb = b.getAttribute('data-char').charCodeAt(0); // add weight if it's a number if (va < 'a'.charCodeAt(0)) va += 100; if (vb < 'a'.charCodeAt(0)) vb += 100; return vb < va ? 1 : -1; } NodeList.prototype.sort = function(callBack) { if (typeof callBack === 'function') { return [].slice.call(this).sort(callBack); } else { return [].slice.call(this).sort(); } } Array.prototype.replaceWith = function() { this.forEach(function(element, index) { element.parentNode.appendChild(element); }); return this; } window.onload = function () { document.querySelectorAll('ul > li[data-char]').sort(sortCharLi).replaceWith(); } 
 <ul> <li data-char="w"> <span>W</span> <ul> <li>WWWWWWWWWWWWWW</li> </ul> </li> <li data-char="5"> <span>5</span> <ul> <li>55555555555555</li> </ul> </li> <li data-char="a"> <span>A</span> <ul> <li>AAAAAAAAAAAAAA</li> </ul> </li> <li data-char="1"> <span>1</span> <ul> <li>11111111111</li> </ul> </li> </ul> 

This is the best answer I can snap off from work, but it might need to be tailored to your html structure. 这是我可以从工作中解脱出来的最佳答案,但可能需要根据您的html结构进行调整。

FUNCTION TO SORT UL WITHOUT JQUERY: 无需观察即可分拣UL的功能:

function sortUnorderedList(ul, sortDescending) {
 if(typeof ul == "string")
    ul = document.getElementById(ul);

  // Idiot-proof, remove if you want
  if(!ul) {
    alert("The UL object is null!");
    return;
  }

  // Get the list items and setup an array for sorting
  var lis = ul.getElementsByTagName("LI");
  var vals = [];

 // Populate the array
  for(var i = 0, l = lis.length; i < l; i++)
    vals.push(lis[i].innerHTML);

  // Sort it
  vals.sort();

  // Sometimes you gotta DESC
  if(sortDescending)
    vals.reverse();

 // Change the list on the page
  for(var i = 0, l = lis.length; i < l; i++)
    lis[i].innerHTML = vals[i];
}

USAGE: 用法:

sortUnorderedList("ID_OF_LIST");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Java进行数字和字母排序表 - Sort table both numerically and alphabetically using Javascript 按数据属性对列表项进行排序,按字母顺序排序,然后按数字排序 - Sorting list items by data attribute, alphabetically and then numerically Javascript按数字排序,而不是按字母排序 - Javascript sort numerically instead of alphabetically 按字母顺序对字符串数组进行排序,然后按特殊字符对数字进行排序 - Sort an array of strings alphabetically, numerically then by special characters 使用数据表按字母顺序而不是数字顺序对地址列进行排序 - Sort Address Column Alphabetically Instead of Numerically With Datatables 如何对表列进行数字和字母排序? - How to sort a table column numerically and alphabetically? jQuery根据内部元素值按字母顺序和数字顺序对无序列表进行排序 - jQuery sort unordered list alphabetically and numerically based on inner element value(s) Javascript:按数据属性按字母顺序对li项目进行排序,而无需使用jquery - Javascript: Sort li items alphabetically by data attribute without jquery 在ul中按字母顺序对表中的列进行排序 - Sort column in a table alphabetically within a ul 如何在angularjs中按字母和数字排序列表? - How do I sort a list alphabetically and numerically in angularjs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM