Offir Pe'er Offir Pe'er - 4 months ago 12
jQuery Question

jQuery or underscore Sorting a list by span text

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.

Answer

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