Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Twitter rest api with Backbone?

I'm trying to build a simple Backbone app from this post Unable to fetch data from Twitter RESTful API using Backbone.js Collection . What I wanna do is adding a text box and a button. Every time a user press a button, my app will request to twitter and will search in twitter based on the textbox content (it will search the word 'NYC' as default).

My code is as follows.

My tweets collection

var Tweets = Backbone.Collection.extend({
    model: Tweet,
    url: 'http://search.twitter.com/search.json?q=NYC&callback=?',
    parse: function(response) {
        console.log('parsing ...')
        return response.results;
    }
});

My view.

var PageView = Backbone.View.extend({
    el: $('body'),
    events: {
    'click button#add': 'addItem'
    },
    initialize: function() {
        _.bindAll(this, 'render', 'addItem');
        this.tweets = new Tweets();
        this.counter = 0;
        this.render();
    },
    render: function() {
        $(this.el).append("<input id= 'search'type='text' placeholder='Write a word'></input>");
        $(this.el).append("<button id='add'>Search twitts</button>");
        $(this.el).append("<ul id='tweets'></ul>");
        return this;
    },
    addItem: function(item) {
        var subject = $('#search').val() || 'NYC';
        this.tweets.url = 'http://search.twitter.com/search.json?q=' + subject + '&callback=?';

        // never called ...
        this.tweets.bind('reset', function(collection) {
            console.log(collection.length);
            alert(collection.length);
        });


        $.each(this.tweets.fetch().models, function(index, tweet) { 
            item = new Tweet();
            item.set({
                order: this.counter,
                info: tweet.attributes.text// modify item defaults
            });
            $('ul', this.el).append("<li>" + item.get('order') + " " + item.get('info') + "</li>");
        });

    }
});
var pageView = new PageView();

The thing is:

  1. First click (empty textbox) : twitter request is captured by parse within Tweets collection. Nothing is appended to my ul element.

  2. Second click (with some word): twitter request is made with that word. However, 'NYC' tweets from the previous call are printed.

  3. Third click (with some other word): 'Some word' from second click are printed.

....

I realize that everytime I try to print my tweets I get the previous reply because Twitter hasn't replied me yet. I suppose that I could get my tweets in the parse callback and printed them, but it seems quite nasty.

On the other hand I've tried to get my tweets binding them to the reset event, but it doesn't work either.

Any ideas??.

Thanks in advance!!

like image 461
Ivan Fernandez Avatar asked Dec 05 '22 17:12

Ivan Fernandez


1 Answers

Here's your example code done in a more idimatic Backbone pattern.

Basically:

  • You have your Tweets collection
  • You bind an event handler to the collection's reset event that does something with the newly populated collection
  • In your view, you set up an event handler for your button-click event that calls collection.fetch() to get new data from the 'server'.
  • When the fetch is completed, the reset event is triggered, calling the event handler bound to the reset event.

Code:

var Tweet = Backbone.Model.extend();

var Tweets = Backbone.Collection.extend({
    model: Tweet,
    url: 'http://search.twitter.com/search.json?q=NYC&callback=?',
    parse: function(response) {
        console.log('parsing ...')
        return response.results;
    }
});
var PageView = Backbone.View.extend({
    el: $('body'),
    events: {
        'click button#add': 'doSearch'
    },
    initialize: function() {
        _.bindAll(this, 'render', 'addItem');
        this.tweets = new Tweets();
        _this = this;
        // Bind an event handler for the reset event.
        this.tweets.bind('reset', function(collection) {
            // Clear any old tweet renderings
            _this.$('#tweets').empty();
            // For each tweet in the collection, we call addItem and
            // and pass the tweet.
            collection.each(function(tweet) {
                _this.addItem(tweet);
            });
        });
        this.counter = 0;
        this.render();
    },
    // This function is the event handler for the button click.
    // It tells the Tweets collection to fetch()
    doSearch: function() {
        var subject = $('#search').val() || 'NYC';
        this.tweets.url = 'http://search.twitter.com/search.json?q=' + subject + '&callback=?';
        this.tweets.fetch();
    },
    render: function() {
        $(this.el).append("<input id= 'search'type='text' placeholder='Write a word'></input>");
        $(this.el).append("<button id='add'>Search twitts</button>");
        $(this.el).append("<ul id='tweets'></ul>");
        return this;
    },
    addItem: function(item) {
        console.log(item);
        $('ul', this.el).append("<li><b>" + item.get('from_user_name') + "</b>:  " + item.get('text') + "</li>");

    }
});
var pageView = new PageView();

Live example to play with: http://jsfiddle.net/38L35/16/

like image 66
Edward M Smith Avatar answered Dec 24 '22 12:12

Edward M Smith