jQuery or underscore Sorting a list by span text

耗尽温柔 提交于 2019-12-07 09:21:06

问题


I am a bit lost with trying to order an ul list by the span in the li.
This is my html code:

<ul id="appsList">
    <li><span>aa</span>  <span class="sort">android</span></li>
    <li><span>aa</span>  <span class="sort">ios</span></li>
    <li><span>aa</span>  <span class="sort">facebook</span></li>
    <li><span>bb</span>  <span class="sort">android</span></li>
    <li><span>bb</span>  <span class="sort">ios</span></li>
    <li><span>bb</span>  <span class="sort">facebook</span></li>
</ul>

I have an array that holds the platform names and doesn't have to contain all the platforms and the order of the platforms in the array doesn't matter. I would like the list to be sorted by alphabet order and after that by the alphabetic order of the first span.

So if my array is ["ios","android","facebook"] I would like to order by the elements in the array alphabetically and also by their first span value. So after sorting of the array we will get this:

<ul id="appsList">
    <li><span>aa</span>  <span class="sort">android</span></li>
    <li><span>bb</span>  <span class="sort">android</span></li>
    <li><span>aa</span>  <span class="sort">facebook</span></li>
    <li><span>bb</span>  <span class="sort">facebook</span></li>
    <li><span>aa</span>  <span class="sort">ios</span></li>
    <li><span>bb</span>  <span class="sort">ios</span></li>
</ul>

If the array is just ["ios"] then sort by alphabetically by the array elements and then the rest of the list by alphabet also:

<ul id="appsList">
    <li><span>aa</span>  <span class="sort">ios</span></li>
    <li><span>bb</span>  <span class="sort">ios</span></li>
    <li><span>aa</span>  <span class="sort">android</span></li>
    <li><span>bb</span>  <span class="sort">android</span></li>
    <li><span>aa</span>  <span class="sort">facebook</span></li>
    <li><span>bb</span>  <span class="sort">facebook</span></li>
</ul>

If the array is ["ios","android"] then "android" will be before "ios" and after that "facebook", because "facebook" is not in the array:

<ul id="appsList">
   <li><span>aa</span>  <span class="sort">android</span></li>
   <li><span>bb</span>  <span class="sort">android</span></li>
   <li><span>aa</span>  <span class="sort">ios</span></li>
   <li><span>bb</span>  <span class="sort">ios</span></li>
   <li><span>aa</span>  <span class="sort">facebook</span></li>
   <li><span>bb</span>  <span class="sort">facebook</span></li>
</ul>

This is what I have done so far: PLNKER

If this can be done easily using Underscore I would prefer that. Thank you.


回答1:


You will need to do break up the tasks by filtering and sorting. And then merging the two results.

Plunker Demo

 var arr = ["ios"];
 var $li = $('#appsList li').clone();
 var mySort = function(a, b) {
        var objA = {
            "span": $(a).find('span').not('.sort').text(),
            "sort": $(a).find('.sort').text()
        }
        var objB = {
            "span": $(b).find('span').not('.sort').text(),
            "sort": $(b).find('.sort').text()
        }
        output = objA.sort.localeCompare(objB.sort);
        if (objA.sort === objB.sort) {
            output = objA.span.localeCompare(objB.span);
        }
        return output
    } // mySort
 // Filter for what's in your array
 var arrFilter = function(index, el) {
    return arr.indexOf($(el).find('.sort').text()) > -1;
 }

 // Filter for what's not in your array
 var notArrFilter = function(index, el) {
    return arr.indexOf($(el).find('.sort').text()) < 0;
 }
 var $arrLi = $li.filter(arrFilter);
 var $notArrLi = $li.filter(notArrFilter);
 $arrLi = $arrLi.sort(mySort);
 $notArrLi = $notArrLi.sort(mySort);
 var $newLi = [];
 $.merge($newLi, $arrLi);
 $.merge($newLi, $notArrLi);
 $('#resultAppsList').html($newLi);



回答2:


My proposal is:

Number.prototype.pad = function(size) {
  var s = String(this);
  while (s.length < (size || 2)) {s = "0" + s;}
  return s;
};

function doStuff(arr) {
  var listAllUniqueEle = $.unique($('#appsList li .sort').map(function(index, element) {
    return element.textContent;
  })).sort().toArray();

  listAllUniqueEle = $.unique(arr.sort().concat(listAllUniqueEle));

  var $li = $('#appsList li').clone().sort(function(a, b) {
    var firstValue =  listAllUniqueEle.indexOf(a.childNodes[2].textContent).pad(3) +
        a.textContent + a.textContent;
    var secondValue = listAllUniqueEle.indexOf(b.childNodes[2].textContent).pad(3) +
        b.textContent;
    return firstValue.localeCompare(secondValue);
  });
  $('#resultAppsList').empty().html($li)
}

