<?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>Christophe Coenraets</title>
	<atom:link href="http://coenraets.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://coenraets.org/blog</link>
	<description>Web Platform, Cloud and Mobile Application Development</description>
	<lastBuildDate>Mon, 13 May 2013 16:05:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Architecting a PhoneGap Application: Video + Slides</title>
		<link>http://coenraets.org/blog/2013/05/architecting-a-phonegap-application-video-slides/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=architecting-a-phonegap-application-video-slides</link>
		<comments>http://coenraets.org/blog/2013/05/architecting-a-phonegap-application-video-slides/#comments</comments>
		<pubDate>Mon, 13 May 2013 16:04:34 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[PhoneGap]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5934</guid>
		<description><![CDATA[Here is the video of my PhoneGap Architecture talk at Adobe MAX 2013: The slides are available here.]]></description>
				<content:encoded><![CDATA[<p>Here is the video of my PhoneGap Architecture talk at Adobe MAX 2013:</p>
<p><iframe title="AdobeTV Video Player" width="640" height="367" src="http://tv.adobe.com/embed/1217/18503/" frameborder="0" allowfullscreen scrolling="no"></iframe></p>
<p>The slides are available <a href="http://coenraets.org/slides/MAX2013_Architecting_Phonegap_Apps.pdf">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/05/architecting-a-phonegap-application-video-slides/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Top 10 Performance Techniques for PhoneGap Applications</title>
		<link>http://coenraets.org/blog/2013/05/top-10-performance-techniques-for-phonegap-applications/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=top-10-performance-techniques-for-phonegap-applications</link>
		<comments>http://coenraets.org/blog/2013/05/top-10-performance-techniques-for-phonegap-applications/#comments</comments>
		<pubDate>Mon, 13 May 2013 15:49:32 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[PhoneGap]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5929</guid>
		<description><![CDATA[Here is the video of my PhoneGap performance session at Adobe MAX 2013:]]></description>
				<content:encoded><![CDATA[<p>Here is the video of my PhoneGap performance session at Adobe MAX 2013:</p>
<p><iframe title="AdobeTV Video Player" width="640" height="367" src="http://tv.adobe.com/embed/1217/18425/" frameborder="0" allowfullscreen scrolling="no"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/05/top-10-performance-techniques-for-phonegap-applications/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Building Pluggable and Mock Data Adapters for Web and PhoneGap Applications</title>
		<link>http://coenraets.org/blog/2013/04/building-pluggable-and-mock-data-adapters-for-web-and-phonegap-applications/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=building-pluggable-and-mock-data-adapters-for-web-and-phonegap-applications</link>
		<comments>http://coenraets.org/blog/2013/04/building-pluggable-and-mock-data-adapters-for-web-and-phonegap-applications/#comments</comments>
		<pubDate>Tue, 23 Apr 2013 17:01:09 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PhoneGap]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5689</guid>
		<description><![CDATA[This is not rocket science, but when planning your web or mobile architecture, it is important to make sure your client application is not tightly coupled to a specific data access strategy. The Problem In tightly coupled applications, the presentation logic is intertwined with data access logic (for example, $.ajax() calls), and it leads to [...]]]></description>
				<content:encoded><![CDATA[<p>This is not rocket science, but when planning your web or mobile architecture, it is important to make sure your client application is not tightly coupled to a specific data access strategy. </p>
<h3>The Problem</h3>
<p>In tightly coupled  applications, the presentation logic is intertwined with data access logic (for example, $.ajax() calls), and it leads to some of the problems below:</p>
<ol>
<li>Slows down the development process. Client side developers often have to wait for services to be built. The back and forth between client side and server side development hampers fast iterations.</li>
<li>Hard to test. It&#8217;s hard to unit test a client application that is hard-wired to server components.</li>
<li>Hampers the designer or developer creativity. It can be hard for the designer or client side developer to think creatively about the User Experience if he or she is constrained by a set of pre-existing data services.</li>
<li>Hard to change. Changing the data access strategy requires major changes in the client code.</li>
<li>Hard to switch the data access strategy on the fly. For example when the application connectivity status changes from online to offline.</li>
</ol>
<h3>The Solution: Pluggable Data Adapters</h3>
<p>The solution is of course to decouple the client code from a specific data access strategy. Practically, this goal can be achieved by using pluggable data adapters.</p>
<p>I often start with an in-memory (or mock data) adapter that allows me to iterate quickly at the client side while the server side may not even exist yet. Later on, I can unplug the in-memory adapter and plug in an Ajax adapter to run my application against actual server data, or a WebSQL (or IndexedDB) adapter to run it against an embedded database. </p>
<p>There are many strategies to implement data adapters, and a complete review of these strategies is beyond the scope of this article. Here is a basic approach&#8230;</p>
<h3>Define a Common Interface</h3>
<p>To be interchangeable, your adapters have to expose a common API. Here is a simple example for an Employee Directory use case:</p>
<pre class="brush: jscript; title: ; notranslate">
function initialize() {}; // Some adapters may require initialization.  

function findByName(key) {};

function findById(id) {};
</pre>
<h3>Assume Asynchronous</h3>
<p>In addition to defining methods with the same name, part of defining a common interface is also to use a common method invocation approach. For example, your in-memory and Ajax adapters wouldn&#8217;t be interchangeable if the in-memory adapter assumed <em>synchronous</em> method invocation and the Ajax adapter assumed <em>asynchronous</em> invocation. A good approach is to provide all your adapters with an asynchronous API. Fortunately, Deferred Objects and Promises make it really easy to work with asynchronous operations. There are different implementations of Deferred Objects and Promises. In the example below, we will use the <a href="http://api.jquery.com/jQuery.Deferred/">jQuery implementation</a>.</p>
<h3>In-Memory Adapter Example</h3>
<p>In this adapter, we work with mock data held in a private array. The public API methods return a promise that is resolved immediately (since looping through an array is a synchronous operation).</p>
<p><script src="https://gist.github.com/ccoenraets/5443777.js?file=memory-adapter.js"></script></p>
<h3>JSONP Adapter Example</h3>
<p>In this adapter, we get the data from RESTful services using JSONP. The $.ajax() method returns a jqXHR object which implements the Promise interface. </p>
<p><script src="https://gist.github.com/ccoenraets/5443777.js?file=jsonp-adapter.js"></script></p>
<h3>The Client Application</h3>
<p>Depending on the adapter you want to use, you import either memory-adapter.js or jsonp-adpater.js in index.html. You then instantiate the appropriate adapter on line 16 and you don&#8217;t have to change anything else in the application.</p>
<p><script src="https://gist.github.com/ccoenraets/5443777.js?file=app.js"></script></p>
<h3>Source Code and Additional Adapters</h3>
<p>The source code for this simple implementation of data adapters is available in <a href="https://github.com/ccoenraets/javascript-data-adapters">this</a> GitHub repository. The repository includes the following adapters:</p>
<ul>
<li>In-Memory Adapter</li>
<li>LocalStorage Adapter</li>
<li>WebSQL Adapter</li>
<li>JSONP Adapter</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/04/building-pluggable-and-mock-data-adapters-for-web-and-phonegap-applications/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sample App: Storing your Application Data in the Cloud with Parse.com and the JavaScript SDK</title>
		<link>http://coenraets.org/blog/2013/04/sample-app-storing-your-application-data-in-the-cloud-with-parse-com-and-the-javascript-sdk/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-app-storing-your-application-data-in-the-cloud-with-parse-com-and-the-javascript-sdk</link>
		<comments>http://coenraets.org/blog/2013/04/sample-app-storing-your-application-data-in-the-cloud-with-parse-com-and-the-javascript-sdk/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 16:54:14 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Backbone.js]]></category>
		<category><![CDATA[Parse.com]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5629</guid>
		<description><![CDATA[A couple of days ago, I shared a new version of the Employee Directory sample application. By default, the application uses an in-memory data store to provide a “download and run” experience (no need to set up a server or a database). In this post, I’ll show how to replace the in-memory data store with [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/04/employee-directory-parse.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/employee-directory-parse.jpg" alt="" title="employee-directory-parse" width="640" height="462" class="alignleft size-full wp-image-5659" /></a></p>
<p>A couple of days ago, I shared a new version of the <a href="http://coenraets.org/blog/2013/04/sample-application-with-backbone-js-and-twitter-bootstrap-updated-and-improved/">Employee Directory</a> sample application. By default, the application uses an in-memory data store to provide a “download and run” experience (no need to set up a server or a database). In this post, I’ll show how to replace the in-memory data store with a database hosted on Parse.com.</p>
<h4>Step 1: Sign Up for Parse.com</h4>
<p>Go to <a href="http://parse.com">http://parse.com</a> and sign up for Parse.</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/04/parse1.gif"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/parse1.gif" alt="" title="parse1" width="640" height="340" class="alignleft size-full wp-image-5634" /></a></p>
<h4>Step 2: Create an Application</h4>
<p>On the next screen, create an application as follows:</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/04/parse22.gif"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/parse22.gif" alt="" title="parse2" width="640" height="340" class="alignleft size-full wp-image-5640" /></a></p>
<h4>Step 3: Get your Application Keys</h4>
<p>In the dashboard, go to Settings and grab the Application ID and the JavaScript key.</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/04/parse3.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/parse3.jpg" alt="" title="parse3" width="640" height="393" class="alignleft size-full wp-image-5642" /></a></p>
<h4>Step 4: Populate the Database</h4>
<p>There are two ways to populate the database:</p>
<ol>
<li>Import a .json, .csv, .xls, or .txt file from the Data Browser interface. This approach works well for simple data structures.</li>
<li>Programmatically, using the the Parse SDK.</li>
</ol>
<p>For the employee directory application I wrote the quick script below to populate the database:</p>
<p><script src="https://gist.github.com/ccoenraets/5421386.js"></script></p>
<h4>Step 5: Run the Employee Directory App using the Parse.com Cloud Data</h4>
<ol>
<li>Download the source code for the Employee Directory client application available in <a href="https://github.com/ccoenraets/directory-backbone-bootstrap">this</a> repository.</li>
<li>Extract the application files to a directory you can reach using a local or hosted web server.<br />
<div class="woo-sc-box note   ">
Because the templates of this application are loaded using XMLHTTPRequest, you will get a cross domain error (Access-Control-Allow-Origin) if you load index.html from the file system (with the file:// protocol). Make sure you load the application from a web server. For example: http://localhost/directory-backbone-bootstrap.<br />
</div>
</li>
<li>Open index.html in your code editor.</li>
<li>Comment out the &#8220;model-in-memory.js&#8221; script, and uncomment the &#8220;parse-1.2.2.min.js&#8221; and &#8220;model-parse-com.js&#8221; scripts.</li>
<li>Open index.html in a Browser and test the application.</li>
</ol>
<h4>Step 6: Secure the Database</h4>
<p>Parse.com offers different security options. A complete discussion of these options is beyond the scope of this article. Since Employee Directory is a read-only and public application, we will simply:</p>
<p>1. Prevent client class creation (In Settings > General Settings):<br />
<a href="http://coenraets.org/blog/wp-content/uploads/2013/04/parse-security1b.gif"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/parse-security1b.gif" alt="" title="parse-security1b" width="636" height="186" class="alignleft size-full wp-image-5672" /></a></p>
<p>2. Disable create, update, delete operations (In Data Browser > More > Set Permissions):</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/04/parse-security2.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/parse-security2.jpg" alt="" title="parse-security2" width="640" height="458" class="alignleft size-full wp-image-5666" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/04/sample-app-storing-your-application-data-in-the-cloud-with-parse-com-and-the-javascript-sdk/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Implementing RESTFul Services with Node.js and MongoDB</title>
		<link>http://coenraets.org/blog/2013/04/implementing-restful-services-with-node-js-and-mongodb/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=implementing-restful-services-with-node-js-and-mongodb</link>
		<comments>http://coenraets.org/blog/2013/04/implementing-restful-services-with-node-js-and-mongodb/#comments</comments>
		<pubDate>Thu, 18 Apr 2013 17:04:19 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Backbone.js]]></category>
		<category><![CDATA[Express]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Node.js]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5516</guid>
		<description><![CDATA[In my previous post, I shared a new version of the Employee Directory sample application. By default, the application uses an in-memory data store to provide a &#8220;download and run&#8221; experience (no need to set up a server or a database). In this post, I&#8217;ll show how to replace the in-memory data store with RESTful [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/04/nodejs-mongodb.png"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/nodejs-mongodb.png" alt="" title="nodejs-mongodb" width="640" height="120" class="alignleft size-full wp-image-5614" /></a><br />
In my <a href="http://coenraets.org/blog/2013/04/sample-application-with-backbone-js-and-twitter-bootstrap-updated-and-improved/">previous post</a>, I shared a new version of the Employee Directory sample application. By default, the application uses an in-memory data store to provide a &#8220;download and run&#8221; experience (no need to set up a server or a database). In this post, I&#8217;ll show how to replace the in-memory data store with RESTful services powered by Node.js, MongoDB and the Express framework. </p>
<div class="woo-sc-box info   ">
If you are not using the Employee Directory sample application, you can still use this post on its own to learn how to implement RESTful services with Node.js, MongoDB and the Express framework.<br />
</div>
<h4>Step 1: Install Node.js</h4>
<p>If it&#8217;s not already installed on your system, follow the steps below to install Node.js:</p>
<ol>
<li>Go to <a href="http://nodejs.org">http://nodejs.org</a>, and click the <em>Install</em> button.</li>
<li>Run the installer that you just downloaded. When the installer completes, a message indicates that <em>Node was installed at /usr/local/bin/node</em> and <em>npm was installed at /usr/local/bin/npm</em>. At this point node.js is ready to use.</li>
</ol>
<h4>Step 2: Install MongoDB</h4>
<p>If MongoDB is not already installed on your system, refer to the <a href="http://www.mongodb.org/display/DOCS/Quickstart">MongoDB QuickStart</a> for platform-specific installation instructions. Here are some quick steps to install MongoDB on a Mac:</p>
<ol>
<li>Go to <a href="http://www.mongodb.org/downloads">http://www.mongodb.org/downloads</a> and download the latest OS X 64-bit production release (2.4.2 at the time of this writing).</li>
<li>In Finder, double-click mongodb-osx-x86_64-2.4.2.tgz to extract its contents. (Alternatively you can use: tar -zxvf mongodb-osx-x86_64-2.4.2.tgz)</li>
<li>Move the mongodb-osx-x86_64-2.4.2 folder to /usr/local (or another folder according to your personal preferences):
<pre class="brush: bash; light: true; title: ; notranslate">
sudo mv -n mongodb-osx-x86_64-2.4.2/ /usr/local/
</pre>
</li>
<li>(Optional) Create a symbolic link to make it easier to access:
<pre class="brush: bash; light: true; title: ; notranslate">
sudo ln -s /usr/local/mongodb-osx-x86_64-2.4.2 /usr/local/mongodb
</pre>
</li>
<li>Create a folder for MongoDB&#8217;s data and set the appropriate permissions:
<pre class="brush: bash; light: true; title: ; notranslate">
sudo mkdir -p /data/db
sudo chown `id -u` /data/db
</pre>
</li>
<li>Start mongodb
<pre class="brush: bash; light: true; title: ; notranslate">
cd /usr/local/mongodb
./bin/mongod
</pre>
</li>
</ol>
<h4>Step 3: Download the Code</h4>
<p>The Node.js code for the Employee Directory RESTful services is available in <a href="https://github.com/ccoenraets/directory-rest-nodejs">this<a/> GitHub repository. Download it <a href="https://github.com/ccoenraets/directory-rest-nodejs/archive/master.zip">here</a> and unzip the file anywhere on your file system.</p>
<p>Open server.js and routes/employee.js in a code editor. The RESTFul API is defined as follows:</p>
<table style="margin-bottom:24px;">
<tr>
<th>Method</th>
<th>URL</th>
<th>Action</th>
</tr>
<tr>
<td>GET</td>
<td>/employees</td>
<td>Retrieve all employees</td>
</tr>
<tr>
<td>GET</td>
<td>/employees?name=j</td>
<td>Retrieve employees whose name includes the letter &#8220;j&#8221;</td>
</tr>
<tr>
<td>GET</td>
<td>/employees/3</td>
<td>Retrieve employee with id=3</td>
</tr>
<tr>
<td>GET</td>
<td>/employees/3/reports</td>
<td>Retrieve employees that are direct reports of employee number 3</td>
</tr>
</table>
<div class="woo-sc-box info   ">
In routes/employee.js, the use of res.jsonp() makes the services work for both JSON and JSONP requests. If the request includes a query parameter named “callback”, a JSONP response is returned, otherwise, a regular JSON response is returned.<br />
</div>
<h4>Step 4: Install dependencies (Express Framework and MongoDB driver)</h4>
<p>Open package.json in a code editor and note that the application has two dependencies: the Express framework and the MongoDB driver. To install these dependencies, open a command line (terminal window), cd to the directory where you extracted the source code, and type:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
npm install
</pre>
<h4>Step 5: Start the server</h4>
<p>Make sure MongoDB is started (Step 2 point 6 above) before you start your Node.js server as follows:</p>
<pre class="brush: bash; light: true; title: ; notranslate">
node server.js
</pre>
<h4>Step 6: Testing the API in your Browser</h4>
<ul>
<li>Retrieve all employees
<p><a href="http://localhost:3000/employees">http://localhost:3000/employees</a></p>
</li>
<li>Retrieve all employees whose name includes the letter &#8220;j&#8221;
<p><a href="http://localhost:3000/employees?name=j">http://localhost:3000/employees?name=j</a></p>
</li>
<li>Retrieve employee with id == 1
<p><a href="http://localhost:3000/employees/1">http://localhost:3000/employees/1</a></p>
</li>
<li>Retrieve employees that are direct reports of employee number 1
<p><a href="http://localhost:3000/employees/1/reports">http://localhost:3000/employees/1/reports</a></p>
</li>
</ul>
<h4>Step 7: Test the API with the Employee Directory Client Application</h4>
<ol>
<li>Download the source code for the Employee Directory client application available in <a href="https://github.com/ccoenraets/directory-backbone-bootstrap">this</a> repository.</li>
<li>Unzip the file anywhere on your file system.</li>
<li>Open index.html in your code editor.</li>
<li>Comment out the &#8220;model-in-memory.js&#8221; script, and uncomment the &#8220;model-jsonp.js&#8221; script to use the JSONP adapter that connects to your Node.js server.</li>
<li>Make sure the MongoDB and Node.js servers are started</li>
<li>Open index.html in a Browser and test the application</li>
</ol>
<div class="woo-sc-box note   ">
Because the templates of this application are loaded using XMLHTTPRequest, you will get a cross domain error (Access-Control-Allow-Origin) if you load index.html from the file system (with the file:// protocol). Make sure you load the application from a web server. For example: http://localhost/directory-backbone-bootstrap.<br />
</div>
<h4>Related Post</h4>
<p>Check out <a href="http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/">this post</a> for another Node.js example with a more complete RESTful API including the ability to add, modify and delete items (POST, PUT, and DELETE HTTP methods). </p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/04/implementing-restful-services-with-node-js-and-mongodb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sample Application with Backbone.js and Twitter Bootstrap: Updated and Improved</title>
		<link>http://coenraets.org/blog/2013/04/sample-application-with-backbone-js-and-twitter-bootstrap-updated-and-improved/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sample-application-with-backbone-js-and-twitter-bootstrap-updated-and-improved</link>
		<comments>http://coenraets.org/blog/2013/04/sample-application-with-backbone-js-and-twitter-bootstrap-updated-and-improved/#comments</comments>
		<pubDate>Wed, 17 Apr 2013 15:27:49 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Backbone.js]]></category>
		<category><![CDATA[Twitter Bootstrap]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5183</guid>
		<description><![CDATA[A year ago, I blogged Employee Directory, a sample application that demonstrates how to build modern web apps with Backbone.js and Twitter Bootstrap. With 1200+ stars and 300+ forks on GitHub, it has been my most popular sample application to date. Because of the continued interest in the application as a starting point and a [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://coenraets.org/directory/"><img src="http://coenraets.org/blog/wp-content/uploads/2013/04/directory-screenshot3.gif" alt="" title="directory-screenshot3" width="640" height="554" class="alignleft size-full wp-image-5422" /></a></p>
<p>A year ago, I blogged <a href="http://coenraets.org/blog/2012/02/sample-app-with-backbone-js-and-twitter-bootstrap/">Employee Directory</a>, a sample application that demonstrates how to build modern web apps with <a href="http://backbonejs.org/">Backbone.js</a> and <a href="http://twitter.github.io/bootstrap/">Twitter Bootstrap</a>. With 1200+ stars and 300+ forks on GitHub, it has been my most popular sample application to date. </p>
<p>Because of the continued interest in the application as a starting point and a reference for Backbone.js and Twitter Bootstrap, I decided to give it a well deserved update.</p>
<p>New in this version:</p>
<ul>
<li>Latest version of Backbone.js (1.0)</li>
<li>Latest version of Twitter Bootstrap (2.3.1)</li>
<li>Layout is now responsive</li>
<li>Data persistence layer is now abstracted (see below)</li>
<li>Additional data persistence options: In-memory datastore, Node.js/MongoDB, Parse.com (In addition to PHP and Java)</li>
<li>New GitHub repository organization (see below)</li>
<li>Bug fixes and cleaner code</li>
</ul>
<h3>Running the Application</h3>
<p>You can test the hosted version of the application <a href="http://coenraets.org/directory/">here</a>, or you can download the code (see GitHub repository information below) and test the application locally.</p>
<h3>Data Persistence Abstraction</h3>
<p>Among the great feedback I received, a number of you mentioned you wanted a self-contained version of the app with no dependency on a specific back end to be able to &#8220;download and run&#8221; without having to set up a server and a database. So I rearchitected the persistence layer with simple and pluggable data adapters. By default the application now uses an in-memory data store, but other adapters are available. To change the data persistence strategy, just comment out model-in-memory.js in index.html and uncomment one of the other data adapters using the table below as a reference.</p>
<p>I initially published the application with two implementations of a RESTful back end: A Java version using Jersey, and a PHP version using Slim.  A year later, I&#8217;m adding the long overdue Node.js/MongoDB back end.</p>
<table>
<tr style="font-weight:bold;">
<td>Adapter</td>
<td>Description</td>
<td>Back end Repo</td>
</tr>
<tr>
<td style="width:140px">model-in-memory.js</td>
<td>In-memory data store</td>
<td style="width:170px">No server required</td>
</tr>
<tr>
<td>model-rest-json.js</td>
<td>Backbone.js default behavior. The application gets data through RESTFul services.</td>
<td><a href="https://github.com/ccoenraets/directory-rest-nodejs">directory-server-nodejs</a><br/><br />
<a href="https://github.com/ccoenraets/directory-rest-php">directory-server-php</a><br/><br />
directory-server-java
</td>
</tr>
<tr>
<td>model-rest-jsonp.js</td>
<td>If the server serving your pages and the server serving your data are on different domains, use this adapter instead to avoid the same origin policy error.</td>
<td><a href="https://github.com/ccoenraets/directory-rest-nodejs">directory-server-nodejs</a><br/><br />
<a href="https://github.com/ccoenraets/directory-rest-php">directory-server-php</a><br/><br />
directory-server-java
</td>
</tr>
<tr>
<td>model-websql.js</td>
<td>Uses local database using the WebSQL api.</td>
<td>No server required</td>
</tr>
<tr>
<td>model-parse-dot-com.js</td>
<td>Don&#8217;t want to host your own data infrastructure? Parse.com is a cloud service that will host your data for you. Use this adapter to test your app with  sample data I deployed on Parse.com.</td>
<td>No server required</td>
</tr>
</table>
<p>The Node.js, Java, and PHP RESTful back ends work with both JSON and JSONP. If the request includes a query parameter named &#8220;callback&#8221;, a JSONP response is returned, otherwise, a regular JSON response is returned.</p>
<h3>New GitHub Repositories</h3>
<p>The original repository (<a href="https://github.com/ccoenraets/backbone-directory">backbone-directory</a>) grew somewhat chaotically as I kept adding different versions and different data persistence options. So I decided to start fresh with new repositories.</p>
<p>The client code for the application is available in the new <a href="https://github.com/ccoenraets/directory-backbone-bootstrap">directory-backbone-bootstrap</a> repository. In the future, this new repository naming scheme will allow me to add different versions of the app (for example, directory-backbone-foundation or directory-angular-bootstrap)  while keeping each repository clean and focused. </p>
<div class="woo-sc-box note   ">
Because the templates of this application are loaded using XMLHTTPRequest, you will get a cross domain error (Access-Control-Allow-Origin) if you load index.html from the file system (with the file:// protocol). Make sure you load the application from a web server. For example: http://localhost/directory-backbone-bootstrap.<br />
</div>
<p>If you want to go beyond the in-memory datastore, you can download the REST services in the following repositories:</p>
<p><a href="https://github.com/ccoenraets/directory-rest-nodejs">directory-rest-nodejs</a> (Node.js/MongoDB implementation)<br />
<a href="https://github.com/ccoenraets/directory-rest-php">directory-rest-php</a> (PHP implementation)<br />
directory-rest-java (Java implementation coming soon)</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/04/sample-application-with-backbone-js-and-twitter-bootstrap-updated-and-improved/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Sociogram Mobile: A Starter-Kit Application for PhoneGap and Facebook Integration</title>
		<link>http://coenraets.org/blog/2013/03/sociogram-mobile-a-starter-kit-application-for-phonegap-and-facebook-integration/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sociogram-mobile-a-starter-kit-application-for-phonegap-and-facebook-integration</link>
		<comments>http://coenraets.org/blog/2013/03/sociogram-mobile-a-starter-kit-application-for-phonegap-and-facebook-integration/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 18:21:37 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[PhoneGap]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5131</guid>
		<description><![CDATA[A few weeks ago I shared Sociogram, a sample application that demonstrates how to use the Facebook JavaScript SDK and the Graph API. A number of people have asked me for a Mobile version of the application. So here is Sociogram Mobile: a sample application that demonstrates how to integrate Facebook social features in a [...]]]></description>
				<content:encoded><![CDATA[<p>A few weeks ago I shared <a href="http://coenraets.org/blog/2013/02/sociogram-a-sample-application-exploring-the-facebook-sdk-and-the-graph-api/">Sociogram</a>, a sample application that demonstrates how to use the Facebook JavaScript SDK and the Graph API. A number of people have asked me for a Mobile version of the application. So here is Sociogram Mobile: a sample application that demonstrates how to integrate Facebook social features in a PhoneGap application.   </p>
<p>Specifically, the application demonstrates:</p>
<ul>
<li>How to login and request permisssions</li>
<li>How to access your profile, friends, and feed</li>
<li>How to access a list of friends</li>
<li>How to access a friend&#8217;s profile, friends, mutual friends, and feed</li>
<li>How to post a message to your feed using a custom UI or using the Facebook native dialogs</li>
<li>How to revoke the permissions granted to the application (useful during development)</li>
</ul>
<p>Here are a few screenshots:</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_home.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_home.jpg" alt="" title="sociogram_home" width="320" height="478" class="alignleft size-full wp-image-5159" /><br/><br/></a><br />
<span id="more-5131"></span><br />
<a href="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_menu.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_menu.jpg" alt="" title="sociogram_menu" width="320" height="478" class="alignleft size-full wp-image-5160" /></a></p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_profile.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_profile.jpg" alt="" title="sociogram_profile" width="320" height="478" class="alignleft size-full wp-image-5157" /></a></p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_post2.gif"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_post2.gif" alt="" title="sociogram_post2" width="320" height="478" class="alignleft size-full wp-image-5154" /></a></p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_feed.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/sociogram_feed.jpg" alt="" title="sociogram_feed" width="320" height="478" class="alignleft size-full wp-image-5161" /></a></p>
<h3 style="clear:both;">Source Code</h3>
<p>The source code is available in <a href="https://github.com/ccoenraets/sociogram-mobile">this GitHub repository</a>. This is still work in progress and I&#8217;ve only tested the app on iOS at this point. I&#8217;ll continue to update the code: there are things that can be polished and things that can be added. </p>
<h3>Libraries</h3>
<p>The application is buil using the following libraries:</p>
<ul>
<li><a href="https://github.com/phonegap/phonegap-facebook-plugin">The Facebook plugin for PhoneGap</a></li>
<li><a href="http://backbonejs.org/">Backbone.js</a></li>
<li><a href="http://maker.github.com/ratchet/">Ratchet</a></li>
<li><a href="https://github.com/ftlabs/fastclick">Fastclick</a></li>
<li><a href="http://jquery.com/">jQuery</a></li>
<li><a href="http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/">PageSlider</a></li>
</ul>
<p>These dependencies (except the first one) can easily be removed to work with your own stack.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/03/sociogram-mobile-a-starter-kit-application-for-phonegap-and-facebook-integration/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Hardware-Accelerated Page Transitions for Mobile Web Apps / PhoneGap Apps</title>
		<link>http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps</link>
		<comments>http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/#comments</comments>
		<pubDate>Mon, 18 Mar 2013 18:01:05 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[css]]></category>
		<category><![CDATA[PhoneGap]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5027</guid>
		<description><![CDATA[I have been delivering a few PhoneGap Architecture and Performance talks in recent weeks. One of the performance techniques I talk about is &#8211;no surprise&#8211; the use of Hardware (GPU) Accelerated animations when available on the device. A typical example in a mobile application, is to hardware accelerate your page transitions. Even though this capability [...]]]></description>
				<content:encoded><![CDATA[<p>I have been delivering a few PhoneGap Architecture and Performance talks in recent weeks. One of the performance techniques I talk about is &#8211;no surprise&#8211; the use of Hardware (GPU) Accelerated animations when available on the device. A typical example in a mobile application, is to hardware accelerate your page transitions. Even though this capability has been around for some time now, I still get a lot of questions about it. So I figured I would discuss it in this blog post.</p>
<h3>Basic Infrastructure</h3>
<p>Here is a typical set up for sliding pages in an out of the viewport in a mobile app:</p>
<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/pageslider2.png"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/pageslider2.png" alt="" title="pageslider2" width="640" height="264" class="alignleft size-full wp-image-5108" /></a></p>
<p>The white box in the middle represents the browser viewport (the window through which the visible part of the document is seen): that is where the current page of your app is displayed at the full (100%) width and height of the viewport.<br />
<span id="more-5027"></span><br />
A page can be positioned to the left or to the right of the viewport by setting its &#8220;x&#8221; coordinate to -100% or 100% respectively (100% representing the viewport width). This can be done using two different approaches as explained below.</p>
<p>To slide a page from the right, you would:</p>
<ol>
<li>Position the page at the starting position of the transition (right)</li>
<li>If needed, force a reflow to anchor the page at its starting position.
<li>Finally, position the page at the ending position of the transition (center) with the <span style="font-family:'Courier New'"><strong>transition-duration</strong></span> style added to the page to indicate that it should be animated to that new position (see style definitions below).</li>
</ol>
<p><div class="woo-sc-box normal   ">In my own experience, I don&#8217;t have to force a reflow (step 2) when animating elements that are already in the DOM. However, I have to force a reflow when adding new elements to the DOM before animating them to their new position (see pageslider.js described below). More information <a href="http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/">here</a>.</div><br />
Here is a code example:</p>
<pre class="brush: jscript; title: ; notranslate">
var homePage = document.getElementById(&quot;homePage&quot;),
    newPage = document.getElementById(&quot;newPage&quot;);
// Position the page at the starting position of the animation
newPage.className = &quot;page right&quot;;
// Position page at ending position of animation and add transition-duration
newPage.className =&quot;page transition center&quot;;
// Simultaneously slide out the current page to the left of the viewport
homePage.className = &quot;page transition left&quot;;
</pre>
<p>And here are two versions of the accompanying CSS: the first version will not hardware accelerate the transition; the second one will.  </p>
<h5>Non hardware accelerated transition:</h5>
<p>Adding <code><strong>transform: translate3d(0,0,0);</strong></code> to the page will hardware accelerate the actual composition (drawing of the element on top of the background). However, it will not hardware accelerate the transition: The &#8220;left&#8221; property cannot be hardware accelerated. Changing the &#8220;left&#8221; property will force a layout every time the property changes (every frame).</p>
<pre class="brush: css; title: ; notranslate">
.page {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}

.page.left {
    left: -100%;
}

.page.center {
    left: 0;
}

.page.right {
    left: 100%;
}

.page.transition {
    -webkit-transition-duration: .25s;
    transition-duration: .25s;
}
</pre>
<h5>Hardware accelerated transition:</h5>
<p>To hardware accelerate the transition, apply a 3D transform to the page&#8217;s x coordinate instead of changing the value of the left property. The version of the style sheet below should hardware accelerate both the actual composition (drawing of the page) and the transition. </p>
<pre class="brush: css; title: ; notranslate">
.page {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}

.page.left {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
}

.page.center {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}

.page.right {
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
}

.page.transition {
    -webkit-transition-duration: .25s;
    transition-duration: .25s;
}
</pre>
<p>Try the simple example below. The code is self-contained in simplepageslider.html. Right-click the sample and select &#8220;View Frame Source&#8221; to check it out.</p>
<p><iframe src="http://coenraets.org/samples/pageslider/simplepageslider.html" width="640" height="320"></iframe></p>
<h3>PageSlider.js: A Micro Library for Simple Page Transitions</h3>
<p>In a real-life application, you will typically want to generalize the process a little bit. For example, you could:</p>
<ul>
<li>Automatically add new pages to the DOM and remove them from the DOM after they are animated out of the viewport.</li>
<li>Automatically determine the sliding direction based on the page history.</li>
<li>Provide a hook (using the <code>webkitTransitionEnd</code> event) for adding some logic when the transition completes.</li>
</ul>
<p>I isolated that logic in <a href="https://github.com/ccoenraets/PageSlider/blob/master/pageslider.js">pageslider.js</a>, an example of a micro library you could use to provide hardware accelerated page transitions in your mobile apps.</p>
<p>Try the example below, or try it fullscreen <a href="http://coenraets.org/samples/pageslider/index.html">here</a>.</p>
<p><iframe src="http://coenraets.org/samples/pageslider/index.html" width="640" height="500"></iframe></p>
<h5>Source Code</h5>
<p>The pageslider.js source code is available in <a href="https://github.com/ccoenraets/PageSlider">this GitHub repository</a>.</p>
<div class="woo-sc-box note   ">Hardware acceleration is not available on all platforms. Check out <a href="http://caniuse.com/transforms3d">caniuse.com</a> to see which platforms are supported. Make sure your animations work on platforms that do not support hardware acceleration.</div>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Presenting &#8220;Modern Tools for the Modern Web&#8221; in London Tonight, Wednesday March 6th</title>
		<link>http://coenraets.org/blog/2013/03/presenting-modern-tools-for-the-modern-web-in-london-tonight-wednesday-march-6th/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=presenting-modern-tools-for-the-modern-web-in-london-tonight-wednesday-march-6th</link>
		<comments>http://coenraets.org/blog/2013/03/presenting-modern-tools-for-the-modern-web-in-london-tonight-wednesday-march-6th/#comments</comments>
		<pubDate>Wed, 06 Mar 2013 10:51:25 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=5009</guid>
		<description><![CDATA[I will be delivering a talk titled &#8220;Modern Tools for the Modern Web&#8221; at Skillsmatter in London tonight (Wednesday March 6th) at 6:30pm. It&#8217;s free and open to all. Simply register here. I&#8217;ll be going over the new Edge Tools and Services (Edge Animate, Edge Reflow, Edge Inspect, Edge Code, PhoneGap and PhoneGap Build, etc), [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/edge_logos.png"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/edge_logos.png" alt="" title="edge_logos" width="640" height="84" class="alignleft size-full wp-image-5017" /></a></p>
<p>I will be delivering a talk titled &#8220;Modern Tools for the Modern Web&#8221; at <a href="http://skillsmatter.com/">Skillsmatter</a> in London tonight (Wednesday March 6th) at 6:30pm. It&#8217;s free and open to all. Simply register <a href="http://skillsmatter.com/podcast/os-mobile-server/modern-tools-for-modern-web">here</a>.</p>
<p>I&#8217;ll be going over the new <a href="http://html.adobe.com/edge/">Edge Tools and Services</a> (Edge Animate, Edge Reflow, Edge Inspect, Edge Code, PhoneGap and PhoneGap Build, etc), and discuss how they can be used to build modern content and applications. The Edge Tools and Services are all part of the <a href="http://creative.adobe.com">Creative Cloud</a>.<br />
<span id="more-5009"></span><br />
I hope to see you there if you are in the London area!</p>
<p>Christophe</p>
<h4>Detailed abstract:</h3>
<p>The next generation of HTML and CSS offer powerful new features for creating graphically rich content and applications. In this session, Christophe will discuss the latest trends of the modern web, and introduce the Adobe Edge Tools: a unique set of tools and services that help designers and developers create content and applications that leverage modern web technologies. </p>
<p>The topics discussed will include:</p>
<ul>
<li>Latest trends of the modern web and Adobe recent contributions to web standards</li>
<li>Edge Reflow: A new tool laser focused on Responsive Web Design (RWD)</li>
<li>Edge Animate: A new tool that lets you create interactive and animated content using HTML, CSS, and JavaScript</li>
<li>PhoneGap and PhoneGap Build: An open source solution for building cross-platform mobile apps with standard-based Web technologies, and a cloud-based build service that lets you build and package your application for six different platforms.</li>
<li>Edge Inspect: A new tool that lets you remotely visualize, inspect, test and debug your HTML content and applications on dozens of mobile devices at the same time.</li>
<li>Edge Code: A code editor for HTML, JavaScript and CSS built with HTML, JavaScript and CSS.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/03/presenting-modern-tools-for-the-modern-web-in-london-tonight-wednesday-march-6th/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Speaking at QCon London Next Week</title>
		<link>http://coenraets.org/blog/2013/03/speaking-at-qcon-london-next-week/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=speaking-at-qcon-london-next-week</link>
		<comments>http://coenraets.org/blog/2013/03/speaking-at-qcon-london-next-week/#comments</comments>
		<pubDate>Fri, 01 Mar 2013 17:51:20 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=4998</guid>
		<description><![CDATA[I&#8217;m excited to be speaking at QCon London again this year. The conference is next week, from Wednesday March 6th to Friday March 8th. As always at QCon, the sessions and the speaker lineup look great. I will be speaking in the &#8220;Next Generation Mobile Apps&#8221; track on Thursday. This year I&#8217;ll go well beyond [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://coenraets.org/blog/wp-content/uploads/2013/03/speaking-at.jpg"><img src="http://coenraets.org/blog/wp-content/uploads/2013/03/speaking-at.jpg" alt="" title="speaking-at" width="150" height="150" class="alignleft size-full wp-image-5001" /></a></p>
<p>I&#8217;m excited to be speaking at <a href="http://qconlondon.com/london-2013/">QCon London</a> again this year. The conference is next week, from Wednesday March 6th to Friday March 8th. As always at QCon, the sessions and the speaker lineup look great. I will be speaking in the &#8220;Next Generation Mobile Apps&#8221; track on Thursday. This year I&#8217;ll go well beyond the PhoneGap basics and focus on <a href="http://qconlondon.com/london-2013/presentation/Architecting%20PhoneGap%20Applications">Architecting PhoneGap Applications</a>. There are many other inspiring tracks and sessions. </p>
<p>I know this is last minute, but if you are interested in attending the conference, you can save £100 off the registration fee by using the promotion code <strong>COEN100</strong>. Hope to see some of you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2013/03/speaking-at-qcon-london-next-week/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
