Skip to content

Instantly share code, notes, and snippets.

@wesleytodd
Created October 24, 2012 19:05
Show Gist options
  • Save wesleytodd/3948155 to your computer and use it in GitHub Desktop.
Save wesleytodd/3948155 to your computer and use it in GitHub Desktop.
Backbone Gallery Notes
@wesleytodd
Copy link
Author

Hey Wes!

Overall it looks great!! The backbone portions of this are exactly how I would have set them up. I only have a few small things that I would have changed.

@wesleytodd
Copy link
Author

oops, I thought I could make line specific comments, but apparently I cannot. So here is the list:

Line 1: This call defers the setup of all the code inside until the page is ready. Because of that it can make the page render seem slower because it has so much to do. In a simple example like this that is not such a big deal, but if it was crunching more data or doing more DOM manipulation that could be worse. And the change is so simple it makes it a no-brainier to just do:

// Everything else here...
wl.ready(function(){
    var gallery_images    = new Gallery();
var gallery_container = new GalleryContainer({ el: $('#gallery_container'), collection: gallery_images });
});

One other thing this enables you to do is move the parts of the Backbone app into separate files for ease of use when the project gets bigger.

Line 33: One thing that I have found is that you often want to run the fetch method from many places. When you do you end up having to write the type: 'POST' and data: ... things over and over. To keep things dry you can move that into the fetch method of the controller:

var Gallery = Backbone.Collection.extend({
    fetch : function(options){
                 if (!_.isUndefined(options)) options = {};
                 if (!_.isUndefined(options.data)) options.data = {};
                 options.data = _.extend({
                          track:  $('#filters\\[track\\]').val(),
                      team:   $('#filters\\[team\\]').val(),
              driver: $('#filters\\[driver\\]').val()
                 }, options.data);
                  var args = _.extend({
                         type: 'POST'
                  }, options);
                  Backbone.Collection.prototype.fetch.call(this, args);
            }
});

Unfortunately JavaScript is a bit verbose when you want to make things flexible, but it is what it is. So basically now this will let you just call fetch wherever you need to and it will grab the filter values automatically.

Line 45: For performance reasons you always want to keep the DOM manipulation to a minimum. So running append for every new image is not the best route. Also, the _.template makes it so you can compile and re-use the templates. So to get both of these fixed I would recommend something more like this:

render:function() {
                    // Setup a new element to add your images to

     var $el = $('

@wesleytodd
Copy link
Author

I think that rendered the "div" as html...here is the full code snippet

render:function() {
    // Setup a new element to add your images to
    var $el = $('<div id="gallery_images" />'),
        // pre-compile the template. tmpl is a function.
        tmpl = _.template($('#gallery_image_template').html());
    // the 'each' function is built into the collection, so you can call it directly
    this.collection.each(function (model) {
        // two things here: the toJSON method is the recommended way to access a model for rendering
        // the output of the tmpl function is appended to the new element to prevent re-draws
        $el.append( tmpl({ image: model.toJSON() }) );
    }, this);
    // replace with so that there is only one re-draw triggered by DOM manipulation
    this.$('#gallery_images').replaceWith($el);
    return this;

    }

@wlionGit
Copy link

Swank. Thanks Wes!

I'll post back again when I get your suggestions in place. They all make sense, and it would have taken me a while to figure out the best way to implement them.

One question though about moving the backbone structure out of the wl.ready() function. What's the best way to prevent conflicts with other variables that may be referenced in the same scope? Gallery and Image seem pretty common. Would you use some kind of prefix convention?

@wlionGit
Copy link

Other than some different variable naming here and there, I've got your suggestions in place. I've separated out the backbone structure from the wl.ready() function. I've also removed the event logging code I had in place for each initialize method. I'm liking this stuff. Thanks again Wes!

@wesleytodd
Copy link
Author

Hey! Sorry for my slow response, I thought I should have gotten an email on this but never did. Anyway, the best way to move it out of the wl.ready() is to use the module pattern:

var dulaney_gallery = (function(){
    // All your code

    // return the parts you want to expose to the world
    return {
        Gallery : Gallery,
        GalleryContainer : GalleryContainer
    };
})();

wl.ready(function(){
    var gallery_images    = new dulaney_gallery.Gallery();
    var gallery_container = new dulaney_gallery.GalleryContainer({
        el: $('#gallery_container'),
        collection: gallery_images
    });
});

For more on the module pattern you can look at this: Learning JavaScript Design Patterns

@wlionGit
Copy link

wlionGit commented Nov 2, 2012

Cool. I'll implement those mods and check out that link when I get some free time again. Thanks again for the great advice!

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