<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Liquid Media</title>
	<atom:link href="http://liquidmedia.ca/feed/" rel="self" type="application/rss+xml" />
	<link>http://liquidmedia.ca</link>
	<description>Custom Software-as-a-Service Application Development</description>
	<lastBuildDate>Thu, 26 Jan 2012 15:09:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>We&#8217;re moving on October 1</title>
		<link>http://liquidmedia.ca/news/2011/09/were-moving-on-october-1/</link>
		<comments>http://liquidmedia.ca/news/2011/09/were-moving-on-october-1/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 18:38:11 +0000</pubDate>
		<dc:creator>pauldoerwald</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=755</guid>
		<description><![CDATA[Our new address is: 400-1668 Barrington St. Halifax NS B3J 2A2 Come visit us!]]></description>
			<content:encoded><![CDATA[<p>Our new address is:</p>
<address>
400-1668 Barrington St.<br/><br />
Halifax NS<br/><br />
B3J 2A2<br/><br />
</address>
<p>Come visit us!</p>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/news/2011/09/were-moving-on-october-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Custom user delete in Devise</title>
		<link>http://liquidmedia.ca/blog/2011/08/custom-user-delete-in-devise/</link>
		<comments>http://liquidmedia.ca/blog/2011/08/custom-user-delete-in-devise/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 14:26:38 +0000</pubDate>
		<dc:creator>pauldoerwald</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=751</guid>
		<description><![CDATA[Devise&#8216;s default behaviour to delete a user is to actually delete them from the database. This isn&#8217;t the right approach for every site; in my case, I prefer to hang on to users in perpetuity and simply mark their record as deleted. The steps are simple. Create a migration: def up add_column :users, :deleted_at, :timestamp [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/plataformatec/devise">Devise</a>&#8216;s default behaviour to delete a user is to actually delete them from the database. This isn&#8217;t the right approach for every site; in my case, I prefer to hang on to users in perpetuity and simply mark their record as deleted. The steps are simple.</p>
<p>Create a migration:</p>
<pre>
  def up
    add_column :users, :deleted_at, :timestamp
  end
</pre>
<p>When deleted_at gets a value, we&#8217;ll consider the record deleted. Otherwise, it is active. Now we need to change the log in behaviour to check if the user has been deleted or not. Devise provides the <code>valid_for_authentication?</code> method, which you can override as I did below:</p>
<pre>
  def valid_for_authentication?
    result = super
    self.deleted_at.present? ? false : result
  end
</pre>
<p>This method first checks whatever &#8216;super&#8217; has to say about the user&#8217;s eligibility to log in, and then checks whether the deleted_at value has been set. If it has, the user is not allowed to log in (returning false). If it has not, then whatever the value for result is is used.</p>
<p>Finally, you&#8217;ll want a scope for active users:</p>
<pre>
scope :active, where(:deleted_at => nil, :confirmation_token => nil)
</pre>
<p>If you&#8217;re using <code>devise_invitable</code> you&#8217;ll also want to include <code>:invitation_token => nil</code>, or any other rules for what defines an active user.</p>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/blog/2011/08/custom-user-delete-in-devise/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An Intro to Backbone.js: Part 3 &#8211; Binding a Collection to a View</title>
		<link>http://liquidmedia.ca/blog/2011/02/backbone-js-part-3/</link>
		<comments>http://liquidmedia.ca/blog/2011/02/backbone-js-part-3/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 13:28:10 +0000</pubDate>
		<dc:creator>n_time</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=582</guid>
		<description><![CDATA[This is Part 3 of a series of tutorials. Here&#8217;s Part 1 and Part 2. So we&#8217;ve covered models, collections, controllers, and the basic case of tying a view to a model&#8217;s callbacks. Now we&#8217;re going to cover tying a view to a collection. This gets a little hairy, so I&#8217;m going to keep it [...]]]></description>
			<content:encoded><![CDATA[<div class="notice" style="padding: 20px; margin-bottom: 20px; color: #000; background-color: #EBEBEB; border-radius: 5px; -moz-border-radius: 5px;"> This is Part 3 of a series of tutorials. Here&#8217;s <a href="http://liquidmedia.ca/blog/2011/01/backbone-js-part-1">Part 1</a> and <a href="http://liquidmedia.ca/blog/2011/01/an-intro-to-backbone-js-part-2-controllers-and-views/">Part 2</a>.</div>
<p>So we&#8217;ve covered models, collections, controllers, and the basic case of tying a view to a model&#8217;s callbacks.</p>
<p>Now we&#8217;re going to cover tying a view to a collection. This gets a little hairy, so I&#8217;m going to keep it nice and simple to start.</p>
<p>Note: As with most things, there are large number of ways you could do this. If you feel that you have a better way, feel free to reply with it as a comment.</p>
<h2>A Basic Collection View</h2>
<p>Let&#8217;s say that we have an existing page that looks like this:</p>
<pre class="brush: xml">
&lt;header&gt; OMG Donut Shop &lt;/header&gt;

&lt;section&gt;
  &lt;header&gt;Donut Selection&lt;/header&gt;
  &lt;ul class=donuts&gt;&lt;/ul&gt;
&lt;/section&gt;
</pre>
<p>I&#8217;m going to define a DonutCollectionView that will, when given a collection of donuts, render an UpdatingDonutView for each donut.</p>
<p>This is a pattern I use fairly often. A View that is composed of other views. In this way you can easily reuse functionality between Views.</p>
<pre class="brush: js">
var DonutCollectionView = Backbone.View.extend({
  initialize : function() {
    var that = this;
    this._donutViews = [];

    this.collection.each(function(donut) {
      that._donutViews.push(new UpdatingDonutView({
        model : donut,
        tagName : 'li'
      }));
    });
  },

  render : function() {
    var that = this;
    // Clear out this element.
    $(this.el).empty();

    // Render each sub-view and append it to the parent view's element.
    _(this._donutViews).each(function(dv) {
      $(that.el).append(dv.render().el);
    });
  }
});
</pre>
<h4>Initialize</h4>
<p>I didn&#8217;t go into much detail about this before. Backbone&#8217;s View, Model, and Collection all have their own constructors (which you don&#8217;t override*) that take care of initializing a number of functionalities, and the &#8220;initialize&#8221; method is run inside of their constructors.</p>
<p>*You could, but you&#8217;d better have a good reason.</p>
<h3>Creating and Rendering</h3>
<p>So let&#8217;s say I create a Backbone.Collection of donuts.</p>
<pre class="brush: js">
var donuts = new Donuts([
  {"name" : "Boston Cream"},
  {"name" : "Lemon-Filled"},
  {"name" : "Rusty Iron Shavings"}
]);
</pre>
<p>I can then create a View with those Donuts.</p>
<pre class="brush: js">
var donutCollectionView = new DonutCollectionView({
  collection : donuts,
  el : $('ul.donuts')[0]
});

donutCollectionView.render();
</pre>
<p>This will render each of the donuts into the View and append them to the ul that I created earlier. Which will end up looking like this:</p>
<pre class="brush: xml">
&lt;header&gt; OMG Donut Shop &lt;header&gt;

&lt;section&gt;
  &lt;header&gt; Donut Selection &lt;header&gt;
  &lt;ul class="donuts"&gt;
	&lt;li&gt; Boston Cream &lt;/li&gt;
	&lt;li&gt; Lemon-Filled &lt;/li&gt;
	&lt;li&gt; Rusty Iron Shavings &lt;/li&gt;
  &lt;/ul&gt;
&lt;/section&gt;
</pre>
<p>So by virtue of using our UpdatingDonutView, the individual donuts will register changes and rerender.</p>
<p>But adding or removing an item from the collection won&#8217;t be reflected. Let&#8217;s alter the above DonutCollectionView and hook it into the Collection&#8217;s events.</p>
<p>As a reminder, the collection will trigger &#8220;add&#8221; events each time a model is added to it, and a &#8220;remove&#8221; event each time a model is removed.</p>
<p>So what would binding the view above to the collection&#8217;s events look like?</p>
<pre class="brush: js">
var DonutCollectionView = Backbone.View.extend({
  initialize : function() {
    // bind the functions 'add' and 'remove' to the view.
    _(this).bindAll('add', 'remove');

    // create an array of donut views to keep track of children
    this._donutViews = [];

    // add each donut to the view
    this.collection.each(this.add);

    // bind this view to the add and remove events of the collection!
    this.collection.bind('add', this.add);
    this.collection.bind('remove', this.remove);
  },

  add : function(donut) {
    // We create an updating donut view for each donut that is added.
    var dv = new UpdatingDonutView({
      tagName : 'li',
      model : donut
    });

    // And add it to the collection so that it's easy to reuse.
    this._donutViews.push(dv);

    // If the view has been rendered, then
    // we immediately append the rendered donut.
    if (this._rendered) {
      $(this.el).append(dv.render().el);
    }
  },

  remove : function(model) {
    var viewToRemove = _(this._donutViews).select(function(cv) { return cv.model === model; })[0];
    this._donutViews = _(this._donutViews).without(viewToRemove);

    if (this._rendered) $(viewToRemove.el).remove();
  },

  render : function() {
    // We keep track of the rendered state of the view
    this._rendered = true;

    $(this.el).empty();

    // Render each Donut View and append them.
    _(this._donutViews).each(function(dv) {
      this.$('ul.donuts').append(dv.render().el);
    });

    return this;
  }
});
</pre>
<p>The use of this DonutCollectionView is identical to the one above, but now it&#8217;s adding and removing properly.</p>
<h2>Building a Generic UpdatingCollectionView</h2>
<p>Alright, so that&#8217;s a lot of code to get an updating collection view for donuts. Maybe not the awesomest thing ever. But does it really need to be tightly coupled to Donuts or DonutViews? Let&#8217;s decouple this jerk and make a generic updating view that we can use like this.</p>
<pre class="brush: js">
var donutCollectionView = new UpdatingCollectionView({
  collection           : donuts,
  childViewConstructor : UpdatingDonutView,
  childViewTagName     : 'li',
  el                   : $('#donut_list')[0]
});</pre>
<p>And here&#8217;s the implementation of that&#8230;</p>
<pre class="brush: js">
var UpdatingCollectionView = Backbone.View.extend({
  initialize : function(options) {
    _(this).bindAll('add', 'remove');

    if (!options.childViewConstructor) throw "no child view constructor provided";
    if (!options.childViewTagName) throw "no child view tag name provided";

    this._childViewConstructor = options.childViewConstructor;
    this._childViewTagName = options.childViewTagName;

    this._childViews = [];

    this.collection.each(this.add);

    this.collection.bind('add', this.add);
    this.collection.bind('remove', this.remove);
  },

  add : function(model) {
    var childView = new this._childViewConstructor({
      tagName : this._childViewTagName,
      model : model
    });

    this._childViews.push(childView);

    if (this._rendered) {
      $(this.el).append(childView.render().el);
    }
  },

  remove : function(model) {
    var viewToRemove = _(this._childViews).select(function(cv) { return cv.model === model; })[0];
    this._childViews = _(this._childViews).without(viewToRemove);

    if (this._rendered) $(viewToRemove.el).remove();
  },

  render : function() {
    var that = this;
    this._rendered = true;

    $(this.el).empty();

    _(this._childViews).each(function(childView) {
      $(that.el).append(childView.render().el);
    });

    return this;
  }
});
</pre>
<h3>Using the UpdatingCollectionView</h3>
<p>So, now that we&#8217;ve made a generic updating collection view, let&#8217;s go through a potential use case of it!<br />
Let&#8217;s say that we&#8217;re building a view for a DonutShop.</p>
<p>I&#8217;m starting to get nice and opinionated now and I&#8217;m going to bring in <a href="http://api.jquery.com/jQuery.template/">jQuery template</a><br />
Here&#8217;s a template for a DonutShop</p>
<pre class="brush: xml">
&lt;script id="tmpl-donut_shop" type="template/jquery"&gt;
  &lt;header&gt;{{name}}&lt;/header&gt;

  &lt;section&gt;
    &lt;header&gt;Donuts offered:&lt;/header&gt;
    &lt;ul class=donuts&gt;&lt;/ul&gt;
  &lt;/section&gt;
&lt;/script&gt;
</pre>
<p>And now I&#8217;ll declare a view that uses that template.</p>
<pre class="brush: js">
var DonutShopView = Backbone.View.extend({
  templateId : 'donut_shop',
  initialize : function() {

    // Don't worry about this syntax too much.
    // Basically all that this template bit does is grab a template from jQuery
    // I'll have taken care of compiling the template somewhere earlier.
    this.template =  $.template(this.templateId);
    this._donutCollectionView = new UpdatingCollectionView({
      collection           : this.model.donuts,
      childViewConstructor : UpdatingDonutView,
      childViewTagName     : 'li'
    });
  },

  render : function() {
    $(this.el).empty();

    // And here I use the template to render this object,
    // then take the rendered template
    // and append it to this view's element.
    $.tmpl(this.template, this.model.toJSON()).appendTo(this.el);

    this._donutCollectionView.el = this.$('.donuts');
    this._donutCollectionView.render();
  }
});

var donutShopView = new DonutShopView({ model : donutShop });
</pre>
<p>So now we&#8217;ve got a donut shop view, which contains an autoupdating collection view, which contains autoupdating model views.</p>
<p>Everything stays in sync.</p>
<p>And everyone is happy.</p>
<p>Next, I will be going over declaratively binding events to views, which is a pretty great thing.</p>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/blog/2011/02/backbone-js-part-3/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Next hacks@ on Saturday 26 February at 4:30 p.m.</title>
		<link>http://liquidmedia.ca/news/2011/02/hacksat-26-feb/</link>
		<comments>http://liquidmedia.ca/news/2011/02/hacksat-26-feb/#comments</comments>
		<pubDate>Mon, 14 Feb 2011 16:21:24 +0000</pubDate>
		<dc:creator>pauldoerwald</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=655</guid>
		<description><![CDATA[The next hacks@ is on 26 February at 4:30 p.m. Read more and sign up.]]></description>
			<content:encoded><![CDATA[<p>The next hacks@ is on 26 February at 4:30 p.m. <a href="/hacksat/">Read more and sign up.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/news/2011/02/hacksat-26-feb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript talk at PodCamp Halifax 2011</title>
		<link>http://liquidmedia.ca/blog/2011/01/javascript-talk-at-podcamp-halifax-2011/</link>
		<comments>http://liquidmedia.ca/blog/2011/01/javascript-talk-at-podcamp-halifax-2011/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 16:40:52 +0000</pubDate>
		<dc:creator>pauldoerwald</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=505</guid>
		<description><![CDATA[I had the opportunity to speak at PodCamp Halifax 2011 this past Sunday January 23 on the topic “JavaScript &#038; jQuery – What it is, How to use it, and Why it’s the future of the web”. Given the predominantly social media audience of the conference, I kept the talk fairly low-tech, breaking the talk [...]]]></description>
			<content:encoded><![CDATA[<p>I had the opportunity to speak at <a href="http://www.podcamphalifax.ca/">PodCamp Halifax 2011</a> this past Sunday January 23 on the topic “JavaScript &#038; jQuery – What it is, How to use it, and Why it’s the future of the web”. Given the predominantly social media audience of the conference, I kept the talk fairly low-tech, breaking the talk into 3 parts:</p>
<ul>
<li>A history of JavaScript and jQuery
<ul>
<li>Where JavaScript started.</li>
<li>Why we hated it (popups! popunders! marquees! dropdown navigation that didn’t work!)</li>
<li>Why developers looked down their noses at JS for years.</li>
<li>The introduction of Ajax and how it changed the web world, being the technological start of Web 2.0, as well as making the Internet a whole lot faster.</li>
<li>JavaScript frameworks, and why jQuery rose to the top to back over 41% of the top 10,000 web sites.</li>
</ul>
<li>A demo of jQuery — I had created a simple blog-like page and then used jQuery to manipulate DOM elements and add events various elements, including a form.
<li>A discussion of why I believe JavaScript is the future of the web — This is the subject of a future blog post, but a few of my bullet points are:
<ul>
<li>JavaScript is amazingly fast and it&#8217;s only getting faster.</li>
<li>JS is available on almost every modern Internet-connected device, and usually with a pretty respectable interpreter.</li>
<li>With recent improvements in browsers, the age of the fat client distributed over the Internet is finally here.</li>
<li>Fat client JS in the browser allows for a really light-weight server, meaning we have a new paradigm of scalability available to us.</li>
</ul>
</ul>
<p>The audience for my talk ended up being about 80% techies and 20% noobs, so I could have probably stepped up the technical complexity a bit to hit the majority a little better. Still the talk was well received and I had the opportunity to meet a number of Halifax-based developers I hadn’t met before. The conference photographer managed to <a href="http://mddesign.zenfolio.com/p368092516/h2a349e49#h2a349e49">snap a photo of me</a> while I gave the talk.</p>
<p><b>Update:</b> <a href="http://www.videojournalist.ca/author/glen-canning/">Glen Canning</a> from <a href="http://videojournalist.ca">videojournalist.ca</a> wrote a really nice <a href="http://www.videojournalist.ca/2011/01/27/podcamp-2011/">review of my talk</a>.</p>
<blockquote><p>That completed the first session. A quick iPad draw, didn’t win, and on to the next session. This one was titled JavaScript &#038; jQuery – What it is, How to use it, and Why it’s the future of the web and it was presented by <a href="http://pauldoerwald.ca">Paul Doerwald</a>. Paul is is Chancellor of <a href="http://liquidmedia.ca">Liquid Media</a>, a boutique web software development shop located in downtown Halifax, Nova Scotia. He and his team develop cutting-edge web applications, built primarily using <a href="http://ruby-lang.org">Ruby</a> and <a href="http://rubyonrails.org">Ruby on Rails</a> framework. I don’t even know what that means. Anyway, I took this session because I want to add more jQuery features to videojournalist.ca. Everyone there seemed to have some web development skills. For me that means Flash, html, php, perl, and a little javascript. For other it meant a great deal more but Paul spoke in a way that allowed his information to be on level with most of us. Thankfully!  So JavaScript is getting huge geek love. All the cool apps are java apps – like <a href="http://twitter.com">Twitter</a> and <a href="http://jquery.com">jQuery</a> is the Standard Library for the web (<a href="http://twitter.com/wycats">@wycats</a>). Paul spoke about Java history, problems, and solutions and explained why jQuery the winner? He even gave samples and coded for us. Loved this presentation and got out of it what I had hoped which was more information on the uses of jQuery.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/blog/2011/01/javascript-talk-at-podcamp-halifax-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Intro to Backbone.js: Part 2 &#8211; Controllers and Views</title>
		<link>http://liquidmedia.ca/blog/2011/01/an-intro-to-backbone-js-part-2-controllers-and-views/</link>
		<comments>http://liquidmedia.ca/blog/2011/01/an-intro-to-backbone-js-part-2-controllers-and-views/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 15:37:18 +0000</pubDate>
		<dc:creator>n_time</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[backbone]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[backbonejs]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=204</guid>
		<description><![CDATA[This is Part 2 of a series of tutorials. You can find Part 1 here. We&#8217;re good with Backbone.Model. We&#8217;re good with Backbone.Collection. We&#8217;re good with Backbone.Events. So: Backbone.Controller: If you&#8217;re coming from Rails land, you&#8217;ll be pretty familiar with this guy, although it&#8217;s got a pretty neat twist. You get to write your routes [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://documentcloud.github.com/backbone"><img class="alignnone size-full wp-image-352" title="backbone-logo" src="http://liquidmedia.ca/wp-content/uploads/2011/01/backbone-logo.png" alt="" width="385" height="126" /></a></p>
<div class="notice" style="padding: 20px; margin-bottom: 20px; color: #000; background-color: #EBEBEB; border-radius: 5px; -moz-border-radius: 5px;"> This is Part 2 of a series of tutorials. You can find <a href="http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/">Part 1 here</a>.</div>
<p>We&#8217;re good with Backbone.Model. We&#8217;re good with Backbone.Collection. We&#8217;re good with Backbone.Events. So:</p>
<h3>Backbone.Controller:</h3>
<p>If you&#8217;re coming from Rails land, you&#8217;ll be pretty familiar with this guy, although it&#8217;s got a pretty neat twist. You get to write your routes right in the controller. This is very, very nice to work with.</p>
<pre class="brush: js">
var MyController = Backbone.Controller.extend({
  routes : {
    "say/:something" : "say"
  },

  say : function(something) {
    alert(something);
  }
});

var yC = new MyController;

Backbone.history.start();
</pre>
<p>This is pretty straightforward. I defined a prototype and constructor for MyController, complete with one route and the property name, as a string, of the function in this Controller that you want it it to call  (analogous to an action in Rails).</p>
<p>Backbone.history is where Backbone stores all of the places you&#8217;ve been. This is necessary in order to not break the back button in your browser.</p>
<p>When I called the constructor, MyController gave all of its&#8217; routes to Backbone.history, along with their relevant callbacks.</p>
<p>Next, when I called Backbone.history.start(), Backbone subscribed to the browser&#8217;s hashchange event*. Whenever the hash changes, Backbone.history takes care of running your Controller&#8217;s function.</p>
<p><span style="font-size: 9px;">*If the browser supports it. Otherwise, it starts monitoring the window.location for hashchanges periodically.</span></p>
<p>Now if I navigate to &#8220;<em>http://myapp.root/#say/hello_world</em>&#8221; &#8230; I get a butt ugly alert with &#8220;hello_world&#8221; in it.</p>
<h2>Backbone.Views:</h2>
<p>Views are designed to encapsulate a DOM element&#8217;s functionality. It exists between a Model/Collection and the DOM.</p>
<p>The View has the following responsibilities:</p>
<ul>
<li>rendering the DOM element</li>
<li>initializing DOM events for user interactions within the element</li>
<li>subscribing to events that are relevant to the DOM element and updating it appropriately, such as:
<ul>
<li>When a Model changes.</li>
<li>When a Collection changes.</li>
<li>When a specific event occurs elsewhere on the page (navigation, etc, etc).</li>
</ul>
</li>
</ul>
<p>While this is the general idea of the View, you are perfectly free to do whatever else you&#8217;d like with it. Backbone also doesn&#8217;t provide any implementation of these details, other than the triggering/binding of Events, so you&#8217;re free to implement what you&#8217;d like with the framework(s) of your choosing.</p>
<h3>Creating a View Prototype</h3>
<p>Let&#8217;s cut to the chase and make one!</p>
<pre class="brush: js">
DonutView = Backbone.View.extend({
  tagName : "div",
  className : "donut",

  render : function() {
    this.el.innerHTML = this.model.get('name');

    return this;
  }
});
</pre>
<p>I&#8217;ve overriden three values in my new prototype. The first two are fairly self-explanatory. When you create the donut view, it will create a div element with the class &#8220;donut&#8221;.</p>
<p>The last &#8212; &#8220;render&#8221; &#8212; is the core function of the Backbone.View. The View itself will create an element, but &#8220;render&#8221; is where you tell your view how to render itself. Backbone has no opinion on how you do this, so feel free to experiment with one of the <a href="https://github.com/janl/mustache.js">dozens</a> of <a href="http://api.jquery.com/jQuery.template/">JavaScript</a> template formats that have crept up. (<a href="http://jsperf.com/dom-vs-innerhtml-based-templating/63">Here&#8217;s a cool performance comparison</a>). In this case I set the innerHTML of the element to the content I desire. Pretty straightforward.</p>
<pre class="brush: js">
var bcDonut = new Donut({
  name : "Boston Cream"
});

var bcDonutView = new DonutView({
  model : bcDonut
});

var renderedDonutElement = bcDonutView.render().el;
</pre>
<h3>Binding a View to a Model&#8217;s Changes</h3>
<p>This is a little bit of overhead for just rendering a model&#8217;s name. but this extra layer of abstractions gets us a lot. For instance, what if you want to automatically update the view whenever the model changes?</p>
<pre class="brush: js">
var UpdatingDonutView = DonutView.extend({
  initialize : function(options) {
    this.render = _.bind(this.render, this); 

    this.model.bind('change:name', this.render);
  }
});
</pre>
<p>Whoa. Did I blow your mind? First thing we inherited the prototype of DonutView, and overrode its&#8217; &#8220;initialize&#8221; property with our own function.</p>
<p>Inside initialize we bind this.render to our instance of UpdatingDonutView. The Underscore method &#8216;bind&#8217; makes sure that when we call &#8220;this&#8221; in  &#8221;render&#8221; it will always reference this UpdatingDonutView instance.</p>
<p>Then we bind to the model&#8217;s &#8220;change:name&#8221; event with &#8220;render&#8221;  as the callback function. It&#8217;ll now re-render this view when the name changes. Cool!</p>
<pre class="brush: js">
var uDonutView = new UpdatingDonutView({
  model : bcDonut
});

var renderedDonutElement = uDonutView.render().el;
</pre>
<p>Now, if we change the name:</p>
<pre class="brush: js">
uDonutView.model.set({name : "Lemon-Filled"});
</pre>
<p>The element reflects the name change!</p>
<pre class="brush: js">
renderedDonutElement.innerHTML;
-&gt; "Lemon-Filled"
</pre>
<p>That took a little longer than I&#8217;d expected to go over, so we&#8217;re going to save collection binding for the next post!</p>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/blog/2011/01/an-intro-to-backbone-js-part-2-controllers-and-views/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>New design coming soon</title>
		<link>http://liquidmedia.ca/blog/2011/01/new-design-coming-soon/</link>
		<comments>http://liquidmedia.ca/blog/2011/01/new-design-coming-soon/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 15:01:18 +0000</pubDate>
		<dc:creator>pauldoerwald</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=427</guid>
		<description><![CDATA[We’ve finally decided on a new design for our site, rather than this purchased (but still cool!) template. Here&#8217;s a glimpse of what our site will look like:]]></description>
			<content:encoded><![CDATA[<p>We’ve finally decided on a new design for our site, rather than this purchased (but still cool!) template. Here&#8217;s a glimpse of what our site will look like:</p>
<p><img src="http://liquidmedia.ca/wp-content/uploads/2011/01/LM-web-home-C4-D2-b-1-e1296054019855.jpeg"></p>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/blog/2011/01/new-design-coming-soon/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An Intro to Backbone.js: Part 1 &#8211; Models and Collections</title>
		<link>http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/</link>
		<comments>http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/#comments</comments>
		<pubDate>Mon, 24 Jan 2011 21:11:38 +0000</pubDate>
		<dc:creator>n_time</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[backbonejs]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://liquidmedia.ca/?p=118</guid>
		<description><![CDATA[This is Part 1 of a series of tutorials. You can find Part 2 here. JavaScript interpreters are FAST, and they&#8217;re in every browser out there. You can run a rich application in the browser using only open technologies and built in browser-functionality, today. Backbone.js can help build it. It&#8217;s a light-weight MVC for the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://documentcloud.github.com/backbone/"><img src="http://liquidmedia.ca/wp-content/uploads/2011/01/backbone-logo.png" alt="" title="backbone-logo" width="385" height="126" class="alignnone size-full wp-image-352" /></a></p>
<div class="notice" style="padding: 20px; margin-bottom: 20px; color: #000; background-color: #EBEBEB; border-radius: 5px; -moz-border-radius: 5px;">This is Part 1 of a series of tutorials. You can find <a href="http://liquidmedia.ca/blog/2011/01/an-intro-to-backbone-js-part-2-controllers-and-views/">Part 2 here</a>.</div>
<p>JavaScript interpreters are FAST, and they&#8217;re in every browser out there. You can run a rich application in the browser using only open technologies and built in browser-functionality, today.</p>
<p><strong><a href="http://documentcloud.github.com/backbone/">Backbone.js</a></strong> can help build it. It&#8217;s a light-weight MVC for the browser &#8211; only <a href="http://documentcloud.github.com/backbone/docs/backbone.html">~1000 lines of code</a>, and it&#8217;s <strong>clean</strong>. </p>
<p>There&#8217;s no magic. It&#8217;s mostly just a structure for the code you write &#8211; not a bulky collection of widgets and doodads. It&#8217;s fast to learn, and lets you work with whatever technologies you&#8217;re already comfortable with.</p>
<h2>Trying Out Backbone</h2>
<p>If you&#8217;re looking to try it out, you&#8217;re going to need to load <a href="http://documentcloud.github.com/underscore/">Underscore.js</a> first. It&#8217;s Backbone&#8217;s only major dependency.</p>
<p>Oh yeah, and Backbone does not have anything to do with the DOM, although it does have some loose dependencies on the $ and ajax calls of jQuery/Zepto. If you aren&#8217;t using jQuery or Zepto then you&#8217;ll need to do a little more work (<em>like 10 lines of code</em>). I&#8217;ll go over the particulars in the next post. For now, play nice and just use jQuery or Zepto if you feel like following along.</p>
<h2>What&#8217;s going on in there?</h2>
<p>There are five main prototypes in Backbone.</p>
<ul>
<li>Backbone.Collection &#8211; A little more than what you&#8217;re thinking.</li>
<li>Backbone.Model &#8211; ActiveRecord implementation, but it&#8217;s got a url!</li>
<li>Backbone.Controller &#8211; More or less exactly what you&#8217;re thinking.</li>
<li>Backbone.View &#8211; If you&#8217;re from Rails, then it&#8217;s not what you&#8217;re thinking.</li>
<li>Backbone.Events &#8211; Inherit from this guy to give your objects PubSub!</li>
</ul>
<p>In this blog post we&#8217;re going to look at <strong>Models, Collections, and Events.</strong></p>
<h3>Backbone.Model:</h3>
<p>An implementation of the ActiveRecord pattern, but using JSON and a RESTful API instead of directly interfacing with a database.</p>
<p>So let&#8217;s say that we&#8217;re working on a donut app, and we want to be able to describe our donuts!</p>
<pre class="brush: js">  // We extend the Backbone.Model prototype to build our own
  var Donut = Backbone.Model.extend({

    // We can pass it default values.
    defaults : {
      name : null,
      sparkles : false,
      cream_filled : false
    },

    url : function() {
      // Important! It's got to know where to send its REST calls.
      // In this case, POST to '/donuts' and PUT to '/donuts/:id'
      return this.id ? '/donuts/' + this.id : '/donuts';
    } 

  });
</pre>
<p>That&#8217;s analogous to defining a model class in Rails. Now let&#8217;s put it through it&#8217;s paces a little.</p>
<pre class="brush: js">
// Instantiating
  var bostonCream = new Donut({ // attributes passed to the Donut constructor will override the defaults
    name : "Bostan Cream",
    cream_filled : true
  });

  // Updating and retrieving attributes
  // Actually, let's put sprinkles on that...
  bostonCream.set({ sprinkles : true }); 

  // Saving
  bostonCream.save(); // this will now POST to the RESTful interface.
</pre>
<p>Backbone.Model#save is an asynchronous method. So you&#8217;ll need to provide a callback. The following code assumes success.</p>
<pre class="brush: js">
  // Now that it's saved it'll have an id..
  bostonCream.id;
  -&gt; 3, or whatever number your JSON api passed up.

  // Wait, what's the name?
  bostonCream.get("name");
  -&gt; "Bostan Cream"

  // Ugh, sprinkles are gross. And there's a typo in the name.
  bostonCream.set({
    sprinkles : false,
    name : "Boston Cream"
  });

  // Updating
  bostonCream.save(); // and now it's a PUT.
  // it will put directly to "donuts/3", since that's the URI
  // of the model now.
</pre>
<h3>Backbone.Collection:</h3>
<p>A collection of models, duh. It&#8217;s a little smarter than that. It proxies to Underscore to give you a bunch of sweet list functions for working your data out, and lets you keep an eye on what your models are up to through a bunch of handy events. Plus, if you have a RESTful API you can tie them directly to a collection on your backend. Cool, right?</p>
<p>So let&#8217;s work out this donut example a little. If you want to manage a collection of donuts, we can use the same API we were working with earlier&#8230;</p>
<pre class="brush: js">  var Donuts = Backbone.Collection.extend({
    model : Donut,
    url : "/donuts"
  });

  var donuts = new Donuts;

  donuts.fetch(); // this makes a call to the server and populates the collection based on the response.</code></pre>
<p>The call to collection#fetch is asynchronous, so let&#8217;s assume this code is being run after the call is complete.</p>
<pre class="brush: js">
  donuts.at(0); -&gt; gets donuts by index.
  donuts.get(0); -&gt; gets donuts by id.
</pre>
<p>And a few examples of the Underscore iterator methods&#8230;</p>
<pre class="brush: js">
  donuts.each(function(donut) {
    console.log(donut.get("name"));
  });

  // Select donuts with names longer than 2
  donuts.select(function(donut) {
    return donut.get("name").length &gt; 2;
  });

  // Map...
  donuts.map(function(donut) {
    return donut.get("name");
  });
</pre>
<h4>Nested Collections</h4>
<p>One of the most common uses for collections is to make them nested. In this case, let&#8217;s introduce another model, the &#8220;Donut Shop&#8221; and let&#8217;s say that it has a list of Donuts that it serves.</p>
<pre class="brush: js">
  var DonutShop = Backbone.Model.extend({
    defaults : {
      name : "Untitled"
    },

    initialize : function() {
      // When you extend a Backbone.Model and give it an initialize function,
      // the function is called when you instantiate an instance of your Model.

      // The initialize function is used repeatedly in Backbone's prototypes. We'll be seeing this again
      this.donuts = new Donuts;
      this.donuts.url = 'donut_shops/' + this.id + "/donuts";
    }
  });
</pre>
<p>So now if you have an existing donut shop that has been saved to the server, you can go:</p>
<pre class="brush: js">
  donutShop.donuts.fetch();
</pre>
<h3>Backbone.Events:</h3>
<p>All of the Backbone core objects give you events to plug in to. For instance, the Collection prototype allows you to bind to &#8220;add&#8221; and &#8220;remove&#8221; events.</p>
<pre class="brush: js">
  donutShop.donuts.bind("add", function(donut) {
    alert("added " + donut.get("name"));
  });

  // now adding a donut will trigger the alert
  var lemonFilled = donutShop.donuts.add({ name : "Lemon Filled" });
</pre>
<p>Backbone provides you with the Backbone.Events object as well. So, since Underscore is a prereq of Backbone anyway, you can do fancy nonsense like this&#8230;</p>
<pre class="brush: js">var application = {};
_(application).extend(Backbone.Events);

// Now your application object has it's own events! For example.

application.bind("fun:had", function() { alert("wee!"); });
application.trigger("fun:had"); // it'll alert "wee!"
</pre>
<p>There&#8217;s part 1. Next time I&#8217;ll take you through some fun parts:</p>
<ul>
<li> Navigating using Backbone.Controllers</li>
<li>HashChange routing!</li>
<li>Creating a view</li>
<li>Tying a view to model events</li>
<li>Tying a view to a collection&#8217;s events.</li>
</ul>
<p>If you&#8217;re looking to try out Backbone, which I&#8217;m guessing you are, here are the relevant links.</p>
<ul>
<li><a href="http://documentcloud.github.com/underscore/">Underscore.js</a>.
<li><a href="http://documentcloud.github.com/backbone/">Backbone.js</a>.</li>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
	</channel>
</rss>

