Search code examples
javascriptsortingbackbone.jsbackbone.js-collections

How do I execute a custom backbone sort on different attributes?


I'm trying to do the following. I would like to sort some baseball players with this in mind. Managers should be at the top (sorted by active then name), then I would like to sort the player or any other type - could be several other types by active and then name.

To top it off, I'm using a case insensitive naturalsort on the name.

This is an example list:

[
    {type: 'manager', name: 'Michael A', active: true},
    {type: 'player', name: 'Abraham B', active: true},
    {type: 'player', name: 'Jason R', active: false},
    {type: 'manager', name: 'John A', active: true},
    {type: 'coach', name: 'Ron A', active: true},
    {type: 'player', name: 'Bobby A', active: false},
    {type: 'player', name: 'Bobby J', active: true}
]

sort on these should produce:

[
    {type: 'manager', name: 'Michael A', active: true},
    {type: 'manager', name: 'John A', active: true},

    {type: 'player', name: 'Abraham B', active: true},
    {type: 'player', name: 'Bobby J', active: true}
    {type: 'coach',  name: 'Ron A', active: true},
    {type: 'player', name: 'Bobby A', active: false},
    {type: 'player', name: 'Jason R', active: false},
]

One thing I've tried is a case statement, but I dont know how to do the next level sort (name and active)

    comparator: function(person) {
        switch (person.get('type')) {
            case 'manager': return 1;
            default: return 2;
        }
    }

Solution

  • Normally you would use the || operator to specify a sorting order. However, In your case, the sorting order based on conditions does not apply. You are not explicitly sorting, but ordering in layers like a cake. So you will need to modify your sort function.

    var list = [{
        type: 'manager',
        name: 'Michael A',
        active: true
      },
      {
        type: 'player',
        name: 'Abraham B',
        active: true
      },
      {
        type: 'player',
        name: 'Jason R',
        active: false
      },
      {
        type: 'manager',
        name: 'John A',
        active: true
      },
      {
        type: 'coach',
        name: 'Ron A',
        active: true
      },
      {
        type: 'player',
        name: 'Bobby A',
        active: false
      },
      {
        type: 'player',
        name: 'Bobby J',
        active: true
      }
    ]
    
    list.sort(function(a, b) {
      return compareActive(a, b) || compareType(a, b) || compareNames(a, b);
    });
    
    function compareActive(a, b) {
      if (a.active === b.active) {
        return 0;
      } else if (a.active === true) {
        return -1;
      } else {
        return 1
      }
    };
    
    function compareNames(a, b) {
      return a.name.localeCompare(b.name);
    };
    
    function compareType(a, b) {
      if (a.type === b.type) {
        return 0;
      } else if (b.type === 'manager') {
        return 1;
      } else if (a.type === 'manager') {
        return -1;
      } else {
        return 0
      }
    }
    console.log(list);