Creating a custom sorting function for use as an option in script

662 Views Asked by At

I'm using the vanilla JS script list.js and am trying to implement a custom sorting function.

I have been using the sort method from the List API without issues for normal sorting, however need to create a custom sort for a couple of situations, however because he never provided an example I'm unsure how to do it.

For example I have this code:

var options = {
    valueNames: [ 'date', 'amount', 'company', 'name' ]
};

// Instantiate our list
var myList = new List('mylist', options);

// Set our default sort
myList.sort('date', {order: "desc"});

// Control our own sorting via the links

$('a.sort').on('click', function(event) {

    // Prevent default action
    event.preventDefault();

    var element = $(event.target);

    // Get sorting method
    var method = element.attr('data-sort');

    // Work out what way we want to order the results

    switch (method) {
        case 'date':
        case 'amount':
            var order = 'desc';
            break;
        case 'company':
        case 'name':
            var order = 'asc';
            break;
        default:
            var order = 'desc';
    }

    // Sort the data
    myList.sort(method, {order: order, sortFunction: function(a, b, options){

    }});

    return false; // IE 8

});

He never stated the expected signature for the function, but I worked out it has 3 parameters filled with data, the first two seem to contain elements from within the sorting list and the third has options of some kind.

I have read about using custom sorting functions but unsure how to complement them here.

One example of a sort we would need is that we have a list of dates, such as:

  • 2015 Spring/Summer
  • 2014 Spring/Summer
  • 2013 Winter
  • 2005 Fall

It should sort by highest number first (in this case 2015) then season in this order first to last: winter, fall, spring/summer.

Is it possible to make a custom sort for stuff like that and if so how can it be implemented with this script?

1

There are 1 best solutions below

8
On BEST ANSWER

The sorting function should return a negative number if a should come before b, 0 if it shouldn't be changed, or a positive number if b should come before a. Here is one possible implementation, assuming the date is a predictable string with the format YYYY {{season}}.

// Putting the season in the keys for ease of use and assigning them values so we know which one comes first.
var seasonMap = {
    'Spring/Summer': 0,
    Winter: 1,
    Fall: 2
};

var order = 'asc'; // ascending or descending

function sortFunction(a, b) {
    var coefficient = order === 'asc' ? 1 : -1; // If the order you pass it is 'asc', the a positive coefficient will retain this function's ascending sorting order; otherwise it will invert this function.

    // Convert the dates into arrays by splitting them by a space ' '
    var aDateComponents = a._values.date.split(' '),
        bDateComponents = b._values.date.split(' ');

    // The 0th value of the array is the year; additionally convert it into a Number instead of a String
    var aYear = Number(aDateComponents[0]),
        bYear = Number(bDateComponents[0]);

    // The 1st value of the array is the season; look up the value from the map object we created in the beginning so we know which season comes after which
    var aSeasonNumber = seasonMap[aDateComponents[1]],
        bSeasonNumber = seasonMap[bDateComponents[1]];

    if (aYear !== bYear) {
        // return aYear - bYear. If a > b this will put a after b. The coefficient will invert it if we're sorting descending.
        return coefficient * (aYear - bYear);
    }

    if (aSeasonNumber !== bSeasonNumber) {
        // Same thing here. Since the season was mapped to a number, we know which season comes first and can return a positive or negative difference.
        return coefficient * (aSeasonNumber - bSeasonNumber);
    }

    // Don't change the order otherwise.
    return 0;
}

You should also validate the date string first, and check if it's a valid season.