HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Filtering a Backbone collection with multiple parameters

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withcollectionbackbonemultipleparametersfiltering

Problem

I've written a short piece of code to get myself familiar with backbone.js. I'm filtering 100 results from the Twitter API. Once those are in, I use a time picker and a hash tag selector to filter my results.

I want the filter to work in the following manner:

Pick a time range, get a filtered collection and a filtered set of hash tags in the selector tag. Pick a hash tag, filter the SAME RESULTS within that time range.

Pick a hashtag, get a filtered collection. Select a date and filter the same results gotten with the originally chosen hashtag.

Don't lose the original collection:

"use strict";


Define the model:

var Tweet = Backbone.Model.extend({});


Define the collection:

var Tweets = Backbone.Collection.extend({
    initialize : function(options) {
        if (options !== undefined) {
            if (options.location !== undefined) {
                this.location = options.location;
                // console.log(location);
            }
        }
    },

    model : Tweet,
    parse : function(response) {
        var data = response.results;
        $(data).each(
                function() {
                    var timezoneOffset = new Date().getTimezoneOffset() / -60;
                    // var offset = Date.getTimezoneOffset(today.getTimezone(),
                    // today.hasDaylightSavingTime());
                    // console.log(timezoneOffset);
                    var dateTime = Date.parse(this.created_at).addHours(
                            timezoneOffset).toString(
                            "dddd, MMMM dd, yyyy, h:mm:ss tt");
                    this.created_at = dateTime;
                    this.text = twttr.txt.autoLink(this.text);
                    this.from_user = twttr.txt.autoLink("@" + this.from_user);
                    // console.log("user: ", this.from_user);
                });
        // console.log('\nformatted data: ', data);
        return data;
    },


Overwrite the sync method to pass over the Sam

Solution

From a once over:

Collection

  • You could merge those 2 if statements into 1



  • You should remove commented out code



  • You should remove console.log code



  • You should try to have 1 chained var block



  • You should use lowerCamelCasing consistently



This makes the code look a little tighter:

var Tweets = Backbone.Collection.extend({
  initialize : function(options) {
    if (options && options.location) {
      this.location = options.location;
    }
  },
  model : Tweet,
  parse : function(response) {
    var data = response.results;
    $(data).each( function() {
      var timezoneOffset = new Date().getTimezoneOffset() / -60,
          dateTime = Date.parse(this.created_at).addHours(timezoneOffset)
                         .toString("dddd, MMMM dd, yyyy, h:mm:ss tt");
      this.createdAt = dateTime;
      this.text = twttr.txt.autoLink(this.text);
      this.fromUser = twttr.txt.autoLink("@" + this.from_user);

    });
    return data;
  },


sync related

  • sync



  • No need to declare self = this, you only use self once, and it is not in a closure.



-
showHide

  • You can return tweetDate.between(fromDate, toDate) in your filter function, it is shorter and more explicit that it return false when tweetDate is outside the provided dates



-
If you drop the console code, and not use a temp variable, your code becomes so much tighter/readable

showhide : function(toDate, fromDate) {
  return this.filter(function(tweet) {
    var tweetDate = Date.parse(tweet.attributes.created_at);
    return tweetDate.between(fromDate, toDate);
  });
},


  • selectShowHide



  • You are using each to find a match, since you should stop searching and exit after finding a match, you should not use each which forces you to go through all entries, a for loop with a return would do a better job



  • When you need all entries to be returned, you could just use this.makeArray() instead of filtering and always returning true.



  • If find code easier to read if you test on equality ( and then switch your 2 blocks )



  • templateLoader



  • You copy data to source, and use source only once, you could name the parameter itself source in that case



  • You might want to consider memoizing the result of the compilations to speed up your code



As for your questions:

Am I on the right track? Should I be using another way?

Looks okay to me, but I am no backbone expert.

Am I in danger of memory leaks?

If you worry about this, then you should use the Google Developer tools, they are the only surefire way to tell.

Code Snippets

var Tweets = Backbone.Collection.extend({
  initialize : function(options) {
    if (options && options.location) {
      this.location = options.location;
    }
  },
  model : Tweet,
  parse : function(response) {
    var data = response.results;
    $(data).each( function() {
      var timezoneOffset = new Date().getTimezoneOffset() / -60,
          dateTime = Date.parse(this.created_at).addHours(timezoneOffset)
                         .toString("dddd, MMMM dd, yyyy, h:mm:ss tt");
      this.createdAt = dateTime;
      this.text = twttr.txt.autoLink(this.text);
      this.fromUser = twttr.txt.autoLink("@" + this.from_user);

    });
    return data;
  },
showhide : function(toDate, fromDate) {
  return this.filter(function(tweet) {
    var tweetDate = Date.parse(tweet.attributes.created_at);
    return tweetDate.between(fromDate, toDate);
  });
},

Context

StackExchange Code Review Q#13454, answer score: 5

Revisions (0)

No revisions yet.