Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

HTML5 Knockout TriState Tree Control

4.67/5 (5 votes)
22 Oct 2012CPOL4 min read 34.7K   1.7K  
Used HTML5 Knockout MVVM binding to make TriState Tree Control

Image 1

Introduction 

There is no denying that the popularity of HTML5 and JavaScript is on the rise. Complex web applications which were previously the domain of plugin technologies (Silverlight, Flex, Flash, Java Applets) are now increasingly being written using JavaScript. Normal HTML Checkbox <input type="checkbox" checked="true" />) is just having two state (Check and Uncheck). When we required Tri state checkbox (Check, Uncheck and Indeterminate) with tree structure then it’s not possible to used regular HTML controls. So I am using KnockoutJS MVVM and HTML5 JavaSript framework to make Tri State Tree Control.

Background

In order to understand the code for the demo, let us first discuss the Knockoutjs.com binding framework

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model. Any time you have sections of UI that update dynamically (e.g., changing depending on the user’s actions or when an external data source changes), KO can help you implement it more simply and maintainably.

Headline features:

  • Elegant dependency tracking - automatically updates the right parts of your UI whenever your data model changes.
  • Declarative bindings - a simple and obvious way to connect parts of your UI to your data model. You can construct a complex dynamic UIs easily using arbitrarily nested binding contexts.
  • Trivially extensible - implement custom behaviors as new declarative bindings for easy reuse in just a few lines of code.

Additional benefits:

  • Pure JavaScript library - works with any server or client-side technology
  • Can be added on top of your existing web application without requiring major architectural changes
  • Compact - around 13kb after gzipping
  • Works on any mainstream browser (IE 6+, Firefox 2+, Chrome, Safari, others)
  • Comprehensive suite of specifications (developed BDD-style) means its correct functioning can easily be verified on new browsers and platforms

For those interested in more in-depth tutorial, I highly recommend the Knockoutjs website

Currently I am finding solution to convert existing Silverlight App to HTML5. I started with knockoutjs and HTML5 to build controls stack for conversion.

I had done with Tri state Check box using Images and HTML controls. Then I used Tri state Checkbox to make Tri state Checkbox Tree Control.

Using the code

Tri State Tree Control is tree control with three status (Check, Uncheck and Indeterminate) checkbox

We have following two models and two Views to represent control
  • ClsTriStateCheckBox : CheckBox Model
  • ClsTriStateTreeNode: Tree View Model
  • Template for Tri state Checkbox : CheckBox View
  • Template for Tri state Checkbox Tree : Tree View

ClsTriStateCheckBox function ClsTriStateCheckBox(parent,cNode, displayTextLength) Has following Properties, Method and Parameter

Parameters

  • parent Reference to parent object control
  • cNode Tree Object to load Initial data (Sample object is in cNodeSampleData.js)
  • displayTextLength Integer Number to trim display text
    JavaScript
    Var cNode =displayText: 'Node1-3-2',
    defaultState: false,
    Childs:
    [{ displayText: 'Node1-3-1',
    defaultState: false,
    Childs: []
    },
    {
    displayText: 'Node1-3-2',
    defaultState: false,
    Childs: []
    }]

Properties

  • Self.State = ko.observable(); To hold current status
  • Self.DisplayText = ko.observable(); To display trimmed text after checkbox
  • Self.Title = ko.observable(); To display text on mouse over
  • Self.EnumState - Enum for State
  • JavaScript
    Self.EnumState = {
        UNCHECKED: ko.observable(0x1), 		// int = 1 in decimal and 01 in binary
        CHECKED: ko.observable(0x2), 		// int = 2 in decimal and 10 in binary
        INDETERMINATE: ko.observable(0x3) 	// int = 3 in decimal and 11 in binary
    };

Methods

  • Self.LoadStatus = function (inputState) Change State Function
  • Self.ChangeStatus = function () onclick event - bind with checkbox control for status change
  • Self.UpdateIndeterminate = function () onclick event - Update status to Indeterminate of checkbox

ClsTriStateTreeNode function ClsTriStateTreeNode(parent, cNode, displayTextLength, lavelToExpanded, currentLavel) Has following Properties, Method and Parameter

Parameters

  • parent Reference to parent object control
  • cNode Tree Object to load Initial data (Sample object is in cNodeSampleData.js)
  • displayTextLength Integer Number to trim display text
  • lavelToExpanded Number of tree node levels check box will get expanded
  • currentLavel Current Tree node level
    JavaScript
    if (lavelToExpanded == null) lavelToExpanded = 0;
    if (currentLavel == null) currentLavel = 1;
    if (lavelToExpanded == 0) {
    isExpandedChild = false;
    } else if (lavelToExpanded < 0) {
    isExpandedChild = true;
    } else if (lavelToExpanded >= currentLavel) {
    isExpandedChild = true;
    } else {
    isExpandedChild = false;;
    }

Properties

  • Self. CurrentNode = ko.observable(); To hold current checkbox Model of type ClsTriStateCheckBox
  • Self. ChildNodes = ko. observableArray (); To hold List of Self Object type Model - ClsTriStateTreeNode
  • Self. Hasi= ko.observable(); To Indicate Current node has Child nodes
  • Self. ShowChild= ko.observable(); To toggle child node display
  • Self. CurrentStatus= 0; Use to update Current Status as per child node status

Methods

  • Self. ExpandChild = function () To Expand Child nodes display
  • Self. ResetStatus = function () Update current status according child status to reset parent
  • Self. UpdateChildStatus = function () Update All Child of current tree with updateStatus para. Call this method to change all child to updateStatus when any node status change to updateStatus
  • Self. SetTriStatus = function () Use recursion to update child first then parent. After changing child status according their child status, Update current status according child status to reset parent used following principle
    Bitwise OR
        UNCHECKED-1(01) & CHECKED-2(10) = INDETERMINATE 3(11)
        UNCHECKED-1(01) & UNCHECKED-1(01) = UNCHECKED 1(01)
        CHECKED-2(10) & CHECKED-2(10) = INDETERMINATE 2(10)

HTML5 Knockout "template" binding

After creating models for view I am using "template" binding of knockout to define views for controls models. View Template for Tri state Checkbox Tree is nested template with having recurcive call him self for tree child nodes.

Template for Tri state Checkbox

XML
<script type="text/html" id="TriStaeCheckBox-Template">
    <div class="CheckBoxOuterDiv" data-bind="click:ChangeStatus,attr: {title:Title}">
        <img data-bind="css: { UncheckedCheckBox: State() == EnumState.UNCHECKED(), 
          CheckedCheckBox: State() == EnumState.CHECKED(),
          IndeterminateCheckBox: State() == EnumState.INDETERMINATE()}">
    <span class="CheckBoxDisplayText" data-bind="text: DisplayText" />
    </div>
</script>

Template for Tri state Checkbox Tree

XML
<script type="text/html" id="TriStaeCheckBoxTree-Template">
    <table>
        <tr>
            <td style="width: 16px; padding: 0px;">
                <img data-bind="click:ExpandChild,css: { ExpandCheckBoxTree: 
                   !ShowChild(),CollapseCheckBoxTree: ShowChild},visible:HasChild">
            </td>
            <td style="margin: 0px; padding: 0px; text-align: left">
                <div data-bind="template: { name: 'TriStaeCheckBox-Template', data: CurrentNode }" />
            </td>
        </tr>
        <tr data-bind="visible:ShowChild" >
            <td colspan="2" style="margin: 0px; padding: 0px; text-align: left">
                <div data-bind="if: HasChild">
                    <ul style="list-style: none; padding-left: 20px" 
                       data-bind="template: { name: 'TriStaeCheckBoxTree-Template', foreach: ChildNodes }" />
                </div>
            </td>
        </tr>
    </table>
</script>

References and Resources

  1. http://www.codeproject.com/Articles/365120/KnockoutJS-vs-Silverlight: CodeProject article by Colin Eberhart, compares MVVM development using KnckoutJS and Silverlight. Excellent resource for Silverlight developers getting started with HTML5 and JavaScript.
  2. http://knockoutjs.com/KnockoutJS home page. This is the ultimate resource on KnockoutJS. It contains conceptual information, documentation, samples, and tutorials.
  3. http://jqueryui.com/: jQueryUI home page. The official resource for jQueryUI, including documentation and samples for the controls (widgets), effects, and utilities included with jQueryUI.4. http://typescript.codeplex.com/: TypeScript home page. The TypeScript compiler adds type information, static error-checking, and IntelliSense to JavaScript.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)