{"id":354,"date":"2011-09-17T14:35:28","date_gmt":"2011-09-17T21:35:28","guid":{"rendered":"http:\/\/blog.monnet-usa.com\/?p=354"},"modified":"2011-09-17T14:35:28","modified_gmt":"2011-09-17T21:35:28","slug":"creating-rich-interactive-web-apps-with-knockoutjs-part-1","status":"publish","type":"post","link":"https:\/\/blog.monnet-usa.com\/?p=354","title":{"rendered":"Creating Rich Interactive Web Apps With KnockoutJS &#8211; Part 1"},"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>\n\t\t\t\t\tWith the advent of online games, social apps, Flash\/AIR apps, and rich instant-feedback sites<br \/>\n\t\t\t\t\tlike Google Search and GMail, consumers are demanding more and more interactivity.\n\t\t\t\t\t<\/p>\n<p>While interacting with your app customer now expect:<\/p>\n<ul>\n<li>Browser-side processing (calculation, business rules, &#8230;)<\/li>\n<li>Instant validation <\/li>\n<li>Instant visual feedback: animation\/effect while making changes (add\/remove\/update)<\/li>\n<li>Dynamic clues on what to do next<\/li>\n<li>More same \/ on page functionality (without the need to refresh or navigate to other pages)<\/li>\n<\/ul>\n<p>For a while adding a sprinkling of AJAX and localized visual refresh using jQuery UI was sufficient.<br \/>\n\t\t\t\t\tBut richer application interactions introduce more elaborate technical approaches: <br \/>\n\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/browser-side-app-stack.png\" \/>\n\t\t\t\t\t<\/p>\n<ul>\n<li>Present more related data at the same time<\/li>\n<li>Leverage graphs and other data visualization techniques<\/li>\n<li>Offer more on-page functionality<\/li>\n<li>Allow interactions with one panel to cause updates on other panels<\/li>\n<li>Support asynchronous back-end interactions<\/li>\n<\/ul>\n<h3>Extending the <a href=\"#mvcp\">Model View Controller Pattern<\/a><\/h3>\n<p>\n\t\t\t\t\tHere 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.):\n\t\t\t\t\t<\/p>\n<ul>\n<li>The routing engine identifies the appropriate controller<\/li>\n<li>The controller retrieves the model<\/li>\n<li>The view engine renders the view<\/li>\n<li>The view contains HTML, CSS, and Javascript code<\/li>\n<li>Rich browser-side applications typically have event handlers to allow page-level interactions to<br \/>\n\t\t\t\t\t\t\thandle validation, hide\/show elements, perform some processing \/ calculations, executebusiness rules, invoke AJAX services, update content<\/li>\n<\/ul>\n<p>\n\t\t\t\t\tNote that the last bullet represents quite a bit of logic (possibly in the 500 to several thousand lines of Javascript code).<br \/>\n\t\t\t\t\tThe logic gets even more complex once you have multiple panels and sets of model elements.<br \/>\n\t\t\t\t\tIf your AJAX services return complex objects you also need to keep track of these objects,<br \/>\n\t\t\t\t\ttheir binding to panel elements\/controls, and their inter-dependencies \/ impact on each other when a change occurs.<\/br><\/p>\n<p>\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/web-app-architecture.png\" \/><\/p>\n<p><b>Key take-away:<\/b><br \/>\n\t\t\t\t\tWe 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>\n<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 \/>\n\t\t\t\t\tLet&#8217;s break things down:\n\t\t\t\t\t<\/p>\n<p>\t\t\t\t\t<a id=\"breakdown\"><\/a><\/p>\n<ol>\n<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 \/>\n\t\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/viewmodel-data-elements.png\" \/><br \/>\n\t\t\t\t\t\t<u>Benefits:<\/u><\/p>\n<ul>\n<li><b>Partitioning<\/b>: each page \/ page can have its own clean model<\/li>\n<li><b>Testability<\/b>: the View and ViewModel can be tested independently from the server logic<\/li>\n<li><b>Modularity<\/b>: ViewModels code can be namespaced and contained in their own <b>.js<\/b> file<\/li>\n<\/ul>\n<p>\n\t\t\t\t\t\t<\/li>\n<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 \/>\n\t\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/viewmodel-observables.png\" \/><br \/>\n\t\t\t\t\t\t<u>Benefits:<\/u><\/p>\n<ul>\n<li><b>Fast UI<\/b>: derived values or content can be produced on-the-fly based on observed attributes<\/li>\n<li><b>Increased responsiveness<\/b>: asynchronous server interactions can be triggered in the background and cause ViewModels to be updated<\/li>\n<\/ul>\n<p>\n\t\t\t\t\t\t<\/li>\n<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 \/>\n\t\t\t\t\t\tThis allows a clean separation between logic related to the ViewModel (calculations, derivations, retrieval, server interaction) and UI-specific presentation logic.<br \/>\n\t\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/viewmodel-data-binding.png\" \/><br \/>\n\t\t\t\t\t\t<u>Benefits:<\/u><\/p>\n<ul>\n<li><b>Synchronization<\/b>: HTML elements and ViewModel attributes are kept in synch<\/li>\n<li><b>Instant visual feedback<\/b>: elements on the page can update visually as you interact \/ update data<\/li>\n<\/ul>\n<p>\n\t\t\t\t\t\t<\/li>\n<\/ol>\n<h3>Introducing KnockOutJS<\/h3>\n<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 \/>\n\t\t\t\t\tFor more details, check out the <a href=\"#ko\">KnockOutJS<\/a> site as well as the <a href=\"#lko\">Learning Playground<\/a>.<br \/>\n\t\t\t\t\tLet&#8217;s dig into the basic infrastructure provided by KnockOutJS and then we&#8217;ll build up to more complex scenarios.\n\t\t\t\t\t<\/p>\n<p>\t\t\t\t\t<a id=\"ko-basics\"><\/a><\/p>\n<h4>Basics<\/h4>\n<ol>\n<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:\n<pre class=\"brush: javascript\">\r\nvar viewModel = {\r\n\tsavingGoalAmount: ko.observable(500), \/\/ dollars\r\n\t\/\/ ... more attributes ...\r\n};\r\n<\/pre>\n<p>\t\t\t\t\t\t\tThe example ViewModel has one attribute: savingGoalAmount, with an initial value of 500.<br \/>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t<\/li>\n<li>You can programmatically <b>&#8220;subscribe&#8221;<\/b> to changes in a ViewModel attribute (a Value Model) like this:\n<pre class=\"brush: javascript\">\r\n\/\/ Set up the ViewModel\r\nvar viewModel = {\r\n\tsavingGoalAmount: ko.observable(500), \/\/ dollars\r\n\t\/\/ ... more attributes ...\r\n};\r\n\r\nviewModel.savingGoalAmount.subscribe(function(newValue) {\r\n\t\/\/ Show the updated value on the FireBug's console\r\n\tconsole.info(\"savingGoalAmount is now \" + newValue);\r\n});\r\n\r\n\/\/ Get KnockoutJS to apply bindings \/ subscriptions\r\nko.applyBindings(viewModel);\t\r\n\r\n\/\/ Test by changing the amount\r\nviewModel.savingGoalAmount(600); \/\/ Should display in the console\r\n<\/pre>\n<p>\t\t\t\t\t\t\tThe <b>subscribe<\/b> function takes a callback function it will invoke upon any change on the value of the savingGoalAmount Value Model.<br \/>\n\t\t\t\t\t\t\tThe <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>\n<\/li>\n<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\n<pre class=\"brush: html\" >\r\n<input id=\"saving-goal-amount\" \r\n\t\t\tsize=\"5\" pattern=\"[0-9]{5}\" min=\"0\" max=\"99999\"\r\n\t\t\tdata-bind=\"value: savingGoalAmount\" \/>\t\r\n<\/pre>\n<p>\t\t\t\t\t\tKnockoutJS uses the <b>data-bind<\/b> attribute to let us specify the type of binding needed.<br \/>\n\t\t\t\t\t\tIn this example we&#8217;re binding the <b>value<\/b> of the INPUT element to the savingGoalAmount Value Model.<br \/>\n\t\t\t\t\t\tWe&#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>\n<p>\t\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/basic-data-binding-example.png\" \/><br \/>\n\t\t\t\t\t\tNote 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>\n<pre class=\"brush: javascript\">\r\n$(\"#saving-goal-amount\")\r\n\t.attr(\"data-bind\",\"value: savingGoalAmount\");\r\n<\/pre>\n<p>\t\t\t\t\t\tYou 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>).\n\t\t\t\t\t\t<\/li>\n<\/ol>\n<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>\n<p>\n\t\t\t\t\t<a id=\"ko-building-up\"><\/a><\/p>\n<h4>Building Up<\/h4>\n<p>Now that we have a basic understanding of KnockoutJS, let&#8217;s add a few more building blocks:<\/p>\n<ol>\n<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>:\n<pre class=\"brush: javascript\">\r\nvar viewModel = {\r\n\tsavingGoalObjectives: ko.observableArray([ 'Discretionary', 'Expensive Purchase', 'Investment']),\r\n\t\/\/ ... more attributes ...\r\n};\r\n<\/pre>\n<p>\t\t\t\t\t\tAdding \/ removing items in the array will cause KnockoutJS to trigger an update to all observers of this Value Model.<br \/>\n\t\t\t\t\t\t\n\t\t\t\t\t\t<\/li>\n<li>In addition to attributes (Value Models), ViewModels can expose &#8220;<b>behaviors<\/b>&#8221; such as:\n<ul>\n<li>Derived attributes, resulting from a calculation, or a business rule.<br \/>\n\t\t\t\t\t\t\t\t\tKnockoutJS refers to them as <a href=\"http:\/\/knockoutjs.com\/documentation\/dependentObservables.html\" target=\"_blank\">dependentObservables<\/a>:<\/p>\n<pre class=\"brush: javascript\">\r\nvar viewModel = {\r\n\tsavingGoalAmount: ko.observable(500), \/\/ dollars\r\n\tsavingMaxDuration: ko.observable(6), \/\/ dollars\r\n\t\/\/ ... more attributes ...\r\n};\r\n\r\n\/\/ Derived data\r\nviewModel.savingTargetPerMonth = ko.dependentObservable(function() {\r\n\treturn this.savingGoalAmount() \/ this.savingMaxDuration();\r\n}, viewModel)\r\n<\/pre>\n<p>\t\t\t\t\t\t\t\t\tWhenever either savingGoalAmount or savingMaxDuration change, the derived savingTargetPerMonth function will be re-evaluated.<br \/>\n\t\t\t\t\t\t\t\t\tIf savingTargetPerMonth is data-bound to the UI, the corresponding element will redisplay.<br \/>\n\t\t\t\t\t\t\t\t\tNote that you can create dependentObservable functions on top of dependent observables or plain observables!<br \/>\n<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/advanced-derived-attribute.png\" \/>\n\t\t\t\t\t\t\t\t\t<\/li>\n<li>Formatted version of the data\n<pre class=\"brush: javascript\">\r\nvar viewModel = {\r\n\tsavingGoalAmount: ko.observable(500), \/\/ dollars\r\n\t\/\/ ... more attributes ...\r\n};\r\n\r\n\/\/ Derived formatted display data\r\nviewModel.savingGoalAmountAsCurrency = ko.dependentObservable(function() {\r\n\treturn accounting.formatMoney(this.savingGoalAmount(), \r\n\t\t\t\"$\", 2, \",\", \".\");  ;\r\n}, viewModel)\r\n<\/pre>\n<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>\n<\/li>\n<li>Add \/ remove logic on arrays\n<pre class=\"brush: javascript\">\r\nvar viewModel = {\r\n\tmyItems: ko.observableArray(),\r\n\t\/\/ ... more attributes ...\r\n};\r\n\r\n\/\/ Add \/ remove behaviors \r\nviewModel.addItem = function (newItem) {\r\n\tvar valid = validateItem(newItem); \/\/ custom logic\r\n\tif (valid) {\r\n\t\tthis.myItems.push(newItem);\r\n\t}\r\n}\r\n<\/pre>\n<p>\t\t\t\t\t\t\t\t\t\tIn this example, <b>addItem<\/b> is a custom behavior attached to the ViewModel which can be invoked to add new valid items.\n\t\t\t\t\t\t\t\t\t<\/li>\n<li>Any other business logic related to an overall ViewModel\n<pre class=\"brush: javascript\">\r\nvar viewModel = {\r\n\tsavingGoalAmount: ko.observable(500), \/\/ dollars\r\n\t\/\/ ... more attributes ...\r\n};\r\n\r\nviewModel.reset = function() {\r\n\tthis.savingGoalAmount(500);\r\n}\r\n<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>To allow other parts of our browser-side logic to access our ViewModels, we need to have a way to access them.<br \/>\n\t\t\t\t\t\tWe can save ViewModels in the DOM, either at the document level or at a panel level using the <b>jQuery.data<\/b> API:<\/p>\n<pre class=\"brush: javascript\">\r\nvar viewModel1 = { }\r\nvar viewModel2 = { }\r\n\r\nko.applyBindings(viewModel1);\t\r\nko.applyBindings(viewModel2);\t\r\n\r\n$(document).data(\"MyDocumentViewModel\", viewModel1);\r\n$(\"#my-panel\").data(\"MyPanelViewModel\", viewModel2);\r\n<\/pre>\n<p>\t\t\t\t\t\tThis allows us to access a specific ViewModel later, outside data-binding logic (e.g. in an event handler) like so:<\/p>\n<pre class=\"brush: javascript\">\r\nvar viewModel1 = $(document).data(\"MyDocumentViewModel\");\r\nvar viewModel2 = $(\"#my-panel\").data(\"MyPanelViewModel\");\r\n<\/pre>\n<p>\t\t\t\t\t\t\tTo keep our code organized we&#8217;ll want to create accessor functions such as for example:<\/p>\n<pre class=\"brush: javascript\">\r\n\tMyApp.Model.GetMyDocumentViewModel = function() {\r\n\t\treturn $(document).data(\"MyDocumentViewModel\");\r\n\t}\r\n\r\n\tMyApp.Model.SetMyDocumentViewModel = function(viewModel) {\r\n\t\t$(document).data(\"MyDocumentViewModel\", viewModel);\r\n\t}\r\n<\/pre>\n<p>\t\t\t\t\t\t\tSo that we can just access our ViewModel from other modules:<\/p>\n<pre class=\"brush: javascript\">\r\n\/\/ Initialization\r\nvar viewModel = { }\r\nko.applyBindings(viewModel);\t\r\nMyApp.Model.SetMyDocumentViewModel(viewModel);\r\n\r\n\/\/ Later on in a different module:\r\nMyApp.Model.GetMyDocumentViewModel()\r\n\t.savingGoalAmount.subscribe(myCallBackFunction);\r\n\r\n<\/pre>\n<p>\n\t\t\t\t\t\t<\/li>\n<li>The attributes (<b>Value Models<\/b>) of the ViewModel can be updated using data returned by an AJAX call to a controller\n<pre class=\"brush: javascript\">\r\n$.getJSON('ajax\/myapi.json', \r\n\t\t\tparms, \r\n\t\t\tfunction(data) {\r\n\t\/\/ Assumption: we have saved the original viewModel \r\n\tvar viewModel = $(document).data(\"MyViewModel\");\r\n\tviewModel.savingGoalAmount(data.amount);\r\n});\r\n<\/pre>\n<\/li>\n<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>\n<\/li>\n<li>Arbitrary Javascript functions can also subscribe to Value Model changes:\n<pre class=\"brush: javascript\">\r\n\/\/ Set up the ViewModel\r\nvar viewModel = {\r\n\tsavingGoalAmount: ko.observable(500), \/\/ dollars\r\n\t\/\/ ... more attributes ...\r\n};\r\n\r\nfunction GraphSavingScenario(newValue) {\r\n\t\/\/ some graphing logic\r\n}\r\n\r\nviewModel.savingGoalAmount.subscribe(GraphSavingScenario);\r\n<\/pre>\n<p>\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\".\/wp-content\/media\/knockoutjs\/advanced-callback-function.png\" \/>\n\t\t\t\t\t\t<\/li>\n<\/ol>\n<p>\t\t\t\t\t<a name='sowhat'><\/a><\/p>\n<h3>So What?<\/h3>\n<p>KnockoutJS can help organize browser-side logic by facilitating the creation of panels (<b>Views<\/b>),<br \/>\n\t\t\t\t\teach 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 \/>\n\t\t\t\t\tData-binding, combined with derived data \/ behaviors, and AJAX will boost the interactivity level of the application.\n\t\t\t\t\t<\/p>\n<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 \/>\n\t\t\t\t\tWe will cover the following topics:<\/p>\n<ul>\n<li>Enabling \/ disabling rules<\/li>\n<li>Condition display<\/li>\n<li>Leveraging jQuery templates<\/li>\n<li>Extracting views into templates<\/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<\/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\n\t\t\t\t\t\n\n<h5>My Other Related Posts:<\/h5>\n\n\n\t\t\t\t\t\n\n<ul name=\"myotherrelatedposts\">\n\t\t\t\t\t\t\n\n<li><a name='caoauth' href='https:\/\/blog.monnet-usa.com\/?p=XXX'>Easily Transform Your Ruby Camping App Into An OAuth Provider<\/a><\/li>\n\n\n\t\t\t\t\t<\/ul>\n\n\n--><br \/>\n\t\t\t\t\t<a name='ko-fiddle'><\/a><\/p>\n<h5>Source Of The KnockoutJS Examples<\/h5>\n<p>You can find the examples on jsFiddle.net here:<\/p>\n<ul>\n<li><a href=\"http:\/\/jsfiddle.net\/techarch\/z5Ptd\/\" target=\"_blank\">Basics &#8211; Example 1<\/a><\/li>\n<li><a href=\"http:\/\/jsfiddle.net\/techarch\/YXxpG\/\" target=\"_blank\">Building Up  &#8211; Example 1<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>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 [&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,30],"tags":[54,32,58],"class_list":["post-354","post","type-post","status-publish","format-standard","hentry","category-ajax","category-javascript","category-jquery","tag-ajax","tag-javascript","tag-jquery"],"_links":{"self":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/354","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=354"}],"version-history":[{"count":12,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/354\/revisions"}],"predecessor-version":[{"id":366,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/354\/revisions\/366"}],"wp:attachment":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=354"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=354"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}