Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort list items using custom sort order in jQuery

My question is very similar to a number of others I've found on Stack Overflow, but not quite the same.

I'd like to sort list items based on the content of a span contained within each item -- but using a sort order that I can define. Here's the HTML for a sample list item:

<li>
    <span class="fname">John</span>
    <span class="lname">Doe</span>
    <span class="year">Sophomore</span>
</li>

I want to sort based on the content of the "year" span, but chronologically rather than alphabetically. The order, obviously, needs to be:

  • Freshman
  • Sophomore
  • Junior
  • Senior

How can I do this?

Just for reference, I'm using the following jQuery code (which works perfectly) to sort alphabetically by last name:

function sortByLastName(){
    var myList = $('#foo ul');
    var listItems = myList.children('li').get();
    listItems.sort(function(a,b){
        var compA = $(a).find('.lname').text().toUpperCase();
        var compB = $(b).find('.lname').text().toUpperCase();
        return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
    });
    $(myList).append(listItems);
};
like image 569
40 Degree Day Avatar asked Jul 06 '11 04:07

40 Degree Day


3 Answers

To match your sortByLastName() function, this would work:

function sortByYear(){
  var myYears = ['Freshman', 'Sophomore', 'Junior', 'Senior'];
  var myList = $('#foo ul');
  var listItems = myList.children('li').get();
  listItems.sort(function(a,b){
    var compA = $.inArray($(a).find('.year').text(), myYears);
    var compB = $.inArray($(b).find('.year').text(), myYears);
    return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
  });
  $(myList).append(listItems);
}

Just use $.inArray() to find the indices of each school year within the array. Note that this will return -1 for values not found in the array, which will put those elements at the top of your list.

like image 65
jaredbranum Avatar answered Nov 04 '22 12:11

jaredbranum


One simple way would be to create an array with your expected values.

var years=['Freshman', 'Sophomore', 'Junior', 'Senior' ];

Then when you sort your elements, compare indexes.

listItems.sort(function(a,b){
    var indexA = $.inArray(  $(a).find('.year').text(), years );
    var indexB = $.inArray( $(b).find('.year').text(), years );
    return ( indexA < indexB) ? -1 : ( indexA > indexB) ? 1 : 0;
});
like image 33
czarchaic Avatar answered Nov 04 '22 13:11

czarchaic


You have to change your sorting criterion callback. Like this:

function sortByLastName(){
    var myList = $('#foo ul');
    var listItems = myList.children('li').get();
    var scores = {
       "FRESHMAN": 0, "SOPHOMORE": 1, "JUNIOR": 2, "SENIOR": 3
    };
    listItems.sort(function(a,b){
        var compA = $(a).find('.lname').text().toUpperCase();
        var compB = $(b).find('.lname').text().toUpperCase();
        compA = scores[compA]; compB = scores[compB]; //Sort by scores instead of values
        return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
    });
    $(myList).append(listItems);
};

Hope this helps

like image 1
Edgar Villegas Alvarado Avatar answered Nov 04 '22 14:11

Edgar Villegas Alvarado