From f5609f2182ae6d31d4a1df8c69519635e302ceab Mon Sep 17 00:00:00 2001 From: Dennis Collinson Date: Tue, 20 Dec 2011 21:20:25 -0800 Subject: [PATCH] App views base renders subviews like magic --- app/views/templates/_templates.haml | 3 + app/views/templates/static_text.ujs | 1 + public/javascripts/app/views.js | 35 +++++++++ .../app/views/stream_object_view.js | 22 +----- spec/javascripts/app/views_spec.js | 76 +++++++++++++++++++ spec/javascripts/support/jasmine.yml | 1 + 6 files changed, 117 insertions(+), 21 deletions(-) create mode 100644 app/views/templates/static_text.ujs create mode 100644 public/javascripts/app/views.js create mode 100644 spec/javascripts/app/views_spec.js diff --git a/app/views/templates/_templates.haml b/app/views/templates/_templates.haml index 33292f5ea..506642d37 100644 --- a/app/views/templates/_templates.haml +++ b/app/views/templates/_templates.haml @@ -8,6 +8,9 @@ %script{:id => "feedback-template", :type => 'text/template'} != File.read("#{Rails.root}/app/views/templates/feedback.ujs") +%script{:id => "static-text-template", :type => 'text/template'} + != File.read("#{Rails.root}/app/views/templates/static_text.ujs") + %script{:id => "stream-element-template", :type => 'text/template'} != File.read("#{Rails.root}/app/views/templates/stream_element.ujs") diff --git a/app/views/templates/static_text.ujs b/app/views/templates/static_text.ujs new file mode 100644 index 000000000..41f6ae6d9 --- /dev/null +++ b/app/views/templates/static_text.ujs @@ -0,0 +1 @@ +<%= text %> diff --git a/public/javascripts/app/views.js b/public/javascripts/app/views.js new file mode 100644 index 000000000..06f67bd1c --- /dev/null +++ b/public/javascripts/app/views.js @@ -0,0 +1,35 @@ +App.Views.Base = Backbone.View.extend({ + presenter : function(){ + return this.defaultPresenter() + }, + + defaultPresenter : function(){ + var modelJson = this.model ? this.model.toJSON() : {} + return _.extend(modelJson, App.user()); + }, + + render : function() { + return this.renderTemplate().renderSubviews() + }, + + renderTemplate : function(){ + this.template = _.template($(this.template_name).html()); + var presenter = _.isFunction(this.presenter) ? this.presenter() : this.presenter + $(this.el).html(this.template(presenter)); + this.postRenderTemplate(); + return this; + }, + + postRenderTemplate : $.noop, //hella callbax yo + + renderSubviews : function(){ + var self = this; + _.each(this.subviews, function(property, selector){ + var view = _.isFunction(self[property]) ? self[property]() : self[property] + self.$(selector).html(view.render().el) + view.delegateEvents(); + }) + + return this + } +}) diff --git a/public/javascripts/app/views/stream_object_view.js b/public/javascripts/app/views/stream_object_view.js index 2d1a0575f..016c3246e 100644 --- a/public/javascripts/app/views/stream_object_view.js +++ b/public/javascripts/app/views/stream_object_view.js @@ -1,5 +1,4 @@ -App.Views.StreamObject = Backbone.View.extend({ - +App.Views.StreamObject = App.Views.Base.extend({ className : "loaded", initialize: function(options) { @@ -10,24 +9,5 @@ App.Views.StreamObject = Backbone.View.extend({ destroyModel: function(evt){ if(evt){ evt.preventDefault(); } this.model.destroy(); - }, - - presenter : function(){ - return this.defaultPresenter() - }, - - defaultPresenter : function(){ - var modelJson = this.model ? this.model.toJSON() : {} - return _.extend(modelJson, App.user()); - }, - - render : function() { - return this.renderTemplate() - }, - - renderTemplate : function(){ - this.template = _.template($(this.template_name).html()); - $(this.el).html(this.template(this.presenter())); - return this; } }); diff --git a/spec/javascripts/app/views_spec.js b/spec/javascripts/app/views_spec.js new file mode 100644 index 000000000..0177e65dc --- /dev/null +++ b/spec/javascripts/app/views_spec.js @@ -0,0 +1,76 @@ +describe("App.Views.Base", function(){ + function stubView(text){ + var stubClass = Backbone.View.extend({ + render : function(){ + $(this.el).html(text) + return this + } + }) + + return new stubClass + } + + describe("#render", function(){ + beforeEach(function(){ + var staticTemplateClass = App.Views.Base.extend({ template_name : "#static-text-template" }) + + this.model = new Backbone.Model({text : "model attributes are in the default presenter"}) + this.view = new staticTemplateClass({model: this.model}) + this.view.render() + }) + + it("renders the template with the presenter", function(){ + expect($(this.view.el).text().trim()).toBe("model attributes are in the default presenter") + }) + + it("it evaluates the presenter every render", function(){ + this.model.set({text : "OMG It's a party" }) + this.view.render() + expect($(this.view.el).text().trim()).toBe("OMG It's a party") + }) + + context("subViewRendering", function(){ + beforeEach(function(){ + var viewClass = App.Views.Base.extend({ + template_name : "#static-text-template", + subviews : { + ".subview1": "subview1", + ".subview2": "createSubview2" + }, + + initialize : function(){ + this.subview1 = stubView("OMG First Subview") + }, + + presenter: { + text : "this comes through on the original render" + }, + + postRenderTemplate : function(){ + $(this.el).append("
") + $(this.el).append("
") + console.log($(this.el).html()) + }, + + createSubview2 : function(){ + return stubView("furreal this is the Second Subview") + } + }) + + this.view = new viewClass().render() + }) + + it("repsects the respects the template rendered with the presenter", function(){ + expect(this.view.$('.text').text().trim()).toBe("this comes through on the original render") + }) + + it("renders subviews from views that are properties of the object", function(){ + expect(this.view.$('.subview1').text().trim()).toBe("OMG First Subview") + }) + + it("renders the sub views from functions", function(){ + expect(this.view.$('.subview2').text().trim()).toBe("furreal this is the Second Subview") + }) + }) + }) +}) diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml index 71531e9f8..643513d10 100644 --- a/spec/javascripts/support/jasmine.yml +++ b/spec/javascripts/support/jasmine.yml @@ -38,6 +38,7 @@ src_files: - public/javascripts/app/app.js - public/javascripts/app/router.js + - public/javascripts/app/views.js - public/javascripts/app/models/* - public/javascripts/app/collections/* - public/javascripts/app/views/stream_object_view.js