Skip to content

Instantly share code, notes, and snippets.

@iros
Created December 22, 2011 18:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save iros/1511225 to your computer and use it in GitHub Desktop.
Save iros/1511225 to your computer and use it in GitHub Desktop.
Backbone Blog Post :: Live Collections
// A collection holding many tweet objects.
// also responsible for performing the
// search that fetches them.
var Tweets = Backbone.Collection.extend({
model: Tweet,
initialize: function(models, options) {
this.query = options.query;
},
url: function() {
return "http://search.twitter.com/search.json?q=" + this.query + "&callback=?";
},
parse: function(data) {
// note that the original result contains tweets inside of a results array, not at
// the root of the response.
return data.results;
},
add : function(models, options) {
var newModels = [];
_.each(models, function(model) {
if (_.isUndefined(this.get(model.id))) {
newModels.push(model);
}
}, this);
return Backbone.Collection.prototype.add.call(this, newModels, options);
}
});
// From Backbone.Collection's definition:
_add : function(model, options) {
options || (options = {});
model = this._prepareModel(model, options);
if (!model) return false;
var already = this.getByCid(model);
if (already) throw new Error(["Can't add the same model to a set twice", already.id]);
var catTweets = new Tweets([], { query : "cats" });
var catTweetsView = new TweetsView({ collection : catTweets });
catTweets.fetch({
success : function(collection) {
$('#example_content').html(catTweetsView.render().el);
}
});
var Tweets = Backbone.Collection.extend({
model : Tweet,
initialize : function(models, options) {
this.query = options.query;
},
url : function() {
return "http://search.twitter.com/search.json?q=" + this.query + "&callback=?";
},
parse : function(data) {
// note that the original result contains tweets inside of a 'results' array, not at
// the root of the response.
return data.results;
}
});
var TweetsView = Backbone.View.extend({
tagName : "ul",
className : "tweets",
render : function() {
// for each tweet, create a view and prepend it to the list.
this.collection.each(function(tweet) {
var tweetView = new TweetView({ model : tweet });
$(this.el).prepend(tweetView.render().el);
}, this);
return this;
}
});
// Base Tweet Model.
var Tweet = Backbone.Model.extend({});
// Base representation of a tweet
var TweetView = Backbone.View.extend({
tagName : "li",
className : "tweet",
render : function() {
// just render the tweet text as the content of this element.
$(this.el).html(this.model.get("text"));
return this;
}
});
// A container for a tweet object.
var Tweet = Backbone.Model.extend({
initialize: function(attributes, options) {
this.cid = this.id;
}
});
var catTweets = new Tweets([], { query : "cats" });
var catTweetsView = new TweetsView({ collection : catTweets });
// Before we even start our fetch, we append the initial view so that it serves as a
// placeholder for all the tweets we will be adding.
$('#example_content').html(catTweetsView.render().el);
// Note that we've added the "add" property to the fetch options
// and set it to true.
// This will ensure each additionally fetched tweet will be _added_ to the collection
// rather than overwrite its existing contents.
var updateTweets = function() {
catTweets.fetch({
add: true
});
setTimeout(updateTweets, 1000);
};
updateTweets();
// A rendering of a collection of tweets.
var TweetsView = Backbone.View.extend({
tagName: "ul",
className : "tweets",
initialize: function(options) {
// Bind on initialization rather than rendering. This might seem
// counter-intuitive because we are effectively "rendering" this
// view by creating other views. The reason we are doing this here
// is because we only want to bind to "add" once, but effectively we should
// be able to call render multiple times without subscribing to "add" more
// than once.
this.collection.bind("add", function(model) {
var tweetView = new TweetView({
model: model
});
$(this.el).prepend(tweetView.render().el);
}, this);
},
render: function() {
return this;
}
});
// Create a StreamCollection
var StreamCollection = Backbone.Collection.extend({
stream: function(options) {
// Cancel any potential previous stream
this.unstream();
var _update = _.bind(function() {
this.fetch(options);
this._intervalFetch = window.setTimeout(_update, options.interval || 1000);
}, this);
_update();
},
unstream: function() {
window.clearTimeout(this._intervalFetch);
delete this._intervalFetch;
},
isStreaming : function() {
return _.isUndefined(this._intervalFetch);
}
});
{
completed_in: 0.014,
max_id: 149590100207091700,
max_id_str: "149590100207091712",
next_page: "?page=2&max_id=149590100207091712&q=cats",
page: 1,
query: "cats",
refresh_url: "?since_id=149590100207091712&q=cats",
results: [
{
created_at: "Wed, 21 Dec 2011 20:40:33 +0000",
from_user: "EmmySchmt",
from_user_id: 105722790,
from_user_id_str: "105722790",
from_user_name: "Emily Schmidt",
geo: null,
id: 149590100207091700,
id_str: "149590100207091712",
iso_language_code: "en",
metadata: {
result_type: "recent"
},
profile_image_url: "http://a3.twimg.com/profile_images/1553973709/LLP_normal.jpg",
profile_image_url_https: "https://si0.twimg.com/profile_images/1553973709/LLP_normal.jpg",
source: "<a href="http://seesmic.com/" rel="nofollow">Seesmic</a>",
text: "My nephews playing a fishing game. Ya know kid, fish aren't cats. You can't pull the bait away from them for fun.",
to_user: null,
to_user_id: null,
to_user_id_str: null,
to_user_name: null
},
{ ... }
]
}
@ryanflorence
Copy link

in add_duplication_check.js you could clean that up a bit using _.filter instead of doing it yourself with _.each.

@barceyken
Copy link

I found stream_collection.js very interesting, I added that code with some loggin to my collection and I realized that the function isStreaming() isnt working well :S

  isStreaming : function() {
    return _.isUndefined(this._intervalFetch);   
  }

return true in the case that _intervalFetch is undefined, I must add return !_.isUndefined(this._intervalFetch);

Greetings :D.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment