JavaScript

  • Parsing a Time String with JavaScript

    Let’s say you are building a UI where you’d like a user to enter a time into a text box.  This time value they might enter needs to handle a lot of different formats, but we’d like it to end up as the same value either way:

    • 1pm
    • 1:00pm
    • 1:00p
    • 13:00

    Here’s a little JavaScript function to do this work.  Most of the interesting bits are the regular expression which helps handle of these various scenarios.  It takes a string representation of a time and attempts to parse it, setting the time on the specified date object sent to the function as the second parameter.  In the case where you do not provide a second parameter, the current date will be used.

    function parseTime(timeStr, dt) {
        if (!dt) {
            dt = new Date();
        }
    
        var time = timeStr.match(/(\d+)(?::(\d\d))?\s*(p?)/i);
        if (!time) {
            return NaN;
        }
        var hours = parseInt(time[1], 10);
        if (hours == 12 && !time[3]) {
            hours = 0;
        }
        else {
            hours += (hours < 12 && time[3]) ? 12 : 0;
        }
    
        dt.setHours(hours);
        dt.setMinutes(parseInt(time[2], 10) || 0);
        dt.setSeconds(0, 0);
        return dt;
    }

    This function will return NaN if it can’t parse the input at all.  The logic immediately following the match() call is to handle the noon/midnight case correctly. 

    Here’s a jsFiddle of this in action:

    Categories: JavaScript

    Tags: Algorithms

  • Improving on KoLite

    In my posts on creating a dynamic menu system, I used KoLite commands to represent what gets invoked when clicking on a menu item.  KoLite adds a command abstraction to Knockout that cleanly encapsulates the execution of a command and the status of a command (with the canExecute() computed, you can disable UI widgets that cannot be executed in the current state).

    There was just one thing missing from the command that I wanted: the ability to tell if a command is toggled or latched.  Latching a command means that the command is “on” and all UI elements bound to this can update their state (for example, a menu item in a drop down menu typically has a checkmark or dot placed next to the item to convey that the item is on or toggled).

    The concept of latching is very simple to implement.  In knockout.command.js, I added the following code to the ko.command constructor function:

    ko.command = function (options) {
        var self = ko.observable(),
            canExecuteDelegate = options.canExecute,
            executeDelegate = options.execute,
            latchedDelegate = options.isLatched; // new
    
        // new computed; everything else is the same
        self.isLatched = ko.computed(function () {
            return latchedDelegate ? latchedDelegate() : false;
        });
    };
    

    This is really simple – it’s just adding a function that delegates to another function you supply when you setup the command.  This function you supply represents the logic required to tell if the command is in a latched state or not.

    Here’s an example of how this could be used:

    var showStatusBarCmd = ko.command({
        execute: function () {
            showStatusBar(!showStatusBar);
        },
        isLatched: function () {
            return showStatusBar() === true;
        }
    });
    

     

    In this example, there’s an observable in the outer scope called showStatusBar that will be used to determine if the status bar in the app is visible.  If the user clicks on a menu item bound to this command, the execute() handler will fire toggling the showStatusBar observable.  The status bar’s visibility is then bound to this value.  Now for latching, the isLatched handler will test to see if showStatusBar is true and will return true if it is.

    Now, in the menu system you would probably wire up an element that would show a checkmark or a dot next to the menu item if the command’s latched state is on.  Note that you could have two different UI elements bound to the same command (like a menu item and a toolbar button) and both would be synchronized automatically to changes in the app’s state.

    Categories: JavaScript

    Tags: Knockoutjs, KoLite

  • Building a Dynamic Application Menu with Durandal.js, Knockout, and Bootstrap (Pt. 3)

    In the last two posts of this series, we built a dynamic menu system.  Now it is time to wrap it up with a discussion on how to actually populate and use these menus.

    One idea is to create the concept of a workspace which represents the UI that the user sees for the application.  The workspace is like a top-level window in a desktop application.  The following module defines a workspace that contains a list of menus and defines a routine to take arbitrary menu layout objects and convert them to Menu and MenuItem instances:

    define(function (require) {
        var Menu = require('ui/menu'),
            MenuItem = require('ui/menuItem'),
            menus = ko.observableArray([]);
    
        function setupWorkspace(cmds) {
            menus([]);
    
            var menus = {
                "File": [
                    { text: "New", command: cmds.new },
                    { text: "Open", command: cmds.open },
                    { divider: true },
                    { text: "Save", command: cmds.save },
                    { text: "Save As", command: cmds.saveas },
                    { divider: true },
                    { text: "Sign out", command: cmds.signout }
                ],
                "Edit": [
                    { text: "Cut", command: cmds.cut },
                    { text: "Copy", command: cmds.copy },
                    { text: "Paste", command: cmds.paste }
                ],
                "View": [
                    { text: "View Mode", subItems: [
                        { text: "Simple", command: cmds.toggleSimpleView },
                        { text: "Advanced" command: cmds.toggleAdvancedView }
                    ]}
                ],
                "Help": [
                    { text: "Contents", command: cmds.helpcontents },
                    { divider: true },
                    { text: "About", command: cmds.about }
                ]
            };
    
            loadMenus(menus);
        }
    
        function loadMenus(menuDefinitions) {
            var menuText, menu;
            for (menuText in menuDefinitions) {
                menu = addMenu(menuText);
                addMenuItems(menu, menuDefinitions[menuText]);
            }
        }
    
        function addMenuItems(menuOrMenuItem, itemDefinitions) {
            for (var i = 0; i < itemDefinitions.length; i++) {
                var definitionItem = itemDefinitions[i];
                if (definitionItem.hasOwnProperty("divider")) {
                    menuOrMenuItem.addDivider();
                }
                else {
                    var menuItem = new MenuItem(definitionItem.text, definitionItem.command);
                    menuOrMenuItem.addMenuItem(menuItem);
                    if (definition.hasOwnProperty("subItems")) {
                        addMenuItems(menuItem, definitionItem.subItems);
                    }
                }
            }
        }
    
        function addMenu(text, position) {
            var menu = new Menu(text);
            if (position) {
                menus.splice(position, 0, menu);
            }
            else {
                menus.push(menu);
            }
    
            return menu;
        }
    
        var workspace = {
            menus: menus,
            addMenu: addMenu,
            setupWorkspace: setupWorkspace
        };
    
        return workspace;
    });
    
    

     

    The main application shell should call the workspace singleton’s setupWorkspace() function and pass in an object that contains references to the desired ko.commands that will get attached to the menu items.  It can also use the menus property in its data-binding to automatically create the UI (as seen in part 2 of this series).

    The setupWorkspace() function creates a menu definition which is just an inline object literal.  The source for this could actually come from the server as JSON, or be in another file, or loaded by a plugin.  The point is that there is a definition format that gets fed into the loadMenus() function that builds the menus by converting the definition into real Menu and MenuItem instances and adding them to the collection.

    The workspace module also exports the addMenu() function which allows someone to add a menu to the menu bar after the initial setup has taken place.  I think more functions (like remove) could be added if you really want to make this robust as far as configuration of menus is concerned (I’m just demoing this to illustrate a point).  And obviously, the commands aren’t built and this is very demo-specific, but you can just swap that out for whatever you want.  You could even send the menu definitions to the setupWorkspace() function instead of embedding it directly in the function.

    You can view a live demo of this series at: http://tblabonne.github.io/DynamicMenus/

    The complete source to the demo can be found at: http://github.com/tblabonne/DynamicMenus

    Categories: JavaScript

    Tags: Bootstrap, Durandal, Knockoutjs, KoLite

  • Building a Dynamic Application Menu with Durandal.js, Knockout, and Bootstrap (Pt. 2)

    In the previous post, I laid out a design for creating a dynamic menu system, specifically the object model that will be used in data binding.  In this post, we’ll look at the Knockout bindings and HTML structure to render the menus.

    This will be pretty straightforward as far as taking our object model and applying markup to it, however, the one complicated part is dealing with sub-menus.  Because menu items can themselves contain other menu items, we need the ability to render a menu within a menu and so on.  We can do this with Durandal’s compose binding handler for KO.  It allows recursive composition that is perfect for hierarchical things like menus.

    Here’s the contents of views/menu.html which is the view component for a single Menu rendering:

    <ul class="dropdown-menu" data-bind="foreach: items">
        <!-- ko if: $data.text !== undefined -->
        <li data-bind="css: { disabled: !command.canExecute(), 'dropdown-submenu': hasSubMenu }">
            <!-- ko ifnot: $data.hasSubMenu -->
            <a href="#" tabindex="-1" data-bind="command: command">
                <span data-bind="text: text"></span>
            </a>
            <!-- /ko -->
            <!-- ko if: $data.hasSubMenu -->
            <a tabindex="-1" data-bind="text: text"></a>
                <!-- ko compose: { view: 'views/menu.html', model: $data } -->
                <!-- /ko -->
            <!-- /ko -->
        </li>
        <!-- /ko -->
        <!-- ko if: $data.divider !== undefined -->
        <li class="divider"></li>
        <!-- /ko -->
    </ul>
    

     

    This markup is a bit complicated so let’s go through it:

    1. In Bootstrap, applying the dropdown-menu class to a <ul> will style it as a drop down menu container.  The data-bind here is also set to loop over each item in the Menu object.
    2. Within the <ul>, we need to decide if the MenuItem is a text-based menu item or a divider.  We do this by detecting if the divider property exists and/or there is text to display.  If the MenuItem is a divider, the special divider class is applied to a <li> and Bootstrap renders it as a thin gray line.
    3. If the MenuItem is actually a text-based item, we style it appropriately in its <li> element.  Notice the binding to command.canExecute().  In KoLite, if you provide a canExecute() function on a command (with is a computed observable), it can determine if the command can be executed or not.  In this case, we want the UI to gray-out or disable if the command cannot execute.  Once the command can execute, it will immediately synchronize the UI element to be a clickable command.
    4. Inside the <li>, we check to see if the MenuItem is a sub-menu or not.  If it is not, we create an <a> element as desired by Bootstrap to create the link to click on, binding the appropriate command to it.  We also bind the text in a <span> element inside the <a>.
    5. If the MenuItem does have a sub-menu, we assume that the MenuItem can’t be clickable, but instead, simply groups other elements.  In that case, we call upon the Durandal compose binding handler to recursively call this view sending the MenuItem as the view model to bind to in that context.

    Now, to render the top-level menu bar, in our main view we’d add the following markup (I’m using nav-pills in Bootstrap to represent the top-level menu items, but you don’t need to do that):

    <ul class="nav nav-pills menu-bar" data-bind="foreach: menus">
        <li class="dropdown">
            <a class="dropdown-toggle" href="#" data-toggle="dropdown" role="button" data-bind="text: text"></a>
            <!-- ko compose: { view: 'views/menu.html', model: $data } -->
            <!-- /ko -->
        </li>
    </ul>
    

    This assumes that the view model for the main view has a collection of Menu objects in an observableArray called menus.

    It renders a <li> element for each Menu giving it a dropdown class.  The <a> element will trigger Bootstrap to open the <ul> element that immediately follows the <a>.  That <ul> is generated by a compose binding calling onto the Menu view to render that one Menu and all of its children recursively.

    Categories: JavaScript

    Tags: Durandal, Knockoutjs, KoLite

  • Building a Dynamic Application Menu with Durandal.js, Knockout, and Bootstrap (Pt. 1)

    I’m going to do a longer series here about how to create a dynamic menu bar system with Durandal, Knockout, and Twitter Bootstrap.  This menu bar is going to emulate the traditional desktop application menu bar you find in apps (like the File, Edit, or View menus, for example).  The special thing here is that it will be 100% dynamic.  This will allow interesting scenarios such as dynamically altering the application menu when the application is in a different mode or allow something like plug-ins to alter the menu structure adding new commands.

    We will use the following libraries/frameworks to perform this task:

    • We’ll use Bootstrap to style the menus and get basic drop down menu support.  The menus in Bootstrap look very pretty and work very well using just one .js file for behavior and a little bit of markup.
    • We’ll use Durandal to structure the application and to take advantage of the composition engine it has.  I assume you know how to get a basic Durandal project up and running so I’m not going to spend a lot of time discussing how Durandal works.
    • We’ll use Knockout to do all of the data binding.  Our menu items will have observable properties in them so that menus will dynamically change when you change things about them in code.
    • We’ll also make use of KoLite by John Papa which provides a simple KO extension (the command) to abstract the idea of a UI command.  A single menu item will wrap a ko.command().  If a command does not allow execution, the corresponding menu item(s) will not allow it and will appear disabled.  Also, when clicking on a menu item, the command will execute.  This will all happen through data binding and will not

    For this first part, let’s build the JavaScript object model for the menu system.  A Menu object (defined in ui/menu.js in my project) represents one menu on a menu bar (such as a File menu).  It will contain zero or more MenuItems which are the individual menu selections in the menu.  There is also a special menu item that acts as a divider or separator.  These dividers draw thin lines between menu items to help visually group commands.  They are not clickable.

    Here’s the code for the MenuItem class (defined in ui/menuItem.js as a Durandal module):

    define(function (require) {
        var MenuItem = function (itemText, command, items) {
            this.text = ko.observable(itemText);
            this.command = command || ko.command({ execute: function () { } });
            this.items = ko.observableArray(items || []);
            this.hasSubMenu = ko.computed(function () {
                return this.items().length > 0;
            }, this);
        };
    
        MenuItem.prototype.addMenuItem = function (menuItem, position) {
            if (position) {
                this.items.splice(position, 0, menuItem);
            }
            else {
                this.items.push(menuItem);
            }
        };
    
        MenuItem.prototype.addDivider = function (position) {
            var item = { divider: true };
            if (position) {
                this.items.splice(position, 0, item);
            }
            else {
                this.items.push(item);
            }
        };
    
        return MenuItem;
    });
    

     

    A menu item takes a menu item text (the text to appear in the menu), an optional KoLite command, and an optional set of child sub-items.  The sub-items are used for when the menu item is actually a menu within a menu and will be rendered with a an arrow to the right of the menu item using Bootstrap.

    A Menu class also exists as a top-level container for MenuItems.  Think of this as the File menu or Edit menu.  It is defined in ui/menu.js as a Durandal module:

    define(function (require) {
        var MenuItem = require('ui/menuItem');
    
        var Menu = function (text, items) {
            this.text = ko.observable(text);
            this.items = ko.observableArray(items || []);
        };
    
        Menu.prototype.addMenuItem = function (menuItem, position) {
            if (position) {
                this.items.splice(position, 0, menuItem);
            }
            else {
                this.items.push(menuItem);
            }
    
            return menuItem;
        };
    
        return Menu;
    });
    

     

    This class takes the text of the menu item (“File”) and the collection of MenuItems to add to the menu.  You can call addMenuItem() to add a menu item after the initial creation of the menu.  The position parameter will add the menu in the specified position.  If you don’t specify a position, it will be added to the end of the menu.

    In the next part of the series, we’ll look at the HTML and KO data-bindings that will render the menus.

    Categories: JavaScript

    Tags: Bootstrap, Durandal, Knockoutjs, KoLite

  • Tree Traversals with JavaScript

    Let’s do this one more time – this time with JS.  Here is a constructor function for a generic tree node that has one parent and possibly N children:

    var TreeNode = function (data) {
        this.parent = data.parent || null;
        this.children = data.children || [];
    };
    
    TreeNode.prototype.isLeaf = function () {
        return this.children.length == 0;
    };
    
    TreeNode.prototype.isRoot = function () {
        return this.parent == null;
    };
    

     

    Here is how we’d traverse the tree with a depth-first search (note that I’m using the underscore.js library for the each() function – you could also use ES5’s Array.forEach() if you do not want to support older browsers – or use a polyfill):

    function visitDfs(node, func) {
        if (func) {
            func(node);
        }
    
        _.each(node.children, function (child) {
            visitDfs(child, func);
        });
    }

    Doing a breadth-first traversal is also straightforward thanks to JavaScript’s Array class and its queue/stack-like functionality:

    function visitBfs(node, func) {
        var q = [node];
        while (q.length > 0) {
            node = q.shift();
            if (func) {
                func(node);
            }
    
            _.each(node.children, function (child) {
                q.push(child);
            });
        }
    }
    

     

    Finally, let’s do something tangible with a depth-first traversal.  In the next code snippet, the prune() function will prune out nodes that are single children to their parents in order to collapse the tree into a simpler structure.  This will eliminate groupings of nodes that aren’t really grouping anything because their branching factor is 1:

    function prune(root) {
        visitDfs(root, function (node) {
            if (node.isRoot()) {
                return; // do not process roots
            }
            if (node.children.length == 1 && !node.children[0].isLeaf()) {
                var child = node.children[0],
                    index = _.indexOf(node.parent.children, node);
                node.parent.children[index] = child;
                child.parent = node.parent;
            }
        });
    }
    

     

    This code works by doing a DFS and calling a function on each node.  That function examines the node to see if it has exactly one child and that the one child node is not a leaf (we don’t want to prune out leaves or roots).  If it is, the child node is extracted out and assigned to the node’s parent’s children and then the child’s parent is reassigned to the node’s parent.  This effectively eliminates (prunes) the node out of the tree collapsing it into a simpler structure.

    Categories: JavaScript

  • First Impressions on Durandal

    I’ve been working with Durandaljs for a few weeks now.  It’s an open-source single page application (SPA) framework written to use technologies that you might already know.  So far, I’m really impressed and I’ve enjoyed working with it.  Since I already do a fair bit of Knockout development, I like the fact that Durandal uses KO and several other things I know such as Requirejs.

    I’ve made SPA-like parts to web apps before but I always found it hard to manage all of the bits and pieces that go together to make an app.  For example, modal dialogs were typically a pain to implement.  In Durandal, it basically handles the management of the modal’s appearance and how its view is retrieved and dynamically bound to the view model that you create.  The development of a Durandal app basically goes like this:

    • Break up your app into views with complementary view models (the views are HTML files with KO bindings and the view models are just JavaScript classes or object literals).  The view model is written as one RequireJS module.  The modularity of your application is one of the great strengths of this framework and really is more of a RequireJS thing than a Durandal thing.  But Durandal does tie all of it together so think of it as a coordinator between libraries rather than its own implementation. 
    • You then setup your navigation and routing.  Currently, Durandal is route-engine agnostic and supports a plug-in model to support routing.  It ships with a SammyJS-based routing engine which is pretty easy to use.  This is one area that I personally lacked some knowledge in, but SammyJS is pretty easy to learn to do most common tasks.
    • Once you get views and view models together, you can move on to advanced stuff like view composition and eventing in Durandal.

    I think one of the biggest strengths of Durandal is that it has a very powerful view composition system.  This basically allows you to find views, merge them with a view model and inject them into your DOM with ease.  You can use composition to swap out or render sub-sections of a page (such as a tab content area) or you can even do awesome things like recursive composition to build tree views or menus with sub-menu capabilities.

    If you are a Pluralsight member, I suggest checking out John Papa’s course on SPAs where he talks about Durandal (and many other aspects of SPAs). 

    The only bad part so far for me is that I wish I had known about this framework six months ago to use it in my current project.  I am currently thinking of refactoring to using Durandal.

    Categories: JavaScript

  • JavaScript Libraries and Frameworks

    I’ve been doing a lot of client-side development lately.  Our web browsers are becoming more capable with each new version.  Browser inconsistencies are disappearing behind standards, polyfills, and abstractions in good JavaScript libraries.  I thought that in this post I would list all of the JavaScript libraries that I use or have used and found to be quite good.  These libraries are extensible, documented, and are well-tested.  They have worked for me in professional and personal projects.  I will probably be adding to this list over time:

    • Durandal.js – a SPA (single page application framework) that adds powerful view composition.  It uses what you might already know (like Knockout.js, SammyJS, and RequireJS).  If you are building a SPA and aren’t using a formal framework like AngularJS, you should check this out.
    • Knockout.js – an MVVM (model-view-viewmodel) library for the web.  This adds data-binding capabilities to your app so your UI stays in sync with your JavaScript models through two-way data binding.  Also known as KO.
    • KoLite – this is small collection of KO extensions that I find useful.  In particular, I like the “command” binding handling that adds a way to add XAML like ICommand-ness to KO. 
    • RequireJS – I use this in conjunction with Durandal as it is a requirement of Durandal.  It allows you to organize your code into “modules” – a programming feature lacking from JS.
    • SammyJS – this is a client-side routing engine that is a default routing plugin for Durandal. 
    • jQuery and jQuery UI – everybody knows these two.
    • toastr – a small and effective notification library that “toasts” a message to the user.  It is so simple and looks very beautiful too.
    • accounting.js – this small library helps with parsing and formatting monetary amounts in JS.  I use this a lot with professional projects because most of the work I do involves capturing and displaying monetary amounts (as do a great deal of applications).
    • mustache.js – a small string template system for when you want to generate HTML using string templates (as opposed to Knockout’s or Angular’s DOM-based templating).  I use this only when I need to work with a third-party control that allows custom templating but templates must be delivered as strings.  In general, DOM templates tend to be better in my opinion.
    • date.format.js – a small date/time parsing and formatting library that works quite well.  I also hear that moment.js is really good, but have not used it.  JS’s support for Dates is pretty bad so these libraries help ease the pain, considerably.

    Most of these libraries have packages on NuGet.  Some are on npm too.

    Categories: JavaScript

  • Building a Knockout.js Extender for Boolean Values

    Many times in my UI, I have a pair of radio buttons that represent two Boolean values such as a question that has a Yes/No answer that the user must make.  By default, a KO observable bound to these radio buttons will be set to the value of the input element that represents the radio button.  For these types of situations, this is not what I want.  What I really want to do is have the underlying value of the observable stay as a Boolean value (true/false) rather than as a string.   I want this because this underlying value is what I want to POST to the server.  Even though radio buttons deal in string values, they are actually modifying a Boolean value in this case.

    What we need is a Knockout.js extender that adds new functionality to these specific observables so that the underlying Boolean value can be preserved.  Here’s the code:

    ko.extenders["booleanValue"] = function (target) {
        target.formattedValue = ko.computed({
            read: function () {
                if (target() === true) return "True";
                else if (target() === false) return "False";
            },
            write: function (newValue) {
                if (newValue) {
                    if (newValue === "False") target(false);
                    else if (newValue === "True") target(true);
                }
            }
        });
    
        target.formattedValue(target());
        return target;
    };

    This code uses a technique that I really like.  It attaches a KO computed observable as a property of the actual observable (in this case, target).  This sub-observable is called formattedValue and this is what you actually bind to in your HTML data-bind attribute.  This technique is cool because this observable is hidden away from ko.toJS() and other functions that don’t see it.  When you serialize your observable back to the raw data values you want to POST, it melts away. 

    Since the formattedValue computed is a writeable computed, you can read and write to it.  The read function will test the underlying observable (remember this is a true JS Boolean value).  It will then convert this to a string value (by convention, “True” or “False”).  The write function will do the opposite: it will test the incoming string value (this is from the HTML control), and will convert to the proper Boolean value on the actual observable.

    To use the extender on your model, you’d do something like the following:

    function Order() {
      this.wantsFries= ko.observable(false).extend({ booleanValue: null });
    }

    The answer property now has a sub-observable (formattedValue) that can be bound to a series of radio buttons to get the correct behavior:

    <span>Do you want fries with that?</span>
    <label>
      <input type="radio" name="question" value="True" 
                 data-bind="value: wantsFries.formattedValue" /> Yes
    </label>
    <label>
      <input type="radio" name="question" value="False" 
                 data-bind="value: wantsFries.formattedValue" /> No
    </label>

    When the user clicks one of the radio buttons, the correct true/false value will be sent into the underlying observable and is ready to be unwrapped and sent to your server.  The main point of this example, I believe, is the power in these sub-observables.  I’ve found this technique to be very clean and useful.

    Categories: JavaScript

    Tags: Knockoutjs

  • Stuff I love: Knockout.js

    I love Knockout.js.  If you haven’t heard of it, it’s a JavaScript library for doing complex UI using simple HTML5 bindings to your JavaScript code and takes care of synchronizing the UI with your data automatically.  It’s basically the MVVM pattern on the web.  I use it almost everyday in my current professional project.

    To use it, you create a JavaScript object model that represents the business objects that are a part of your page (for example, let’s say you are making a movie browser and therefore your object model contains an object for Movie with properties like Title, Description, Rating, etc).  With this object model, you wrap your properties in what are known as observables.  Observables are functions that ensure that when their underlying value changes, any bound UI will automatically change. 

    Knockout.js also handles the other way – if a UI records a change in input (say, a text box changing in value), the new value gets sent into the observable.  This means that KO handles two-way data binding. 

    The website for Knockout really does a great job of explaining what it does as well as documenting all the features.  It’s got some of the best documentation I’ve seen on an open source project.  You should check out the tutorials if you are brand new to it.

    One of the things that I like best about KO is that it is so extensible.  I can write extenders, bindingHandlers, and subscribable functions to really extend the way that it works.  This allows me to go beyond the basics.  If you haven’t checked it out, Ryan Niemeyer’s Knock Me Out blog is indispensible if you are starting out with KO.  Go and read all of it, it’s that good.

    Over the next couple of days, I’m going to post some Knockout extenders that I’ve written or used over the past few months that I’ve found to work well.

    Categories: JavaScript

    Tags: Knockoutjs

  • 1