<?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>Life As An Evangelist &#187; Christophe Coenraets</title>
	<atom:link href="http://lifeasanevangelist.com/author/christophe-coenraets/feed/" rel="self" type="application/rss+xml" />
	<link>http://lifeasanevangelist.com</link>
	<description>Keep up to date with Adobe's Platform Evangelists</description>
	<lastBuildDate>Wed, 08 Feb 2012 05:13:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Sample Mobile App with Backbone.js, PhoneGap, and a Local Database</title>
		<link>http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-phonegap-and-a-local-database/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-mobile-app-with-backbone-js-phonegap-and-a-local-database</link>
		<comments>http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-phonegap-and-a-local-database/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-mobile-app-with-backbone-js-phonegap-and-a-local-database#comments</comments>
		<pubDate>Tue, 07 Feb 2012 16:29:39 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=3044</guid>
		<description><![CDATA[In my previous post, I shared a simple Wine Cellar application built with Backbone.js and packaged as a mobile app with PhoneGap. That version of the application gets its data from a set of RESTful services, which means that you can only use it while online. In this post, we explore an offline version of [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Sample%20Mobile%20App%20with%20Backbone.js,%20PhoneGap,%20and%20a%20Local%20Database%20http://coenraets.org/blog/?p=3044" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-phonegap-and-a-local-database/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-and-phonegap/">previous post</a>, I shared a simple Wine Cellar application built with <a href="http://documentcloud.github.com/backbone/">Backbone.js</a> and packaged as a mobile app with <a href="http://phonegap.com/">PhoneGap</a>. That version of the application gets its data from a set of RESTful services, which means that you can only use it while online.</p>
<p>In this post, we explore an offline version of the same application: this new version gets its data from your device&#8217;s local database using the PhoneGap SQL database API. </p>
<p>By default, Backbone.js Models access their data using RESTful services defined by the Models &#8220;url&#8221; and &#8220;urlRoot&#8221; attributes. But Backbone.js also makes it easy and elegant to change your Models data access mechanism: All you have to do is override the Backbone.sync method. From the Backbone.js <a href="http://documentcloud.github.com/backbone/#Sync">documentation</a>:</p>
<blockquote><p>Backbone.sync is the function that Backbone calls every time it attempts to read or save a model to the server. By default, it uses (jQuery/Zepto).ajax to make a RESTful JSON request. You can override it in order to use a different persistence strategy, such as WebSockets, XML transport, or Local Storage.</p></blockquote>
<p>The documentation includes a <a href="http://documentcloud.github.com/backbone/docs/backbone-localstorage.html">useful example</a> that shows how to replace the default Backbone.sync implementation with localStorage-based persistence where models are saved into JSON objects.  </p>
<p>In our application, we will replace the default Backbone.sync implementation with SQL-based persistence using the device&#8217;s local database.<br />
<span id="more-3044"></span><br />
First, we create a data access object that encapsulates the logic to read (find), create, update, and delete wines. This simple application is read-only and only needs to retrieve collections. So, I only implemented the findAll() method and stubbed the other methods (find, create, update, destroy). WineDAO also has a &#8220;populate&#8221; function to populate the wine table with sample data. </p>
<pre class="brush: jscript; title: ; notranslate">
window.WineDAO = function (db) {
    this.db = db;
};

_.extend(window.WineDAO.prototype, {

    findAll:function (callback) {
        this.db.transaction(
            function (tx) {
                var sql = &quot;SELECT * FROM wine ORDER BY name&quot;;
                tx.executeSql(sql, [], function (tx, results) {
                    var len = results.rows.length;
                    var wines = [];
                    for (var i = 0; i &lt; len; i++) {
                        wines[i] = results.rows.item(i);
                    }
                    callback(wines);
                });
            },
            function (tx, error) {
                alert(&quot;Transaction Error: &quot; + error);
            }
        );
    },

    create:function (model, callback) {
//        TODO: Implement
    },

    update:function (model, callback) {
//        TODO: Implement
    },

    destroy:function (model, callback) {
//        TODO: Implement
    },

    find:function (model, callback) {
//        TODO: Implement
    },

//  Populate Wine table with sample data
    populate:function (callback) {
        this.db.transaction(
            function (tx) {
                console.log('Dropping WINE table');
                tx.executeSql('DROP TABLE IF EXISTS wine');
                var sql =
                    &quot;CREATE TABLE IF NOT EXISTS wine ( &quot; +
                        &quot;id INTEGER PRIMARY KEY AUTOINCREMENT, &quot; +
                        &quot;name VARCHAR(50), &quot; +
                        &quot;year VARCHAR(50), &quot; +
                        &quot;grapes VARCHAR(50), &quot; +
                        &quot;country VARCHAR(50), &quot; +
                        &quot;region VARCHAR(50), &quot; +
                        &quot;description TEXT, &quot; +
                        &quot;picture VARCHAR(200))&quot;;
                console.log('Creating WINE table');
                tx.executeSql(sql);
                console.log('Inserting wines');
                tx.executeSql(&quot;INSERT INTO wine VALUES (1,'CHATEAU DE SAINT COSME','2009','Grenache / Syrah','France','Southern Rhone / Gigondas','The aromas of fruit and spice give one a hint of the light drinkability of this lovely wine, which makes an excellent complement to fish dishes.','saint_cosme.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (2,'LAN RIOJA CRIANZA','2006','Tempranillo','Spain','Rioja','A resurgence of interest in boutique vineyards has opened the door for this excellent foray into the dessert wine market. Light and bouncy, with a hint of black truffle, this wine will not fail to tickle the taste buds.','lan_rioja.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (3,'MARGERUM SYBARITE','2010','Sauvignon Blanc','USA','California Central Cosat','The cache of a fine Cabernet in ones wine cellar can now be replaced with a childishly playful wine bubbling over with tempting tastes of black cherry and licorice. This is a taste sure to transport you back in time.','margerum.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (4,'OWEN ROE \&quot;EX UMBRIS\&quot;','2009','Syrah','USA','Washington','A one-two punch of black pepper and jalapeno will send your senses reeling, as the orange essence snaps you back to reality. Do not miss this award-winning taste sensation.','ex_umbris.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (5,'REX HILL','2009','Pinot Noir','USA','Oregon','One cannot doubt that this will be the wine served at the Hollywood award shows, because it has undeniable star power. Be the first to catch the debut that everyone will be talking about tomorrow.','rex_hill.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (6,'VITICCIO CLASSICO RISERVA','2007','Sangiovese Merlot','Italy','Tuscany','Though soft and rounded in texture, the body of this wine is full and rich and oh-so-appealing. This delivery is even more impressive when one takes note of the tender tannins that leave the taste buds wholly satisfied.','viticcio.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (7,'CHATEAU LE DOYENNE','2005','Merlot','France','Bordeaux','Though dense and chewy, this wine does not overpower with its finely balanced depth and structure. It is a truly luxurious experience for the senses.','le_doyenne.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (8,'DOMAINE DU BOUSCAT','2009','Merlot','France','Bordeaux','The light golden color of this wine belies the bright flavor it holds. A true summer wine, it begs for a picnic lunch in a sun-soaked vineyard.','bouscat.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (9,'BLOCK NINE','2009','Pinot Noir','USA','California','With hints of ginger and spice, this wine makes an excellent complement to light appetizer and dessert fare for a holiday gathering.','block_nine.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (10,'DOMAINE SERENE','2007','Pinot Noir','USA','Oregon','Though subtle in its complexities, this wine is sure to please a wide range of enthusiasts. Notes of pomegranate will delight as the nutty finish completes the picture of a fine sipping experience.','domaine_serene.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (11,'BODEGA LURTON','2011','Pinot Gris','Argentina','Mendoza','Solid notes of black currant blended with a light citrus make this wine an easy pour for varied palates.','bodega_lurton.jpg')&quot;);
                tx.executeSql(&quot;INSERT INTO wine VALUES (12,'LES MORIZOTTES','2009','Chardonnay','France','Burgundy','Breaking the mold of the classics, this offering will surprise and undoubtedly get tongues wagging with the hints of coffee and tobacco in perfect alignment with more traditional notes. Breaking the mold of the classics, this offering will surprise and undoubtedly get tongues wagging with the hints of coffee and tobacco in perfect alignment with more traditional notes. Sure to please the late-night crowd with the slight jolt of adrenaline it brings.','morizottes.jpg')&quot;);
            },
            function (tx, error) {
                alert('Transaction error ' + error);
            },
            function (tx) {
                callback();
            }
        );
    }
});
</pre>
<p>I then added a &#8220;dao&#8221; attribute to the Models to specify which data object should be used to access their underlying data.</p>
<pre class="brush: jscript; title: ; notranslate">
window.Wine = Backbone.Model.extend({
	urlRoot: &quot;http://coenraets.org/backbone-cellar/part1/api/wines&quot;,
    dao: WineDAO
});

window.WineCollection = Backbone.Collection.extend({
	model: Wine,
	url: &quot;http://coenraets.org/backbone-cellar/part1/api/wines&quot;,
    dao: WineDAO
});
</pre>
<p>NOTE: The application doesn&#8217;t need the url and urlRoot attributes anymore, but you can imagine a more sophisticated version of the app that would work with the RESTful services while online and fall back to the local database while offline. </p>
<p>With that infrastructure in place, we can now override Backbone.sync as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
Backbone.sync = function (method, model, options) {

    var dao = new model.dao(window.db);

    switch (method) {
        case &quot;read&quot;:
            if (model.id)
                dao.find(model, function (data) {
                    options.success(data);
                });
            else
                dao.findAll(function (data) {
                    options.success(data);
                });
            break;
        case &quot;create&quot;:
            dao.create(model, function (data) {
                options.success(data);
            });
            break;
        case &quot;update&quot;:
            dao.update(model, function (data) {
                options.success(data);
            });
            break;
        case &quot;delete&quot;:
            dao.destroy(model, function (data) {
                options.success(data);
            });
            break;
    }

};
</pre>
<p>And finally, we need to open the database (and populate it with sample data) at startup:</p>
<pre class="brush: jscript; title: ; notranslate">
window.startApp = function () {
    var self = this;
    window.db = window.openDatabase(&quot;WineCellar&quot;, &quot;1.0&quot;, &quot;WineCellar Demo DB&quot;, 200000);
    var wineDAO = new WineDAO(self.db);
    wineDAO.populate(function () {
        this.templateLoader.load(['wine-list', 'wine-details', 'wine-list-item'], function () {
            self.app = new AppRouter();
            Backbone.history.start();
        });
    })
}
</pre>
<h4>Download</h4>
<p>I added this version of the application to the backbone-cellar GitHub repository <a href="https://github.com/ccoenraets/backbone-cellar/tree/master/mobile/offline">here</a>. </p>
<p>NOTE: You will have to create a PhoneGap project (see <a href="http://phonegap.com/start">documentation</a> here) or use the <a href="https://build.phonegap.com/">hosted build service</a> to package the code as a native app for different mobile platforms.</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Sample%20Mobile%20App%20with%20Backbone.js,%20PhoneGap,%20and%20a%20Local%20Database%20http://coenraets.org/blog/?p=3044" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-phonegap-and-a-local-database/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-phonegap-and-a-local-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sample Mobile App with Backbone.js and PhoneGap</title>
		<link>http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-and-phonegap/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-mobile-app-with-backbone-js-and-phonegap</link>
		<comments>http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-and-phonegap/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-mobile-app-with-backbone-js-and-phonegap#comments</comments>
		<pubDate>Mon, 06 Feb 2012 17:27:53 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2987</guid>
		<description><![CDATA[I recently blogged a tutorial (part 1, part 2, part 3, and postface) that takes you through the process of building a CRUD application using HTML and the Backbone.js framework. The application used in this tutorial is a Wine Cellar management app, and I thought it would be fun to create a Mobile version using [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Sample%20Mobile%20App%20with%20Backbone.js%20and%20PhoneGap%20http://coenraets.org/blog/?p=2987" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-and-phonegap/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p>I recently blogged a tutorial (<a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-1-getting-started/">part 1</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-2-crud/">part 2</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-3-deep-linking-and-application-states/">part 3</a>, and <a href="http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/">postface</a>) that takes you through the process of building a CRUD application using HTML and the <a href="http://documentcloud.github.com/backbone/">Backbone.js</a> framework. The application used in this tutorial is a Wine Cellar management app, and I thought it would be fun to create a Mobile version using <a href="http://phonegap.com/">PhoneGap</a>.</p>
<p>PhoneGap &#8212; if you are not familiar with it &#8212; is an open source platform that allows you develop cross-platform Mobile applications using HTML and JavaScript. Specifically, it allows you to:</p>
<ol>
<li>Package an HTML application as a native app on all the key mobile platforms (iOS, Android, BlackBerry, Windows Phone, WebOS, Symbian, Bada).</li>
<li>Access your device capabilities (Camera, GPS, database, accelerometer, etc) using a cross-platform JavaScript API.</li>
</ol>
<p>Backbone.js is a great framework to give structure to your web application regardless of where it is running: in a traditional Web Browser, or as an app packaged with PhoneGap. </p>
<p>So, here is the app&#8230;<br />
<span id="more-2987"></span></p>
<p>
<img src="http://coenraets.org/blog/wp-content/uploads/2012/02/wine4.jpg" alt="" title="wine4" width="300" height="450" style="float: left;" /></p>
<p><img src="http://coenraets.org/blog/wp-content/uploads/2012/02/wine3.jpg" alt="" title="wine3" width="300" height="450" style="float: right;margin-top:-20px;"/>
</p>
<p style="clear: both;">&nbsp;</p>
<p>The UI is intentionally plain to keep the focus on the architectural framework. This is a simple &#8216;consumer&#8217; version of the application: It allows you to look for wines in your Wine Cellar. The tutorial application mentioned above is an &#8216;admin&#8217; version: You can create, update, delete wines in your Wine Cellar. Most of the code is shared between the Mobile &#8216;consumer&#8217; version and the browser-based &#8216;admin&#8217; version.</p>
<p>In this version, the application gets the data from RESTful services hosted on my server. In my next post, I will provide another version of the application that gets the data using a local database on your device.</p>
<h4>Download</h4>
<p>I added the source code for the mobile application to the <a href="https://github.com/ccoenraets/backbone-cellar">backbone-cellar GitHub repository</a>. You can download the zip file <a href="https://github.com/ccoenraets/backbone-cellar/zipball/master">here</a>. For your convenience, I created an <a href="https://github.com/ccoenraets/backbone-cellar/tree/master/mobile/ios">iOS directory</a> with the Xcode project and an <a href="https://github.com/ccoenraets/backbone-cellar/tree/master/mobile/android">Android directory</a> with the Eclipse project. The core application is in the www directory (<a href="https://github.com/ccoenraets/backbone-cellar/tree/master/mobile/ios/WineCellar/www">iOS</a> and <a href="https://github.com/ccoenraets/backbone-cellar/tree/master/mobile/android/BackboneCellarAndroid/assets/www">android</a>) and it is the same code for both iOS and Android.</p>
<p>If you want to run the application on your Android device without installing the project, you can also download the apk file available in the <a href="https://github.com/ccoenraets/backbone-cellar/tree/master/mobile/android/BackboneCellarAndroid/bin">bin directory</a>.</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Sample%20Mobile%20App%20with%20Backbone.js%20and%20PhoneGap%20http://coenraets.org/blog/?p=2987" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-and-phonegap/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2012/02/sample-mobile-app-with-backbone-js-and-phonegap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sample Application with Angular.js</title>
		<link>http://coenraets.org/blog/2012/02/sample-application-with-angular-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-application-with-angular-js</link>
		<comments>http://coenraets.org/blog/2012/02/sample-application-with-angular-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-application-with-angular-js#comments</comments>
		<pubDate>Thu, 02 Feb 2012 20:33:32 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2889</guid>
		<description><![CDATA[After I blogged a three-part Backbone.js tutorial (part 1, part 2, part 3), a number of people asked me to try Angular.js. So I decided to take it for a test drive. I thought it would be interesting to rebuild with Angular.js the Wine Cellar application I had built with Backbone. If you are new [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Sample%20Application%20with%20Angular.js%20http://coenraets.org/blog/?p=2889" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/02/sample-application-with-angular-js/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p>After I blogged a three-part Backbone.js tutorial (<a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-1-getting-started/">part 1</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-2-crud/">part 2</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-3-deep-linking-and-application-states/">part 3</a>), a number of people asked me to try <a href="http://angularjs.org/">Angular.js</a>. So I decided to take it for a test drive. I thought it would be interesting to rebuild with Angular.js the Wine Cellar application I had built with Backbone.<br />
<span id="more-2889"></span></p>
<p><img src="http://coenraets.org/blog/wp-content/uploads/2011/12/cellar2.jpg" alt="" title="cellar2" width="640" height="496" class="alignnone size-full wp-image-2392" /></p>
<p>If you are new to my Wine Cellar application, it is a simple CRUD app that allows you to manage (create, update, delete) wines in a Wine Cellar. The data is stored in a MySQL database that the client application accesses through a simple RESTful API. This seemed to be a good fit since CRUD applications are often positioned as the sweet spot for Angular.js.</p>
<p>You can run the application <a href="http://coenraets.org/angular-cellar">here</a>. The UI is intentionally plain to keep the focus on the key learning points. For obvious reasons, this online version is &#8220;read-only&#8221;. You can download the fully enabled version <a href="https://github.com/ccoenraets/angular-cellar">here</a>. </p>
<h4>Application Walkthrough</h4>
<p>The best way to get started with Angular.js is to go through the <a href="http://docs.angularjs.org/#!/tutorial">excellent tutorial</a> that is part of the documentation, so I&#8217;ll only provide a high level overview of my code here. </p>
<p>Like the Backbone.js implementation, the Angular.js version is a deep-linkable single page application. index.html is defined as follows:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE HTML&gt;
&lt;html xmlns:ng=&quot;http://angularjs.org&quot;&gt;
&lt;head&gt;
&lt;title&gt;Angular Cellar&lt;/title&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/styles.css&quot; /&gt;
&lt;/head&gt;

&lt;body ng:controller=&quot;RouteCtrl&quot;&gt;

&lt;div id=&quot;header&quot;&gt;
    Angular Cellar
    &lt;button ng:click=&quot;addWine()&quot;&gt;New Wine&lt;/button&gt;
&lt;/div&gt;

&lt;div id=&quot;sidebar&quot;&gt;
    &lt;ng:include src=&quot;'tpl/wine-list.html'&quot;&gt;&lt;/ng:include&gt;
&lt;/div&gt;

&lt;div id=&quot;content&quot;&gt;
    &lt;ng:view&gt;&lt;/ng:view&gt;
&lt;/div&gt;

&lt;script src=&quot;lib/angular-0.9.19.min.js&quot; ng:autobind&gt;&lt;/script&gt;
&lt;script src=&quot;js/services.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/controllers.js&quot;&gt;&lt;/script&gt;

&lt;/body&gt;

&lt;/html&gt;
</pre>
<p>The application is driven by a set of <strong>Controllers</strong> that I defined in controllers.js as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
function RouteCtrl($route) {

    var self = this;

    $route.when('/wines', {template:'tpl/welcome.html'});

    $route.when('/wines/:wineId', {template:'tpl/wine-details.html', controller:WineDetailCtrl});

    $route.otherwise({redirectTo:'/wines'});

    $route.onChange(function () {
        self.params = $route.current.params;
    });

    $route.parent(this);

    this.addWine = function () {
        window.location = &quot;#/wines/add&quot;;
    };

}

function WineListCtrl(Wine) {

    this.wines = Wine.query();

}

function WineDetailCtrl(Wine) {

    this.wine = Wine.get({wineId:this.params.wineId});

    this.saveWine = function () {
        if (this.wine.id &gt; 0)
            this.wine.$update({wineId:this.wine.id});
        else
            this.wine.$save();
        window.location = &quot;#/wines&quot;;
    }

    this.deleteWine = function () {
        this.wine.$delete({wineId:this.wine.id}, function() {
            alert('Wine ' + wine.name + ' deleted')
            window.location = &quot;#/wines&quot;;
        });
    }

}
</pre>
<p><strong>RouteCtrl</strong> defines the routes of the application. Each route is defined by a template that is rendered in &lt;ng:view&gt; inside index.html. There can only be one &lt;ng:view&gt; in a document (more on that later). For example, here is the wine-list.html template:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;ul ng:controller=&quot;WineListCtrl&quot;&gt;
    &lt;li ng:repeat=&quot;wine in wines&quot;&gt;
        &lt;a href='#/wines/{{ wine.id }}'&gt;{{ wine.name }}&lt;/a&gt;
    &lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>The <strong>WineListCtrl</strong> and <strong>WineDetailCtrl</strong> controllers provide access to the data using a service defined in services.js as follows: </p>
<pre class="brush: jscript; title: ; notranslate">
angular.service('Wine', function ($resource) {
    return $resource('api/wines/:wineId', {}, {
        update: {method:'PUT'}
    });
});
</pre>
<p>Services provide a great way to abstract your data access logic, and to easily change it without impacting the rest of the application. For example, you could easily change the Wine service to use a Mock service instead of a RESTful service.</p>
<h4>Impressions</h4>
<p>I was able to build this application in a very limited amount of time with no prior knowledge of the framework. The data-binding implementation is nice, and, in general, the amount of boilerplate code you have to write is very limited. Frameworks are often a matter of style and personal preferences. Angular.js takes a more declarative approach than other frameworks. Based on this initial experience, I would also describe it as more prescriptive: I didn&#8217;t have to spend a lot of time wondering what was the best way to do things as Angular.js tends to have clear utilization patterns. I haven&#8217;t spend enough time with the framework to determine if that comes at the cost of less control, and I&#8217;d love to hear what other people are thinking.</p>
<p>The only problem I ran into while building the application is the &#8220;one route / one view&#8221; coupling I alluded to above. As suggested in <a href="http://groups.google.com/group/angular/browse_thread/thread/c482321a95bc2949/2e5c9074485c102d?hide_quotes=no">this thread</a>, you can use &lt;ng:include&gt; to bind partials in the page. The same thread also indicates that multiple &lt;ng:views&gt; per route definition will be supported in the future. I was able to handle the simple UI requirements of this app using one &lt;ng:view&gt; and one &lt;ng:include&gt;. For more complex applications, I&#8217;d love the routing infrastructure to allow me to easily and arbitrarily add, remove, change, or animate different elements of the DOM when the route changes in order to support deeper UI transformations. I&#8217;m sure there are ways to do this. If Angular.js folks are reading this post, I&#8217;d love to hear what they think and what&#8217;s coming.</p>
<h4>Download</h4>
<p>The application is available on GitHub <a href="https://github.com/ccoenraets/angular-cellar">here</a>. </p>
<p>You will need the RESTful services to run this application. A PHP version (using the Slim framework) is available as part of the download. If you want to test the application with a Java back-end, you can download the Backbone version <a href="https://github.com/ccoenraets/backbone-jax-cellar">here</a>, and reuse its JAX-RS back-end.</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Sample%20Application%20with%20Angular.js%20http://coenraets.org/blog/?p=2889" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/02/sample-application-with-angular-js/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2012/02/sample-application-with-angular-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backbone.js Lessons Learned and Improved Sample App</title>
		<link>http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=backbone-js-lessons-learned-and-improved-sample-app</link>
		<comments>http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=backbone-js-lessons-learned-and-improved-sample-app#comments</comments>
		<pubDate>Mon, 30 Jan 2012 16:06:42 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2810</guid>
		<description><![CDATA[A few weeks ago, I posted a three-part Backbone.js tutorial (part 1, part 2, part 3). Since then, I spent more time building a real-life application with Backbone. I ran into a number of interesting problems, spent time thinking about solutions, and decided to write them down in this post. These are not definitive answers, [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Backbone.js%20Lessons%20Learned%20and%20Improved%20Sample%20App%20http://coenraets.org/blog/?p=2810" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago, I posted a three-part Backbone.js tutorial (<a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-1-getting-started/">part 1</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-2-crud/">part 2</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-3-deep-linking-and-application-states/">part 3</a>). Since then, I spent more time building a real-life application with Backbone. I ran into a number of interesting problems, spent time thinking about solutions, and decided to write them down in this post. These are not definitive answers, just my current thoughts&#8230; and as always, I value your input.</p>
<p>Based on this new experience, I revisited the Wine Cellar application used in my tutorial. You can find the improved version <a href="https://github.com/ccoenraets/backbone-cellar">here</a> (PHP back-end) or <a href="https://github.com/ccoenraets/backbone-jax-cellar">here</a> (Java back-end).  </p>
<h4>Externalizing Templates</h4>
<p>In the initial implementation of my wine cellar app, I &#8220;inlined&#8221; my templates in a succession of &lt;script&gt; tags like the one below inside index.html.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/template&quot; id=&quot;wine-list-item&quot;&gt;
	&lt;li&gt;&lt;a href='#wines/&lt;%= id %&gt;'&gt;&lt;%= name %&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/script&gt;
</pre>
<p>This approach works fine for a simple application with a limited number of templates. In a larger project, it makes templates hard to maintain. It also makes it difficult for multiple developers to work on different templates at the same time. Removing the script body and adding a src attribute to point to an external file didn’t seem to work to load HTML templates.<br />
<span id="more-2810"></span><br />
In <a href="http://stackoverflow.com/questions/8366733/external-template-in-underscore">this</a> StackOverflow thread, Brian Genisio suggests loading external templates as string variables in a .js file. Using this approach, a template definition looks like this:</p>
<pre class="brush: jscript; title: ; notranslate">
app.templates.view = &quot; \
    &lt;h3&gt;something code&lt;/h3&gt; \
&quot;;
</pre>
<p>That’s certainly a valid approach, but depending on your circumstances, it may still not be the ideal solution: long string concatenation is painful (especially for larger templates). In addition, if you define HTML in string variables, you will probably not be able to benefit from the HTML capabilities of your editor.  </p>
<p>Other people load external templates using <a href="http://requirejs.org/">Require.js</a> and the text plugin, which is definitely an approach worth considering for larger projects. In my case, I didn’t feel that the size of my project mandated it.</p>
<p>In the end, I decided to write my own simple template loader. It is implemented as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
tpl = {

    // Hash of preloaded templates for the app
    templates: {},

    // Recursively pre-load all the templates for the app.
    // This implementation should be changed in a production environment:
    // All the template files should be concatenated in a single file.
    loadTemplates: function(names, callback) {

        var that = this;

        var loadTemplate = function(index) {
            var name = names[index];
            console.log('Loading template: ' + name);
            $.get('tpl/' + name + '.html', function(data) {
                that.templates[name] = data;
                index++;
                if (index &lt; names.length) {
                    loadTemplate(index);
                } else {
                    callback();
                }
            });
        }

        loadTemplate(0);
    },

    // Get template by name from hash of preloaded templates
    get: function(name) {
        return this.templates[name];
    }

};
</pre>
<p>I use it to preload all my templates before bootstrapping Backbone:</p>
<pre class="brush: jscript; title: ; notranslate">
tpl.loadTemplates(['header', 'wine-details', 'wine-list-item'], function() {
    app = new AppRouter();
    Backbone.history.start();
});
</pre>
<p>Loading templates separately is great during development: you can modify and test individual templates without requiring a “build” or the concatenation of multiple template files. In production however, loading dozens of templates as separate HTTP requests can be a serious bottleneck. So when you are ready to move to production, it&#8217;s a good idea to somehow combine all your templates in a single file so that you can load them all with a single HTTP request.</p>
<h4> Decouple Views from other DOM elements</h4>
<p>In the initial version of my application, I didn’t pay much attention to the way I chose the &#8220;el&#8221; or &#8220;tagName&#8221; of my Views. I often assigned the View’s &#8220;el&#8221; to an existing element of the document.</p>
<p>&#8220;Before&#8221; code:</p>
<pre class="brush: jscript; title: ; notranslate">
window.WineView = Backbone.View.extend({

    el: $('#content'),

    render: function(eventName) {
		$(this.el).html(this.template(this.model.toJSON()));
		return this;
    }

});
</pre>
<p>&#8230; and here is the Router&#8217;s code that instantiated and displayed a WineView:</p>
<pre class="brush: jscript; title: ; notranslate">
new WineView().render();
</pre>
<p>After more careful consideration, I realized that this approach wasn’t very good. The View is not fully encapsulated: it “reaches out” to an attribute (element) of the containing document (&#8216;#mainArea&#8217;), creating an undesirable dependency. A better approach is to make sure a View doesn’t know about its hosting document. It should not know about (or assume the presence) of other elements in the document. The knowledge of the View should be limited to the elements in its own template.  That will make the view reusable in many different contexts. The corollary of this rule is that a View shouldn’t attach itself to a DOM element in its render() method. The render() method should be limited to populating its own &#8220;detached&#8221; el attribute. The code that invokes the View’s render() method can then decide what to do with the View’s HTML fragment: attach it, append it, etc. The View is therefore more reusable and more versatile.</p>
<p>&#8220;After&#8221; code:</p>
<pre class="brush: jscript; title: ; notranslate">
window.WineView = Backbone.View.extend({

    tagName: &quot;div&quot;, // Not required since 'div' is the default if no el or tagName specified

    render: function(eventName) {
		$(this.el).html(this.template(this.model.toJSON()));
		return this;
    }

});
</pre>
<p>&#8230; and here is the Router’s code that instantiates and displays a WineView defined as above:</p>
<pre class="brush: jscript; title: ; notranslate">
$('#content').html( new WineView().render().el );
</pre>
<p>&nbsp;</p>
<h4>Cleaning Up: Avoiding Memory Leaks and Ghost Views</h4>
<p>Before getting rid of a view, you need to clean up, which mainly consists of removing the bindings that could prevent the View from being properly destroyed. A View that is not properly destroyed becomes a “Ghost View”: you don’t see it, you think it’s gone,  but it still manifests itself in some unpleasant ways: its events are still firing and it still uses memory (memory leaks). Ghost Views often first manifest themselves in the form of events firing multiple times. </p>
<p>In my initial implementation, I provided views with a close() method that took care of cleaning up. There was nothing wrong with that approach except that you had to remember to call the close() method! </p>
<p>Derick Bailey has a <a href="http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/">great post</a> on this topic and provides a more generalized approach: It consists of adding a generic close() method to the Backbone View prototype. I borrowed Derick’s approach and implemented my generic close() method as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
Backbone.View.prototype.close = function () {
    if (this.beforeClose) {
        this.beforeClose();
    }
    this.remove();
    this.unbind();
};
</pre>
<p>The call to beforeClose() (if it exists in the view) is a hook to add some view-specific cleanup code if required.</p>
<p>In your Router, you then create new Views by invoking a custom showView() method that invokes close() on the currentView before replacing it with the new View. </p>
<pre class="brush: jscript; title: ; notranslate">
showView: function(selector, view) {
    if (this.currentView)
        this.currentView.close();
    $(selector).html(view.render().el);
    this.currentView = view;
    return view;
}
</pre>
<p>Note that this is only part of the solution. For example, if you have composite views (views containing other views), you still have to make sure you close the “child” views when the parent view is closed. A good approach here is for the parent view to keep track of its child views so that it can call their respective close() methods when its own close() method is invoked. The beforeClose() method (explained above) of the parent View is a good place to close the child Views.</p>
<h4>Route pre-processing (aka Filters)</h4>
<p>Backbone’s Router is great at routing requests to the important/stateful/bookmarkable locations in your application. </p>
<p>When defining the routes in my application, I sometimes find myself in a situation where a pre-condition has to be met before a route can be taken.</p>
<p>For example: </p>
<ul>
<li>Some routes may require the user to be authenticated.</li>
<li>Some routes may require some data to be loaded.</li>
</ul>
<p>It’s easy to verify the pre-condition in the method that implements a specific route. That’s what I did in the initial version of my application. But in a larger application, this approach will quickly start cluttering your route methods.</p>
<p>My instinct was to look for a “Filter” feature in the Backbone Router API, but it doesn’t currently exist out-of-the-box, and in <a href="https://github.com/documentcloud/backbone/pull/299">this thread</a>, Jeremy makes the case that the same result can be achieved using underscore’s _.wrap() method.</p>
<p>_.wrap() didn’t work for me because my pre-condition involved asynchronous processing and I can only pass control back to the routing method after the successful completion of my async code.</p>
<p>In the end, I implemented a simple/low-tech before() method that is somewhat similar to wrap() but supports async chaining. </p>
<pre class="brush: jscript; title: ; notranslate">
var AppRouter = Backbone.Router.extend({

	routes: {
		&quot;wines/:id&quot;	: &quot;wineDetails&quot;
	},

	wineDetails: function(id) {
        this.before(function() {
			var wine = app.wineList.get(id);
		    app.showView( '#content', new WineView({model: wine}) );
        });
  	},

    showView: function(selector, view) {
        if (this.currentView)
            this.currentView.close();
        $(selector).html(view.render().el);
        this.currentView = view;
        return view;
    },

    before: function(callback) {
        if (this.wineList) {
            if (callback) callback();
        } else {
            this.wineList = new WineCollection();
       		this.wineList.fetch({success: function() {
               $('#sidebar').html( new WineListView({model: app.wineList}).render().el );
               if (callback) callback();
            }});
        }
    }

});
</pre>
<p>This solution is not as “decoupled” as a traditional filter implementation would be, but it allowed me to unclutter my code in a way that was suitable for my requirements. Jake Dempsey<br />
 has built a more traditional filter implementation <a href="https://github.com/angelo0000/backbone_filters">here</a> that you may want to take a look at. </p>
<h4>Download</h4>
<p>The source code for this application is hosted on GitHub. The application uses RESTful services to access the data.</p>
<p>For a version of this application using a PHP back-end, use <a href="https://github.com/ccoenraets/backbone-cellar">this project</a> (use the &#8216;final&#8217; folder for the version of the application discussed in this article.</p>
<p>For a version of this application using a Java back-end (using JAX-RS), use <a href="https://github.com/ccoenraets/backbone-jax-cellar">this project</a>.</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Backbone.js%20Lessons%20Learned%20and%20Improved%20Sample%20App%20http://coenraets.org/blog/?p=2810" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Backbone.js with a RESTful Java Back-End</title>
		<link>http://coenraets.org/blog/2012/01/using-backbone-js-with-a-restful-java-back-end/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-backbone-js-with-a-restful-java-back-end</link>
		<comments>http://coenraets.org/blog/2012/01/using-backbone-js-with-a-restful-java-back-end/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-backbone-js-with-a-restful-java-back-end#comments</comments>
		<pubDate>Tue, 10 Jan 2012 17:39:44 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2765</guid>
		<description><![CDATA[In a previous post, RESTful services with jQuery and Java using JAX-RS and Jersey, I demonstrated how to build a RESTful API using JAX-RS and Jersey, and how to build a jQuery application that leverages that API. The application used as an example was a Wine Cellar management application. In follow-up posts, &#8220;Backbone.js Wine Cellar [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Using%20Backbone.js%20with%20a%20RESTful%20Java%20Back-End%20http://coenraets.org/blog/?p=2765" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/01/using-backbone-js-with-a-restful-java-back-end/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p><a href="http://coenraets.org/blog/wp-content/uploads/2012/01/backbone-java4.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2012/01/backbone-java4.jpg" alt="" title="backbone-java4" width="428" height="148" class="aligncenter size-full wp-image-2792" /></a></p>
<p>In a previous post, <a href="http://coenraets.org/blog/2011/12/restful-services-with-jquery-and-java-using-jax-rs-and-jersey/">RESTful services with jQuery and Java using JAX-RS and Jersey</a>, I demonstrated how to build a RESTful API using JAX-RS and Jersey, and how to build a jQuery application that leverages that API. The application used as an example was a Wine Cellar management application.</p>
<p>In follow-up posts, &#8220;Backbone.js Wine Cellar Tutorial&#8221; (<a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-1-getting-started/">part1</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-2-crud/">part 2</a>, <a href="http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-3-deep-linking-and-application-states/">part 3</a>), I showed how to add structure to the client-side of the Wine Cellar application using <a href="http://documentcloud.github.com/backbone/">Backbone.js</a>. But that three-part tutorial was provided with a PHP back-end.</p>
<p>By popular demand, here is a version of the Backbone.js Wine Cellar application powered by a Java / JAX-RS back-end using Jersey. The server-side of the application provides an example of building a complete RESTful API in Java using the different HTTP methods:<br />
<span id="more-2765"></span></p>
<ul>
<li><strong>GET</strong> to retrieve and search wines</li>
<li><strong>POST</strong> to add a wine</li>
<li><strong>PUT</strong> to update a wine</li>
<li><strong>DELETE</strong> to delete a wine</li>
</ul>
<p>As already mentioned, the client-side of the application provides an example of adding structure to your JavaScript code using the Backbone.js Model, View and Router components. To learn more about the Backbone.js implementation, refer to the three part tutorial mentioned above: it is entirely back-end agnostic. </p>
<p>The source code for this application is hosted on GitHub <a href="https://github.com/ccoenraets/backbone-jax-cellar">here</a>. It consists of the Eclipse Dynamic Web Project with the source code for both the Java back-end and JavaScript/Backbone.js client.</p>
<p>You can run the application (Part 3) <a href="http://coenraets.org/backbone-cellar/part3/">here</a>. The create/update/delete features are disabled in this online version.</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Using%20Backbone.js%20with%20a%20RESTful%20Java%20Back-End%20http://coenraets.org/blog/?p=2765" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/01/using-backbone-js-with-a-restful-java-back-end/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2012/01/using-backbone-js-with-a-restful-java-back-end/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting Up WordPress on Amazon EC2 in 5 minutes</title>
		<link>http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=setting-up-wordpress-on-amazon-ec2-in-5-minutes</link>
		<comments>http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=setting-up-wordpress-on-amazon-ec2-in-5-minutes#comments</comments>
		<pubDate>Thu, 05 Jan 2012 20:45:48 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2672</guid>
		<description><![CDATA[Step 1: Create an AWS Account First things first: you need to create your AWS account. You can sign up here. You&#8217;ll have to provide a credit card and a phone number where you will be called as part of the online registration process for verification purposes. Amazon offers a Free Usage Tier, which is [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Setting%20Up%20WordPress%20on%20Amazon%20EC2%20in%205%20minutes%20http://coenraets.org/blog/?p=2672" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p><a href="http://coenraets.org/blog/wp-content/uploads/2012/01/awswp.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2012/01/awswp.jpg" alt="" title="awswp" width="289" height="100" class="aligncenter size-full wp-image-2753" /></a></p>
<h4>Step 1: Create an AWS Account</h4>
<p>First things first: you need to create your AWS account. You can sign up <a href="http://aws.amazon.com/ec2/">here</a>. You&#8217;ll have to provide a credit card and a phone number where you will be called as part of the online registration process for verification purposes. Amazon offers a <em>Free Usage Tier</em>, which is great to explore the services and even host real apps without being charged. Check the details <a href="http://aws.amazon.com/free/">here</a>.<br />
<span id="more-2672"></span></p>
<h4>Step 2: Create an Instance</h4>
<p><em>What type of EC2 instance should you use?</em> I started my experiments with a Micro instance because its price structure is very attractive. However, after a few minutes to a couple of hours, my blog systematically became unresponsive and I had to restart Apache and/or MySQL. I did some research, and found out that other people were reporting similar problems. It may depend on your blog traffic. My blog typically gets a few thousand page views a day. It also hosts live sample applications running with a PHP or a Java back-end running on Tomcat. It looks like that combination was too much for a Micro instance. I tried a Small instance and the problems went away. Greg Wilson has a <a href="http://gregsramblings.com/2011/02/07/amazon-ec2-micro-instance-cpu-steal/">great post</a> on the limitations of the Micro instance.</p>
<p>To create a new instance, access the AWS Management Console and click the EC2 tab:</p>
<ul>
<li>Choose an AMI in the classic instance wizard: I chose the <strong>Basic 32-bit Amazon Linux AMI</strong>.</li>
<li>Instance details: Select the <strong>Instance Type</strong> you want to use. I chose <strong>Small</strong> (m1.small).</li>
<li>Create a new key pair. Enter a name for your key pair (i.e. christophe) and download your key pair (i.e. christophe.pem).</li>
<li>Select the quick start security group.</li>
<li>Launch your instance.</li>
</ul>
<h4>Step 3: SSH into your Instance</h4>
<p>Once your instance is running, you can ssh into it. First, you need to identify the address of your instance: Select the instance in the AWS Management Console, and look for the Public DNS in the instance description (bottom part of the screen).</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2011/11/aws2.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2011/11/aws2.jpg" alt="" title="aws2" width="640" height="578" class="alignnone size-full wp-image-2212" /></a></p>
<p>Use that address (and a path to your .pem file) to ssh into your instance:<br/><span style="font-family:courier;font-weight:bold;color:#000;">ssh ec2-user@ec2-50-17-14-16.compute-1.amazonaws.com -i ~/christophe.pem<br />
</span><br />
If you get a message about your .pem file permissions being too open, chmod your .pem file as follows:<br /><span style="font-family:courier;font-weight:bold;color:#000;">chmod 600 ~/christophe.pem</span></p>
<p>Many of the shell commands below require root access. To avoid having to prefix these commands with sudo, let&#8217;s just switch user once and for all:<br /><span style="font-family:courier;font-weight:bold;color:#000;">sudo su</span></p>
<h4>Step 4: Install the Apache Web Server</h4>
<p>To install the Apache Web Server, type:<br /><span style="font-family:courier;font-weight:bold;color:#000;">yum install httpd</span></p>
<p>Start the Apache Web Server:<br /><span style="font-family:courier;font-weight:bold;color:#000;">service httpd start</span></p>
<p>To test your Web Server, open a browser and access your web site: <a href="http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=setting-up-wordpress-on-amazon-ec2-in-5-minutes">http://ec2-50-17-14-16.compute-1.amazonaws.com</a> (Use your actual public DNS name). You should see a standard Amazon place holder page.</p>
<h4>Step 5: Install PHP</h4>
<p>To install PHP, type:<br /><span style="font-family:courier;font-weight:bold;color:#000;">yum install php php-mysql</span></p>
<p>Restart the Apache Web Server:<br /><span style="font-family:courier;font-weight:bold;color:#000;">service httpd restart</span></p>
<p>Create a page to test your PHP installation:<br /><span style="font-family:courier;font-weight:bold;color:#000;">cd /var/www/html<br />vi test.php</span></p>
<ol>
<li>Type <span style="font-family:courier;font-weight:bold;color:#000;">i</span> to start the insert mode</li>
<li>Type <span style="font-family:courier;font-weight:bold;color:#000;">&lt;?php phpinfo() ?></span></li>
<li>Type <span style="font-family:courier;font-weight:bold;color:#000;">:wq</span> to write the file and quit vi</li>
</ol>
<p>Open a browser and access test.php to test your PHP installation: <a href="http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=setting-up-wordpress-on-amazon-ec2-in-5-minutes">http://ec2-50-17-14-16.compute-1.amazonaws.com/test.php</a> (Use your actual public DNS name).</p>
<h4>Step 6: Install MySQL</h4>
<p>To install MySQL, type:<br /><span style="font-family:courier;font-weight:bold;color:#000;">yum install mysql-server</span></p>
<p>Start MySQL:<br /><span style="font-family:courier;font-weight:bold;color:#000;">service mysqld start</span></p>
<p>Create your &#8220;blog&#8221; database:<br /><span style="font-family:courier;font-weight:bold;color:#000;">mysqladmin -uroot create blog</span></p>
<p>Secure your database:<br /><span style="font-family:courier;font-weight:bold;color:#000;">mysql_secure_Installation</span></p>
<p>Answer the wizard questions as follows:</p>
<ol>
<li>Enter current password for root: Press return for none</li>
<li>Change Root Password: Y</li>
<li>New Password: Enter your new password</li>
<li>Remove anonymous user: Y</li>
<li>Disallow root login remotely: Y</li>
<li>Remove test database and access to it: Y</li>
<li>Reload privilege tables now: Y</li>
</ol>
<h4>Step 7: Install WordPress</h4>
<p>To install WordPress, type:<br /><span style="font-family:courier;font-weight:bold;color:#000;">cd /var/www/html<br />
wget http://wordpress.org/latest.tar.gz<br />
tar -xzvf latest.tar.gzcd<br />
</span></p>
<p>This will uncompress WordPress in its own &#8220;wordpress&#8221; directory. I like having WordPress in a separate directory, but would rather rename it to &#8220;blog&#8221;:<br /><span style="font-family:courier;font-weight:bold;color:#000;">mv wordpress blog</span></p>
<p>Create the WordPress wp-config.php file: <br /><span style="font-family:courier;font-weight:bold;color:#000;">cd blog<br />
mv wp-config-sample.php wp-config.php<br />
vi wp-config.php</span></p>
<ol>
<li>Type <span style="font-family:courier;font-weight:bold;color:#000;">i</span> to start insert mode.</li>
<li>Modify the database connection parameters as follows:<br />
<span style="font-family:courier;font-weight:bold;color:#000;">define(&#8216;DB_NAME&#8217;, &#8216;blog&#8217;);<br />
define(&#8216;DB_USER&#8217;, &#8216;root&#8217;);<br />
define(&#8216;DB_PASSWORD&#8217;, &#8216;YOUR_PASSWORD&#8217;);<br />
define(&#8216;DB_HOST&#8217;, &#8216;localhost&#8217;);</span>
</li>
<li>Type <span style="font-family:courier;font-weight:bold;color:#000;">:wq</span> to write the file and quit vi</li>
</ol>
<p>Open a Browser and access your blog: <a href="http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=setting-up-wordpress-on-amazon-ec2-in-5-minutes">http://ec2-50-17-14-16.compute-1.amazonaws.com/blog</a> (Use your actual public DNS name). This should trigger the WordPress configuration process.</p>
<h4>Step 8: Map IP Address and Domain Name</h4>
<p>To use your blog in production, you will have to:</p>
<ol>
<li>Associate an IP address to your instance</li>
<li>Map your domain name to that IP address</li>
</ol>
<p>To associate an IP address to your instance:</p>
<ol>
<li>In the AWS Management Console, click Elastic IPs (left navigation bar)</li>
<li>Click Allocate New Address, and confirm by clicking the &#8220;Yes, Allocate&#8221; button</li>
<li>Right-click the newly allocated IP address and select &#8220;Associate&#8221; in the popup menu. Select the instance you just created and click &#8220;Yes, Associate&#8221;</li>
</ol>
<p>To map your domain name to your IP address, you will have to use the tools provided by your domain registrar. If you use GoDaddy, specify NS73.DOMAINCONTROL.COM and NS74.DOMAINCONTROL.COM as the name servers for your domain, and use the DNS Manager to modify the A record and point to your IP address. Documentation is available <a href="http://help.godaddy.com/article/680">here</a>.</p>
<p>Once everything is configured and mapped correctly, access the General Settings in the WordPress management console and make sure the WordPress Address and Site Address are specified correctly using your domain name as in the screenshot below.<br />
<a href="http://coenraets.org/blog/wp-content/uploads/2012/01/wp-settings.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2012/01/wp-settings.jpg" alt="" title="wp-settings" width="550" height="240" class="alignnone size-full wp-image-2742" /></a></p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Setting%20Up%20WordPress%20on%20Amazon%20EC2%20in%205%20minutes%20http://coenraets.org/blog/?p=2672" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2012/01/setting-up-wordpress-on-amazon-ec2-in-5-minutes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tutorial: HTML Templates with Mustache.js</title>
		<link>http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tutorial-html-templates-with-mustache-js</link>
		<comments>http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tutorial-html-templates-with-mustache-js#comments</comments>
		<pubDate>Tue, 20 Dec 2011 15:53:43 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2658</guid>
		<description><![CDATA[} When developing modern HTML applications, you often write a lot of HTML fragments programmatically. You concatenate HTML tags and dynamic data, and insert the resulting UI markup into the DOM. Here is a random code example of this approach: The proliferation of this kind of code throughout your application comes with some downsides. The [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Tutorial:%20HTML%20Templates%20with%20Mustache.js%20http://coenraets.org/blog/?p=2660" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p><span  style="color:black;-webkit-transform: rotate(-90deg);-moz-transform: rotate(-90deg);display: block;font-size: 250px;font-family: Georgia;text-align: center;margin: 40px;">}</span></p>
<p>When developing modern HTML applications, you often write a lot of HTML fragments programmatically. You concatenate HTML tags and dynamic data, and insert the resulting UI markup into the DOM. Here is a random code example of this approach:</p>
<pre class="brush: jscript; title: ; notranslate">
$.each(messages.reverse(), function(index, message) {
	$('#messageList').append(
		'&lt;li&gt;&lt;span class=&quot;list-title&quot;&gt;' +
		message.userName + '&lt;/span&gt;' +
		'&lt;abbr class=&quot;list-timestamp&quot; title=&quot;' +
		message.datePosted + '&quot;&gt;&lt;/abbr&gt;' +
		'&lt;p class=&quot;list-text&quot;&gt;' + message.messageText + '&lt;/p&gt;&lt;/li&gt;');
	}
});
</pre>
<p>The proliferation of this kind of code throughout your application comes with some downsides. The tight coupling of UI and data logic doesn&#8217;t promote separation of concerns and reuse. It makes your application harder to write and harder to maintain.<br />
<span id="more-2660"></span><br />
HTML templates address this issue by decoupling the UI definition (HTML markup) from the data. There are a number of HTML template solutions out there: jQuery Templates, Underscore.js, and <a href="https://github.com/janl/mustache.js">Mustache.js</a> to name a few. Mustache.js is a popular choice because of its powerful syntax and fast rendering.</p>
<p><a href="http://mustache.github.com/">Mustache</a> is a &#8220;logic-less&#8221; template syntax. &#8220;Logic-less&#8221; means that it doesn&#8217;t rely on procedural statements (if, else, for, etc.): Mustache templates are entirely defined with tags. Mustache is implemented in different languages: Ruby, JavaScript, Python, PHP, Perl, Objective-C, Java, .NET, Android, C++, Go, Lua, Scala, etc. <a href="https://github.com/janl/mustache.js">Mustache.js</a> is the JavaScript implementation.</p>
<p>In this article, we take a quick tour of some of the capabilities of Mustache.js.</p>
<p>To start using Mustache.js, simply add a script tag to your html file pointing to mustache.js which is available <a href="https://github.com/janl/mustache.js/blob/master/mustache.js">here</a>.</p>
<p>You can run all the examples below <a href="http://coenraets.org/tutorials/mustache">here</a>.</p>
<h4>Sample 1: Basic Template</h4>
<p>This is a self-explanatory example. Note that:</p>
<ul>
<li>Instead of being defined in a variable, the data often comes from a service call (see sample 2)</li>
<li>Instead of being defined in a variable, the template is often read from a file (see sample 3)</li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
	var person = {
		firstName: &quot;Christophe&quot;,
		lastName: &quot;Coenraets&quot;,
		blogURL: &quot;http://coenraets.org&quot;
	};
	var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;Blog: {{blogURL}}&quot;;
	var html = Mustache.to_html(template, person);
	$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample1" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Christophe Coenraets</h1>
<p>Blog: http://coenraets.org</p></div>
<p>&nbsp;</p>
<h4>Sample 2: Basic Template using Ajax data</h4>
<p>Same as sample 1, except that we get the data from an Ajax service call.</p>
<pre class="brush: jscript; title: ; notranslate">
$.getJSON('json/data.json', function(data) {
	var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;Blog: {{blogURL}}&quot;;
	var html = Mustache.to_html(template, data);
	$('#sampleArea').html(html);
});
</pre>
<p>Result:</p>
<div id="sample2" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>John Smith</h1>
<p>Blog: http://johnsmith.com</p></div>
<p>&nbsp;</p>
<h4>Sample 3: Externalized Template</h4>
<p>Same as sample 2, except that we read the template from the main HTML file.</p>
<pre class="brush: jscript; title: ; notranslate">
$.getJSON('json/data2.json', function(data) {
	var template = $('#personTpl').html();
	var html = Mustache.to_html(template, data);
	$('#sampleArea').html(html);
});
</pre>
<p>The template is defined as follows in index.html:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script id=&quot;personTpl&quot; type=&quot;text/template&quot;&gt;
&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;
&lt;p&gt;Blog URL: &lt;a href=&quot;{{blogURL}}&quot;&gt;{{blogURL}}&lt;/a&gt;&lt;/p&gt;
&lt;/script&gt;
</pre>
<p>Result:</p>
<div id="sample3" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Lisa Jones</h1>
<p>Blog URL: <a href="http://lisajones.com">http://lisajones.com</a></p>
</div>
<p>&nbsp;</p>
<p><strong>NOTE:</strong> Sample 3 represents the way templates are being used in many dynamic Web applications:</p>
<ul>
<li>You get data from an Ajax service</li>
<li>You read the template from an external file
</ul>
<p>In the remaining of this article, we declare the data and the template in variables to keep the examples self-contained. Remember to refer to sample 3 for a traditional setup when using templates in a dynamic Web application.</p>
<p>&nbsp;</p>
<h4>Sample 4: Enumerable Section</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = {name: &quot;John Smith&quot;, skills: ['JavaScript', 'PHP', 'Java']};
var tpl = &quot;{{name}} skills:&lt;ul&gt;{{#skills}}&lt;li&gt;{{.}}&lt;/li&gt;{{/skills}}&lt;/ul&gt;&quot;;
var html = Mustache.to_html(tpl, data);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample4" style='border: solid 1px #ddd;background-color:#ddd;'>John Smith skills:
<ul>
<li>JavaScript</li>
<li>PHP</li>
<li>Java</li>
</ul>
</div>
<p>&nbsp;</p>
<h4>Sample 5: Enumerable Section with Objects</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = {
	employees: [
	{	firstName: &quot;Christophe&quot;,
		lastName: &quot;Coenraets&quot;},
	{	firstName: &quot;John&quot;,
		lastName: &quot;Smith&quot;}
	]};
var template = &quot;Employees:&lt;ul&gt;{{#employees}}&quot; +
                            &quot;&lt;li&gt;{{firstName}} {{lastName}}&lt;/li&gt;&quot; +
                            &quot;{{/employees}}&lt;/ul&gt;&quot;;
var html = Mustache.to_html(template, data);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample5" style='border: solid 1px #ddd;background-color:#ddd;'>Employees:
<ul>
<li>Christophe Coenraets</li>
<li>John Smith</li>
</ul>
</div>
<p>&nbsp;</p>
<h4>Sample 6: Nested Objects</h4>
<p>You can use the dot notation to access object properties.</p>
<pre class="brush: jscript; title: ; notranslate">
var person = {
	firstName: &quot;Christophe&quot;,
	lastName: &quot;Coenraets&quot;,
	blogURL: &quot;http://coenraets.org&quot;,
	manager : {
		firstName: &quot;John&quot;,
		lastName: &quot;Smith&quot;
	}
};
var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;&lt;p&gt;{{blogURL}}&lt;/p&gt;&quot; +
               &quot;Manager: {{manager.firstName}} {{manager.lastName}}&quot;;
var html = Mustache.to_html(template, person);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample6" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Christophe Coenraets</h1>
<p>http://coenraets.org</p>
<p>Manager: John Smith</p></div>
<p>&nbsp;</p>
<h4>Sample 7: Dereferencing</h4>
<p>Same as sample 6, except that we &#8220;dereference&#8221; the manager object to make it easier to access its properties (without having to use the dot notation).</p>
<pre class="brush: jscript; title: ; notranslate">
var person = {
	firstName: &quot;John&quot;,
	lastName: &quot;Smith&quot;,
	blogURL: &quot;http://johnsmith.com&quot;,
	manager : {
		firstName: &quot;Lisa&quot;,
		lastName: &quot;Jones&quot;
	}
};
var tpl = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;&lt;p&gt;{{blogURL}}&lt;/p&gt;&quot; +
          &quot;{{#manager}}Manager: {{firstName}} {{lastName}}{{/manager}}&quot;;
var html = Mustache.to_html(tpl, person);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample7" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>John Smith</h1>
<p>http://johnsmith.com</p>
<p>Manager: Lisa Jones</p></div>
<p>&nbsp;</p>
<h4>Sample 8: Function</h4>
<p>Templates can reference functions like totalPrice in this example.</p>
<pre class="brush: jscript; title: ; notranslate">
var product = {
	name: &quot;FooBar&quot;,
	price: 100,
	salesTax: 0.05,
	totalPrice: function() {
		return this.price + this.price * this.salesTax;
	}
};
var template = &quot;&lt;p&gt;Product Name: {{name}}&lt;/p&gt;Price: {{totalPrice}}&quot;;
var html = Mustache.to_html(template, product);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample8" style='border: solid 1px #ddd;background-color:#ddd;'>
<p>Product Name: FooBar</p>
<p>Price: 105</p></div>
<p>&nbsp;</p>
<h4>Sample 9: Condition</h4>
<p>Templates can include conditional sections. Conditional sections only render if the condition evaluates to true. A conditional section begins with {{#condition}} and ends with {{/condition}}. &#8220;condition&#8221; can be a boolean value or a function returning a boolean.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {
	employees: [
	{	firstName: &quot;Christophe&quot;,
		lastName: &quot;Coenraets&quot;,
		fullTime: true,
		phone: &quot;617-123-4567&quot;
	},
	{	firstName: &quot;John&quot;,
		lastName: &quot;Smith&quot;,
		fullTime: false,
		phone: &quot;617-987-6543&quot;
	},
	{	firstName: &quot;Lisa&quot;,
		lastName: &quot;Jones&quot;,
		fullTime: true,
		phone: &quot;617-111-2323&quot;
	},
	]};
var tpl = &quot;Employees:&lt;ul&gt;{{#employees}}&lt;li&gt;{{firstName}} {{lastName}}&quot; +
          &quot;{{#fullTime}} {{phone}}{{/fullTime}}&lt;/li&gt;{{/employees}}&lt;/ul&gt;&quot;;
var html = Mustache.to_html(tpl, data);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample9" style='border: solid 1px #ddd;background-color:#ddd;'>Employees:
<ul>
<li>Christophe Coenraets 617-123-4567</li>
<li>John Smith</li>
<li>Lisa Jones 617-111-2323</li>
</ul>
</div>
<p>&nbsp;</p>
<h4>Sample 10: Partials</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = {
	firstName: &quot;Christophe&quot;,
	lastName: &quot;Coenraets&quot;,
	address: &quot;1 Main street&quot;,
	city: &quot;Boston&quot;,
	state: &quot;MA&quot;,
	zip: &quot;02106&quot;
};

var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;{{&gt;address}}&quot;;
var partials = {address: &quot;&lt;p&gt;{{address}}&lt;/p&gt;{{city}}, {{state}} {{zip}}&quot;};
var html = Mustache.to_html(template, data, partials);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample10" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Christophe Coenraets</h1>
<p>1 Main street</p>
<p>Boston, MA 02106</p></div>
<p>&nbsp;</p>
<h4>Sample 11: Partials in Enumerable Section</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = { depts: [
	{	name: &quot;Engineering&quot;,
		employees: [
			{firstName: &quot;Christophe&quot;, lastName: &quot;Coenraets&quot;},
			{firstName: &quot;John&quot;, lastName: &quot;Smith&quot;}]
	},
	{	name: &quot;Sales&quot;,
		employees: [
			{firstName: &quot;Paula&quot;, lastName: &quot;Taylor&quot;},
			{firstName: &quot;Lisa&quot;, lastName: &quot;Jones&quot;}]
	}]
};

var tpl = &quot;{{#depts}}&lt;h1&gt;{{name}}&lt;/h1&gt;&quot; +
          &quot;&lt;ul&gt;{{#employees}}{{&gt;employee}}{{/employees}}&lt;/ul&gt;{{/depts}}&quot;;
var partials = {employee: &quot;&lt;li&gt;{{firstName}} {{lastName}}&lt;/li&gt;&quot;};
var html = Mustache.to_html(tpl, data, partials);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample11" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Engineering</h1>
<ul>
<li>Christophe Coenraets</li>
<li>John Smith</li>
</ul>
<h1>Sales</h1>
<ul>
<li>Paula Taylor</li>
<li>Lisa Jones</li>
</ul>
</div>
<p>&nbsp;</p>
<p>You can run all the examples <a href="http://coenraets.org/tutorials/mustache">here</a>.</p>
<p>&nbsp;</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Tutorial:%20HTML%20Templates%20with%20Mustache.js%20http://coenraets.org/blog/?p=2660" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tutorial: HTML Templates with Mustache.js</title>
		<link>http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/</link>
		<comments>http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 15:53:43 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org//blog/?p=2658</guid>
		<description><![CDATA[} When developing modern HTML applications, you often write a lot of HTML fragments programmatically. You concatenate HTML tags and dynamic data, and insert the resulting UI markup into the DOM. Here is a random code example of this approach: The proliferation of this kind of code throughout your application comes with some downsides. The [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Tutorial:%20HTML%20Templates%20with%20Mustache.js%20http://coenraets.org/blog/?p=2660" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p><span  style="color:black;-webkit-transform: rotate(-90deg);-moz-transform: rotate(-90deg);display: block;font-size: 250px;font-family: Georgia;text-align: center;margin: 40px;">}</span></p>
<p>When developing modern HTML applications, you often write a lot of HTML fragments programmatically. You concatenate HTML tags and dynamic data, and insert the resulting UI markup into the DOM. Here is a random code example of this approach:</p>
<pre class="brush: jscript; title: ; notranslate">
$.each(messages.reverse(), function(index, message) {
	$('#messageList').append(
		'&lt;li&gt;&lt;span class=&quot;list-title&quot;&gt;' +
		message.userName + '&lt;/span&gt;' +
		'&lt;abbr class=&quot;list-timestamp&quot; title=&quot;' +
		message.datePosted + '&quot;&gt;&lt;/abbr&gt;' +
		'&lt;p class=&quot;list-text&quot;&gt;' + message.messageText + '&lt;/p&gt;&lt;/li&gt;');
	}
});
</pre>
<p>The proliferation of this kind of code throughout your application comes with some downsides. The tight coupling of UI and data logic doesn&#8217;t promote separation of concerns and reuse. It makes your application harder to write and harder to maintain.<br />
<span id="more-2660"></span><br />
HTML templates address this issue by decoupling the UI definition (HTML markup) from the data. There are a number of HTML template solutions out there: jQuery Templates, Underscore.js, and <a href="https://github.com/janl/mustache.js">Mustache.js</a> to name a few. Mustache.js is a popular choice because of its powerful syntax and fast rendering.</p>
<p><a href="http://mustache.github.com/">Mustache</a> is a &#8220;logic-less&#8221; template syntax. &#8220;Logic-less&#8221; means that it doesn&#8217;t rely on procedural statements (if, else, for, etc.): Mustache templates are entirely defined with tags. Mustache is implemented in different languages: Ruby, JavaScript, Python, PHP, Perl, Objective-C, Java, .NET, Android, C++, Go, Lua, Scala, etc. <a href="https://github.com/janl/mustache.js">Mustache.js</a> is the JavaScript implementation.</p>
<p>In this article, we take a quick tour of some of the capabilities of Mustache.js.</p>
<p>To start using Mustache.js, simply add a script tag to your html file pointing to mustache.js which is available <a href="https://github.com/janl/mustache.js/blob/master/mustache.js">here</a>.</p>
<p>You can run all the examples below <a href="http://coenraets.org/tutorials/mustache">here</a>.</p>
<h4>Sample 1: Basic Template</h4>
<p>This is a self-explanatory example. Note that:</p>
<ul>
<li>Instead of being defined in a variable, the data often comes from a service call (see sample 2)</li>
<li>Instead of being defined in a variable, the template is often read from a file (see sample 3)</li>
</ul>
<pre class="brush: jscript; title: ; notranslate">
	var person = {
		firstName: &quot;Christophe&quot;,
		lastName: &quot;Coenraets&quot;,
		blogURL: &quot;http://coenraets.org&quot;
	};
	var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;Blog: {{blogURL}}&quot;;
	var html = Mustache.to_html(template, person);
	$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample1" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Christophe Coenraets</h1>
<p>Blog: http://coenraets.org</p></div>
<p>&nbsp;</p>
<h4>Sample 2: Basic Template using Ajax data</h4>
<p>Same as sample 1, except that we get the data from an Ajax service call.</p>
<pre class="brush: jscript; title: ; notranslate">
$.getJSON('json/data.json', function(data) {
	var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;Blog: {{blogURL}}&quot;;
	var html = Mustache.to_html(template, data);
	$('#sampleArea').html(html);
});
</pre>
<p>Result:</p>
<div id="sample2" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>John Smith</h1>
<p>Blog: http://johnsmith.com</p></div>
<p>&nbsp;</p>
<h4>Sample 3: Externalized Template</h4>
<p>Same as sample 2, except that we read the template from the main HTML file.</p>
<pre class="brush: jscript; title: ; notranslate">
$.getJSON('json/data2.json', function(data) {
	var template = $('#personTpl').html();
	var html = Mustache.to_html(template, data);
	$('#sampleArea').html(html);
});
</pre>
<p>The template is defined as follows in index.html:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script id=&quot;personTpl&quot; type=&quot;text/template&quot;&gt;
&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;
&lt;p&gt;Blog URL: &lt;a href=&quot;{{blogURL}}&quot;&gt;{{blogURL}}&lt;/a&gt;&lt;/p&gt;
&lt;/script&gt;
</pre>
<p>Result:</p>
<div id="sample3" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Lisa Jones</h1>
<p>Blog URL: <a href="http://lisajones.com">http://lisajones.com</a></p>
</div>
<p>&nbsp;</p>
<p><strong>NOTE:</strong> Sample 3 represents the way templates are being used in many dynamic Web applications:</p>
<ul>
<li>You get data from an Ajax service</li>
<li>You read the template from an external file
</ul>
<p>In the remaining of this article, we declare the data and the template in variables to keep the examples self-contained. Remember to refer to sample 3 for a traditional setup when using templates in a dynamic Web application.</p>
<p>&nbsp;</p>
<h4>Sample 4: Enumerable Section</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = {name: &quot;John Smith&quot;, skills: ['JavaScript', 'PHP', 'Java']};
var tpl = &quot;{{name}} skills:&lt;ul&gt;{{#skills}}&lt;li&gt;{{.}}&lt;/li&gt;{{/skills}}&lt;/ul&gt;&quot;;
var html = Mustache.to_html(tpl, data);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample4" style='border: solid 1px #ddd;background-color:#ddd;'>John Smith skills:
<ul>
<li>JavaScript</li>
<li>PHP</li>
<li>Java</li>
</ul>
</div>
<p>&nbsp;</p>
<h4>Sample 5: Enumerable Section with Objects</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = {
	employees: [
	{	firstName: &quot;Christophe&quot;,
		lastName: &quot;Coenraets&quot;},
	{	firstName: &quot;John&quot;,
		lastName: &quot;Smith&quot;}
	]};
var template = &quot;Employees:&lt;ul&gt;{{#employees}}&quot; +
                            &quot;&lt;li&gt;{{firstName}} {{lastName}}&lt;/li&gt;&quot; +
                            &quot;{{/employees}}&lt;/ul&gt;&quot;;
var html = Mustache.to_html(template, data);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample5" style='border: solid 1px #ddd;background-color:#ddd;'>Employees:
<ul>
<li>Christophe Coenraets</li>
<li>John Smith</li>
</ul>
</div>
<p>&nbsp;</p>
<h4>Sample 6: Nested Objects</h4>
<p>You can use the dot notation to access object properties.</p>
<pre class="brush: jscript; title: ; notranslate">
var person = {
	firstName: &quot;Christophe&quot;,
	lastName: &quot;Coenraets&quot;,
	blogURL: &quot;http://coenraets.org&quot;,
	manager : {
		firstName: &quot;John&quot;,
		lastName: &quot;Smith&quot;
	}
};
var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;&lt;p&gt;{{blogURL}}&lt;/p&gt;&quot; +
               &quot;Manager: {{manager.firstName}} {{manager.lastName}}&quot;;
var html = Mustache.to_html(template, person);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample6" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Christophe Coenraets</h1>
<p>http://coenraets.org</p>
<p>Manager: John Smith</p></div>
<p>&nbsp;</p>
<h4>Sample 7: Dereferencing</h4>
<p>Same as sample 6, except that we &#8220;dereference&#8221; the manager object to make it easier to access its properties (without having to use the dot notation).</p>
<pre class="brush: jscript; title: ; notranslate">
var person = {
	firstName: &quot;John&quot;,
	lastName: &quot;Smith&quot;,
	blogURL: &quot;http://johnsmith.com&quot;,
	manager : {
		firstName: &quot;Lisa&quot;,
		lastName: &quot;Jones&quot;
	}
};
var tpl = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;&lt;p&gt;{{blogURL}}&lt;/p&gt;&quot; +
          &quot;{{#manager}}Manager: {{firstName}} {{lastName}}{{/manager}}&quot;;
var html = Mustache.to_html(tpl, person);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample7" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>John Smith</h1>
<p>http://johnsmith.com</p>
<p>Manager: Lisa Jones</p></div>
<p>&nbsp;</p>
<h4>Sample 8: Function</h4>
<p>Templates can reference functions like totalPrice in this example.</p>
<pre class="brush: jscript; title: ; notranslate">
var product = {
	name: &quot;FooBar&quot;,
	price: 100,
	salesTax: 0.05,
	totalPrice: function() {
		return this.price + this.price * this.salesTax;
	}
};
var template = &quot;&lt;p&gt;Product Name: {{name}}&lt;/p&gt;Price: {{totalPrice}}&quot;;
var html = Mustache.to_html(template, product);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample8" style='border: solid 1px #ddd;background-color:#ddd;'>
<p>Product Name: FooBar</p>
<p>Price: 105</p></div>
<p>&nbsp;</p>
<h4>Sample 9: Condition</h4>
<p>Templates can include conditional sections. Conditional sections only render if the condition evaluates to true. A conditional section begins with {{#condition}} and ends with {{/condition}}. &#8220;condition&#8221; can be a boolean value or a function returning a boolean.</p>
<pre class="brush: jscript; title: ; notranslate">
var data = {
	employees: [
	{	firstName: &quot;Christophe&quot;,
		lastName: &quot;Coenraets&quot;,
		fullTime: true,
		phone: &quot;617-123-4567&quot;
	},
	{	firstName: &quot;John&quot;,
		lastName: &quot;Smith&quot;,
		fullTime: false,
		phone: &quot;617-987-6543&quot;
	},
	{	firstName: &quot;Lisa&quot;,
		lastName: &quot;Jones&quot;,
		fullTime: true,
		phone: &quot;617-111-2323&quot;
	},
	]};
var tpl = &quot;Employees:&lt;ul&gt;{{#employees}}&lt;li&gt;{{firstName}} {{lastName}}&quot; +
          &quot;{{#fullTime}} {{phone}}{{/fullTime}}&lt;/li&gt;{{/employees}}&lt;/ul&gt;&quot;;
var html = Mustache.to_html(tpl, data);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample9" style='border: solid 1px #ddd;background-color:#ddd;'>Employees:
<ul>
<li>Christophe Coenraets 617-123-4567</li>
<li>John Smith</li>
<li>Lisa Jones 617-111-2323</li>
</ul>
</div>
<p>&nbsp;</p>
<h4>Sample 10: Partials</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = {
	firstName: &quot;Christophe&quot;,
	lastName: &quot;Coenraets&quot;,
	address: &quot;1 Main street&quot;,
	city: &quot;Boston&quot;,
	state: &quot;MA&quot;,
	zip: &quot;02106&quot;
};

var template = &quot;&lt;h1&gt;{{firstName}} {{lastName}}&lt;/h1&gt;{{&gt;address}}&quot;;
var partials = {address: &quot;&lt;p&gt;{{address}}&lt;/p&gt;{{city}}, {{state}} {{zip}}&quot;};
var html = Mustache.to_html(template, data, partials);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample10" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Christophe Coenraets</h1>
<p>1 Main street</p>
<p>Boston, MA 02106</p></div>
<p>&nbsp;</p>
<h4>Sample 11: Partials in Enumerable Section</h4>
<pre class="brush: jscript; title: ; notranslate">
var data = { depts: [
	{	name: &quot;Engineering&quot;,
		employees: [
			{firstName: &quot;Christophe&quot;, lastName: &quot;Coenraets&quot;},
			{firstName: &quot;John&quot;, lastName: &quot;Smith&quot;}]
	},
	{	name: &quot;Sales&quot;,
		employees: [
			{firstName: &quot;Paula&quot;, lastName: &quot;Taylor&quot;},
			{firstName: &quot;Lisa&quot;, lastName: &quot;Jones&quot;}]
	}]
};

var tpl = &quot;{{#depts}}&lt;h1&gt;{{name}}&lt;/h1&gt;&quot; +
          &quot;&lt;ul&gt;{{#employees}}{{&gt;employee}}{{/employees}}&lt;/ul&gt;{{/depts}}&quot;;
var partials = {employee: &quot;&lt;li&gt;{{firstName}} {{lastName}}&lt;/li&gt;&quot;};
var html = Mustache.to_html(tpl, data, partials);
$('#sampleArea').html(html);
</pre>
<p>Result:</p>
<div id="sample11" style='border: solid 1px #ddd;background-color:#ddd;'>
<h1>Engineering</h1>
<ul>
<li>Christophe Coenraets</li>
<li>John Smith</li>
</ul>
<h1>Sales</h1>
<ul>
<li>Paula Taylor</li>
<li>Lisa Jones</li>
</ul>
</div>
<p>&nbsp;</p>
<p>You can run all the examples <a href="http://coenraets.org/tutorials/mustache">here</a>.</p>
<p>&nbsp;</p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Tutorial:%20HTML%20Templates%20with%20Mustache.js%20http://coenraets.org/blog/?p=2660" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fact Check Michele Bachmann with Politifact and Flex</title>
		<link>http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fact-check-michele-bachmann-with-politifact-and-flex</link>
		<comments>http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fact-check-michele-bachmann-with-politifact-and-flex#comments</comments>
		<pubDate>Fri, 16 Dec 2011 18:02:03 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=2629</guid>
		<description><![CDATA[During the GOP presidential debate last night, Michelle Bachmann said this: After the debate that we had last week, Politifact came out and said that everything I said was true. Did Politifact really give her a &#8220;True&#8221; rating across the board for a performance in the previous debate? The best way to check if you [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Fact%20Check%20Michele%20Bachmann%20with%20Politifact%20and%20Flex%20http://coenraets.org/blog/?p=2629" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p>During the GOP presidential debate last night, Michelle Bachmann said this:</p>
<blockquote><p>After the debate that we had last week, Politifact came out and said that everything I said was true.</p></blockquote>
<p>Did Politifact really give her a &#8220;True&#8221; rating across the board for a performance in the previous debate?</p>
<p>The best way to check if you are on the go, is to use Politifact’s mobile application which was built with Flex and runs on the iPhone, the iPad, the BlackBerry PlayBook, the Kindle Fire, the Barnes and Noble Nook, and other Android devices&#8230; using the exact same code. 100% code reusability.<br />
<span id="more-2629"></span></p>
<div style='float:right'>
<a href="http://coenraets.org/blog/wp-content/uploads/2011/12/tom-true.gif"><img src="http://coenraets.org/blog/wp-content/uploads/2011/12/tom-true.gif" alt="" title="tom-true" width="84" height="75" class="alignnone size-full wp-image-2641" /></a>
</div>
<p><strong>100% Code Reusability</strong><br />
I’ll let you check Michelle Bachmann statements in Politifact’s Mobile app, but since I helped build it, I can tell you that the 100% Flex code reusability across devices statement is absolutely “True”!</p>
<p>The Politifact Mobile application is available in the following app stores:</p>
<p><a href="http://itunes.apple.com/us/app/politifact-mobile/id444548650">Apple App Store</a><br />
<a href="https://market.android.com/details?id=air.com.tampabay.Politifact">Android Market</a><br />
<a href="http://www.amazon.com/Times-Publishing-Company-Politifact-Mobile/dp/B005FHP5K8">Amazon App Store</a><br />
<a href="http://appworld.blackberry.com/webstore/content/49265?lang=en">BlackBerry App World</a><br />
<a href="http://www.barnesandnoble.com/s/politifact-mobile?dref=6455">Barnes and Noble Nook Store</a></p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2011/12/photo1.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2011/12/photo1.jpg" alt="" title="photo" width="320" height="480" class="alignnone size-full wp-image-2656" /></a></p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Fact%20Check%20Michele%20Bachmann%20with%20Politifact%20and%20Flex%20http://coenraets.org/blog/?p=2629" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fact Check Michele Bachmann with Politifact and Flex</title>
		<link>http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/</link>
		<comments>http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 18:02:03 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[blogs]]></category>

		<guid isPermaLink="false">http://coenraets.org//blog/?p=2629</guid>
		<description><![CDATA[During the GOP presidential debate last night, Michelle Bachmann said this: After the debate that we had last week, Politifact came out and said that everything I said was true. Did Politifact really give her a &#8220;True&#8221; rating across the board for a performance in the previous debate? The best way to check if you [...]
	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Fact%20Check%20Michele%20Bachmann%20with%20Politifact%20and%20Flex%20http://coenraets.org/blog/?p=2629" target="_blank">Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/" target="_blank">Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");]]></description>
			<content:encoded><![CDATA[<p>During the GOP presidential debate last night, Michelle Bachmann said this:</p>
<blockquote><p>After the debate that we had last week, Politifact came out and said that everything I said was true.</p></blockquote>
<p>Did Politifact really give her a &#8220;True&#8221; rating across the board for a performance in the previous debate?</p>
<p>The best way to check if you are on the go, is to use Politifact’s mobile application which was built with Flex and runs on the iPhone, the iPad, the BlackBerry PlayBook, the Kindle Fire, the Barnes and Noble Nook, and other Android devices&#8230; using the exact same code. 100% code reusability.<br />
<span id="more-2629"></span></p>
<div style='float:right'>
<a href="http://coenraets.org/blog/wp-content/uploads/2011/12/tom-true.gif"><img src="http://coenraets.org/blog/wp-content/uploads/2011/12/tom-true.gif" alt="" title="tom-true" width="84" height="75" class="alignnone size-full wp-image-2641" /></a>
</div>
<p><strong>100% Code Reusability</strong><br />
I’ll let you check Michelle Bachmann statements in Politifact’s Mobile app, but since I helped build it, I can tell you that the 100% Flex code reusability across devices statement is absolutely “True” <img src='http://coenraets.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The Politifact Mobile application is available in the following app stores:</p>
<p><a href="http://itunes.apple.com/us/app/politifact-mobile/id444548650">Apple App Store</a><br />
<a href="https://market.android.com/details?id=air.com.tampabay.Politifact">Android Market</a><br />
<a href="http://www.amazon.com/Times-Publishing-Company-Politifact-Mobile/dp/B005FHP5K8">Amazon App Store</a><br />
<a href="http://appworld.blackberry.com/webstore/content/49265?lang=en">BlackBerry App World</a><br />
<a href="http://www.barnesandnoble.com/s/politifact-mobile?dref=6455">Barnes and Noble Nook Store</a></p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2011/12/photo1.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2011/12/photo1.jpg" alt="" title="photo" width="320" height="480" class="alignnone size-full wp-image-2656" /></a></p>

	
<!-- Start WP Socializer Plugin - Retweet Button -->
<a href="http://twitter.com/?status=RT%20@%20Fact%20Check%20Michele%20Bachmann%20with%20Politifact%20and%20Flex%20http://coenraets.org/blog/?p=2629" >Retweet this</a>
<!-- End WP Socializer Plugin - Retweet Button -->

	
	
<!-- Start WP Socializer Plugin - Facebook Button -->
<a href="https://www.facebook.com/sharer.php?u=http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/" >Share on Facebook</a>
<!-- End WP Socializer Plugin - Facebook Button -->



Follow @ccoenraets
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2011/12/fact-check-michele-bachmann-with-politifact-and-flex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

