Site Meter
 
 

Category: Uncategorized

Rich JavaScript Applications – the Seven Frameworks (Throne of JS, 2012)

A week ago was the Throne of JS conference in Toronto, perhaps the most interesting and different conference I’ve been to for a while. Quoting its website:

It’s no longer good enough to build web apps around full page loads and then “progressively enhance” them to behave more dynamically. Building apps which are fast, responsive and modern require you to completely rethink your approach.

The premise was to take the seven top JavaScript frameworks/libraries for single-page and rich JavaScript applications — AngularJS, Backbone, Batman, CanJS, Ember, Meteor, Knockout, Spine — get the creators of all of them in one location, and compare the technologies head to head.*

Disclaimer: I was there to represent Knockout, so obviously I’m not neutral. In this post my focus is on what the creators said about the scope and philosophy of their technologies, and not so much on whether I agree or disagree.

* Yes, I know that’s eight frameworks, not seven. This part was never fully explained…

TL;DR Executive Summary

  • For many web developers, it’s now taken for granted that such client-side frameworks are the way to build rich web apps. If you’re not using one, you’re either not building an application, or you’re just missing out.
  • There’s lots of consensus among the main frameworks about how to do it (Model-View-* architecture, declarative bindings, etc. — details below), so to some extent you get similar benefits whichever you choose.
  • Some major philosophical differences remain, especially the big split between frameworks and libraries. Your choice will deeply influence your architecture.
  • The conference itself was stylish and upbeat, with a lot of socialising and conversations across different technology groups. I’d like to see more like this.

Technologies: Agreement and Disagreement

As each SPA technology was presented, some fairly clear patterns of similarity and difference emerged.

Agreement: Progressive enhancement isn’t for building real apps.

All the technologies follow from the view that serious JavaScript applications require proper data models and ability to do client-side rendering, not just server rendering plus some Ajax and jQuery code.

Quote from Jeremy Ashkenas, the Backbone creator: “At this point, saying ‘single-page application’ is like saying ‘horseless carriage’” (i.e., it’s not even a novelty any more).

Agreement: Model-View-Whatever.

All the technologies made use of model-view separation. Some specifically talked about MVC, some about MVVM, and some specifically refused to define the third piece (just saying it’s models, views, and some kind of application thing that makes them work together). The net result in each case was similar.

Agreement: Data binding is good.

All except Backbone and Spine have a built-in notion of declarative data binding in their views (Backbone instead has a “bring your own view technology” design).

Agreement: IE 6 is dead already.

In a panel discussion, most framework creators said their IE support focus was limited to version 7+ (in fact, Ember and AngularJS only go for IE8, and Batman requires an ES5 shim to run on IE older than v9). This is the way of things to come: even jQuery 2 is set to drop support for IE older than v9.

The only stalwarts here appear to be Backbone and Knockout which support IE6+ (I don’t know about Backbone’s internals, but for KO this means transparently working around a lot of crazy edge-case IE6/7 rendering and eventing weirdnesses).

Agreement: Licensing and source control.

Every single one is MIT licensed and hosted on GitHub.

Disagreement: Libraries vs frameworks.

This is the biggest split right now. You could group them as follows:

Libraries Frameworks

Backbone (9552)

Knockout (2357)

Spine (2017)

CanJS (321)

Ember (3993)

AngularJS (2925)

Batman (958)

Meteor (4172) — unusual, see later

Numbers in brackets are a point-in-time snapshot of the number of GitHub watchers, as a crude indicator of relative influence.

What does this mean?

  • Libraries slot into your existing architecture and add specific functionality
  • Frameworks give you an architecture (file structure, etc.) that you are meant to follow and, if you do, are intended to handle all common requirements

By far the most passionate advocate of the framework model is Ember, whose creator Yehuda Katz is formerly of the Rails and SproutCore projects (similar philosophy). His argument was that anything less is just not ambitious enough and isn’t seriously advancing the state of the art. The counter-argument is that libraries are more focused, and hence can be easier to learn, adopt, customize, and help minimise project risk because your architecture isn’t so deeply tied to a specific external project. Based on my conversations, I’d say the audience was split and supported both sides of this debate.

Note that AngularJS is arguably somewhere in between library and framework: it doesn’t require a particular layout of files at development time (library-like), but at runtime it provides an “app lifecycle” that you fit your code into (framework-like). I’m listing it as a framework because that’s the terminology the AngularJS team prefers.