$(function () {
  $('#btn1').on('click', function(e) {
    doStuff(["ios","android","facebook"]);
  });

  $('#btn2').on('click', function(e) {
    doStuff(["ios"]);
  });

  $('#btn3').on('click', function(e) {
    doStuff(["ios","android"]);
  });
});
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>

<button id="btn1">["ios","android","facebook"]</button>
<button id="btn2">["ios"]</button>
<button id="btn3">["ios","android"]</button>
<br>Before sort :
<ul id="appsList">
    <li><span>bb</span> <span class="sort">ios</span></li>
    <li><span>bb</span> <span class="sort">facebook</span></li>
    <li><span>bb</span> <span class="sort">android</span></li>
    <li><span>aa</span> <span class="sort">ios</span></li>
    <li><span>aa</span> <span class="sort">facebook</span></li>
    <li><span>aa</span> <span class="sort">android</span></li>
    <li><span>aa</span> <span class="sort">android01</span></li>
    <li><span>bb</span> <span class="sort">android01</span></li>
    <li><span>aa</span> <span class="sort">android02</span></li>
    <li><span>bb</span> <span class="sort">android02</span></li>
    <li><span>aa</span> <span class="sort">android03</span></li>
    <li><span>bb</span> <span class="sort">android03</span></li>
    <li><span>aa</span> <span class="sort">android04</span></li>
    <li><span>bb</span> <span class="sort">android04</span></li>
    <li><span>aa</span> <span class="sort">android05</span></li>
    <li><span>bb</span> <span class="sort">android05</span></li>
    <li><span>aa</span> <span class="sort">android06</span></li>
    <li><span>bb</span> <span class="sort">android06</span></li>
    <li><span>aa</span> <span class="sort">android07</span></li>
    <li><span>bb</span> <span class="sort">android07</span></li>
    <li><span>aa</span> <span class="sort">android08</span></li>
    <li><span>bb</span> <span class="sort">android08</span></li>
    <li><span>aa</span> <span class="sort">android09</span></li>
    <li><span>bb</span> <span class="sort">android09</span></li>
    <li><span>aa</span> <span class="sort">android10</span></li>
    <li><span>bb</span> <span class="sort">android10</span></li>
    <li><span>aa</span> <span class="sort">android11</span></li>
    <li><span>bb</span> <span class="sort">android11</span></li>
    <li><span>aa</span> <span class="sort">android12</span></li>
    <li><span>bb</span> <span class="sort">android12</span></li>
    <li><span>aa</span> <span class="sort">android13</span></li>
    <li><span>bb</span> <span class="sort">android13</span></li>
    <li><span>aa</span> <span class="sort">android14</span></li>
    <li><span>bb</span> <span class="sort">android14</span></li>
    <li><span>aa</span> <span class="sort">android15</span></li>
    <li><span>bb</span> <span class="sort">android15</span></li>
    <li><span>aa</span> <span class="sort">android16</span></li>
    <li><span>bb</span> <span class="sort">android16</span></li>
    <li><span>aa</span> <span class="sort">android17</span></li>
    <li><span>bb</span> <span class="sort">android17</span></li>
    <li><span>aa</span> <span class="sort">android18</span></li>
    <li><span>bb</span> <span class="sort">android18</span></li>
    <li><span>aa</span> <span class="sort">android19</span></li>
    <li><span>bb</span> <span class="sort">android19</span></li>
    <li><span>aa</span> <span class="sort">android20</span></li>
    <li><span>bb</span> <span class="sort">android20</span></li>
</ul>

After sort :
<ul id="resultAppsList">
</ul>



回答3:


EDIT: this only does the first sort, you'll have to modify sortElements to group them by .sort then do another pass on li span:first-child.

I use roughly this to sort a list by data-* attributes, here's the code modified for your use. Get the array of elements with jquery then use javascript's native sort to order them. This will sort them alphabetically. In my use case, each element is assigned a data-* attribute with a numerical value (that code is below the first example). Here's a jsfiddle.

function sortElements($parent, selector, sortSelector) {
    var elArr = $parent.find(selector).get();

    var sorted = elArr.sort(function (a, b) {
        var aSortOrder = $(a).find(sortSelector).text();
        var bSortOrder = $(b).find(sortSelector).text();

        if (aSortOrder > bSortOrder)
            return 1;
        else if (aSortOrder < bSortOrder)
            return -1;
        else
            return 0;
    });

    $parent.html(sorted);
}

Sorting by numerical data-* attributes:

function sortElements($parent, selector, dataAttr) {
    var elArr = $parent.find(selector).get();

    var sorted = elArr.sort(function (a, b) {
        var aSortOrder = parseInt($(a).data(dataAttr), 10);
        var bSortOrder = parseInt($(b).data(dataAttr), 10);

        if (aSortOrder > bSortOrder)
            return 1;
        else if (aSortOrder < bSortOrder)
            return -1;
        else
            return 0;
    });

    $parent.html(sorted);
}



回答4:


I have found a solution: this is my js code

function listElementsWithMyArray(){

    //here you can configure your array
    var myArray = ["ios"];

    //creates all needed variables
    var elements = document.getElementsByClassName("sort");
    var ulelement = document.getElementById("myUL");
    var elementStrings = [];
    var elementStringsInMyArray = [];
    var elementStringsNotInMyArray = [];

    //to fill the list with the values of the spans
    for(var i = 0; i < elements.length; i++){
        var element = elements[i];
        elementStrings.push(element.innerHTML);
    }

    //sort the list and also remove the <li> items
    elementStrings.sort();
    ulelement.innerHTML = "";

    //check if the item is in your array and add to the final arrays
    for(var i = 0; i < elementStrings.length; i++){
        var b = 0;
        if(myArray.indexOf(elementStrings[i]) > -1){
            elementStringsInMyArray.push(elementStrings[i]);
            b = 1;
        }else{
            elementStringsNotInMyArray.push(elementStrings[i]);
        }
    }

    //sort both arrays
    elementStringsInMyArray.sort();
    elementStringsNotInMyArray.sort();

    //list all items from myArray and later on from notMyArray
    for(var i = 0; i < elementStringsInMyArray.length; i++){
        ulelement.innerHTML = ulelement.innerHTML + '<li><span class="sort">' + elementStringsInMyArray[i] + '</class></li>';
    }
    for(var i = 0; i < elementStringsNotInMyArray.length; i++){
        ulelement.innerHTML = ulelement.innerHTML + '<li><span class="sort">' + elementStringsNotInMyArray[i] + '</class></li>';
    }

}

and this is my html code

<ul id="myUL">
    <li><span class="sort">android</span>
    <li><span class="sort">facebook</span>
    <li><span class="sort">ios</span>
    <li><span class="sort">android</span>
    <li><span class="sort">facebook</span>
    <li><span class="sort">ios</span>
</ul>

I know you would have liked the code in jQuery but I saw it just when I finished - if you like my code and you'd like me to rewrite it in jQuery I'm fine with that ^^

elsewhise I hope it helps ;)




回答5:


I think this is what you are after. It produces a sort based first on the inclusion in the array, then on the .sort span and finally on the initial span. The results are appended back to the original parent container appearing to be an in-place sort. This example starts with your "unsorted" list from your code.

A lot of this is code is just comments that you can of course strip out.

// --------------------------
// items in this array will sort ahead of those not in the array
// note: position in the array is not important
// --------------------------
var arr = ["ios"];
// --------------------------

// --------------------------
// the parent container
// used to find children and for re-inserting children in the correct order
// --------------------------
var parent = document.getElementById("appsList");
// --------------------------

// --------------------------
// children to be sorted
// --------------------------
var items = Array.from(parent.querySelectorAll("li"));
// --------------------------

// --------------------------
// sort the children
// --------------------------
items.sort(function(a,b){
  // --------------------------
  // create a string that will be sorted
  // --------------------------
  var _prep = function(item){
    var text1 = item.querySelector("span").innerText;
    var text2 = item.querySelector(".sort").innerText;
    return (arr.indexOf(text2) != -1 ? "a~" : "z~") + text2 + "~" + text1
  };
  // --------------------------

  // --------------------------
  // traditional alpha sort function
  // --------------------------
  var _sortAlpha = function(a, b){
    if( a < b ) return -1;
    if( a > b) return 1;
    return 0;
  };
  // --------------------------
  
  // --------------------------
  // return the alpha sorting of our special strings
  // --------------------------
  return _sortAlpha(_prep(a), _prep(b));
  // --------------------------
});
// --------------------------

// --------------------------
// re-insert the children back into the parent
// effectively an in-place sorting
// --------------------------
items.forEach(function(item){ parent.appendChild(item); });
// --------------------------
<ul id="appsList">
    <li><span>bb</span> <span class="sort">ios</span></li>
    <li><span>bb</span> <span class="sort">facebook</span></li>
    <li><span>bb</span> <span class="sort">android</span></li>
    <li><span>aa</span> <span class="sort">ios</span></li>
    <li><span>aa</span> <span class="sort">facebook</span></li>
    <li><span>aa</span> <span class="sort">android</span></li>
 </ul>


来源:https://stackoverflow.com/questions/38247204/jquery-or-underscore-sorting-a-list-by-span-text

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!