Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting next and previous model from a collection

Tags:

backbone.js

I've seen a few different ways to get the next or previous model from a collection, but was wondering if anyone could offer some advice on the way I decided to implement it. My collection is ordered, but the id that i'm sorting on is not guaranteed to be sequential. It's only guaranteed to be unique. Assume that smaller ids are "older" entries to the collection and larger ids are "newer".

MyCollection = Backbone.Collection.extend({
  model: MyModel,
  initialize:function (){
    this.getElement = this._getElement(0);
  },
  comparator: function(model) {
    return model.get("id");
  },
  _getElement: function (index){
    var self = this;
    return function (what){
     if (what === "next"){
       if (index+1 >= self.length) return null;
       return self.at(++index);
     }
     if (what === "prev"){
       if (index-1 < 0 ) return null;
       return self.at(--index);
     }
     // what doesn't equal anything useful
     return null;
    };
  }
});

When using getElement, I do things like getElement("next") and getElement("prev") to ask for the next or previous model in my collection. What is returned from getElement is the actual model, not the index. I know about collection.indexOf, but I wanted a way to loop through a collection without first having a model to start from. Is this implementation harder than it needs to be?

like image 353
Sneaky Wombat Avatar asked Apr 17 '12 23:04

Sneaky Wombat


2 Answers

I would do something like this. Keep in mind that there isn't any error handling currently so if you are currently at the first model in the collection and try to get the previous you will probably get an error.

MyCollection = Backbone.Collection.extend({
  model: MyModel,
  initialize:function (){
    this.bindAll(this);
    this.setElement(this.at(0));
  },
  comparator: function(model) {
    return model.get("id");
  },
  getElement: function() {
    return this.currentElement;
  },
  setElement: function(model) {
    this.currentElement = model;
  },
  next: function (){
    this.setElement(this.at(this.indexOf(this.getElement()) + 1));
    return this;
  },
  prev: function() {
    this.setElement(this.at(this.indexOf(this.getElement()) - 1));
    return this;
  }
});

To progress to the next model collection.next(). To progress to the next model and return it var m = collection.next().getElement();

To explain a little better how next/prev works.

// The current model
this.getElement();
// Index of the current model in the collection
this.indexOf(this.getElement())
// Get the model either one before or one after where the current model is in the collection
this.at(this.indexOf(this.getElement()) + 1)
// Set the new model as the current model
this.setElement(this.at(this.indexOf(this.getElement()) + 1));
like image 77
abraham Avatar answered Nov 06 '22 21:11

abraham


I've done this slightly differently in that I'm adding the methods to the model rather than to the collection. That way, I can grab any model, and get the next one in the sequence.

next: function () {
    if (this.collection) {
        return this.collection.at(this.collection.indexOf(this) + 1);
    }
},
prev: function () {
    if (this.collection) {
        return this.collection.at(this.collection.indexOf(this) - 1);
    }
},
like image 45
Tom Avatar answered Nov 06 '22 22:11

Tom