Disagreement: What’s flexible, what’s integrated.

Each technology has different levels of prescriptiveness:

Views

URL routing

Data storage

AngularJS

Built-in DOM-based templates (mandatory)

Built-in (optional)

Built-in system (optional)

Backbone

Choose your own (most used handlebars.js, a string-based template library)

Built-in (optional)

Built-in (overridable)

Batman

Built-in DOM-based templates (mandatory)

Built-in (mandatory)

Built-in system (mandatory)

CanJS

Built-in string-based templates (mandatory)

Built in (optional)

Built in (optional)

Ember

Built-in string-based templates (mandatory)

Built-in (mandatory)

Built-in (overridable)

Knockout

Built-in DOM-based templates (optional, can do string-based too)

Choose your own (most use sammy.js or history.js)

Choose your own (e.g., knockout.mapping or just $.ajax)

Meteor

Built-in string-based templates (mandatory)

Built-in (mandatory?)

Built-in (Mongo, mandatory)

Spine

Choose your own string-based templates

Built-in (optional)

Built-in (optional?)

As expected, whenever a library leaves a decision open, they argue it is better overall to guarantee composablity with arbitrary 3rd-party libraries. And the obvious counter-argument is that integration can be more seamless if built-in. Again, based on my conversations, the audience was split and opinions went in all directions — usually based on how much other technology stack an individual was wedded to.

Quote from Tom Dale of Ember: “We do a lot of magic, but it’s good magic, which means it decomposes into sane primitives.

Disagreement: String-based vs DOM-based templates

(As shown in the above table.) For string-based templates, almost everyone used Handlebars.js as the template engine, which seems to dominate this space, though CanJS used EJS. Arguments in favour of string-based templates include “it’s faster” (debatable) and “theoretically, the server can render them too” (also debatable, as that’s only true if you can actually run all of your model code on the server, and nobody actually does that in practice).

DOM-based templates means doing control flow (each, if, etc.) purely via bindings in your actual markup and not relying on any external templating library. Argument include “it’s faster” (debatable) and “the code is easier to read and write, because there’s no weird chasm between markup and templates, and it’s obvious how CSS will interact with it“.

In my view, the strongest argument here came from the AngularJS guys who stated that in the near future, they expect DOM-based templating will be native in browsers, so we’ll best prepare ourselves for the future by adopting it now. AngularJS is from Google, so they are already working on this with Chromium and standards bodies.

Disagreement: Levels of server-agnosticism

Batman and Meteor express explicit demands on the server: Batman is designed for Rails, and Meteor is its own server. Most others have a goal of being indifferent to what’s on your server, but in practice the architecture, conventions, and some tooling in Ember leans towards Rails developers. Ember absolutely works on other server technologies too, though today it takes a little more manual setup.

The technologies — quick overview

Here’s a rundown of the basic details of each technology covered:

Backbone
  • Who: Jeremy Ashkenas and DocumentCloud
  • What:
    • Model-View in JavaScript, MIT licensed
    • Most minimal of all the libraries — only one file, 800 lines of code!
    • Extremely tightly-scoped functionality — just provides REST-persistable models with simple routing and callbacks so you know when to render views (you supply your own view-rendering mechanism).
    • The best-known of them all, with the most production deployments on big-name sites (perhaps easy to adopt because it’s so minimal)
  • Why:
    • It’s so small, you can read and understand all of the source before you use it.
    • No impact on your server architecture or file layout. Can work in a small section of your page — doesn’t need to control whole page.
    • Jeremy seems to exist in a kind of zen state of calm, reasonable opinions about everything. He was like the grown up, supervising all the arguing kids.
  • Where: GitHub and own site
  • When: In production for nearly 2 years now
Meteor
  • Who: The Meteor development group, who just raised $11.2 Million so they can do this full-time
  • What:
    • Crazy amazing framework from the future, barely reminiscent of anything you’ve ever seen (except perhaps Derby)
    • Bridges a server-side runtime (on Node+Mongo) with a client-side one, so your code appears to run on both, including the database. WebSockets syncs between all client(s) and server.
    • Does “live deployments” every time you edit your code – client-side runtimes are updated on the fly without losing their state
    • Makes more sense if you watch the video
    • Like everyone I spoke to at the event, I really want this to succeed — web development needs something this radical to move forwards
  • Why: You’ve had enough of conventional web development and now want to live on the bleeding edge.
  • Where: GitHub and own site
  • When: It’s still early days; I don’t know if there are any production Meteor sites yet except built by the core team. They’re totally serious about doing this, though.
Ember
  • Who: Yehuda Katz (formerly of jQuery and Rails), the Ember team, and Yehuda’s company Tilde
  • What:
    • Everything you need to build an “ambitious web application”, MIT license
    • Biggest framework of them all in both functionality and code size
    • Lots of thought has gone into how you can decompose your page into a hierarchy of controls, and how this ties in with a statemachine-powered hierarchical routing system
    • Very sophisticated data access library (Ember.Data) currently in development
    • Intended to control your whole page at runtime, so not suitable for use in small “islands of richness” on a wider page
    • Pretty heavily opinionated about files, URLs, etc., but everything is overridable if you know how
    • Design inspired by Rails and Cocoa
    • Tooling: They supply project templates for Rails (but you can use other server platforms if you write the code manually)
  • Why: Common problems should have common solutions — Ember makes all the common solutions so you only have to think about what’s unique to your own application
  • Where: GitHub and own site
  • When: Not yet at 1.0, but aiming for it soon. API will solidify then.
AngularJS
  • Who: Developed by Google; used internally by them and MIT licensed.
  • What:
    • Model-View-Whatever in JavaScript, MIT licensed
    • DOM-based templating with observability, declarative bindings, and an almost-MVVM code style (they say Model-View-Whatever)
    • Basic URL routing and data persistence built in
    • Tooling: they ship a Chrome debugger plugin that lets you explore your models while debugging, and a plugin for the Jasmine testing framework.
  • Why:
    • Conceptually, they say it’s a polyfill between what browsers can do today and what they will do natively in a few years (declarative binding and observability), so we should start coding this way right now
    • No impact on your server architecture or file layout. Can work in a small section of your page — doesn’t need to control whole page.
  • Where: GitHub and own site
  • When: In production now (has been at Google for a while)
Knockout
  • Who: The Knockout team and community (currently three on the core team, including me)
  • What:
    • Model-View-ViewModel (MVVM) in JavaScript, MIT licensed
    • Tightly focused on rich UIs: DOM-based templates with declarative bindings, and observable models with automatic dependency detection
    • Not opinionated about URL routing or data access — combines with arbitrary third-party libraries (e.g., Sammy.js for routing and plain ajax for storage)
    • Big focus on approachability, with extensive documentation and interactive examples
  • Why:
    • Does one thing well (UI), right back to IE 6
    • No impact on your server architecture or file layout. Can work in a small section of your page — doesn’t need to control whole page.
  • Where: GitHub and own site
  • When: In production for nearly 2 years now
Spine
  • Who: Alex MacCaw
  • What:
    • MVC in JavaScript, MIT license
    • Worked example originally written for an O’Reilly book grew into an actual OSS project
    • Is a kind of modified clone of Backbone (hence the name)
  • Why: You like Backbone, but want a few things to be different.
  • Where: GitHub and own site
  • When: It’s past v1.0.0 now
Batman
  • Who: the team at Shopify (an eCommerce platform company)
  • What:
    • MVC in JavaScript, almost exclusively for Rails+CoffeeScript developers, MIT licensed
    • Most opinionated of them all. You must follow their conventions (e.g., for file layout and URLs) or, as they say in their presentation,”go use another framework
    • Full-stack framework with pretty rich models, views, and controllers and routing. And observability mechanism of course.
    • DOM-based templating.
  • Why: If you use Rails and CoffeeScript, you’ll be right at home
  • Where: GitHub and own site
  • When: Currently at 0.9. Aiming for 1.0 in coming months.
CanJS
  • Who: the team at Bitovi (a JavaScript consulting/training company)
  • What:
    • MVC in JavaScript, MIT licensed
    • REST-persistable models, basic routing, string-based templating
    • Not widely known (I hadn’t heard of it before last week), though is actually a reboot of the older JavaScriptMVC project
  • Why: Aims to be the best of all worlds by delivering features similar to the above libraries while also being small
  • Where: GitHub and own site
  • When: Past 1.0 already

Summary

