Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding Backbone.js comparator

I have a simple backbone.js twitter application that needs to sort tweets in reverse order. I've currently implemented a comparator sort by date. When the "Reverse" button is clicked (as seen in the View) how do I reverse sort all the tweets without going back through the comparator? My impression is that when I call sort it will attempt to re-render the list (which means the comparator will sort the data again, which is undesirable). How do I override this?

Tweet = Backbone.Model.extend();

 // Define the collection
Tweets = Backbone.Collection.extend(
{
    model: Tweet,
    // Url to request when fetch() is called
    url: 'http://search.twitter.com/search.json?q=codinghorror',

    parse: function(response) {

        //modify dates to be more readable
        $.each(response.results, function(i,val) {
            val.created_at = val.created_at.slice(0, val.created_at.length - 6);
          });

        return response.results;
    },
    // Overwrite the sync method to pass over the Same Origin Policy
    sync: function(method, model, options) {
        var that = this;
            var params = _.extend({
                type: 'GET',
                dataType: 'jsonp',
                url: that.url,
                processData: true
            }, options);

        return $.ajax(params);
    },
    comparator: function(activity){

        var date = new Date(activity.get('created_at'));
        return -date.getTime();

    }
});

   // Define the View
  TweetsView = Backbone.View.extend({
initialize: function() {
  _.bindAll(this, 'render');
  // create a collection
  this.collection = new Tweets;
  // Fetch the collection and call render() method
  var that = this;
  this.collection.fetch({
    success: function (s) {
        console.log("fetched", s);
        that.render();
    }
  });
},

el: $('#tweetContainer'),
// Use an external template

template: _.template($('#tweettemplate').html()),

render: function() {
    // Fill the html with the template and the collection
    $(this.el).html(this.template({ tweets: this.collection.toJSON() }));
},

events : {
    'click .refresh' : 'refresh',
    **'click .reverse' : 'reverse'**
},

refresh : function() {

 this.collection.fetch();
console.log('refresh', this.collection);
 this.render();

},

**reverse : function() {**

    console.log("you clicked reverse");

    console.log(this.collection, "collection");

    this.collection.sort();

   //How do I reverse the list without going through the comparator?

**}**

});

var app = new TweetsView();
 });
like image 656
The Internet Avatar asked Aug 02 '26 04:08

The Internet


1 Answers

The usual solution to Backbone problems is to use events. Calling sort will trigger a "reset" event:

Calling sort triggers the collection's "reset" event, unless silenced by passing {silent: true}.

So you could have a "sort order" flag in your collection:

Backbone.Collection.extend({
    //...
    initialize: function() {
        //...
        this.sort_order = 'desc';
        //...
    }
});

and then your comparator can pay attention to that flag:

comparator: function(activity) {
    var date = new Date(activity.get('created_at'));
    return this.sort_order == 'desc'
         ? -date.getTime()
         :  date.getTime()
}

and you could have a method on the collection to change the sort order:

reverse: function() {
    this.sort_order = this.sort_order = 'desc' ? 'asc' : 'desc';
    this.sort();
}

Then your view can listen for the "reset" event and redisplay the collection when you change the sort order. Once all that's in place, you just tell your your reverse button to call view.collection.reverse() and everything will be fine.

Demo: http://jsfiddle.net/ambiguous/SJDKy/

like image 131
mu is too short Avatar answered Aug 03 '26 18:08

mu is too short



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!