我有点力不从心,我希望这是可能的。

我希望能够调用一个函数,该函数将按字母顺序对列表中的所有项进行排序。

我一直在寻找通过jQuery UI排序,但这似乎不是它。任何想法吗?


当前回答

改进基于Jeetendra Chauhan的回答

$('ul.menu').each(function(){
    $(this).children('li').sort((a,b)=>a.innerText.localeCompare(b.innerText)).appendTo(this);
});

为什么我认为这是一个进步:

using each to support running on more than one ul using children('li') instead of ('ul li') is important because we only want to process direct children and not descendants using the arrow function (a,b)=> just looks better (IE not supported) using vanilla innerText instead of $(a).text() for speed improvement using vanilla localeCompare improves speed in case of equal elements (rare in real life usage) using appendTo(this) instead of using another selector will make sure that even if the selector catches more than one ul still nothing breaks

其他回答

@SolutionYogi的答案很有魅力,但似乎使用$。这两种方法都不如直接添加列表来得直接和有效:

var mylist = $('#list');
var listitems = mylist.children('li').get();

listitems.sort(function(a, b) {
   return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
})

mylist.empty().append(listitems);

小提琴

将列表放入一个数组中,使用JavaScript的.sort(),它默认是按字母顺序排列的,然后将数组转换回列表。

http://www.w3schools.com/jsref/jsref_sort.asp

我想自己做这件事,我对提供的任何答案都不满意,因为我相信,它们是二次时间,而我需要在数百个项目的列表上做这件事。

我最终扩展了jquery,我的解决方案使用jquery,但可以很容易地修改为直接使用javascript。

我只访问每个条目两次,并执行一次线性排序,所以我认为,这应该在大型数据集上工作得更快,尽管我坦率地承认我可能错了:

sortList: function() {
   if (!this.is("ul") || !this.length)
      return
   else {
      var getData = function(ul) {
         var lis     = ul.find('li'),
             liData  = {
               liTexts : []
            }; 

         for(var i = 0; i<lis.length; i++){
             var key              = $(lis[i]).text().trim().toLowerCase().replace(/\s/g, ""),
             attrs                = lis[i].attributes;
             liData[key]          = {},
             liData[key]['attrs'] = {},
             liData[key]['html']  = $(lis[i]).html();

             liData.liTexts.push(key);

             for (var j = 0; j < attrs.length; j++) {
                liData[key]['attrs'][attrs[j].nodeName] = attrs[j].nodeValue;
             }
          }

          return liData;
       },

       processData = function (obj){
          var sortedTexts = obj.liTexts.sort(),
              htmlStr     = '';

          for(var i = 0; i < sortedTexts.length; i++){
             var attrsStr   = '',
                 attributes = obj[sortedTexts[i]].attrs;

             for(attr in attributes){
                var str = attr + "=\'" + attributes[attr] + "\' ";
                attrsStr += str;
             }

             htmlStr += "<li "+ attrsStr + ">" + obj[sortedTexts[i]].html+"</li>";
          }

          return htmlStr;

       };

       this.html(processData(getData(this)));
    }
}

改进基于Jeetendra Chauhan的回答

$('ul.menu').each(function(){
    $(this).children('li').sort((a,b)=>a.innerText.localeCompare(b.innerText)).appendTo(this);
});

为什么我认为这是一个进步:

using each to support running on more than one ul using children('li') instead of ('ul li') is important because we only want to process direct children and not descendants using the arrow function (a,b)=> just looks better (IE not supported) using vanilla innerText instead of $(a).text() for speed improvement using vanilla localeCompare improves speed in case of equal elements (rare in real life usage) using appendTo(this) instead of using another selector will make sure that even if the selector catches more than one ul still nothing breaks

为了使这个工作在包括Chrome在内的所有浏览器中工作,你需要使sort()的回调函数返回-1、0或1。

参见http://inderpreetsingh.com/2010/12/01/chromes-javascript-sort-array-function-is-different-yet-proper/

function sortUL(selector) {
    $(selector).children("li").sort(function(a, b) {
        var upA = $(a).text().toUpperCase();
        var upB = $(b).text().toUpperCase();
        return (upA < upB) ? -1 : (upA > upB) ? 1 : 0;
    }).appendTo(selector);
}
sortUL("ul.mylist");