If you’re trying to make sense of which of these is a good starting point for your project, I’d suggest two questions areas to consider:

  • Scope. How much do you want a framework or library to do for you? Are you starting from blank and want a complete pre-prepared architecture to guide you from beginning to end? Or do you prefer to pick your own combinations of patterns and libraries? Either choice has value and is right for different projects and teams.
  • Design aesthetic. Have you actually looked at code and tried building something small with each of your candidates? Do you like doing it? Don’t choose based on descriptions or feature lists alone: they’re relevant but limited. Ignoring your own subjective coding experience would be like picking a novel based on the number of chapters, or a spouse based on their resume/CV.

Despite the differences, I’d argue there is one killer feature all the above technologies share: the idea of Model/View separation. This is a classic design pattern that predates the web itself by about 20 years. If you’re building even the most basic kind of web application UI, you’ll almost certainly benefit from applying this on the client.

Review: Open-source components used in learn.knockoutjs.com

Over the last two months I’ve been using my wife-approved weekend coding time to build learn.knockoutjs.com, a set of interactive in-browser coding exercises to help people learn the basics of knockout.js in a convenient and fun way. If you haven’t already seen it, grab a hot drink and treat yourself to 15 minutes of enjoyable learning right now!

image

Since this was a one-person weekend project, I’ve been using all possible means to minimise the total development time. A key part of that has been using existing open source components so I can avoid reinventing stuff wherever possible.

In the end, I was surprised to realise just how many open source projects went into building this single-page application, and how high-quality and easy-to-use most of them were. So, I’d like to give them a bit of recognition by listing them here and giving you a mini-review of each. Maybe you’ll benefit from a few of these in your own projects.

1: Knapsack

Knapsack (NuGet: knapsack) is Andrew Davey’s JavaScript / CSS dependency manager for ASP.NET. It lets you define a series of JS/CSS references like this:

Html.ReferenceScript("Scripts/Lib/knockout-1.3.0.latest.js");
Html.ReferenceScript("Scripts/Custom/bindings.js");
Html.ReferenceScript("Scripts/Custom/appViewModel.js");
Html.ReferenceStylesheet("Content/App/boilerplate.css");
// ... etc ...

… and then emit the actual <script> / <link rel="stylesheet"> tags like this:

@Html.RenderScripts()

What’s the point? Well, in debug mode, it just emits one <script> tag per referenced script, as usual, so you can use your browser’s JavaScript debugger as always. But in release mode, it emits just one <script> tag pointing to a special URL that returns all of the JavaScript code combined into a single file, minified using the MS Ajax Minifier library. So, if you view source on learn.knockoutjs.com, you’ll see only one or two <script> tags even though I’m actually using dozens of JS files.

It also sets all the right cache/etag headers so the browser can avoid making unnecessary HTTP requests, but doesn’t risk using out-of-date scripts because the dynamic script URL changes whenever you change the referenced script files (the URL includes a hash of your JavaScript source code).

I’ve been very happy with knapsack, and would definitely recommend it. The one caveat I discovered is that it automatically references all JavaScript files in any folder that you point it at, which is surprising if you intentionally didn’t reference one of the files in that folder. That aside, if you can organise your JS/CSS files into folders to match how they should be combined, you’ll probably be very happy with Knapsack too.

Note: Knapsack will soon be changing its name to something else due to a cease-and-desist.

2: YamlSerializer

As part of my minimum viable product kind of philosophy for the site, I didn’t create any kind of editor for the tutorials, and I didn’t even store them in a database. The simplest editor is a text editor, and the simplest data store is files on disk. So, the tutorials are written in YAML – a human-editable structured text format.

To parse these YAML files, I used YamlSerializer (NuGet: yamlserializer), a .NET library written by Osamu Takeuchi. So, I have .NET classes like this:

public class Tutorial
{
    public string Title { get; set; }
    public virtual ICollection<tutorialStep> Steps { get; set; }
    // ... various other properties ...
}
 
public class TutorialStep
{
    public string Instructions { get; set; }
    // ... other properties ...
}

… and YAML files like this:

title: Introduction
steps:
 - instructions: |
    ##Welcome!
    Blah blah blah, here's what to do...
 - instructions: |
    ##Doing the next thing
    Do the following things...

… and YamlSerializer parses Tutorial/TutorialStep instances like this:

Dictionary data = new YamlSerializer().Deserialize(allText);
return new Tutorial {
    Title = (string)data["title"],
    Steps = (from stepDict in (Dictionary)data["steps"]
             select new TutorialStep {
                 Instructions = ((string)stepDict["instructions"]).Trim(),
                 // ... other properties ...
             }).ToList(),
    // ... other properties ...
};

