{"id":368,"date":"2011-10-17T20:29:18","date_gmt":"2011-10-18T03:29:18","guid":{"rendered":"http:\/\/blog.monnet-usa.com\/?p=368"},"modified":"2011-10-30T06:51:25","modified_gmt":"2011-10-30T13:51:25","slug":"creating-rich-interactive-web-apps-with-knockout-js-part-2","status":"publish","type":"post","link":"https:\/\/blog.monnet-usa.com\/?p=368","title":{"rendered":"Creating Rich Interactive Web Apps With KnockOut.js &#8211; Part 2"},"content":{"rendered":"<style>\n\t\t\t\t\t\th3 {\ttext-decoration: underline; }<\/p>\n<p>\t\t\t\t\t\th5 {margin-left:20px !important;}<\/p>\n<p>\t\t\t\t\t\t.details_table \n\t\t\t\t\t\t{border: 1px solid #f0f0f0;\n\t\t\t\t\t\tborder-spacing: 1px;\n\t\t\t\t\t\tbackground-color:white;\n\t\t\t\t\t\tmargin-left: 40px;\n\t\t\t\t\t\t}<\/p>\n<p>\t\t\t\t\t\t.details_table tr\n\t\t\t\t\t\t{\n\t\t\t\t\t\tvertical-align: top;\n\t\t\t\t\t\tborder-bottom: 1px solid LightGoldenRodYellow;\n\t\t\t\t\t\t}<\/p>\n<p>\t\t\t\t\t\t.details_table th\n\t\t\t\t\t\t{\n\t\t\t\t\t\tbackground-color:lightgray;\n\t\t\t\t\t\t}<\/p>\n<p>\t\t\t\t\t\t.details_table td\n\t\t\t\t\t\t{\n\t\t\t\t\t\tborder-bottom: 1px solid LightGoldenRodYellow;\n\t\t\t\t\t\t}<\/p>\n<p>\t\t\t\t\t\t.download_panel\n\t\t\t\t\t\t{\n\t\t\t\t\t\tbackground-color: #EDD6AD; \n\t\t\t\t\t\tcolor: #555555; \n\t\t\t\t\t\tfont-weight:bold;\n\t\t\t\t\t\ttext-align:center;\n\t\t\t\t\t\tmargin:0 50px 0 50px;\n\t\t\t\t\t\tpadding:6px;\n\t\t\t\t\t\t}<\/p>\n<\/style>\n<h3>Intro<\/h3>\n<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>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/patterns.png\" \/><\/p>\n<p>In this second post, we will cover the following topics while creating a fun app:<\/p>\n<ul>\n<li>Architecting our  application so it can easily be extended over time<\/li>\n<li>Splitting the logic according to separations of concerns<\/li>\n<li>Incorporating rudimentary elements of usability<\/li>\n<\/ul>\n<h3>For The Price Of N Cups of Coffee &#8230;<\/h3>\n<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.\n\t\t\t\t\t<\/p>\n<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>\n<h3>Building Our App Step-By-Step<\/h3>\n<p>Here is an outline of the approach:<\/p>\n<table class='details_table'>\n<tr>\n<th>#<\/th>\n<th>To Do<\/th>\n<th>Area<\/th>\n<\/tr>\n<tr>\n<td><a href='#todo1'>1<\/a><\/td>\n<td>Create a Shell Application<\/td>\n<td>Main app<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo2'>2<\/a><\/td>\n<td>Organize our Application Code<\/td>\n<td>Main App<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo3'>3<\/a><\/td>\n<td>Create the Savings Goal View<\/td>\n<td>View<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo4'>4<\/a><\/td>\n<td>Create the Savings Goal ViewModel<\/td>\n<td>View Model<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo5'>5<\/a><\/td>\n<td>Create the Savings Goal View Mediator<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo6'>6<\/a><\/td>\n<td>Link the Page and the View Mediator<\/td>\n<td>Main App<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo7'>7<\/a><\/td>\n<td>Apply Data Masking Business Rules<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo8'>8<\/a><\/td>\n<td>Apply Custom Masking Rules<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo9'>9<\/a><\/td>\n<td>Applying Formatting Rules<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo10'>10<\/a><\/td>\n<td>Providing Visual Feedback Cues<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<\/table>\n<p>\n\t\t\t\t\tThanks 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 \/>\n\t\t\t\t\t<\/p>\n<p>\t\t\t\t\t<a name='todo1'><\/a><\/p>\n<h5>1. Create a Shell Application<\/h5>\n<p>Note: In this tutorial we will de-emphasize the server framework side and focus on browser considerations.<br \/>\n\t\t\t\t\tSo let&#8217;s start:<\/p>\n<ol>\n<li>Create a root folder for our application named <b>savings-goal-simulator<\/b><\/li>\n<li>Create a file named <b>index.html<\/b> for our main page<\/li>\n<li>Create a folder for our Javascript files named <b>scripts<\/b><\/li>\n<li>Create a sub-folder under <b>scripts<\/b> for our vendor Javascript libraries named <b>vendor<\/b><\/li>\n<li>Add the basic markup for a page in <b>index.html<\/b><\/li>\n<\/ol>\n<p>\t\t\t\t\t<a name='vendor-libraries'><\/a><\/p>\n<p>Ok, now we&#8217;re ready to add our key <b>external Javascript libraries<\/b>.<br \/>\n\t\t\t\t\tHere is the basic minimum we&#8217;ll need with a quick rationale as of why they will help us:<\/p>\n<table class='details_table'>\n<tr>\n<th>Library<\/th>\n<th>Purpose \/ Rationale<\/th>\n<\/tr>\n<tr>\n<td><a href='#js-modernizr'>Modernizr<\/a><\/td>\n<td>Detects HTML 5 support and provide IE shims<\/td>\n<\/tr>\n<tr>\n<td><a href='#jquery'>jQuery<\/a><\/td>\n<td>Main foundation (do I need to say more :-) ?!)<\/td>\n<\/tr>\n<tr>\n<td><a href='#jqueryui'>jQuery UI<\/a><\/td>\n<td>Prefabricated UI super-elements like tabs, accordions, sliders, etc.<\/td>\n<\/tr>\n<tr>\n<td><a href='#jquery-cookies'>jQuery Cookies<\/a><\/td>\n<td>Easy management of cookies<\/td>\n<\/tr>\n<tr>\n<td><a href='#jquery-hotkeys'>jQuery HotKeys<\/a><\/td>\n<td>Handling of keyboard shortcuts<\/td>\n<\/tr>\n<tr>\n<td><a href='#jquery-maskedinput'>jQuery Masked Input<\/a><\/td>\n<td>Allow creation of custom input masks<\/td>\n<\/tr>\n<tr>\n<td><a href='#jquery-validate'>jQuery Validate<\/a><\/td>\n<td>Validation framework<\/td>\n<\/tr>\n<tr>\n<td><a href='#js-accounting'>Accounting.js<\/a><\/td>\n<td>Allow formatting currency amounts<\/td>\n<\/tr>\n<tr>\n<td><a href='#js-currencymask'>CurrencyMaskJS<\/a><\/td>\n<td>Allow masked input of currency amounts<\/td>\n<\/tr>\n<tr>\n<td><a href='#jquery-jstorage'>jStorage<\/a><\/td>\n<td>Wrapper for local storage APIs<\/td>\n<\/tr>\n<\/table>\n<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>\n<p>\t\t\t\t\t<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 \/>\n\t\t\t\t\tFor 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 \/>\n\t\t\t\t\tSo we&#8217;ll need to include the script for <a href=\"#js-modernizr\">Modernizr<\/a> right at the beginning our our HEAD section.<\/p>\n<pre class=\"brush: html\">\r\n&lt;head&gt;\r\n\t&lt;!-- Important: Modernizr must be the very first script in HEAD --&gt;\r\n\t&lt;script src=\"scripts\/vendor\/modernizr.custom.min.js\"&gt;&lt;\/script&gt; \r\n\t\r\n\t&lt;!-- ... --&gt;\r\n&lt;\/head&gt;\t\r\n<\/pre>\n<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 \/>\n\t\t\t\t\tFor this app, I chose <a href='#labjs'>LABjs<\/a> as it is specializes only on loading and is commonly used.<br \/>\n\t\t\t\t\tBut note that you could use some of the conditional loading features of Modernizr, called <a href=\"http:\/\/yepnopejs.com\/\" target='_blank'>yepnope<\/a>.<br \/>\n\t\t\t\t\tI chose to keep things minimal for our app. ;-)\n\t\t\t\t\t<\/p>\n<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 \/>\n\t\t\t\t\tWe&#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>\n<pre class=\"brush: html\">\r\n&lt;head&gt;\r\n\t&lt;!-- Important: Modernizr must be the very first script in HEAD --&gt;\r\n\t&lt;script src=\"scripts\/vendor\/modernizr.custom.min.js\"&gt;&lt;\/script&gt; \r\n\t&lt;script src=\"LAB.js\"&gt;&lt;\/script&gt; &lt;!-- Important: must be the very first script in HEAD --&gt;\r\n\t&lt;script&gt;\r\n\t$LAB\r\n\t\t.script(\"http:\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/1.6.4\/jquery.min.js\").wait()\r\n\t\t.script(\"http:\/\/ajax.googleapis.com\/ajax\/libs\/jqueryui\/1.8.16\/jquery-ui.min.js\")\r\n\t\t.script(\"http:\/\/ajax.aspnetcdn.com\/ajax\/jquery.templates\/beta1\/jquery.tmpl.min.js\")\r\n\t\t.script(\"scripts\/vendor\/knockout-1.2.1.debug.js\").wait()\r\n\t\t.script(\"scripts\/vendor\/jquery.cookie.js\")\r\n\t\t.script(\"scripts\/vendor\/jquery.blockUI.js\")\r\n\t\t.script(\"scripts\/vendor\/jquery.hotkeys.js\")\r\n\t\t.script(\"scripts\/vendor\/jquery.maskedinput-1.3.min.js\")\r\n\t\t.script(\"scripts\/vendor\/jquery.validate.min.js\")\r\n\t\t.script(\"scripts\/vendor\/accounting.min.js\")\r\n\t\t.script(\"scripts\/vendor\/jstorage.min.js\")\r\n\t\t.script(\"scripts\/vendor\/raphael-min.js\").wait()\r\n\t\t.script(\"scripts\/vendor\/g.raphael-min.js\").wait()\r\n\t\t.script(\"scripts\/vendor\/g.line-min.js\").wait()\r\n\t\t.script(\"scripts\/application.js\").wait(function(){\r\n\t\t\t\/\/ When ALL scripts have been loaded AND executed:\r\n\t\t\tInitializeApplication();\r\n\t\t});\r\n\t&lt;\/script&gt;\r\n\t\r\n\t&lt;!-- CSS and other HEAD-specific tags --&gt;\r\n&lt;\/head&gt;\t\r\n<\/pre>\n<p>You will notice that I am assuming a specific directory structure for our locally hosted Javascript code<\/p>\n<ul>\n<li><b>scripts<\/b> is the root of all .js files<\/li>\n<ul>\n<li><b>Vendor<\/b> will host external vendor libraries not available on a CDN.<br \/>\n\t\t\t\t\t\t\t\tHaving all external JS libraries in a dedicated folder will keep our directory structure clean.<\/li>\n<li><b>ViewMediator<\/b> will include Javascript code <b>mediating<\/b> interactions between Views and ViewModels<\/li>\n<li><b>ViewModel<\/b> will include our ViewModel-specific Javascript code<\/li>\n<li><b>application.js<\/b> will be the main application .js file with an <b>InitializeApplication<\/b> function (called from our $LAB configuration)<\/li>\n<\/ul>\n<\/ul>\n<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 \/>\n\t\t\t\t\tYou can use the links in the <a href='#vendor-libraries'>External Javascript Libraries<\/a> table above.<\/p>\n<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>\n<pre class=\"brush: javascript\">\r\nfunction InitializeApplication() {\r\n\tif (typeof(console) != 'undefined' && console) \r\n\t\tconsole.info(\"InitializeApplication starting ...\");\r\n}\r\n<\/pre>\n<p>If you run the application you should see the informational message being displayed in the console.<br \/>\n\t\t\t\t\tAnd in Firefox Firebug, or on a WebKit browser you should see the parallel loading of the scripts.<\/p>\n<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 \/>\n\t\t\t\t\tWe&#8217;ll also create an <b>application.css<\/b> file for our application-specific styles.\n\t\t\t\t\t<\/p>\n<pre class=\"brush: html\">\r\n&lt;link href=\"css\/custom-theme\/jquery-ui-1.8.16.custom.css\" rel=\"stylesheet\" type=\"text\/css\"  \/&gt;\r\n&lt;link href=\"css\/application.css\" rel=\"stylesheet\" type=\"text\/css\"  \/&gt;\r\n<\/pre>\n<p>\t\t\t\t\t<a name='todo2'><\/a><\/p>\n<h5>2. Organize our Application Code<\/h5>\n<p>Since our application will very modular and encompass many functions or classes,<br \/>\n\t\t\t\t\twe&#8217;ll establish a namespace to provide some structure and avoid function name clashes.<br \/>\n\t\t\t\t\tYou can read more about how to implement namespaces in Javascript in the following two articles:<\/p>\n<ul>\n<li><a href='http:\/\/elegantcode.com\/2011\/01\/26\/basic-javascript-part-8-namespaces\/' target='_blank'>Elegant Code &#8211; Namespaces<a><\/li>\n<li><a href='http:\/\/stackoverflow.com\/questions\/881515\/javascript-namespace-declaration' target='_blank'>StackOverflow &#8220;Javascript Namespace Declaration&#8221;<\/a><\/li>\n<\/ul>\n<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 \/>\n\t\t\t\t\tfollowed by either <b>model<\/b> or <b>mediator<\/b> for ViewModel and ViewMediator respectively.<br \/>\n\t\t\t\t\tTo keep our markup free of Javascript logic, we&#8217;ll organize the application code in the following folders:<\/p>\n<ol>\n<li>application.js will contain only logic to initialize \/ setup the views and viewmodels<\/li>\n<li>ViewModel &#8211; this folder will contain several files:\n<ul>\n<li>sgs.model.common.js for reusable logic across all types of ViewModels<\/li>\n<li>one file for the page-level view model &#8211; e.g. sgs.model.index.js<\/li>\n<li>one file for each view-specific view model &#8211; e.g. sgs.model.savings-goal.js &#8211; <\/li>\n<\/ul>\n<\/li>\n<li>ViewMediator &#8211; this folder will contain several files:\n<ul>\n<li>sgs.mediator.common.js for reusable logic across all view mediators<\/li>\n<li>one file for the page-level view mediator &#8211; e.g. sgs.mediator.index.js<\/li>\n<li>one file for each view-specific view mediator &#8211; e.g. sgs.mediator.savings-goal.js &#8211; <\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<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>\n<pre class=\"brush: html\">\r\n&lt;head&gt;\r\n\t&lt;!-- ... --&gt;\r\n\t$LAB\r\n\t\t\/\/ ...\r\n\t\t.script(\"scripts\/viewmodel\/sgs.model.common.js\")\r\n\t\t.script(\"scripts\/viewmediator\/sgs.mediator.common.js\")\r\n\t\t.script(\"scripts\/application.js\").wait(function(){\r\n\t\t\t\/\/ When ALL scripts have been loaded AND executed:\r\n\t\t\tInitializeApplication();\r\n\t\t});\r\n\t&lt;\/script&gt;\r\n\t\r\n\t&lt;!-- ... --&gt;\r\n&lt;\/head&gt;\t\r\n<\/pre>\n<p>Here is a quick synopsis of the architecture for the first increment of our app:<\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-1.png\" \/><\/p>\n<p>\t\t\t\t\t<a name='todo3'><\/a><\/p>\n<h5>3. Create the Savings Goal View<\/h5>\n<p>Now that we have a minimal shell in <b>index.html<\/b>,<br \/>\n\t\t\t\t\tlet&#8217;s add a section tag to represent our first panel \/ view: the <b>savings-goal-view<\/b>.<br \/>\n\t\t\t\t\tThe view will let us enter a savings goal amout and a maximum number of months.<\/p>\n<pre class=\"brush: html\">\r\n&lt;body&gt;\r\n\t&lt;section id='savings-goal-view'&gt;\r\n\t&lt;\/section&gt;\r\n&lt;\/body&gt;\r\n<\/pre>\n<p>Now we can add the two input elements (<b>savings-goal-amount<\/b> and <b>savings-max-duration<\/b>).<br \/>\n\t\t\t\t\tAnd 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>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-1a.png\" \/><\/p>\n<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>\n<pre class=\"brush: html\">\r\n&lt;section id='savings-goal-view'&gt;\r\n\t&lt;label for=\"savings-goal-amount\"&gt;Savings Goal Amount:&lt;\/label&gt;\r\n\t&lt;input id=\"savings-goal-amount\" \/&gt;&lt;br\/&gt;\r\n\r\n\t&lt;label for=\"savings-max-duration\"&gt;Savings Max Duration (In Months):&lt;\/label&gt;\r\n\t&lt;input id=\"savings-max-duration\" \/&gt;&lt;br\/&gt;\r\n\r\n\t&lt;label for=\"savings-target-per-month\"&gt;Savings Target Per Month:&lt;\/label&gt;\r\n\t&lt;span id=\"savings-target-per-month\" \/&gt;&lt;br\/&gt;\r\n&lt;\/section&gt;\r\n<\/pre>\n<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>\n<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>\n<p>\t\t\t\t\t<a name='todo4'><\/a><\/p>\n<h5>4. Create the Savings Goal ViewModel<\/h5>\n<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>.\n\t\t\t\t\t<\/p>\n<p>Here is a diagram summarizing what we&#8217;re about to implement:<\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-todo4.png\" \/><\/p>\n<p>As we indicated earlier, we&#8217;ll use namespaces to structure our code and avoid name collisions with other libraries.<br \/>\n\t\t\t\t\tThere 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>\n<p>\t\t\t\t\tFor 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 \/>\n\t\t\t\t\tTo 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>\n<pre class=\"brush: javascript\">\r\n\/\/ Lazy initialize our namespace context: sgs.model.savingsgoal\r\nif (typeof(sgs) == 'undefined') sgs = { }\r\nif (typeof(sgs.model) == 'undefined') sgs.model = { }\r\nif (typeof(sgs.model.savingsgoal) == 'undefined') sgs.model.savingsgoal = { }\r\n<\/pre>\n<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>\n<pre class=\"brush: javascript\">\r\nsgs.model.savingsgoal.initializeViewModel = function (pageSettings) {\r\n\t\/\/ We can use properties of the pageSettings as default values for any of our ValueModels\r\n\t\/\/ If pageSettings are not provided we'll initialize an empty object\r\n\tif (typeof(pageSettings) == 'undefined') var pageSettings = { }\r\n\t\r\n\tvar viewModel = {\r\n\t\tsavingsGoalAmount: ko.observable(pageSettings.defaultSavingsGoal || 0), \/\/ dollars\r\n\t\tsavingsMaxDuration: ko.observable(6), \/\/ months\r\n\t};\r\n\t\r\n\treturn viewModel;\r\n}<\/pre>\n<p>So our viewModel is basically an object literal (hash) where each property value is a <b>value model<\/b>,<br \/>\n\t\t\t\t\timplemented 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>\n<p>Now let&#8217;s add a derived function (a.k.a. a dependent observable in KnockoutJS-speak) named <b>savingsTargetPerMonth<\/b>:\n\t\t\t\t\t<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.model.savingsgoal.initializeViewModel = function (pageSettings) {\r\n\t\/\/ We can use properties of the pageSettings as default values for any of our ValueModels\r\n\t\/\/ If pageSettings are not provided we'll initialize an empty object\r\n\tif (typeof(pageSettings) == 'undefined') var pageSettings = { }\r\n\t\r\n\tvar viewModel = {\r\n\t\tsavingsGoalAmount: ko.observable(pageSettings.defaultSavingsGoal || 0), \/\/ dollars\r\n\t\tsavingsMaxDuration: ko.observable(6), \/\/ months\r\n\t};\r\n\t\r\n\tviewModel.savingsTargetPerMonth = ko.dependentObservable(function() {\r\n\t\tvar result = 0;\r\n\t\tif (this.savingsMaxDuration() > 0) {\r\n\t\t\tresult = this.savingsGoalAmount() \/ this.savingsMaxDuration();\r\n\t\t}\r\n\t\treturn result;\r\n\t}, viewModel);\r\n\r\n\treturn viewModel;\r\n}\r\n<\/pre>\n<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>\n<p>Over time we can add more business logic to our <b>sgs.mode.savingsgoal<\/b> module.<\/p>\n<p>\t\t\t\t\t<a name='todo5'><\/a><\/p>\n<h5>5. Create the Savings Goal View Mediator<\/h5>\n<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 \/>\n\t\t\t\t\tThis 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>\n<p>Here is a diagram summarizing what we&#8217;re about to implement:<\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-todo5.png\" \/><\/p>\n<p>Let&#8217;s define our namespace:<\/p>\n<pre class=\"brush: javascript\">\r\n\/\/ Lazy initialize our namespace context: sgs.mediator.savingsgoal\r\nif (typeof(sgs) == 'undefined') sgs = { }\r\nif (typeof(sgs.mediator) == 'undefined') sgs.mediator = { }\r\nif (typeof(sgs.mediator.savingsgoal) == 'undefined') sgs.mediator.savingsgoal = { }\r\n\r\nif (typeof(console) != 'undefined' && console) console.info(\"sgs.mediator.savingsgoal loading!\");\r\n<\/pre>\n<p>Now as a convention, let&#8217;s create a new function for our mediator named <b>createViewMediator<\/b><br \/>\n\t\t\t\t\twhich we will eventually invoke from the <b>InitializeApplication<\/b> method in <b>application.js<\/b>.<br \/>\n\t\t\t\t\tThe createViewMediator function will have 3 responsibilities:<\/p>\n<ol>\n<li>Instantiate a view model for the savings goal view<\/li>\n<li>Declare the data-binding between the HTML elements of the view and their corresponding value models in the view model<\/li>\n<li>Ask KnockoutJS to make the bindings effective (they will be live right after that)<\/li>\n<li>Save off the view model so we can access it from other parts of the app<\/li>\n<\/ol>\n<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>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ Create the view Savings Goal view-specific view model\r\n\tvar viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);\r\n}\r\n<\/pre>\n<p>Now let&#8217;s declare each of the 3 data-bindings we need:<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ Create the view Savings Goal view-specific view model\r\n\tvar viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);\r\n\t\r\n\t\/\/ Declare the HTML element-level data bindings\r\n\t$(\"#savings-goal-amount\").attr(\"data-bind\",\"value: savingsGoalAmount\");\r\n\t$(\"#savings-max-duration\").attr(\"data-bind\",\"value: savingsMaxDuration\");\r\n\t$(\"#savings-target-per-month\").attr(\"data-bind\",\"text: savingsTargetPerMonth()\");\r\n}\r\n<\/pre>\n<p>Now we&#8217;ll ask KnockoutJS to &#8220;apply&#8221;, i.e. register \/ enable our bindings. <\/p>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ Create the view Savings Goal view-specific view model\r\n\tvar viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);\r\n\t\r\n\t\/\/ Declare the HTML element-level data bindings\r\n\t$(\"#savings-goal-amount\").attr(\"data-bind\",\"value: savingsGoalAmount\");\r\n\t$(\"#savings-max-duration\").attr(\"data-bind\",\"value: savingsMaxDuration\");\r\n\t$(\"#savings-target-per-month\").attr(\"data-bind\",\"text: savingsTargetPerMonth()\");\r\n\t\r\n\t\/\/ Ask KnockoutJS to data-bind the view model to the view\r\n\tvar viewNode = $('#savings-goal-view')[0];\r\n\tko.applyBindings(viewModel, viewNode);\r\n}\r\n<\/pre>\n<p>This is where KnockoutJS is performing some heavy lifting behind the covers such as:<\/p>\n<ul>\n<li>Setting observers on the actual HTML elements<\/li>\n<li>Connecting these observers with the value models of the view model<\/li>\n<li>Getting the initial value of each value model<\/li>\n<li>Initializing each HTML element with that corresponding initial value<\/li>\n<\/ul>\n<p>To make it possible to store and retrieve our view model later we&#8217;ll leverage the jQuery data API.<br \/>\n\t\t\t\t\tSo 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>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.getViewModel = function() {\r\n\treturn $(document).data(\"sgs.model.savingsgoal.viewmodel\");\r\n}\r\n\r\nsgs.mediator.savingsgoal.setViewModel = function(viewModel) {\r\n\t$(document).data(\"sgs.model.savingsgoal.viewmodel\", viewModel);\r\n}\r\n<\/pre>\n<p>Now we can use the setViewModel function inside createViewMediator to save off our freshly-created view model.<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ Create the view Savings Goal view-specific view model\r\n\tvar viewModel = sgs.model.savingsgoal.initializeViewModel(pageSettings);\r\n\t\r\n\t\/\/ Declare the HTML element-level data bindings\r\n\t$(\"#savings-goal-amount\").attr(\"data-bind\",\"value: savingsGoalAmount\");\r\n\t$(\"#savings-max-duration\").attr(\"data-bind\",\"value: savingsMaxDuration\");\r\n\t$(\"#savings-target-per-month\").attr(\"data-bind\",\"text: savingsTargetPerMonth()\");\r\n\t\r\n\t\/\/ Ask KnockoutJS to data-bind the view model to the view\r\n\tvar viewNode = $('#savings-goal-view')[0];\r\n\tko.applyBindings(viewModel, viewNode);\r\n\r\n\t\/\/ Save the view model\r\n\tsgs.mediator.savingsgoal.setViewModel(viewModel);\t\r\n\r\n\tif (typeof(console) != 'undefined' && console) console.info(\"sgs.mediator.savingsgoal ready!\");\r\n}\r\n<\/pre>\n<p>\t\t\t\t\t<a name='todo6'><\/a><\/p>\n<h5>6. Link the Page and the View Mediator<\/h5>\n<p>Here is a diagram summarizing how we&#8217;ll be linking our parts:<\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-todo6.png\" \/><\/p>\n<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>\n<pre class=\"brush: javascript\">\r\nfunction InitializeApplication() {\r\n\tif (typeof(console) != 'undefined' && console) \r\n\t\tconsole.info(\"InitializeApplication starting ...\");\r\n\t\t\r\n\t\/\/ Initialize our page-wide settings\r\n\tvar pageSettings = { defaultSavingsGoal: 500 }\r\n\t\r\n\t\/\/ Create \/ launch our view mediator(s)\r\n\tsgs.mediator.savingsgoal.createViewMediator(pageSettings);\r\n\r\n\tif (typeof(console) != 'undefined' && console) \r\n\t\tconsole.info(\"InitializeApplication done ...\");\t\r\n}\r\n<\/pre>\n<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:\n\t\t\t\t\t<\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-1b.png\" \/><\/p>\n<p>\t\t\t\t\t<a name='todo7'><\/a><\/p>\n<h5>7. Apply Data Formatting \/ Masking Business Rules<\/h5>\n<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 \/>\n\t\t\t\t\tTo 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 \/>\n\t\t\t\t\tSince 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 \/>\n\t\t\t\t\tSo 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>\n<pre class=\"brush: html\">\r\n&lt;head&gt;\r\n\t&lt;!-- ... --&gt;\r\n\t$LAB\r\n\t\t\/\/ ...\r\n\t\t.script(\"scripts\/vendor\/currency-mask-0.5.0-min.js\").wait()\r\n\t\t.script(\"scripts\/application.js\").wait(function(){\r\n\t\t\t\/\/ When ALL scripts have been loaded AND executed:\r\n\t\t\tInitializeApplication();\r\n\t\t});\r\n\t&lt;\/script&gt;\r\n\t\r\n\t&lt;!-- ... --&gt;\r\n&lt;\/head&gt;\t\r\n<\/pre>\n<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>\n<pre class=\"brush: javascript\">\r\n    var savingsGoalAmountMask = new Mask(\"$#,###\", \"number\");\r\n    savingsGoalAmountMask.attach($(\"#savings-goal-amount\")[0]);\r\n<\/pre>\n<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>\n<pre class=\"brush: javascript\">\r\nsgs.model.savingsgoal.initializeViewModel = function (pageSettings) {\r\n\t\/\/ ...\r\n\r\n\tvar viewModel = {\r\n\t\tsavingsGoalAmountFormatted: ko.observable(\"\"), \r\n\t\tsavingsGoalAmountMask: new Mask(\"$#,###\", \"number\"),\r\n\t\t\/\/ ...\r\n\t};\r\n\t\r\n\t\/\/ ...\r\n}\t\r\n<\/pre>\n<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>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ ...\r\n\r\n\t\/\/ Declare the HTML element-level data bindings\r\n\t\/\/ ...\r\n\t\r\n\t\/\/ Apply masking to the savings goal amount input field\r\n    viewModel.savingsGoalAmountMask.attach($(\"#savings-goal-amount\")[0]);\r\n\r\n\t\/\/ ...\r\n}\t\r\n<\/pre>\n<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>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-2.png\" \/><\/p>\n<p>But &#8230; we just introduced an issue (see the infamous NAN displayed in the Savings Target Per Month)!<br \/>\n\t\t\t\t\tWell, once formatted the savingsGoalAmount value model will now be a string containing currency and thousands delimiter characters.<br \/>\n\t\t\t\t\tSo let&#8217;s recognize that semantic change by re-naming our <b>savingsGoalAmount<\/b> value model as <b>savingsGoalAmountFormatted<\/b> value model:<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.model.savingsgoal.initializeViewModel = function (pageSettings) {\r\n\t\/\/ ...\r\n\t\r\n\tvar viewModel = {\r\n\t\tsavingsGoalAmountFormatted: ko.observable(pageSettings.defaultSavingsGoal || 0), \/\/ dollars\r\n\t\t\/\/ ...\r\n\t};\r\n<\/pre>\n<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 \/>\n\t\t\t\t\tKnockoutJS 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:\n\t\t\t\t\t<\/p>\n<ul>\n<li><b>owner<\/b> &#8211; will specify the value of <b>this<\/b><\/li>\n<li><b>read<\/b> &#8211; a function which can perform some post-processing and ultimately return the value of the observable<\/li>\n<li><b>write<\/b> &#8211; a function which can perform some pre-processing of a value and ultimately store it<\/li>\n<\/ul>\n<p>So here is a skeleton of what the savingsGoalAmount value model would look like as a dependentObservable:<\/p>\n<pre class=\"brush: javascript\">\r\nviewModel.savingsGoalAmount = ko.dependentObservable({\r\n\towner: viewModel,\r\n\tread: function () {\r\n\t\t\/\/ some post processing code\r\n\t},\r\n\twrite: function (value) {\r\n\t\t\/\/ some pre processing code\r\n\t}\r\n});\t\r\n<\/pre>\n<p>Let&#8217;s tackle the <b>read<\/b> function first. It will need to:<\/p>\n<ul>\n<li>Get the current value model from <b>savingsGoalAmountFormatted<\/b><\/li>\n<li>Ask the savingsGoalAmountMask for a stripped (unformatted) value<\/li>\n<li>Return a valid float value<\/li>\n<\/ul>\n<p>Here is what the code looks like for the &#8220;read&#8221;:<\/p>\n<pre class=\"brush: javascript\">\r\n\tread: function () {\r\n\t\t\/\/ Get the current formatted value model \r\n\t\t\/\/ Important Note: Even though we don't use the formatted_amt variable\r\n\t\t\/\/ in the rest of the function, we need to let KnockoutJS \"know\"\r\n\t\t\/\/ that this closure has a dependency on savingsGoalAmountFormatted\r\n\t\t\/\/ otherwise the closure will never be invoked on a read.\r\n\t\tvar formatted_amt = this.savingsGoalAmountFormatted();\r\n\r\n\t\t\/\/ Unformat the value\r\n\t\tvar amt = this.savingsGoalAmountMask.strippedValue;\r\n\t\t\r\n\t\t\/\/ Convert the result to a float\r\n\t\tif (amt.length == 0) { amt = 0 };\r\n\t\treturn parseFloat(amt);\r\n\t},\r\n<\/pre>\n<p>Now let&#8217;s tackle the <b>write<\/b> function first. It will need to:<\/p>\n<ul>\n<li>Ask the savingsGoalAmountMask to format the value<\/li>\n<li>Set the <b>savingsGoalAmountFormatted<\/b> to the formatted value<\/li>\n<li>Return the passed value<\/li>\n<\/ul>\n<p>Here is what the code looks like for the &#8220;write&#8221;:<\/p>\n<pre class=\"brush: javascript\">\r\n\twrite: function (value) {\r\n\t\t\/\/ Format the passed in value using the mask\r\n\t\tvar formatted_value = this.savingsGoalAmountMask.updateFormattedValue(value);\r\n\t\t\r\n\t\t\/\/ Update the savingsGoalAmountFormatted value model\r\n\t\tthis.savingsGoalAmountFormatted(formatted_value);\r\n\t\treturn value;\r\n\t}\r\n<\/pre>\n<p>The complete and refactored savingsGoalAmount dependentObservable will now look like this:<\/p>\n<pre class=\"brush: javascript\">\r\nviewModel.savingsGoalAmount = ko.dependentObservable({\r\n\towner: viewModel,\r\n\tread: function () {\r\n\t\t\/\/ Get the current formatted value model\r\n\t\tvar formatted_amt = this.savingsGoalAmountFormatted();\r\n\t\t\r\n\t\t\/\/ Unformat the value\r\n\t\tvar amt = this.savingsGoalAmountMask.strippedValue;\r\n\t\t\r\n\t\t\/\/ Convert the result to a float\r\n\t\tif (amt.length == 0) { amt = 0 };\r\n\t\treturn parseFloat(amt);\r\n\t},\r\n\twrite: function (value) {\r\n\t\t\/\/ Format the passed in value using the mask\r\n\t\tvar formatted_value = this.savingsGoalAmountMask.updateFormattedValue(value);\r\n\t\t\r\n\t\t\/\/ Update the savingsGoalAmountFormatted value model\r\n\t\tthis.savingsGoalAmountFormatted(formatted_value);\r\n\t\treturn value;\r\n\t}\r\n});\t\r\n<\/pre>\n<p>Now refreshing the index.html page should allow you to enter amounts and see the calculated value!<\/p>\n<p>Here is a diagram summarizing how we restructured the various parts using the dependent observables and the mask:<\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-todo7.png\" \/><\/p>\n<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 \/>\n\t\t\t\t\tIn that case the mask will be a little simpler since we need at most 2 digits.<\/p>\n<p>\t\t\t\t\t<a name='todo8'><\/a><\/p>\n<h3>8. Apply Custom Masking Rules<\/h3>\n<p>For custom masking needs, such as for example a phone number, social security id, special identifier,<br \/>\n\t\t\t\t\tI strongly recommend <a href=\"http:\/\/digitalbush.com\/about\/\" target=\"_blank\">Josh Bush<\/a>&#8216; <a href=\"#jquery-maskedinput\">Masked Input Plugin<\/a>.\n\t\t\t\t\t<\/p>\n<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>\n<p>\t\t\t\t\t<a name='todo9'><\/a><\/p>\n<h3>9. Applying Formatting Rules<\/h3>\n<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>\n<ul>\n<li>Apply formatting to the float inside savingsTargetPerMonth<\/li>\n<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>\n<\/ul>\n<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.\n\t\t\t\t\t<\/p>\n<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>\n<pre class=\"brush: javascript\">\r\n\t\tvar result = this.savingsGoalAmount() \/ this.savingsMaxDuration();\r\n\t\tvar formattedResult = accounting.formatMoney(result, \"$\", 2, \",\", \".\");  ;\r\n\t\treturn formattedResult;\r\n<\/pre>\n<p>Approach 2 would require us to add a new dependentObservable named savingsTargetPerMonthFormatted in our savings goal view model:<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.model.savingsgoal.initializeViewModel = function (pageSettings) {\r\n\t\/\/ ...\r\n\t\r\n\tviewModel.savingsTargetPerMonthFormatted = ko.dependentObservable(function() {\r\n\t\tvar result = 0;\r\n\t\tif (this.savingsMaxDuration() > 0) {\r\n\t\t\tresult = this.savingsGoalAmount() \/ this.savingsMaxDuration();\r\n\t\t}\r\n\t\tvar formattedResult = accounting.formatMoney(result, \"$\", 2, \",\", \".\");  ;\r\n\t\treturn formattedResult;\r\n\t}, viewModel);\r\n}\r\n<\/pre>\n<p>And we then need to update the data-binding code in the <b>createViewMediator<\/b> function of our mediator module:<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ ...\r\n\t\r\n\t$(\"#savings-target-per-month\").attr(\"data-bind\",\"text: savingsTargetPerMonthFormatted()\");\r\n\t\r\n\t\/\/ ...\r\n}\r\n<\/pre>\n<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>\n<p>\t\t\t\t\t<a name='todo10'><\/a><\/p>\n<h3>10. Applying Visual Feedback Cues<\/h3>\n<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>\n<pre class=\"brush: javascript\">\r\n\t\t$(\"#savings-target-per-month\")\r\n\t\t\t.effect('highlight', { color: 'LightGreen' }, 3000); \/\/ for 3 seconds\r\n<\/pre>\n<p>Logically the code belongs to the mediator, so let&#8217;s <b>subscribe<\/b> to the <b>savingsTargetPerMonthFormatted<\/b> value model changes<br \/>\n\t\t\t\t\tinside our <b>createViewMediator<\/b> function.<\/p>\n<pre class=\"brush: javascript\">\r\nsgs.mediator.savingsgoal.createViewMediator = function (pageSettings) {\r\n\t\/\/ ...\r\n\r\n\t\/\/ Subscribe to interesting value model changes\r\n\tviewModel.savingsTargetPerMonthFormatted.subscribe(function() {\r\n\t\t$(\"#savings-target-per-month\")\r\n\t\t\t.effect('highlight', { color: 'LightGreen' }, 3000); \/\/ for 3 seconds\r\n\t});\r\n\t\r\n\t\/\/ ...\r\n}\r\n<\/pre>\n<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>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/savings-goal-simulator-part1-3.png\" \/><\/p>\n<hr>\n<h5>Overall Recap<\/h5>\n<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 \/>\n\t\t\t\t\tSo here is a quick recap of the steps we followed:<\/p>\n<table class='details_table'>\n<tr>\n<th>#<\/th>\n<th>To Do<\/th>\n<th>Area (Module)<\/th>\n<\/tr>\n<tr>\n<td><a href='#todo1'>1<\/a><\/td>\n<td>Create a Shell Application<\/td>\n<td>Main app<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo2'>2<\/a><\/td>\n<td>Organize your Application Code<\/td>\n<td>Main App<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo3'>3<\/a><\/td>\n<td>Break down each independent panel into Views<\/td>\n<td>View<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo4'>4<\/a><\/td>\n<td>Create a ViewModel for each View<\/td>\n<td>View Model<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo5'>5<\/a><\/td>\n<td>Create a View Mediator for each View<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo6'>6<\/a><\/td>\n<td>Link the Page and the View Mediator(s)<\/td>\n<td>Main App<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo7'>7<\/a><\/td>\n<td>Apply Data Formatting \/ Masking Business Rules<\/td>\n<td>View<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo8'>8<\/a><\/td>\n<td>Apply Custom Masking Rules<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo9'>9<\/a><\/td>\n<td>Applying Formatting Rules<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<tr>\n<td><a href='#todo10'>10<\/a><\/td>\n<td>Providing Visual Feedback Cues<\/td>\n<td>View Mediator<\/td>\n<\/tr>\n<\/table>\n<p>\t\t\t\t\t<a name='sowhat'><\/a><\/p>\n<h3>So What?<\/h3>\n<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>\n<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>\n<p>We have focused on a one-view increment for the app but in Part 3 we will cover the following topics:<\/p>\n<ul>\n<li>Adding more views, viewmodels and mediators to our basic app<\/li>\n<li>Sharing data across views and mediators<\/li>\n<li>Implementing masking and formatting<\/li>\n<li>Incorporating rudimentary elements of usability<\/li>\n<li>&#8230; and more!<\/li>\n<\/ul>\n<p>So stay tuned!<\/p>\n<p>\t\t\t\t\t<a name=\"referencesandresources\" ><\/a><\/p>\n<h3>References and Resources<\/h3>\n<h5>Patterns<\/h5>\n<ul>\n<li><a name='mvvmp' href='http:\/\/en.wikipedia.org\/wiki\/Model_View_ViewModel'>Model View &#8211; ViewModel Pattern<\/a><\/li>\n<li><a name='mvcp' href='http:\/\/heim.ifi.uio.no\/~trygver\/themes\/mvc\/mvc-index.html'>MVC Xerox Parc 1978-79<\/a><\/li>\n<li><a name='mvcp' href='http:\/\/c2.com\/cgi\/wiki?ModelViewController'>MVC Pattern<\/a><\/li>\n<li><a name='obp' href='http:\/\/c2.com\/cgi\/wiki?ObserverPattern'>Observer Pattern<\/a><\/li>\n<li><a name='psp' href='http:\/\/c2.com\/cgi\/wiki?PublishSubscribeModel'>Publish Subscribe Pattern<\/a><\/li>\n<li><a name='vmp' href='http:\/\/c2.com\/cgi\/wiki?ValueModel'>Value Model Pattern<\/a><\/li>\n<li><a name='dbp' href='http:\/\/c2.com\/cgi\/wiki?DataBinding'>Data Binding Pattern<\/a><\/li>\n<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>\n<li><a name='ns-objectliteral' href='http:\/\/stackoverflow.com\/questions\/881515\/javascript-namespace-declaration\/881556#881556'>Namespacing using Object Literals<\/a><\/li>\n<li><a name='ns-function' href='http:\/\/stackoverflow.com\/questions\/881515\/javascript-namespace-declaration\/881611#881611'>Namespacing using Functions<\/a><\/li>\n<\/ul>\n<h5>Frameworks And Blogs<\/h5>\n<ul>\n<li><a name='ko' href='http:\/\/knockoutjs.com\/'>KnockoutJS<\/a><\/li>\n<li><a name='lko' href='http:\/\/learn.knockoutjs.com\/'>Learn KnockoutJS (Interactive Tutorial \/ Playground)<\/a><\/li>\n<li><a name='jq' href='http:\/\/jquery.com\/'>jQuery<\/a><\/li>\n<li><a name='jqui' href='http:\/\/jqueryui.com\/'>jQuery UI<\/a><\/li>\n<li><a name='jqt' href='http:\/\/api.jquery.com\/jQuery.template\/'>jQuery Template<\/a><\/li>\n<li><a name='jqtapi' href='http:\/\/api.jquery.com\/jQuery.template\/'>jQuery Template API<\/a><\/li>\n<li><a name='ss' href='http:\/\/blog.stevensanderson.com\/'>Knock Me Out (Steve Sanderson&#8217;s Blog)<\/a><\/li>\n<li><a name='kmo' href='http:\/\/www.knockmeout.net\/'>Knock Me Out (Ryan Niemeyer&#8217;s Blog)<\/a><\/li>\n<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>\n<\/ul>\n<p>\t\t\t\t\t<a name=\"javascript-loaders\" ><\/a><\/p>\n<h5>Javascript Loaders<\/h5>\n<ul>\n<li><a name='headjs' href='http:\/\/headjs.com\/' target='_blank'>HeadJS<\/a><\/li>\n<li><a name='labjs' href='http:\/\/labjs.com\/' target='_blank'>LABjs<\/a><\/li>\n<li><a name='lazyload' href='https:\/\/github.com\/rgrove\/lazyload' target='_blank'>LazyLoad<\/a><\/li>\n<li><a name='jquery-cookie' href='https:\/\/github.com\/carhartl\/jquery-cookie\/blob\/master\/jquery.cookie.js' target='_blank'>jQuery Cookie<\/a><\/li>\n<\/ul>\n<p>\t\t\t\t\t<a name=\"jquery-plugins\" ><\/a><\/p>\n<h5>jQuery Plugins<\/h5>\n<ul>\n<li><a name='jquery-blockui' href='http:\/\/jquery.malsup.com\/block\/' target='_blank'>jQuery BlockUI<\/a><\/li>\n<li><a name='jquery-cookie' href='https:\/\/github.com\/carhartl\/jquery-cookie\/blob\/master\/jquery.cookie.js' target='_blank'>jQuery Cookie<\/a><\/li>\n<li><a name='jquery-datatables' href='http:\/\/datatables.net\/' target='_blank'>jQuery DataTables<\/a><\/li>\n<li><a name='jquery-hotkeys' href='https:\/\/github.com\/tzuryby\/jquery.hotkeys' target='_blank'>jQuery HotKeys<\/a><\/li>\n<li><a name='jquery-tree' href='http:\/\/www.jstree.com\/' target='_blank'>jQuery jsTree<\/a><\/li>\n<li><a name='jquery-validate' href='http:\/\/plugins.jquery.com\/project\/jqueryvalidate' target='_blank'>jQuery Validate<\/a><\/li>\n<\/ul>\n<p>\t\t\t\t\t<a name=\"other-js-libraries\" ><\/a><\/p>\n<h5>Other Javascript Libraries<\/h5>\n<ul>\n<li><a name='js-modernizr' href='http:\/\/www.modernizr.com\/' target='_blank'>Modernizr<\/a><\/li>\n<li><a name='js-blockui' href='http:\/\/jquery.malsup.com\/block\/' target='_blank'>BlockUI<\/a><\/li>\n<li><a name='js-accounting' href='http:\/\/josscrowcroft.github.com\/accounting.js\/' target='_blank'>Accounting.js<\/a><\/li>\n<li><a name='js-currencymask' href='https:\/\/github.com\/techarch\/CurrencyMaskJS' target='_blank'>CurrencyMask JS<\/a><\/li>\n<li><a name='jquery-maskedinput' href='http:\/\/digitalbush.com\/projects\/masked-input-plugin\/' target='_blank'>Masked Input<\/a><\/li>\n<li><a name='js-raphael' href='http:\/\/raphaeljs.com\/' target='_blank'>Raphael JS<\/a><\/li>\n<li><a name='js-graphael' href='http:\/\/g.raphaeljs.com\/' target='_blank'>gRaphael JS<\/a><\/li>\n<li><a name='js-storage' href='https:\/\/github.com\/andris9\/jStorage' target='_blank'>jStorage<\/a><\/li>\n<li><a name='js-underscore' href='http:\/\/documentcloud.github.com\/underscore\/' target='_blank'>Underscore<\/a><\/li>\n<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>\n<\/ul>\n<p>\t\t\t\t\t<a name=\"js-test-frameworks\" ><\/a><\/p>\n<h5>Javascript Test Frameworks<\/h5>\n<ul>\n<li><a name='js-jasmine' href='http:\/\/http:\/\/pivotal.github.com\/jasmine\/' target='_blank'>Jasmine, BDD for Javascript<\/a><\/li>\n<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>\n<\/ul>\n<h5>My Other Related Posts:<\/h5>\n<ul name=\"myotherrelatedposts\">\n<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>\n<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>\n<\/ul>\n<p>\t\t\t\t\t<a name='kodemosrc'><\/a><\/p>\n<h5>Full Source Of The Savings Goal Simulator (KnockoutJS Demo)<\/h5>\n<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>\n<p>\t\t\t\t\t<a name='credits'><\/a><\/p>\n<h5>Credits<\/h5>\n<p>Special thanks for <a href=\"http:\/\/blog.logeek.fr\/\" target='_blank'>Thibaut Barr\u00e8re<\/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>\n<div class=\"blog-msm-ad\">\n<div class=\"blog-msm-ad1\">\n\t\t\t\t\t\t\tIf 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.\n\t\t\t\t\t\t<\/div>\n<div class=\"blog-msm-ad2\">\n\t\t\t\t\t\t\t\t<a href=\"http:\/\/www.myskillsmap.com\/take-charge-of-your-skills-development\"><br \/>\n\t\t\t\t\t\t\t\t\t<img src='.\/wp-content\/media\/msm\/start-your-free-trial-now.png'  \/><br \/>\n\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t<\/div>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,59,47,46,4],"tags":[],"class_list":["post-368","post","type-post","status-publish","format-standard","hentry","category-ajax","category-javascript","category-patterns","category-rich-web-apps","category-tools"],"_links":{"self":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=368"}],"version-history":[{"count":33,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/368\/revisions"}],"predecessor-version":[{"id":387,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/368\/revisions\/387"}],"wp:attachment":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}