问题
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