It’s maybe not quite as pretty as it could be with a more generics-oriented API (or maybe even a dynamic one?) but it’s robust, fast enough (though I do cache the parsed result), and I had it working in minutes. So I’m satisfied with that!

3: Ninject

image

I didn’t strictly need to use Dependency Injection in this project, but since it takes exactly 10 seconds to set up thanks to NuGet, I did it anyway. My favourite DI container is Ninject (NuGet: Ninject.MVC3), a very easy-to-configure product from Nate Kohari. The MVC 3 version hooks itself into the MVC 3 Dependency Injection extensibility point automatically (internally, it uses David Ebbo’s WebActivator to make itself run when your app first starts).

In this site, it’s only used to supply ITutorialRepository instances to my one-and-only HomeController. Really I could have just hardcoded the dependency, as there is only one tutorial repository (YamlTutorialRepository), but hey it genuinely did take less than one minute to set up the DI and it made me feel less like I was just hacking things together…

4: CodeMirror

image

See those lovely in-browser code editors with context-specific syntax highlighting, the ones that even work on IE6? That’s CodeMirror, a JavaScript library from Marijn Haverbeke.

This was not particularly easy to get working just as I wanted – I hit a range of browser-specific performance problems mainly because of my compulsive need to put rounded corners and dropshadows on every element on the page. Nonetheless, it’s a completely vital component, the entire site couldn’t exist without it, and it’s an impressive technical achievement in its own right, so I’m willing it to give it plenty of slack.

The one alternative code editor I tried was Ace – it looks very promising, but had serious layout issues in IE (e.g, if you resize the font). In the future Ace might overtake CodeMirror to become the smartest and best-performing in-browser code editor, but it’s not there yet.

5: Amplify.js

image

Did you notice that if you work on one of the tutorials, then leave the tutorial (possibly even the whole site), and then later come back, the site will offer to restore your code and your position in that tutorial? How can this be, given that you didn’t even register for an account? It’s HTML 5 local storage, of course.

To implement this, I used Amplify.js (NuGet: amplifyjs), a JavaScript library from appendTo. Of all the JavaScript libraries I used, this one was the easiest to get working. It was completely trivial, in fact – just about three lines of code in total.

Whenever you run your code, the site saves your state:

amplify.store("tutorialState." + tutorial.Id, { view: ..., viewModel: ..., stepIndex: ... });

Similarly, whenever you load a tutorial, the site checks if you have saved state:

var savedState = amplify.store("tutorialState." + id);

… and if so, offers to restore it. The site doesn’t care what browser you’re running, because Amplify.js figures out what local storage options exist and uses whichever one is going to work for you.

6: json2.js

Amplify.js needs your browser to support JSON.stringify, the JavaScript API for serializing an object to JSON. All decent browsers do, but just in case you’re running IE 7 (What kind of web developer are you? Shame on you!), I reference json2.js (NuGet: json2) which provides an implementation of JSON.stringify. Json2.js is the work of legendary JavaScript guru and JSON inventer, Douglas Crockford.

7: Highlight.js

In the tutorial instructions, there are lots of little snippets of code showing you what to do. For the syntax highlighting here, I used highlight.js from Ivan Sagalaev.

There are dozens of code-highlighting JavaScript libraries, and I’ve no reason to say this one is better than the rest. I chose this one simply because it lets me “highlight” a certain DOM element at an arbitrary time of my choosing, and doesn’t get fussy about doing things when the page first loads. Also it tolerates existing HTML markup in the element you’re highlighting, which is how I was able to put special yellow backgrounds on selected bits of code to emphasise the key points.

Highlight.js was pretty easy to work with. I made a Knockout custom binding to display the tutorial steps, and whenever it updates the UI, it highlights any code blocks like this:

$('pre code', element).each(function () {
    hljs.highlightBlock(this, '    ' /* tab = four spaces */)
});

To customise the colour scheme, you just edit its CSS file. Pretty convenient.

8: Showdown.js

I said the tutorials are written in YAML, but that’s just how the .NET objects are represented as text. To represent the actual markup within the instructions (e.g., the headings, links, code blocks, etc.), I used Markdown, a simple text-formatting DSL invented by John Gruber. So I’ve got “markdown” syntax within my YAML files, like this:

 - instructions: |
    ##How to write markdown
    To emphasise text, use *asterisks*. To include a code snippet, just indent it like this:
 
        var blah = "this is some JavaScript"
 
    You can put bits of text into code font `using backtick quotes`.

