<?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>The &quot;Tech. Arch.&quot;</title>
	<atom:link href="http://blog.monnet-usa.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>https://blog.monnet-usa.com</link>
	<description>Architecting Forward ::&#62;</description>
	<lastBuildDate>Sat, 29 Dec 2012 15:38:57 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Creating Mobile Apps With KnockOutJS, PhoneGap &#038; jQuery Mobile</title>
		<link>https://blog.monnet-usa.com/?p=420</link>
					<comments>https://blog.monnet-usa.com/?p=420#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Sat, 29 Dec 2012 15:38:57 +0000</pubDate>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[KnockoutJS]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[rich web apps]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[jQuery Mobile]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=420</guid>

					<description><![CDATA[Intro In part 4 we built a complete working version of the Savings Goal Simulator as a rich web app where each view model, view and view mediator is nicely modularized. How could we leverage our browser-side markup and logic to create a mobile app, portable across multiple platforms such as IOS, Android, Windows Mobile? [&#8230;]]]></description>
										<content:encoded><![CDATA[<h3>Intro <a id='part5-intro'></a></h3>
<p>In <a href="https://blog.monnet-usa.com/?p=411">part 4</a> we built a complete working version of the <a href="http://savings-goal-simulator.heroku.com/">Savings Goal Simulator</a> as <strong><em>a rich web app</em></strong> where each view model, view and view mediator is nicely modularized. How could we leverage our browser-side markup and logic to create a <strong><em>mobile app</em></strong>, portable across <strong><em>multiple platforms</em></strong> such as IOS, Android, Windows Mobile? Well, the goal of this post is to present a potential approach. (Of course you can take a peek at the <a href="#part5-sowhat">&#8220;So What?&#8221;</a> section)</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/mobile-app-stack.png" alt="Mobile App Framework Stack" title="Mobile App Framework Stack" /></p>
<p>The idea behind <a href="#acrdva">PhoneGap</a> is to provide a cross-mobile-platform framework allowing a <strong><em>self-contained web app</em></strong> built using HTML5 + CSS3 + Javascript to run inside a <strong><em>full screen web view</em></strong>, while allowing access to the device features such as for example: geolocation, accelerometer, camera, storage, etc..</p>
<p>So PhoneGap will serve as our foundation. For each platform you intend on supporting, you will use the corresponding SDK, code project templates and PhoneGap runtime. Let&#8217;s take a look at the 3 most common platforms:</p>
<p>On IOS, the SDK and application consist of:</p>
<ul>
<li>a CordovaLib libray</li>
<li>an XCode project template</li>
<li>a main module launching a UIApplicationMain</li>
<li>an AppDelegate class launching a ViewController</li>
<li>a ViewController loading the main page (index.html) of your app into a WebView</li>
</ul>
<p>On Android, the SDK and application consist of:</p>
<ul>
<li>an Apache Cordova JAR containing the Java implementation of PhoneGap for the Android platform</li>
<li>an Eclipse project template</li>
<li>a DroidGap parent class used for your own Java Droid activity class loading the main page (index.html) of your app.</li>
<li>an assets/www folder containing web resources (.html, .js, .css, images, etc.)</li>
</ul>
<p>On Windows Mobile Phone, the SDK and application consist of:</p>
<ul>
<li>a WP7CordovaClassLib library</li>
<li>a XAML application with a phone application page containing a CordovaView</li>
<li>a CordovaView including a browser window hosting the main page (index.html) of your app</li>
<li>a www folder containing web resources (.html, .js, .css, images, etc.)</li>
</ul>
<p>In summary, for each platform, PhoneGap is used to create a sort of &#8220;<strong><em>launcher</em></strong>&#8221; application, which starts a &#8220;<strong><em>controller</em></strong>&#8220;, which in turns loads your main .html web page into a full-screen <strong><em>web view</em></strong>, and exposes underlying platform features through a <strong><em>Javascript API</em></strong>.</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/phonegap.png" alt="PhoneGap Framework" title="PhoneGap Framework" /></p>
<p>So with PhoneGap, we will keep the launcher part of our mobile app fairly small and trivial. Consequently the minimum skills and associated learning curve for each platform we&#8217;ll want to target will also be more manageable. The majority of your app components will be based on standard HTML5 + CSS3 + Javascript.</p>
<h3>Synopsis<a id='part5-approach'></a></h3>
<p>The approach will consist of:</p>
<ol>
<li>Creating (or leveraging parts of) a minimal web app using HTML and Javascript</li>
<li>Hosting the web app in a PhoneGap &#8220;<strong><em>launcher</em></strong>&#8221; app (based on the desired mobile platform)</li>
<li>Leveraging jQuery Mobile UI widgets for a consistent look and feel</li>
<li>Theme the app using CSS3 including transitions</li>
<li>Expand the web app functionality while:
<ul>
<li>Modularizing pages and views using a templating engine</li>
<li>Partitioning application logic between view models and view mediators</li>
<li>Using KnockoutJS for data-binding </li>
</ul>
</li>
</ol>
<h3>Prerequisites<a id='part5-prerequisites'></a></h3>
<p>Your starting point may differ based on your current skills and experience:</p>
<ul>
<li>
<p>If you already have a significant development experience on a given platform (e.g. Mac <strong><em>OSX</em></strong> with <strong><em>XCode</em></strong>, or <strong><em>Windows</em></strong> with <strong><em>Visual Studio</em></strong>), then download the SDK for your platform and follow the corresponding <a href="http://docs.phonegap.com/en/2.1.0/guide_getting-started_index.md.html#Getting%20Started%20Guides">Getting Started Guide</a>. You will benefit from a more integrated experience and faster device emulation.</p>
<p><em>Note for IOS: an Apple Developer License will be required if you want to deploy the app to your device (otherwise you will only be able to use the emulator).</em>  </p>
</li>
<li>
<p>If you have limited overall experience, starting out with the <strong><em>Android</em></strong> platform and the <strong><em>Aptana Studio IDE</em></strong> (a custom version of the Eclipse IDE optimized for HTML5/CSS3 and Javascript development) might be easier as you can run it on any OS (Windows, Mac, Linux). To get started you will need to install the following tools (in order):</p>
<ul>
<li><a href="http://www.aptana.com/products/studio3">Aptana Studio 3</a>    </li>
<li><a href="http://developer.android.com/sdk/installing/index.html">Android SDK</a></li>
<li><a href="http://developer.android.com/sdk/installing/installing-adt.html">Android Development Tools (ADT) plugin for Eclipse / Aptana Studio</a> </li>
</ul>
<p><em>Note: I recommend the basic tutorial to create a <a href="http://developer.android.com/training/basics/firstapp/creating-project.html">basic Android app</a> to ensure all the prerequisites are installed correctly. Then you can follow the PhoneGap <a href="http://docs.phonegap.com/en/2.1.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android">Getting Started Guide for Android</a>.</em></p>
</li>
</ul>
<p>In the rest of this tutorial I will assume that your mobile development environment is configured and working, and that you have successfully followed the PhoneGap Getting Started Guide. In the next sections I will use the <strong><em>Android</em></strong> platform as an example.</p>
<h3>High-Level Steps<a id='part5-high-level-steps'></a></h3>
<p><em>Note: this tutorial builds upon the previous four <a href="#criwawkotuts">tutorials</a> and assumes you have built a rich interactive web application using view models, view mediators, and modularized views.</em></p>
<p>Before we get started, here is a <em>bird&#8217;s-eye-view</em> of the steps we will be going through in details in later sections:</p>
<ol>
<li>Creating the actual <strong><em>app shell</em></strong> using PhoneGap&#8217;s <a href="http://docs.phonegap.com/en/2.1.0/guide_getting-started_index.md.html#Getting%20Started%20Guides">Getting Started Guide</a> for the platform you want to start out with.</li>
<li>Test the basic sample shell to make sure everything is working correctly</li>
<li>Customize the assets/www <strong><em>folder structure</em></strong> including all needed JS libraries</li>
<li>Add all needed references for CSS and Javascript files</li>
<li>Define placeholder / container divs for each <strong><em>&#8220;logical&#8221; jQuery Mobile page</em></strong></li>
<li>Create separate sets of files for each logical page:
<ul>
<li>view markup (.html) based on a templating engine</li>
<li>view model code (.js)</li>
<li>view mediator code (.js)</li>
</ul>
</li>
<li>Create a main application Javascript module responsible for
<ul>
<li>loading all view markup / templates</li>
<li>initialize all view mediators (wich in turn initialize their respective view model and data bind the view model to the view)</li>
<li>trigger the overall rendering of the main page by jQuery Mobile</li>
</ul>
</li>
<li>Create a <strong><em>phone and a tablet version</em></strong> of the main web page (e.g. index.phone.html vs. index.tablet.html</li>
<li>Customize the <strong><em>mobile controller</em></strong> to load the appropriate index page based on device type (phone vs. tablet) </li>
<li>Tailor the look and feel (layout, styling, etc.) for the tablet vs. phone version</li>
<li>Prepare for packaging</li>
<li>Host your app on an <strong><em>&#8220;app store&#8221;</em></strong></li>
</ol>
<h3>Building Our App Step-By-Step<a id='part5-implementation'></a></h3>
<p>Once we are finished the mobile version of the Savings Goal Simulator will look like this:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-newlook.png" alt="New Look" title="New Look" />   </p>
<p>Let&#8217;s download the version of PhoneGap from <a href="http://phonegap.com/download">http://phonegap.com/download</a> and extract the content to a PhoneGap folder (e.g. PhoneGapSDK). We&#8217;ll use the content later.</p>
<h3>Creating The Android Application Shell<a id='part5-android-shell'></a></h3>
<p>On the Android platform, the application shell takes the form a <strong>Java class</strong> called an &#8220;<strong>activity</strong>&#8220;. It inherits from the <a href="#android-activity">android.app.Activity</a> which is the mobile app&#8217;s main application <a href="#controller">&#8220;<strong>controller</strong>&#8220;</a> in the <a href="#mvc">Model-View-Controller</a> sense.</p>
<p>So let&#8217;s get started in Aptana Studio and follow the steps from the <a href="http://docs.phonegap.com/en/2.1.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android">PhoneGap Getting Started With Android guide</a>:</p>
<ol>
<li>From Aptana Studio, select File, New Project to start the project creation wizard</li>
<li>Expand the Android folder and select &#8220;Android Application Project&#8221;</li>
<li>Let&#8217;s name the application and Eclipse project &#8220;Savings Goal Simulator&#8221;</li>
<li>Customize the namespace e.g.: com.yournamespace.savingsgoalsimulator </li>
<li>Select the minimum version of the Android SDK your app should require, e.g. API7: Android 2.1 </li>
<li>By default the project folder will be created in the default Eclipse workspace project unless you want to customize the path.<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-new-android-project.png" alt="Creating the base Android app" title="Creating the base Android app" /></li>
<li>Click Next </li>
<li>Accept the default icon settings for now (you can customize them later) and click Next</li>
<li>Accept the default kind of activity settings and click Next</li>
<li>Accept the default activity settings and click Next &#8211; the project will then be created:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-default-android-project-S.png" alt="Creating the base Android app" title="Creating the base Android app" />  </li>
</ol>
<p>At this point we have a basic Android app that you can run in the simulator:</p>
<ul>
<li>Select Run, then Run, </li>
<li>Select &#8220;Android Application&#8221; in the Run As dialog, then click Ok</li>
<li>The emulator will boot Android</li>
<li>
<p>Then click and drag the lock to the right to unlock the virtual phone, your app will appear:  </p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-runnin-default-android-app.png" alt="Running the base Android app" title="Running the base Android app" />  </p>
</li>
</ul>
<p>Let&#8217;s take a brief look at what was generated:</p>
<ol>
<li>
<p>Expand the src folder recursively until you can see and double-click on the MainActivity.java file.</p>
<pre class="brush: javascript">package com.yournamespace.savingsgoalsimulator;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;  

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }   

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}	
</pre>
<p>}
</li>
<li>The <strong>MainActivity</strong> class inherits from the core Android Activity class</li>
<li>The <strong>OnCreate</strong> method calls <strong>setContentView</strong> to create the main view based on the layout provided</li>
<li>Under the <strong>res\layout</strong> folder, open the <strong>activity_main.xml</strong> resource</li>
<li>The <strong>RelativeLayout</strong> includes a <strong>TextView</strong> for which the text is provided by the string resource named <strong>hello_world</strong></li>
<li>Under <strong>res\values</strong>, open the <strong>strings.xml</strong> resource and find the definition of <strong>hello_world</strong> </li>
</ol>
<p>Once we upgrade our app to PhoneGap, we will no longer use an Android content view nor a layout. Instead we will use a web view loaded with a local web page.</p>
<h3>Creating The PhoneGap Application Shell<a id='part5-phonegap-shell'></a></h3>
<p>PhoneGap provides a subclass of Activity called <strong>DroidGap</strong> which instead of creating an Android content view based on a layout, will <strong>create a web view and load the .html page of your choice</strong>, which like any page will load stylesheets and scripts, and run the Javascript code. So we&#8217;ll make the necessary changes to upgrade the default app to PhoneGap:</p>
<ol>
<li>
<p>Let&#8217;s copy the <strong>Cordova Java archive</strong> (<strong>cordova-2.2.0.jar</strong> as of this writing) of the <strong>lib\android</strong> located in our <strong>PhoneGapSDK</strong> folder we extracted earlier to the <strong>libs</strong> folder of your project (the folder currently contains a file named android-support-v4.jar). The Cordova JAR will now appear in Aptana Studio under <strong>libs</strong>.<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-cordova-jar.png" alt="Adding the Cordova JAR to the project" title="Adding the Cordova JAR to the project" /></p>
</li>
<li>
<p>Now we need to add the Cordova JAR to the Java Build Path. In AptanaStudio, right click on the <strong>libs</strong> folder, select &#8220;Build Path&#8221;, then select &#8220;Configure Build Path&#8221;, select the &#8220;Libraries&#8221; tab, click on &#8220;Add JARs &#8230;&#8221;, drill down to the libs folder of your project, select the <strong>Cordova JAR</strong>, and click OK.<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-cordova-jar-lib.png" alt="Adding the Cordova JAR to the Java Build Path" title="Adding the Cordova JAR to the Java Build Path" />  </p>
</li>
<li>
<p>The Cordova JAR will also appear under the &#8220;<strong>Referenced Libraries</strong>&#8221; folder of your project.<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-ref-libs.png" alt="Java Build Path - Referenced Libraries" title="Java Build Path - Referenced Libraries" /></p>
</li>
<li>
<p>Let&#8217;s go to the <strong>MainActivity</strong> Java class source file. Since we&#8217;re no longer going to need the default Android Activity approach, let&#8217;s replace the 2 imports related to android.app.Activity and android.view.Menu by a import for the <strong>org.apache.cordova.*</strong> namespace:</p>
<pre class="brush: javascript">package com.yournamespace.savingsgoalsimulator;
import android.os.Bundle;
import org.apache.cordova.*
</pre>
</li>
<li>
<p>Let&#8217;s change the <strong>parent class</strong> for MainActivity to the new <strong>DroidGap</strong> class:</p>
<pre class="brush: javascript">public class MainActivity extends DroidGap
</pre>
</li>
<li>
<p>Now we&#8217;ll change the implementation of the <strong>onCreate</strong> method. So let&#8217;s replace the line starting with setContentView by the following code which load the content from a local url:</p>
<pre class="brush: javascript">@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");
}
</pre>
</li>
<li>
<p>Let&#8217;s remove the <strong>onCreateOptionsMenu</strong> method as it is no longer needed.</p>
</li>
<li>
<p>If we ran the app again, the emulator would tell us that the index.html could not be loaded which makes sense since we have not created it yet!<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-missing-index.html.png" alt="No index.html found yet" title="No index.html found yet" /></p>
</li>
<li>
<p>Note that PhoneGap is looking for the resource in a <strong>www</strong> folder under a logical android<em>asset folder. Although it might seem counter-intuitive Android maps the &#8220;<strong>android</em>asset</strong>&#8221; url folder to the physical <strong>assets</strong> folder! So right click on <strong>assets</strong> and create the <strong>www</strong> folder.</p>
</li>
<li>
<p>Under <strong>assets/www</strong>, create an <strong>index.html</strong> web page file with the following basic HTML source:</p>
<pre class="brush: html">&lt;!DOCTYPE HTML&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Cordova&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;Hello World&lt;/h1&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
</li>
<li>
<p>Re-run the app and the page should now display in the emulator. At this point we just exercized the basic ability for the <strong>DroidGap</strong> class to load a web page into a web view. We&#8217;ll soon add the Cordova Javascript library to the page so we can expose the bi-directional API between the web page and the actual device. But first we need to add the permissions PhoneGap will need to the application. For that, double-click on the <strong>AndroidManifest.xml</strong> and switch to the XML view. Locate the line starting with the <strong>&lt;application tag</strong> and insert the following lines <strong>above</strong> it, then save the XML file:</p>
<pre class="brush: javascript">&lt;supports-screens 
    android:largeScreens="true" 
    android:normalScreens="true" 
    android:smallScreens="true" 
    android:resizeable="true" 
    android:anyDensity="true" /&gt;


&lt;uses-permission android:name="android.permission.VIBRATE" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /&gt;
&lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.RECEIVE_SMS" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.READ_CONTACTS" /&gt;
&lt;uses-permission android:name="android.permission.WRITE_CONTACTS" /&gt;
&lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt; 
&lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
&lt;uses-permission android:name="android.permission.BROADCAST_STICKY" /&gt;
</pre>
<p>Technically your application may only need a subset of these permissions, but for this tutorial we&#8217;ll add them all. Additionally, if you want the application to support orientation changes, add the following attribute before the end of the &lt;activity tag !(located underneath the &lt;application tag):</p>
<pre class="brush: javascript">android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
</pre>
<p>The whole opening &lt;activity tag should now look as follows: </p>
<pre class="brush: javascript">&lt;activity
    android:name=".MainActivity"
    android:label="@string/title_activity_main"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
 &gt;
</pre>
</li>
<li>
<p>To allow our WebView to interact with the PhoneGap / Cordova plugins for the mobile device we need to add configuration information to our <strong>res</strong> resource folder. So copy the <strong>xml</strong> folder located in the <strong>android</strong> folder of the <strong>PhoneGapSDK</strong> folder to the <strong>res</strong> folder of our project:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-cordova-xml-S.png" alt="Adding the Cordova xml folder to the project" title="Adding the Cordova xml folder to the project" /></p>
<p><em>Note: if you forget this step, later the mobile app will show an error message indicating that the Cordova class cannot be found since the WebView will not be able to locate the Cordova plugins.</em></p>
</li>
<li>
<p>As in our original <a href="https://blog.monnet-usa.com/?p=368">Creating Rich Interactive Web Apps With KnockOut.js – Part 2</a> tutorial, let&#8217;s further expand the www folder into subfolders, by creating a <strong>scripts</strong> subfolder, and below that a <strong>vendor</strong> subfolder. Now go back to the PhoneGap SDK folder and copy the Cordova Javascript library file (cordova-2.2.0.js as of this writing) to our new assets/www/scripts/vendor folder.<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-cordova.js.png" alt="Adding Cordova JS to the project" title="Adding Cordova JS to the project" />   </p>
</li>
<li>
<p>Let&#8217;s create a separate <strong>application.js</strong> shell module under our <strong>assets/www/scripts</strong> folder. The module will contain the code to initialize our web page but for now, let&#8217;s keep it minimal and let&#8217;s provide 2 functions: InitializeApplication and OnLoad:</p>
<pre class="brush: javascript">function InitializeApplication() {
    alert("Application Initialized!");
}  


function OnLoad() {
    InitializeApplication();
}
</pre>
</li>
<li>
<p>Let&#8217;s switch to the index.html page and add our 2 Javascript files to our &lt;head&gt; tag:</p>
<pre class="brush: html">&lt;head&gt;
    &lt;title&gt;Cordova&lt;/title&gt;
    &lt;script src="scripts/vendor/cordova-2.2.0.js"&gt;&lt;/script&gt;
    &lt;script src="scripts/application.js"&gt;&lt;/script&gt; 
&lt;/head&gt;
</pre>
<p>And for now, let&#8217;s add a call to the OnLoad function to the body onload event of the page:</p>
<pre class="brush: html">&lt;body onload="OnLoad();"&gt;
    &lt;h1&gt;Hello World&lt;/h1&gt;
&lt;/body&gt;
</pre>
</li>
<li>
<p>Now you should be able to re-run the application and see the alert pop-up.</p>
<p>Note: if you don&#8217;t see the alert, verify the scripts and the page. You can also troubleshoot the index.html from your favorite browser debugging tools (e.g. Chrome, Developer Tools). This is always the best technique to troubleshoot your Javascript anyway.</p>
</li>
<li>
<p>We&#8217;re now ready to dig into the application initialization lifecycle! The browser triggered the <strong>onload</strong> event once the page has been loaded. PhoneGap / Cordova will trigger a different event named <strong>deviceready</strong> once the bidirectional API between the mobile device and Javascript has been fully initialized. To react to the <strong>deviceready</strong> event we will need to add an <strong>event listener</strong> once the <strong>onload</strong> event has been triggered. So let&#8217;s add a new function named <strong>OnDeviceReady</strong> to our <strong>application.js</strong> module. We&#8217;ll move the call to InitializeApplication from OnLoad to the new function since we actually want to initialize our app once the deviceready event has occurred.</p>
<pre class="brush: javascript">function OnDeviceReady() {  
    InitializeApplication();
}
</pre>
<p>Now let&#8217;s setup the event listener in the OnLoad function:</p>
<pre class="brush: javascript">function OnLoad() {
    document.addEventListener("deviceready", OnDeviceReady, false);
}
</pre>
<p>This allows us to customize the InitializeApplication to use some of the device information exposed by PhoneGap:</p>
<pre class="brush: javascript">function InitializeApplication() {
    alert("Welcome to PhoneGap " 
            + device.cordova 
            + " version " + device.version 
            + " for " + device.platform 
            + " on device: " + device.name );
}
</pre>
<p>Now let&#8217;s run the application again and our alert with the device information should appear!<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-basic-initialize-app.png" alt="Application Initialization On deviceready Event" title="Application Initialization On deviceready Event" /></p>
</li>
</ol>
<p>This concludes the creation of the basic PhoneGap application shell. In summary here is what our application does:</p>
<ol>
<li>Android launches our MainActivity class which inherits from the DroidGap</li>
<li>The onCreate method of DroidGap creates a WebView</li>
<li>The onCreate method of MainActivity sets the url content of the WebView to index.html</li>
<li>Our index.html loads the Cordova library and our application.js</li>
<li>The onload event of the page sets up an event listener for the PhoneGap deviceready event</li>
<li>Once PhoneGap is fully initialized the deviceready event is triggered</li>
<li>Our custom InitializeApplication function is called &#8211; at that point the PhoneGap API is fully operational</li>
</ol>
<h3>Applying a jQuery Mobile &#8220;Veneer&#8221;<a id='part5-jquery-mobile'></a></h3>
<h4>Introduction to jQuery Mobile<a id='part5-jquery-mobile-intro'></a></h4>
<p>Since our app is built using HTML and CSS we can create a complete custom look and feel for our app. This is fine if you are creating something truly unique like a game or something very graphical.<br />
But if you are planning on creating an application focused on <strong>manipulating data</strong> I would recommend following <strong>mobile UI conventions</strong>. One easy way to ensure a more standardized look that your customers will feel familiar with is to leverage jQuery Mobile. You will benefit from:</p>
<ul>
<li>a set of common UI elements optimized for a mobile experience
<ul>
<li>larger buttons and easier to use form controls</li>
<li>toolbars, listviews, collapsible panels, grids</li>
</ul>
</li>
<li>navigation between &#8220;logical pages&#8221;</li>
<li>cross-platform compatibility helping you create a uniform experience across devices</li>
<li>customizable themes</li>
</ul>
<p>Here is how jQuery Mobile makes this possible:</p>
<ul>
<li>
<p>jQuery Mobile allows declaration of its custom UI elements by augmenting traditional HTML elements with new attributes. E.g.: a jQM button is created by enhancing the anchor tag with a data-role=&#8221;button&#8221; attribute (as well as other attributes to add details about how the button should be rendered, such as with an icon positioned above the label):  </p>
<pre class="brush: javascript">&lt;a href="#addContact" 
    data-role="button" 
    data-icon="plus" 
    data-iconpos="top"&gt;Add Contact&lt;/a&gt;
</pre>
</li>
<li>
<p>As the DOM is loaded, jQuery Mobile injects additional needed elements and CSS classes based on the various <strong>data-*</strong> attributes to produce the desired effect.</p>
</li>
</ul>
<p>I would not be providing a balanced view point if I did not mention the following associated challenges:</p>
<ul>
<li>
<p>Since &#8220;logical pages&#8221; are defined using div elements enhanced with data-role=&#8221;page&#8221; attribute which causes the physical .html page to become large and difficult to maintain:  </p>
<pre class="brush: javascript">&lt;div id="page1" data-role="page"&gt;
    &lt;!-- ... --&gt;
&lt;/div&gt;


&lt;div id="page2" data-role="page"&gt;
    &lt;!-- ... --&gt;
&lt;/div&gt;


&lt;!-- ... --&gt;


&lt;div id="pageN" data-role="page"&gt;
    &lt;!-- ... --&gt;
&lt;/div&gt;
</pre>
<p>We&#8217;ll use external views based on templates and the jQuery View Loader plugin to address this issue.  </p>
</li>
<li>
<p>Defining common elements such as the bottom toolbar for each &#8220;logical page&#8221; also requires the use of templates if we do not want to duplicate the markup over and over.</p>
</li>
<li>
<p>Since the markup is automatically enhanced as it is being loaded, dynamically changing elements becomes a bit more complicated since jQuery Mobile needs to be notified to &#8220;re-enhance&#8221; the new markup fragments. This will become even more apparent when we use a viewmodel to view data-binding library like KnockoutJS. But again there are some solutions.</p>
</li>
</ul>
<p>Overall despite the learning curve and the need to make jQuery Mobile &#8220;play nice&#8221; with other libraries manipulating the DOM, the benefits strongly outweigh the challenges. This tutorial will provide the necessary guidance to increase your chances of success. </p>
<h4>Adding A jQuery Mobile Shell<a id='part5-jquery-mobile-shell'></a></h4>
<ol>
<li>
<p>First, download the full ZIP version of jQueryMobile and extract it out locally.  </p>
</li>
<li>
<p>Before we add the files to our project, let&#8217;s create a <strong>css</strong> folder under <strong>assets/www</strong>. This will provide a central place for all CSS files needed for our application.  </p>
</li>
<li>
<p>Let&#8217;s create a <strong>jquery.mobile</strong> folder under <strong>assets/www/css</strong>  </p>
</li>
<li>
<p>Now copy the .css files (only) and the images folder from your extracted jQueryMobile ZIP to <strong>assets/www/css/jquery.mobile</strong>. Your project structure should now look like this:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-jqm-css.png" alt="jQuery Mobile CSS Folder Setup" title="jQuery Mobile CSS Folder Setup" /></p>
</li>
<li>
<p>And then copy the .js files from your extracted jQueryMobile ZIP to <strong>assets/www/scripts/vendor</strong></p>
</li>
<li>
<p>Since jQuery Mobile builds on top of the jQuery Core, download both the development and production versions of jQuery and copy the corresponding .js files to <strong>assets/www/scripts/vendor</strong>. Your project structure should now look like this:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-jqm-js.png" alt="jQuery Mobile JS Folder Setup" title="jQuery Mobile JS Folder Setup" /></p>
</li>
<li>
<p>Now let&#8217;s go back to our index.html page and add the jQuery Mobile stylesheets. We&#8217;ll also add a meta tag to provide device information which will be leveraged by jQuery Mobile to optimize rendering for the device.</p>
<pre class="brush: javascript">&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /&gt;                
&lt;link href="css/jquery.mobile/jquery.mobile-1.2.0.css" rel="stylesheet" type="text/css"  /&gt;  
&lt;link href="css/jquery.mobile/jquery.mobile.structure-1.2.0.css" rel="stylesheet" type="text/css"  /&gt; 
</pre>
</li>
<li>
<p>Let&#8217;s include the .js files for jQuery and jQuery Mobile in between the cordova JS and our application.js</p>
<pre class="brush: javascript">&lt;script src="scripts/vendor/cordova-2.2.0.js"&gt;&lt;/script&gt;     
&lt;script src="scripts/vendor/jquery-1.8.2.js"&gt;&lt;/script&gt; 
&lt;script src="scripts/vendor/jquery.mobile-1.2.0.js"&gt;&lt;/script&gt;       
&lt;script src="scripts/application.js"&gt;&lt;/script&gt; 
</pre>
</li>
<li>
<p>And let&#8217;s define a minimal jQuery Mobile &#8220;<strong>logical page</strong>&#8220;</p>
<pre class="brush: javascript">&lt;body onload="OnLoad();"&gt;
    &lt;div id="page-home" data-role="page"&gt;
        &lt;div data-role="header"&gt;
            Savings Goal Simulator
        &lt;/div&gt;
        &lt;div data-role="content"&gt;
            Welcome!
        &lt;/div&gt;
        &lt;div data-role="footer"&gt;
            powered by PhoneGap and jQueryMobile
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
</pre>
<p>Let&#8217;s run the app in the simulator:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-basic-jqm.png" alt="Minimal jQuery Mobile Logical Page" title="Minimal jQuery Mobile Logical Page" /></p>
</li>
<li>
<p>jQueryMobile fires an event named <strong>mobileinit</strong> as soon as it starts executing. Since we may want to override some of the framework defaults (more on that later), let&#8217;s add a script with an event handler for <strong>mobileinit</strong>. Since we want to setup the event handler before jQuery Mobile starts to load, we&#8217;ll define the script right before the inclusion of jQuery Mobile.</p>
<pre class="brush: javascript">&lt;script type="text/javascript"&gt;
    // IMPORTANT: This must execute before jQueryMobile is loaded!
    $(document).bind("mobileinit", function() {
         console.log("mobileinit","info");
         // Placeholder for framework settings overrides
         // See http://jquerymobile.com/demos/1.2.0/docs/api/globalconfig.html
    });            
&lt;/script&gt;       
&lt;script src="scripts/vendor/jquery.mobile-1.2.0.js"&gt;&lt;/script&gt; 
</pre>
</li>
<li>
<p>In the jQuery world, a <strong>ready</strong> event is triggered on the document once the page has fully loaded. But in jQuery Mobile, since you can have multiple &#8220;logical pages&#8221;, jQuery Mobile will trigger a <strong>pageinit</strong> event on a given page once it has been created and initialized. So typically we&#8217;ll setup an event handler for pageinit when triggered on the main / &#8220;home&#8221; logical page. This handler will perform any  initialization specific to that page. So let&#8217;s add the following script below our &#8220;logical page&#8221; definition:</p>
<pre class="brush: javascript">&lt;script type="text/javascript"&gt;
    $("#page-home").live("pageinit", function() {
        // When ALL scripts have been loaded AND executed:
        alert("page-home is ready!");
    })
&lt;/script&gt;       
</pre>
<p>Now run the application. What do you notice?<br />
The &#8220;page-home is ready!&#8221; alert message appears BEFORE the PhoneGap alert message!<br />
Why is that?<br />
Well, <em>jQuery Mobile starts processing the markup as soon as it is created</em> while PhoneGap <strong>deviceready</strong> event is not triggered until the whole physical page is loaded and until the PhoneGap library is fully initialized.  </p>
<p>IMPORTANT: The initialization code for our application will need to be split according to when various initializations are needed. For example: </p>
<ul>
<li>If we need to <strong>fetch data</strong> from a remote app, we should trigger the fetch from a [jQuery Mobile] <strong>pageinit</strong> event</li>
<li>If we need to <strong>use data from or related to the device</strong> (e.g. local storage), we should retrieve the data from the <strong>deviceready</strong> [PhoneGap] event</li>
</ul>
</li>
</ol>
<p>So at this point, we have a minimal PhoneGap + jQuery Mobile application!</p>
<h3>Transforming Our Savings Goal Simulator Web App Into A Mobile App<a id='part5-web-to-mobile'></a></h3>
<p>At the end of <a href="#criwawko4">Creating Rich Interactive Web Apps With KnockoutJS – Part 4</a> we had a very modular browser-side rich web app. As you will see we&#8217;ll be able to adapt the code to &#8220;make it fit&#8221; with the PhoneGap and jQuery Mobile framework. At a high-level we will need to:</p>
<ul>
<li>adapt our views to fit mobile device dimensions</li>
<li>enhance our view markup with jQuery Mobile attributes (e.g.: data-role, etc.)</li>
</ul>
<h4>Installing The Web Version Of The Savings Goal Simulator<a id='part5-installing-the-web-version-of-the-savings-goal-simulator'></a></h4>
<p>So let&#8217;s first migrate the source of the web version of the Savings Goal Simulator to our mobile project:</p>
<ol>
<li>Download the <a href="#criwawkosrc">source code for the web version of the Savings Goal Simulator</a> from GitHub</li>
<li>Extract and open the download source</li>
<li>Copy the <strong>application.css</strong> from savings-goal-simulator-master\css\ to the <strong>assets\www\css</strong> folder of your project</li>
<li>Copy only the subfolders of savings-goal-simulator-master\scripts\ to the assets\www\scripts folder of your project (do not copy the application.js)</li>
<li>Rename the index.html in savings-goal-simulator-master to index.web.html</li>
<li>Copy index.web.html from savings-goal-simulator-master to assets\www</li>
<li>Rename the application.js in savings-goal-simulator-master to application.web.js</li>
<li>Copy application.web.js in savings-goal-simulator-master to assets\www\scripts</li>
<li>So far your project workspace should now reflect the new folders under assets\www\scripts and the new files:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-web-migration.png" alt="Workspace with web version of the Savings Goal Simulator" title="Workspace with web version of the Savings Goal Simulator" /></li>
<li>To make troubleshooting easier, let&#8217;s make a couple changes so that we can run the web version using index.web.html in a browser. This way we can always compare our mobile version to the web version to help identify and resolve potential issues.
<ul>
<li>Open index.web.html, look for a reference to application.js and rename it to application.web.js (since we renamed that Javascript file earlier)</li>
<li>Open Google Chrome (or your favorite browser), and open the Developer Tools</li>
<li>Drag index.web.html to the browser</li>
<li>Test the app &#8211; it should work fine &#8211; you will notice that there is no &#8220;styling&#8221; since we did not copy the jQuery UI theme (because we will use jQuery Mobile instead) </li>
</ul>
</li>
</ol>
<p>Now we are ready to adapt our web app into a mobile app.</p>
<h3>Rudimentary Migration Of The Savings Goal Simulator Source Code<a id='part5-rudimentary-migration'></a></h3>
<p>The idea is to progressively enhance the basic <strong>index.html</strong> we created in the <a href="#part5-jquery-mobile-shell">&#8220;Adding A jQuery Mobile Shell&#8221;</a> section by incorporating elements of the web version of the app. The modest goal for this section is to be able to bring up the Savings Goal Simulator in the mobile device simulator.</p>
<ol>
<li>
<p>In <a href="#criwawko2">Creating Rich Interactive Web Apps With KnockoutJS – Part 2</a>, we implemented asynchronous parallel loading of Javascript libraries using <a href="#labjs">LAB.js</a> to speed up the loading process of our web application. We will apply the same technique to our mobile app.</p>
<ul>
<li>
<p>In index.html, let&#8217;s load the <strong>LAB.js</strong> Javascript library <strong>after</strong> loading application.js and let&#8217;s add a script block:</p>
<pre class="brush: javascript">&lt;script src="scripts/vendor/cordova-2.2.0.js"&gt;&lt;/script&gt;     
&lt;script src="scripts/vendor/jquery-1.8.2.js"&gt;&lt;/script&gt; 
&lt;script src="scripts/vendor/jquery.mobile-1.2.0.js"&gt;&lt;/script&gt;       
&lt;script src="scripts/application.js"&gt;&lt;/script&gt;  
&lt;script src="scripts/vendor/LAB.min.js" type="text/javascript" &gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    $LAB
        .wait(function () {
        });
&lt;/script&gt;   
</pre>
</li>
<li>
<p>Now let&#8217;s replace the script loading for jquery.mobile-1.2.0.js by a call to load the script via LAB.js:</p>
<pre class="brush: javascript">&lt;script src="scripts/vendor/LAB.min.js" type="text/javascript" &gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    $LAB
        .script("scripts/vendor/jquery.mobile-1.2.0.js").wait()
        .wait(function () {
        // When ALL scripts have been loaded AND executed:                  
        });
&lt;/script&gt;   
</pre>
</li>
<li>
<p>If we try to run our app we will notice that the &#8220;page-home is ready!&#8221; alert never pops-up and that we see an &#8220;$ undefined&#8221; error in the console. This is due to the fact that our scripts are being loaded in parallel of our page execution. So the code we had pageinit event handler we had placed below our page definition needs to be synchronized with our LAB.js-based script loading:</p>
<pre class="brush: javascript">&lt;script type="text/javascript"&gt;
    $LAB
    .wait(function () {
        $("#page-home").live("pageinit", function() {
            // When ALL scripts have been loaded AND executed:
            //alert("page-home is ready!");
            console.log("page-home is ready!","info");
        })
    })
    .script("scripts/vendor/jquery.mobile-1.2.0.js")
    .wait(function () {
        // When ALL scripts have been loaded AND executed:                  
    });
&lt;/script&gt;
</pre>
<p>Now the application should work correctly in the simulator. </p>
</li>
<li>
<p>We can proceed and add requests to load all other Javascript libraries we&#8217;ll need:</p>
<pre class="brush: javascript">&lt;script type="text/javascript"&gt;
    $LAB
    .wait(function () {
        $("#page-home").live("pageinit", function() {
            // When ALL scripts have been loaded AND executed:
            alert("page-home is ready!");
            console.log("page-home is ready!","info");
        })
    })
    .wait(function (){
        // IMPORTANT: This must execute before jQueryMobile is loaded!
        $(document).bind("mobileinit", function() {
             console.log("mobileinit","info");
             // Placeholder for framework settings overrides
             $.support.cors = true;
        });            
    })
    .script("scripts/vendor/jquery.tmpl.min.js").wait()
    .script("scripts/vendor/knockout-latest.debug.js").wait()
    .script("scripts/vendor/jquery.viewloader.js").wait()
    .script("scripts/vendor/jquery.cookie.js")
    .script("scripts/vendor/jquery.blockUI.js")
    .script("scripts/vendor/jquery.hotkeys.js")
    .script("scripts/vendor/jquery.maskedinput-1.3.min.js")
    .script("scripts/vendor/jquery.validate.min.js")
    .script("scripts/vendor/accounting.min.js")
    .script("scripts/vendor/jstorage.min.js")
    .script("scripts/vendor/currency-mask-0.5.0-min.js")
    .script("scripts/viewmodel/sgs.model.common.js")
    .script("scripts/viewmediator/sgs.mediator.common.js")
    .script("scripts/viewmodel/sgs.model.savings-goal.js").wait()
    .script("scripts/viewmediator/sgs.mediator.savings-goal.js")
    .script("scripts/viewmodel/sgs.model.coffee-pricing.js").wait()
    .script("scripts/viewmediator/sgs.mediator.coffee-pricing.js")
    .script("scripts/viewmodel/sgs.model.coffee-consumption.js").wait()
    .script("scripts/viewmodel/sgs.model.consumption-scenarios.js").wait()
    .script("scripts/viewmediator/sgs.mediator.consumption-scenarios.js")
    .script("scripts/viewmodel/sgs.model.savings-forecast.js").wait()
    .script("scripts/viewmediator/sgs.mediator.savings-forecast.js")
    .script("scripts/vendor/jquery.mobile-1.2.0.js")
    .wait(function () {
        // When ALL scripts have been loaded AND executed:                  
    });
&lt;/script&gt;
</pre>
<p>If you run the app in the simulator or the browser you will see in the console that each of the module is being loaded.</p>
</li>
</ul>
</li>
<li>
<p>Currently the <strong>body</strong> of our <strong>index.html</strong> page has a div with a <strong>data-role</strong> of &#8220;<strong>content</strong>&#8220;, let&#8217;s replace our &#8220;Welcome!&#8221; text in the div with the content of body tag from our index.web.html:</p>
<pre class="brush: html">&lt;body onload="OnLoad();"&gt;
    &lt;div id="page-home" data-role="page"&gt;
        &lt;div data-role="header"&gt;
            Savings Goal Simulator
        &lt;/div&gt;
        &lt;div data-role="content"&gt;
            &lt;script id='savings-goal-view-template'
                    type='text/html'
                    src='scripts/view/index/_savings-goal.view.html' &gt;
            &lt;/script&gt;
            &lt;div id='savings-goal-view-container'
                    data-bind='template: { name: "savings-goal-view-template", afterRender: sgs.mediator.savingsgoal.setupViewDataBindings } ' &gt;
            &lt;/div&gt;                  
            &lt;script id='consumption-scenarios-view-template'
                    type='text/html'
                    src='scripts/view/index/_consumption-scenarios.view.html' &gt;
            &lt;/script&gt;
            &lt;div id='consumption-scenarios-view-container'
                    data-bind='template: { name: "consumption-scenarios-view-template", afterRender: sgs.mediator.consumptionscenarios.setupViewDataBindings } ' &gt;
            &lt;/div&gt;                  
            &lt;script id='savings-forecast-view-template'
                    type='text/html'
                    src='scripts/view/index/_savings-forecast.view.html' &gt;
            &lt;/script&gt;
            &lt;div id='savings-forecast-view-container'
                    data-bind='template: { name: "savings-forecast-view-template", afterRender: sgs.mediator.savingsforecast.setupViewDataBindings } ' &gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div data-role="footer"&gt;
            powered by PhoneGap and jQueryMobile
        &lt;/div&gt;                          
    &lt;/div&gt;      
&lt;/body&gt;
</pre>
<p>As a brief reminder, the scripts of type <strong>text/html</strong> represent definition of <strong>jQuery Templates</strong> used to render views / panels within the app using data-bind tags. So the data-role=&#8221;content&#8221; div contains 3 views to track the savings goal, scenarios, and corresponding forecast. If we run the app now the views will not appear as we have not yet ported over the view loading logic.</p>
</li>
<li>
<p>In the web version, the view loading is done in the InitializeApplication function of application.web.js. Let&#8217;s copy the content of application.web.js at the end of application.js and rename the InitializeApplication we just copied to <strong>LoadApplicationViews</strong>.  </p>
</li>
<li>
<p>Now we need to make the call to LoadApplicationViews before jQuery Mobile gets a chance to run. So let&#8217;s insert a wait block before loading it using LAB.js:</p>
<pre class="brush: javascript">&lt;script type="text/javascript"&gt;
    $LAB
    // ... shortened for brevity
    // ...
    .script("scripts/viewmediator/sgs.mediator.savings-forecast.js")
    .wait(function () {
        LoadApplicationViews();
    })
    .script("scripts/vendor/jquery.mobile-1.2.0.js")
    .wait(function () {
        // When ALL scripts have been loaded AND executed:              
    });
&lt;/script&gt;
</pre>
<p>If you look at the code for <strong>LoadApplicationViews</strong> you will notice that it using the <a href="#jqvl">jQuery View Loader library</a> to identify and load all templates (scripts of type text/html).<br />
Note: make sure you at least have version 0.3 of jQuery View Loader (to ensure compatibility with jQuery Mobile).</p>
<pre class="brush: javascript">function LoadApplicationViews() {
    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("LoadApplicationViews starting ...");          
    // Configure the ViewLoader
    $(document).viewloader({
        logLevel: "debug",
        success: function (successfulResolution) {
            InitializeViewMediators();
        },          
        error: function (failedResolution) {
            // Loading failed somehow
            if (typeof(console) != 'undefined' &amp;&amp; console) {
                console.error("index.html page failed to load");    
            }
        }
    });     
    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("LoadApplicationViews done ...");  
}
</pre>
<p>You should now be able to run the application and see the views appear (in the simulator or browser).<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-before-jqm.png" alt="Savings Goal Simulator Before jQuery Mobile Conversion" title="Savings Goal Simulator Before jQuery Mobile Conversion" /><br />
As you can see, even though the app actually works, it is not really usable and we will definitely need adapt the layout and styling of the web app to fit the much smaller screen dimensions of a mobile device.</p>
</li>
</ol>
<h3>Adapting The UI For Mobile Use<a id='part5-adapting-the-ui-for-mobile-use'></a></h3>
<p>Overall our goals will be to: </p>
<ul>
<li>optimize the layout of all panels to ensure you can see all critical elements of the app</li>
<li>make input fields, buttons and controls larger so our fingers can easily work with them</li>
<li>adding sliders where appropriate to allow easy change to numeric values</li>
<li>using collapsible panels to maximize the use of space</li>
</ul>
<p>So let&#8217;s start with the &#8220;savings goal&#8221; panel first.</p>
<ol>
<li>
<p>In Aptana Studio, expand the <strong>assets/www/script/views</strong> folder containing all our views, then expand <strong>index</strong> which contains <strong>partial views</strong> (with an <strong>underscore prefix</strong>) for the index.html page, and open the <strong>_savings-goal.view.html</strong> page:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-views-folder.png" alt="Views Folder" title="Views Folder" />  </p>
<p>I would recommend to make a copy of the file and name it _savings-goal.<strong>web</strong>.view.html and change the reference to the file in <strong>index.web.html</strong>: </p>
<pre class="brush: html">&lt;script id='savings-goal-view-template'
        type='text/html'
        src='scripts/view/index/_savings-goal.web.view.html' &gt;&lt;/script&gt;
</pre>
<p>This way we can keep a baseline of what the web version looks like while we customize the mobile version.</p>
</li>
<li>
<p>Currently, it consists simply of a section with pairs of label + input (or span) tags:  </p>
<pre class="brush: html">&lt;section id='savings-goal-view' &gt;
    &lt;label for="savings-goal-amount"&gt;Savings Goal Amount:&lt;/label&gt;
    &lt;input id="savings-goal-amount"  /&gt;&lt;br/&gt;        
    &lt;label for="savings-max-duration"&gt;Savings Max Duration (In Months):&lt;/label&gt;
    &lt;input id="savings-max-duration" maxlength="3" /&gt;&lt;br/&gt;      
    &lt;label for="savings-target-per-month"&gt;Savings Target Per Month:&lt;/label&gt;
    &lt;span id="savings-target-per-month"  /&gt;&lt;br/&gt;
&lt;/section&gt;      
</pre>
</li>
<li>
<p>Let&#8217;s wrap the first pair of label + input with a div with a data-role=&#8221;fieldcontain&#8221; so that jQuery Mobile can enhance it to make the field bigger.</p>
<pre class="brush: html">&lt;div id="goal-amount" data-role="fieldcontain"&gt;
    &lt;label for="savings-goal-amount"&gt;Savings Goal Amount:&lt;/label&gt;
    &lt;input id="savings-goal-amount"  /&gt;&lt;br/&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>Let&#8217;s repeat the process for the remaining pairs:</p>
<pre class="brush: html">&lt;div id="max-duration" data-role="fieldcontain"&gt;
    &lt;label for="savings-max-duration"&gt;Savings Max Duration (In Months):&lt;/label&gt;
    &lt;input id="savings-max-duration" maxlength="3" /&gt;
&lt;/div&gt;
&lt;div id="target-per-month" data-role="fieldcontain"&gt;
    &lt;label for="savings-target-per-month"&gt;Savings Target Per Month:&lt;/label&gt;
    &lt;span id="savings-target-per-month"&gt;&lt;/span&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>Let&#8217;s add a header above all data-role=&#8221;field-contain&#8221; blocks:</p>
<pre class="brush: html">&lt;section id='savings-goal-view' &gt;
    &lt;header&gt;
        &lt;h2&gt;Goal&lt;/h2&gt;
    &lt;/header&gt;
    &lt;div id="goal-amount" data-role="fieldcontain"&gt;
        &lt;label for="savings-goal-amount"&gt;Savings Goal Amount:&lt;/label&gt;
        &lt;input id="savings-goal-amount"  /&gt;
    &lt;/div&gt;
    &lt;div id="max-duration" data-role="fieldcontain"&gt;
        &lt;label for="savings-max-duration"&gt;Savings Max Duration (In Months):&lt;/label&gt;
        &lt;input id="savings-max-duration" maxlength="3" /&gt;
    &lt;/div&gt;
    &lt;div id="target-per-month" data-role="fieldcontain"&gt;
        &lt;label for="savings-target-per-month"&gt;Savings Target Per Month:&lt;/label&gt;
        &lt;span id="savings-target-per-month"&gt;&lt;/span&gt;
    &lt;/div&gt;
&lt;/section&gt;
</pre>
</li>
<li>
<p>If you run the app in the simulator you will notice that sometimes the jQuery Mobile &#8220;look&#8221; appears and sometimes it does not. This is due to timing issues between the web view and jQuery Mobile. To remedy this, we&#8217;ll request a jQuery Mobile &#8220;refresh&#8221; of our page by triggering a <strong>create</strong> event on our page div. Let&#8217;s add that as the final script statement to execute once LAB.js has completed the processing of jquery.mobile-1.2.0.js:</p>
<pre class="brush: javascript">&lt;script type="text/javascript"&gt;
    $LAB
    // ... shortened for brevity
    // ...
    .script("scripts/vendor/jquery.mobile-1.2.0.js")
    .wait(function () {
        // When ALL scripts have been loaded AND executed:
        setTimeout(function() {
            // Refresh the jQuery Mobile rendering
            $('#page-home').trigger('create');
        }, 50);
    });
&lt;/script&gt;
</pre>
</li>
<li>
<p>Let&#8217;s run the app in the simulator again:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-goal-panel-increment1.png" alt="jQueryMobile-ized Goal Panel Increment 1" title="jQueryMobile-ized Goal Panel Increment 1" />  </p>
</li>
<li>
<p>Now the 2 input fields are big enough for a phone but notice the type of keyboard that comes up if you bring focus to the amount field:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-goal-panel-increment1b.png" alt="Goal Amount With Text Keyboard" title="Goal Amount With Text Keyboard" /><br />
This is a text keyboard. What we need is to tell the device to use a numeric keyboard. This is accomplished using <strong>new HTML5 attributes</strong>: <strong>type</strong>, <strong>min</strong>, and <strong>max</strong>. So let&#8217;s add them to the amount input tag:</p>
<pre class="brush: html">&lt;input id="savings-goal-amount" type="number" min="1" max="1000" maxlength="4" /&gt;
</pre>
<p>And let&#8217;s test again:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-goal-panel-increment2.png" alt="Goal Amount With Numeric Keyboard" title="Goal Amount With Numeric Keyboard" /><br />
Yippee, we now have a numeric keyboard, and notice that there is a Next button to navigate to the next input field!</p>
</li>
<li>
<p>Let&#8217;s repeat the technique for the max number of months field:</p>
<pre html">&lt;input id="savings-max-duration"  type="number" min="1" max="120" maxlength="3" /&gt;
</pre>
</li>
<li>
<p>Now we can use the appropriate numeric keypad to enter values, but it is still not very convenient if we want to vary the values and really test their impact. What we need is the jQuery Mobile slider.</p>
</li>
<li>
<p>In AptanaStudio expand the <strong>assets/www/scripts/viewmediator</strong> folder and let&#8217;s open the sgs.mediator.savings-goal.js module which includes the view mediator responsible for the UI interactions between the view and the viewmodel. Look for the function named sgs.mediator.savingsgoal.<strong>setupViewDataBindings</strong> and let&#8217;s add the following statements to initialize sliders for our input fields:</p>
<pre class="brush: javascript">// Add sliders to our input fields
$('#savings-goal-amount').slider(); 
$("#savings-max-duration").slider();
</pre>
<p>The whole function should now look like this:</p>
<pre class="brush: javascript">sgs.mediator.savingsgoal.setupViewDataBindings = function(renderedNodes, boundViewModel) {
    // Declare the HTML element-level data bindings
    $("#savings-goal-amount")       .attr("data-bind","value: savingsGoalAmount");
    $("#savings-max-duration")      .attr("data-bind","value: savingsMaxDuration");
    $("#savings-target-per-month")  .attr("data-bind","text: savingsTargetPerMonthFormatted()");        
    // Ask KnockoutJS to data-bind the view model to the view
    var viewNode = $('#savings-goal-view')[0];
    var viewModel = sgs.mediator.savingsgoal.getViewModel();                
    ko.applyBindings(viewModel, viewNode);              
    // Initialize default for value models linked to masked fields 
    var pageSettings = GetPageSettings();
    viewModel.savingsGoalAmount(pageSettings.defaultSavingsGoal || 0);
    viewModel.savingsMaxDuration(pageSettings.defaultSavingsMaxDuration || 0);      
    // Add sliders to our input fields      
    $('#savings-goal-amount').slider(); 
    $("#savings-max-duration").slider();            
    if (typeof(console) != 'undefined' &amp;&amp; console) 
            console.info("sgs.mediator.savingsgoal.setupViewDataBindings done!");
}
</pre>
<p>Now let&#8217;s re-run the app, you should see the 2 sliders<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-goal-panel-increment3.png" alt="Savings Goal Panel With Sliders" title="Savings Goal Panel With Sliders" /><br />
And moving the sliders should automatically change the values.</p>
</li>
<li>
<p>Let&#8217;s shorten our labels to save space:</p>
<ul>
<li>Shorten &#8220;Savings Goal Amount:&#8221; to just &#8220;Amount:&#8221;</li>
<li>Shorten &#8220;Savings Max Duration (In Months)&#8221; to just &#8220;Period (In Months):&#8221;</li>
<li>Shorten &#8220;Savings Target Per Month:&#8221; to &#8220;Per Month:&#8221;</li>
</ul>
</li>
</ol>
<h3>Adapting The Stylesheets For Mobile Use<a id='part5-adapting-css-for-mobile-use'></a></h3>
<p>So far we have only used the default style sheets from jQuery Mobile. Let&#8217;s integrate the original application.css from the web version.</p>
<ol>
<li>
<p>In <strong>index.html</strong>, after the jQuery Mobile stylesheet, let&#8217;s include <strong>application.css</strong>:  </p>
<pre class="brush: html">&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /&gt;                   
&lt;link href="css/jquery.mobile/jquery.mobile-1.2.0.css" rel="stylesheet" type="text/css"  /&gt;  
&lt;link href="css/jquery.mobile/jquery.mobile.structure-1.2.0.css" rel="stylesheet" type="text/css"  /&gt;   
&lt;link href="css/application.css" rel="stylesheet" type="text/css"  /&gt;   
</pre>
</li>
<li>
<p>To allow the application to adapt to different form factors, we will create different CSS files and direct the browser to use the appropriate stylesheet based on the media directive.</p>
</li>
<li>
<p>Under <strong>assets/www/css</strong>, let&#8217;s create two new CSS files:</p>
<ul>
<li>application.<strong>phone</strong>.css </li>
<li>application.<strong>tablet</strong>.css </li>
<ul>
</li>
<li>
<p>In index.html, after the include for application.css, let&#8217;s add two new include statements, each specifying what values the <strong>media query</strong> should match.</p>
<pre class="brush: html">&lt;link href="css/application.tablet.css" type="text/css" rel="stylesheet" 
        media="only screen and (max-device-width: 1024px)" /&gt;
</pre>
<p>This stylesheet should be used if the maximum device width is 1024px which usually means a tablet.</p>
<pre class="brush: html">&lt;link href="css/application.iphone.css" type="text/css" rel="stylesheet" 
        media="only screen and (max-device-width: 480px)" /&gt;        
</pre>
<p>This stylesheet should be used if the maximum device width is 480px which usually means a phone.</p>
</li>
<li>
<p>Now let&#8217;s tweak our original application.css</p>
<ul>
<li>
<p>Let&#8217;s remove the styles details for the section element:  </p>
<pre class="brush: css">section
{
}
</pre>
</li>
<li>
<p>Let&#8217;s remove the standard padding for the h2 element:  </p>
<pre class="brush: css">section header h2
{
    margin: 0;
}
</pre>
</li>
<li>
<p>Let&#8217;s remove the styles details for the #savings-goal-view element:</p>
<pre class="brush: css">#savings-goal-view
{   
}
</pre>
</li>
<li>
<p>Let&#8217;s adjust the styles details for the #savings-goal-view label rule:  </p>
<pre class="brush: css">#savings-goal-view label
{
    display: inline-block;
    text-align: right;
    width: 90px;
}
</pre>
</li>
<li>
<p>Let&#8217;s adjust the styles details for the #consumption-scenarios-view rule:  </p>
<pre class="brush: css">#consumption-scenarios-view
{
    margin: 5px 0;
} 
</pre>
</li>
<li>
<p>Let&#8217;s adjust the styles details for the #savings-forecast-view rule:  </p>
<pre class="brush: css">#savings-forecast-view
{
    margin: 5px 0;
}
</pre>
</li>
<li>
<p>Let&#8217;s adjust a new rule to override the border and padding used in our jQuery Mobile ui-field-contain divs:  </p>
<pre class="brush: css">.ui-field-contain
{
    border: none;
    padding: 0;
}
</pre>
</li>
<li>
<p>Let&#8217;s adjust a new rule to override the font used in our jQuery Mobile labels:  </p>
<pre class="brush: css">.ui-field-contain label
{
    font-size: 10px;
    margin: 2px 2px;
}
</pre>
</li>
<li>
<p>Let&#8217;s adjust a new rule to override the width used in our jQuery Mobile sliders:  </p>
<pre class="brush: css">div.ui-slider
{
    width: 30%;
}
</pre>
</li>
<li>
<p>Let&#8217;s create an override rule for the collapsible panels:</p>
<pre class="brush: css">.ui-collapsible-inset .ui-collapsible-content
{
    border-color: black;
    border-style: solid;
    border-width: 1px;
}
</pre>
</li>
</ul>
</li>
<li>
<p>Let&#8217;s run the app in the browser and simulator to see our new styling:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-goal-panel-increment4.png" alt="Savings Goal Panel With New Styling" title="Savings Goal Panel With New Styling" />  </p>
</li>
</ol>
<p>At this point we could continue adapting the look of the Savings Goal panel, by adjusting the CSS styles to make it fit a little bit more tightly. The easiest way to do that is to use your trusted browser developer tool to learn what styles are being used by jQuery Mobile and to experiment.</p>
<p>I will leave this as an exercise for the reader. </p>
<h3>Adapting The Consumption Scenarios View For Mobile Use<a id='part5-adapting-consumption-scenario-view-for-mobile-use'></a></h3>
<p>In the web version of the application, the different type of coffee consumption options consists or set of radio buttons layed out in a table. But at minimum for a phone version of the app we need to <strong>conserve the vertical space</strong> so we can see the goals, a subset of the consumption options, and the savings forecast. </p>
<p>So let&#8217;s use <strong>collapsible panels</strong> for each type of consumption option such as &#8220;type&#8221; (of beverage), size, and frequency. This way as a user you can expand the option you want to play with, tweak the current and proposed settings, see the impact on the forecast, and repeat the process.</p>
<ol>
<li>
<p>First, let&#8217;s make a copy of the <strong>_consumption-scenarios.view.html</strong> file under assets/www/scripts/view/index and rename the copy to _consumption-scenarios.<strong>web</strong>.view.html and change the reference to the file in <strong>index.web.html</strong>:</p>
<pre class="brush: html">&lt;script id='consumption-scenarios-view-template'
        type='text/html'
        src='scripts/view/index/_consumption-scenarios.web.view.html' &gt;&lt;/script&gt;
</pre>
<p>Again we now have a baseline of the original web version.</p>
</li>
<li>
<p>Now open the <strong>_consumption-scenarios.view.html</strong> file in Aptana Studio. Locate the header tag, and let&#8217;s wrap the &#8220;Weekly Coffee Consumption&#8221; title in an h2 tag:</p>
<pre class="brush: html">&lt;header&gt;
    &lt;h2&gt;Weekly Coffee Consumption&lt;/h2&gt;
&lt;/header&gt;
</pre>
</li>
<li>
<p>Right below the header but before the table, let&#8217;s add a div of [jQuery Mobile] data-role &#8220;<strong>collapsible-set</strong>&#8221; indicating that contained elements of data-role &#8220;collapsible&#8221; can be grouped together.</p>
<pre class="brush: html">&lt;div id="weekly-consumption-accordion" data-role="collapsible-set"&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>Let&#8217;s add a div of data-role &#8220;<strong>collapsible</strong>&#8221; for our consumption type option. The div will contain a h3 for the panel title, followed by a table element to hold the details of our option</p>
<pre class="brush: html">&lt;div id="weekly-consumption-accordion" data-role="collapsible-set"&gt;
    &lt;div data-role="collapsible" data-theme="a"  data-mini="true" &gt;
        &lt;h3&gt;Consumption Type&lt;/h3&gt;
        &lt;table&gt;
            &lt;tr&gt;
                &lt;th&gt;Current Habits&lt;/th&gt;
                &lt;th&gt;Proposed Change&lt;/th&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>Now we can move the markup related to the drink types from the original table over to the second row of our new table within the collapsible div:</p>
<pre class="brush: html">&lt;div id="weekly-consumption-accordion" data-role="collapsible-set"&gt;
    &lt;div data-role="collapsible" data-theme="a"  data-mini="true" &gt;
        &lt;h3&gt;Consumption Type&lt;/h3&gt;
        &lt;table&gt;
            &lt;tr&gt;
                &lt;th&gt;Current Habits&lt;/th&gt;
                &lt;th&gt;Proposed Change&lt;/th&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &lt;div id="current-drink-type"&gt;
                        &lt;input type="radio" id="current-drink-regular"  name="CurrentDrinkType" value="Regular" /&gt;
                            &lt;label for="current-drink-regular"&gt;Regular&lt;/label&gt;&lt;br/&gt;
                        &lt;input type="radio" id="current-drink-latte"  name="CurrentDrinkType" value="Latte" /&gt;
                            &lt;label for="current-drink-latte"&gt;Latte&lt;/label&gt;&lt;br/&gt;
                        &lt;input type="radio" id="current-drink-espresso"  name="CurrentDrinkType" value="Espresso" /&gt;
                            &lt;label for="current-drink-espresso"&gt;Espresso&lt;/label&gt;&lt;br/&gt;
                    &lt;/div&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;div id="proposed-drink-type"&gt;
                        &lt;input type="radio" id="proposed-drink-regular"  name="ProposedDrinkType" value="Regular" /&gt;
                            &lt;label for="proposed-drink-regular"&gt;Regular&lt;/label&gt;&lt;br/&gt;
                        &lt;input type="radio" id="proposed-drink-latte"  name="ProposedDrinkType" value="Latte" /&gt;
                            &lt;label for="proposed-drink-latte"&gt;Latte&lt;/label&gt;&lt;br/&gt;
                        &lt;input type="radio" id="proposed-drink-espresso"  name="ProposedDrinkType" value="Espresso" /&gt;
                            &lt;label for="proposed-drink-espresso"&gt;Espresso&lt;/label&gt;&lt;br/&gt;
                    &lt;/div&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>Let&#8217;s remove all the &lt;br/&gt; tags since we no longer need them since jQuery Mobile is enhancing our DOM and styling new elements. </p>
</li>
<li>
<p>Let&#8217;s run in the browser and the simulator.<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-scenarios-panel-increment1.png" alt="Collapsible Consumption Type Panel" title="Collapsible Consumption Type Panel" />  </p>
<p>You will notice a couple things:</p>
<ul>
<li>
<p>The collapsible element does expand and collapse when we toggle it</p>
</li>
<li>
<p>jQuery Mobile has rendered our radio buttons as regular buttons. Apparently jQuery Mobile require a radio button group to be codified as a <strong>fieldset</strong> with a data-role of &#8220;<strong>controlgroup</strong>&#8220;.<br />
So let&#8217;s replace our div for the current-drink-type:</p>
<pre class="brush: html">&lt;div id="current-drink-type"&gt;
    &lt;!-- ... --&gt;
&lt;/div&gt;
</pre>
<p>by a fieldset &#8211; note that we&#8217;ll request a &#8220;mini&#8221; version (using data-mini=&#8221;true&#8221;) to minimize the vertical space taken by the resulting jQuery Mobile radio button group:</p>
<pre class="brush: html">&lt;fieldset id="current-drink-type" data-role="controlgroup" data-mini="true"&gt;
    &lt;!-- ... --&gt;
&lt;/fieldset&gt;
</pre>
<p>Let&#8217;s re-run:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-scenarios-panel-increment2.png" alt="Collapsible Consumption Type Panel" title="Collapsible Consumption Type Panel" />   </p>
</li>
</ul>
</li>
<li>
<p>Now let&#8217;s repeat the process for the other 2 types of consumption options (Size and Frequency):</p>
<ul>
<li>Add a div of data-role &#8220;<strong>collapsible</strong>&#8221; for our consumption option. The div will contain a h3 for the panel title, followed by a table element to hold the details of our option.</li>
<li>Move the markup related to the consumption option from the original table over to the second row of our new table within the collapsible div</li>
<li>Change the div containing the radio buttons into a fieldset of data-role &#8220;radiobuttongroup&#8221;</li>
</ul>
</li>
<li>
<p>For the frequency collapsible panel, the &#8220;Other:&#8221; option has an input field associated with it. So we will need to wrap the input field with a div of data-role &#8220;field-contain&#8221;, and add HTML5 type, min and max attributes:</p>
<pre class="brush: html">&lt;div data-role="fieldcontain"&gt;
    &lt;input type="text" 
            id="current-custom-frequency" 
            name="CurrentCustomFrequency"
            type="number" min="1" max="999" maxlength="3" /&gt;
&lt;/div&gt;
</pre>
<p>To allow the input field to be positioned to the right of the radio button, we will need to move the markup for data-role &#8220;fieldcontain&#8221; inside the label tag of the radio button like so:</p>
<pre class="brush: html">&lt;label for="current-frequency-other"&gt;Other:
    &lt;div data-role="fieldcontain"&gt;
        &lt;input type="text" 
                id="current-custom-frequency" 
                name="CurrentCustomFrequency"
                type="number" min="1" max="999" maxlength="3" /&gt;
    &lt;/div&gt;
&lt;/label&gt;
</pre>
<p>If you run in the browser or simulator, you will notice that the input field is not positioned where we would like it. So let&#8217;s add a CSS class on the div <strong>data-role &#8220;fieldcontain&#8221;</strong> named &#8220;<strong>other-input</strong>&#8220;:  </p>
<pre class="brush: html">    &lt;div data-role="fieldcontain" class="other-input"&gt;
        &lt;input type="text" 
                id="current-custom-frequency" 
                name="CurrentCustomFrequency"
                type="number" min="1" max="999" maxlength="3" /&gt;
    &lt;/div&gt;
</pre>
<p>And let&#8217;s define the new class in <strong>application.css</strong>: </p>
<pre class="brush: css">.other-input
{
    display: inline-block;
    left: -20px;
    margin: 0 0 5px 0;
    top: -10px;
    width: 30px;    
}


.other-input input
{
    height: 24px;
}
</pre>
<p>Let&#8217;s re-run:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-scenarios-panel-increment3.png" alt="Collapsible Consumption Frequency Panel" title="Collapsible Consumption Frequency Panel" />   </p>
<p>Now the positioning is much better!</p>
</li>
<li>
<p>For the number of drinks per day, let&#8217;s create a <strong>separate collapsible panel</strong> like so:</p>
<pre class="brush: html">    &lt;div data-role="collapsible" data-theme="a"  data-mini="true" &gt;
        &lt;h3&gt;Drinks Per Day&lt;/h3&gt;
        &lt;table&gt;
            &lt;tr&gt;
                &lt;th&gt;Current Habits&lt;/th&gt;
                &lt;th&gt;Proposed Change&lt;/th&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &lt;input type="text" id="current-drinks-per-day" name="CurrentDrinksPerDay" /&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;input type="text" id="proposed-drinks-per-day" name="ProposedDrinksPerDay" /&gt;
                &lt;/td&gt;
            &lt;/tr&gt;               
        &lt;/table&gt;
    &lt;/div&gt;
</pre>
<p>Let&#8217;s re-run:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-scenarios-panel-increment4.png" alt="Collapsible Drinks Per Day Panel" title="Collapsible Drinks Per Day Panel" />   </p>
</li>
<li>
<p>Now we need to cleanup the bottom remaining table in _consumption-scenarios.view.html.<br />
Let&#8217;s give the table an id of <strong>consumption-summary-table</strong>:  </p>
<pre class="brush: html">&lt;table id="consumption-summary-table"&gt;
&lt;/table&gt;
</pre>
<p>Let&#8217;s cleanup the obsolete table header and let&#8217;s reuse it for our weekly summary.</p>
<pre class="brush: html">&lt;thead&gt;
    &lt;tr&gt;
        &lt;th&gt;Weekly Summary&lt;/th&gt;
        &lt;th&gt;Current Habits&lt;/th&gt;
        &lt;th&gt;Proposed Change&lt;/th&gt;
    &lt;/tr&gt;
&lt;/thead&gt;
</pre>
<p>And remove the obsolete column titles:</p>
<pre class="brush: html">&lt;tbody&gt;
    &lt;tr&gt;                    
        &lt;td&gt;Type:&lt;/td&gt;
    &lt;/tr&gt;       
    &lt;tr&gt;
        &lt;td&gt;Size:&lt;/td&gt;
    &lt;/tr&gt;           
    &lt;tr&gt;
        &lt;td&gt;Frequency:&lt;/td&gt;
    &lt;/tr&gt;
    &lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>Let&#8217;s define styling for consumption-summary-table in application.css:</p>
<pre class="brush: html">#consumption-summary-table
{
    border-radius: 8px;
    background-color: white;
    width: 100%;
}


#consumption-summary-table th
{
    border-bottom: 1px solid Grey;  
}
</pre>
<p>Let&#8217;s re-run:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-scenarios-panel-increment5.png" alt="Collapsible Consumption Option Panels" title="Collapsible Consumption Option Panels" />   </p>
<p>You will notice that we&#8217;re pretty close to our goal of optimizing for the vertical height of a phone!  </p>
</li>
</ol>
<h3>Adapting The Savings Forecast View For Mobile Use<a id='part5-adapting-savings-forecast-view-for-mobile-use'></a></h3>
<ol>
<li>
<p>First, let&#8217;s make a copy of the <strong>_savings-forecast.view.html</strong> file under assets/www/scripts/view/index and rename the copy to _savings-forecast.<strong>web</strong>.view.html and change the reference to the file in <strong>index.web.html</strong>:</p>
<pre class="brush: html">&lt;script id='savings-forecast-view-template'
        type='text/html'
        src='scripts/view/index/__savings-forecast.web.view.html' &gt;&lt;/script&gt;
</pre>
<p>Again we now have a baseline of the original web version.</p>
</li>
<li>
<p>Now open the <strong>_savings-forecast.view.html</strong> file in Aptana Studio. To maximize vertical space, let&#8217;s turn the current markup into a horizontal table where the labels become column headers. We&#8217;ll also shorten the column headers and the unit of measure in each data cell:</p>
<pre class="brush: html">&lt;section id='savings-forecast-view'&gt;
    &lt;table id='savings-forecast-table'&gt; 
        &lt;tr&gt;
            &lt;th&gt;Forecast&lt;/th&gt;
            &lt;th&gt;Variance&lt;/th&gt;
            &lt;th&gt;Months&lt;/th&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span id="savings-forecast-per-month" &gt;&lt;/span&gt;/m&lt;/td&gt;
            &lt;td&gt;&lt;span id="forecast-variance-per-month"&gt;&lt;/span&gt;/m&lt;/td&gt;
            &lt;td&gt;&lt;span id="time-to-goal-in-months"&gt;&lt;/span&gt;m&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/section&gt; 
</pre>
</li>
<li>
<p>Let&#8217;s define styles for our new table in application.css:  </p>
<pre class="brush: css">#savings-forecast-table {
    width: 100%;
}


#savings-forecast-table tr td {
    text-align: center;
}


#savings-forecast-view input
{
    width: 30px;
}
</pre>
<p>Run the app:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-forecast-panel-increment1.png" alt="Forecast Panel" title="Forecast Panel" />   </p>
</li>
<li>
<p>Ideally we would like the forecast panel to be visible at all times. An idea is to integrate it in the footer of the page and &#8220;<strong>pin</strong>&#8221; the footer at the bottom of the screen.<br />
So open the <strong>index.html</strong> page, and let&#8217;s move the script include for the <strong>savings-forecast-view-template</strong> and the actual <strong>savings-forecast-view-container</strong> div into the footer:</p>
<pre class="brush: html">&lt;div data-role="footer" data-position="fixed"  data-theme="e"&gt;
    &lt;script id='savings-forecast-view-template'
            type='text/html'
            src='scripts/view/index/_savings-forecast.view.html' &gt;&lt;/script&gt;
    &lt;div id='savings-forecast-view-container'
            data-bind='template: { name: "savings-forecast-view-template", afterRender: sgs.mediator.savingsforecast.setupViewDataBindings } ' &gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>To &#8220;<strong>pin</strong>&#8221; the header, let&#8217;s add a <strong>data-position=&#8221;fixed&#8221;</strong> and <strong>data-fullscreen=&#8221;true&#8221;</strong> as attributes on the footer. And while were at it let&#8217;s specify a different jQuery Mobile theme for the footer using <strong>data-theme=&#8221;e&#8221;</strong>.</p>
<pre class="brush: html">&lt;div data-role="footer" data-position="fixed" data-fullscreen="true" data-theme="e"&gt;
    &lt;!-- --&gt;
&lt;/div&gt;
</pre>
<p>Let&#8217;s refresh:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-forecast-panel-increment2.png" alt="Forecast Panel" title="Forecast Panel" />   </p>
<p>This is much nicer!</p>
</li>
</ol>
<h3>More Visual Tweaks<a id='part5-more-visual-tweaks'></a></h3>
<ol>
<li>
<p>In the <strong>index.html</strong>, let&#8217;s customize the jQuery Mobile <strong>theme</strong> to be used on all its widgets</p>
<pre class="brush: html">&lt;div id="page-home" data-role="page" data-content-theme="b"&gt;
    &lt;!-- ... --&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>Let&#8217;s increase the horizontal <strong>padding</strong> for all section elements:</p>
<pre class="brush: css">section
{
    padding: 0px 2px;
}
</pre>
</li>
<li>
<p>Let&#8217;s tweak the <strong>height</strong> of the <strong>#page-home</strong> div and its <strong>data-role=&#8221;content&#8221;</strong> div:</p>
<pre class="brush: css">#page-home 
{
    height: 100%;
    overflow: hidden;
}


#page-home div.ui-content
{
    height: 88%;
}
</pre>
</li>
<li>
<p>Let&#8217;s move the &#8220;Per Month&#8221; elements from the bottom of the savings goal panel to the section header:</p>
<pre class="brush: html">&lt;header&gt;
    &lt;h2&gt;Goal&lt;/h2&gt;
    &lt;div id="target-per-month" data-role="fieldcontain"&gt;
        &lt;label for="savings-target-per-month"&gt;Per Month:&lt;/label&gt;
        &lt;span id="savings-target-per-month"&gt;&lt;/span&gt;
    &lt;/div&gt;
&lt;/header&gt;
</pre>
<p>And let&#8217;s add the following styles to application.css:  </p>
<pre class="brush: css">#savings-goal-view header h2 {
    display: inline-block; 
}


#target-per-month {
  display: inline-block;
  right: -114px;
}


#savings-goal-view #target-per-month label
{
    min-width: 30px;
}


#savings-goal-view #savings-target-per-month {
    font-size: 0.8em;
}
</pre>
</li>
<li>
<p>Let&#8217;s remove the word &#8220;Consumption&#8221; from our collapsible panels.</p>
</li>
<li>
<p>Let&#8217;s re-run:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-newlook.png" alt="New Look" title="New Look" />   </p>
<p>The look is now a bit more &#8220;professional&#8221;, the visual elements stand out and the vertical positioning is optimized.</p>
</li>
</ol>
<h3>UI &#8220;Feel&#8221; / Behavior Tweaks<a id='part5-ui-feel-behavior-tweaks'></a></h3>
<p>Originally the web app depended on jQuery UI, but since we&#8217;re usin jQuery Mobile instead, we will need to tweak the mediators associated with our panels.</p>
<ol>
<li>
<p>Two view mediators use the jQuery UI <strong>highlight</strong> effect to provide a visual indication of key changes. But now that we have sliders, the effect would take too long since it would be triggered on each mouse move. So let&#8217;s remove the effect.   </p>
</li>
<li>
<p>Open <strong>sgs.mediator.savings-goal.js</strong> under <strong>assets\www\scripts\viewmediator</strong> and look for a call to the <strong>effect</strong> function:</p>
<pre class="brush: javascript">viewModel.savingsTargetPerMonthFormatted.subscribe(function() {
    $("#savings-target-per-month")
        .effect('highlight', { color: 'LightGreen' }, 3000); // for 3 seconds
});
</pre>
<p>and let&#8217;s remove the overall statement altogether:</p>
<pre class="brush: javascript">viewModel.savingsTargetPerMonthFormatted.subscribe(function() {
    // Placeholder for future use
});
</pre>
</li>
<li>
<p>Open <strong>sgs.mediator.consumption-scenarios.js</strong> and repeat the process:  </p>
<pre class="brush: javascript">viewModel.savingsPerWeekFormatted.subscribe(function() {
    // Placeholder for future use
});
</pre>
</li>
</ol>
<p>So if you had been noticing exceptions for the effect call in the browser console, now these are a thing of the past.</p>
<h3>Adding An Other jQuery Mobile Page<a id='part5-adding-another-jquery-mobile-page'></a></h3>
<p>Currently our application has only one jQuery Mobile &#8220;<strong>logical page</strong>&#8220;, that is, a div with a <strong>data-role=&#8221;page&#8221;</strong>. It would be nice if we could have another page to edit the coffee beverage list prices! jQuery Mobile allow the definition of multiple pages and provide associated navigation mechanisms. So let&#8217;s see how to do that.</p>
<ol>
<li>
<p>First, in the <strong>index.html</strong>, before the end of the body tag, let&#8217;s add the shell for our new page:</p>
<pre class="brush: html">&lt;div id="coffee-pricing-dialog"
     data-role="page" 
     data-content-theme="b" 
     data-url="edit-coffee-pricing.html" &gt;
        Shell for our price list!
       &lt;/div&gt;
&lt;/div&gt;
</pre>
</li>
<li>
<p>We need a button to navigate to the new page. Let&#8217;s edit <strong>_consumption-scenarios.view.html</strong> and add a button (div with <strong>data-role=&#8221;button&#8221;</strong>) in the <strong>header</strong>, after the <strong>h2</strong> title:</p>
<pre class="brush: html">&lt;section id='consumption-scenarios-view'&gt;
    &lt;header&gt;
        &lt;h2&gt;Weekly Coffee Consumption&lt;/h2&gt;
        &lt;a id="edit-pricing-button" href="#coffee-pricing-dialog" class="ui-btn-right"
            data-rel="dialog" 
            data-role="button" 
            data-mini="true"
            data-icon="gear"
            data-theme="e" &gt;Pricing&lt;/a&gt;
    &lt;/header&gt;
    &lt;!-- ... ---&gt; 
&lt;/section&gt;
</pre>
<p>You will notice that we specified a <strong>data-rel</strong> attribute with a value of &#8220;<strong>dialog</strong>&#8220;. This tells jQuery Mobile that we would like a pop-up transition effect and a dialog theme: dark background, rounded corners, etc.. See the <a href="http://jquerymobile.com/demos/1.2.0/docs/pages/dialog/index.html">Dialog documentation</a> for more details.</p>
<p>If you run the app in the simulator, you should see the new Pricing button:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-button.png" alt="New Pricing Button" title="New Pricing Button" />   </p>
<p>And clicking on it will cause the navigation to the new page to occur:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-panel-shell.png" alt="New Pricing Panel Shell" title="New Pricing Panel Shell" />   </p>
<p>If you hit the back button, the page-home page will be displayed again (without any of our values to be lost &#8211; since the pages are just hidden/shown during the navigation process).</p>
</li>
<li>
<p>Like for other panels, let&#8217;s externalize the markup for our new pricing page. So let&#8217;s create a new markup folder (one for each page) under <strong>assets/www/scripts/</strong>views/named &#8220;<strong>pricing</strong>&#8220;, and then create a file named <strong>index.view.html</strong>, an cut/paste our shell message inside the following template:</p>
<pre class="brush: html">&lt;section id='coffee-pricing-view'&gt;
    &lt;header data-role="header"&gt;
        &lt;h3&gt;Edit Pricing&lt;/h3&gt;
    &lt;/header&gt;           
    &lt;div data-role="content"&gt;
        Shell for our price list!
    &lt;/div&gt;
&lt;/section&gt;
</pre>
</li>
<li>
<p>To render the externalized view we have to:</p>
<ul>
<li>include a text/html template script reference in the main index.html file</li>
<li>create a container div data-bound to the template</li>
<li>ask KnockoutJS to render it. </li>
</ul>
<p>So remove the &#8220;Shell for our price list!&#8221; content from the <strong>coffee-pricing-dialog</strong> div and replace it with:</p>
<pre class="brush: html">&lt;script id='coffee-pricing-view-template'
        type='text/html'
        src='scripts/view/pricing/index.view.html' &gt;
&lt;/script&gt;
</pre>
<p>This allows the inclusion of our new jQuery template in the app.<br />
And right below let&#8217;s add our div container:  </p>
<pre class="brush: html">&lt;div id='coffee-pricing-view-container'
        data-bind='template: { name: "coffee-pricing-view-template", afterRender: sgs.mediator.coffeepricing.setupViewDataBindings} ' &gt;
&lt;/div&gt;
</pre>
<p>Note: the <strong>afterRender</strong> callback references a <strong>setupViewDataBindings</strong> function we have not yet created in the sgs.mediator.coffeepricing module. So if you run the app now, the content of the view will not be rendered. </p>
</li>
<li>
<p>Open up the <strong>sgs.mediator.coffeepricing.js</strong> module under <strong>assets/www/scripts/viewmediator</strong> and let&#8217;s create a shell for the <strong>setupViewDataBindings</strong> function:</p>
<pre class="brush: javascript">sgs.mediator.coffeepricing.setupViewDataBindings = function(renderedNodes, boundViewModel) {


}
</pre>
<p>Then let&#8217;s update the <strong>createViewMediator</strong> function to request <strong>data binding</strong> of the coffee pricing <strong>view container</strong> with the <strong>template</strong>. This will cause KnockoutJS to render the template using jQuery Template:</p>
<pre class="brush: javascript">sgs.mediator.coffeepricing.createViewMediator = function (pageSettings) {
    // Create the view Pricing Editor view-specific view model
    var viewModel = sgs.model.coffeepricing.initializeViewModel(pageSettings);
    // Save the view model
    sgs.mediator.coffeepricing.setViewModel(viewModel);         
    // Ask KnockoutJS to data-bind the view model to the view
    var viewNode = $('#coffee-pricing-view-container')[0];
    var viewModel = sgs.mediator.coffeepricing.getViewModel();
    ko.applyBindings(viewModel, viewNode);      
    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("sgs.mediator.coffeepricing ready!");  
}
</pre>
<p>Now we can expand the code for <strong>setupViewDataBindings</strong> to data-bind the coffee pricing <strong>view</strong> div with our KnockoutJS coffee pricing <strong>view model</strong>:</p>
<pre class="brush: javascript">sgs.mediator.coffeepricing.setupViewDataBindings = function(renderedNodes, boundViewModel) {
    // Apply the bindings
    var viewNode = $('#coffee-pricing-view')[0];
    var viewModel = sgs.mediator.coffeepricing.getViewModel();
    ko.applyBindings(viewModel, viewNode);
    // Get jQuery Mobile to refresh/enhance the page        
    $('#coffee-pricing-dialog').trigger('create');
}
</pre>
<p>Now if run the app and click on the pricing button we should see our new pricing shell page:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-panel-externalized.png" alt="Externalized Pricing Panel Shell" title="Externalized Pricing Panel Shell" />   </p>
</li>
<li>
<p>Let&#8217;s add some input fields to our pricing/<strong>index.view.html</strong> view to capture the pricing data:</p>
<pre class="brush: html">&lt;section id='coffee-pricing-view'&gt;
    &lt;header data-role="header"&gt;
        &lt;h3&gt;Edit Pricing&lt;/h3&gt;
    &lt;/header&gt;           
    &lt;div data-role="content"&gt;
        &lt;div class="ui-bar ui-bar-b" data-position="inline"&gt;
            Regular Coffee
        &lt;/div&gt;
        &lt;div data-role="fieldcontain"&gt;
            &lt;label for="pricing-regular-tall"&gt;Tall:&lt;/label&gt;
            &lt;input id="pricing-regular-tall" type="number" min="1" max="5" maxlength="4" /&gt;
        &lt;/div&gt;              
        &lt;div data-role="fieldcontain"&gt;
            &lt;label for="pricing-regular-grande"&gt;Grande:&lt;/label&gt;
            &lt;input id="pricing-regular-grande" type="number" min="1" max="5" maxlength="4" /&gt;
        &lt;/div&gt;              
        &lt;div data-role="fieldcontain"&gt;
            &lt;label for="pricing-regular-venti"&gt;Venti:&lt;/label&gt;
            &lt;input id="pricing-regular-venti" type="number" min="1" max="5" maxlength="4" /&gt;
        &lt;/div&gt;      
    &lt;/div&gt;
&lt;/section&gt;  
</pre>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-panel-regular-coffee.png" alt="Regular Coffee Pricing Shell" title="Regular Coffee Pricing Shell" />   </p>
<p>You can repeat the process for the beverages like caffe latte and espresso.    </p>
<p>If you run the app you will see an empty dialog since we have not created a value models for each of the pricing options in the pricing view model, nor  added the data binding for the various fields yet.  </p>
</li>
<li>
<p>If we look at the current definition of our coffee pricing <strong>view model</strong>, we&#8217;ll see that it includes only one <strong>value model</strong>: &#8220;<strong>pricing</strong>&#8220;:</p>
<pre class="brush: javascript">sgs.model.coffeepricing.initializeViewModel = function (pageSettings) {  
    // ...          
    // Lazy-initialize the price list
    var priceList = sgs.model.coffeepricing.getPriceList();         
    var viewModel = {
        pricing:        ko.observable(priceList)
    }  
    // ...          
    return viewModel;  
}
</pre>
<p>If we evaluate / inspect the both the <strong>view model</strong> and the <strong>pricing value model</strong> in the browser tools console we&#8217;ll see:  </p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-viewmodel-current.png" alt="Current Coffee Pricing ViewModel" title="Current Coffee Pricing ViewModel" />   </p>
<p>But so the coffee pricing view model does not have a separate <strong>value model</strong> for each <strong>property</strong> of the pricing value model. We have two options: a) declare a value model for each property, or b) leverage the dynamic nature of Javascript to dynamically declare a new value model  for each property of our pricing object. Let&#8217;s choose the latter approach.<br />
Let&#8217;s add a new function named <strong>publishPriceList</strong> to our sgs.model.coffeepricing module. </p>
<pre class="brush: javascript">sgs.model.coffeepricing.publishPriceList = function (viewModel) {
    var priceList = viewModel.pricing();
    // Find all property names for the pricing object
    var productKeys = Object.keys(priceList);           
    // Process all properties
    for ( var i = 0; i &lt; productKeys.length; i++) {
        // Get product details
        var productKey = productKeys[i];
        var productPrice = priceList[productKey];
        // Create an observable name based on the property
        var observableName = 'pricing' + productKey.replace('-','');        
        // Check if we already have value model (observable) with the same name
        var valueModel = viewModel[observableName];
        if (typeof(valueModel) == 'undefined') {
            // Dynamically create a value model
            valueModel = ko.observable(null);
            // Add it to the overall view model
            viewModel[observableName] = valueModel;
        }               
        // Update the value model's actual pricing
        valueModel(productPrice);
    }
}
</pre>
<p>You can test it in the browser console by evaluating:  </p>
<p>sgs.model.coffeepricing.publishPriceList(sgs.mediator.coffeepricing.getViewModel())</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-viewmodel-enhanced.png" alt="Enhanced Coffee Pricing ViewModel" title="Enhanced Coffee Pricing ViewModel" />   </p>
<p>You now see the new value models!<br />
So let&#8217;s add a call to the <strong>publishPriceList</strong> function from <strong>initializeViewModel</strong>:</p>
<pre class="brush: javascript">sgs.model.coffeepricing.initializeViewModel = function (pageSettings) {
    // ..
    var priceList = sgs.model.coffeepricing.getPriceList();         
    var viewModel = {
        pricing:        ko.observable(priceList)
    }           
    // Publish the pricing data as individual value models
    sgs.model.coffeepricing.publishPriceList(viewModel);            
    // ...
    return viewModel;
}
</pre>
<p>This way the <strong>new value models</strong> will be created <strong>upon initialization</strong> of the view model.</p>
</li>
<li>
<p>Now we can add the corresponding <strong>data bindings</strong> in the <strong>setupViewDataBindings</strong> function of the sgs.mediator.coffee-pricing.js module:</p>
<pre class="brush: javascript">sgs.mediator.coffeepricing.setupViewDataBindings = function(renderedNodes, boundViewModel) {
    // Ask KnockoutJS to data-bind the view model to the view
    $("#pricing-regular-tall").attr("data-bind","value: pricingRegularTall");
    $("#pricing-regular-grande").attr("data-bind","value: pricingRegularGrande");
    $("#pricing-regular-venti").attr("data-bind","value: pricingRegularVenti");
    // Apply the bindings
    var viewNode = $('#coffee-pricing-view')[0];
    var viewModel = sgs.mediator.coffeepricing.getViewModel();
    ko.applyBindings(viewModel, viewNode);
    // Get jQuery Mobile to refresh/enhance the page
    $('#coffee-pricing-dialog').trigger('create');
}
</pre>
<p>If we re-run the app we now see the pricing details:<br />
<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-panel-regular-coffee-databound.png" alt="Regular Coffee Pricing" title="Regular Coffee Pricing" /></p>
<p>And if you update a price, close the dialog, then reopen it the new pricing is still there. But you might notice that the calculations are not reflecting the price update. And if you closed and terminated the mobile app and relaunched it your new price would be lost. </p>
</li>
<li>
<p>What we need is to add logic to <strong>save the new pricing data</strong> once we&#8217;re done with our updates on the pricing dialog. First, let&#8217;s add a <strong>save</strong> button to the pricing/<strong>index.view.html</strong> view:  </p>
<pre class="brush: html">&lt;section id='coffee-pricing-view'&gt;
    &lt;!-- ... --&gt;            
    &lt;div data-role="content"&gt;
    &lt;!-- ... --&gt;            
        &lt;a id="save-pricing-button" href="#" 
                data-rel="back"
                data-role="button" 
                data-icon="check"
                data-theme="e" &gt;Save Pricing&lt;/a&gt;
    &lt;/div&gt;
&lt;/section&gt;
</pre>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-save-button.png" alt="Save Pricing Button" title="Save Pricing Button" /></p>
</li>
<li>
<p>Let&#8217;s add a <strong>click event handler</strong> for our new button in the <strong>setupViewDataBindings</strong> function of the sgs.mediator.coffee-pricing.js module.</p>
<pre class="brush: javascript">sgs.mediator.coffeepricing.setupViewDataBindings = function(renderedNodes, boundViewModel) {
    // ...  
    // Get jQuery Mobile to refresh/enhance the page
    $('#coffee-pricing-dialog').trigger('create');          
    // Add a click handler of the Save Pricing button
    $('#save-pricing-button')
        .die('click')
        .bind('click',sgs.mediator.coffeepricing.savePriceList);            
}
</pre>
</li>
<li>
<p>Le&#8217;s define the sgs.mediator.coffeepricing.savePriceList and make it call savePriceList in sgs.model.coffee-pricing.js module:</p>
<pre class="brush: javascript">sgs.mediator.coffeepricing.savePriceList = function() {
    sgs.model.coffeepricing.savePriceList();
}
</pre>
</li>
<li>
<p>We just need to implement the new <strong>savePriceList</strong> function in the sgs.model.coffee-pricing.js module. For now let&#8217;s create a shell:</p>
<pre class="brush: javascript">sgs.model.coffeepricing.savePriceList = function () {  
}
</pre>
</li>
<li>
<p>The requirements for the savePriceList are to:</p>
<ul>
<li>Apply the current data of the individual price value models back to the master pricing value model</li>
<li>Save our pricing value model data to local storage using the jStorage library</li>
</ul>
<p>Here is the code:  </p>
<pre class="brush: javascript">sgs.model.coffeepricing.savePriceList = function () {
    var viewModel = sgs.mediator.coffeepricing.getViewModel();
    var priceList = viewModel.pricing();
    // Find all property names for the pricing object
    var productKeys = Object.keys(priceList);
    // Process all properties
    for ( var i = 0; i &lt; productKeys.length; i++) {
        // Get product details
        var productKey = productKeys[i];
        // Find the corresponding observable
        var observableName = 'pricing' + productKey.replace('-','');
        var valueModel = viewModel[observableName];
        // Update the value model
        var productPrice = parseFloat(valueModel());
        priceList[productKey] = productPrice;
    }
    // Store the updated pricing in local storage
    $.jStorage.set("coffee-price-list", priceList);
}
</pre>
</li>
<li>
<p>If you re-run the app, you now should be able to see the impact of updating the pricing of a regular tall coffee from 1.4 to 1.5. And if you restart the app you should see that your pricing data had been  saved and restored.<br />
In the browser developer toolls, you should be able to inspect the local storage and confirm that your can see your pricing data:</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part5-sgs-pricing-local-storage.png" alt="Pricing In Local Storage" title="Pricing In Local Storage" /></p>
</li>
</ol>
<p>At this point you have a well-rounded mobile version of the Savings Goal Simulator!</p>
<p>Note: as an exercise for the reader, go ahead and externalize the content of the #page-home as a separate template named <strong>index.view.html</strong> in the <strong>assets/www/views/index</strong> folder. This will keep the overall index.html main page as small as possible.</p>
<h3>Phone And Table Versions Of The App<a id='part5-phone-and-tablet-versions'></a></h3>
<p>Currently we have an index.html which is primarily designed to fit on a phone. And although it will take the full size of the display on a tablet, the application will still work fine. But what if we want to offer a more optimized design for a tablet such as for example do away with collapsible sections, or change the layout of the app?</p>
<p>Well, this is where the <strong>modularity</strong> of our views and application, plus the use of HTML and CSS will pay off.</p>
<p>Two approaches can be considered based on your design need:</p>
<ol>
<li>Have a separate main web page for the phone and for the tablet version and launch the appropriate page based on the device display size.  </li>
<li>Keep a single web page, but just custom CSS stylesheets to tweak the layout as needed</li>
</ol>
<p>The first option provide the most flexibility, so let&#8217;s look at how to implement it.</p>
<p>Let&#8217;s look back at the code we used in the &#8220;controller&#8221; or &#8220;launcher&#8221; (implemented as Java Activity on the Android platform):</p>
<pre class="brush: javascript">    package com.yournamespace.savingsgoalsimulator;

    import android.os.Bundle;
    import org.apache.cordova.*;

    public class MainActivity extends DroidGap {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            super.loadUrl("file:///android_asset/www/index.html");
        }

    }
</pre>
<p>At a high-level, we need to:</p>
<ul>
<li>Rename our index.html to index.<strong>phone</strong>.html</li>
<li>Clone our index.phone.html into a new index.<strong>tablet</strong>.html</li>
<li>Change the <strong>onCreate</strong> method to detect the device size and load index.phone.html or index.tablet.html</li>
</ul>
<p>Here is an implementation for onCreate based on a check for the width of the device:</p>
<pre class="brush: javascript">
        @Override
        public void onCreate(Bundle savedInstanceState) {
            protected float TABLET_WIDTH = 768;

            super.onCreate(savedInstanceState);

            // Get actual screen size so we can determine if the device is a tablet or not
            Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            int width  = display.getWidth(); 
            int height = display.getHeight(); 

            // Is the width is at least the minimum width of a tablet?
            boolean isTablet = (width &gt;= TABLET_WIDTH); 
            Log.v("Device size detection", "width=" + width + " height=" + height + " isTablet=" + isTablet );

            // Determine the name of the corresponding main page
            String deviceType = isTablet ? "tablet" : "phone";
            String pageUrl = "file:///android_asset/www/index." + deviceType + ".html";

            super.loadUrl(pageUrl);
        }
</pre>
<p>Now you can customize the index.tablet.html page to your liking, such as for example:</p>
<ul>
<li>Adding new functionality</li>
<li>Adding new jQuery Mobile logical pages</li>
<li>Adding new template views</li>
<li>Splitting existing views into separate phone and tablet versions</li>
</ul>
<p>Note: we had already included a media query and conditional inclusion of device-specific CSS (see  the <a href="#part5-adapting-css-for-mobile-use'">&#8220;Adapting The Stylesheets For Mobile Use&#8221;</a> section details) in our main html page. So now you can expand the customization to suit the appropriate device.</p>
<h3>Prepare For Packaging <a id='todo-part5-packaging'></a></h3>
<p>Since packaging is different for each device OS platform, I would recommend consulting the corresponding platform documentation. But the following items for consideration apply to all platforms:</p>
<ul>
<li>Creating the application icon in several resolutions</li>
<li>Creating the initial screen image which is displayed while the app is loading or being re-activated</li>
<li>Applying code signing certificates</li>
</ul>
<h3>Hosting The Application Package On An &#8220;AppStore&#8221;<a id='todo-part5-hosting'></a></h3>
<p>Of course, if your mobile application is for public consumption (for free or for sale) then the hosting guidelines of your platform apply (e.g. Apple AppStore, Google Play, Microsoft Windows Phone App Store).</p>
<p>But if your mobile application is for enterprise consumption, provided that you are enrolled in an enterprise program (e.g. iOS Developer Enterprise Program), you can create your own &#8220;custom app store&#8221; as a web application, require user authentication and authorization, tailor the app catalog based on user privileges. In that situation, each app has a link to either the package (for Android) or an application descriptor (for iOS &#8211; .plist file) which contains the location of your application package (e.g. Android .apk file, iOS .ipa file). Clicking on the link triggers an &#8220;Over The Air&#8221; installation of the application once you have approved the process.</p>
<p>This section was meant to just give you a sense of the possibilities, but you will need to refer the corresponding platform documentation for details.</p>
<p><a id='todo-part5-recap'></a></p>
<h3>5. Recap</h3>
<p>Even though we touched on all the basic minimum aspects of a PhoneGap + jQuery Mobile app, in some ways we barely scratched the surface. For example, we did not cover the following topics:</p>
<ul>
<li>leveraging device capabilities such as media, geolocation, etc. &#8211; but you easily lookup the corresponding details in the <a href="#acrdvadoc">PhoneGap documentation</a></li>
<li>using PhoneGap plugins such as the mobile notifications </li>
<li>dynamically altering jQuery Mobile-enhanced HTML controls &#8211; in a nutshell you would create <a href="#kocustombindingHandlers">custom bindingHandlers for KnockoutJS</a></li>
<li>interfacing with web services (via AJAX)</li>
</ul>
<p>These more advanced topics will be the subject of a separate tutorial.</p>
<p>Here is a quick recap of the steps we followed:</p>
<table class="details_table" style="border:1px solid #DDD;border-collapse:collapse;background-color:#FFF;">
<tr>
<th style="border:1px solid #DDD;background-color:#DDD;">
<div style="width:30px;">#</div>
</th>
<th style="border:1px solid #DDD;background-color:#DDD;text-align:left;">To Do</th>
<th style="border:1px solid #DDD;background-color:#DDD;text-align:left;">
<div style="width:90px;text-align:center;">Area</div>
</th>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">1</a></div>
</td>
<td style="border:1px solid #DDD">
<ul>
<li>Create a PhoneGap project for your mobile platform</li>
<li>Create a www folder structure under /assets for all types of resources:
<ul>
<li>www/css</li>
<li>www/css/jquery.mobile</li>
<li>www/scripts</li>
<li>www/scripts/vendor</li>
<li>www/scripts/view</li>
<li>www/scripts/viewmediator</li>
<li>www/scripts/viewmodel</li>
</ul>
</li>
<li>Add external JS libraries including Cordova, jQuery, jQuery Mobile, etc. under www/scripts/vendor</li>
<li>Add the jQuery Mobile stylesheets and theme content under www/css/jquery.mobile</li>
<li>Create a shell page for each type of device:
<ul>
<li>index.phone.html</li>
<li>index.tablet.html</li>
</ul>
</li>
<li>Customize the application controller (Activity in Android, AppDelegate in iOS) logic to detect the device display dimensions and launch the phone or tablet version of the index page</li>
<li>Under www/scripts, create an application.js module with the following function placeholders:
<ul>
<li>InitializeApplication</li>
<li>InitializeViewMediators</li>
<li>LoadApplicationViews</li>
<li>OnLoad</li>
<li>OnDeviceReady</li>
</ul>
</li>
<li>Wire-up the onload event on the body tag of both index pages to the OnLoad function</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">Application</div>
</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">2</a></div>
</td>
<td style="border:1px solid #DDD">
<ul>
<li>Customize the application style sheets under www/css
<ul>
<li>application.css</li>
<li>application.phone.css</li>
<li>application.tablet.css</li>
</ul>
</li>
<li>Starting with the index.phone.html:
<ul>
<li>include core JS libraries, </li>
<li>add logic to asynchronously load other libraries via LAB.js</li>
<li>add a call to LoadApplicationViews (from application.js) once LAB.js has completed all loading</li>
<li>include stylesheets</li>
</ul>
</li>
<li>Customize the LoadApplicationViews (from application.js) to use the jQuery View Loader to load all views and call InitializeViewMediators once done</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">View</div>
</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">3</a></div>
</td>
<td style="border:1px solid #DDD">
            For each &#8220;logical page&#8221; in the app:</p>
<ul>
<li>Create a folder under www/scripts/view to group all markup templates for that page</li>
<li>Create an index.view.html for the page in the new folder</li>
<li>Add a div with data-role=&#8217;page&#8217; in the body of both index.phone.html and index.tablet.html</li>
<li>Inside the new div, add a script tag referencing the index.view.html template from the page folder </li>
<li>Inside the new div, add a container div with data-bind=&#8217;template: { &#8230; }&#8217; binding the div with the template</li>
<li>Create templates for any sub-panels of the page with the naming convention: _{panel-name}.view.html</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">View</div>
</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">4</a></div>
</td>
<td style="border:1px solid #DDD">
            For each view model you need (e.g one global plus one per logical page):</p>
<ul>
<li>Create a Javascript module under www/scripts/viewmodel</li>
<li>Customize the namespace</li>
<li>Define a function named initializeViewModel to instantiate and return a view model and define value models (observables) and dependent observable functions</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">View Model</div>
</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">4</a></div>
</td>
<td style="border:1px solid #DDD">
            For each view mediator you need (e.g one per logical page):</p>
<ul>
<li>Create a Javascript module under www/scripts/viewmediator</li>
<li>Customize the namespace</li>
<li>Define a function named createViewMediator to:
<ul>
<li>request a corresponding view model</li>
<li>save off the view model</li>
<li>bind the corresponding container div with its template</li>
</ul>
</li>
<li>Define a function named setupViewDataBindings to bind each element of the page/view with their corresponding value model</li>
<li>If you need custom pre page rendering logic, create a function and wire it up to the pageinit event in the LAB.js post-loading code section</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">View Mediator</div>
</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">4</a></div>
</td>
<td style="border:1px solid #DDD">
            Customize the application initialization:</p>
<ul>
<li>Update InitializeApplication with any custom initialization logic based on device data or features</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">Application</div>
</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:30px;text-align:center;">
                <a href="#xxx">4</a></div>
</td>
<td style="border:1px solid #DDD">
            Update the InitializeViewMediators function of the www/scripts/application.js for each &#8220;logical page&#8221;:</p>
<ul>
<li>Add a call to the createViewMediator of each mediator</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">
<div style="width:90px;text-align:center;">Application</div>
</td>
</tr>
</table>
<h3>So What? <a id='part5-sowhat'></a></h3>
<p>The &#8220;<a href="#acrdva">PhoneGap</a> + <a href="#jqtpl">jQuery Mobile</a> + <a href="#jqvl">jQuery ViewLoader</a> + <a href="#kojs">Knockout JS</a>&#8221; <strong>stack</strong> allows you to create portable mobile apps by leveraging your existing HTML5 and Javascript skills, while minimizing your need to master all the details of each platform.</p>
<p>This is a big deal because you can:</p>
<ul>
<li>achieve a much <strong>greater portable code base</strong> (the platform-specific code base will be small)</li>
<li>get started quickly </li>
<li>use your favorite IDE</li>
<li>style your mobile app using CSS3 (including transitions and effects)</li>
<li>adopt the look of the base platform &#8220;automagically&#8221; (via jQuery Mobile rendering)</li>
<li><strong>debug</strong> a great portion of the app using <strong>standard browser tools</strong> (e.g.: Google Chrome, Firefox + Firebug, &#8230;)</li>
<li>target one platform initially then expand to other ones over time</li>
</ul>
<p>So if you have solid web skills it is time for you to apply them towards the creation of mobile apps!</p>
<h3>References And Resources</h3>
<h5>PhoneGap Platform</h5>
<ul>
<li><a id='acrdva'></a> <a href="http://www.phonegap.com/">PhoneGap / Apache Cordova</a> mobile framework : http://www.phonegap.com/</li>
<li><a id='acrdvagsg'></a> <a href="http://docs.phonegap.com/en/2.2.0/guide_getting-started_index.md.html">PhoneGap Getting Started Guides</a> : http://docs.phonegap.com/en/2.2.0/guide<em>getting-started</em>index.md.html</li>
<li><a id='acrdvadoc'></a> <a href="http://docs.phonegap.com/en/2.2.0/index.html/">PhoneGap Documentation</a> : http://docs.phonegap.com/en/2.2.0/index.html</li>
</ul>
<h5>Android Platform</h5>
<ul>
<li><a id='androidsdk'></a> <a href="http://developer.android.com/sdk/installing/index.html" title="Android SDK">Android SDK</a> : http://developer.android.com/sdk/installing/index.html</li>
<li><a id='aptanastudio'></a> <a href="http://www.aptana.com/products/studio3" title="Aptana Studio 3">Aptana Studio 3</a> : http://www.aptana.com/products/studio3</li>
<li><a id='adt'></a> <a href="http://developer.android.com/sdk/installing/installing-adt.html" title="Android Development Tools (ADT) plugin for Eclipse / Aptana Studio">Android Development Tools (ADT) plugin for Eclipse / Aptana Studio</a> : http://developer.android.com/sdk/installing/installing-adt.html</li>
</ul>
<h5>Javascript Frameworks</h5>
<ul>
<li><a id='jqm'></a> <a href="http://jquerymobile.com/" title="jQuery Mobile">jQuery Mobile</a> : http://jquerymobile.com/</li>
<li><a id='jqmd'></a> <a href="http://jquerymobile.com/demos/" title="jQuery Mobile Documentation">jQuery Mobile Documentation</a> : http://jquerymobile.com/demos/</li>
<li><a id='jqtpl'></a> <a href="http://api.jquery.com/category/plugins/templates/" title="jQuery Template">jQuery Template</a> : http://api.jquery.com/category/plugins/templates/</li>
<li><a id='jqvl'></a> <a href="http://github.com/techarch/jquery-viewloader" title="jQuery ViewLoader">jQuery ViewLoader</a> : http://github.com/techarch/jquery-viewloader</li>
<li><a id='viewldr'></a> <a href="https://github.com/techarch/jquery-viewloader">jQuery ViewLoader</a> rendering engine : https://github.com/techarch/jquery-viewloader</li>
<li><a id='kojs'></a> <a href="http://knockoutjs.com/">Knockout JS</a> Model-View-ViewModel framework : http://knockoutjs.com/</li>
<li><a id='kojs'></a> <a href="http://www.knockmeout.net/">Knock Me Out</a> &#8211; Ryan Niemeyer&#8217;s blog : http://www.knockmeout.net/</li>
<li><a id='labjs'></a> <a href="http://labjs.com/">LAB.js</a> Parallel and Asynchronous Javascript Loader : http://labjs.com/</li>
</ul>
<h5>Miscellaneous</h5>
<ul>
<li><a id='koafterrender'></a> <a href="http://knockoutjs.com/documentation/template-binding.html#note_4_using_the__option" title="KnockoutJS afterRender">KnockoutJS afterRender</a> : http://knockoutjs.com/documentation/template-binding.html#note<em>4</em>using<em>the</em>_option</li>
<li><a id='kocustombindingHandlers'></a> <a href="http://www.knockmeout.net/2011/07/another-look-at-custom-bindings-for.html" title="KnockoutJS afterRender">Another Look at Custom Bindings for KnockoutJS</a> : http://www.knockmeout.net/2011/07/another-look-at-custom-bindings-for.html</li>
<li><a id='jqmkocustombindingHandlers'></a> <a href="http://jsfiddle.net/rniemeyer/mydTu/" title="Example of KnockoutJS custom bindings for jQuery Mobile">Example of KnockoutJS custom bindings for jQuery Mobile</a> </li>
<li><a id='sgs-site'></a> <a href="http://savings-goal-simulator.heroku.com/" title="Savings Goal Simulator">Savings Goal Simulator</a> : http://savings-goal-simulator.heroku.com/</li>
</ul>
<h5><a id='patterns'></a>Patterns</h5>
<ul>
<li><a id='mvc'></a> <a href="http://c2.com/cgi/wiki?ModelViewController" title="Model-View-Controller pattern">Model-View-Controller pattern</a> : http://c2.com/cgi/wiki?ModelViewController</li>
<li><a id='controller'></a> <a href="http://c2.com/cgi/wiki?ApplicationController" title="Controller pattern">Controller pattern</a> : http://c2.com/cgi/wiki?ApplicationController</li>
</ul>
<h5><a id='criwawkotuts'></a>Other Tutorials In The Same Series</h5>
<ul>
<li><a id='criwawko1'></a> <a href="https://blog.monnet-usa.com/?p=354" title="Creating Rich Interactive Web Apps With KnockoutJS – Part 1">Creating Rich Interactive Web Apps With KnockoutJS – Part 1</a> : Introduction to KnockoutJS</li>
<li><a id='criwawko2'></a> <a href="https://blog.monnet-usa.com/?p=368" title="Creating Rich Interactive Web Apps With KnockoutJS – Part 2">Creating Rich Interactive Web Apps With KnockoutJS – Part 2</a> : Using view models and view mediators</li>
<li><a id='criwawko3'></a> <a href="https://blog.monnet-usa.com/?p=404" title="Creating Rich Interactive Web Apps With KnockoutJS – Part 3">Creating Rich Interactive Web Apps With KnockoutJS – Part 3</a> : Modularizing view models and view mediators</li>
<li><a id='criwawko4'></a> <a href="https://blog.monnet-usa.com/?p=411" title="Creating Rich Interactive Web Apps With KnockoutJS – Part 4">Creating Rich Interactive Web Apps With KnockoutJS – Part 4</a> : Modularizing and extracting view components  </li>
</ul>
<h5><a id='sgspkg'></a>Savings Goal Simulator</h5>
<ul>
<li><a id='criwawkosrc'></a>Web <a href="https://github.com/techarch/savings-goal-simulator" title="Web Savings Goal Simulator Source Code">Savings Goal Simulator Source Code</a></li>
<li>Download the Mobile App:</li>
</ul>
<table class="details_table" style="">
<tr>
<td><a id='sgsforios'></a><a href='https://itunes.apple.com/pk/app/savings-goal-simulator/id507644102?mt=8' title='Mobile Savings Goal Simulator for iOS' target="_blank"><img src='./wp-content/media/appstores/Download_on_the_App_Store_Badge_US-UK_135x40.png' height='49'/></a></td>
<td><a id='sgsforandroid'></a><a href='http://www.amazon.com/Philippe-Monnet-techarch-Savings-Simulator/dp/B006RUAIFE' title='Mobile Savings Goal Simulator for Android' target="_blank"><img src='./wp-content/media/appstores/6a0148c71fb71b970c014e8a07bf5a970d.png' height="50"/></a></td>
</tr>
</table>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
		If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap"  target="_blank">mySkillsMap</a>, my skills management app.
	</div>
<div class="blog-msm-ad2">
			<a href="http://www.myskillsmap.com/take-charge-of-your-skills-development" target="_blank"><br />
				<img decoding="async" src="./wp-content/media/msm/start-your-free-trial-now.png"><br />
			</a>
	</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=420</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 4</title>
		<link>https://blog.monnet-usa.com/?p=411</link>
					<comments>https://blog.monnet-usa.com/?p=411#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Tue, 03 Jan 2012 04:30:00 +0000</pubDate>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[KnockoutJS]]></category>
		<category><![CDATA[rich web apps]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=411</guid>

					<description><![CDATA[Intro In part 3 we built a complete working version of the Savings Goal Simulator where each view model and view mediator is nicely separated in its own module and corresponding source file. But what about the view? Well the goal of part 4 is to modularize and extract each view component. Synopsis Of The [&#8230;]]]></description>
										<content:encoded><![CDATA[<h3>Intro <a id='part4-intro'></a></h3>
<p>In <a href='https://blog.monnet-usa.com/?p=404'>part 3</a> we built a complete working version of the <a href="http://savings-goal-simulator.heroku.com/">Savings Goal Simulator</a> where each view model and view mediator is nicely separated in its own module and corresponding source file. But what about the view? Well the goal of part 4 is to <b>modularize</b> and <b>extract each view</b> component.</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-intro1.png" alt="Breaking up [views] is not hard to do ...!" title="Breaking up [views] is not hard to do ...!" /></p>
<h3>Synopsis Of The Approach <a id='part4-approach'></a></h3>
<p>The approach will need to meet the following requirements:</p>
<ol>
<li>The view markup needs to have its own <a href="#part4-view-url"><strong>url</strong></a> and be cacheable</li>
<li>The view markup needs an <a href="#part4-view-id"><strong>ID</strong></a></li>
<li>The view should have an HTML <a href="#part4-view-element"><strong>element</strong></a> </li>
<li>The view HTML element should be <a href="#part4-view-renderable"><strong>renderable</strong></a></li>
</ol>
<h5>View Markup With A URL <a id='part4-view-url'></a></h5>
<p>Just like script blocks and images can be &#8220;sourced&#8221; externally from any url, we need a similar mechanism for our views.</p>
<pre class="brush: javascript">    &lt;view src="http://my.view.html"&gt;
    &lt;/view&gt;
</pre>
<p>So since the <strong>script</strong> tag allow us to do that already, let&#8217;s use it, assign an id, but let&#8217;s use a more appropriate <strong>type</strong> like <strong>text/html</strong>. </p>
<pre class="brush: javascript">    &lt;script src="http://my.view.html" 
            type="text/html"&gt;
    &lt;/script&gt;
</pre>
<h5>View Markup With An ID <a id='part4-view-id'></a></h5>
<p>To make it possible to reference the &#8220;script-view-markup&#8221; later on in our page or Javascript code, we&#8217;ll just assign the script an ID like so:</p>
<pre class="brush: javascript">    &lt;script id="my-view-markup"
            src="http://my.view.html" 
            type="text/html"&gt;
    &lt;/script&gt;
</pre>
<h5>View HTML Element <a id='part4-view-element'></a></h5>
<p>Now that we have a way to define how a view markup can be &#8220;included&#8221; in our page, we&#8217;ll just define our view &#8220;container&#8221; as a normal HTML element. We can use a &#8220;<strong>div</strong>&#8221; or any of the more semantically significant HTML5 elements like &#8220;<strong>section</strong>&#8220;:</p>
<pre class="brush: javascript">    &lt;div id="my-view"&gt;
    &lt;/div&gt;
</pre>
<p>What we&#8217;re missing is a mechanism to:</p>
<ul>
<li><strong>associate</strong> the view element and the view markup together</li>
<li><strong>render</strong> the actual view</li>
<li>optionally: <strong>data-bind</strong> any view model to the view</li>
</ul>
<h5>Renderable View <a id='part4-view-renderable'></a></h5>
<p>To render the markup for a given view we need a <strong>view rendering engine</strong>. As of this writing, the most prevalent option is <a href="#jqtpl">jQuery Template</a>. </p>
<p><em><u>Note:</u> The <a href="#jqtpl">jQuery Template</a> implementation is rock solid and in use in many production web sites and internal applications. However the <a href="#jqui">jQuery UI</a> core team is in the process of deprecating its use and eventually replace it with another implementation. A serious contender for this is the <a href="#jsrv">jsRender + jsViews</a> library. Other options also include <a href="#musta">Mustache</a> and <a href="#hdbars">Handlebars</a>. Although this tutorial is leveraging jQuery Template as its platform, I recommend you perform some additional due diligence once you&#8217;re ready to settle on library.</em></p>
<p><a href="#ko">KnockoutJS</a> goes one step further by integrating the view rendering engine with data-binding capabilities.</p>
<p><em><u>Note:</u> <a href="#ko">KnockoutJS</a> will allow pluggable view rendering engines over time, making it possible to use the one you choose (as long a as a plugin exists).</em></p>
<p>So <a href="#ko">KnockoutJS</a> can take a <strong>view element</strong> with a corresponding &#8220;<strong>view template</strong>&#8221;  and a <strong>view model</strong>, and render the resulting <strong>view</strong>.</p>
<p>Since we introduced the notion of &#8220;<strong>view template</strong>&#8220;, let&#8217;s spend some time getting familiar with the concept before proceeding with externalized views.</p>
<h3>Introduction To Templating <a id='part4-tpl-intro'></a></h3>
<h5>Simple String-Based Templates <a id='part4-string-tpl'></a></h5>
<p>An string-based template is just a string containing text plus <strong>placeholders</strong> for variables. A <strong>placeholder</strong> is the name of the <strong>variable</strong> surrounded by <strong>curly braces</strong> and a prefixed by a <strong>dollar sign</strong>. So for example a template to display a <strong>time</strong> variable would look like:</p>
<pre class="brush: javascript">    var viewTemplate = "${firstName}, the time is now ${time}"
</pre>
<p>We can group our &#8220;variables&#8221; in a Javascript object literal like so:</p>
<pre class="brush: javascript">    var viewData = { firstName: 'Chris',
                     time:  (new Date()).toLocaleTimeString()
                    }
</pre>
<p>We can get the engine to bind the template and the data like so:</p>
<pre class="brush: javascript">    var viewContent = $.tmpl(viewTemplate, viewData);
</pre>
<p>Finally assuming a div with the id &#8216;my-view&#8217;, jQuery can render the view content like so:</p>
<pre class="brush: javascript">    $('#my-view').html(viewContent);
</pre>
<p>In summary here is a diagram showing the relationships between the various components used in templating:<br />
<br /><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-intro2.png" alt="Template Engine Schematic" title="Template Engine Schematic" /></p>
<p>To try this out yourself:</p>
<ol>
<li>Create a web page named index.html</li>
<li>Add script references to both jQuery and jQuery Template using their content distribution network urls:
<ul>
<li>http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js</li>
<li>http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js</li>
</ul>
</li>
<li>
<p>Add a div with the id &#8216;my-view&#8217; in the body of the page</p>
<pre class="brush: javascript">&lt;div id='my-view'&gt;&lt;/div&gt;
</pre>
</li>
<li>
<p>Add a Javascript script block with a jQuery ready function with our template rendering code:</p>
<pre class="brush: javascript">&lt;script type="text/javascript" &gt;
    $(document).ready(function () {
        var viewTemplate = "${firstName}, the time is now ${time}";
        var viewData = { firstName: 'Chris',
                         time:  (new Date()).toLocaleTimeString()
        }
        var viewContent = $.tmpl(viewTemplate, viewData);
        $("#my-view").html(viewData);
    }
&lt;/script&gt;
</pre>
</li>
</ol>
<p>You should be able to open the <strong>index.html</strong> web page in a browser and the div should now contain the rendered text with the first name and the current time.</p>
<p>Now we have an idea of how templating using jQuery Template is working. But in this example we are just using a string to hold our template. The library actually has a feature where you can store the template in a script tag on the same page.</p>
<h5>Simple Inline Templates <a id='part4-inline-tpls'></a></h5>
<p>The jQuery Template library also allow us to store the template in a script tag with a text/html type like so:</p>
<pre class="brush: javascript">&lt;script id='my-view-template' type='text/html'&gt;
    ${firstName}, the time is now ${time}
&lt;/script&gt;
</pre>
<p>The template can then be rendered with a slightly different form of the <strong>tmpl</strong> API:</p>
<pre class="brush: javascript">var viewContent = $('#my-view-template').tmpl(viewData);
</pre>
<p>Having the template moved out of the code is a step in the right direction, but what we need is the ability to externalize the template to an external url. We&#8217;ll tackle that subject soon I promise, but in the meantime let&#8217;s look at what <a href="#ko">KnockoutJS</a> brings us in terms of additional templating power.</p>
<h5>KnockoutJS Databinding Support For Inline Templates <a id='part4-knockoutjs-tpl-databindng'></a></h5>
<p>Up to now, we have had to write the actual code to: a) <strong>render</strong> the template, and then b) <strong>insert</strong> the resulting text in an HTML element. Well, let&#8217;s see what <a href="#ko">KnockoutJS</a> can do to simplify our task. (This will be very handy especially when your main page has many views.)</p>
<p>As you know, <a href="#ko">KnockoutJS</a> provides a &#8220;<strong>data-bind</strong>&#8221; attribute where you can specify the visual or behavioral <strong>aspects</strong> <em>(e.g. value, text, visible, enable, &#8230;)</em> to <u>link</u> to a <strong>value model</strong> or <strong>dependent observable function</strong>. When we want to data-bind an HTML element to both a template and a view model, we&#8217;ll use the following syntax:</p>
<pre class="brush: javascript">&lt;div id='my-view'
     data-bind='template: { name: "my-view",
                            data: myViewModel }'&gt;
&lt;/div&gt;
</pre>
<p><a id='introToAfterRender'></a>It is even possible to specify a Javascript function in an <a href="#koafterrender"><strong>afterRender</strong></a> template parameter. That function will the be invoked <strong>once the HTML element has been rendered</strong>. This can be useful if you need to <strong>dynamically attach</strong> new behaviors or event handlers to the produced content. For example, you could invoke jQuery UI component configuration APIs such as applying icons for a jQuery UI button.  </p>
<pre class="brush: javascript">&lt;div id='my-view'
     data-bind='template: { name: "my-view",
                            data: myViewModel,
                            afterRender: myViewHookup }'&gt;
&lt;/div&gt;
</pre>
<p>Our view model would then be re-written as follows: </p>
<pre class="brush: javascript">var myViewModel = { firstName: ko.observable('Chris'),
                    time: ko.observable((new Date()).toLocaleTimeString())
}
</pre>
<p>And our &#8220;myViewHookup&#8221; <a href="#koafterrender"><strong>after-render</strong></a> function would have the following form:</p>
<pre class="brush: javascript">function myViewHookup(renderedElements, viewModel) {
    // E.g. highlight the new content for 3 seconds
    renderedElements.effect('highlight', 
                            { color: 'LightGreen' }, 
                            3000); 
}
</pre>
<p>And finally our page initialization code would ask <a href="#ko">KnockoutJS</a> to apply the data bindings using the  ko.applyBindings API:</p>
<pre class="brush: javascript">$(document).ready(function () {
    var myViewModel = { firstName: ko.observable('Chris'),
                        time: ko.observable((new Date()).toLocaleTimeString())
    }

    ko.applyBindings(viewModel);        
});                 
</pre>
<p>So when using jQuery, <a href="#jqtpl">jQuery Template</a>, and <a href="#ko">KnockoutJS</a>, we can define a template-based view and data-bind it to a view model so it can be rendered dynamically.</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-intro3.png" alt="Knockout Templating" title="Knockout Templating" /></p>
<p>Now we have covered all but one requirement: the ability to externalize the view template to a specific url.</p>
<h3>Externalized View Templates</h3>
<h5>Basic Mechanism Needed To Externalize A Template</h5>
<p>Let&#8217;s review our simple &#8220;template script markup&#8221;:</p>
<pre class="brush: javascript">&lt;script id='my-view-template' type='text/html'&gt;
    ${firstName}, the time is now ${time}
&lt;/script&gt;
</pre>
<p>What we really need at this point is a way to <strong>externalize</strong> this template into its own file (maybe in a sub-folder named after the parent page, itself organized under a &#8220;<strong>view</strong>&#8221; folder):</p>
<table>
<tr>
<th>/view/mypage/my.view.html</th>
</tr>
<tr>
<td style='padding:4px;border:1px solid #aaa'>${firstName}, the time is now ${time}</td>
</tr>
</table>
<p>We would then just add a <strong>src</strong> tag to our <strong>script</strong> block:</p>
<pre class="brush: javascript">&lt;script id='my-view-template' 
        type='text/html'
        src='/view/mypage/_my.view.html' &gt;
&lt;/script&gt;
</pre>
<p>If you try this out you will notice that the browser will indeed [wget] &#8220;<strong>fetch</strong>&#8221; the content of <strong>_my.view.html</strong>, and using the web developer tool of your browser you will actually see the template markup. </p>
<p>But if you try to access the content of the script element using jQuery using:</p>
<pre class="brush: javascript">$("#my-view-template").text()
</pre>
<p>&#8230; you will notice that the content is <strong><em>empty</em></strong>! The browser engine has retrieved the content but <u>did not store</u> it in the actual DOM element for the script. This is due to the fact that a script of type text/html is not recognized as being a script to interpret.</p>
<p>So we need a mechanism to fetch and store the source. The approach consists of re-fetching the source using jQuery&#8217;s <a href="#jqget"><strong>$.get</strong></a> API. Since it was fetched once, the content is stored in the browser&#8217;s cache so retrieval wil be very fast. We then store it in the DOM&#8217;s element.<br />
Here is a simplistic example of what the code would look like:</p>
<pre class="brush: javascript">$(document).ready(function () {
    $.get("/view/mypage/_my.view.html", 
                function(data, textStatus, jqXHR) {     
                    $("#my-view-template")
                        .text(jqXHR.responseText);
                }
    );
});                 
</pre>
<p>So finally we can integrate our <a href="#ko">KnockoutJS</a> view model code in the ready function:</p>
<pre class="brush: javascript">$(document).ready(function () {
    $.get("/view/mypage/_my.view.html", 
                function(data, textStatus, jqXHR) {
                    $("#my-view-template")
                        .text(jqXHR.responseText);

                    var myViewModel = { firstName: ko.observable('Chris'),
                                        time: ko.observable((new Date()).toLocaleTimeString())
                    }

                    ko.applyBindings(viewModel);        
                }
    );
}); 
</pre>
<p>You now have <strong>externalized</strong> the view template, <strong>dynamically loaded</strong> it, <strong>data-bound</strong> it to a view model using <a href="#ko">KnockoutJS</a>, and <strong>rendered</strong> using the <a href="#jqtpl">jQuery Template</a> engine!</p>
<p>Our example was fairly basic but it illustrates the overall concept and approach. </p>
<h5>Generic ViewLoader Plugin</h5>
<p>The <a href="#viewldr">jQuery ViewLoader</a> plugin will take us even further by providing the ability to:</p>
<ol>
<li>Handle <strong>nested</strong> externalized templates</li>
<li><strong>Parallelize</strong> the processing of each template</li>
<li>Provide a simple way to handle all templates on a page and <strong>synchronize their post-processing</strong> so that the page initialization logic can proceed.</li>
</ol>
<p>Here is what the minimum syntax looks like:</p>
<pre class="brush: javascript">$(document).viewloader({
    logLevel: "debug",
    success: function () {
        ko.applyBindings(viewModel);
    }
});
</pre>
<p>The plugin will identify all scripts of <strong>type text/html</strong> and a source url ending in &#8220;<strong>.view.html</strong>&#8220;, including <strong>nested</strong> template scripts and request their <strong>parallel loading</strong>. Once <strong>all</strong> template scripts have been succesfully <strong>processed</strong> the <strong>success</strong> function is invoked.</p>
<p>Behind the scenes, <a href="#viewldr">jQuery ViewLoader</a> relies on the jQuery concept of <a href="#jqdfd">&#8220;<strong>Deferred</strong>&#8220;</a>, an action which can be <strong>launched for &#8220;deferred&#8221; (i.e. later) execution</strong>, but can <strong>trigger a callback when completed</strong>. Actions can be grouped together so that a specific callback can be triggered once all of them have completed.</p>
<p>Here is a diagram of the approach:<br />
<br /><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-intro4.png" alt="Dynamically Loaded External Templates" title="Dynamically Loaded External Templates" /></p>
<h3>Externalizing The Views Of Our Savings Goal Simulator</h3>
<h5>Intro</h5>
<p>We can now apply the new approach to our <a href="#sgs-site">Savings Goal Simulator</a> web app since it currently contains 3 views:</p>
<ol>
<li>savings-goal-view</li>
<li>consumption-scenarios-view</li>
<li>savings-forecast-view</li>
</ol>
<p>For each view, we will: </p>
<ol>
<li>Create an <strong>externalized template</strong> in the <strong>/view/index</strong> folder based on the view markup</li>
<li>Replace the <strong>view</strong> in index.html by a <strong>template script</strong> reference and a <strong>container DIV</strong> data-bound to the template.</li>
</ol>
<p>Finally, we&#8217;ll update the main <strong>application.js</strong> to plugin the <a href="#viewldr">jQuery ViewLoader</a>.</p>
<p>Here is an outline of the step-by-step approach:</p>
<table class="details_table">
<tr>
<th>#</th>
<th>To Do</th>
<th>Area</th>
</tr>
<tr>
<td><a href="#todo-part4-1">1</a></td>
<td>Create An External Template For The savings-goal-view</td>
<td>View</td>
</tr>
<tr>
<td><a href="#todo-part4-2">2</a></td>
<td>Refactor the savings-goal-view In Our Web Page</td>
<td>View</td>
</tr>
<tr>
<td><a href="#todo-part4-3">3</a></td>
<td>Hookup jQuery ViewLoader In Our Main application.js</td>
<td>Application</td>
</tr>
<tr>
<td><a href="#todo-part4-4">4</a></td>
<td>Refactor The Savings Goal Mediator</td>
<td>View Mediator</td>
</tr>
</table>
<p><a id='todo-part4-1'></a></p>
<h5>1. Create An External Template For The savings-goal-view</h5>
<p>Our first step will be to create a new folder named <strong>view</strong> under <strong>scripts</strong> to organize our external views. Similarly to frameworks like Ruby On Rails, or ASP.NET MVC, we&#8217;ll create a subfolder named <strong>shared</strong>, for all views reusable across pages, then we&#8217;ll create a subfolder named <strong>index</strong> for views appearing on our <strong>index.html</strong> web page.</p>
<p>In the <strong>scripts/view/index</strong> folder, let&#8217;s create a file named <strong>_savings-goal.view.html</strong>. I used an <strong>underscore prefix</strong> to reflect the Rails convention of &#8220;<strong>partial views</strong>&#8221; being prefixed that way.</p>
<p>Then we can copy the <strong>savings-goal-view markup</strong> from <strong>index.html</strong> page and paste it in our new <strong>_savings-goal.view.html</strong> file.</p>
<pre class="brush: javascript">&lt;section id='savings-goal-view' &gt;
    &lt;label for="savings-goal-amount"&gt;Savings Goal Amount:&lt;/label&gt;
    &lt;input id="savings-goal-amount"  /&gt;&lt;br/&gt;

    &lt;label for="savings-max-duration"&gt;Savings Max Duration (In Months):&lt;/label&gt;
    &lt;input id="savings-max-duration" maxlength="3" /&gt;&lt;br/&gt;

    &lt;label for="savings-target-per-month"&gt;Savings Target Per Month:&lt;/label&gt;
    &lt;span id="savings-target-per-month"  /&gt;&lt;br/&gt;
&lt;/section&gt;  
</pre>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-todo1.png" alt="Externalizing savings-goal-view" title="Externalizing savings-goal-view" /></p>
<p>Now we can refactor index.html.</p>
<p><a id='todo-part4-2'></a></p>
<h5>2. Refactor the savings-goal-view In Our Web Page</h5>
<p>In place of our <strong>savings-goal-view</strong> markup, let&#8217;s first add a script reference to the view we just created, and give it an id of savings-goal-view<strong>-template</strong>:</p>
<pre class="brush: javascript">&lt;script id='savings-goal-view-template'
        type='text/html'
        src='scripts/view/index/_savings-goal.view.html' &gt;
&lt;/script&gt;
</pre>
<p>Second, let&#8217;s add a <strong>div</strong> acting as a <strong>container</strong> for our external view. We&#8217;ll give it an id of savings-goal-view<strong>-container</strong>, and declare our KnockoutJS data-binding with the <strong>savings-goal-view-template</strong>:</p>
<pre class="brush: javascript">&lt;div id='savings-goal-view-container'
     data-bind='template: { name: "savings-goal-view-template" } ' &gt;
&lt;/div&gt;
</pre>
<p>Let&#8217;s download:</p>
<ol>
<li>the latest version of jQuery Templates from https://github.com/jquery/jquery-tmpl</li>
<li>the latest version of KnockoutJS from https://github.com/SteveSanderson/knockout</li>
<li>the <a href="#viewldr">jQuery ViewLoader</a> plugin and place it in the <strong>/scripts/vendor</strong> folder.</li>
</ol>
<p>In the index.html page, in the LAB loader section, let&#8217;s:</p>
<ol>
<li>Replace the call to load jQuery Template from our downloaded version (instead of the version from the CDN which is older)</li>
<li>Replace the call to load KnockoutJS from our downloaded version</li>
<li>
<p>Add a call to load the <a href="#viewldr">jQuery ViewLoader</a> plugin:</p>
<pre class="brush: javascript">
&lt;script type="text/javascript"&gt;
$LAB
    .script("http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js").wait()
    // ...
    .script("scripts/vendor/jquery.tmpl.min.js").wait()
    .script("scripts/vendor/knockout-latest.debug.js").wait()
    // ...
    .script("scripts/vendor/jquery.viewloader.js").wait()
    // ...
&lt;/script&gt; 
</pre>
</li>
</ol>
<p>Here is how all the piece parts will fit together:</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-todo2.png" alt="Dynamic loading of the savings-goal-view" title="Dynamic loading of the savings-goal-view" /></p>
<p>Ok, now it&#8217;s time to plug in code to get the ViewLoader to load our view.</p>
<p><a id='todo-part4-3'></a></p>
<h5>3. Hookup jQuery ViewLoader In Our Main application.js</h5>
<p>First let&#8217;s create 2 new utility functions in application.js:</p>
<ol>
<li>GetPageSettings &#8211; to retrieve our page settings from the DOM</li>
<li>
<p>SetPageSettings &#8211; to store our page settings in the DOM</p>
<pre class="brush: javascript">function GetPageSettings() {
    return $(document).data("sgs.pagesettings");
}


function SetPageSettings(pageSettings) {
    $(document).data("sgs.pagesettings", pageSettings);
}
</pre>
</li>
</ol>
<p>Let&#8217;s review the <strong>InitializeApplication</strong> function of our main <strong>application.js</strong> module. The core code consists of initializing a pageSettings dictionary and invoking our view mediators.</p>
<p>Let&#8217;s extract that part of the code into a new function named <strong>InitializeViewMediators</strong>:</p>
<pre class="brush: javascript">function InitializeViewMediators() {
    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("InitializeViewMediators starting ...");

    // Initialize our page-wide settings
    var pageSettings = { defaultSavingsGoal: 500,
                         defaultSavingsMaxDuration: 6
    }

    // Save the page-wide settings
    SetPageSettings(pageSettings);

    // Create / launch our view mediator(s)
    sgs.mediator.savingsgoal.createViewMediator(pageSettings);
    sgs.mediator.coffeepricing.createViewMediator(pageSettings);
    sgs.mediator.consumptionscenarios.createViewMediator(pageSettings);
    sgs.mediator.savingsforecast.createViewMediator(pageSettings);

    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("InitializeViewMediators done ...");   
}
</pre>
<p>Let&#8217;s add the code to <strong>InitializeApplication</strong> to <strong>attach</strong> our ViewLoader plugin to the <strong>document</strong> object and invoke <strong>InitializeViewMediators</strong> upon success (i.e. once all views have been loaded):</p>
<pre class="brush: javascript">function InitializeApplication() {
    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("InitializeApplication starting ...");

    $(document).viewloader({
        logLevel: "debug",
        success: function (successfulResolution) {
            InitializeViewMediators();
        }
    );

    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("InitializeApplication done ..."); 
}
</pre>
<p>And let&#8217;s add some <strong>logging</strong> code in the <strong>error function</strong> to know when the ViewLoader is failing to load a given view.</p>
<pre class="brush: javascript">function InitializeApplication() {
    // ...

    $(document).viewloader({
        // ...
        success: function (successfulResolution) {
            InitializeViewMediators();
        },          
        error: function (failedResolution) {
            if (typeof(console) != 'undefined' &amp;&amp; console) {
                console.error("index.html page failed to load");    
            }
        }
    });

    // ...
}
</pre>
<p>Here is the visual depiction of how application.js coordinates with the ViewLoader:</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-todo3.png" alt="Hooking up jQuery ViewLoader with application.js" title="Hooking up jQuery ViewLoader with application.js" /></p>
<p>Not so fast &#8230; if we run the app, we&#8217;ll get an <em>error</em>. This is due to the fact that the code from the <strong>createViewMediator</strong> function of our <strong>sgs.mediator.savingsgoal</strong> module is <em>expecting the view to be available</em>. But at this point in the execution the view as <em>not yet been rendered</em>. This leads us to one more refactoring.</p>
<p><a id='todo-part4-4'></a></p>
<h5>4. Refactor The Savings Goal Mediator</h5>
<p>The current implementation of the <strong>createViewMediator</strong> function of our <strong>sgs.mediator.savingsgoal</strong> module assumes that our view is in the DOM, but at the moment the ViewLoader plugin kicked off the <strong>InitializeViewMediators</strong> function, KnockoutJS <em>has not been requested to apply bindings yet</em> nor <em>render any view templates</em>. </p>
<p>So let&#8217;s refactor the code related to setting up the various data-bindings and invoking KnockoutJS into a new function named <strong>setupViewDataBindings</strong>:</p>
<pre class="brush: javascript">sgs.mediator.savingsgoal.setupViewDataBindings = function() {
    // Declare the HTML element-level data bindings
    $("#savings-goal-amount").attr("data-bind","value: savingsGoalAmount");
    $("#savings-max-duration").attr("data-bind","value: savingsMaxDuration");
    $("#savings-target-per-month").attr("data-bind","text: savingsTargetPerMonthFormatted()");

    // Ask KnockoutJS to data-bind the view model to the view
    var viewNode = $('#savings-goal-view')[0];
    var viewModel = sgs.mediator.savingsgoal.getViewModel();            
    ko.applyBindings(viewModel, viewNode);

    // Apply masking to the savings goal amount and max duration input fields 
    viewModel.savingsGoalAmountMask.attach($("#savings-goal-amount")[0]);
    viewModel.savingsMaxDurationMask.attach($("#savings-max-duration")[0]); 

    // Initialize default for value models linked to masked fields 
    var pageSettings = GetPageSettings();
    viewModel.savingsGoalAmount(pageSettings.defaultSavingsGoal || 0);
    viewModel.savingsMaxDuration(pageSettings.defaultSavingsMaxDuration || 0);

    // Subscribe to interesting value model changes
    viewModel.savingsTargetPerMonthFormatted.subscribe(function() {
        $("#savings-target-per-month")
            .effect('highlight', { color: 'LightGreen' }, 3000); // for 3 seconds
    });

    if (typeof(console) != 'undefined' &amp;&amp; console) 
        console.info("sgs.mediator.setupViewDataBindings done!");
}
</pre>
<p>Note: We had to add a new line to <em>access</em> the <strong>viewModel</strong> since it is now available in the DOM and accessible using the sgs.mediator.savingsgoal.<strong>getViewModel</strong> function. We also add to add a line to get the <strong>pageSettings</strong> using our new <strong>GetPageSettings</strong> function.</p>
<p>After having extracted some of the code the <strong>createViewMediator</strong> function consist of the following:</p>
<pre class="brush: javascript">sgs.mediator.savingsgoal.createViewMediator = function (pageSettings, pageViewModel) {
    // Create the view Savings Goal view-specific view model
    var viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);

    // Save the view model
    sgs.mediator.savingsgoal.setViewModel(viewModel);   

    if (typeof(console) != 'undefined' &amp;&amp; console) console.info("sgs.mediator.savingsgoal ready!");
}
</pre>
<p>But since we added the <strong>savings-goal-view-container</strong> <strong>div</strong> to the page, we need to handle its <strong>data binding</strong> here. So let&#8217;s do that:</p>
<pre class="brush: javascript">sgs.mediator.savingsgoal.createViewMediator = function (pageSettings, pageViewModel) {
    // Create the view Savings Goal view-specific view model
    var viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);

    // Save the view model
    sgs.mediator.savingsgoal.setViewModel(viewModel);   

    // Ask KnockoutJS to data-bind the view model to the view
    var viewNode = $('#savings-goal-view-container')[0];
    ko.applyBindings(viewModel, viewNode);

    if (typeof(console) != 'undefined' &amp;&amp; console) console.info ("sgs.mediator.savingsgoal ready!");
}
</pre>
<p>You probably noticed that there is <strong><em>no call</em></strong> yet to invoke our new <strong>setupViewDataBindings</strong> function! So where will it be invoked then? Well do you remember the comment about KnockoutJS exposing an <strong>afterRender</strong> callback function? (See back in <a href="#introToAfterRender" title="Intro to afterRender">KnockoutJS Databinding Support For Inline Templates</a>.)</p>
<p>We&#8217;ll update the data-binding of <strong>savings-goal-view-container</strong> in our <strong>index.html</strong>, by assigning our new <strong>sgs.mediator.savingsgoal.setupViewDataBindings</strong> function to the <strong>afterRender</strong> attribute:</p>
<pre class="brush: javascript">&lt;div id='savings-goal-view-container'
     data-bind='template: { name: "savings-goal-view-template", 
                            afterRender: sgs.mediator.savingsgoal.setupViewDataBindings } ' &gt;
&lt;/div&gt;
</pre>
<p>And now if we re-run our application, we&#8217;ll see in the console that <strong>setupViewDataBindings</strong>  is being called while the <strong>savings-goal-view</strong> is being rendered, after the loading is successfully completed. </p>
<p>Here is an excerpt of the console:</p>
<pre class="brush: javascript">InitializeApplication starting ...
viewloader.loadSourceForPartialView loading source for view: id=savings-goal-view-template src=scripts/view/index/_savings-goal.view.html
InitializeApplication done ...
viewloader.loadSourceForPartialView saving source in savings-goal-view-template
viewloader.loadAllPartialViews executing 'success' function
InitializeViewMediators starting ...
sgs.mediator.setupViewDataBindings done!
sgs.mediator.savingsgoal ready!
...
InitializeViewMediators done ...
</pre>
<p>We have successfully externalized the markup for the savings-goal-view!!!</p>
<p>In summary here is a diagram illustrating the page load processing flow:</p>
<p><img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part4-todo4.png" alt="Page Load Processing Flow Recap" title="Page Load Processing Flow Recap" /></p>
<p><a id='todo-part4-5'></a></p>
<h5>5. Recap</h5>
<p>Here is a quick recap of the steps we followed:</p>
<table class="details_table" style="border:1px solid #DDD;border-collapse:collapse;background-color:#FFF;">
<tr>
<th style="border:1px solid #DDD;background-color:#DDD;">#</th>
<th style="border:1px solid #DDD;background-color:#DDD;text-align:left;">To Do</th>
<th style="border:1px solid #DDD;background-color:#DDD;text-align:left;">Area</th>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;"><a href="#todo-part4-1">1</a></td>
<td style="border:1px solid #DDD">Create An External Template For The savings-goal-view</p>
<ul>
<li>Create a _your.view.html file</li>
<li>Cut the view markup from your .html and paste it in the .view.html</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">View</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;"><a href="#todo-part4-2">2</a></td>
<td style="border:1px solid #DDD">Refactor the savings-goal-view In Our Web Page</p>
<ul>
<li>Add a script tag with an id, a text/html type and point the source to the new .view.html</li>
<li>Create a DIV container and add a data-bind with the template name (id)</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">View</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;"><a href="#todo-part4-3">3</a></td>
<td style="border:1px solid #DDD">Hookup jQuery ViewLoader In Our Main application.js</p>
<ul>
<li>Split the view mediators initialization code into a separate InitializeViewMeditors function</li>
<li>Add $(document).viewloader({ // &#8230; }) to InitializeApplication</li>
<li>Call InitializeViewMeditors from the success callback of viewloader</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">Application</td>
</tr>
<tr>
<td style="border:1px solid #DDD;vertical-align:top;"><a href="#todo-part4-4">4</a></td>
<td style="border:1px solid #DDD">Refactor The Savings Goal Mediator</p>
<ul>
<li>Create a new setupViewDataBindings function to create and apply data bindings inside the view</li>
<li>Trim down createViewMediators to focus only on initializing and storing the view model and asking KnockoutJS to apply the bindings to the view container.</li>
<li>Add an afterRender parameter to the template data-binding to instruct the template engine to invoke the setupViewDataBindings</li>
</ul>
</td>
<td style="border:1px solid #DDD;vertical-align:top;">View Mediator</td>
</tr>
</table>
<p><a id='todo-part4-6'></a></p>
<h5>6. Externalizing The Remaining Views</h5>
<p>Now we just need to repeat the process on our remaining two views:</p>
<ul>
<li>consumption-scenarios-view</li>
<li>savings-forecast-view</li>
</ul>
<p>If you want to follow along with the source code changes, just get code for the <strong>tag</strong> corresponding to any particular step on the <a href="https://github.com/techarch/savings-goal-simulator/tags">GitHub repository</a> for the Savings Goal Simulator.</p>
<h3>So What? <a id='part4-sowhat'></a></h3>
<p><a href="#jqtpl">jQuery Template</a> and <a href="#jqvl">jQuery ViewLoader</a> allow you to structure and load views within a web page.</p>
<p>Externalizing your views makes your web pages more <strong>modular</strong> and <strong>easier to maintain</strong>, especially if you are working within a team as this allows you to assign different views (markup + code) to different individuals.</p>
<p>In the context of a &#8220;single page application&#8221; where you may have many views, these benefits are crucial to help you manage the <strong>complexity</strong> and allow you to <strong>grow</strong> the application <strong>organically</strong> / incrementally.</p>
<p>Another benefit of modularizing your views and view mediators will be that it will be easier to adapt and create different versions of the application for other channels, like a mobile web site or a mobile version of the application (using for example jQuery Mobile and PhoneGap).</p>
<h3>References And Resources</h3>
<h5>jQuery Plugins</h5>
<ul>
<li><a id='jqtpl'></a> <a href="http://api.jquery.com/category/plugins/templates/" title="jQuery Template">jQuery Template</a> : http://api.jquery.com/category/plugins/templates/</li>
<li><a id='jqvl'></a> <a href="http://github.com/techarch/jquery-viewloader" title="jQuery ViewLoader">jQuery ViewLoader</a> : http://github.com/techarch/jquery-viewloader</li>
<li><a id='jsrv'></a> <a href="https://github.com/BorisMoore/jsviews">jsRender + jsViews</a> rendering engine : https://github.com/BorisMoore/jsviews</li>
<li><a id='musta'></a> <a href="http://mustache.github.com/">Mustache</a> rendering engine : http://mustache.github.com/</li>
<li><a id='hdbars'></a> <a href="http://www.handlebarsjs.com/">Handlebars</a> rendering engine : http://www.handlebarsjs.com/</li>
<li><a id='viewldr'></a> <a href="https://github.com/techarch/jquery-viewloader">jQuery ViewLoader</a> rendering engine : https://github.com/techarch/jquery-viewloader</li>
</ul>
<h5>Miscellaneous</h5>
<ul>
<li><a id='jqget'></a> <a href="http://api.jquery.com/jQuery.get/" title="jQuery $.get">jQuery $.get</a> : http://api.jquery.com/jQuery.get/</li>
<li><a id='jqdfd'></a> <a href="http://api.jquery.com/category/deferred-object/" title="jQuery Deferred">jQuery Deferred</a> : http://api.jquery.com/category/deferred-object/</li>
<li><a id='koafterrender'></a> <a href="http://knockoutjs.com/documentation/template-binding.html#note_4_using_the__option" title="KnockoutJS afterRender">KnockoutJS afterRender</a> : http://knockoutjs.com/documentation/template-binding.html#note<em>4</em>using<em>the</em>_option</li>
<li><a id='sgs-site'></a> <a href="http://savings-goal-simulator.heroku.com/" title="Savings Goal Simulator">Savings Goal Simulator</a> : http://savings-goal-simulator.heroku.com/</li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a name='ko-part1' href='https://blog.monnet-usa.com/?p=354'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 1</a></li>
<li><a name='ko-part2' href='https://blog.monnet-usa.com/?p=368'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 2</a></li>
<li><a name='ko-part3' href='https://blog.monnet-usa.com/?p=404'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 3</a></li>
</ul>
<p><a name='kodemosrc'></a></p>
<h5>Full Source Of The Savings Goal Simulator (KnockoutJS Demo)</h5>
<p>The whole application is available on Github under <a href='https://github.com/techarch/savings-goal-simulator' target='_blank'>techarch / savings-goal-simulator</a>.</p>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
		If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
	</div>
<div class="blog-msm-ad2">
			<a href="http://www.myskillsmap.com/take-charge-of-your-skills-development"><br />
				<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
			</a>
	</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=411</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 3</title>
		<link>https://blog.monnet-usa.com/?p=404</link>
					<comments>https://blog.monnet-usa.com/?p=404#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Sun, 30 Oct 2011 13:44:33 +0000</pubDate>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[KnockoutJS]]></category>
		<category><![CDATA[rich web apps]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=404</guid>

					<description><![CDATA[Intro In Part 1, we introduced the key concepts and patterns including KnockoutJS. In Part 2, we started to build the first increment of our Savings Goal Simulation rich web app. The objectives of this third tutorial are: Build up the rest of the application Gain more practice with View Models, View Mediators, and KnockoutJS [&#8230;]]]></description>
										<content:encoded><![CDATA[<style>
						h3 {	text-decoration: underline; }</p>
<p>						h5 {margin-left:20px !important;}</p>
<p>						.details_table 
						{border: 1px solid #f0f0f0;
						border-spacing: 1px;
						background-color:white;
						margin-left: 40px;
						}</p>
<p>						.details_table tr
						{
						vertical-align: top;
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.details_table th
						{
						background-color:lightgray;
						}</p>
<p>						.details_table td
						{
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.download_panel
						{
						background-color: #EDD6AD; 
						color: #555555; 
						font-weight:bold;
						text-align:center;
						margin:0 50px 0 50px;
						padding:6px;
						}</p>
</style>
<h3>Intro</h3>
<p>In <a href="https://blog.monnet-usa.com/?p=354" target="_blank">Part 1</a>, we introduced the key concepts and patterns including KnockoutJS. In <a href="https://blog.monnet-usa.com/?p=368" target="_blank">Part 2</a>, we started to build the first increment of our Savings Goal Simulation rich web app. The objectives of this third tutorial are:</p>
<ul>
<li>Build up the rest of the application</li>
<li>Gain more practice with View Models, View Mediators, and KnockoutJS</li>
<li>Incorporate some basic elements of usability</li>
</ul>
<p>Here is the overall target structure of the application:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-overview.png" /></p>
<h3>Building Our App Step-By-Step</h3>
<p>Here is what the app will look like at the end of this tutorial:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-6.png" /></p>
<p>Here is an outline of the approach:</p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
<th>Area</th>
</tr>
<tr>
<td><a href='#todo1'>1</a></td>
<td>Create the Consumption Scenarios View</td>
<td>View</td>
</tr>
<tr>
<td><a href='#todo2'>2</a></td>
<td>Create the Consumption Scenarios ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo3'>3</a></td>
<td>Create the Consumption Scenarios View Mediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo4'>4</a></td>
<td>Link the Page and the View Mediator</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo5'>5</a></td>
<td>Create the Coffee Pricing ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo6'>6</a></td>
<td>Create the Coffee Pricing ViewMediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo7'>7</a></td>
<td>Link the Page and the Coffee Pricing View Mediator</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo8'>8</a></td>
<td>Leveraging Independent View Models</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo9'>9</a></td>
<td>Create the Savings Forecast View</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo10'>10</a></td>
<td>Create the Savings Forecast ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo11'>11</a></td>
<td>Create the Savings Forecast View Mediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo12'>12</a></td>
<td>Link the Page and the Savings Forecast View Mediator</td>
<td>Main App</td>
</tr>
</table>
<p></p>
<p>					<a name='todo1'></a></p>
<h5>1. Create the Consumption Scenarios View</h5>
<p>In our <b>index.html</b> page, let&#8217;s add a second section tag to represent our second panel / view: the <b>consumption-scenarios-view</b>.The view will let us enter current habits and see how modifying these habits can yield savings counting towards our saving goal.</p>
<pre class="brush: html">
&lt;body&gt;
	&lt;!-- ... --&gt;
	&lt;section id='consumption-scenarios-view'&gt;
	&lt;/section&gt;
&lt;/body&gt;
</pre>
<p>This is what the view will look like:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-1.png" /></p>
<p>Let&#8217;s add a table with 3 columns, one for the dimension to capture and affect (e.g. drink size), one for current habits, and one for our proposed consumption:</p>
<pre class="brush: html">
&lt;body&gt;
	&lt;!-- ... --&gt;
	&lt;section id='consumption-scenarios-view'&gt;
			&lt;header&gt;Weekly Coffee Consumption&lt;/header&gt;
			
			&lt;table&gt;
				&lt;thead&gt;
					&lt;tr&gt;
						&lt;th&gt;Coffee Options&lt;/th&gt;
						&lt;th&gt;Current Habits&lt;/th&gt;
						&lt;th&gt;Proposed Change&lt;/th&gt;
					&lt;/tr&gt;
				&lt;/thead&gt;
				
				&lt;tbody&gt;
					&lt;tr&gt;					
						&lt;td&gt;Type:&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td&gt;Size:&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td&gt;Frequency:&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td&gt;&lt;label for="drinks-per-day"&gt;Drinks per Day:&lt;/label&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
					&lt;/tr&gt;

					&lt;tr&gt;
						&lt;td&gt;&lt;label for="cost-per-week"&gt;Cost Per Week:&lt;/label&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
						&lt;td&gt;&lt;/td&gt;
					&lt;/tr&gt;
				&lt;/tbody&gt;
			&lt;/table&gt;
	&lt;/section&gt;
&lt;/body&gt;
</pre>
<p>Let&#8217;s fill the [Drink] Type row, consisting of sets of radio buttons for Regular, Latte, and Espresso, in both Current and Proposed columns:</p>
<pre class="brush: html">
&lt;tbody&gt;
	&lt;tr&gt;					
		&lt;td&gt;Type:&lt;/td&gt;
		&lt;td&gt;
			&lt;div id="current-drink-type"&gt;
				&lt;input type="radio" id="current-drink-regular"  name="CurrentDrinkType" value="Regular" /&gt;
					&lt;label for="current-drink-regular"&gt;Regular&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="current-drink-latte"  name="CurrentDrinkType" value="Latte" /&gt;
					&lt;label for="current-drink-latte"&gt;Latte&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="current-drink-espresso"  name="CurrentDrinkType" value="Espresso" /&gt;
					&lt;label for="current-drink-espresso"&gt;Espresso&lt;/label&gt;&lt;br/&gt;
			&lt;/div&gt;
		&lt;/td&gt;
		&lt;td&gt;
			&lt;div id="proposed-drink-type"&gt;
				&lt;input type="radio" id="proposed-drink-regular"  name="ProposedDrinkType" value="Regular" /&gt;
					&lt;label for="proposed-drink-regular"&gt;Regular&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="proposed-drink-latte"  name="ProposedDrinkType" value="Latte" /&gt;
					&lt;label for="proposed-drink-latte"&gt;Latte&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="proposed-drink-espresso"  name="ProposedDrinkType" value="Espresso" /&gt;
					&lt;label for="proposed-drink-espresso"&gt;Espresso&lt;/label&gt;&lt;br/&gt;
			&lt;/div&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>Let&#8217;s fill the [Drink] Size row, consisting of sets of radio buttons for Tall, Grande, and Venti, in both Current and Proposed columns:</p>
<pre class="brush: html">
&lt;tbody&gt;
	&lt;!-- ... --&gt;
	&lt;tr&gt;					
		&lt;td&gt;Size:&lt;/td&gt;
		&lt;td&gt;
				&lt;div id="current-drink-size"&gt;
					&lt;input type="radio" id="current-size-tall" 		name="CurrentDrinkSize" value="Tall" /&gt;
						&lt;label for="current-size-tall"&gt;Tall&lt;/label&gt;&lt;br/&gt;
					&lt;input type="radio" id="current-size-grande" 	name="CurrentDrinkSize" value="Grande" /&gt;
						&lt;label for="current-size-grande"&gt;Grande&lt;/label&gt;&lt;br/&gt;
					&lt;input type="radio" id="current-size-venti" 	name="CurrentDrinkSize" value="Venti" /&gt;
						&lt;label for="current-size-venti"&gt;Venti&lt;/label&gt;&lt;br/&gt;
				&lt;/div&gt;						
		&lt;/td&gt;
		&lt;td&gt;
				&lt;div id="proposed-drink-size"&gt;
					&lt;input type="radio" id="proposed-size-tall" 		name="ProposedDrinkSize" value="Tall" /&gt;
						&lt;label for="proposed-size-tall"&gt;Tall&lt;/label&gt;&lt;br/&gt;
					&lt;input type="radio" id="proposed-size-grande" 	name="ProposedDrinkSize" value="Grande" /&gt;
						&lt;label for="proposed-size-grande"&gt;Grande&lt;/label&gt;&lt;br/&gt;
					&lt;input type="radio" id="proposed-size-venti" 	name="ProposedDrinkSize" value="Venti" /&gt;
						&lt;label for="proposed-size-venti"&gt;Venti&lt;/label&gt;&lt;br/&gt;
				&lt;/div&gt;						
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>Let&#8217;s fill the [Drink] Frequency row, consisting of sets of radio buttons for Everyday, Monday-through-Friday, and Other (i.e. N days per week), in both Current and Proposed columns:</p>
<pre class="brush: html">
&lt;tbody&gt;
	&lt;!-- ... --&gt;
	&lt;tr&gt;					
		&lt;td&gt;Frequency:&lt;/td&gt;
		&lt;td&gt;
			&lt;div id="current-drink-frequency"&gt;
				&lt;input type="radio" id="current-frequency-everyday"	name="CurrentDrinkFrequency" value="Everyday" /&gt;
					&lt;label for="current-frequency-everyday"&gt;Everyday&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="current-frequency-workdays" name="CurrentDrinkFrequency" value="WorkDays" /&gt;
					&lt;label for="current-frequency-workdays"&gt;Mon-Fri&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="current-frequency-other" 		name="CurrentDrinkFrequency" value="Other" /&gt;
					&lt;label for="current-frequency-other"&gt;Other:&lt;/label&gt;
					&lt;input type="text" id="current-custom-frequency" name="CurrentCustomFrequency" /&gt;&lt;br/&gt;
			&lt;/div&gt;						
		&lt;/td&gt;
		&lt;td&gt;
			&lt;div id="proposed-drink-frequency"&gt;
				&lt;input type="radio" id="proposed-frequency-everyday"	name="ProposedDrinkFrequency" value="Everyday" /&gt;
					&lt;label for="proposed-frequency-everyday"&gt;Everyday&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="proposed-frequency-workdays" name="ProposedDrinkFrequency" value="WorkDays" /&gt;
					&lt;label for="proposed-frequency-workdays"&gt;Mon-Fri&lt;/label&gt;&lt;br/&gt;
				&lt;input type="radio" id="proposed-frequency-other" 		name="ProposedDrinkFrequency" value="Other" /&gt;
					&lt;label for="proposed-frequency-other"&gt;Other:&lt;/label&gt;
					&lt;input type="text" id="proposed-custom-frequency" name="ProposedCustomFrequency" /&gt;&lt;br/&gt;
			&lt;/div&gt;						
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>Let&#8217;s fill the Drinks Per Day row consisting of an simple input field, in both Current and Proposed columns:</p>
<pre class="brush: html">
&lt;tbody&gt;
	&lt;!-- ... --&gt;
	&lt;tr&gt;					
		&lt;td&gt;&lt;label for="drinks-per-day"&gt;Drinks per Day:&lt;/label&gt;&lt;/td&gt;
		&lt;td&gt;
				&lt;input type="text" id="current-drinks-per-day" name="CurrentDrinksPerDay" /&gt;
		&lt;/td&gt;
		&lt;td&gt;
				&lt;input type="text" id="proposed-drinks-per-day" name="ProposedDrinksPerDay" /&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>Let&#8217;s fill the Cost Per Week row consisting of &lt;div&#038;gt: results elements, in both Current and Proposed columns:</p>
<pre class="brush: html">
&lt;tbody&gt;
	&lt;!-- ... --&gt;
	&lt;tr&gt;					
		&lt;td&gt;&lt;label for="cost-per-week"&gt;Cost Per Week:&lt;/label&gt;&lt;/td&gt;
		&lt;td&gt;
				&lt;div id="current-cost-per-week"&gt;&lt;/div&gt;
		&lt;/td&gt;
		&lt;td&gt;
				&lt;div id="proposed-cost-per-week"&gt;&lt;/div&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>Let&#8217;s fill the Savings Per Week row consisting of &lt;div&#038;gt: results elements, in the Proposed column:</p>
<pre class="brush: html">
&lt;tbody&gt;
	&lt;!-- ... --&gt;
	&lt;tr&gt;					
		&lt;td&gt;&lt;label for="savings-per-week"&gt;Savings Per Week:&lt;/label&gt;&lt;/td&gt;
		&lt;td&gt;
				&nsbsp;
		&lt;/td&gt;
		&lt;td&gt;
				&lt;div id="savings-per-week"&gt;&lt;/div&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;!-- ... --&gt;
&lt;/tbody&gt;
</pre>
<p>					<a name='todo2'></a></p>
<h5>2. Create the Consumption Scenarios ViewModel</h5>
<p>In the <b>ViewModels</b> folder under the <b>scripts</b> folder, create a file named: <b>sgs.model.consumption-scenarios.js</b>.And let&#8217;s add a statement to load our new module in in our <b>LAB.js</b> section:
					</p>
<pre class="brush: javascript">
$LAB
	// ...
	.script("scripts/viewmodel/sgs.model.savings-goal.js").wait()
	.script("scripts/viewmodel/sgs.model.savings-goal.js").wait()
	.script("scripts/viewmediator/sgs.mediator.savings-goal.js").wait()
	.script("scripts/viewmodel/sgs.model.consumption-scenarios.js").wait()
	// ...
</pre>
<p>Let&#8217;s add the code snippet to lazy-create the namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.model.consumptionscenarios
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.model) == 'undefined') sgs.model = { }
if (typeof(sgs.model.consumptionscenarios) == 'undefined') sgs.model.consumptionscenarios = { }
</pre>
<p>Let&#8217;s create our <b>initializeViewModel</b> function to initialize the view model and its three value models:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo2a.png" /></p>
<ul>
<li><b>currentConsumption</b> will track our current coffee drinking habits</li>
<li><b>proposedConsumption</b> will allow us to experiment to see how much we could save</li>
<li><b>savingsPerWeek</b> will show us the difference between proposed and current costs and will be implemented as a dependent observable function</li>
<li><b>savingsPerMonth</b>(self explanatory)</li>
</ul>
<p>For now let&#8217;s just assign currentConsumption and proposedConsumption to a <b>ko.observable(null)</b> for now &#8211; we&#8217;ll change that <a href="#todo2c">later</a> (once we create the needed sub-view model).</p>
<pre class="brush: javascript">
sgs.model.consumptionscenarios.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var viewModel = {
		currentConsumption: 	ko.observable(null),
		proposedConsumption: 	ko.observable(null)
	};
	
	// Stub implementation to be fully implemented later on
	viewModel.savingsPerWeek = ko.dependentObservable(function() {
		var result = 0;
		return result;
	}, viewModel);

	viewModel.savingsPerMonth = ko.dependentObservable(function() {
		var perMonth = this.savingsPerWeek() * 4;
		var result = Math.round(perMonth * 100) / 100;
		return result;
	}, viewModel);

	return viewModel;
}
</pre>
<p>We need a way to model our coffee consumption.<br />
					So we&#8217;ll create a new module file named <b>sgs.model.coffee-consumption.js</b> under <b>scripts/viewmodel</b>.<br />
					And let&#8217;s add a statement to load our new module in in our <b>LAB.js</b> section (right before consumption-scenarios):
					</p>
<pre class="brush: javascript">
$LAB
	// ...
	.script("scripts/viewmodel/sgs.model.coffee-consumption.js").wait()
	.script("scripts/viewmodel/sgs.model.consumption-scenarios.js").wait()
	// ...
</pre>
<p>Let&#8217;s add the code snippet to lazy-create the namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.model.coffeeconsumption
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.model) == 'undefined') sgs.model = { }
if (typeof(sgs.model.coffeeconsumption) == 'undefined') sgs.model.coffeeconsumption = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.model.coffeeconsumption loading!");
</pre>
<p>Let&#8217;s create our <b>initializeViewModel</b> function to initialize the view model based on the pageSettins as well as a scenario name. We&#8217;ll have the following value models:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo2b.png" /></p>
<ul>
<li>scenarioName &#8211; will be either Current or Proposed</li>
<li>drinkType</li>
<li>drinkSize</li>
<li>drinkFrequency</li>
<li>customFrequency</li>
<li>drinksPerDay</li>
</ul>
<pre class="brush: javascript">
sgs.model.coffeeconsumption.initializeViewModel = function (pageSettings, scenarioName) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var viewModel = {
		scenarioName: 		ko.observable(scenarioName), 
		drinkType: 			ko.observable("Regular"), 
		drinkSize: 			ko.observable("Tall"), 
		drinkFrequency: 	ko.observable("Everyday"), 
		customFrequency:	ko.observable(1),
		drinksPerDay: 		ko.observable(1)
	}
	
	return viewModel;
}
</pre>
<p>Let&#8217;s add two dependent observable functions named <b>drinkHasStandardSize</b> (will allow us to later restrict the drink size options based on the drink type) and <b>drinkDaysPerWeek</b> (will allow to calculate the cost per week):</p>
<pre class="brush: javascript">
sgs.model.coffeeconsumption.initializeViewModel = function (pageSettings, scenarioName) {
	// ...
	
	var viewModel = {
		// ...
	}
	
	viewModel.drinkHasStandardSize = ko.dependentObservable(function() {
		return this.drinkType() != 'Espresso';
	}, viewModel);
	
	viewModel.drinkDaysPerWeek = ko.dependentObservable(function() {
		var count = 0;
		
		switch(this.drinkFrequency()) {
			case "Everyday":
				count = 7;
				break;
				
			case "WorkDays":
				count = 5;
				break;
				
			case "Other":
				count = this.customFrequency();
				break;
		}
		
		return count;
	}, viewModel);
	
	return viewModel;
}
</pre>
<p>I encourage you to test as you develop along , whether or not you are using a TDD or BDD approach (and framework like <a href="#js-jasmie">Jasmine</a>). So refresh your browser and in the Firebug (or Webkit browser) console, instantiate a <b>sgs.model.coffeeconsumption</b> view model and invoke its <b>drinkDaysPerWeek</b> dependent observable like so:</p>
<pre class="brush: javascript">
var cs = sgs.model.coffeeconsumption.initializeViewModel()
cs.drinkDaysPerWeek()
</pre>
<p>You can also step through the code in the debugger if you really want to check out what happens.</p>
<p>Now let&#8217;s move on and add a stub for a third dependent observable function named: <b>costPerWeek</b></p>
<pre class="brush: javascript">
sgs.model.coffeeconsumption.initializeViewModel = function (pageSettings, scenarioName) {
	// ...
	
	var viewModel = {
		// ...
	}
	
	// ...
	
	// Stub implementation to be fully implemented later on
	viewModel.costPerWeek = ko.dependentObservable(function() {
		var result = 0;
		return result;
	}, viewModel);
	
	return viewModel;
}
</pre>
<p>Later on we&#8217;ll come back to this view model and complete the stub implementation of the <b>costPerWeek</b> dependentObservable function to calculate the actual cost of the consumption model (based on pricing).</p>
<p>					<a name="todo2c"></a></p>
<p>Now let&#8217;s go back to the <b>initializeViewModel</b> of our <b>sgs.model.consumptionscenarios</b> module and update the value model definitions to use custom instantiations of the sgs.model.coffeeconsumption view model so that the relationship between the two view models looks like this:</p>
<p>										<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo2c.png" /></p>
<pre class="brush: javascript">
sgs.model.consumptionscenarios.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var current 	= sgs.model.coffeeconsumption.initializeViewModel (pageSettings, "Current");
	var proposed 	= sgs.model.coffeeconsumption.initializeViewModel (pageSettings, "Proposed");
	
	var viewModel = {
		currentConsumption: 	ko.observable(current),
		proposedConsumption: 	ko.observable(proposed)
	}
		
	// Stub implementation to be fully implemented later on
	viewModel.savingsPerWeek = ko.dependentObservable(function() {
		var result = 0;
		return result;
	}, viewModel);

	viewModel.savingsPerMonth = ko.dependentObservable(function() {
		var perMonth = this.savingsPerWeek() * 4;
		var result = Math.round(perMonth * 100) / 100;
		return result;
	}, viewModel);
	
	return viewModel;
}
</pre>
<p>So now you have implemented an example of hierarchical view model! Again I invite you to test it using the browser Javascript console and debugger.</p>
<p>					<a name='todo3'></a></p>
<h5>3. Create the Consumption Scenarios View Mediator</h5>
<p>Let&#8217;s tackle the view mediator and connect the parts!<br />In the <b>ViewMediator</b> folder under the <b>scripts</b> folder, create a file named: <b>sgs.mediator.consumption-scenarios.js</b>.<br />
					This is the module where we&#8217;ll place our data-binding logic as well as any code related to mediating access between<br />
					the page, the consumption scenario view, and its view model.<br />
					And let&#8217;s add a statement to load our new module in in our <b>LAB.js</b> section:
					</p>
<pre class="brush: javascript">
$LAB
	// ...
	.script("scripts/viewmodel/sgs.model.consumption-scenarios.js").wait()
	.script("scripts/viewmediator/sgs.mediator.consumption-scenarios.js").wait()
	// ...
</pre>
<p>Let&#8217;s define our namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.mediator.consumptionscenarios
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.mediator) == 'undefined') sgs.mediator = { }
if (typeof(sgs.mediator.consumptionscenarios) == 'undefined') sgs.mediator.consumptionscenarios = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.consumptionscenarios loading!");
</pre>
<p>Let&#8217;s create our <b>createViewMediator</b> function (per our convention) which we will eventually invoke from the <b>InitializeApplication</b> method in <b>application.js</b>. The createViewMediator function will have 4 responsibilities:</p>
<ol>
<li>Instantiate a view model for the consumption scenarios view</li>
<li>Declare the data-binding between the HTML elements of the view and their corresponding value models in the view model</li>
<li>Ask KnockoutJS to make the bindings effective (they will be live right after that)</li>
<li>Save off the view model so we can access it from other parts of the app</li>
</ol>
<p>So let&#8217;s implement the first responsibility to instantiate a view model for the consumption scenario view (using the <b>initializeViewModel</b> function we just created in the consumption scenario view model module).</p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.createViewMediator = function (pageSettings) {
	// Create the view Consumption Scenarios view-specific view model
	var viewModel = sgs.model.consumptionscenarios.initializeViewModel(pageSettings);
}
</pre>
<p>Now let&#8217;s declare the data-bindings we need. For <b>input</b> elements we used the <b>value</b> attribute in our <b>data-bind</b> declaration, but since we have some radio buttons, it is the <b>checked</b> attribute of <b>each radio button</b> we need to target. Note that our binding will have a level of indirection via the <b>currentConsumption</b> value model, which is itself a view model with value models like <b>drinkType</b>. Here is what a snippet looks like for the radio buttons located inside the <b>current-drink-type</b> div:</p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.createViewMediator = function (pageSettings) {
	// Create the view Consumption Scenarios view-specific view model
	var viewModel = sgs.model.consumptionscenarios
		.initializeViewModel(pageSettings);
	
	// Declare the HTML element-level data bindings for the Current Habits column
	$("#current-drink-type input[type=radio]")
		.attr("data-bind",
				"checked: currentConsumption().drinkType");

</pre>
<p>Let&#8217;s finish up the rest of the bindings:</p>
<pre class="brush: javascript">
	// ...
	
	// Declare the HTML element-level data bindings for the Current Habits column
	$("#current-drink-type  input[type=radio]")
		.attr("data-bind","checked: currentConsumption().drinkType");
	$("#current-drink-size input[type=radio]")
		.attr("data-bind","checked: currentConsumption().drinkSize");
	$("#current-drink-frequency input[type=radio]")
		.attr("data-bind","checked: currentConsumption().drinkFrequency");
	$("#current-custom-frequency")						
		.attr("data-bind","value: currentConsumption().customFrequency");
	$("#current-drinks-per-day")
		.attr("data-bind","value: currentConsumption().drinksPerDay");
	$("#current-cost-per-week")
		.attr("data-bind","text: currentConsumption().costPerWeek");
	
	// Declare the HTML element-level data bindings for the Proposed Change column
	$("#proposed-drink-type input[type=radio]")
		.attr("data-bind","checked: proposedConsumption().drinkType");
	$("#proposed-drink-size input[type=radio]")
		.attr("data-bind","checked: proposedConsumption().drinkSize");
	$("#proposed-drink-frequency input[type=radio]")
		.attr("data-bind","checked: proposedConsumption().drinkFrequency");
	$("#proposed-custom-frequency")							 
		.attr("data-bind","value: proposedConsumption().customFrequency");
	$("#proposed-drinks-per-day")								 
		.attr("data-bind","value: proposedConsumption().drinksPerDay");
	$("#proposed-cost-per-week")
		.attr("data-bind","text: proposedConsumption().costPerWeek");
	$("#savings-per-week")
		.attr("data-bind","text: savingsPerWeek");

	// ...
</pre>
<p>Let&#8217;s add a new kind of binding attribute: &#8220;<b>enable</b>&#8220;, which allow us to control whether or not the data-bound HTML element should be enabled. This is a very useful binding as it will simplify enabling/disabling rules a lot. Here we&#8217;ll use it to control whether or not the drink size radio buttons should be enabled, since an espresso does not typically come in a Tall / Grande / Venti size! (Wow imagine the buzz on Venti!)</p>
<p>					<u>Reminder:</u> The syntax of data-bind in KnockoutJS is:
					</p>
<pre class="brush: javascript">
databind="attribute1: valueModel1, attribute2: valueModel2, etc." // comma-separated list
</pre>
<p>This means that we will need to <b>comma-separate</b> and <b>concatenate</b> our new &#8220;<b>attribute: valueModel</b>&#8221; binding pair at the end of our existing declaration for the &#8220;checked&#8221; attribute like so:
</p>
<pre class="brush: javascript">
	// ...
	
	// Declare the HTML element-level data bindings for the Current Habits column
	// ...
	$("#current-drink-size input[type=radio]")
		.attr("data-bind","checked: currentConsumption().drinkSize " +
						", enable: currentConsumption().drinkHasStandardSize");
	// ...
	
	// Declare the HTML element-level data bindings for the Proposed Change column
	// ...
	$("#proposed-drink-size input[type=radio]")
		.attr("data-bind","checked: proposedConsumption().drinkSize" +
						", enable: proposedConsumption().drinkHasStandardSize");
	
	// ...
</pre>
<p><u>Caution</u>: the name of the attribute is &#8220;<b>enable</b>&#8221; <i>(not &#8220;enabled&#8221; &#8211; I have been bit by that many times)</i>!</p>
<p>Now we&#8217;ll ask KnockoutJS to &#8220;apply&#8221;, i.e. register / enable our bindings. </p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.createViewMediator = function (pageSettings) {
	// ...
	
	// Ask KnockoutJS to data-bind the view model to the view
	var viewNode = $('#consumption-scenarios-view')[0];
	ko.applyBindings(viewModel, viewNode);
}
</pre>
<p>Now let&#8217;s add the 2 functions to store retrieve our consumption scenarios view model:</p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.getViewModel = function() {
	return $(document).data("sgs.model.consumptionscenarios.viewmodel");
}

sgs.mediator.consumptionscenarios.setViewModel = function(viewModel) {
	$(document).data("sgs.model.consumptionscenarios.viewmodel", viewModel);
}
</pre>
<p>Now we can call the <b>setViewModel</b> function from inside <b>createViewMediator</b> to save off our freshly-created view model.</p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.createViewMediator = function (pageSettings) {
	// ...
	
	// Save the view model
	sgs.mediator.consumptionscenarios.setViewModel(viewModel);	

	if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.coffeeconsumption ready!");
}
</pre>
<p>If you want to test the mediator, just refresh the browser, and invoke the <b>createViewMediator</b> in the browser Javascript console like so:</p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.createViewMediator({})
</pre>
<p>You will then see the radio buttons get set to their default value. And clicking on the Espresso radio button should cause the Size radio buttons to become disabled.</p>
<p>					<a name='todo4'></a></p>
<h5>4. Link the Page and the Consumptions Scenarios View Mediator</h5>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo4.png" /></p>
<p>To instantiate our new mediator, we just need to add a call to the overall page <b>InitializeApplication</b> function (located in our <b>scripts/application.js</b>) to our consumption scenario <b>createViewMediator</b> function like so:</p>
<pre class="brush: javascript">
function InitializeApplication() {
	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication starting ...");
		
	// Initialize our page-wide settings
	var pageSettings = { defaultSavingsGoal: 500 }
	
	// Create / launch our view mediator(s)
	sgs.mediator.savingsgoal.createViewMediator(pageSettings);
	sgs.mediator.consumptionscenarios.createViewMediator(pageSettings);

	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication done ...");	
}
</pre>
<p>So now you should be able to load your index.html page in Firefox with the Firebug console on and watch the debug statement and finally our new consumption scenarios view displays with our default values:
					</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-2.png" /></p>
<p>					<a name='todo5'></a></p>
<h5>5. Create the Coffee Pricing ViewModel</h5>
<p>Now we need a pricing engine! It needs to ake into account : the drink type and drink size. And we can apply frequency and drinks per day to calculate the cost. To keep logic encapsulated, let&#8217;s create a new module file in the <b>scripts/viewmodel</b> folder named <b>sgs.model.coffee-pricing.js</b>. The new module will be responsible for:
					</p>
<ol>
<li>having a default example pricing list for the various coffee options</li>
<li>providing its own view model with a <b>pricing</b> value model</li>
<li>loading / saving its content to the browser local storage (using <a href="#js-jstorage">jStorage</a>, a cross-browser HTML 5 local storage abstraction library)</li>
</ol>
<p>Let&#8217;s add the code snippet to lazy-create the namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.model.coffeeconsumption
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.model) == 'undefined') sgs.model = { }
if (typeof(sgs.model.coffeepricing) == 'undefined') sgs.model.coffeepricing = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.model.coffeepricing loading!");
</pre>
<p>Update the LAB.js section of the index.html page so we can load the new module (before sgs.model.coffee-consumption):</p>
<pre class="brush: html">
	$LAB
		// ...
		.script("scripts/viewmodel/sgs.model.coffee-pricing.js").wait()
		.script("scripts/viewmodel/sgs.model.coffee-consumption.js").wait()
		// ...
</pre>
<p>Now we&#8217;ll create an <b>examplePricing</b> function which will return a hash of key-value pairs where the key will be a composite of the coffee type and size, and the value an amount.</p>
<pre class="brush: javascript">
sgs.model.coffeepricing.examplePricing = function() {
	var priceList = {
		"Regular-Tall": 1.40,
		"Regular-Grande": 1.60,
		"Regular-Venti": 1.70,

		"Latte-Tall": 2.55,
		"Latte-Grande": 3.10,
		"Latte-Venti": 3.40,

		"Espresso": 1.75,
		"EspressoShot": 0.25
	}
	
	return priceList;
}
</pre>
<p>Now let&#8217;s define our initializeViewModel function with a place holder for the price list:</p>
<pre class="brush: javascript">
sgs.model.coffeepricing.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var priceList = { }
	var viewModel = {
		pricing: 		ko.observable(priceList)
	}
	
	return viewModel;
}
</pre>
<p>Ok, now we want to check if we have a price list in local storage and lazy-initialize it otherwise. We&#8217;ll encapsulate the logic in a function named: <b>getPriceList</b>. We&#8217;ll try to retrieve the &#8220;<b>coffee-price-list</b>&#8221; using <b>$.jStorage.get(key)</b> API:</p>
<pre class="brush: javascript">
sgs.model.coffeepricing.getPriceList = function () {
	// Check if we have ever stored the price list locally
	var priceList = $.jStorage.get("coffee-price-list");
	
	if (priceList == null) {
		// If not create an example
		priceList = sgs.model.coffeepricing.examplePricing();
		
		// Save it off
		$.jStorage.set("coffee-price-list", priceList);
	}
	
	return priceList;
}
</pre>
<p>So now we can edit our in <b>initializeViewModel</b> function and plug in the <b>getPriceList</b> for the initialization of the <b>pricing</b> value model:</p>
<pre class="brush: javascript">
sgs.model.coffeepricing.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	// Lazy-initialize the price list
	var priceList = sgs.model.coffeepricing.getPriceList();
	
	var viewModel = {
		pricing: 		ko.observable(priceList)
	}
	
	return viewModel;
}
</pre>
<p>To encapsulate pricing data requests, let&#8217;s add a &#8220;normal&#8221; function (i.e. not an dependent observable) named <b>getCoffeeBeveragePrice</b> to our view model:</p>
<pre class="brush: javascript">
sgs.model.coffeepricing.initializeViewModel = function (pageSettings) {
	// ...
	
	viewModel.getCoffeeBeveragePrice = function (drinkType, drinkSize) {
		var key = drinkType;
		
		if (drinkType != 'Espresso' && drinkSize) {
			key += '-' + drinkSize;
		}
		
		var price = viewModel.pricing()[key];
		return price;
	}
	
	return viewModel;
}
</pre>
<p>Once reloading the index.html page, you should be able to experiment with jStorage. To see all keys stored with jStorage (should be an empty array initially):</p>
<pre class="brush: javascript">
$.jStorage.index()
</pre>
<p>Now, let&#8217;s make a call to <b>sgs.model.coffeepricing.getPriceList()</b>. This will lazy-initialize the price list and store it. So when asking for the jStorage index a second time the console should display an array with our &#8220;<b>coffee-price-list</b>&#8221; key. And we can access the value for our key using:</p>
<pre class="brush: javascript">
sgs.model.coffeepricing.getPriceList()
$.jStorage.index()
$.jStorage.get("coffee-price-list")
</pre>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-3.png" /></p>
<p>					<a name='todo6'></a></p>
<h5>6. Create the Coffee Pricing ViewMediator</h5>
<p>In the <b>Viewmediator</b> folder under the <b>scripts</b> folder, create a file named: <b>sgs.mediator.coffee-pricing.js</b>. This is the module where we&#8217;ll place our data-binding logic as well as any code related to mediating access between the page, a future pricing editing view, and its view model.<br /> And let&#8217;s add a statement to load our new module in in our <b>LAB.js</b> section:
					</p>
<pre class="brush: javascript">
$LAB
	// ...
	.script("scripts/viewmodel/sgs.model.coffee-pricing.js").wait()
	.script("scripts/viewmediator/sgs.mediator.coffee-pricing.js").wait()
	// ...
</pre>
<p>Let&#8217;s define our namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.mediator.coffeepricing
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.mediator) == 'undefined') sgs.mediator = { }
if (typeof(sgs.mediator.coffeepricing) == 'undefined') sgs.mediator.coffeepricing = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.coffeepricing loading!");
</pre>
<p>Let&#8217;s create our <b>createViewMediator</b> function (per our convention) which we will eventually invoke from the <b>InitializeApplication</b> method in <b>application.js</b>. The createViewMediator function will have 3 responsibilities:</p>
<ol>
<li>Instantiate a view model for the future pricing editor view</li>
<li>Ask KnockoutJS to make the bindings effective (they will be live right after that)</li>
<li>Save off the view model so we can access it from other parts of the app</li>
</ol>
<p>Note: this mediator will not need to setup any data-bindings with the view, since we are not planning on displaying the pricing. However, the <b>consumption scenario mediator</b> will collaborate with it in order to access its <b>pricing view model</b>.</p>
<p>So let&#8217;s implement the first responsibility to instantiate a view model<br />
					(using the <b>initializeViewModel</b> function we just created in the coffee pricing view model module).</p>
<pre class="brush: javascript">
sgs.mediator.coffeepricing.createViewMediator = function (pageSettings) {
	// Create the view Pricing Editor view-specific view model
	var viewModel = sgs.model.coffeepricing.initializeViewModel(pageSettings);
}
</pre>
<p>Now let&#8217;s add the 2 functions to store retrieve our coffee pricing view model:</p>
<pre class="brush: javascript">
sgs.mediator.coffeepricing.getViewModel = function() {
	return $(document).data("sgs.model.coffeepricing.viewmodel");
}

sgs.mediator.coffeepricing.setViewModel = function(viewModel) {
	$(document).data("sgs.model.coffeepricing.viewmodel", viewModel);
}
</pre>
<p>Now we can use the setViewModel function inside createViewMediator to save off our freshly-created view model.</p>
<pre class="brush: javascript">
sgs.mediator.coffeepricing.createViewMediator = function (pageSettings) {
	// ...
	
	// Save the view model
	sgs.mediator.coffeepricing.setViewModel(viewModel);	

	if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.coffeepricing ready!");
}
</pre>
<p>					<a name='todo7'></a></p>
<h5>7. Link the Page and the Coffee Pricing View Mediator</h5>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo7.png" /></p>
<p>To instantiate our new mediator, we just need to add a call to the overall page <b>InitializeApplication</b> function (located in our <b>scripts/application.js</b>) to our coffee pricing <b>createViewMediator</b> function like so:</p>
<pre class="brush: javascript">
function InitializeApplication() {
	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication starting ...");
		
	// Initialize our page-wide settings
	var pageSettings = { defaultSavingsGoal: 500 }
	
	// Create / launch our view mediator(s)
	sgs.mediator.savingsgoal.createViewMediator(pageSettings);
	sgs.mediator.coffeepricing.createViewMediator(pageSettings);
	sgs.mediator.consumptionscenarios.createViewMediator(pageSettings);

	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication done ...");	
}
</pre>
<p>					<a name='todo8'></a></p>
<h5>8. Leveraging Independent View Models</h5>
<p>At this point we have created the consumption, scenarios, and pricing view models, but we have not yet &#8220;connected&#8221; all the parts to allow for the <b>costPerWeek</b> value model of <b>coffeeconsumption</b> to work. Before we proceed let&#8217;s review a few requirements and guiding principles:</p>
<ul>
<li>The consumptionscenarios view model knows about the <b>current</b> and <b>proposed</b> coffee consumptions</li>
<li>The coffeeconsumption view model has the <b>costPerWeek</b> dependent observable function</li>
<li>The coffeepricing view model has the <b>pricing</b></li>
<li>The coffeepricing view mediator manages access to its view model</li>
<li>We want to keep the view models from knowing about the mediators</li>
<li>Over time, we may want to test different pricing models in each scenario</li>
</ul>
<p>So to maintain isolation but yet gain some flexibility we will:</p>
<ol>
<li>Add a <b>pricing</b> value model to the <b>coffeeconsumption</b> view model &#8211; this way costPerWeek will have access to it</li>
<li>Add a <b>pricing</b> value model to the <b>consumptionscenarios</b> view model &#8211; this way it can pass it on each of the current and proposed consumptions models</li>
<li>Add a <b>subscription</b> to the <b>pricing change</b> in the <b>consumptionscenarios</b> view model so we can update the pricing of the current and proposed consumptions models</li>
<li>Have the consumption-scenario and coffee pricing view mediators <b>share the pricing</b> view model</li>
</ol>
<p>Here is what the relationship between the various mediators and model will look like:</p>
<p>										<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo8.png" /></p>
<p>First, let&#8217;s add a <b>pricing</b> value model to the <b>coffeeconsumption</b> view model (located in <b>scripts/viewmodel/sgs.model.coffeeconsumption.js</b>):</p>
<pre class="brush: javascript">
sgs.model.coffeeconsumption.initializeViewModel = function (pageSettings, scenarioName) {
	// ...
	
	var viewModel = {
		pricing: 		ko.observable(null), 
		scenarioName: 	ko.observable(scenarioName), 
		// ...
	}

	// ...
}
</pre>
<p>Second, let&#8217;s add a <b>pricing</b> value model to the <b>consumptionscenarios</b> view model (located in <b>scripts/viewmodel/sgs.model.consumptionscenarios.js</b>)</p>
<pre class="brush: javascript">
sgs.model.consumptionscenarios.initializeViewModel = function (pageSettings) {
	// ...
	
	var viewModel = {
		pricing: 				ko.observable(null), 
		currentConsumption: 	ko.observable(current),
		proposedConsumption: 	ko.observable(proposed)
	}

	// ...
}
</pre>
<p>Third, let&#8217;s add a <b>subscription</b> to <b>pricing</b> value model so we can re-act to pricing model changes and pass the new pricing down to our 2 consumption models:</p>
<pre class="brush: javascript">
sgs.model.consumptionscenarios.initializeViewModel = function (pageSettings) {
	// ...
		
	viewModel.pricing.subscribe(function(newPricing) {
		viewModel.currentConsumption().pricing(newPricing);
		viewModel.proposedConsumption().pricing(newPricing);
	});
	
	// ...
}</pre>
<p>Fourth, let&#8217;s have the <a href="">consumption-scenario view mediator</a> set the <b>pricing</b> based on the view model of the <b>coffee pricing view mediator</b>:</p>
<pre class="brush: javascript">
sgs.mediator.consumptionscenarios.createViewMediator = function (pageSettings) {
	// ...

	// Save the view model
	sgs.mediator.consumptionscenarios.setViewModel(viewModel);	

	// Set the pricing based on the Coffee Pricing view model
	var priceList = sgs.mediator.coffeepricing.getViewModel();
	viewModel.pricing(priceList);
	
	// ...
}
</pre>
<p>So now we have the bits in place to fully implement the <b>costPerWeek</b> function of the <b>coffeeconsumption</b> view model. (Remember we had just put in a stub implementation returning 0 in step <a href="#todo2">&#8220;2. Create the Consumption Scenarios ViewModel&#8221;</a>). It&#8217;s a matter of performing the calculations like so:</p>
<pre class="brush: javascript">
sgs.model.coffeeconsumption.initializeViewModel = function (pageSettings, scenarioName) {
	// ...
	
	viewModel.costPerWeek = ko.dependentObservable(function() {
		// Get the base price
		if (this.pricing() == null) {
			return 0;
		}
		
		var basePrice 	= this.pricing().getCoffeeBeveragePrice(this.drinkType(), this.drinkSize());
		var dailyCost 	= basePrice * this.drinksPerDay();
		var weeklyCost	= dailyCost * this.drinkDaysPerWeek();
		var result 		= Math.round(weeklyCost * 100) / 100;
		
		return result;
	}, viewModel);

	return viewModel;
}
</pre>
<p>And finally we can go back and finish the implementation of the <b>savingsPerWeek</b> function in the <b>consumptionscenarios</b> view model. (Remember we had just put in a stub implementation returning 0 in step <a href="#todo2">&#8220;2. Create the Consumption Scenarios ViewModel&#8221;</a>)</p>
<pre class="brush: javascript">
sgs.model.consumptionscenarios.initializeViewModel = function (pageSettings) {
	// ...

	viewModel.savingsPerWeek = ko.dependentObservable(function() {
		var costDifference = this.currentConsumption().costPerWeek() - this.proposedConsumption().costPerWeek();
		var result = Math.round(costDifference * 100) / 100;
		return result;
	}, viewModel);

	// ...
	
	return viewModel;
}
</pre>
<p>Now we&#8217;re ready to refresh the index.html page, select Grande Latte under Current Habits and Tall Regular under Proposed Changes and you should see the costs update as well as the savings. We now have a functioning Weekly Coffee Consumption panel! :-)</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-4.png" /></p>
<p>I will leave the following usability additions for you to do:</p>
<ul>
<li>Formatting of the costs and saving amounts (dependent observables and Accounting.js &#8211; see <a href="https://blog.monnet-usa.com/?p=368#todo9" target='_blank'>Part 1 ToDo #9 &#8211; Applying Formatting Rules</a>)</li>
<li>Add visual feedback (using the jQuery highlight effect) for the costs and savings fields see <a href="https://blog.monnet-usa.com/?p=368#todo10" target='_blank'>Part 1 ToDo #10 &#8211; Applying Visual Feedback Clues</a></li>
<li>Overall styling</li>
</ul>
<p>					<a name='todo9'></a></p>
<h5>9. Create the Savings Forecast View</h5>
<p>In our <b>index.html</b> page, let&#8217;s add a second section tag to represent our third panel / view:<br />
					the <b>savings-forecast-view</b>.<br />
					The view will help us compare projected savings against our goal.</p>
<pre class="brush: html">
&lt;body&gt;
	&lt;!-- ... --&gt;
	&lt;section id='savings-forecast-view'&gt;
	&lt;/section&gt;
&lt;/body&gt;
</pre>
<p>This is what the view will look like:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-5.png" /></p>
<p>The view will have three pairs of labels and spans to show calculated values for:</p>
<ul>
<li>Savings forecast per month</li>
<li>Forecast variance from the target monthly savings goal</li>
<li>Forecasted number of months to achieve the savings goal</li>
</ul>
<pre class="brush: html">
			&lt;label for="savings-forecast-per-month"&gt;Savings Forecast Per Month:&lt;/label&gt;
			&lt;span id="savings-forecast-per-month" &gt;&lt;/span&gt;&lt;br/&gt;

			&lt;label for="forecast-variance-per-month"&gt;Forecast Variance:&lt;/label&gt;
			&lt;span id="forecast-variance-per-month"&gt;&lt;/span&gt;&lt;br/&gt;

			&lt;label for="time-to-goal-in-months"&gt;Months To Savings Goal:&lt;/label&gt;
			&lt;span id="time-to-goal-in-months"&gt;&lt;/span&gt;&lt;br/&gt;
</pre>
<p>					<a name='todo10'></a></p>
<h5>10. Create the Savings Forecast ViewModel</h5>
<p>In the <b>ViewModels</b> folder under the <b>scripts</b> folder, create a file named: <b>sgs.model.savings-forecast.js</b>.<br />
					And let&#8217;s add a statement to load our new module in in our <b>LAB.js</b> section:
					</p>
<pre class="brush: javascript">
$LAB
	// ...
	.script("scripts/viewmodel/sgs.model.savings-forecast.js").wait()
	// ...
</pre>
<p>Let&#8217;s add the code snippet to lazy-create the namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.model.savingsforecast
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.model) == 'undefined') sgs.model = { }
if (typeof(sgs.model.savingsforecast) == 'undefined') sgs.model.savingsforecast = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.model.savingsforecast loading!");
</pre>
<p>Let&#8217;s create our <b>initializeViewModel</b> function to initialize the view model.<br />
					We need two dependent observable functions:</p>
<ul>
<li><b>forecastVariancePerMonth</b> will allow us to experiment to see how much we could save</li>
<li><b>timeToGoalInMonths</b> will show us the difference between proposed and current costs and will be implemented as a dependent observable function</li>
</ul>
<p>										<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo10.png" /></p>
<pre class="brush: javascript">
sgs.model.savingsforecast.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var viewModel = {
	};	

	viewModel.forecastVariancePerMonth = ko.dependentObservable(function() {
		// TBD
	}, viewModel);

	viewModel.timeToGoalInMonths = ko.dependentObservable(function() {
		// TBD
	}, viewModel);

	return viewModel;
}
</pre>
<p>Design Note: in this series of tutorial I have promoted the idea of <b>decoupling all views, models, and mediators</b> (as possible) as it makes the application <b>more modular</b> and it is <b>easier to test</b> all parts independently. So for this view model, instead of requesting the value models from other mediators namely <b>savingsGoalAmount</b>, <b>savingsTargetPerMonth</b> and  <b>savingsPerMonth</b>, we will create dedicated value models which will later synchronize with using subscriptions in our mediators &#8211; since it is ok for the mediators to collaborate.
					</p>
<pre class="brush: javascript">
sgs.model.savingsforecast.initializeViewModel = function (pageSettings) {
	// ...
	
	var viewModel = {
		savingsGoalAmount: ko.observable(0), 
		savingsTargetPerMonth: ko.observable(0), 
		savingsPerMonth: ko.observable(0)
	};	

	// ...
	
	return viewModel;
}
</pre>
<p>Let&#8217;s flesh-out our calculations:</p>
<pre class="brush: javascript">
sgs.model.savingsforecast.initializeViewModel = function (pageSettings) {
	// ...	

	viewModel.forecastVariancePerMonth = ko.dependentObservable(function() {
		var variance = this.savingsPerMonth() - this.savingsTargetPerMonth();
		var result = Math.round(variance * 100) / 100;
		return result;
	}, viewModel);

	viewModel.timeToGoalInMonths = ko.dependentObservable(function() {
		var timeToGoal = 0;
		var savingsPerMonth = this.savingsPerMonth();
		var savingsGoalAmount = this.savingsGoalAmount();
		
		if (savingsPerMonth != 0) {
			timeToGoal = savingsGoalAmount / savingsPerMonth;
		}
	}, viewModel);

	// ...
}
</pre>
<p>					<a name='todo11'></a></p>
<h5>11. Create the Savings Forecast View Mediator</h5>
<p>In the <b>Viewmediator</b> folder under the <b>scripts</b> folder, create a file named: <b>sgs.mediator.savings-forecast.js</b>. This is the module where we&#8217;ll place our data-binding logic as well as any code related to mediating access between the page, the consumption scenario view, and its view model.<br /> And let&#8217;s add a statement to load our new module in in our <b>LAB.js</b> section:
					</p>
<pre class="brush: javascript">
$LAB
	// ...
	.script("scripts/viewmodel/sgs.model.savings-forecast.js").wait()
	.script("scripts/viewmediator/sgs.mediator.savings-forecast.js").wait()
	// ...
</pre>
<p>Let&#8217;s define our namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.mediator.savingsforecast
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.mediator) == 'undefined') sgs.mediator = { }
if (typeof(sgs.mediator.savingsforecast) == 'undefined') sgs.mediator.savingsforecast = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.savingsforecast loading!");
</pre>
<p>Let&#8217;s create our <b>createViewMediator</b> function (per our convention) which we will eventually invoke from the <b>InitializeApplication</b> method in <b>application.js</b>. The createViewMediator function will have 5 responsibilities:</p>
<ol>
<li>Instantiate a view model for the savings forecast view</li>
<li>Establish subscriptions for various value models to keep the main view model synchronized</li>
<li>Declare the data-binding between the HTML elements of the view and their corresponding value models in the view model</li>
<li>Ask KnockoutJS to make the bindings effective (they will be live right after that)</li>
<li>Save off the view model so we can access it from other parts of the app</li>
</ol>
<p>So let&#8217;s implement the first responsibility to instantiate a view model for the consumption scenario view  (using the <b>initializeViewModel</b> function we just created in the consumption scenario view model module).</p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.createViewMediator = function (pageSettings) {
	// Create the view Savings Forecast view-specific view model
	var viewModel = sgs.model.savingsforecast.initializeViewModel(pageSettings);
}
</pre>
<p>Now we need to establish <b>3 subscriptions</b> so that we can keep our saving forecast view model in synch with value models from the <b>savings goal</b>  and <b>consumption scenarios</b> view models. Here is a graphical depiction of what we need:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo11.png" /></p>
<p>To make this happen we need the <b>savingsforecast mediator</b> to request specific value models from the view models of the <b>savingsgoal</b> and <b>consumptionsscenarios</b> mediators:</p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.createViewMediator = function (pageSettings) {
	// ...
	
	// Subscribe to changes in savingsGoalAmount and savingsTargetPerMonth 
	// to synchronize our own equivalent value models
	var savingsGoalModel = sgs.mediator.savingsgoal.getViewModel();
	
	// Initialize the current savingsGoalAmount
	viewModel.savingsGoalAmount(savingsGoalModel.savingsGoalAmount());

	savingsGoalModel.savingsGoalAmount.subscribe(function(newValue) {
		viewModel.savingsGoalAmount(newValue);
	});

	savingsGoalModel.savingsTargetPerMonth.subscribe(function(newValue) {
		viewModel.savingsTargetPerMonth(newValue);
	});

	// Subscribe to changes in savingsPerMonth to synchronize our own equivalent value model
	var consumptionscenariosModel = sgs.mediator.consumptionscenarios.getViewModel();
	consumptionscenariosModel.savingsPerMonth.subscribe(function(newValue) {
		viewModel.savingsPerMonth(newValue);
	});
	
	// ...
}
</pre>
<p>Now let&#8217;s declare the data-bindings we need.</p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.createViewMediator = function (pageSettings) {
	// Create the view Savings Forecast view-specific view model
	var viewModel = sgs.model.savingsforecast
		.initializeViewModel(pageSettings);
	
	// Declare the HTML element-level data bindings 
	$("#savings-forecast-per-month")
		.attr("data-bind","text: savingsPerMonth");
	$("#forecast-variance-per-month")	
		.attr("data-bind","text: forecastVariancePerMonth");
	$("#time-to-goal-in-months")	
		.attr("data-bind","text: timeToGoalInMonths");

	// ...
</pre>
<p>Now we&#8217;ll ask KnockoutJS to &#8220;apply&#8221;, i.e. register / enable our bindings. </p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.createViewMediator = function (pageSettings) {
	// ...
	
	// Ask KnockoutJS to data-bind the view model to the view
	var viewNode = $('#savings-forecast-view')[0];
	ko.applyBindings(viewModel, viewNode);
}
</pre>
<p>Now let&#8217;s add the 2 functions to store retrieve our savings forecast view model:</p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.getViewModel = function() {
	return $(document).data("sgs.model.savingsforecast.viewmodel");
}

sgs.mediator.savingsforecast.setViewModel = function(viewModel) {
	$(document).data("sgs.model.savingsforecast.viewmodel", viewModel);
}
</pre>
<p>Now we can use the setViewModel function inside createViewMediator to save off our freshly-created view model.</p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.createViewMediator = function (pageSettings) {
	// ...
	
	// Save the view model
	sgs.mediator.savingsforecast.setViewModel(viewModel);	

	if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.savingsforecast ready!");
}
</pre>
<p>Again you can try your new mediator using the browser console:</p>
<pre class="brush: javascript">
sgs.mediator.savingsforecast.createViewMediator({})
</pre>
<p>Playing with the simulation should now update the savings-forecast view.</p>
<p>					<a name='todo12'></a></p>
<h5>12. Link the Page and the Savings Forecast View Mediator</h5>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part3-todo12.png" /></p>
<p>To instantiate our new mediator, we just need to add a call to the overall page <b>InitializeApplication</b> function (located in our <b>scripts/application.js</b>) to our consumption scenario <b>createViewMediator</b> function like so:</p>
<pre class="brush: javascript">
function InitializeApplication() {
	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication starting ...");
		
	// Initialize our page-wide settings
	var pageSettings = { defaultSavingsGoal: 500 }
	
	// Create / launch our view mediator(s)
	sgs.mediator.savingsgoal.createViewMediator(pageSettings);
	sgs.mediator.coffeepricing.createViewMediator(pageSettings);
	sgs.mediator.consumptionscenarios.createViewMediator(pageSettings);
	sgs.mediator.savingsforecast.createViewMediator(pageSettings);

	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication done ...");	
}
</pre>
<p>Now you can refresh your page and should be able to see the new savings forecast view update as you experiment!</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part2-6.png" /></p>
<hr>
<h5>Overall Recap</h5>
<p>In this part 3 of the tutorial we have added quite a bit more functionality and complexity. Hopefully the modularization, separation into different files and folders, the namespacing, and various patterns are now starting to reveal their purpose and value. ;-)<br /> So here is a quick recap of the steps we followed:</p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
<th>Area (Module)</th>
</tr>
<tr>
<td><a href='#todo1'>1</a></td>
<td>Create the Consumption Scenarios View</td>
<td>View</td>
</tr>
<tr>
<td><a href='#todo2'>2</a></td>
<td>Create the Consumption Scenarios ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo3'>3</a></td>
<td>Create the Consumption Scenarios View Mediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo4'>4</a></td>
<td>Link the Page and the View Mediator</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo5'>5</a></td>
<td>Create the Coffee Pricing ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo6'>6</a></td>
<td>Create the Coffee Pricing ViewMediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo7'>7</a></td>
<td>Link the Page and the Coffee Pricing View Mediator</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo8'>8</a></td>
<td>Leveraging Independent View Models</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo9'>9</a></td>
<td>Create the Savings Forecast View</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo10'>10</a></td>
<td>Create the Savings Forecast ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo11'>11</a></td>
<td>Create the Savings Forecast View Mediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo12'>12</a></td>
<td>Link the Page and the Savings Forecast View Mediator</td>
<td>Main App</td>
</tr>
</table>
<p>					<a name='sowhat'></a></p>
<h3>So What?</h3>
<p>This part 3 gave you a lot more practice with the core patterns and also showed you the following:</p>
<ul>
<li>Create hierarchical view models</li>
<li>Setup custom subscriptions to keep independent view models synchronized</li>
<li>Configure multiple attributes inside a data-bind declaration (e.g. checked and enabled)</li>
<li>Leverage jStorage for local browser data caching</li>
</ul>
<p>If we step back and look at the <b>modularization</b> of our application so far, we&#8217;ll notice that although our models and view mediators are modular, the actual index.html web page has become larger and is not modular at all. Wouldn&#8217;t it be nice if we could extract each of our views into external modules? Well, this is exactly what <a href="#">part 4</a> will cover!</p>
<ul>
<li>Leveraging jQuery templates</li>
<li>Extracting views into templates (and in separate files)</li>
<li>&#8230; and more!</li>
</ul>
<p>So stay tuned!</p>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>Patterns</h5>
<ul>
<li><a name='mvvmp' href='http://en.wikipedia.org/wiki/Model_View_ViewModel'>Model View &#8211; ViewModel Pattern</a></li>
<li><a name='mvcp' href='http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html'>MVC Xerox Parc 1978-79</a></li>
<li><a name='mvcp' href='http://c2.com/cgi/wiki?ModelViewController'>MVC Pattern</a></li>
<li><a name='obp' href='http://c2.com/cgi/wiki?ObserverPattern'>Observer Pattern</a></li>
<li><a name='psp' href='http://c2.com/cgi/wiki?PublishSubscribeModel'>Publish Subscribe Pattern</a></li>
<li><a name='vmp' href='http://c2.com/cgi/wiki?ValueModel'>Value Model Pattern</a></li>
<li><a name='dbp' href='http://c2.com/cgi/wiki?DataBinding'>Data Binding Pattern</a></li>
<li><a name='ns-summary' href='http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/'>Summary of Namespacing Approaches (by Elijah Manor)</a></li>
<li><a name='ns-objectliteral' href='http://stackoverflow.com/questions/881515/javascript-namespace-declaration/881556#881556'>Namespacing using Object Literals</a></li>
<li><a name='ns-function' href='http://stackoverflow.com/questions/881515/javascript-namespace-declaration/881611#881611'>Namespacing using Functions</a></li>
</ul>
<h5>Frameworks And Blogs</h5>
<ul>
<li><a name='ko' href='http://knockoutjs.com/'>KnockoutJS</a></li>
<li><a name='lko' href='http://learn.knockoutjs.com/'>Learn KnockoutJS (Interactive Tutorial / Playground)</a></li>
<li><a name='jq' href='http://jquery.com/'>jQuery</a></li>
<li><a name='jqui' href='http://jqueryui.com/'>jQuery UI</a></li>
<li><a name='jqt' href='http://api.jquery.com/jQuery.template/'>jQuery Template</a></li>
<li><a name='jqtapi' href='http://api.jquery.com/jQuery.template/'>jQuery Template API</a></li>
<li><a name='ss' href='http://blog.stevensanderson.com/'>Knock Me Out (Steve Sanderson&#8217;s Blog)</a></li>
<li><a name='kmo' href='http://www.knockmeout.net/'>Knock Me Out (Ryan Niemeyer&#8217;s Blog)</a></li>
<li><a name='pflsjaa' href='http://addyosmani.com/blog/patterns-for-large-scale-javascript-application-architecture/'>Patterns For Large-Scale Javascript Architecture (Addy Osmani)</a></li>
</ul>
<p>					<a name="javascript-loaders" ></a></p>
<h5>Javascript Loaders</h5>
<ul>
<li><a name='headjs' href='http://headjs.com/' target='_blank'>HeadJS</a></li>
<li><a name='labjs' href='http://labjs.com/' target='_blank'>LABjs</a></li>
<li><a name='lazyload' href='https://github.com/rgrove/lazyload' target='_blank'>LazyLoad</a></li>
<li><a name='jquery-cookie' href='https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js' target='_blank'>jQuery Cookie</a></li>
</ul>
<p>					<a name="jquery-plugins" ></a></p>
<h5>jQuery Plugins</h5>
<ul>
<li><a name='jquery-blockui' href='http://jquery.malsup.com/block/' target='_blank'>jQuery BlockUI</a></li>
<li><a name='jquery-cookie' href='https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js' target='_blank'>jQuery Cookie</a></li>
<li><a name='jquery-datatables' href='http://datatables.net/' target='_blank'>jQuery DataTables</a></li>
<li><a name='jquery-hotkeys' href='https://github.com/tzuryby/jquery.hotkeys' target='_blank'>jQuery HotKeys</a></li>
<li><a name='jquery-tree' href='http://www.jstree.com/' target='_blank'>jQuery jsTree</a></li>
<li><a name='jquery-validate' href='http://plugins.jquery.com/project/jqueryvalidate' target='_blank'>jQuery Validate</a></li>
</ul>
<p>					<a name="other-js-libraries" ></a></p>
<h5>Other Javascript Libraries</h5>
<ul>
<li><a name='js-modernizr' href='http://www.modernizr.com/' target='_blank'>Modernizr</a></li>
<li><a name='js-blockui' href='http://jquery.malsup.com/block/' target='_blank'>BlockUI</a></li>
<li><a name='js-accounting' href='http://josscrowcroft.github.com/accounting.js/' target='_blank'>Accounting.js</a></li>
<li><a name='js-currencymask' href='https://github.com/techarch/CurrencyMaskJS' target='_blank'>CurrencyMask JS</a></li>
<li><a name='jquery-maskedinput' href='http://digitalbush.com/projects/masked-input-plugin/' target='_blank'>Masked Input</a></li>
<li><a name='js-raphael' href='http://raphaeljs.com/' target='_blank'>Raphael JS</a></li>
<li><a name='js-graphael' href='http://g.raphaeljs.com/' target='_blank'>gRaphael JS</a></li>
<li><a name='js-storage' href='https://github.com/andris9/jStorage' target='_blank'>jStorage</a></li>
<li><a name='js-underscore' href='http://documentcloud.github.com/underscore/' target='_blank'>Underscore</a></li>
<li><a name='js-fixtures' href='http://jupiterjs.com/news/organizing-a-jquery-application#news/ajax-fixtures-plugin-for-jquery' target='_blank'>Ajax Fixtures</a></li>
</ul>
<p>					<a name="js-test-frameworks" ></a></p>
<h5>Javascript Test Frameworks</h5>
<ul>
<li><a name='js-jasmine' href='http://http://pivotal.github.com/jasmine/' target='_blank'>Jasmine, BDD for Javascript</a></li>
<li><a name='js-jasmine-species' href='http://rudylattae.github.com/jasmine-species/' target='_blank'>Jasmine Species, BDD Grammar Extensions (Given, When, Then, etc.)</a></li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a name='ko-part1' href='https://blog.monnet-usa.com/?p=354'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 1</a></li>
<li><a name='ko-part2' href='https://blog.monnet-usa.com/?p=368'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 2</a></li>
</ul>
<p>					<a name='kodemosrc'></a></p>
<h5>Full Source Of The Savings Goal Simulator (KnockoutJS Demo)</h5>
<p>The whole application is available on Github under <a href='https://github.com/techarch/savings-goal-simulator' target='_blank'>techarch / savings-goal-simulator</a>.</p>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
							If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
						</div>
<div class="blog-msm-ad2">
								<a href="http://www.myskillsmap.com/take-charge-of-your-skills-development"><br />
									<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
								</a>
						</div>
</p></div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=404</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 2</title>
		<link>https://blog.monnet-usa.com/?p=368</link>
					<comments>https://blog.monnet-usa.com/?p=368#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Tue, 18 Oct 2011 03:29:18 +0000</pubDate>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[rich web apps]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=368</guid>

					<description><![CDATA[Intro In Part 1 of &#8220;Creating Rich Interactive Web Apps With KnockOut.js&#8221;, I reviewed some of the key patterns you need to consider such as: MVC, Model View &#8211; ViewModel, Observer, Publish Subscribe, Value Model, Data Binding. In this second post, we will cover the following topics while creating a fun app: Architecting our application [&#8230;]]]></description>
										<content:encoded><![CDATA[<style>
						h3 {	text-decoration: underline; }</p>
<p>						h5 {margin-left:20px !important;}</p>
<p>						.details_table 
						{border: 1px solid #f0f0f0;
						border-spacing: 1px;
						background-color:white;
						margin-left: 40px;
						}</p>
<p>						.details_table tr
						{
						vertical-align: top;
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.details_table th
						{
						background-color:lightgray;
						}</p>
<p>						.details_table td
						{
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.download_panel
						{
						background-color: #EDD6AD; 
						color: #555555; 
						font-weight:bold;
						text-align:center;
						margin:0 50px 0 50px;
						padding:6px;
						}</p>
</style>
<h3>Intro</h3>
<p>In <a href="https://blog.monnet-usa.com/?p=354" target="_blank">Part 1 of &#8220;Creating Rich Interactive Web Apps With KnockOut.js&#8221;</a>, I reviewed some of the key patterns you need to consider such as: <a name='mvcp' href='http://c2.com/cgi/wiki?ModelViewController' target='_blank'>MVC</a>, <a name='mvvmp' href='http://en.wikipedia.org/wiki/Model_View_ViewModel' target='_blank'>Model View &#8211; ViewModel</a>, <a name='obp' href='http://c2.com/cgi/wiki?ObserverPattern' target='_blank'>Observer</a>, <a name='psp' href='http://c2.com/cgi/wiki?PublishSubscribeModel' target='_blank'>Publish Subscribe</a>, <a name='vmp' href='http://c2.com/cgi/wiki?ValueModel' target='_blank'>Value Model</a>, <a name='dbp' href='http://c2.com/cgi/wiki?DataBinding' target='_blank'>Data Binding</a>.</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/patterns.png" /></p>
<p>In this second post, we will cover the following topics while creating a fun app:</p>
<ul>
<li>Architecting our  application so it can easily be extended over time</li>
<li>Splitting the logic according to separations of concerns</li>
<li>Incorporating rudimentary elements of usability</li>
</ul>
<h3>For The Price Of N Cups of Coffee &#8230;</h3>
<p>To illustrate the various concepts, we&#8217;ll create a simulator application to figure out how we can tweak our coffee consumption habits to save a given amount of money over a period of time.
					</p>
<p>Note: You can try the app at: <a href='http://savings-goal-simulator.heroku.com/' target='_blank'>savings-goal-simulator.heroku.com</a> and inspect / play with it in Firebug. The full source is also available on Github under <a href='https://github.com/techarch/savings-goal-simulator' target='_blank'>techarch / savings-goal-simulator</a>.</p>
<h3>Building Our App Step-By-Step</h3>
<p>Here is an outline of the approach:</p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
<th>Area</th>
</tr>
<tr>
<td><a href='#todo1'>1</a></td>
<td>Create a Shell Application</td>
<td>Main app</td>
</tr>
<tr>
<td><a href='#todo2'>2</a></td>
<td>Organize our Application Code</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo3'>3</a></td>
<td>Create the Savings Goal View</td>
<td>View</td>
</tr>
<tr>
<td><a href='#todo4'>4</a></td>
<td>Create the Savings Goal ViewModel</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo5'>5</a></td>
<td>Create the Savings Goal View Mediator</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo6'>6</a></td>
<td>Link the Page and the View Mediator</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo7'>7</a></td>
<td>Apply Data Masking Business Rules</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo8'>8</a></td>
<td>Apply Custom Masking Rules</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo9'>9</a></td>
<td>Applying Formatting Rules</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo10'>10</a></td>
<td>Providing Visual Feedback Cues</td>
<td>View Mediator</td>
</tr>
</table>
<p>
					Thanks to <a href="http://susanpotter.net/" target='_blank'>Susan Potter</a>&#8216;s suggestion of tagging the source code on Github, you can download the source corresponding to the application as of the end of each &#8220;todo&#8221; step! You can find the list of tags <a href="https://github.com/techarch/savings-goal-simulator/tags" target='_blank'>here</a>.<br />
					</p>
<p>					<a name='todo1'></a></p>
<h5>1. Create a Shell Application</h5>
<p>Note: In this tutorial we will de-emphasize the server framework side and focus on browser considerations.<br />
					So let&#8217;s start:</p>
<ol>
<li>Create a root folder for our application named <b>savings-goal-simulator</b></li>
<li>Create a file named <b>index.html</b> for our main page</li>
<li>Create a folder for our Javascript files named <b>scripts</b></li>
<li>Create a sub-folder under <b>scripts</b> for our vendor Javascript libraries named <b>vendor</b></li>
<li>Add the basic markup for a page in <b>index.html</b></li>
</ol>
<p>					<a name='vendor-libraries'></a></p>
<p>Ok, now we&#8217;re ready to add our key <b>external Javascript libraries</b>.<br />
					Here is the basic minimum we&#8217;ll need with a quick rationale as of why they will help us:</p>
<table class='details_table'>
<tr>
<th>Library</th>
<th>Purpose / Rationale</th>
</tr>
<tr>
<td><a href='#js-modernizr'>Modernizr</a></td>
<td>Detects HTML 5 support and provide IE shims</td>
</tr>
<tr>
<td><a href='#jquery'>jQuery</a></td>
<td>Main foundation (do I need to say more :-) ?!)</td>
</tr>
<tr>
<td><a href='#jqueryui'>jQuery UI</a></td>
<td>Prefabricated UI super-elements like tabs, accordions, sliders, etc.</td>
</tr>
<tr>
<td><a href='#jquery-cookies'>jQuery Cookies</a></td>
<td>Easy management of cookies</td>
</tr>
<tr>
<td><a href='#jquery-hotkeys'>jQuery HotKeys</a></td>
<td>Handling of keyboard shortcuts</td>
</tr>
<tr>
<td><a href='#jquery-maskedinput'>jQuery Masked Input</a></td>
<td>Allow creation of custom input masks</td>
</tr>
<tr>
<td><a href='#jquery-validate'>jQuery Validate</a></td>
<td>Validation framework</td>
</tr>
<tr>
<td><a href='#js-accounting'>Accounting.js</a></td>
<td>Allow formatting currency amounts</td>
</tr>
<tr>
<td><a href='#js-currencymask'>CurrencyMaskJS</a></td>
<td>Allow masked input of currency amounts</td>
</tr>
<tr>
<td><a href='#jquery-jstorage'>jStorage</a></td>
<td>Wrapper for local storage APIs</td>
</tr>
</table>
<p>If we want to start authoring HTML 5 semantic pages, <a href="#js-modernizr">Modernizr</a> is a library which can facilitate detection of specific HTML5 and CSS3 features. But it also shines for Internet Explorer versions earlier than 9 by plugging in &#8220;<b>shims</b>&#8220;, i.e. fake HTML elements in the DOM, named after the new HTML5 missing elements, making it possible to use tags like<b>header</b>, <b>footer</b>, <b>section</b>, etc. and styling them too. </p>
<p>					<u>You</u> will need to create <u>your own</u> custom version of Modernizr based on the features you need. This will ensure the smallest most effective script for your situation. <br />
					For our app, I chose to only include the &#8220;HTML5 Shim/IEPP&#8221; and the &#8220;CSS classes&#8221; &#8211; see <a href="http://www.modernizr.com/download/#-iepp-cssclasses" target='_blank'>this download</a> configuration. I renamed the resulted file as <b>modernizr.custom.min.js</b> and placed it in the <b>scripts/vendor</b> folder.<br />
					So we&#8217;ll need to include the script for <a href="#js-modernizr">Modernizr</a> right at the beginning our our HEAD section.</p>
<pre class="brush: html">
&lt;head&gt;
	&lt;!-- Important: Modernizr must be the very first script in HEAD --&gt;
	&lt;script src="scripts/vendor/modernizr.custom.min.js"&gt;&lt;/script&gt; 
	
	&lt;!-- ... --&gt;
&lt;/head&gt;	
</pre>
<p>For performance reasons, we&#8217;ll use a Javascript loader (see available <a href='#javascript-loaders'>options</a> further on) to ensure the Javascript libraries we&#8217;ll need can be loaded asynchronously, in parallel, and not block the execution of our page load.<br />
					For this app, I chose <a href='#labjs'>LABjs</a> as it is specializes only on loading and is commonly used.<br />
					But note that you could use some of the conditional loading features of Modernizr, called <a href="http://yepnopejs.com/" target='_blank'>yepnope</a>.<br />
					I chose to keep things minimal for our app. ;-)
					</p>
<p>Starting from a basic HTML page, let&#8217;s add a script reference to <a href="#labjs"><b>lab.js</b></a> below our <b>modernizr</b> script, and then let&#8217;s define the order in which we want to load our libraries.<br />
					We&#8217;ll add a call to <b><u>wait()</u></b> if we want the execution of the actual code to be order-dependent:</p>
<pre class="brush: html">
&lt;head&gt;
	&lt;!-- Important: Modernizr must be the very first script in HEAD --&gt;
	&lt;script src="scripts/vendor/modernizr.custom.min.js"&gt;&lt;/script&gt; 
	&lt;script src="LAB.js"&gt;&lt;/script&gt; &lt;!-- Important: must be the very first script in HEAD --&gt;
	&lt;script&gt;
	$LAB
		.script("http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js").wait()
		.script("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js")
		.script("http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js")
		.script("scripts/vendor/knockout-1.2.1.debug.js").wait()
		.script("scripts/vendor/jquery.cookie.js")
		.script("scripts/vendor/jquery.blockUI.js")
		.script("scripts/vendor/jquery.hotkeys.js")
		.script("scripts/vendor/jquery.maskedinput-1.3.min.js")
		.script("scripts/vendor/jquery.validate.min.js")
		.script("scripts/vendor/accounting.min.js")
		.script("scripts/vendor/jstorage.min.js")
		.script("scripts/vendor/raphael-min.js").wait()
		.script("scripts/vendor/g.raphael-min.js").wait()
		.script("scripts/vendor/g.line-min.js").wait()
		.script("scripts/application.js").wait(function(){
			// When ALL scripts have been loaded AND executed:
			InitializeApplication();
		});
	&lt;/script&gt;
	
	&lt;!-- CSS and other HEAD-specific tags --&gt;
&lt;/head&gt;	
</pre>
<p>You will notice that I am assuming a specific directory structure for our locally hosted Javascript code</p>
<ul>
<li><b>scripts</b> is the root of all .js files</li>
<ul>
<li><b>Vendor</b> will host external vendor libraries not available on a CDN.<br />
								Having all external JS libraries in a dedicated folder will keep our directory structure clean.</li>
<li><b>ViewMediator</b> will include Javascript code <b>mediating</b> interactions between Views and ViewModels</li>
<li><b>ViewModel</b> will include our ViewModel-specific Javascript code</li>
<li><b>application.js</b> will be the main application .js file with an <b>InitializeApplication</b> function (called from our $LAB configuration)</li>
</ul>
</ul>
<p>At this point go ahead and create the same folder structure and download the needed Javascript libraries for the <b>Vendor</b> folder.<br />
					You can use the links in the <a href='#vendor-libraries'>External Javascript Libraries</a> table above.</p>
<p>And create the application.js file under the root of the scripts folder, and let&#8217;s provide a minimal implementation for now:</p>
<pre class="brush: javascript">
function InitializeApplication() {
	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication starting ...");
}
</pre>
<p>If you run the application you should see the informational message being displayed in the console.<br />
					And in Firefox Firebug, or on a WebKit browser you should see the parallel loading of the scripts.</p>
<p>For our CSS, let&#8217;s create a folder named <b><u>css</u></b> in which we&#8217;ll extract the <b>custom-theme</b> folder from our jQuery UI download.<br />
					We&#8217;ll also create an <b>application.css</b> file for our application-specific styles.
					</p>
<pre class="brush: html">
&lt;link href="css/custom-theme/jquery-ui-1.8.16.custom.css" rel="stylesheet" type="text/css"  /&gt;
&lt;link href="css/application.css" rel="stylesheet" type="text/css"  /&gt;
</pre>
<p>					<a name='todo2'></a></p>
<h5>2. Organize our Application Code</h5>
<p>Since our application will very modular and encompass many functions or classes,<br />
					we&#8217;ll establish a namespace to provide some structure and avoid function name clashes.<br />
					You can read more about how to implement namespaces in Javascript in the following two articles:</p>
<ul>
<li><a href='http://elegantcode.com/2011/01/26/basic-javascript-part-8-namespaces/' target='_blank'>Elegant Code &#8211; Namespaces<a></li>
<li><a href='http://stackoverflow.com/questions/881515/javascript-namespace-declaration' target='_blank'>StackOverflow &#8220;Javascript Namespace Declaration&#8221;</a></li>
</ul>
<p>For this app, we&#8217;ll use <b>sgs</b> (for <b>s</b>avings <b>g</b>oal <b>s</b>imulator) as a prefix,<br />
					followed by either <b>model</b> or <b>mediator</b> for ViewModel and ViewMediator respectively.<br />
					To keep our markup free of Javascript logic, we&#8217;ll organize the application code in the following folders:</p>
<ol>
<li>application.js will contain only logic to initialize / setup the views and viewmodels</li>
<li>ViewModel &#8211; this folder will contain several files:
<ul>
<li>sgs.model.common.js for reusable logic across all types of ViewModels</li>
<li>one file for the page-level view model &#8211; e.g. sgs.model.index.js</li>
<li>one file for each view-specific view model &#8211; e.g. sgs.model.savings-goal.js &#8211; </li>
</ul>
</li>
<li>ViewMediator &#8211; this folder will contain several files:
<ul>
<li>sgs.mediator.common.js for reusable logic across all view mediators</li>
<li>one file for the page-level view mediator &#8211; e.g. sgs.mediator.index.js</li>
<li>one file for each view-specific view mediator &#8211; e.g. sgs.mediator.savings-goal.js &#8211; </li>
</ul>
</li>
</ol>
<p>So at this point, create the folder structure described above as well as stub content for <b>sgs.model.common.js</b> and <b>sgs.model.common.js</b> (they can remain empty for now). And let&#8217;s update the LAB.js section to load these 2 files (before application.js):</p>
<pre class="brush: html">
&lt;head&gt;
	&lt;!-- ... --&gt;
	$LAB
		// ...
		.script("scripts/viewmodel/sgs.model.common.js")
		.script("scripts/viewmediator/sgs.mediator.common.js")
		.script("scripts/application.js").wait(function(){
			// When ALL scripts have been loaded AND executed:
			InitializeApplication();
		});
	&lt;/script&gt;
	
	&lt;!-- ... --&gt;
&lt;/head&gt;	
</pre>
<p>Here is a quick synopsis of the architecture for the first increment of our app:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-1.png" /></p>
<p>					<a name='todo3'></a></p>
<h5>3. Create the Savings Goal View</h5>
<p>Now that we have a minimal shell in <b>index.html</b>,<br />
					let&#8217;s add a section tag to represent our first panel / view: the <b>savings-goal-view</b>.<br />
					The view will let us enter a savings goal amout and a maximum number of months.</p>
<pre class="brush: html">
&lt;body&gt;
	&lt;section id='savings-goal-view'&gt;
	&lt;/section&gt;
&lt;/body&gt;
</pre>
<p>Now we can add the two input elements (<b>savings-goal-amount</b> and <b>savings-max-duration</b>).<br />
					And we&#8217;ll have a span to display the calculated (derived) <b>savings-target-per-month</b>. This is what the view will look like:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-1a.png" /></p>
<p><i><u>Important Note:</u> In this tutorial, <b>instead</b> of &#8220;<b>inlining</b>&#8221; the data-binding declaration with the view model inside the markup (like you will see in the KnockoutJS site or on any other simple tutorials), I am proposing a more &#8220;<b>unobtrusive</b>&#8221; approach consisting of <b>keeping the markup pure</b> and explicitly <b>defining data-bindings separately later</b> (in the <b>view mediator</b> which we&#8217;ll see soon in the next <a href='#todo4'>section</a>).</i></p>
<pre class="brush: html">
&lt;section id='savings-goal-view'&gt;
	&lt;label for="savings-goal-amount"&gt;Savings Goal Amount:&lt;/label&gt;
	&lt;input id="savings-goal-amount" /&gt;&lt;br/&gt;

	&lt;label for="savings-max-duration"&gt;Savings Max Duration (In Months):&lt;/label&gt;
	&lt;input id="savings-max-duration" /&gt;&lt;br/&gt;

	&lt;label for="savings-target-per-month"&gt;Savings Target Per Month:&lt;/label&gt;
	&lt;span id="savings-target-per-month" /&gt;&lt;br/&gt;
&lt;/section&gt;
</pre>
<p>At some point in the future, once the number of views increases beyond a couple, we&#8217;ll externalize our views as individual [jQuery] template files &#8211; but we&#8217;ll see the approach in detail later.</p>
<p><i><u>Note:</u> as we go along in the tutorial, I will not cover the CSS styling explicitly but you can always get the CSS when downloading the source based on the tag for a given step. Example: <a href="https://github.com/techarch/savings-goal-simulator/zipball/part2-todo-2" target='_blank'>tag: part2-todo-2.zip</a> (also available in tar.gz form). Look under for <b>css/application.css</b></i></p>
<p>					<a name='todo4'></a></p>
<h5>4. Create the Savings Goal ViewModel</h5>
<p>If you have not yet created the <b>ViewModels</b> folder under the <b>scripts</b> folder, do that now. And then create a file named: <b>sgs.model.savings-goal.js</b>.
					</p>
<p>Here is a diagram summarizing what we&#8217;re about to implement:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-todo4.png" /></p>
<p>As we indicated earlier, we&#8217;ll use namespaces to structure our code and avoid name collisions with other libraries.<br />
					There are various approaches for namespacing code in Javascript, some uses <a href="#ns-objectliteral">object literals</a>, and some use <a href="ns-function">functions</a> as containers for our functions. Elijah Manor has a great <a href="#ns-summary">summary</a> highlighting the pros and cons of the various approaches.</p>
<p>					For our needs and to make it easy to extend and edit our namespace we&#8217;ll use the <a href="#ns-objectliteral">object literals</a>.<br />
					To lazy initialize our namespace hierarchy let&#8217;s add the following snippet, which checks if each node in our namespace exists and creates it if it is not yet defined.</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.model.savingsgoal
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.model) == 'undefined') sgs.model = { }
if (typeof(sgs.model.savingsgoal) == 'undefined') sgs.model.savingsgoal = { }
</pre>
<p>Now we can create functions prefixed by our namespace such as for e.g. the function to initialize the view model and its two value models:</p>
<pre class="brush: javascript">
sgs.model.savingsgoal.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var viewModel = {
		savingsGoalAmount: ko.observable(pageSettings.defaultSavingsGoal || 0), // dollars
		savingsMaxDuration: ko.observable(6), // months
	};
	
	return viewModel;
}</pre>
<p>So our viewModel is basically an object literal (hash) where each property value is a <b>value model</b>,<br />
					implemented as <a href='http://knockoutjs.com/documentation/observables.html' target='_blank'>KnockoutJS observable</a>, essentially a function acting as an interceptor for a value. Everytime the function is acting as a setter, the interceptor notifies all observers (subscribers) of the value change.</p>
<p>Now let&#8217;s add a derived function (a.k.a. a dependent observable in KnockoutJS-speak) named <b>savingsTargetPerMonth</b>:
					</p>
<pre class="brush: javascript">
sgs.model.savingsgoal.initializeViewModel = function (pageSettings) {
	// We can use properties of the pageSettings as default values for any of our ValueModels
	// If pageSettings are not provided we'll initialize an empty object
	if (typeof(pageSettings) == 'undefined') var pageSettings = { }
	
	var viewModel = {
		savingsGoalAmount: ko.observable(pageSettings.defaultSavingsGoal || 0), // dollars
		savingsMaxDuration: ko.observable(6), // months
	};
	
	viewModel.savingsTargetPerMonth = ko.dependentObservable(function() {
		var result = 0;
		if (this.savingsMaxDuration() > 0) {
			result = this.savingsGoalAmount() / this.savingsMaxDuration();
		}
		return result;
	}, viewModel);

	return viewModel;
}
</pre>
<p>Note that <b>ko.dependentObservable</b> takes a function as a parameter as you would expect, but can also take a second optional parameter used to define the meaning of <b>this</b> inside the derived function. Typically we always pass the variable containing our viewModel.</p>
<p>Over time we can add more business logic to our <b>sgs.mode.savingsgoal</b> module.</p>
<p>					<a name='todo5'></a></p>
<h5>5. Create the Savings Goal View Mediator</h5>
<p>If you have not yet created the <b>ViewMediators</b> folder under the <b>scripts</b> folder, do that now. And then create a file named: <b>sgs.mediator.savings-goal.js</b>.<br />
					This is the module where we&#8217;ll place our data-binding logic as well as any code related to mediating access between the page, the savings goal view, and its view model.</p>
<p>Here is a diagram summarizing what we&#8217;re about to implement:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-todo5.png" /></p>
<p>Let&#8217;s define our namespace:</p>
<pre class="brush: javascript">
// Lazy initialize our namespace context: sgs.mediator.savingsgoal
if (typeof(sgs) == 'undefined') sgs = { }
if (typeof(sgs.mediator) == 'undefined') sgs.mediator = { }
if (typeof(sgs.mediator.savingsgoal) == 'undefined') sgs.mediator.savingsgoal = { }

if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.savingsgoal loading!");
</pre>
<p>Now as a convention, let&#8217;s create a new function for our mediator named <b>createViewMediator</b><br />
					which we will eventually invoke from the <b>InitializeApplication</b> method in <b>application.js</b>.<br />
					The createViewMediator function will have 3 responsibilities:</p>
<ol>
<li>Instantiate a view model for the savings goal view</li>
<li>Declare the data-binding between the HTML elements of the view and their corresponding value models in the view model</li>
<li>Ask KnockoutJS to make the bindings effective (they will be live right after that)</li>
<li>Save off the view model so we can access it from other parts of the app</li>
</ol>
<p>So let&#8217;s implement the first responsibility to instantiate a view model for the savings goal view (using the <b>initializeViewModel</b> function we just created in the savings goal view model module).</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// Create the view Savings Goal view-specific view model
	var viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);
}
</pre>
<p>Now let&#8217;s declare each of the 3 data-bindings we need:</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// Create the view Savings Goal view-specific view model
	var viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);
	
	// Declare the HTML element-level data bindings
	$("#savings-goal-amount").attr("data-bind","value: savingsGoalAmount");
	$("#savings-max-duration").attr("data-bind","value: savingsMaxDuration");
	$("#savings-target-per-month").attr("data-bind","text: savingsTargetPerMonth()");
}
</pre>
<p>Now we&#8217;ll ask KnockoutJS to &#8220;apply&#8221;, i.e. register / enable our bindings. </p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// Create the view Savings Goal view-specific view model
	var viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);
	
	// Declare the HTML element-level data bindings
	$("#savings-goal-amount").attr("data-bind","value: savingsGoalAmount");
	$("#savings-max-duration").attr("data-bind","value: savingsMaxDuration");
	$("#savings-target-per-month").attr("data-bind","text: savingsTargetPerMonth()");
	
	// Ask KnockoutJS to data-bind the view model to the view
	var viewNode = $('#savings-goal-view')[0];
	ko.applyBindings(viewModel, viewNode);
}
</pre>
<p>This is where KnockoutJS is performing some heavy lifting behind the covers such as:</p>
<ul>
<li>Setting observers on the actual HTML elements</li>
<li>Connecting these observers with the value models of the view model</li>
<li>Getting the initial value of each value model</li>
<li>Initializing each HTML element with that corresponding initial value</li>
</ul>
<p>To make it possible to store and retrieve our view model later we&#8217;ll leverage the jQuery data API.<br />
					So let&#8217;s create 2 functions in the savings goal mediator (since it is acting as an intermediate between the browser, page, view and the model:</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.getViewModel = function() {
	return $(document).data("sgs.model.savingsgoal.viewmodel");
}

sgs.mediator.savingsgoal.setViewModel = function(viewModel) {
	$(document).data("sgs.model.savingsgoal.viewmodel", viewModel);
}
</pre>
<p>Now we can use the setViewModel function inside createViewMediator to save off our freshly-created view model.</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// Create the view Savings Goal view-specific view model
	var viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);
	
	// Declare the HTML element-level data bindings
	$("#savings-goal-amount").attr("data-bind","value: savingsGoalAmount");
	$("#savings-max-duration").attr("data-bind","value: savingsMaxDuration");
	$("#savings-target-per-month").attr("data-bind","text: savingsTargetPerMonth()");
	
	// Ask KnockoutJS to data-bind the view model to the view
	var viewNode = $('#savings-goal-view')[0];
	ko.applyBindings(viewModel, viewNode);

	// Save the view model
	sgs.mediator.savingsgoal.setViewModel(viewModel);	

	if (typeof(console) != 'undefined' && console) console.info("sgs.mediator.savingsgoal ready!");
}
</pre>
<p>					<a name='todo6'></a></p>
<h5>6. Link the Page and the View Mediator</h5>
<p>Here is a diagram summarizing how we&#8217;ll be linking our parts:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-todo6.png" /></p>
<p>Ok now we&#8217;re at a point to start testing our first draft, we just need to add a call to the overall page <b>InitializeApplication</b> function (located in <b>scripts/application.js</b>) to our savings goal <b>createViewMediator</b> function like so:</p>
<pre class="brush: javascript">
function InitializeApplication() {
	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication starting ...");
		
	// Initialize our page-wide settings
	var pageSettings = { defaultSavingsGoal: 500 }
	
	// Create / launch our view mediator(s)
	sgs.mediator.savingsgoal.createViewMediator(pageSettings);

	if (typeof(console) != 'undefined' && console) 
		console.info("InitializeApplication done ...");	
}
</pre>
<p>So now you should be able to load your index.html page in Firefox with the Firebug console on and watch the debug statement and finally our view displays with our initial data as well as the initial derived data for the &#8220;Savings Target Per Month&#8221; when you tab out of the amount or max number of months input fields:
					</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-1b.png" /></p>
<p>					<a name='todo7'></a></p>
<h5>7. Apply Data Formatting / Masking Business Rules</h5>
<p>So far we have a nice simplistic example but if you build a solid app you will want to format and ensure our amounts are correct / valid / displayed according to conventional rules.<br />
					To my knowledge (having researched these types of libraries for a while), only library from <a href="http://www.pengoworks.com/" target="_blank">PengoWorks</a> has currency <b>masking</b> capabilities and will format the amount as you type it.<br />
					Since that library stopped being maintained in 2007, I started updating it (after checking with the original author, David Switzer) to make it work with current browsers). The resulting library is called <a href="#js-currencymask">CurrencyMask JS</a>.<br />
					So let&#8217;s download the <a href="https://github.com/techarch/CurrencyMaskJS" target="_blank">latest version</a> to our <b>./scripts/vendor</b> folder, and add a code snippet in our &lt;head&gt; LAB section:</p>
<pre class="brush: html">
&lt;head&gt;
	&lt;!-- ... --&gt;
	$LAB
		// ...
		.script("scripts/vendor/currency-mask-0.5.0-min.js").wait()
		.script("scripts/application.js").wait(function(){
			// When ALL scripts have been loaded AND executed:
			InitializeApplication();
		});
	&lt;/script&gt;
	
	&lt;!-- ... --&gt;
&lt;/head&gt;	
</pre>
<p>To apply masking to a field, you instantiate a Mask object with the format you want (e.g. &#8220;$#,###&#8221; for amounts up to $9,999 without decimals) and you attach it to the targetted HTML element like so:</p>
<pre class="brush: javascript">
    var savingsGoalAmountMask = new Mask("$#,###", "number");
    savingsGoalAmountMask.attach($("#savings-goal-amount")[0]);
</pre>
<p>Let&#8217;s add the mask instantiation snippet to the savings goal view model (at the end of the <b>initializeViewModel</b> function in <b>sgs.model.savings-goal.js</b>). Also note that we will need to perform the initialization of savingsGoalAmount based on pageSettings later on in the mediator &#8211; so here we&#8217;ll set the default value of savingsGoalAmountFormatted to an empty string:</p>
<pre class="brush: javascript">
sgs.model.savingsgoal.initializeViewModel = function (pageSettings) {
	// ...

	var viewModel = {
		savingsGoalAmountFormatted: ko.observable(""), 
		savingsGoalAmountMask: new Mask("$#,###", "number"),
		// ...
	};
	
	// ...
}	
</pre>
<p>And let&#8217;s add the &#8220;attach&#8221; snippet to the savings goal view mediator in the <b>createViewMediator</b> function in <b>sgs.mediator.savings-goal.js</b>, right after the bindings declarations:</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// ...

	// Declare the HTML element-level data bindings
	// ...
	
	// Apply masking to the savings goal amount input field
    viewModel.savingsGoalAmountMask.attach($("#savings-goal-amount")[0]);

	// ...
}	
</pre>
<p>And if we refresh the page and start typing 1500 in the amount it should format as we type along and prevent any other character input, ensuring the amount is valid.</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-2.png" /></p>
<p>But &#8230; we just introduced an issue (see the infamous NAN displayed in the Savings Target Per Month)!<br />
					Well, once formatted the savingsGoalAmount value model will now be a string containing currency and thousands delimiter characters.<br />
					So let&#8217;s recognize that semantic change by re-naming our <b>savingsGoalAmount</b> value model as <b>savingsGoalAmountFormatted</b> value model:</p>
<pre class="brush: javascript">
sgs.model.savingsgoal.initializeViewModel = function (pageSettings) {
	// ...
	
	var viewModel = {
		savingsGoalAmountFormatted: ko.observable(pageSettings.defaultSavingsGoal || 0), // dollars
		// ...
	};
</pre>
<p>Now what we need to re-create a new <b>savingsGoalAmount</b> value model, and make it act as a two-way adapter to convert back and forth between formatted and unformatted values.<br />
					KnockoutJS can help us with that, using a &#8220;<b>dependentObservable</b>&#8220;. KnockoutJS also allows a hash to be passed to ko.dependentObservable. That hash can include the following key-value pairs:
					</p>
<ul>
<li><b>owner</b> &#8211; will specify the value of <b>this</b></li>
<li><b>read</b> &#8211; a function which can perform some post-processing and ultimately return the value of the observable</li>
<li><b>write</b> &#8211; a function which can perform some pre-processing of a value and ultimately store it</li>
</ul>
<p>So here is a skeleton of what the savingsGoalAmount value model would look like as a dependentObservable:</p>
<pre class="brush: javascript">
viewModel.savingsGoalAmount = ko.dependentObservable({
	owner: viewModel,
	read: function () {
		// some post processing code
	},
	write: function (value) {
		// some pre processing code
	}
});	
</pre>
<p>Let&#8217;s tackle the <b>read</b> function first. It will need to:</p>
<ul>
<li>Get the current value model from <b>savingsGoalAmountFormatted</b></li>
<li>Ask the savingsGoalAmountMask for a stripped (unformatted) value</li>
<li>Return a valid float value</li>
</ul>
<p>Here is what the code looks like for the &#8220;read&#8221;:</p>
<pre class="brush: javascript">
	read: function () {
		// Get the current formatted value model 
		// Important Note: Even though we don't use the formatted_amt variable
		// in the rest of the function, we need to let KnockoutJS "know"
		// that this closure has a dependency on savingsGoalAmountFormatted
		// otherwise the closure will never be invoked on a read.
		var formatted_amt = this.savingsGoalAmountFormatted();

		// Unformat the value
		var amt = this.savingsGoalAmountMask.strippedValue;
		
		// Convert the result to a float
		if (amt.length == 0) { amt = 0 };
		return parseFloat(amt);
	},
</pre>
<p>Now let&#8217;s tackle the <b>write</b> function first. It will need to:</p>
<ul>
<li>Ask the savingsGoalAmountMask to format the value</li>
<li>Set the <b>savingsGoalAmountFormatted</b> to the formatted value</li>
<li>Return the passed value</li>
</ul>
<p>Here is what the code looks like for the &#8220;write&#8221;:</p>
<pre class="brush: javascript">
	write: function (value) {
		// Format the passed in value using the mask
		var formatted_value = this.savingsGoalAmountMask.updateFormattedValue(value);
		
		// Update the savingsGoalAmountFormatted value model
		this.savingsGoalAmountFormatted(formatted_value);
		return value;
	}
</pre>
<p>The complete and refactored savingsGoalAmount dependentObservable will now look like this:</p>
<pre class="brush: javascript">
viewModel.savingsGoalAmount = ko.dependentObservable({
	owner: viewModel,
	read: function () {
		// Get the current formatted value model
		var formatted_amt = this.savingsGoalAmountFormatted();
		
		// Unformat the value
		var amt = this.savingsGoalAmountMask.strippedValue;
		
		// Convert the result to a float
		if (amt.length == 0) { amt = 0 };
		return parseFloat(amt);
	},
	write: function (value) {
		// Format the passed in value using the mask
		var formatted_value = this.savingsGoalAmountMask.updateFormattedValue(value);
		
		// Update the savingsGoalAmountFormatted value model
		this.savingsGoalAmountFormatted(formatted_value);
		return value;
	}
});	
</pre>
<p>Now refreshing the index.html page should allow you to enter amounts and see the calculated value!</p>
<p>Here is a diagram summarizing how we restructured the various parts using the dependent observables and the mask:</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-todo7.png" /></p>
<p>I will leave the exercise for you dear reader to follow the same pattern for the &#8220;Savings Max Duration (In Months)&#8221; input field.<br />
					In that case the mask will be a little simpler since we need at most 2 digits.</p>
<p>					<a name='todo8'></a></p>
<h3>8. Apply Custom Masking Rules</h3>
<p>For custom masking needs, such as for example a phone number, social security id, special identifier,<br />
					I strongly recommend <a href="http://digitalbush.com/about/" target="_blank">Josh Bush</a>&#8216; <a href="#jquery-maskedinput">Masked Input Plugin</a>.
					</p>
<p>For dates I suggest using  Masked Input together with <a href="http://jqueryui.com/demos/datepicker/" target="_blank">jQuery Datepicker</a> since the calendar makes it easy to select a date but does <u>not</u> provide <b>masking</b> features.</p>
<p>					<a name='todo9'></a></p>
<h3>9. Applying Formatting Rules</h3>
<p>When using our simple view you might have noticed that the &#8220;Savings Target Per Month&#8221; may show some numbers with many decimals. This is because the <b>&lt;span&gt;</b> element is data-bound to the <b>savingsTargetPerMonth</b> dependentObservable which returns a <b>float</b>. So we have two options:</p>
<ul>
<li>Apply formatting to the float inside savingsTargetPerMonth</li>
<li>Or create another dependentObservable named savingsTargetPerMonthFormatted, in which we can apply the needed formatting logic. Then we would change the data binding for the <b>&lt;span&gt;</b>  to use our new value model.</li>
</ul>
<p>The cleanest approach is #2 since it also allows you in the future to build other dependentObservables on top of <b>savingsTargetPerMonth</b>. But if you don&#8217;t think you will need that ability then #1 will work and is very simple.
					</p>
<p>Approach 1 would require us to format the calculated value using the <b>formatMoney</b> function of <a href="#js-accounting">Accounting.js</a> like so:</p>
<pre class="brush: javascript">
		var result = this.savingsGoalAmount() / this.savingsMaxDuration();
		var formattedResult = accounting.formatMoney(result, "$", 2, ",", ".");  ;
		return formattedResult;
</pre>
<p>Approach 2 would require us to add a new dependentObservable named savingsTargetPerMonthFormatted in our savings goal view model:</p>
<pre class="brush: javascript">
sgs.model.savingsgoal.initializeViewModel = function (pageSettings) {
	// ...
	
	viewModel.savingsTargetPerMonthFormatted = ko.dependentObservable(function() {
		var result = 0;
		if (this.savingsMaxDuration() > 0) {
			result = this.savingsGoalAmount() / this.savingsMaxDuration();
		}
		var formattedResult = accounting.formatMoney(result, "$", 2, ",", ".");  ;
		return formattedResult;
	}, viewModel);
}
</pre>
<p>And we then need to update the data-binding code in the <b>createViewMediator</b> function of our mediator module:</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// ...
	
	$("#savings-target-per-month").attr("data-bind","text: savingsTargetPerMonthFormatted()");
	
	// ...
}
</pre>
<p>Let&#8217;s refresh the index.html page and now when we enter $500 and 7 months, the max per month updates to dollar formatted two-decimal amount: $71.43!</p>
<p>					<a name='todo10'></a></p>
<h3>10. Applying Visual Feedback Cues</h3>
<p>When web pages require a round-trip to the server, the user waits and then sees the whole page refreshing, but in rich interactive apps since processing happens often very fast without a page refresh, we need to provide visual cues when changes occur. For quick feedback logic (e.g. not requiring an Ajax call or processing longer than a second) I recommend using a jQuery UI <a href="http://jqueryui.com/demos/effect/" target="_blank">&#8220;effect&#8221;</a>, such a temporary highlight using a soft color, like so:</p>
<pre class="brush: javascript">
		$("#savings-target-per-month")
			.effect('highlight', { color: 'LightGreen' }, 3000); // for 3 seconds
</pre>
<p>Logically the code belongs to the mediator, so let&#8217;s <b>subscribe</b> to the <b>savingsTargetPerMonthFormatted</b> value model changes<br />
					inside our <b>createViewMediator</b> function.</p>
<pre class="brush: javascript">
sgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {
	// ...

	// Subscribe to interesting value model changes
	viewModel.savingsTargetPerMonthFormatted.subscribe(function() {
		$("#savings-target-per-month")
			.effect('highlight', { color: 'LightGreen' }, 3000); // for 3 seconds
	});
	
	// ...
}
</pre>
<p>Let&#8217;s refresh index.html, and whenever we see the xxx recalculate, the light green highlight of the result should fade in and out during our 3-second timeframe!</p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/savings-goal-simulator-part1-3.png" /></p>
<hr>
<h5>Overall Recap</h5>
<p>So at this point we have built a reasonably solid foundation for our app even though it contains only one view. The architectural steps we took to decouple view, viewmodel, view mediator and the page will yield some benefits once we add continue adding features to our app (in part 3).<br />
					So here is a quick recap of the steps we followed:</p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
<th>Area (Module)</th>
</tr>
<tr>
<td><a href='#todo1'>1</a></td>
<td>Create a Shell Application</td>
<td>Main app</td>
</tr>
<tr>
<td><a href='#todo2'>2</a></td>
<td>Organize your Application Code</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo3'>3</a></td>
<td>Break down each independent panel into Views</td>
<td>View</td>
</tr>
<tr>
<td><a href='#todo4'>4</a></td>
<td>Create a ViewModel for each View</td>
<td>View Model</td>
</tr>
<tr>
<td><a href='#todo5'>5</a></td>
<td>Create a View Mediator for each View</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo6'>6</a></td>
<td>Link the Page and the View Mediator(s)</td>
<td>Main App</td>
</tr>
<tr>
<td><a href='#todo7'>7</a></td>
<td>Apply Data Formatting / Masking Business Rules</td>
<td>View</td>
</tr>
<tr>
<td><a href='#todo8'>8</a></td>
<td>Apply Custom Masking Rules</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo9'>9</a></td>
<td>Applying Formatting Rules</td>
<td>View Mediator</td>
</tr>
<tr>
<td><a href='#todo10'>10</a></td>
<td>Providing Visual Feedback Cues</td>
<td>View Mediator</td>
</tr>
</table>
<p>					<a name='sowhat'></a></p>
<h3>So What?</h3>
<p>Many KnockoutJS tutorials focus on giving you the basics to run simple scenarios. My approach here although more &#8220;<b>architected</b>&#8221; is geared at building rich interactive apps made of multiple panels/views with solid interactions. </p>
<p>The modularization of our code base will also lend itself better to unit testing and even BDD testing using Javascript test frameworks like <a name='js-jasmine' href='http://http://pivotal.github.com/jasmine/' target='_blank'>Jasmine</a> and <a name='js-jasmine-species' href='http://rudylattae.github.com/jasmine-species/' target='_blank'>Jasmine-Species</a>. They will allow us to write tests against our view models and to a certain degree some of the various Javascript modules.</p>
<p>We have focused on a one-view increment for the app but in Part 3 we will cover the following topics:</p>
<ul>
<li>Adding more views, viewmodels and mediators to our basic app</li>
<li>Sharing data across views and mediators</li>
<li>Implementing masking and formatting</li>
<li>Incorporating rudimentary elements of usability</li>
<li>&#8230; and more!</li>
</ul>
<p>So stay tuned!</p>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>Patterns</h5>
<ul>
<li><a name='mvvmp' href='http://en.wikipedia.org/wiki/Model_View_ViewModel'>Model View &#8211; ViewModel Pattern</a></li>
<li><a name='mvcp' href='http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html'>MVC Xerox Parc 1978-79</a></li>
<li><a name='mvcp' href='http://c2.com/cgi/wiki?ModelViewController'>MVC Pattern</a></li>
<li><a name='obp' href='http://c2.com/cgi/wiki?ObserverPattern'>Observer Pattern</a></li>
<li><a name='psp' href='http://c2.com/cgi/wiki?PublishSubscribeModel'>Publish Subscribe Pattern</a></li>
<li><a name='vmp' href='http://c2.com/cgi/wiki?ValueModel'>Value Model Pattern</a></li>
<li><a name='dbp' href='http://c2.com/cgi/wiki?DataBinding'>Data Binding Pattern</a></li>
<li><a name='ns-summary' href='http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/'>Summary of Namespacing Approaches (by Elijah Manor)</a></li>
<li><a name='ns-objectliteral' href='http://stackoverflow.com/questions/881515/javascript-namespace-declaration/881556#881556'>Namespacing using Object Literals</a></li>
<li><a name='ns-function' href='http://stackoverflow.com/questions/881515/javascript-namespace-declaration/881611#881611'>Namespacing using Functions</a></li>
</ul>
<h5>Frameworks And Blogs</h5>
<ul>
<li><a name='ko' href='http://knockoutjs.com/'>KnockoutJS</a></li>
<li><a name='lko' href='http://learn.knockoutjs.com/'>Learn KnockoutJS (Interactive Tutorial / Playground)</a></li>
<li><a name='jq' href='http://jquery.com/'>jQuery</a></li>
<li><a name='jqui' href='http://jqueryui.com/'>jQuery UI</a></li>
<li><a name='jqt' href='http://api.jquery.com/jQuery.template/'>jQuery Template</a></li>
<li><a name='jqtapi' href='http://api.jquery.com/jQuery.template/'>jQuery Template API</a></li>
<li><a name='ss' href='http://blog.stevensanderson.com/'>Knock Me Out (Steve Sanderson&#8217;s Blog)</a></li>
<li><a name='kmo' href='http://www.knockmeout.net/'>Knock Me Out (Ryan Niemeyer&#8217;s Blog)</a></li>
<li><a name='pflsjaa' href='http://addyosmani.com/blog/patterns-for-large-scale-javascript-application-architecture/'>Patterns For Large-Scale Javascript Architecture (Addy Osmani)</a></li>
</ul>
<p>					<a name="javascript-loaders" ></a></p>
<h5>Javascript Loaders</h5>
<ul>
<li><a name='headjs' href='http://headjs.com/' target='_blank'>HeadJS</a></li>
<li><a name='labjs' href='http://labjs.com/' target='_blank'>LABjs</a></li>
<li><a name='lazyload' href='https://github.com/rgrove/lazyload' target='_blank'>LazyLoad</a></li>
<li><a name='jquery-cookie' href='https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js' target='_blank'>jQuery Cookie</a></li>
</ul>
<p>					<a name="jquery-plugins" ></a></p>
<h5>jQuery Plugins</h5>
<ul>
<li><a name='jquery-blockui' href='http://jquery.malsup.com/block/' target='_blank'>jQuery BlockUI</a></li>
<li><a name='jquery-cookie' href='https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js' target='_blank'>jQuery Cookie</a></li>
<li><a name='jquery-datatables' href='http://datatables.net/' target='_blank'>jQuery DataTables</a></li>
<li><a name='jquery-hotkeys' href='https://github.com/tzuryby/jquery.hotkeys' target='_blank'>jQuery HotKeys</a></li>
<li><a name='jquery-tree' href='http://www.jstree.com/' target='_blank'>jQuery jsTree</a></li>
<li><a name='jquery-validate' href='http://plugins.jquery.com/project/jqueryvalidate' target='_blank'>jQuery Validate</a></li>
</ul>
<p>					<a name="other-js-libraries" ></a></p>
<h5>Other Javascript Libraries</h5>
<ul>
<li><a name='js-modernizr' href='http://www.modernizr.com/' target='_blank'>Modernizr</a></li>
<li><a name='js-blockui' href='http://jquery.malsup.com/block/' target='_blank'>BlockUI</a></li>
<li><a name='js-accounting' href='http://josscrowcroft.github.com/accounting.js/' target='_blank'>Accounting.js</a></li>
<li><a name='js-currencymask' href='https://github.com/techarch/CurrencyMaskJS' target='_blank'>CurrencyMask JS</a></li>
<li><a name='jquery-maskedinput' href='http://digitalbush.com/projects/masked-input-plugin/' target='_blank'>Masked Input</a></li>
<li><a name='js-raphael' href='http://raphaeljs.com/' target='_blank'>Raphael JS</a></li>
<li><a name='js-graphael' href='http://g.raphaeljs.com/' target='_blank'>gRaphael JS</a></li>
<li><a name='js-storage' href='https://github.com/andris9/jStorage' target='_blank'>jStorage</a></li>
<li><a name='js-underscore' href='http://documentcloud.github.com/underscore/' target='_blank'>Underscore</a></li>
<li><a name='js-fixtures' href='http://jupiterjs.com/news/organizing-a-jquery-application#news/ajax-fixtures-plugin-for-jquery' target='_blank'>Ajax Fixtures</a></li>
</ul>
<p>					<a name="js-test-frameworks" ></a></p>
<h5>Javascript Test Frameworks</h5>
<ul>
<li><a name='js-jasmine' href='http://http://pivotal.github.com/jasmine/' target='_blank'>Jasmine, BDD for Javascript</a></li>
<li><a name='js-jasmine-species' href='http://rudylattae.github.com/jasmine-species/' target='_blank'>Jasmine Species, BDD Grammar Extensions (Given, When, Then, etc.)</a></li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a name='ko-part1' href='https://blog.monnet-usa.com/?p=354'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 1</a></li>
<li><a name='ko-part3' href='https://blog.monnet-usa.com/?p=404'>Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 3</a></li>
</ul>
<p>					<a name='kodemosrc'></a></p>
<h5>Full Source Of The Savings Goal Simulator (KnockoutJS Demo)</h5>
<p>The whole application is available on Github under <a href='https://github.com/techarch/savings-goal-simulator' target='_blank'>techarch / savings-goal-simulator</a>.</p>
<p>					<a name='credits'></a></p>
<h5>Credits</h5>
<p>Special thanks for <a href="http://blog.logeek.fr/" target='_blank'>Thibaut Barrère</a> and <a href="http://susanpotter.net/" target='_blank'>Susan Potter</a> for their feedback while I was working on drafts for this tutorial! :-)</p>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
							If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
						</div>
<div class="blog-msm-ad2">
								<a href="http://www.myskillsmap.com/take-charge-of-your-skills-development"><br />
									<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
								</a>
						</div>
</p></div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=368</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>Creating Rich Interactive Web Apps With KnockoutJS &#8211; Part 1</title>
		<link>https://blog.monnet-usa.com/?p=354</link>
					<comments>https://blog.monnet-usa.com/?p=354#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Sat, 17 Sep 2011 21:35:28 +0000</pubDate>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=354</guid>

					<description><![CDATA[Intro With the advent of online games, social apps, Flash/AIR apps, and rich instant-feedback sites like Google Search and GMail, consumers are demanding more and more interactivity. While interacting with your app customer now expect: Browser-side processing (calculation, business rules, &#8230;) Instant validation Instant visual feedback: animation/effect while making changes (add/remove/update) Dynamic clues on what [&#8230;]]]></description>
										<content:encoded><![CDATA[<style>
						h3 {	text-decoration: underline; }</p>
<p>						h5 {margin-left:20px !important;}</p>
<p>						.details_table 
						{border: 1px solid #f0f0f0;
						border-spacing: 1px;
						background-color:white;
						margin-left: 40px;
						}</p>
<p>						.details_table tr
						{
						vertical-align: top;
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.details_table th
						{
						background-color:lightgray;
						}</p>
<p>						.details_table td
						{
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.download_panel
						{
						background-color: #EDD6AD; 
						color: #555555; 
						font-weight:bold;
						text-align:center;
						margin:0 50px 0 50px;
						padding:6px;
						}</p>
</style>
<h3>Intro</h3>
<p>
					With the advent of online games, social apps, Flash/AIR apps, and rich instant-feedback sites<br />
					like Google Search and GMail, consumers are demanding more and more interactivity.
					</p>
<p>While interacting with your app customer now expect:</p>
<ul>
<li>Browser-side processing (calculation, business rules, &#8230;)</li>
<li>Instant validation </li>
<li>Instant visual feedback: animation/effect while making changes (add/remove/update)</li>
<li>Dynamic clues on what to do next</li>
<li>More same / on page functionality (without the need to refresh or navigate to other pages)</li>
</ul>
<p>For a while adding a sprinkling of AJAX and localized visual refresh using jQuery UI was sufficient.<br />
					But richer application interactions introduce more elaborate technical approaches: <br />
					<img decoding="async" src="./wp-content/media/knockoutjs/browser-side-app-stack.png" />
					</p>
<ul>
<li>Present more related data at the same time</li>
<li>Leverage graphs and other data visualization techniques</li>
<li>Offer more on-page functionality</li>
<li>Allow interactions with one panel to cause updates on other panels</li>
<li>Support asynchronous back-end interactions</li>
</ul>
<h3>Extending the <a href="#mvcp">Model View Controller Pattern</a></h3>
<p>
					Here is a reminder of what typically happens in a traditional <a href="#mvcp">MVC</a> web app (e.g. Ruby On Rails, Ruby Camping, ASP.NET MVC, Cake PHP, Django Python, etc.):
					</p>
<ul>
<li>The routing engine identifies the appropriate controller</li>
<li>The controller retrieves the model</li>
<li>The view engine renders the view</li>
<li>The view contains HTML, CSS, and Javascript code</li>
<li>Rich browser-side applications typically have event handlers to allow page-level interactions to<br />
							handle validation, hide/show elements, perform some processing / calculations, executebusiness rules, invoke AJAX services, update content</li>
</ul>
<p>
					Note that the last bullet represents quite a bit of logic (possibly in the 500 to several thousand lines of Javascript code).<br />
					The logic gets even more complex once you have multiple panels and sets of model elements.<br />
					If your AJAX services return complex objects you also need to keep track of these objects,<br />
					their binding to panel elements/controls, and their inter-dependencies / impact on each other when a change occurs.</br></p>
<p>					<img decoding="async" src="./wp-content/media/knockoutjs/web-app-architecture.png" /></p>
<p><b>Key take-away:</b><br />
					We need to organize our browser-side code (markup, CSS, and JS) according to their <b>concern</b>, i.e. model representation, business rules, display, user interaction, event handling, server interaction, etc..</p>
<p>This is where the notion of <a href="#mvvmp">ViewModel</a> and <a href="#obp">Observables</a> come in to help us out.<br />
					Let&#8217;s break things down:
					</p>
<p>					<a id="breakdown"></a></p>
<ol>
<li>The ViewModel is a specialized <b>browser-side</b> Javascript <b><u>m</u>odel</b> representing a <b>group of data elements</b> a given page or panel (View) will display or facilitate interaction with.<br />
						<img decoding="async" src="./wp-content/media/knockoutjs/viewmodel-data-elements.png" /><br />
						<u>Benefits:</u></p>
<ul>
<li><b>Partitioning</b>: each page / page can have its own clean model</li>
<li><b>Testability</b>: the View and ViewModel can be tested independently from the server logic</li>
<li><b>Modularity</b>: ViewModels code can be namespaced and contained in their own <b>.js</b> file</li>
</ul>
<p>
						</li>
<li>Each attribute of a ViewModel will be mapped to an <a href="#obp">Observable</a> so that any value change can be <b>broadcasted</b> (a.k.a. &#8220;published&#8221; in the <a href="#psp">publish/subscribe</a> terminology) to any interested <b>subscriber</b>. (So essentially a ViewModel attribute is what is called a <a href="#vmp">Value Model</a>)<br />
						<img decoding="async" src="./wp-content/media/knockoutjs/viewmodel-observables.png" /><br />
						<u>Benefits:</u></p>
<ul>
<li><b>Fast UI</b>: derived values or content can be produced on-the-fly based on observed attributes</li>
<li><b>Increased responsiveness</b>: asynchronous server interactions can be triggered in the background and cause ViewModels to be updated</li>
</ul>
<p>
						</li>
<li>The scenario where a UI element <b>subscribe</b> to a ViewModel attribute (Value Model) is known as &#8220;<a href="#dbp">Data-Binding</a>&#8220;.<br />
						This allows a clean separation between logic related to the ViewModel (calculations, derivations, retrieval, server interaction) and UI-specific presentation logic.<br />
						<img decoding="async" src="./wp-content/media/knockoutjs/viewmodel-data-binding.png" /><br />
						<u>Benefits:</u></p>
<ul>
<li><b>Synchronization</b>: HTML elements and ViewModel attributes are kept in synch</li>
<li><b>Instant visual feedback</b>: elements on the page can update visually as you interact / update data</li>
</ul>
<p>
						</li>
</ol>
<h3>Introducing KnockOutJS</h3>
<p>KnockOutJS is a Javascript framework created by <a href="#ss">Steve Sanderson</a> to provide support for <a href="#mvvmp">ViewModel</a>, <a href="#obp">Observable</a>, and <a href="#dbp">Data-Binding</a> using jQuery.<br />
					For more details, check out the <a href="#ko">KnockOutJS</a> site as well as the <a href="#lko">Learning Playground</a>.<br />
					Let&#8217;s dig into the basic infrastructure provided by KnockOutJS and then we&#8217;ll build up to more complex scenarios.
					</p>
<p>					<a id="ko-basics"></a></p>
<h4>Basics</h4>
<ol>
<li>In <a href="">KnockoutJS</a>, a ViewModel is defined as a Javascript Object Literal. Value Models are defined using <b>ko.observable()</b> and an initial value as follows:
<pre class="brush: javascript">
var viewModel = {
	savingGoalAmount: ko.observable(500), // dollars
	// ... more attributes ...
};
</pre>
<p>							The example ViewModel has one attribute: savingGoalAmount, with an initial value of 500.<br />
							
						</li>
<li>You can programmatically <b>&#8220;subscribe&#8221;</b> to changes in a ViewModel attribute (a Value Model) like this:
<pre class="brush: javascript">
// Set up the ViewModel
var viewModel = {
	savingGoalAmount: ko.observable(500), // dollars
	// ... more attributes ...
};

viewModel.savingGoalAmount.subscribe(function(newValue) {
	// Show the updated value on the FireBug's console
	console.info("savingGoalAmount is now " + newValue);
});

// Get KnockoutJS to apply bindings / subscriptions
ko.applyBindings(viewModel);	

// Test by changing the amount
viewModel.savingGoalAmount(600); // Should display in the console
</pre>
<p>							The <b>subscribe</b> function takes a callback function it will invoke upon any change on the value of the savingGoalAmount Value Model.<br />
							The <b>ko.applyBindings</b> function tells KnockoutJS to start the dependency tracking. From that point on all subscribers will be notified of any changes.</p>
</li>
<li>KnockoutJS makes it easy to setup <a href="#dbp">data binding</a> between any HTML element (e.g. INPUT) and a ViewModel attribute (Value Model) using the <a href="#kodb">data-bind</a> syntax and the <b>value:</b> keyword
<pre class="brush: html" >
<input id="saving-goal-amount" 
			size="5" pattern="[0-9]{5}" min="0" max="99999"
			data-bind="value: savingGoalAmount" />	
</pre>
<p>						KnockoutJS uses the <b>data-bind</b> attribute to let us specify the type of binding needed.<br />
						In this example we&#8217;re binding the <b>value</b> of the INPUT element to the savingGoalAmount Value Model.<br />
						We&#8217;ll see later on that there are other types of data-binding such as specific attributes, visibility, styling, etc. although you can see the full reference in the <a href="http://knockoutjs.com/documentation/visible-binding.html" target="_blank">documentation</a>.</p>
<p>						<img decoding="async" src="./wp-content/media/knockoutjs/basic-data-binding-example.png" /><br />
						Note that the <a href="#kodb">data-bind</a> syntax is just &#8220;syntactic sugar&#8221; for use in our markup. If you prefer a clean separation between markup and Javascript, you can declare your data-bindings like so:</p>
<pre class="brush: javascript">
$("#saving-goal-amount")
	.attr("data-bind","value: savingGoalAmount");
</pre>
<p>						You just need to make sure these declarations are performed <b><u>before</u></b> you get KnockoutJS to apply the bindings (using <b>ko.applyBindings</b>).
						</li>
</ol>
<p>You can play and run the examples above on this <a href="http://jsfiddle.net/techarch/z5Ptd/6/" target="_blank">jsFiddle.net</a> page.</p>
<p>
					<a id="ko-building-up"></a></p>
<h4>Building Up</h4>
<p>Now that we have a basic understanding of KnockoutJS, let&#8217;s add a few more building blocks:</p>
<ol>
<li>If a ViewModel attribute needs to store an array, KnockoutJS provides a specialized type of <a href="#obp">Observable</a> called an <b>ko.observableArray</b>:
<pre class="brush: javascript">
var viewModel = {
	savingGoalObjectives: ko.observableArray([ 'Discretionary', 'Expensive Purchase', 'Investment']),
	// ... more attributes ...
};
</pre>
<p>						Adding / removing items in the array will cause KnockoutJS to trigger an update to all observers of this Value Model.<br />
						
						</li>
<li>In addition to attributes (Value Models), ViewModels can expose &#8220;<b>behaviors</b>&#8221; such as:
<ul>
<li>Derived attributes, resulting from a calculation, or a business rule.<br />
									KnockoutJS refers to them as <a href="http://knockoutjs.com/documentation/dependentObservables.html" target="_blank">dependentObservables</a>:</p>
<pre class="brush: javascript">
var viewModel = {
	savingGoalAmount: ko.observable(500), // dollars
	savingMaxDuration: ko.observable(6), // dollars
	// ... more attributes ...
};

// Derived data
viewModel.savingTargetPerMonth = ko.dependentObservable(function() {
	return this.savingGoalAmount() / this.savingMaxDuration();
}, viewModel)
</pre>
<p>									Whenever either savingGoalAmount or savingMaxDuration change, the derived savingTargetPerMonth function will be re-evaluated.<br />
									If savingTargetPerMonth is data-bound to the UI, the corresponding element will redisplay.<br />
									Note that you can create dependentObservable functions on top of dependent observables or plain observables!<br />
<img decoding="async" src="./wp-content/media/knockoutjs/advanced-derived-attribute.png" />
									</li>
<li>Formatted version of the data
<pre class="brush: javascript">
var viewModel = {
	savingGoalAmount: ko.observable(500), // dollars
	// ... more attributes ...
};

// Derived formatted display data
viewModel.savingGoalAmountAsCurrency = ko.dependentObservable(function() {
	return accounting.formatMoney(this.savingGoalAmount(), 
			"$", 2, ",", ".");  ;
}, viewModel)
</pre>
<p>Above is an example using the <a href="http://josscrowcroft.github.com/accounting.js/" target="_blank">Accounting.js</a> library to format our savingGoalAmount Value Model within our dependent observable so that we can display a nicely formatted currency representation on the UI.</p>
</li>
<li>Add / remove logic on arrays
<pre class="brush: javascript">
var viewModel = {
	myItems: ko.observableArray(),
	// ... more attributes ...
};

// Add / remove behaviors 
viewModel.addItem = function (newItem) {
	var valid = validateItem(newItem); // custom logic
	if (valid) {
		this.myItems.push(newItem);
	}
}
</pre>
<p>										In this example, <b>addItem</b> is a custom behavior attached to the ViewModel which can be invoked to add new valid items.
									</li>
<li>Any other business logic related to an overall ViewModel
<pre class="brush: javascript">
var viewModel = {
	savingGoalAmount: ko.observable(500), // dollars
	// ... more attributes ...
};

viewModel.reset = function() {
	this.savingGoalAmount(500);
}
</pre>
</li>
</ul>
</li>
<li>To allow other parts of our browser-side logic to access our ViewModels, we need to have a way to access them.<br />
						We can save ViewModels in the DOM, either at the document level or at a panel level using the <b>jQuery.data</b> API:</p>
<pre class="brush: javascript">
var viewModel1 = { }
var viewModel2 = { }

ko.applyBindings(viewModel1);	
ko.applyBindings(viewModel2);	

$(document).data("MyDocumentViewModel", viewModel1);
$("#my-panel").data("MyPanelViewModel", viewModel2);
</pre>
<p>						This allows us to access a specific ViewModel later, outside data-binding logic (e.g. in an event handler) like so:</p>
<pre class="brush: javascript">
var viewModel1 = $(document).data("MyDocumentViewModel");
var viewModel2 = $("#my-panel").data("MyPanelViewModel");
</pre>
<p>							To keep our code organized we&#8217;ll want to create accessor functions such as for example:</p>
<pre class="brush: javascript">
	MyApp.Model.GetMyDocumentViewModel = function() {
		return $(document).data("MyDocumentViewModel");
	}

	MyApp.Model.SetMyDocumentViewModel = function(viewModel) {
		$(document).data("MyDocumentViewModel", viewModel);
	}
</pre>
<p>							So that we can just access our ViewModel from other modules:</p>
<pre class="brush: javascript">
// Initialization
var viewModel = { }
ko.applyBindings(viewModel);	
MyApp.Model.SetMyDocumentViewModel(viewModel);

// Later on in a different module:
MyApp.Model.GetMyDocumentViewModel()
	.savingGoalAmount.subscribe(myCallBackFunction);

</pre>
<p>
						</li>
<li>The attributes (<b>Value Models</b>) of the ViewModel can be updated using data returned by an AJAX call to a controller
<pre class="brush: javascript">
$.getJSON('ajax/myapi.json', 
			parms, 
			function(data) {
	// Assumption: we have saved the original viewModel 
	var viewModel = $(document).data("MyViewModel");
	viewModel.savingGoalAmount(data.amount);
});
</pre>
</li>
<li>The ViewModel can also aggregate a <b>subset of attributes</b> from one or even several <b>server-side</b> [MVC] <b><u>M</u>odels</b>
</li>
<li>Arbitrary Javascript functions can also subscribe to Value Model changes:
<pre class="brush: javascript">
// Set up the ViewModel
var viewModel = {
	savingGoalAmount: ko.observable(500), // dollars
	// ... more attributes ...
};

function GraphSavingScenario(newValue) {
	// some graphing logic
}

viewModel.savingGoalAmount.subscribe(GraphSavingScenario);
</pre>
<p>										<img decoding="async" src="./wp-content/media/knockoutjs/advanced-callback-function.png" />
						</li>
</ol>
<p>					<a name='sowhat'></a></p>
<h3>So What?</h3>
<p>KnockoutJS can help organize browser-side logic by facilitating the creation of panels (<b>Views</b>),<br />
					each logically data-bound to <a href="#mvvmp">ViewModels</a> built on top of a <u>local</u> <a href="#psp">publish/subscribe</a> mechanism using <a href="#obp">Observables</a>.<br />
					Data-binding, combined with derived data / behaviors, and AJAX will boost the interactivity level of the application.
					</p>
<p>Part 2 of the series on &#8220;Creating Rich Interactive Web Apps&#8221; will be a tutorial on how to build a moderate complexity application with KnockoutJS.<br />
					We will cover the following topics:</p>
<ul>
<li>Enabling / disabling rules</li>
<li>Condition display</li>
<li>Leveraging jQuery templates</li>
<li>Extracting views into templates</li>
<li>&#8230; and more!</li>
</ul>
<p>So stay tuned!</p>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>Patterns</h5>
<ul>
<li><a name='mvvmp' href='http://en.wikipedia.org/wiki/Model_View_ViewModel'>Model View &#8211; ViewModel Pattern</a></li>
<li><a name='mvcp' href='http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html'>MVC Xerox Parc 1978-79</a></li>
<li><a name='mvcp' href='http://c2.com/cgi/wiki?ModelViewController'>MVC Pattern</a></li>
<li><a name='obp' href='http://c2.com/cgi/wiki?ObserverPattern'>Observer Pattern</a></li>
<li><a name='psp' href='http://c2.com/cgi/wiki?PublishSubscribeModel'>Publish Subscribe Pattern</a></li>
<li><a name='vmp' href='http://c2.com/cgi/wiki?ValueModel'>Value Model Pattern</a></li>
<li><a name='dbp' href='http://c2.com/cgi/wiki?DataBinding'>Data Binding Pattern</a></li>
</ul>
<h5>Frameworks And Blogs</h5>
<ul>
<li><a name='ko' href='http://knockoutjs.com/'>KnockoutJS</a></li>
<li><a name='lko' href='http://learn.knockoutjs.com/'>Learn KnockoutJS (Interactive Tutorial / Playground)</a></li>
<li><a name='jq' href='http://jquery.com/'>jQuery</a></li>
<li><a name='jqui' href='http://jqueryui.com/'>jQuery UI</a></li>
<li><a name='jqt' href='http://api.jquery.com/jQuery.template/'>jQuery Template</a></li>
<li><a name='jqtapi' href='http://api.jquery.com/jQuery.template/'>jQuery Template API</a></li>
<li><a name='ss' href='http://blog.stevensanderson.com/'>Knock Me Out (Steve Sanderson&#8217;s Blog)</a></li>
<li><a name='kmo' href='http://www.knockmeout.net/'>Knock Me Out (Ryan Niemeyer&#8217;s Blog)</a></li>
<li><a name='pflsjaa' href='http://addyosmani.com/blog/patterns-for-large-scale-javascript-application-architecture/'>Patterns For Large-Scale Javascript Architecture (Addy Osmani)</a></li>
</ul>
<p><!--					
					

<h5>My Other Related Posts:</h5>


					

<ul name="myotherrelatedposts">
						

<li><a name='caoauth' href='https://blog.monnet-usa.com/?p=XXX'>Easily Transform Your Ruby Camping App Into An OAuth Provider</a></li>


					</ul>


--><br />
					<a name='ko-fiddle'></a></p>
<h5>Source Of The KnockoutJS Examples</h5>
<p>You can find the examples on jsFiddle.net here:</p>
<ul>
<li><a href="http://jsfiddle.net/techarch/z5Ptd/" target="_blank">Basics &#8211; Example 1</a></li>
<li><a href="http://jsfiddle.net/techarch/YXxpG/" target="_blank">Building Up  &#8211; Example 1</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=354</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>Leverage Twitter Features In Your Ruby Application With Twitter4R</title>
		<link>https://blog.monnet-usa.com/?p=342</link>
					<comments>https://blog.monnet-usa.com/?p=342#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Fri, 18 Mar 2011 03:24:08 +0000</pubDate>
				<category><![CDATA[OAuth]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Twitter4R]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=342</guid>

					<description><![CDATA[Intro A few years ago I integrated Twitter with a Ruby application, mainly to display a subset of my timeline. Later I added the ability to post tweets. All this became possible using Susan Potter&#8216;s &#8220;most-excellent&#8221; Twitter4R gem. Back in late 2010, Twitter upgraded its API from simple id/password authentication to OAuth authentication. The Twitter4R [&#8230;]]]></description>
										<content:encoded><![CDATA[<style>
						h3 {	text-decoration: underline; }</p>
<p>						h5 
						{
							margin:0 50px 0 50px;
						}</p>
<p>						.download_panel
						{
						background-color: #EDD6AD; 
						color: #555555; 
						font-weight:bold;
						text-align:center;
						margin:0 50px 0 50px;
						padding:6px;
						}</p>
</style>
<h3>Intro </h3>
<p>A few years ago I integrated Twitter with a Ruby application, mainly to display a subset of my timeline.<br />
					Later I added the ability to post tweets. All this became possible using <a href='#spbg'>Susan Potter</a>&#8216;s &#8220;most-excellent&#8221; <a href='#tw4rgh'>Twitter4R</a> gem.
					</p>
<p>Back in late 2010, Twitter upgraded its API from simple id/password authentication to <a href='#oan'>OAuth</a> authentication. The <a href='#tw4rgh'>Twitter4R</a> gem was then also enhanced to leverage the <a href='#oagh'>OAuth-Ruby</a> library. I had created a to-do item to go back and upgrade my apps so this past week I decided it was time to document the process in a quick tutorial!</p>
<h3>Twitter4R Approach</h3>
<p>					<img src='./wp-content/media/twitter4r/twitter4r-approach.png' width='60%'> </p>
<p>When you register your client application with Twitter, you are assigned an <a>App OAuth Token</a> consisting of a <a>consumer key</a> and <a>consumer secret</a> pair. Your app will configure Twitter4R to use this app token during all API calls with Twitter.</p>
<p>Your app will also need to keep track of <a>User OAuth Tokens</a> and pass a specific user token through the API.<br />
					Behind the scene Twitter4R will perform REST calls to the actual Twitter API using JSON data.</p>
<p><p>If you only want your app to access your own account, you will create an Access Token for your Twitter account on your newly-registered app</p>
<h3>Playing With Twitter4R In The Console</h3>
<h5>Installing Twitter4R</h5>
<p>From a command window / shell, just run:</p>
<pre class="brush: ruby">
gem install oauth
</pre>
<p>Notice that both the Twitter4R and the OAuth gems are installed.</p>
<p>					<img src='./wp-content/media/twitter4r/twitter4r-install.png' > </p>
<h5>Registering Our App With Twitter</h5>
<p>To obtain a <a>consumer key and secret pair</a>, we&#8217;ll need to register our application with Twitter at <a href='https://dev.twitter.com/apps'>https://dev.twitter.com/apps</a>. We will need to provide the following:</p>
<ol>
<li>The name of our app (which must be unique within Twitter&#8217;s app registry)</li>
<li>A description</li>
<li>The base url of our app</li>
<li>The url to redirect authenticated users to in our app</li>
<li>The type of access needed: read or read/write (if we want to be able to update our status)</li>
</ol>
<p>						<span>Example:</span><br />
						<img src='./wp-content/media/twitter4r/twitter4r-registration.png' > </p>
<h5>Obtaining Your Own User OAuth Access Token</h5>
<p>Once you have registered the app, if you click on the &#8220;My Access Token&#8221; button, Twitter will give your OAuth user key and secret token.<br />
					<span>Example:</span><br />
					<img src='./wp-content/media/twitter4r/twitter4r-mytoken.png' > </p>
<p>In another section we&#8217;ll see how to authorize a user and get its access token programmatically.</p>
<h5>Testing Twitter4R In IRB</h5>
<p>Let&#8217;s start a Ruby console using IRB and load Twitter4R:</p>
<pre class="brush: ruby">
gem 'twitter4r'
require 'twitter'
require 'twitter/console'
 </pre>
<p>Now we can configure the Twitter4R client using the Twitter::Client.configure class method.<br />
					The block allows us to customize the application and its app OAuth token. Evaluate the following code snippet:</p>
<pre class="brush: ruby">
Twitter::Client.configure do |conf|
   # App configuration
   conf.application_name = 'BeaconPulse)))'
   conf.application_version = '1.0'
   conf.application_url = 'http://beaconpulse.heroku.com/'

   #  App OAuth token key/secret pair
   conf.oauth_consumer_token = "***YourAppConsumerKeyFromYourTwitterAppRegistration***"
   conf.oauth_consumer_secret = "***YourAppConsumerSecretFromYourTwitterAppRegistration***"
end
</pre>
<p>We can then inspect the resulting configuration using:</p>
<pre class="brush: ruby">
cfg = Twitter::Client.config
 </pre>
<h5>Instantiating A Twitter4RClient</h5>
<p>We&#8217;ll use the user key/secret pair we looked up on the Twitter Access Token page earlier:</p>
<pre class="brush: ruby">
client = Twitter::Client.new(:oauth_access => 
 { 	:key 	=> "***YourUserOAuthAccessTokenKey***", 
	:secret => "***YourUserOAuthAccessTokenPassword***"
 })
 </pre>
<h5>Taking Twitter Features For A Spin</h5>
<p>Now that we have a client instance, we can exercise its various methods (see <a href='http://twitter4r.rubyforge.org/rdoc/classes/Twitter/Client.html'>rdoc</a> for details) such as:</p>
<ul>
<li><a href='http://twitter4r.rubyforge.org/rdoc/classes/Twitter/Client.html#M000048'>user</a> information about a given account:
<pre class="brush: ruby">
i = client.user 'techarch'
 </pre>
</li>
<li><a href='http://twitter4r.rubyforge.org/rdoc/classes/Twitter/Client.html#M000049'>my</a> info / friends / followers:
<pre class="brush: ruby">
fr = client.my :friends
fo = client.my :followers
 </pre>
</li>
<li><a href='http://twitter4r.rubyforge.org/rdoc/classes/Twitter/Client.html#M000035'>timeline_for</a> me / user / public / friends / :
<pre class="brush: ruby">
tm = client.timeline_for :me
tm1 = client.timeline_for :me, :count => 1 # my last tweet

tu = client.timeline_for :user, :id => 'susanpotter'
tp = client.timeline_for :public
tf = client.timeline_for :friends
 </pre>
</li>
<li>post a <a href='http://twitter4r.rubyforge.org/rdoc/classes/Twitter/Client.html#M000045'>status</a>:
<pre class="brush: ruby">
t = client.status :post, 'Posting tweets from IRB using the Twitter4R gem rocks!'
</pre>
</li>
</ul>
<p>					As you can see you can have a lot of fun with the client!
					</p>
<h3>Authorizing A User And Getting Its Access Token</h3>
<p>In an earlier section, we just looked up our own access token on the Twitter page for our app registration.<br />
					But to allow any user to access our app we would need to:</p>
<ol>
<li>Instantiate an <a>OAuth Consumer</a> (like Twitter4R does behind the scenes) with our app consumer key/secret pair:
<pre class="brush: ruby">
# we reuse the cfg variable we set earlier since it contains our app configuration
k = cfg.oauth_consumer_token
s = cfg.oauth_consumer_secret
u = "#{(cfg.protocol == :ssl ? :https : cfg.protocol).to_s}://#{cfg.host}:#{cfg.port}"

oc = OAuth::Consumer.new(k ,s, :site=> u)
</pre>
</li>
<li>Ask the OAuth consumer to:
<ul>
<li>create an <a>OAuth RequestToken</a> (a temporary credential token used to authenticate our consumer app on Twitter)</li>
<li>and give us an authorization url:</li>
</ul>
<pre class="brush: ruby">
rt = oc.get_request_token
auth_url = rt.authorize_url
</pre>
<p>							We can actually paste this url in a browser.</p>
</li>
<li>Redirect the user to the authorization url so that Twitter can prompt for authorization to access our app
</li>
<li>Once authorized, get the <a>OAuth Verifier</a> (a verification code which will be passed back to Twitter in subsequent requests)
</li>
<li>User the Request Token to retrieve an <a>OAuth AccessToken</a> (the actual authorized user token needed for all future API calls to Twitter) for the user based on the OAuth Verifier:
<pre class="brush: ruby">
at = rt.get_access_token(:oauth_verifier=>'***ThePINnumberReturnedByTwitter***')

user_key = at.token
user_secret = at.secret
 </pre>
</li>
<li>Optionally store the user OAuth key/secret pair so we can instantiate a Twitter4R Client to invoke APIs on the user&#8217;s behalf:
<pre class="brush: ruby">
client = Twitter::Client.new(:oauth_access => { :key => user_key, :secret => user_secret })
info = client.user 'techarch'
 </pre>
</li>
</ol>
<h3>Approach For Integrating Twitter4R In Your App</h3>
<p>Now that you have a handle on the basics using the Interactive Ruby Console, you can check out the full <a href='http://twitter4r.rubyforge.org/rdoc/'>RDoc</a><br />
					and add Twitter support to your favorite Ruby app. In a future blog post I&#8217;ll cover the integration approach for a Ruby Camping web app.</p>
<p><span>Here is what the Twitter4R ecosystem looks like from 50,000 feet:</span><br />
					<img src='./wp-content/media/twitter4r/twitter4r-yuml.png' > </p>
<p></p>
<h3>So What? </h3>
<p>Since Twitter has moved to <a href='#oan'>OAuth</a> you need a robust and efficient library like <a href='#tw4rgh'>Twitter4R</a> to integrate Twitter in your application.<br />
					<a href='#tw4rgh'>Twitter4R</a> leverages the Twitter REST API using the JSON format to limit bandwith consumption.<br />
					The gem is &#8220;framework-neutral&#8221;, so it can be used in pure Ruby apps, as well as on top of frameworks such as Rails, <a href='#rc'>Ruby-Camping</a>, and Sinatra.<br />
					If you have not experimented with <a href='#tw4rgh'>Twitter4R</a>, hopefully this tutorial will get you started.</p>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>Twitter4R</h5>
<ul>
<li><a name='tw4rgh' href='https://github.com/twitter4r/twitter4r-core'>Twitter4R on GitHub</a></li>
<li><a name='spbg' href='http://geek.susanpotter.net/'>Susan Potter&#8217;s blog</a></li>
<li><a name='tw4rsh' href='http://www.slideshare.net/mbbx6spp/twitter4r-oauth'>&#8220;Configuring Your Twitter4R App With OAuth&#8221; by Susan Potter &#8211; on SlideShare</a></li>
</ul>
<h5>OAuth And My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a name='oan' href='http://oauth.net/'>OAuth.net site</a></li>
<li><a name='oau' href='http://hueniverse.com/'>OAuth Universe site</a></li>
<li><a name='oagh' href='https://github.com/oauth/oauth-ruby'>OAuth Ruby on GitHub</a></li>
<li><a href='https://blog.monnet-usa.com/?p=293'>Transform Your Ruby Camping Web App Into An OAuth Provider (explains the OAuth &#8220;dance&#8221;!)</a></li>
<li><a name='rc' href='http://github.com/camping/camping'>Ruby Camping Framework</a></li>
</ul>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
							If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
						</div>
<div class="blog-msm-ad2">
								<a href="http://www.myskillsmap.com/take-charge-of-your-skills-development"><br />
									<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
								</a>
						</div>
</p></div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=342</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Improving Web Conversions In 3 Key Steps</title>
		<link>https://blog.monnet-usa.com/?p=337</link>
					<comments>https://blog.monnet-usa.com/?p=337#comments</comments>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Sun, 09 Jan 2011 15:00:05 +0000</pubDate>
				<category><![CDATA[A/B Testing]]></category>
		<category><![CDATA[Conversion Optimization]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Web Analytics]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=337</guid>

					<description><![CDATA[Intro I am a huge fan of the TechZing podcast, a show focused on bootstrapped web entrepreneur. In the last couple months Jason Roberts and Justin Vincent have had a series of interviews focused on improving usability, web analytics. The latest show (#98) includes Lance Jones as a guest and focuses on Conversion Optimization. After [&#8230;]]]></description>
										<content:encoded><![CDATA[<style>
						h3 {	text-decoration: underline; }</p>
<p>						h5 
						{
							margin:0 50px 0 50px;
						}</p>
<p>						.download_panel
						{
						background-color: #EDD6AD; 
						color: #555555; 
						font-weight:bold;
						text-align:center;
						margin:0 50px 0 50px;
						padding:6px;
						}</p>
</style>
<h3>Intro </h3>
<p>I am a huge fan of the <a href="http://techzinglive.com/">TechZing</a> podcast, a show focused on bootstrapped web entrepreneur.<br />
					In the last couple months <a href="http://www.codusoperandi.com/">Jason Roberts</a> and <a href="http://justinvincent.com/">Justin Vincent</a><br />
					have had a <a href='#tzshows'>series of interviews</a> focused on improving usability, web analytics.<br />
					The <a href="http://techzinglive.com/page/606/98-tz-interview-lance-jones-conversion-optimization/">latest show (#98)</a> includes Lance Jones as a guest and focuses on <b>Conversion Optimization</b>.
					</p>
<p>After listening to the show while driving I decided to replay it once more and take notes as I think it brings a lot of value for any web entrepreneur!<br />
					And since I could not fit all the contents and links in the comments I decided to create this short post. Enjoy!</p>
<h3>The 3-Step Process</h3>
<p>					<img src='./wp-content/media/conversion-optimization/conversion-optimization-1.png' width='80%'></p>
<p>Before starting any A/B test or optimization it is important to really think through the goals and key performance indicators you want to optimize for.<br />
					Otherwise you will waste a lot of time or may not get meaningful information and probably not achieve your target goals.<br />
					To optimize the conversion process you need to:</p>
<ol>
<li>Track and analyze <b>conversions</b></li>
<li>Analyze and understand <b>user behavior</b></li>
<li>Optimize the <b>user experience</b>, the <b>copy (key content)</b>, and <b>affect user behavior</b></li>
</ol>
<p>It is critical to have enough traffic to get statistically meaningful data from the tests.<br />
							You need probably about 100 conversions per bucket or test option.<br />
							So assuming different conversion rates you need quite a lot of users entering the funnel:</p>
<ul>
<li>a 2% conversion rate requires 5000 users</li>
<li>a 5% conversion rate requires 2000 users</li>
<li>etc.</li>
</ul>
<h3>Supporting Tools</h3>
<style>
						#tools_table {border: 1px solid #f0f0f0;border-spacing: 1px;background-color:#eee;margin:10px 0px 0px 40px;border: 1px solid black;}
						#tools_table tr {vertical-align: top;border-bottom: 1px solid #eee;}
						.tools_table_section {background-color:lightgray;}
						#tools_table th {background-color:lightgray;}
						#tools_table td {border-bottom: 1px solid #eee;}</p>
</style>
<table id="tools_table" style="">
<tr>
<th>Product</th>
<th>Comments</th>
</tr>
<tr>
<td class="tools_table_section" colspan='2'>Tools to tracking and analyze conversions</td>
</tr>
<tr>
<td><a href="http://getclicky.com">Clicky</a></td>
<td></td>
</tr>
<tr>
<td><a href="http://www.google.com/websiteoptimizer">Google web site optimizer</a></td>
<td></td>
</tr>
<tr>
<td><a href="http://www.crazyegg.com">Crazyegg</a></td>
<td>Includes  heatmap</td>
</tr>
<tr>
<td><a href="http://mixpanel.com">Mixpanel</a></td>
<td>Great for tracking business/user events</td>
</tr>
<tr>
<td><a href="http://www.performable.com">Performable</a></td>
<td>Full customer experience and revenue tracking, reverse funnel analysis</td>
</tr>
<tr>
<td><a href="http://www.omniture.com">Omniture</a></td>
<td>The Cadillac option for large enterprises</td>
</tr>
<tr>
<td  class="tools_table_section" colspan='2'>Tools to survey and understand user behavior</td>
</tr>
<tr>
<td><a href="http://www.iperceptions.com">iperceptions</a></td>
<td>Define quick short surveys to understand user motivations and success</td>
</tr>
<tr>
<td><a href="http://www.kissinsights.com">KissInsights</a></td>
<td>Prompt users for one quick simple question</td>
</tr>
<tr>
<td><a href="http://www.4qsurvey.com">4Q Survey</a></td>
<td>Prompts users for the 4 essential questions about their experience</td>
</tr>
<tr>
<td><a href="http://www.foreseeresults.com">ForeseeResults</a></td>
<td>Focuses on complete web effectiveness</td>
</tr>
<tr>
<td><a href="http://www.opinionlab.com">Opinionlab</a></td>
<td>More sophisticated option with survey modules, reports, <etc></etc></p>
<div class=""></div>
</td>
</tr>
<tr>
<td class="tools_table_section" colspan='2'>Getting input from real testers</td>
</tr>
<tr>
<td><a href="http://www.usertesting.com">UserTesting</a></td>
<td>Testers narrate their test using video</td>
</tr>
<tr>
<td><a href="http://www.feedbackarmy.com">FeedbackArmy</a></td>
<td>You submit 4-6 questions about your site and you receive 10 answers</td>
</tr>
<tr>
<td><a href="http://fivesecondtest.com">5secondtest</a></td>
<td>Testers have 5 seconds to get an impression of your landing page</td>
</tr>
<tr>
<td class="tools_table_section" colspan='2'>Tools to optimize the site</td>
</tr>
<tr>
<td><a href="http://www.google.com/websiteoptimizer">Google web site optimizer</a></td>
<td></td>
</tr>
<tr>
<td><a href="http://www.sumooptimize.com">SumoOptimize</a></td>
<td>Recent entrant</td>
</tr>
<tr>
<td><a href="http://www.optimizely.com">Optimizely</a></td>
<td>Great wysiwyg editing of your own pages</td>
</tr>
<tr>
<td><a href="http://unbounce.com">Unbounce</a></td>
<td>Great for testing different landing pages and starting A/B tests</td>
</tr>
<tr>
<td><a href="http://visualwebsiteoptimizer.com">Visual website optimizer</a></td>
<td>Rich functionality with a great wysiwyg interface</td>
</tr>
</table>
<p><i>Note: the list above and associated comments are just based on the show, not on an exhaustive analysis of all vendors and products.</i></p>
<h3>So What? </h3>
<p>So if you put all the concepts together you get the following approach synopsis:</p>
<p>					<img src='./wp-content/media/conversion-optimization/conversion-optimization-2.png' width='100%'></p>
<p>Web conversion optimization is not &#8220;black magic&#8221;, try to follow the process highlighted above as well as the tools.<br />
					Providing you can generate enough traffic to your site to run multiple iterations, over time you will most likely see a positive change in your conversions.</p>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>A/B Testing</h5>
<ul>
<li><a name='abwp' href='http://en.wikipedia.org/wiki/A/B_Testing'>A/B Testing Definition on Wikipedia</a></li>
<li><a name='abbasics' href='http://elem.com/~btilly/effective-ab-testing/'>Effective A/B Testing Basics (by Ben Tilly)</a></li>
</ul>
<p>					<a name="tzshows"></a></p>
<h5>TechZing</h5>
<ul>
<li><a name='tz' 	href='http://techzinglive.com'>TechZing Podcast for web startup entrepreneurs</a></li>
<li><a name='tzjr' 	href='http://www.codusoperandi.com/'>Jason Robert&#8217;s blog</a></li>
<li><a name='tzjv' 	href='http://justinvincent.com/'>Justin Vincent&#8217;s blog</a></li>
<li><a name='tz98' 	href='http://techzinglive.com/page/606/98-tz-interview-lance-jones-conversion-optimization/'>TechZing 98: TZ Interview – Lance Jones / Conversion Optimization</a></li>
<li><a name='tz92' 	href='http://techzinglive.com/page/544/92-tz-interview-ilya-lichtenstein-insight-io'>TechZing 92: TZ Interview – Ilya Lichtenstein / insight.io</a></li>
<li><a name='tz89' 	href='http://techzinglive.com/page/528/89-tz-interview-david-cancel-performable'>TechZing 89: TZ Interview – David Cancel / Performable</a></li>
<li><a name='tz87' 	href='http://techzinglive.com/page/522/87-tz-interview-luke-wroblewski-the-user-interface-is-the-product'>TechZing 87: TZ Interview – Luke Wroblewski / The User Interface Is The Product</a></li>
<li><a name='tz79' 	href='http://techzinglive.com/page/479/79-tz-interview-%e2%80%93-patrick-mckenzie-optimize-this'>TechZing 79: Patrick McKenzie / The Long Tail of Optimization</a></li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a href='https://blog.monnet-usa.com/?p=223'>Visualize Application Metrics on NewRelic for your Ruby Camping Application</a></li>
<li><a href='https://blog.monnet-usa.com/?p=322'>A/B Test Your Ruby Camping Web App Using ABingo</a></li>
</ul>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
							If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
						</div>
<div class="blog-msm-ad2">
								<a href="http://www.myskillsmap.com/take-charge-of-your-skills-development"><br />
									<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
								</a>
						</div>
</p></div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.monnet-usa.com/?feed=rss2&#038;p=337</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>A/B Test Your Ruby Camping Web App Using ABingo (Part 2)</title>
		<link>https://blog.monnet-usa.com/?p=330</link>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Tue, 14 Dec 2010 07:00:16 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=330</guid>

					<description><![CDATA[Intro In &#8220;A/B Test Your Ruby Camping Web App Using ABingo (Part 1)&#8221;, I introduced the ABingo A/B testing framework and the new Camping ABingo plugin. In this article I will cover the following topics: Look under the ABingo Hood to understand its API, object model, and underlying database tables Create a draft of the [&#8230;]]]></description>
										<content:encoded><![CDATA[<br />
<h3>Intro </h3>
<p>In <a href="https://blog.monnet-usa.com/?p=322">&#8220;A/B Test Your Ruby Camping Web App Using ABingo (Part 1)&#8221;</a>, I introduced  the <a href="#abpmk">ABingo A/B testing framework</a> and the new <a href="#tacaab">Camping ABingo plugin</a>. In this article I will cover the following topics:
					</p>
<ol>
<li>Look under the ABingo Hood to understand its API, object model, and underlying database tables</li>
<li>Create a draft of the ABingo Test Application</li>
<li>Integrate ABingo into our test app</li>
<li>Run and analyze experiments</li>
</ol>
<h3>Under The ABingo Hood</h3>
<p>Before we can dive in the integration of the <a href='#tacaab'>Camping ABingo plugin</a> with our prototype application, here is a quick overview of the basics of the ABingo framework.</p>
<h4>ABingo API</h4>
<p>The two most important APIs are <a href="http://camping-abingo.monnet-usa.com/classes/ABingoCampingPlugin/Helpers.html#M000050">ab_test</a> and <a href="http://camping-abingo.monnet-usa.com/classes/Abingo.html#M000006">bingo!</a>:<br />
					<img src='./wp-content/media/camping-abingo/camping-abingo-api.png'  width="90%" />
					</p>
<table class='details_table'>
<tr>
<th>API</th>
<th>Parameters</th>
<th>Context</th>
<th>Purpose/Usage</th>
</tr>
<tr>
<td><a name='api_ab_test'><br />
		</a>ab_test</td>
<td>
<ul class="api_parm">
<li>test name</li>
<li><i>optional:</i> array of alternatives</li>
<li><i>optional:</i> conversion name</li>
</ul>
</td>
<td>View or Controller</td>
<td>Select an alternative for the current user based on the alternatives specified for this test. If no alternatives are specified a boolean value is returned. Tracks the execution using the conversion name if provided otherwise use the test name.</td>
</tr>
<tr>
<td><a name='api_bingo'></a>bingo!</td>
<td>
<ul  class="api_parm">
<li>conversion name (or test name)</li>
</ul>
</td>
<td>Controller</td>
<td>Tracks a conversion for the current user and the conversion specified. The test name is the fallback option.</td>
</tr>
</table>
<p></p>
<p>Note: these 2 main APIs are implemented in Camping in a helper module being included in both controllers and views. The <b>ab_test</b>  is <i>syntactic sugar</i> over the <b>test</b> method provided by the core <a href="http://camping-abingo.monnet-usa.com/classes/Abingo.html" target=”_blank”>Abingo class</a>.</p>
<h4  style="page-break-before:always;">Model</h4>
<p>The basic object model for the ABingo framework looks like this:<br />
					<img src='./wp-content/media/camping-abingo/camping-abingo-uml.png' width='100%'/>
					</p>
<p><a name='abmo'></a></p>
<table class='details_table'>
<tr>
<th>Model</th>
<th>Responsibilities</th>
</tr>
<tr>
<td><a name='abus'></a>User</td>
<td>The user account on the prototype app</td>
</tr>
<tr>
<td><a name='abapi'></a>Abingo</td>
<td>ABingo&#8217;s main API class</td>
</tr>
<tr>
<td><a name='abexp'></a>Experiment</td>
<td>Represents a specific test based on multiple alternatives</td>
</tr>
<tr>
<td><a name='abalt'></a>Alternative</td>
<td>Tracks participants and conversions for a given alternative</td>
</tr>
</table>
<p></p>
<h4>ABingo Database Tables</h4>
<p>ABingo will need to track executions of your <a href="#abexp">Experiments</a> and their corresponding <a href="#abalt">Alternatives</a> in the database associated with your application. So the ABingo Camping plugin will include the needed migration to add 2 tables to your schema. We&#8217;ll see this in more details later.</p>
<h3>Create An ABingo Test Application</h3>
<h4>Install Camping-ABingo</h4>
<p>First let&#8217;s install the gem. (If you don&#8217;t have Camping or any of its dependent gem they will be installed)</p>
<pre class="brush: ruby; gutter: false; toolbar: false;">
gem install camping-abingo
</pre>
<p>Note: You will find the fully functional test application under the <b>examples/camping-abingo-test</b> folder in the camping-abingo gem folder. If you want to start using it right away, skip the next sections and go straight to <b><a href="#caabtest">Setting Up Our First A/B Test</a></b>. Otherwise follow along.</p>
<h4>Running the Skeleton pre-ABingo Test Application</h4>
<p>In the next sections I will show you how to integrate ABingo with the skeleton test app. But before let&#8217;s get the skeleton application up and running.</p>
<ol class="blog-post-list">
<li>Locate the <b>examples/camping-abingo-test</b> folder under your camping-abingo gem folder.<br />
					<img src='./wp-content/media/camping-abingo/camping-abingo-cmd-1.png' ><br />
					There are two versions of the test app: </p>
<ul>
<li>the skeleton (without ABingo support)</li>
<li>the fully implemented version</li>
</ul>
</li>
<li>Open <b>camping-abingo-test-skeleton.rb</b> in an editor. </li>
<li>Then let&#8217;s start the <b>Camping</b> server with our skeleton:
<pre class="brush: ruby; gutter: false; toolbar: false;">
camping camping-abingo-test-skeleton.rb
</pre>
</li>
<li>Open a browser and access the skeleton from the browser at the following url:
<pre class="brush: ruby; gutter: false; toolbar: false;">
http://localhost:3001/
</pre>
<p>						<span  style="page-break-before:always;">Camping will run the first migration to create the table for our User model:</span></p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-cmd-migration1.png' width="610px"></p>
<p>						And the basic test app should now come up:</p>
<p>						<img src='./wp-content/media/camping-abingo/camping-abingo-tester.png' >
						</li>
<li>You can now test the basic flow of the application. When viewing the landing page, the sign-up button should always be labeled &#8220;Sign-Up Now!&#8221;. Once ABingo is integrated we will be experimenting with different alternatives.</li>
</ol>
<p>					<a name="addabprsu" ></a></p>
<h3>Adding ABingo Support To The Skeleton Test App</h3>
<p>The ABingo plugin is composed of several modules mirroring the standard modules a typical Camping application would contain.<br />
					Integrating the plugin will consist of linking the various modules using a combination of <b>include</b> and/or <b>extend</b> statements where appropriate. Here is a high-level diagram of the integration approach:</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo.png' width="600px" style="margin-left: 40px"></p>
<p  style="page-break-before:always;">Here are the steps we will be following:</p>
<p><a name='caoatodo'></a></p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
</tr>
<tr>
<td><a href='#caabtodoa'>A</a></td>
<td>Reference and require the needed gems</td>
</tr>
<tr>
<td><a href='#caabtodob'>B</a></td>
<td>Customize the main module</td>
</tr>
<tr>
<td><a href='#caabtodod'>C</a></td>
<td>Plugging in the ABingo common helpers module</td>
</tr>
<tr>
<td><a href='#caabtodoc'>D</a></td>
<td>Plugging in the ABingo Experience and Alternative models</td>
</tr>
<tr>
<td><a href='#caabtodoe'>E</a></td>
<td>Plugging in the ABingo Dashboard controllers</td>
</tr>
<tr>
<td><a href='#caabtodof'>F</a></td>
<td>Plugging in the ABingo Dashboard views</td>
</tr>
<tr>
<td><a href='#caabtodog'>G</a></td>
<td>Add code to manage the ABingo user identity in our controllers</td>
</tr>
</table>
<p>	</p>
<p>					<a name='caabtodoa'></a></p>
<h5>A. Reference and require the needed gems</h5>
<p>We will need to reference 2 gems: <b>filtering_camping</b> and <b>camping-abingo</b>. Also we will require the corresponding files we need: filtering_camping and camping-abingo.So now the top of the source should look like this:</p>
<pre class="brush: ruby">
gem 'camping' , '>= 2.0'	
gem 'filtering_camping' , '>= 1.0'	
gem 'camping-abingo'

%w(rubygems active_record erb  fileutils json markaby md5 redcloth  
camping camping/session filtering_camping camping-abingo
).each { |lib| require lib }

Camping.goes :CampingABingoTest
</pre>
<p>					<a name='caabtodob'></a></p>
<h5>B.Customizing the main module</h5>
<p>Ok, so now we&#8217;re ready to enhance the main app module. First we&#8217;ll make sure to include the Camping::Session and CampingFilters modules, and to extend the app module with ABingoCampingPlugin and its Filters submodule, like so:</p>
<pre class="brush: ruby">
module CampingABingoTest
	include Camping::Session
	include CampingFilters

	extend  ABingoCampingPlugin
	include ABingoCampingPlugin::Filters
	
	# ...
end
</pre>
<p>We can also associate the logger with our <a href='#tacaab'>camping-abingo plugin</a>.</p>
<pre class="brush: ruby">
	Camping::Models::Base.logger = app_logger
	ABingoCampingPlugin.logger   = app_logger
</pre>
<p>Now let&#8217;s customize the <b>create</b> method by adding a call to ABingoCampingPlugin.create, so we can get the plugin to run any needed initialization.</p>
<pre class="brush: ruby">
	def CampingABingoTest.create
		ABingoCampingPlugin.create
	end
</pre>
<p>We need to more things: let&#8217;s link our logger to the ABingo cache logger (to make it easier to debug issues), and let&#8217;s define which User id represent the administrator who will have access to the ABingo Dashboard. Now the final version of the create method looks like this:</p>
<pre class="brush: ruby">
	def CampingABingoTest.create
		dbconfig = YAML.load(File.read('config/database.yml'))								
		environment = ENV['DATABASE_URL'] ? 'production' : 'development'
		Camping::Models::Base.establish_connection  dbconfig[environment]

		ABingoCampingPlugin.create
		Abingo.cache.logger = Camping::Models::Base.logger
		Abingo.options[:abingo_administrator_user_id] = 1

		CampingABingoTest::Models.create_schema :assume => (CampingABingoTest::Models::User.table_exists? ? 1.1 : 0.0)
	end
</pre>
<p>Ok, at this point we have a minimally configured application module. </p>
<p>					<span  style="page-break-before:always;"></span><br />
					<a name='caabtodod'></a></p>
<h5>C.Plugging in the ABingo common helpers module</h5>
<p>The Helpers module is used in <a href='#rc'>Camping</a> to provide common utilities to both the Controllers and Views modules. Enhancing our Helpers module is very easy, we need to add both an <b>extend</b> and an <b>include</b> of the ABingoCampingPlugin::Helpers module so we can enhance both instance and class sides:</p>
<pre class="brush: ruby">
module CampingABingoTest::Helpers
	extend ABingoCampingPlugin::Helpers
	include ABingoCampingPlugin::Helpers
end</pre>
<p>					<a name='caabtodoc'></a></p>
<h5>D.Plugging in the ABingo Experience and Alternative models</h5>
<p>First, we&#8217;ll include the include ABingoCampingPlugin::Models module so we can get all the <a href='#abmo'>ABingo-specific models</a>. Our model will look like this:</p>
<pre class="brush: ruby">
module CampingABingoTest::Models
	include ABingoCampingPlugin::Models

	# ...
end
</pre>
<p>Now we&#8217;ll enhance the CreateUserSchema migration class to plug in our ABingo model migration.</p>
<ul>
<li>We&#8217;ll bump up the migration version number of the CreateUserSchema class to 1.1</li>
<li>In the <b>up</b> method we will add a call to <b>ABingoCampingPlugin::Models.up</b> so that the <a href='#abexp'>Experience</a>, <a href='#abalt'>Alternative</a> tables can be created.</li>
<li>In the <b>down</b> method we will add a call to <b>ABingoCampingPlugin::Models.down</b> to drop the ABingo tables.</li>
</ul>
<pre class="brush: ruby">
	class CreateUserSchema < V 1.1
		def self.up
			create_table :CampingABingoTest_users, :force => true do |t|
				# ...
			end
			
			# ...
			
			ABingoCampingPlugin::Models.up
		end
		
		def self.down		
			ABingoCampingPlugin::Models.down
			
			drop_table :CampingABingoTest_users
		end
	end
</pre>
<p>Now if we restart the application, our version 1.1 migration should be executed:</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-cmd-migration2.png' /></p>
<p>					<span  style="page-break-before:always;"></span><br />
					<a name='caabtodoe'></a></p>
<h5>E.Plugging in the ABingo Dashboard controllers</h5>
<p>We will need to extend our app <b>Controllers</b> module with the <b>ABingoCampingPlugin::Controllers</b> module using the <b>extend</b> statement. Then just before the end of the Controllers module, we&#8217;ll add a call to the <b>include_abingo_controllers</b> method. This is how <a href='#tacaab'>camping-abingo</a> will inject and plugin the ABingo Dashboard controllers and helpers. It is important that this call <u>always remaining the last statement of the module</u>, even when you add new controller classes. So the module should look like so:</p>
<pre class="brush: ruby">
module CampingABingoTest::Controllers
	extend ABingoCampingPlugin::Controllers

	# ...

	include_abingo_controllers
end #Controllers
</pre>
<p>					<a name='caabtodof'></a></p>
<h5>F.Plugging in the ABingo Dashboard views</h5>
<p>We will need to extend our app <b>Views</b> module with the <b>ABingoCampingPlugin::Views</b> module using the <b>extend</b> statement. Then just before the end of the Views module, we&#8217;ll add a call to the <b>include_abingo_views</b> method. This is how <a href='#tacaab'>camping-abingo</a> will inject and plugin the ABingo Dashboard views. It is important that this call <u>always remaining the last statement of the module</u>, even when you add new view methods. So the module should look like so:</p>
<pre class="brush: ruby">
module CampingABingoTest::Views
	extend ABingoCampingPlugin::Views

	# ...
	
	include_abingo_views
end
</pre>
<p>					<a name='caabtodog'></a></p>
<h5>G.Add code to manage the ABingo user identity in our controllers</h5>
<p>ABingo tracks the selected experiment alternatives and potential conversions for a <b>given user</b> using a property named <a href="http://camping-abingo.monnet-usa.com/classes/Abingo.html#M000003">identity</a>. Currently the <b>ABingoCampingPlugin::Filters</b> we included in our main module provides a <b>filter</b> that executes <b>before all</b> controllers. That filter is responsible for ensuring the <b>Abingo.identity</b> is set using either a large random integer if the user is anonymous, or the actual id of an existing user. Here is what the filter looks like:</p>
<pre class="brush: ruby">
	before :all do
		set_abingo_identity
	end
</pre>
<p>To handle non-anonymous users and for our integration with our controllers to be complete we will need to:</p>
<ol class="blog-post-list">
<li>Set the identity to the new user&#8217;s id once signup is complete.<br />
							So in the <b>post</b> action of our <b>SignUp</b> controller, let&#8217;s set the <b>@state.abingo_identity</b> to our user&#8217;s id before rendering the Welcome view &#8211; see line 14:</p>
<pre class="brush: ruby">
	class SignUp < R '/signup'
		# get ...
		
		def post
			@user = User.find_by_username(input.username)
			if @user
				@info = 'A user account already exist for this username.'
			else
				@user = User.new :username => input.username,
					:password => input.password
				@user.save
				if @user
					@state.user_id = @user.id
					@state.abingo_identity = @user.id
					redirect R(Welcome)
				else
					@info = @user.errors.full_messages unless @user.errors.empty?
				end
			end
			render :signup
		end
	end
</pre>
</li>
<li>Replace the <b>abingo_identity</b> with the user&#8217;s id (<b>@user.id</b>) when someone signs-in. See line 9:
<pre class="brush: ruby">
	class SignIn < R '/signin'
		# ...
		
		def post
			@user = User.find_by_username_and_password(input.username, input.password)

			if @user
				@state.user_id = @user.id
				@state.abingo_identity = @user.id

				if @state.return_to.nil?
					redirect R(Welcome)
				else
					return_to = @state.return_to
					@state.return_to = nil
					redirect(return_to)
				end
			else
				@info = 'Wrong username or password.'
			end
			
			render :signin		
		end
	end
</pre>
</li>
<li>Generate a new random identity when the current user has signed-out.<br />
						So let's set the <b>@state.abingo_identity</b> to another large random integer in the <b>get</b> action of our <b>SignOut</b> controller. See line 4:</p>
<pre class="brush: ruby">
	class SignOut < R '/signout'		
		def get
			@state.user_id = nil
			@state.abingo_identity = Abingo.identity = rand(10 ** 10).to_i
			
			render :index
		end
	end
</pre>
</li>
<ol>
<p>Now our integration steps are complete. We're now ready to do some A/B testing!</p>
<p>					<a name='caabtest'></a></p>
<h3>Setting Up Our First A/B Test</h3>
<h5>Selecting A Random Alternative For a Given Experience</h5>
<p>For our first experiment named <b>call_to_action</b> we'll vary the text for our <b>signup_btn</b> button by selecting one of 3 alternatives based on the user.<br />
					<img src='./wp-content/media/camping-abingo/camping-abingo-abtests-funnel-2.png'  width="90%" /></p>
<p>					So let's modify the <b>landing</b> view of our test application. We'll change the assignment of the <b>signup_text</b> variable to the result of the <a href="http://camping-abingo.monnet-usa.com/classes/ABingoCampingPlugin/Helpers.html#M000050">ab_test</a> call. So our code will look like the following (with the ab_test call on line 9):</p>
<pre class="brush: ruby">
	def landing
		div.xyz do
			h1 'XYZ SAAS Application'
			
			div.marketing! do
				# benefits ...
				
				div.actnow! do
					signup_text = ab_test("call_to_action", 
											[ 	"Sign-Up Now!",
												"Try It For Free Now!",
												"Start Your Free Trial Now!",
											])
					
					a :href=>"/signup" do
						div.signup_btn!  signup_text
					end
				end
			end
		end
	end
</pre>
<h5>Recording A User Conversion</h5>
<p>If we ran the application now ABingo would choose an alternative and keep track of it in terms of user <b>participation</b>.<br />
					So now we just need to <b>record</b> an actual <b>conversion</b> for the <b>call_to_action</b> test when the user clicks on the <b>signup_btn</b> button.<br />
					<img src='./wp-content/media/camping-abingo/camping-abingo-abtests-funnel-3.png'  width="90%" />					</p>
<p>					To do that, we'll enhance the <b>get</b> action of our <b>SignUp</b> controller by calling the <a href="http://camping-abingo.monnet-usa.com/classes/Abingo.html#M000006">bingo!</a> API with <b>call_to_action</b> as the name of the test. See line 3 below:</p>
<p>At this stage, we have a basic Camping ABingo-enabled application, now let's test it!</p>
<h3  style="page-break-before:always;">Running Our First A/B Test</h3>
<p>So let's refresh the browser - if you stopped the Camping server then restart it (as a note Camping automatically reloads your changes). You have two in three chances to get a different alternatives than our original hard-coded text:</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-test5.png' width="575px" ></p>
<p>Let's look at the content of our <b>camping-abingo-test.db</b> SQLite database (preferably with <a href='#lita'>Lita</a>, an AIR-based SQLite administration tool):</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-test6.png' width="575px" ><br />
					Note that the number of participants for the displayed alternative is 1.
					</p>
<p>If you are using FireBug with FireCookie, delete the <b>campingabingotest.state</b> and refresh the page. You should notice that the <b>abingo_identity</b> should change as well as the button text. Repeat the process several times. And occasionally click on the button to cause a conversion to occur.<br />
					Let's refresh our table contents in Lita:</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-test7.png'  width="575px" ><br />	<br />
					Note that the number of participants and conversions have increased across alternatives.
					</p>
<h3>Viewing A/B Test Results With The ABingo Dashboard</h3>
<p>Checking the database for our results is quite tedious (even with Lita!), luckily ABingo has a built-in <b>Dashboard</b>. Our Camping ABingo plugin has already defined a couple controllers and routes. We just need to expose the main <b>/abingo/dashboard</b> route.</p>
<p>So let's go to the <b>layout</b> method of our ABingo Test app. Right below the link for <b>Sign-Out</b> let's add a code fragment to only show a link to <b></b> if the id of the current signed-in user is the id of the allowed ABingo Administrator (using the <b>abingo_administrator_user_id</b> ABingo helper method). See lines 7-10:</p>
<pre class="brush: ruby">
def layout
	html do
		# ...
		
						a "Sign-Out",	:href=>'/signout'
						
						if @state.user_id == abingo_administrator_user_id
							span " | "
							a "ABingo Dashboard", :href=>"/abingo/dashboard"
						end
						
		# ...
	end
end
</pre>
<p>Now let's sign-in as the default administrator for our app. Use <b>admin</b> for the id and <b>camping</b> as the password. You should now see a <b>"ABingo Dashboard"</b> link in the top right of the navigation bar. Click on it. The dashboard should now show you the results:</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-dashboard-2.png'   >	</p>
<p>Now it is easy to see the results and even terminate a given alternative if we want to.<br />
					Note: each experiment you have defined will be listed with its corresponding details. </p>
<h5>Choosing Your Caching Mechanism</h5>
<p>By default the ABingo Plugin initialize its cache based on a <b>:memory_store</b>. This is fine and easy to troubleshoot our simple test app. But for your application you should consider a more advanced caching mechanisms - see the <a href="http://api.rubyonrails.org/classes/ActiveSupport/Cache.html">ActiveSupport Cache</a> documentation. One suggestion is to use Memcached if possible (e.g. on Heroku).</p>
<h3>So What? </h3>
<ol>
<li>Patrick McKenzie's <a href='#abpmk'>ABingo</a> is a powerful A/B testing framework for Ruby apps.</li>
<li><a href='#abpmk'>ABingo</a> makes it easy to define and execute experiments with multiple alternatives.</li>
<li>The ABingo Dashboard makes interpreting test results a breeze!</li>
</ol>
<p>So hopefully this second post on ABingo (see <a href="https://blog.monnet-usa.com/?p=322">here for the first post</a> of the serie) will have given you a feel for how easy it is to <b>A/B test-enable</b> a Ruby <a href='#rc'>Camping</a>-based web application using the <a href='#tacaab'>Camping ABingo plugin</a>.</p>
<p>					Happy ABingo A/B experiments!!!</p>
<p>					<i>Note: You can try the demo app yourself at: <a href='http://camping-abingo.heroku.com/'>camping-abingo.heroku.com</a> (including the ABingo Dashboard if you sign in as admin / camping).</i></p>
<p>					In a subsequent post I will cover some advanced topics (caching, troubleshooting, multi-variates, etc.) for Camping ABingo. Stay tuned!</p>
<div  style="page-break-before:always;"></div>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>A/B Testing</h5>
<ul>
<li><a name='abwp' href='http://en.wikipedia.org/wiki/A/B_Testing'>A/B Testing Definition on Wikipedia</a></li>
<li><a name='abbasics' href='http://elem.com/~btilly/effective-ab-testing/'>Effective A/B Testing Basics (by Ben Tilly)</a></li>
<li><a name='abgg' href='https://www.google.com/analytics/siteopt/siteopt/help/overvw.html'>Google Website Optmizer</a></li>
<li><a name='abpmk' href='http://www.bingocardcreator.com/abingo'>ABingo A/B Testing Framework (by Patrick McKenzie)</a></li>
<li><a name='pmk' href='http://www.kalzumeus.com/'>Patrick McKenzie's Blog</a></li>
<li><a name='abpmktz' href='http://techzinglive.com/page/479/79-tz-interview-%e2%80%93-patrick-mckenzie-optimize-this'>Patrick McKenzie Interview On TechZing Podcast</a></li>
</ul>
<h5>Camping</h5>
<ul>
<li><a name='rc' href='http://github.com/camping/camping'>Ruby Camping Framework</a></li>
<li><a name='tacaab' href='http://github.com/techarch/camping-abingo'>Camping-ABingo repository on GitHub</a></li>
<li><a name='tacaabdo' href='http://camping-abingo.heroku.com/'>Camping-ABingo Demo On Heroku</a></li>
</ul>
<h5>Miscellaneous</h5>
<ul>
<li><a name='tz' 	href='http://techzinglive.com'>TechZing Podcast for web startup entrepreneurs</a></li>
<li><a name='lita' href='http://www.dehats.com/drupal/?q=node/58'>Lita, a SQLite administration tool</a></li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a href='https://blog.monnet-usa.com/?p=322'>A/B Test Your Ruby Camping Web App Using ABingo (Part 1)</a></li>
<li><a href='https://blog.monnet-usa.com/?p=223'>Visualize Application Metrics on NewRelic for your Ruby Camping Application</a></li>
</ul>
<p>					<a name='abcasrc'></a></p>
<h5>Source Code</h5>
<div   class='download_panel'>All source is available on GitHub:</p>
<ul>
						<a href='http://bit.ly/camping-abingo'>Camping ABingo <b>Plugin</b> library</a><br />
						<a href='http://bit.ly/cgabtst'>Camping ABingo <b>Test</b> Example</a>
					</div>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
							If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
						</div>
<div class="blog-msm-ad2">
								<a href="http://www.myskillsmap.com/signup?opt=trial&#038;origin=tabg"><br />
									<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
								</a>
						</div>
</p></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>A/B Test Your Ruby Camping Web App Using ABingo (Part 1)</title>
		<link>https://blog.monnet-usa.com/?p=322</link>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Thu, 02 Dec 2010 05:13:31 +0000</pubDate>
				<category><![CDATA[A/B Testing]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby Camping]]></category>
		<category><![CDATA[a/b testing]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=322</guid>

					<description><![CDATA[Intro Over the past few months, while listening to TechZing, a fantastic podcast for web startup entrepreneurs, the concept of A/B Testing keeps coming up as key technique to track and measure conversion of site visitors into potential or true customers. Performing A/B testing implies: Selecting content variations or use case variations to test Identifying [&#8230;]]]></description>
										<content:encoded><![CDATA[<style>
						h3 {	text-decoration: underline; }</p>
<p>						h4
						{
							font-size: 1.1em;
							margin:0 50px 0 15px;
						}</p>
<p>						h5 
						{
							margin:0 50px 0 50px;
						}</p>
<p>						.download_panel
						{
						background-color: #EDD6AD; 
						color: #555555; 
						font-weight:bold;
						text-align:center;
						margin:0 50px 0 50px;
						padding:6px;
						}</p>
<p>						.details_table 
						{border: 1px solid #f0f0f0;
						border-spacing: 1px;
						background-color:white;
						margin-left: 40px;
						}</p>
<p>						.details_table tr
						{
						vertical-align: top;
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.details_table th
						{
						background-color:lightgray;
						}</p>
<p>						.details_table td
						{
						border-bottom: 1px solid LightGoldenRodYellow;
						}</p>
<p>						.blog-msm-ad {
							background-color: #919191;
							border-top: 6px solid #E2E2E2;
							color: white;
							display: block;
							height: 40px;
							margin-left: 12px;
							margin-top: 20px;
							padding: 10px;
							width: 537px;							
						}</p>
<p>						.blog-msm-ad1 {
							float: left;
							width: 310px;
						}</p>
<p>						.blog-msm-ad2 {
							float: right;
							width: 225px;
						}</p>
<p>						.blog-msm-ad a {
							color: #A0D1F1;
							font-weight: bold;
						}</p>
</style>
<h3>Intro </h3>
<p>Over the past few months, while listening to <a href='#tz'>TechZing</a>, a fantastic podcast for web startup entrepreneurs, the concept of <a href='#abwp'>A/B Testing</a> keeps coming up as key technique to track and <b>measure conversion</b> of site <b>visitors</b> into potential or true <b>customers</b>. Performing A/B testing implies:
					</p>
<ol>
<li>Selecting <b>content variations</b> or <b>use case variations</b> to test</li>
<li>Identifying a couple <b>alternatives</b> for each test (a.k.a. experiments)
<p>						<i>Example of an experiment on the wording of a call to action button:</i><br />
						<img src='./wp-content/media/camping-abingo/camping-abingo-abtests-call-to-action-button.png'  width="90%" />
						</li>
<li><b>Trigger</b> a test on a given page by <b>selecting an alternative</b> for a given user</li>
<li><b>Track</b> any resulting <b>conversion for a given user</b> on a targetted page</li>
<li>Measure the <b>participation</b> in our tests</li>
<li>Measure the <b>conversion</b> in our tests</li>
</ol>
<div  class='download_panel'>Click <a href='#abcasrc'>here</a> if you want to skip straight to the <a href='#abcasrc'>ABingo Camping Plugin source code</a></div>
<h3>A/B Test Solutions</h3>
<p>Google provides very basic A/B Testing capabilities as part of the Google Analytics <a href="#abgg">Website Optimizer</a>. The downsides of that approach are:</p>
<ul>
<li>The tests (experiments), their alternatives, and corresponding urls have to be defined on the Google site</li>
<li>The resulting &#8220;test tracking Javascript snippets&#8221; have to be copy/pasted inside your own site</li>
<li>All the data remains locked in Google&#8217;s databases (although you can export it)</li>
</ul>
<p>If your web application is built on Ruby on Rails, you are in luck, as <a href="#pmz">Patrick McKenzie</a> has created <a href="#abingo">ABingo</a>, an excellent A/B testing framework plugin. ABingo even includes a dashboard to view the test participations and conversions. </p>
<p>Since I am a big fan of the lightweight Ruby <a href='#rc'>Camping Micro-Framework</a>, what I needed was an <a href='#tacaab'>ABingo Camping plugin</a>. Since none existed I emailed Patrick McKenzie to get his blessing and started to <a href='#abcasrc'>adapt</a> his plugin!</p>
<h3 style="page-break-before:always;">Starting With The End In Mind</h3>
<h4>ABingo Test Application</h4>
<p>To illustrate the usage of ABingo, we&#8217;ll use a simple tester representing a fictitious <b>SAAS Application</b>. From the <b>home</b> page we&#8217;ll be able to access the <b>landing</b> and corresponding <b>sign-up</b> pages that we want to <b>experiment with</b>.<br />
							<img src='./wp-content/media/camping-abingo/camping-abingo-test-nav-flow.png'  width="80%" /><br />
							We&#8217;ll also provide sign-in/sign-out options and a  link to the <b>ABingo dashboard</b> if the signed in user is the administrator.
					</p>
<h4>Objective: Increasing Our Sign-Ups</h4>
<p>To increase our sign-ups we will be experimenting first with different <b>calls to action</b> in our sign-up button.<br />
					Our experiment named <b>call_to_action</b> will randomly vary the text of the button. We track the selected option and track the conversion on our sign-up page. After running our experiment for a while we will be able to see on the dashboard which option generated the most conversion!</p>
<h4>The Conversion Funnel</h4>
<p>The <b>path</b> taken by a group of customers from the various options (A/B/C) of the <b>landing</b> page to our <b>sign-up </b> page is called a <b>conversion funnel</b>:<br />
					<img src='./wp-content/media/camping-abingo/camping-abingo-abtests-funnel.png'  width="90%" />
					</p>
<h3 style="page-break-before:always;">High-Level Implementation Synopsis</h3>
<p>Once ABingo is integrated in your application, tracking and measuring the conversion funnel will consist of 2 basic steps:</p>
<h4>Selecting an alternative for a given experiment</h4>
<p>In the <b>landing view</b> code we will invoke the ABingo <b>ab_test</b> API to choose an alternative for the <b>call_to_action</b> experiment based on an array of text options:</p>
<pre class="brush: ruby">
	def landing
		# ...

		signup_text = ab_test("call_to_action", 
								[ 	"Sign-Up Now!",
									"Try It For Free Now!",
									"Start Your Free Trial Now!",
								])
		
		a :href=>"/signup" do
			div.signup_btn!  signup_text
		end
		
		# ...
	end
	
</pre>
<p>It&#8217;s that easy! And as a side note an experiment alternative can be a simple boolean, an array of arbitrary values, or even a hash of options.</p>
<p></p>
<h4>Tracking the conversion for our experiment</h4>
<p>In the <b>SignUp</b> controller, before rendering the signup view we will invoke the <b>abingo!</b> API to indicate that a conversion just occurred on our <b>call_to_action</b> experiment:</p>
<pre class="brush: ruby">
	class SignUp < R '/signup'
		def get
			bingo! "call_to_action"
			
			render :signup
		end
	end
</pre>
<h4>Fun With Experiments!</h4>
<p>Now that you have seen how ridiculously simple it is to setup and track an experiment you'll want to try to run different types of experiments such as for example:</p>
<ul>
<li>different styles (size, color) for the sign-up button</li>
<li>special offers</li>
<li>different ways to present pricing options</li>
<li>etc.</li>
</ul>
<p>Example of a landing page with a <b>special_promo</b> experiment:<br />
						<img src='./wp-content/media/camping-abingo/camping-abingo-abtests-multiple-content-areas.png'  width="70%" />
					</p>
<h3>Reviewing A/B Test Results With The ABingo Dashboard</h4>
<p>The dashboard consists of a couple routes built using Camping controllers and views. Although we will walk through the setup of such a dashboard in our prototype app in a later article, here is a teaser screenshot:</p>
<p>					<img src='./wp-content/media/camping-abingo/camping-abingo-dashboard.png' /></p>
<p>The conclusions we can draw from these experiments are:</p>
<ol>
<li>For the <b>special_promo</b> experiment, the "true" alternative results in the most conversions (%)</li>
<li>For the <b>call_to_action</b> experiment, the "Start Your Free Trial Now!" alternative results in the most conversions (%)</li>
</ol>
<p>You can try the demo app yourself at: <a href="http://camping-abingo.heroku.com/">http://camping-abingo.heroku.com/</a>.</p>
<h3  style="page-break-before:always;">So What? </h3>
<ol>
<li>A/B testing is a key practice to improve usability as well as user conversion on a web application.</li>
<li>Patrick McKenzie's <a href='#abpmk'>ABingo</a> is a powerful A/B testing framework for Ruby apps.</li>
<li><a href='#abpmk'>ABingo</a> makes it easy to define and execute experiments with multiple alternatives.</li>
</ol>
<p>This introduction to ABingo should have given you a feel for how easy it is to add A/B testing capabilities to a Ruby <a href='#rc'>Camping</a> web application using the <a href='#tacaab'>ABingo Camping plugin</a>. <br />
					In a subsequent post I will cover the specific implementation steps to add ABingo to our test application. Stay tuned!
					</p>
<p>					<a name='abcasrc'></a></p>
<h5>Source Code</h5>
<div   class='download_panel'>All source is available on GitHub:</p>
<ul>
						<a href='http://bit.ly/camping-abingo'>Camping ABingo <b>Plugin</b> library</a><br />
						<a href='http://bit.ly/cgabtst'>Camping ABingo <b>Test</b> Example</a>
					</div>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>A/B Testing</h5>
<ul>
<li><a name='abwp' href='http://en.wikipedia.org/wiki/A/B_Testing'>A/B Testing Definition on Wikipedia</a></li>
<li><a name='abbasics' href='http://elem.com/~btilly/effective-ab-testing/'>Effective A/B Testing Basics (by Ben Tilly)</a></li>
<li><a name='abgg' href='https://www.google.com/analytics/siteopt/siteopt/help/overvw.html'>Google Website Optmizer</a></li>
<li><a name='abpmk' href='http://www.bingocardcreator.com/abingo'>ABingo A/B Testing Framework (by Patrick McKenzie)</a></li>
<li><a name='pmk' href='http://www.kalzumeus.com/'>Patrick McKenzie's Blog</a></li>
<li><a name='abpmktz' href='http://techzinglive.com/page/479/79-tz-interview-%e2%80%93-patrick-mckenzie-optimize-this'>Patrick McKenzie Interview On TechZing Podcast</a></li>
</ul>
<h5>Camping</h5>
<ul>
<li><a name='rc' href='http://github.com/camping/camping'>Ruby Camping Framework</a></li>
<li><a name='tacaab' href='http://github.com/techarch/camping-abingo'>Camping-ABingo repository on GitHub</a></li>
</ul>
<h5>Miscellaneous</h5>
<ul>
<li><a name='tz' 	href='http://techzinglive.com'>TechZing Podcast for web startup entrepreneurs</a></li>
<li><a name='lita' 	href='http://www.dehats.com/drupal/?q=node/58'>Lita, a SQLite administration tool</a></li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a href='https://blog.monnet-usa.com/?p=223'>Visualize Application Metrics on NewRelic for your Ruby Camping Application</a></li>
</ul>
<div class="blog-msm-ad">
<div class="blog-msm-ad1">
							If you enjoyed this post, I would love it if you could check out <a href="http://bit.ly/myskillsmap">mySkillsMap</a>, my skills management app.
						</div>
<div class="blog-msm-ad2">
								<a href="http://www.myskillsmap.com/signup?opt=trial&#038;origin=tabg"><br />
									<img src='./wp-content/media/msm/start-your-free-trial-now.png'  /><br />
								</a>
						</div>
</p></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Implementing Ruby Camping REST Services With RESTstop</title>
		<link>https://blog.monnet-usa.com/?p=298</link>
		
		<dc:creator><![CDATA[techarch]]></dc:creator>
		<pubDate>Wed, 23 Jun 2010 04:50:47 +0000</pubDate>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby Camping]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[camping]]></category>
		<category><![CDATA[reststop]]></category>
		<guid isPermaLink="false">http://blog.monnet-usa.com/?p=298</guid>

					<description><![CDATA[Intro It is pretty common nowadays for web applications and sites to expose a developer API to allow consumers to integrate their data with other application. Examples: Twitter, LinkedIn, Bit.ly, etc. Although there are various options for implementing web services, as of 2010, the REST protocol seems to have achieved a comfortable lead over other [&#8230;]]]></description>
										<content:encoded><![CDATA[<br />
<h3>Intro </h3>
<p>It is pretty common nowadays for web applications and sites to expose a developer API to allow consumers to integrate their data with other application. Examples: Twitter, LinkedIn, Bit.ly, etc. </p>
<p>Although there are various options for implementing web services, as of 2010, the <a href='#rest'>REST</a> protocol seems to have achieved a <b>comfortable lead</b> over other approaches for <b>Internet</b>-based <b>resource-oriented</b> services.</p>
<p><a href='#rs'>RESTstop</a> is a Ruby library making it easy to implement <a href='#rest'>REST</a> services<br />
					on top of the <a href='#rc'>Camping framework</a>.</p>
<p>					<img src='./wp-content/media/camping-reststop/reststop.png' style='margin-left:60px;'></p>
<h3>Web Services Implementation Options</h3>
<p>Before jumping to <a href='#rs'>RESTstop</a> (if you insist click <a href='#reststop-plugin'>here</a>), let&#8217;s do a brief review of the few options,<br />
					developers have historically leveraged to build web services:</p>
<ol>
<li><a href='#soap-svcs'>SOAP services</a>:  the API is <b>formally defined</b> using the WSDL format. API messages use a specific XML representation.<br />
						Additional services can be composed on top of the basic protocol to provide authentication, authorization, etc.<br />
						Although powerful, SOAP has proven <b>too complex</b> and <b>too heavy</b> for web developer APIs .<br />
						Also they require a full <b>SOAP-compatible client stack</b> for making them more difficult to call especially in the case of AJAX applications.<br />
						As a consequence, SOAP services tend to have been relegated to <b>intra-enterprise cross-application services</b>. </li>
<p></p>
<li><a href='#xml-svcs'>XML services</a>: the API is <b>not formally defined</b> but end-points and their inputs and outputs are usually documented on a developer site.<br />
						Each service has a given url and uses XML to represent messages. As such an <b>XML parser</b> is required to provide robust processing<br />
						especially if the data structures are complex and rely on namespaces.</li>
<p></p>
<li><a href='#json-svcs'>JSON services</a>: similarly to the XML services the API is also <b>not formally defined</b>.<br />
						Messages are represented as <a href='#json'>JSON</a> structures.<br />
						<a href='#json'>JSON</a> services lend themselves very well to <b>AJAX</b> calls from browser applications since<br />
						<a href='#json'>JSON</a> structures can be easily processed using basic Javascript.</li>
<p></p>
<li>APIs for web sites mostly need to expose &#8220;<a href='#resource'>resources</a>&#8221; as opposed to behaviors (e.g. : CRUD operations on Posts) </li>
</ol>
<h3>Camping for Web Services</h3>
<p>Since <a href='#rc'>Camping</a> is a generic Ruby web application framework, you can define service <a href='#routes'>endpoints as url routes</a>,<br />
					each mapped to a given <b>controller</b>.<br />
					An HTML-based view is not necessary obviously, so instead one option is to render the model<br />
					using the desired format: <b>XML</b> or <a href='#json'>JSON</a>.<br />
					Example:
					</p>
<pre class="brush: ruby">
gem 'camping' , '>= 2.0'	
%w(rubygems active_support active_support/json active_record camping camping/session markaby erb ).each { | lib | require lib }

Camping.goes :CampingJsonServices

module CampingJsonServices
	include Camping::Session

	def CampingJsonServices.create
	end

	module CampingJsonServices::Controllers

		class APIDateToday < R '/datetoday'
			def get
				@result = {:today=>Date.today.to_s}
				
				@headers['Content-Type'] = "application/json"
				@result.to_xml(:root=>'response')
			end
		end

		class APITimeNow < R '/timenow'
			def get
				@result = {:now=>Time.now.utc.to_s}
				
				@headers['Content-Type'] = "application/json"
				@result.to_json
			end
		end

	end
end	
</pre>
<p>Such as an approach is fine for <i>function-oriented APIs</i> but if we want to provide CRUD access to <a href='#resource'>resources</a>,<br />
					then a <a href='#rest'>REST</a> approach provides more structure. You can of course implement a <a href='#rest'>REST</a>-style API on your own<br />
					by overriding the route dispatch mechanism and mapping the HTTP verbs such as PUT and DELETE<br />
					to the appropriate route controller methods.
					</p>
<p>					<a name='reststop-plugin'></a>	</p>
<h3>RESTstop, a REST plugin for Camping</h3>
<p><a href='#mz'>Matt Zukowski</a> wrote the <a href='#rs'>RESTstop</a> library to easily provide access to <a href='#resource'>REST resources</a> using the underlying Camping route engine and controllers.<br />
					The idea was powerful yet simple, as a developer you would create a controller per <a href='#resource'>resource</a><br />
					and specify the <a href='#rest'>REST</a> nature of the route like so:</p>
<pre class="brush: ruby">
module Blog::Controllers
  extend Reststop::Controllers

	class Posts < REST 'posts'      
	end
end
</pre>
<p>Then similarly to the standard <b>get</b> and <b>post</b> methods of Camping controllers, you would create <b>CRUD-style</b> action methods<br />
					such as: <b>create</b>, <b>read</b>, <b>update</b>, <b>delete</b>, and <b>list</b>:</p>
<pre class="brush: ruby">
class Posts < REST 'posts'      
      # POST /posts
      def create 
      end

      # GET /posts/1
      # GET /posts/1.xml
      def read(post_id)
      end

      # PUT /posts/1
      def update(post_id)
      end

      # DELETE /posts/1
      def delete(post_id)
      end

      # GET /posts
      # GET /posts.xml
      def list
	end
end
</pre>
<p>Then once you had a controller, you would implement a <b>special type of view</b> appropriate for the format of the data you wanted to expose.<br />
					For example you could create views to render the data as XML or <a href='#json'>JSON</a> or any other format you liked.</p>
<pre class="brush: ruby">
module Blog::Views
  extend Reststop::Views
  
  module HTML
    include Blog::Controllers
    include Blog::Views
	
    def index
      if @posts.empty?
        p 'No posts found.'
      else
        for post in @posts
          _post(post)
        end
      end
      p { a 'Add', :href => R(Posts, 'new') }
    end
	
  end
  
  module XML
    include Blog::Controllers
    include Blog::Views
	
    def index
      @posts.to_xml(:root => 'blog')
    end
	
  end
  
  module JSON
    include Blog::Controllers
    include Blog::Views
	
    def index
      @posts.to_json
    end
  end
	
</pre>
<h3>The Inner Plumbing Of RESTstop</h3>
<p><a href='#rs'>RESTstop</a> is an interesting plugin to dissect as it is a good illustration of <a href='#metaprog'>meta-programming</a> in Ruby.<br />
					<a href='#mz'>Matt</a> took the following approach:</p>
<ol>
<li>Alias and override the base <b>service</b> method to save off the HTTP verb</li>
<li>Add a new route creation method called <b>REST</b> to replace the base <b>r</b> route creation method.<br />
							The new method will register all the expected REST resource routes and wire them up to the controller.</li>
<li>Default or decode the rendering format specified in the url (e.g. /posts.xml vs. /posts.json)</li>
<li>Structure the Views module according to the various formats to specify: HTML vs. XML vs. JSON</li>
<li>Render the controller output using the specified format</li>
</ol>
<p>I would definitely recommend that your read the plugin's source. At 449 lines with many comments<br />
					it is pretty easy to see how it actually works. This will also make it easier for you to troubleshoot your code when needed.</p>
<h3>Let's Create The REST Version Of The Blog Sample</h3>
<p>Here is an outline of the approach:</p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
<th>Area (Module)</th>
</tr>
<tr>
<td><a href='#todo1'>1</a></td>
<td>Plug in RESTstop into the app</td>
<td>Main app</td>
</tr>
<tr>
<td><a href='#todo2'>2</a></td>
<td>Plug in RESTstop into the Base</td>
<td>Base</td>
</tr>
<tr>
<td><a href='#todo3'>3</a></td>
<td>Plug in RESTstop into the Controllers</td>
<td>Controllers</td>
</tr>
<tr>
<td><a href='#todo4'>4</a></td>
<td>Create the REST <b>Sessions</b> controller</td>
<td>Controllers</td>
</tr>
<tr>
<td><a href='#todo5'>5</a></td>
<td>Plug in RESTstop into the Helpers</td>
<td>Helpers</td>
</tr>
<tr>
<td><a href='#todo6'>6</a></td>
<td>Plug in RESTstop into the Views</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo7'>7</a></td>
<td>Finish the REST <b>Sessions</b> controller</td>
<td>Controllers</td>
</tr>
<tr>
<td><a href='#todo8'>8</a></td>
<td>Add <b>JSON</b> support</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo9'>9</a></td>
<td>Create the REST <b>Posts</b> controller</td>
<td>Controllers</td>
</tr>
<tr>
<td><a href='#todo10'>10</a></td>
<td>Add an HTML view module for Posts</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo11'>11</a></td>
<td>Add an XML view module for Posts</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo12'>12</a></td>
<td>Add a JSON view module for Posts</td>
<td>Views</td>
</tr>
</table>
<p></p>
<p>					<a name='todo1'></a></p>
<h5>1. Plug In RESTstop</h5>
<p>Our first step is to install the gem and add a require for RESTstop:</p>
<pre class="brush: ruby">
gem install reststop
</pre>
<p>Now let's create a new Ruby source file and name it <b>camping-svcs.rb</b>.<br />
					Then let's require RESTstop and include its main module in the blog's main module.</p>
<pre class="brush: ruby">
require 'reststop'

Camping.goes :Blog

module Blog
  include Camping::Session
  include Reststop
end
</pre>
<p>					<a name='todo2'></a></p>
<h5>2.Plug in RESTstop into the Base</h5>
<p>Now we need to enhance the Base module, so let's specify it.<br />
					This is the place where we'll add most of the extensions code taking care of:</p>
<ul>
<li>Aliasing 3 methods: render, lookup, and service so RESTstop can "insert" its magic</li>
<li>Including Reststop::Base in the Base</li>
<li>Adapt the Camping lookup method to look for view methods inside the RESTstop-specific Views::HTML module</li>
</ul>
<p>So add the following code:</p>
<pre class="brush: ruby">
module Blog::Base
  alias camping_render render
  alias camping_lookup lookup	# @techarch: required if camping > 2.0
  alias camping_service service
  include Reststop::Base
  alias service reststop_service
  alias render reststop_render
  
	# Overrides the new Tilt-centric lookup method In camping
	# RESTstop needs to have a first try at looking up the view
	# located in the Views::HTML module. 
    def lookup(n)
      T.fetch(n.to_sym) do |k|
        t = Blog::Views::HTML.method_defined?(k) || camping_lookup(n)
      end
    end
end
</pre>
<p>					<a name='todo3'></a></p>
<h5>3. Plug in RESTstop into the Controllers</h5>
<p>Here we'll add an extend for the Reststop::Controllers.</p>
<pre class="brush: ruby">
module Blog::Controllers
  extend Reststop::Controllers
end
</pre>
<p>This will add 2 new methods</p>
<ul>
<li><b>determine_format</b> : will extract the service data format from the request url - e.g json from /posts.json</li>
<li><b>REST</b> : will allow definition of REST resources in our controller declarations - e.g. class Posts < REST 'posts'</li>
</ul>
<p>					<a name='todo4'></a></p>
<h5>4. Create the REST Sessions controller</h5>
<p>The <a href='#rcb'>Camping Blog example</a> has a simple <b>login system</b> built on top of the Camping session.<br />
					For our REST blog, we'll want to support both an interactive web app login (like in the original blog)<br />
					as well as a service-based login so that only authenticated applications can call our services.</p>
<p>So we'll expose a new REST resource called <b>Session</b>. Applications will be able to <b>create</b> and <b>delete</b> sessions -<br />
					to mirror the login and logout behavior. So let's create our first REST controller and name it <b>Sessions</b>:</p>
<pre class="brush: ruby">
    class Sessions < REST 'sessions'
	end
</pre>
<p>Now we just need to declare only a subset of the standard <b>CRUD</b> REST methods: <b>create</b>, and <b>delete</b>.<br />
					For now, let's just create the shell:</p>
<pre class="brush: ruby">
        # POST /sessions
        def create
        end   

        # DELETE /sessions
        def delete
        end
</pre>
<p>For the <b>create</b> method, we will lookup the user based on the user id and password.<br />
					If not found we'll return a 401 (unauthorized) error with a message.<br />
					If found, we'll create a Camping session and render a view we'll create in a bit called <b><a href='#todo6b'>user</a></b>.<br />
					Here is the code:</p>
<pre class="brush: ruby">
        # POST /sessions
        def create
          @user = User.find_by_username_and_password(input.username, input.password)

          if @user
            @state.user_id = @user.id
            render :user
          else
			r(401, 'Wrong username or password.')
          end
        end   
</pre>
<p>Let's test the error scenario. For that we'll use the following 2 tools:</p>
<ol>
<li>The <a href='#restr'>restr</a> gem. This is another nice library created by <a href='#mz'>Matt</a>.
<pre class="brush: ruby">gem install restr</pre>
<p>							We'll use the library from IRB as a simple REST client.</p>
</li>
<li>Pocket Soap's <a href='#tcpt'>TcpTrace</a>, a tool to inspect the contents of Tcp messages.<br />
						This will really help us troubleshoot the various interactions between client and service.</li>
</ol>
<p>Ok so let's start our camping app on the default 3301 port:</p>
<pre class="brush: ruby">
camping camping-svcs.rb
</pre>
<p>Now let's run <a href='#tcpt'>TcpTrace</a> and start a new trace listening on port 8080 and forwarding to port 3301. <br />
					<i>Note: we'll set our IRB-based client to post to port 8080).</i><br />
					<img src='./wp-content/media/camping-reststop/tcptrace-start.png'></p>
<p>Then start IRB and run the following statements to invoke <b>create</b> on the <b>Sessions</b> resource:</p>
<pre class="brush: ruby">
gem 'xml-simple'
gem 'restr'
require 'restr'

# Set the url of our resource (via port 8080 for TcpTrace)
u0 =  "http://localhost:8080/sessions.xml"

# Set the user name and incorrect password
o = { :username=>'admin', :password=>'wrong'}

# Post to the Sessions resource
p0 = Restr.post(u0,o)
</pre>
<p>In <a href='#tcpt'>TcpTrace</a> you should see the request and the response:<br />
				<img src='./wp-content/media/camping-reststop/tcptrace-session-create-error.png'>
				</p>
<p>In IRB you should also see the 401 error:<br />
				<img src='./wp-content/media/camping-reststop/restr-session-create-error.png' width='570px'>
				</p>
<p>So now we have successfully tested the error scenario!<br />
					Let's go back to our code and continue setting up our RESTstop code so we can then define our <b><a href='#todo6b'>user</a></b> view.</p>
<p>					<a name='todo5'></a></p>
<h5>5. Plug in RESTstop into the Helpers</h5>
<p>We'll explicitly define our Helpers module so we can:</p>
<ol>
<li>alias the R method since RESTstop will need to intercept it to provide a way to create routes to resources (e.g. R(Posts/1)</li>
<li>include the Reststop::Helpers module</li>
</ol>
<pre class="brush: ruby">
module CampingRestServices::Helpers
  alias_method :_R, :R
  remove_method :R
  include Reststop::Helpers
end
</pre>
<p>					<a name='todo6'></a></p>
<h5>6. Plug in RESTstop into the Views</h5>
<p>In the Views module, we'll first add an extend for the RESTstop Views module</p>
<pre class="brush: ruby">
module CampingRestServices::Views
  extend Reststop::Views
end
</pre>
<p>Then we'll create 3 sub-modules, one for each type of format we'll support: HTML, XML, and JSON.<br />
					We'll also indicate that HTML is the default format.<br />
					For the moment we'll just create shells:</p>
<pre class="brush: ruby">
module CampingRestServices::Views
  extend Reststop::Views
  
  module HTML
  end
  
  module XML
  end

  module JSON
  end
  
  default_format :HTML   
end  
</pre>
<p>					<a name='todo6b'></a></p>
<p>Since we needed to create a <b>user</b> view when successfully creating a Session resource,<br />
					let's create a user view method in the XML submodule. The code will just serialize the @user object to XML.</p>
<pre class="brush: ruby">
  module XML
  
	def user
		@user.to_xml(:root => 'user')
	end
	
  end
</pre>
<p>We're now ready to test the happy path!<br />
						So go back to your IRB session and evaluate the following statements:</p>
<pre class="brush: ruby">
# Set the user name and correct password
o = { :username=>'admin', :password=>'camping'}

# Post to the Sessions resource
p0 = Restr.post(u0,o)
</pre>
<p>In <a href='#tcpt'>TcpTrace</a> you should see the request and the response containing the serialized user:<br />
				<img src='./wp-content/media/camping-reststop/tcptrace-session-create.png'>
				</p>
<p>In IRB you should also see the returned user instance, deserialized from XML<br />
				<img src='./wp-content/media/camping-reststop/restr-session-create.png' width='570px'>
				</p>
<p>					<a name='todo7'></a></p>
<h5>7. Finish the REST <b>Sessions</b> controller</h5>
<p>The remaining part of our Sessions controller is the <b>delete</b> method.<br />
					Delete will terminate the session and return a 200 message to that effect:</p>
<pre class="brush: ruby">
    class Sessions < REST 'sessions'
        # ...   

        # DELETE /sessions
        def delete
          @state.user_id = nil
          r(200, 'Session terminated')
        end
    end
</pre>
<p>Let's test this out from IRB by evaluating the following statement to DELETE the current session:</p>
<pre class="brush: ruby">
p0=Restr.delete(u0,{})
</pre>
<p>In <a href='#tcpt'>TcpTrace</a> you should see the request and the response containing the session termination message:<br />
				<img src='./wp-content/media/camping-reststop/tcptrace-session-delete.png'>
				</p>
<p>In IRB you should also see the same message:<br />
				<img src='./wp-content/media/camping-reststop/restr-session-delete.png' width='570px'></p>
<p>				So here is a recap for what we have accomplished so far:</p>
<ol>
<li>We have plugged in RESTstop in the following modules:
<ul>
<li><a href='#todo1'>Main app</a></li>
<li><a href='#todo2'>Base</a></li>
<li><a href='#todo3'>Controllers</a></li>
<li><a href='#todo5'>Helpers</a></li>
<li><a href='#todo6'>Views</a></li>
</ul>
</li>
<li>We have created our first REST controller: <a href='#todo4'>Sessions</a> implementing the <a href='#todo4'>create</a> and <a href='#todo7'>delete</a> methods</li>
<li>We have created an XML submodule in our Views module to render the <a href='#todo6b'>user</a> XML view</li>
<li>We have monitored the message protocol using <a href='#tcpt'>TcpTrace</a></li>
<li>We tested the API using the <a href='#restr'>restr</a> client library</li>
</ol>
<p>					<a name='todo8'></a></p>
<h5>8. Add JSON Support</h5>
<p>Our Session resource can currently only be accessed via an XML REST interface.<br />
					So let's add <a href='#json'>JSON</a> support by adding a <b>user</b> view to the JSON submodule (within our Views module):</p>
<pre class="brush: ruby">
  module JSON
  
	def user
		@user.to_json
	end
	
  end
</pre>
<p>Let's go back to your IRB session and evaluate the following statements:</p>
<pre class="brush: ruby">
# Set the url for the JSON Resource format
u0b =  "http://localhost:8080/sessions.json"

# Post to the Sessions resource
p0=Restr.post(u0b,o)
</pre>
<p>In <a href='#tcpt'>TcpTrace</a> you should see the request and the response containing the serialized user in JSON format:<br />
				<img src='./wp-content/media/camping-reststop/tcptrace-session-create-json.png'>
				</p>
<p>In IRB you should also see the returned user instance, deserialized from JSON:<br />
				<img src='./wp-content/media/camping-reststop/restr-session-create-json.png' width='570px'>
				</p>
<p>At this stage, our service can provide authentication via the <b><a href='#todo4'>Sessions</a></b> resource using either an XML or JSON protocol.<br />
				I will leave the HTML implementation for the reader. The approach would include re-using the existing Login controller,<br />
				but the login view would be moved to the HTML submodule and could be modified to POST to the Sessions resource.</p>
<p>So we now have the basic building authentication block for the rest of the functionality for our service.<br />
				Although this would work fine, this approach is not very robust for industrial-strength services.<br />
				I would recommend using <b><a href='#caoauth'>OAuth</a></b> as it provides more features such as:</p>
<ul>
<li>per-user consumer app registration</li>
<li>token-based authorization</li>
<li>explicit user-based authorization of tokens</li>
</ul>
<p>I recently created an <b><a href='#caoauth'>OAuth plugin for Camping</a></b> so check out the details on this post <u><a href='#caoauth'>here</a></u>.</p>
<p>					<a name='todo9'></a></p>
<h5>9. Create the REST Posts controller</h5>
<p>We will model the <b>Posts</b> REST controller after the <b><a href='#todo4'>Sessions</a></b> controller, with a few new twists such as the<br />
					<b>read</b>, <b>update</b> and <b>list</b> methods.</p>
<p>Currently, in the <a href='#rcb'>Camping Blog example</a>, there are several controllers responsible for managing posts: Index, PostNew, PostN, and Edit.<br />
					We will combine them into a brand new REST controller called <b>Posts</b>. So let's define a <b>Posts controller</b> with a REST route of <u><b>'posts'</b></u>:</p>
<pre class="brush: ruby">
class Posts < R 'posts'
end
</pre>
<p>Now we just need to declare the standard <b>CRUD</b> REST methods: <b>create</b>, <b>read</b>, <b>update</b>, <b>delete</b>, and <b>list</b>.<br />
					For now, let's just create the shell:</p>
<pre class="brush: ruby">
class Posts < R 'posts'
      # POST /posts
      def create
      end

      # GET /posts/1 or 
      # GET /posts/1.xml or
      # GET /posts/1.json
      def read(post_id)
      end

      # PUT /posts/1
      def update(post_id)
      end

      # DELETE /posts/1
      def delete(post_id)
      end

      # GET /posts or
      # GET /posts.xml or
      # GET /posts.json
      def list
      end
end
</pre>
<p>					<a name='todo-list-c'></a>					</p>
<p>Let's start with the simplest method: <b>list</b>.<br />
					We will just take the code from the old <b>Index</b> controller's <b>get</b> method<br />
					(and later we'll move the <b><a href='#todo-index-v'>index</a></b> view method into the <b>HTML</b> submodule).</p>
<pre class="brush: ruby">
      # GET /posts
      # GET /posts.xml
      def list
        @posts = Post.all(:order => 'updated_at DESC')
        render :index
      end
</pre>
<p>					<a name='todo-create-c'></a>					</p>
<p>Now for the <b>create</b> method, we will start with the code from the old <b>PostNew</b> controller's <b>post</b> method.<br />
					But we will tweak the Post.create parameters list to accept either <b>input.post_title</b> (when coming from an HTML form)<br />
					or <b>input.title</b> (when coming from a REST service call). We'll do the same for the <b>body</b> input parameter. <br />
					Then we will adjust the redirect call to use the RESTstop-enhanced <b>R</b> route creation method as opposed<br />
					to redirecting to the old <b>PostN</b> controller.<br />
					So all in all the code will now look like this:</p>
<pre class="brush: ruby">
      # POST /posts
      def create
          require_login!
          @post = Post.create :title => (input.post_title || input.title),	
		  :body => (input.post_body || input.body),							
          :user_id => @state.user_id
		  
        redirect R(@post)	
      end
</pre>
<p>					<a name='todo-read-c'></a>					</p>
<p>The <b>read</b> method is easy as it is a straight copy paste from the old <b>PostN</b> controller's <b>get</b> method<br />
					(and later we'll move the <b><a href='#todo-view-v'>view</a></b> view method into the <b>HTML</b> submodule).</p>
<pre class="brush: ruby">
      # GET /posts/1
      # GET /posts/1.xml
      def read(post_id)
        @post = Post.find(post_id)

        render :view
      end
</pre>
<p>					<a name='todo-update-c'></a>					</p>
<p>For the <b>update</b> method, we'll use the same technique as for the <b>create</b> method:<br />
					we'll start with the code from the old <b>Edit</b> controller's <b>post</b> method and allow for the<br />
					variations in the input parameters (depending on whether we come from an HTML post or a REST post).<br />
					We'll also adapt the redirect to use the new <b>R</b> method. So the code should look like this:</p>
<pre class="brush: ruby">
      # PUT /posts/1
      def update(post_id)
        require_login!
        @post = Post.find(post_id)
        @post.update_attributes :title => (input.post_title || input.title),	
			:body => (input.post_body || input.body)								

		redirect R(@post)
      end
</pre>
<p>					<a name='todo-delete-c'></a>					</p>
<p>The original Camping blog does not have code to delete a post, but the code for our <b>delete</b> method<br />
					is pretty straightforward:</p>
<pre class="brush: ruby">
      # DELETE /posts/1
      def delete(post_id)
        require_login!
        @post = Post.find post_id

        if @post.destroy
          redirect R(Posts)
        else
          _error("Unable to delete post #{@post.id}", 500)
        end
      end
</pre>
<p>					<a name='todo-new-c'></a>					</p>
<p>We will need a route to create new blog entries via HTML, so let's add a <b>new</b> action method<br />
					to instantiate a new Post and render the <b><a href='#todo-add-v'>add</a></b> view method:</p>
<pre class="brush: ruby">
      # GET /posts/new
      def new
        require_login!
		@user = User.find @state.user_id	
        @post = Post.new
        render :add
      end
</pre>
<p>					<a name='todo-edit-c'></a>					</p>
<p>Then finally we will need a route to edit an existing blog entry via HTML, so let's add an <b>edit</b> action method<br />
					to lookup an existing Post by id and render it using the <b><a href='#todo-edit-v'>edit</a></b> view method:</p>
<pre class="brush: ruby">
      # GET /posts/1/edit
      def edit(post_id)
        require_login!
 		@user = User.find @state.user_id	
        @post = Post.find(post_id)
        render :edit
      end
</pre>
<p>					<a name='todo-utility-c'></a>					</p>
<p>To finish up the application, there a few more "utility" controllers we'll need such as:</p>
<ol>
<li>an Index controller for the "home"/"index" page</li>
<li>a Login controller</li>
<li>a Logout controller</li>
</ol>
<p>					<a name='todo-index-c'></a>					</p>
<p>So first let's copy but change the original Index controller so that it just redirects to the <u><b>/posts</b></u> route<br />
					since the logic is now in the <b>list</b> method of the new <b>Posts</b> REST controller.</p>
<pre class="brush: ruby">
    class Index
		def get
			redirect '/posts'
		end
	end
</pre>
<p>					<a name='todo-login-c'></a></p>
<p>Then, we need a <b>Login</b> controller to render the <b><a href='#todo-login-v'>login</a></b> HTML view:</p>
<pre class="brush: ruby">
	class Login < R '/login'
		def get
			render :login
		end
	end
</pre>
<p>					<a name='todo-logout-c'></a></p>
<p>And we also need a <b>Logout</b> controller to render the <b><a href='#todo-logout-v'>logout</a></b> HTML view:</p>
<pre class="brush: ruby">
	class Logout < R '/logout'
		def get
			render :logout
		end
	end
</pre>
<p>You can also migrate the original <b>Styles controller</b>, as well as the <b>CSS declarations</b> (located at the end of the original Camping blog source).</p>
<p>Before we start working on the views, let's define a couple login-related helper methods in our CampingRestServices::Helpers module:</p>
<ul>
<li>logged_in? : to test if we have a logged in user</li>
<li>require_login! : to force a redirect to the login page if we don't have a valid user session</li>
</ul>
<pre class="brush: ruby">
module CampingRestServices::Helpers
  # ...

  def logged_in?
    !!@state.user_id
  end

  def require_login!
    unless logged_in?
      redirect(R(CampingRestServices::Controllers::Login))
      throw :halt
    end
  end
end
</pre>
<p>We're now officially done with our Controllers module! :-)</p>
<p>					<a name='todo10'></a></p>
<h5>10. Add an HTML view module for Posts</h5>
<p>OK now that we have a functional Posts REST controller, we need to create the corresponding views<br />
					in the appropriate Views submodule (HTML vs. XML vs. JSON).</p>
<p>Let's start by migrating the old HTML views by copying the contents of the old Views module <u>into</u><br />
					the new <b>HTML</b> submodule</p>
<pre class="brush: ruby">
module CampingRestServices::Views
  extend Reststop::Views
  
  module HTML
	# PLACE THE OLD Views CODE HERE
  end
  
  # ...
  
  default_format :HTML   
end  
</pre>
<p>We will leave the <b>layout</b> view method unchanged.</p>
<p>Our first edit will be in the <b>index</b> method where we'll change the code to<br />
					create a route for the "<u><b>add one</b></u>" link to route to the '"<b>new</b>" action of our new <b>Posts</b> REST resource<br />
					as opposed to routing to the old <b>PostNew</b> controller.</p>
<p>					<a name='todo-index-v'></a>					</p>
<pre class="brush: ruby">
    def index
      if @posts.empty?
        h2 'No posts'
        p do
          text 'Could not find any posts. Feel free to '
          a 'add one', :href => R(Posts, 'new')
          text ' yourself. '
        end
      else
        @posts.each do |post|
          _post(post)
        end
      end
    end
</pre>
<p>					<a name='todo-login-v'></a>					</p>
<p>The next view method to change is <b>login</b>. In the original Camping version the form will post to the Login controller.<br />
					We now need it to post to the new <b>Sessions</b> REST resource. So let's adapt the code as follows:</p>
<pre class="brush: ruby">
    def login
      h2 'Login'
      p.info @info if @info
      
      form :action => R(Sessions), :method => 'post' do
        input :name => 'to', :type => 'hidden', :value => @to if @to
        
        label 'Username', :for => 'username'
        input :name => 'username', :id => 'username', :type => 'text'

        label 'Password', :for => 'password'
        input :name => 'password', :id => 'password', :type => 'password'

        input :type => 'submit', :class => 'submit', :value => 'Login'
      end
    end
</pre>
<p>Once the user has logged in we need to render the <b>user</b> HTML view<br />
					(if you remember we created an XML and JSON version but not an HTML one).<br />
					So let's add a quick view to greet the user and provide a link to the Posts page:</p>
<pre class="brush: ruby">
    def user
      h2 "Welcome #{@user.username}!"
      a 'View Posts', :href => '/posts'
    end
</pre>
<p>					<a name='todo-logout-v'></a>					</p>
<p>And we need to create a <b>logout</b> view too, with a form which once submitted<br />
					would invoke the <b>DELETE</b> HTTP verb on the <b>Sessions</b> REST controller:</p>
<pre class="brush: ruby">
    def logout
      h2 'Logout'
      
      form :action => R(Sessions), :method => 'delete' do
        input :type => 'submit', 
				:class => 'submit', 
				:value => 'Logout'
      end
    end
</pre>
<p>					<a name='todo-add-v'></a>					</p>
<p>For the <b>add</b> view, we'll only adjust the posting route<br />
					from the old <b>PostNew</b> controller to the new <b>Posts</b> REST controller:</p>
<pre class="brush: ruby">
    def add
      _form(@post, :action => R(Posts))
    end
</pre>
<p>					<a name='todo-edit-v'></a>					</p>
<p>For the <b>edit</b> view, we'll also adjust the posting route<br />
					from the old <b>Edit</b> controller to an item-specific action (using the post id) on the<br />
					new <b>Posts</b> REST controller using the <b>PUT</b> HTTP verb:</p>
<pre class="brush: ruby">
    def edit
      _form(@post, :action => R(@post), :method => :put) 
    end
</pre>
<p>					<a name='todo-view-v'></a>					</p>
<p>We will copy the <b>view</b> view as-is:</p>
<pre class="brush: ruby">
    def view
      _post(@post)
    end
</pre>
<p>For the <b>_post</b> partial view, we'll adjust the h2 title link<br />
					from the old <b>PostN</b> controller to an item-specific action (using the post id) on the<br />
					new <b>Posts</b> REST controller. And we'll add a statement to display the post's body:</p>
<pre class="brush: ruby">
    def _post(post)
      h2 { a post.title, :href => R(Posts, post.id) }
	  p { post.body }

      p.info do
        text "Written by <strong>#{post.user.username}</strong> "
        text post.updated_at.strftime('%B %M, %Y @ %H:%M ')
        _post_menu(post)
      end
      text post.html_body
    end
</pre>
<p>The next partial view to update is <b>_admin_menu</b>, where we'll adjust the link<br />
					from the old <b>PostNew</b> controller to the <b>new</b> action of the new <b>Posts</b> REST controller:</p>
<pre class="brush: ruby">
    def _admin_menu
      text [['Log out', R(Logout)], ['New', R(Posts, 'new')]].map { |name, to|
        capture { a name, :href => to}
      }.join(' &ndash; ')
    end
</pre>
<p>The last partial view to update is <b>_post_menu</b>, where we'll adjust the edit link<br />
					from the old <b>Edit</b> controller to an item-specific <b>edit</b> action (using the post id) on the<br />
					new <b>Posts</b> REST controller. And we'll also add a link to delete the blog post using<br />
					an item-specific <b>delete</b> action.</p>
<pre class="brush: ruby">
    def _post_menu(post)
      if logged_in?
        a '(edit)',   :href => R(Posts, post.id, 'edit')
		span ' | '
        a '(delete)', :href => R(Posts, post.id, 'delete')		
      end
    end
</pre>
<p>The <b>_form</b> partial view will most remain the same, except for a few visual tweaks:</p>
<pre class="brush: ruby">
    def _form(post, opts)
      form({:method => 'post'}.merge(opts)) do
        label 'Title:', :for => 'post_title'
        input :name => 'post_title', :id => 'post_title', :type => 'text', 
              :value => post.title
		br
		
        label 'Body:', :for => 'post_body'
        textarea post.body, :name => 'post_body', :id => 'post_body'
		br
		
        input :type => 'hidden', :name => 'post_id', :value => post.id
        input :type => 'submit', :class => 'submit', :value => 'Submit'
      end
    end
</pre>
<p>We're now officially done with our Views::HTML module!<br />
					So we should be able to test it out: start the Camping server and navigate to the app.<br />
					You should get the home/index page.<br />
					<img src='./wp-content/media/camping-reststop/ff-home.png' width='570px'>
					</p>
<p>At this point you should be able to "exercise" all aspects of the app, from login to add, edit, delete, and logout.<br />
					<img src='./wp-content/media/camping-reststop/ff-new.png' width='570px'>
					</p>
<p></p>
<p>					<a name='todo11'></a></p>
<h5>11. Add REST XML and JSON view modules for Posts</h5>
<p>The HTML submodule was the most complicated believe it or not! Adding the XML view support is very straightforward and consists of:</p>
<ol>
<li>a layout method whose only job is to yield the content</li>
<li>a <b>user</b> view which we already created earlier when testing the Sessions controller</li>
<li>an <b>index</b> view to return the list of posts formatted as XML</li>
<li>a <b>view</b> view to return the details of a given posts formatted as XML</li>
</ol>
<p>
						The submodule will look like this:
					</p>
<pre class="brush: ruby">
module CampingRestServices::Views
  extend Reststop::Views

  # ...
  
  module XML
    def layout
      yield
    end

	def user
		@user.to_xml(:root => 'user')
	end
	
    def index
      @posts.to_xml(:root => 'blog')
    end

    def view
      @post.to_xml(:root => 'post')
    end
  end

  # ...

end
</pre>
<p>To test the API you can either:</p>
<ol>
<li>Navigate to:
<pre class="brush: ruby">
http://localhost:3301/posts.xml
</pre>
<p>					<img src='./wp-content/media/camping-reststop/ff-list-xml.png' width='570px'>
							</li>
<li>Or use IRB and the RESTR client, by evaluating the following statements:
<pre class="brush: ruby">
u1="http://localhost:8080/posts.xml"

# Get all Posts resources
p1 = Restr.get(u1,o)
</pre>
<p>					<img src='./wp-content/media/camping-reststop/tcptrace-posts-list-xml.png' width='570px'></p>
</li>
</ol>
<p>Here are a few other examples to try out from IRB to test the create, read, update, delete methods:</p>
<pre class="brush: ruby">
p2={ :title=>'Brand new REST-issued post', 
	:body=>'RESTstop makes it happen!!!'} 

# Create a new resource
p2b=Restr.post(u1,p2)

# -----------------------------------------------------

u3 = "http://localhost:8080/posts/1.xml"
p3 = Restr.get(u3,o)

# Modify the title
p3['title']='UPDATED: ' + p3['title']

# Update the resource
p3b = Restr.put(u2,p3,o)

# -----------------------------------------------------

# Delete a resource
p4=Restr.delete(u3)
</pre>
<p>You have now successfully implemented the XML rendering!</p>
<p>					<a name='todo12'></a></p>
<h5>12. Add a JSON view module for Posts</h5>
<p>The JSON submodule will be as simple as the XML submodule and will look near identical except for the JSON serialization code:</p>
<pre class="brush: ruby">
module CampingRestServices::Views
  extend Reststop::Views

  # ...
  
  module JSON
    def layout
      yield
    end

	def user
		@user.to_json 
	end
	
    def index
      @posts.to_json
    end

    def view
      @post.to_json
    end
  end

  # ...
  
end
</pre>
<p>Again, to test the JSON API you can either:</p>
<ol>
<li>Navigate to the JSON version of the url:
<pre class="brush: ruby">
http://localhost:3301/posts.json
</pre>
<p>					<img src='./wp-content/media/camping-reststop/ff-list-json.png' width='570px'>
							</li>
<li>Or use IRB and the RESTR client, by evaluating the following statements:
<pre class="brush: ruby">
u1="http://localhost:8080/posts.json"

# Get all Posts resources
p1 = Restr.get(u1,o)
</pre>
<p>					<img src='./wp-content/media/camping-reststop/tcptrace-posts-list-json.png' width='570px'></p>
</li>
</ol>
<p>You have now successfully implemented the JSON rendering!</p>
<p></p>
<hr>
<h5>Overall Recap</h5>
<p>So when you need to implement your own REST Camping app, here are the basic steps to remember:</p>
<table class='details_table'>
<tr>
<th>#</th>
<th>To Do</th>
<th>Area (Module)</th>
</tr>
<tr>
<td><a href='#todo1'>1</a></td>
<td>Plug in RESTstop into the app</td>
<td>Main app</td>
</tr>
<tr>
<td><a href='#todo2'>2</a></td>
<td>Plug in RESTstop into the Base</td>
<td>Base</td>
</tr>
<tr>
<td><a href='#todo3'>3</a></td>
<td>Plug in RESTstop into the Controllers</td>
<td>Controllers</td>
</tr>
<tr>
<td><a href='#todo5'>4</a></td>
<td>Plug in RESTstop into the Helpers</td>
<td>Helpers</td>
</tr>
<tr>
<td><a href='#todo6'>5</a></td>
<td>Plug in RESTstop into the Views</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo4'>6</a></td>
<td>Create your REST resource controller</td>
<td>Controllers</td>
</tr>
<tr>
<td><a href='#todo10'>7</a></td>
<td>Add an HTML view module for your controller</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo11'>8</a></td>
<td>Add an XML view module for your controller</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo12'>9</a></td>
<td>Add a JSON view module for your controller</td>
<td>Views</td>
</tr>
<tr>
<td><a href='#todo4'>10</a></td>
<td>Either create a REST <b>Sessions</b> controller or implement OAuth</td>
<td>Controllers</td>
</tr>
</table>
<p>					<a name='sowhat'></a></p>
<h3>So What?</h3>
<p>Although you can create REST services "by hand" using either basic Ruby web server or using the Camping framework,<br />
					<a href='#rs'>RESTstop</a> brings you the following benefits:</p>
<ol>
<li>makes it easy to define REST controllers using <b>minimal syntax</b> like:
<pre class="brush: ruby">
class Posts < REST 'posts'
end
</pre>
</li>
<li>provides a simple <b>convention</b> for <b>CRUD</b> resource operations</li>
<li>delegates the API output format to the appropriate <b>format-specific view submodule</b></li>
<li>fits nicely within the overall Camping framework architecture</li>
</ol>
<p>So if you have been hesitant to provide a REST api in your Camping web application due to the anticipated complexity,<br />
					or if you want to create REST API separate from your web app, <a href='#rs'>RESTstop</a> is the right solution for you!</p>
<p>The only additional suggestion I would have is to consider using <a href='#caoauth'>OAuth</a> authorization framework<br />
					in conjunction with your REST API. This will increase the robustness and security of your service.</p>
<p>					<a name="referencesandresources" ></a></p>
<h3>References and Resources</h3>
<h5>REST</h5>
<ul>
<li><a name='rest' href='http://en.wikipedia.org/wiki/Representational_State_Transfer'>REST Definition on Wikipedia</a></li>
<li><a name='resource' href='http://en.wikipedia.org/wiki/Representational_State_Transfer#Guiding_principles_of_a_REST_interface'>REST resource</a></li>
<li><a name='dissertation' href='http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm'>Roy Fielding's dissertation on REST</a></li>
<li><a name='wife' href='http://tomayko.com/writings/rest-to-my-wife'>Ryan Tomayko's "How I explained REST to my wife"</a></li>
<li><a name='json' href='http://www.json.org/'>JSON</a></li>
</ul>
<h5>Camping</h5>
<ul>
<li><a name='rc' href='http://github.com/camping/camping'>Ruby Camping Framework</a></li>
<li><a name='rcb' href='http://github.com/camping/camping/examples/blog.rb'>Original Camping Blog example</a></li>
<li><a name='rcroutes' href='http://camping.rubyforge.org/book/02_getting_started.html#routes'>Camping controller routes</a></li>
<li><a name='json' href='http://www.json.org/'>JSON</a></li>
<li><a name='rs' href='http://bit.ly/bsCcsS'>RESTstop library on GitHub</a></li>
<li><a name='tacaoa' href='http://github.com/techarch/camping-oauth'>Camping-OAuth repository on GitHub</a></li>
</ul>
<h5>Tools</h5>
<ul>
<li><a name='jsonvrpn' href='https://addons.mozilla.org/firefox/addon/10869'>JSON Viewer plugin for FireFox</a></li>
<li><a name='jsonvr' href='http://jsonviewer.codeplex.com/'>JSON Viewer client</a></li>
<li><a name='restr' href='http://github.com/zuk/restr'>Matt's RESTr client</a></li>
<li><a name='tcpt' 	href='http://www.pocketsoap.com/tcptrace/'>TCP Trace</a></li>
</ul>
<p>					<a name="contributors" ></a></p>
<h5>Contributors/Ruby-ists</h5>
<ul>
<li><a name='mh' href='http://judofyr.net/'>Magnus Holm (@judofyr)</a> - Camping, ...</li>
<li><a name='mz' href='http://matt.zukowski.ca/'>Matt Zukowski</a> - RESTstop, RESTr, ...</li>
</ul>
<p>					<a name="metaprog" ></a></p>
<h5>Metaprogramming</h5>
<ul>
<li><a name='inex' href='http://railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/'>Include vs. Extend in Ruby (by John Nunemaker)</a></li>
<li><a name='momi' href='http://ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html#S2'>[Module] Mixins (in Programming Ruby)</a></li>
<li><a name='clex' href='http://ruby-doc.org/docs/ProgrammingRuby/html/classes.html#UD'>Extending Objects (in Programming Ruby)</a></li>
<li><a name='moev' href='http://www.ruby-doc.org/docs/ProgrammingRuby/ref_c_module.html#Module.module_eval'>Adding module behavior with module_eval (in Programming Ruby)</a></li>
<li><a name='iece' href='http://bmorearty.wordpress.com/2009/01/09/fun-with-rubys-instance_eval-and-class_eval/'>Fun with Ruby’s instance_eval and class_eval (by Brian Morearty)</a></li>
</ul>
<h5>My Other Related Posts:</h5>
<ul name="myotherrelatedposts">
<li><a name='caoauth' href='https://blog.monnet-usa.com/?p=293'>Easily Transform Your Ruby Camping App Into An OAuth Provider</a></li>
<li><a href='https://blog.monnet-usa.com/?p=288'>Camping light (nosql) with MongoDB</a></li>
<li><a href='https://blog.monnet-usa.com/?p=223'>Visualize Application Metrics on NewRelic for your Ruby Camping Application</a></li>
<li><a href='https://blog.monnet-usa.com/?p=166'>Running the Camping Microframework on IronRuby</a></li>
</ul>
<p>					<a name='oacasrc'></a></p>
<h5>Full Source Of The RESTstop Camping REST Services App</h5>
<p>Here is the full source (you can also download it from GitHub <a href='http://bit.ly/campingsvcs'>here</a>)</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
