Skip to content

Commit

Permalink
Upgraded Backbone, Underscore, jQuery. Also templatized the movie tab…
Browse files Browse the repository at this point in the history
…le and created a new view for the select control. Finally, I also started the refactoring of views to follow the new design pattern.
  • Loading branch information
abelmartin committed Apr 30, 2012
1 parent 3ad86ff commit 9c333d9
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 50 deletions.
2 changes: 2 additions & 0 deletions public/javascripts/app/models/sort_manager.js
@@ -1,4 +1,6 @@
var SortManager = Backbone.Model.extend({
//Sorting in backbone apps is a little annoying
//To deal with that, we have this handy sort manager
defaults: {
direction: null,
column: null,
Expand Down
19 changes: 11 additions & 8 deletions public/javascripts/app/router.js
@@ -1,5 +1,4 @@
var CommentOnTheMovies = Backbone.Router.extend({
movie_table_view: null,
// We'll set the proxy URL in the controller.
// This way we have one place to reference it.
proxy_root: "/proxy",
Expand Down Expand Up @@ -41,14 +40,17 @@ var CommentOnTheMovies = Backbone.Router.extend({
start: function(){
this.logEvent("EVENT: We loaded the BACKBONE APP::START FUNCTION");

// We'll instantiate the MovieTableView that we'll need.
// We'll instantiate the collections of movies that we'll be binding events to.
this.movies = new Movies();

// We instantiate & call render() because the controls view only gets rendered once.
this.list_controls_view = new ListControlsView().render();

// The bound events will hand the rendering for us so we can simply instantiate.
this.movie_table_view = new MovieTableView();

//This kicks off the hash routing which really gives the app it's power.
Backbone.history.start();

//It's always good to return the object in question when possible.
return this;
},

routes: {
Expand All @@ -62,13 +64,14 @@ var CommentOnTheMovies = Backbone.Router.extend({
//Let's redirect users to the box_office view if they hit the home view
this.logEvent("EVENT: We loaded the INDEX view");
this.logEvent("EVENT: We should load the following URL:" + window.location.host + "#!list/box_office");
window.location = "http://" + window.location.host + "#!list/box_office";
this.navigate("!list/box_office", {trigger: true, replace: true});
},

list: function(list_name){
// This lets us update the movie table view
this.logEvent("EVENT: We loaded the LIST view");
this.movie_table_view.collection.fetch();
this.logEvent("EVENT: We're loading a new list: " + list_name);
this.movies.list = list_name;
this.movies.fetch();
},

movie: function(movie_id){
Expand Down
29 changes: 29 additions & 0 deletions public/javascripts/app/views/list_controls.js
@@ -0,0 +1,29 @@
var ListControlsView = Backbone.View.extend({
id: "SearchControls",
template: $("#TMPSearchControls").html(),

initialize: function(opts){
_.bindAll(this,
'render',
'listChanged');
this.collection = window.COTM.movies;
$("#MovieTableContainer").append(this.$el);
},

events: {
"change #MovieList" : "listChanged"
},

listChanged: function(e){
//We'll simply change trigger a routing action.
//This gives us bookmarkable urls and simplifies our code.
var new_list = $(e.target).val();
window.COTM.navigate("!list/" + new_list, {trigger: true, replace: true});
window.COTM.logEvent("The Movie List changed. We called for new data from the API: " + new_list);
},

render: function(){
this.$el.html( $.mustache( this.template ) );
return this;
}
});
31 changes: 9 additions & 22 deletions public/javascripts/app/views/movie_table.js
@@ -1,26 +1,26 @@
var MovieTableView = Backbone.View.extend({
// Here we bind our view to the ID in the markup.
el: $("#MovieTableContainer"),
id: "MovieTable",
tagName: "table",
template: $("#TMPMovieTable").html(),

initialize: function(options){
_.bindAll(this,
'render',
'listChanged',
'changeSortAndDirection',
'applyNewSort');

this.collection = new Movies();
this.collection = window.COTM.movies;
this.collection.bind('all', this.render);

//We'll create a property that's also a Backbone Model.
//This way we'll get the events when we change the table's sort.
this.collection.sort_man.bind('change', this.applyNewSort);

return this;
$("#MovieTableContainer").append(this.$el);
},

events: {
"change #MovieList" : "listChanged",
"click th a" : "changeSortAndDirection"
},

Expand All @@ -36,19 +36,12 @@ var MovieTableView = Backbone.View.extend({
this.collection.sort();
},

listChanged: function(e){
this.collection.list = $(e.target).val();
this.collection.fetch();
COTM.logEvent("The Movie List changed. We called for new data from the API");
},

render: function(){
var that = this;
//This resets the contents of the movie table
this.$el.html( $.mustache( this.template ) );
var row_holder = this.make('div');

// Remove all the rows but the header
this.el.find("tr.movie_row").remove();

if( this.collection.isEmpty() ){
$("#MovieTable").hide();
$("#EmptyMessage").show();
Expand All @@ -63,21 +56,15 @@ var MovieTableView = Backbone.View.extend({
// You never want to append nodes to the DOM iteratively.
// It's always best to insert them as one action.
_.each(that.collection.models, function(movie){
//Let's set the comment count on the model silently.
/*movie.set({comment_count: COTM.helper.getCommentCount(movie.id)},*/
/*{silent:true});*/
var row = new MovieTableRowView({model: movie});
$(row_holder).append( $( row.render().el ) );
$(row_holder).append( $( row.render().$el ) );
});
that.el.find("#MovieTable").append( $(row_holder).html() );

that.$el.append( $(row_holder).html() );
}

// Now we'll hide loading image.
$("#LoadingImage").hide();

COTM.navigate("#!list/"+this.collection.list);

return this;
}
});
2 changes: 1 addition & 1 deletion public/main.css
Expand Up @@ -98,7 +98,7 @@ th.title{
width: 147px
}

#WOTY{
#ListType{
font-size:17px;
font-weight: bold;
}
8 changes: 8 additions & 0 deletions test_cotm.rb
Expand Up @@ -2,6 +2,14 @@
require 'capybara'
require 'capybara/dsl'
require 'test/unit'
require 'vcr'
require 'webmock'
require 'webmock/test_unit'

VCR.configure do |c|
c.cassette_library_dir = 'fixtures/vcr_cassettes'
c.hook_into :webmock
end

class TestCOTM < Test::Unit::TestCase
include Capybara::DSL
Expand Down
41 changes: 22 additions & 19 deletions views/index.haml
Expand Up @@ -8,10 +8,14 @@
%link{:href => "http://github.com/necolas/normalize.css", :media => "screen", :rel => "stylesheet"}/
%link{:href => "main.css", :media => "screen", :rel => "stylesheet"}/
%body
%h1
%h1#PageTitle
%a{:href => "/"}Comment on the Movies
#MovieTableContainer
%span#WOTY Movie List Type:
#EmptyMessage{:style => "display:none;"}
While it's possible there are no movies in this list, it's more likely there was an API error.

%script#TMPSearchControls{ :type => "text/x-jquery-tmpl"}
%span#ListType Movie List Type:
%select#MovieList
/ Sinatra doesn't have the same form helpers that Rails does (AFAIK), so I'm putting together by hand here.
/ If I'm wrong, please let me know.
Expand All @@ -21,19 +25,18 @@
%option{:value => 'upcoming'} Upcoming Movies

%img#LoadingImage{:src => '/images/ajax-loader.gif', :alt => 'loading...'}
%table#MovieTable
%tr.header_row
%th.title
%a{:href => '#'} Movie
%th.freshness
%a{:href => '#'} Freshness
%th.opening_day
%a{:href => '#'} Opening Day
%th.comment_count
%a{:href => '#'} # of Comments
#EmptyMessage
While it's possible there are no movies in this list, it's more likely there was an API error.


%script#TMPMovieTable{ :type => "text/x-jquery-tmpl"}
%tr.header_row
%th.title
%a{:href => '#'} Movie
%th.freshness
%a{:href => '#'} Freshness
%th.opening_day
%a{:href => '#'} Opening Day
%th.comment_count
%a{:href => '#'} # of Comments

%script#TMPMovieRows{ :type => "text/x-jquery-tmpl"}
%td
%img.poster_thumbnail{:src => "{{attributes.posters.thumbnail}}", :title => "thumbnail"}
Expand Down Expand Up @@ -75,10 +78,9 @@
/ We're going all CDN crazy with googleapis and cdnjs
/ http://www.cdnjs.com has insane uptime and serves a TON of libraries across Amazon Cloudfront & Route 53 :)
/ Required Libraries
%script{:src => "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"}
%script{:src => "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.2/underscore-min.js"}
%script{:src => "http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js"}
/ %script{:src => "http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"}
%script{:src => "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"}
%script{:src => "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js"}
%script{:src => "http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"}
%script{:src => "/javascripts/req/amplify.min.js"}
%script{:src => "/javascripts/req/jquery.mustache.js"}

Expand All @@ -93,6 +95,7 @@
%script{:src => "javascripts/app/collections/comments.js"}

/ [3] Views
%script{:src => "javascripts/app/views/list_controls.js"}
%script{:src => "javascripts/app/views/movie_table_row.js"}
%script{:src => "javascripts/app/views/movie_table.js"}

Expand Down

0 comments on commit 9c333d9

Please sign in to comment.