That markdown text gets sent to the client (in JSON form, of course – so many text-based formats!). To render it as HTML in the browser, I use showdown.js, a Markdown-to-HTML conversion library from John Fraser. This is pretty straightforward – I have a Knockout custom binding like this:

ko.bindingHandlers.markdown = {
    update: function (element, valueAccessor) {
        var markdownValue = ko.utils.unwrapObservable(valueAccessor());
        var htmlValue = markdownValue && new Showdown.converter().makeHtml(markdownValue);
        $(element).html(htmlValue || "");
    }
};

… and then I can bind elements to show markdown data like as follows, and it will refresh the display whenever the markdown text changes:

<div data-bind="markdown: someMarkdownValue"></div>

9: jQuery and friends

image

Obviously I used jQuery. I won’t bother discussing the core library because everyone knows about that, but I will mention the jQuery plugins I used:

  • jQuery UI, not for any of the visual elements, but merely for its “draggable” API. (You can drag to resize the panes, see?). I didn’t need any of its buttons, menus, etc.
  • jQuery Impromptu, to display the overlaid prompts (e.g., for choosing a tutorial or for explaining that your code will be overwritten when you click “Help, it’s not working!”). To be honest, this is the only component I regretted using. It’s is probably great if you use it for its intended use case (which includes things like multi-step wizards), but all I wanted was to move an existing DOM element in front of a gray background, lightbox style. jQuery Impromptu tries to do all manner of extra things that that screwed around with my DOM and its default animation was horribly stuttery on Chrome and Safari. In the end, I butchered its source code almost beyond recognition to get the desired behaviour with tolerable performance. It would have been much quicker for me to write my own version from scratch…
  • jQuery Templates (used internally by Knockout, and soon to be replaced with JsRender)
  • jQuery Address (used internally by knockout.address for the hash-based navigation)

10: … and of course, Knockout.js

icon

Not surprisingly, the UI is all orchestrated with knockout.js (NuGet: knockoutjs), so I have a very tidy MVVM architecture for the client-side code. There are objects to represent each of the major UI elements (panes, draggable splitters, code editors, prompts, etc.), and Knockout takes care of keeping the visible UI in sync with that whole object graph.

But I don’t need to explain this – you can learn much more from the tutorials

Summary

Building an application by smashing together a lot of different open-source projects is pretty quick. The end result is not always a perfectly harmonious symphony, as each component brings its own coding styles and conventions, but it works.

What I’ve learned about components is kind of predictable: the most useful ones are

  • Focused. Just solve one problem, please.
  • Self-contained. I’m not going to accept a tall stack of dependencies; it’s too risky.
  • Clearly documented. First I want examples, then a systematic list of API functions.
  • Available on NuGet Smile

It wasn’t difficult to find components to suit my requirements. It’s great to see the open source ecosystems are thriving, both on .NET and JavaScript.

Knockout.js 1.2.0 released

Earlier today I published the final 1.2.0 build of knockout.js. This is a big release with stacks of new goodness since 1.1.2:

  • Changed the license to MIT (more permissive than the previous license, MS-PL)
  • Added useful new bindings: event, attr, html
  • Enhanced some existing bindings: options, checked
  • Enhanced templating features (now supports jquery.tmpl 1.0.0pre as well as previous versions, template polymorphism, passing additional data via options)
  • Various performance improvements (e.g., now precompiles and caches templates, and ensures all data/subscriptions associated with DOM elements are cleaned immediately when those elements are removed) plus bugfixes
  • Better compilation style (ensures Closure Compiler no longer adds any extra variables to global namespace)
  • Various new extensibility points requested by plugin authors
  • Minor syntactical improvements (e.g., added zero-arg constructor for observable arrays)
  • All documentation updated to match 1.2.0

Thanks very much to the many people who have contributed ideas, pull requests, bug reports, and support to make this release possible! I’m really enjoying the community that’s growing around this.

Hang on, what’s Knockout.js?

In case you’ve never heard of it, here’s tekmaven’s explaination: Smile

image

(By the way, for Visual Studio developers: Install-Package knockoutjs)

More specifically, Knockout is a JavaScript library for building rich, responsive user interfaces. It uses automatic dependency tracking and declarative bindings to update your UI whenever your data model changes, letting you cleanly structure your code around the MVVM pattern.

No, that’s just marketing blather… show me something real

OK then, to learn more: