Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse sort order with Backbone.js

With Backbone.js I've got a collection set up with a comparator function. It's nicely sorting the models, but I'd like to reverse the order.

How can I sort the models in descending order rather than ascending?

like image 736
Drew Dara-Abrams Avatar asked Feb 16 '11 07:02

Drew Dara-Abrams


2 Answers

Well, you can return negative values from comparator. If we take, for example, the example from Backbone's site and want to reverse the order, it will look like this:

var Chapter  = Backbone.Model; var chapters = new Backbone.Collection;  chapters.comparator = function(chapter) {   return -chapter.get("page"); // Note the minus! };  chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"}));  alert(chapters.pluck('title')); 
like image 129
Infeligo Avatar answered Oct 11 '22 11:10

Infeligo


Personally, I'm not that happy with any of the solutions given here:

  • The multiplying by -1 solution fails to work when the sort type is non-numeric. Although there are ways around this (by calling Date.getTime() for example) these cases are specific. I would like a general way to reverse the direction of any sort, without having to worry about the specific type of the field being sorted.

  • For the string solution, constructing a string one character at a time seems like a performance bottleneck, especially when using large collections (or indeed, large sort field strings)

Here's a solution that works nicely for String, Date and Numeric fields:

Firstly, declare a comparator that will reverse the result of a result of a sortBy function, like this:

function reverseSortBy(sortByFunction) {   return function(left, right) {     var l = sortByFunction(left);     var r = sortByFunction(right);      if (l === void 0) return -1;     if (r === void 0) return 1;      return l < r ? 1 : l > r ? -1 : 0;   }; } 

Now, if you want to reverse the direction of the sort, all we need to do is:

var Chapter  = Backbone.Model; var chapters = new Backbone.Collection;  // Your normal sortBy function chapters.comparator = function(chapter) {   return chapter.get("title");  };   // If you want to reverse the direction of the sort, apply  // the reverseSortBy function. // Assuming the reverse flag is kept in a boolean var called reverseDirection  if(reverseDirection) {    chapters.comparator = reverseSortBy(chapters.comparator); }  chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"}));  alert(chapters.pluck('title')); 

The reason this works is that Backbone.Collection.sort behaves differently if the sort function has two arguments. In this case, it behaves in the same manner as the comparator passed into Array.sort. This solution works by adapting the single argument sortBy function into a two argument comparator and reversing the result.

like image 42
Andrew Newdigate Avatar answered Oct 11 '22 12:10

Andrew Newdigate