jQuery or underscore Sorting a list by span text

独自空忆成欢 提交于 2019-12-05 16:49:30

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);

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>

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);
}

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 ;)

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