Announcement

Thursday, September 06, 2012

'shortcut' binding for KnockoutJS

[NOTE : This post was originally published on  BootStrapToday blog as "Shortcut binding for Knockoutjs"]

Now that we have BootStrapToday V3 based on KnockoutJS in production, we are working on various enhancements to improve user experience. One of the enhancement we have added in this release, is Keyboard shortcuts for various operations (Ctrl+Enter for form submit, Esc for cancel and various other shortcuts). However, implementing shortcuts is tricky. Basically we wanted to do the following
  • Simulate A 'click' on some attached html element when user presses the shortcut key.
  • The shortcuts can contain the modifier keys like 'ctrl or meta', 'alt' and special keys like 'enter' or 'escape'.
  • Since we dynamically 'load' various pages, different shortcuts will be available at different points, or same shortcut will behave differently on different pages. For example, when 'e' is pressed when Ticket view is visible, will open the ticket edit form, same key will open 'milestone' edit when milestone view is visible. Hence any event handler attached has to be removed and new handler need to be added when the context changes.
  • Different browsers behave slightly differently. For example, 'ctrl+enter'  will trigger 'keydown' event but not the 'keypress' event in some browsers. Chrome capture Ctrl+F and Alt+F, so we cannot use some combinations.
  • Consider a situation, where shortcut key is 'n'. I  added an 'event handler' to handle the keypress. Now if form is open and focus is on form input field, if user presses 'n', shortcut will be triggered. Obviously this is not expected. So shortcuts without modifiers have to be ignored, when focus is on some form input field.
  • Sometimes the element is not visible (for example, drop down menus). In such cases, click should be triggered only when the element is visible.
There are lots of complications involved. Since every page requires some shortcuts to be defined, it was time for a custom knockout binding. So I am going to show you how I developed the shortcut binding handling all the complexities mentioned above. It's not perfect and may require more tweaks.

Version 1:

I started with a simple approach of adding a jquery event handler for the 'keypress' event. The event handler is added to 'body' tag so that it works whatever element has focus. I used a regex to handle 'ctrl' modifier. The binding triggers a 'click' on the element attached to it.

 /*short cut binding handler. Defines a keyboard short for 'click' event */  
 ko.bindingHandlers.shortcut = {  
   init: function(element, valueAccessor, allBindingsAccessor,viewModel) {      
     var key = valueAccessor();      
     var regx = /ctrl\+/gi;  
     key = key.replace(regx,'');  
     var handler = function(event) {  
       if((event.metaKey || event.ctrlKey) && event.charCode == key.charCodeAt(0)) {      
         event.preventDefault();      
         event.stopPropagation();  
         $(element).click();  
         return false;    
       }  
       return true;  
     }  
     $('body').on('keypress', handler);  
   }  
 }  

Version 2:

This version handles 'alt' modifier as well. Sometimes the element is not visible (for example, drop down menus). In such cases, click should be triggered only when the element is visible. Hence I added a check to ensure that element is visible.

 ko.bindingHandlers.shortcut = {  
   init: function(element, valueAccessor, allBindingsAccessor,viewModel) {  
     var key = valueAccessor();  
     key = key.toLowerCase();  
     var match = key.match(/ctrl\+/gi);  
     var ctrl_modifier = (match && match.length > 0);  
     match = key.match(/alt\+/gi);  
     var alt_modifier = (match && match.length > 0);  
     key = key.replace(/(alt\+|ctrl\+)/gi,'');  
     key = key.charCodeAt(0);  
     var handler = function(event) {  
       //first check if the element is visible. Do not trigger clicks  
       // on invisible elements. This way I can add short cuts on  
       // drop down menus.  
       if($(element).is(':visible')) {  
         var modifier_match = ( ctrl_modifier && (event.metaKey || event.ctrlKey))  
           || ( alt_modifier && event.altKey );  
         if( modifier_match &&event.charCode == key) {        
           event.preventDefault();  
           event.stopPropagation();  
           $(element).click();  
           return false;  
         }  
       }  
       return true;  
     }    
     $('body').on('keypress', handler);  
   }  
 }  

Version 3:

Still the special keys like 'enter' and 'escape' are not handled. Also Safari/Chrome do not trigger 'keypress' event for special keys like 'escape'. So based on if shortcut is an alpha numeric key or special key, 'keypress' or 'keydown' event is used.

 var special_key_map = { 'enter': 13, 'esc': 27}  
 ko.bindingHandlers.shortcut = {  
   init: function(element, valueAccessor, allBindingsAccessor,viewModel) {  
     var key = valueAccessor();  
     key = key.toLowerCase();  
     var match = key.match(/ctrl\+/gi);  
     var ctrl_modifier = Boolean(match && match.length > 0);  
     match = key.match(/alt\+/gi);  
     var alt_modifier = Boolean(match && match.length > 0);  
     key = key.replace(/(alt\+|ctrl\+)/gi,'');  
     var keycode = null;      
     if( key in special_key_map) {      
       keycode = special_key_map[key];      
     }else {    
       keycode = key.charCodeAt(0);  
     }  
     var handler = function(event) {  
       //first check if the element is visible. Do not trigger clicks      
       // on invisible elements. This way I can add short cuts on      
       // drop down menus. if($(element).is(':visible')){  
       var modifier_match = ( ctrl_modifier == (event.metaKey || event.ctrlKey))  
         && ( alt_modifier == event.altKey );  
       if( modifier_match && (event.charCode == keycode || event.keyCode == keycode)) {  
         event.preventDefault();  
         event.stopPropagation();  
         $(element).click();  
         return false;    
       }  
       return true;  
     }  
     if( key in special_key_map) {  
       $('body').on('keydown', handler);  
     }else {  
       $('body').on('keypress', handler);  
     }  
   }  
 }  

Version 4:

Now shortcuts like just 'n' has to be ignored if the focus is on a form input field. However, shortcut like 'escape' or 'ctrl+n' (i.e. special key or with modifier) should work even when the focus is on form input. So lets add that condition as well.

 var special_key_map = { 'enter': 13, 'esc': 27}  
 ko.bindingHandlers.shortcut = {  
   init: function(element, valueAccessor, allBindingsAccessor,viewModel) {  
     var key = valueAccessor();      
     key = key.toLowerCase();  
     var match = key.match(/ctrl\+/gi);      
     var ctrl_modifier = Boolean(match && match.length > 0);  
     match = key.match(/alt\+/gi);      
     var alt_modifier = Boolean(match && match.length > 0);  
     key = key.replace(/(alt\+|ctrl\+)/gi,'');  
     var keycode = null;  
     if( key in special_key_map) {  
       keycode = special_key_map[key];   
     }else {  
       keycode = key.charCodeAt(0);  
     }  
     // if no modifiers are specified in the shortcut (.e.g shortcut is just 'n')  
     // in such cases, do not trigger the shortcut if the focus is on  
     // form field.  
     // if modifier are specified, then even if focus is on form field  
     // trigger the shortcut (e.g. ctrl+enter)  
     var ignore_form_input=Boolean(ctrl_modifier || alt_modifier || key in special_key_map);  
     var handler = function(event) {  
       //first check if the element is visible. Do not trigger clicks  
       // on invisible elements. This way I can add short cuts on  
       // drop down menus.  
       var $element = $(element);        
       var $target = $(event.target);  
       var is_forminput = Boolean($target.is('button')==false && $target.is(':input')==true);  
       if($element.is(':visible') && (ignore_form_input==true || is_forminput==false)) {  
         var modifier_match = ( ctrl_modifier == (event.metaKey || event.ctrlKey))  
           && ( alt_modifier == event.altKey );  
         if( modifier_match && (event.charCode == keycode || event.keyCode == keycode)) {  
           event.preventDefault();  
           event.stopPropagation();  
           $element.click();  
           return false;  
         }  
       }  
     return true;  
     }  
     if( key in special_key_map) {  
       $('body').on('keydown', handler);  
     }else {  
       $('body').on('keypress', handler);  
     }  
   }  
 }  

Version 5 (Final):

So far we are not removing the attached event handlers. Obviously it's not a good idea especially if binding get evaluated multiple times and event handler gets attached multiple times. To remove the event handler, we have to define a 'dispose' callback which gets called, whenever the element (to which the binding is attached) is disposed/deleted from the DOM.

 /*  
 * Copyright 2012 Sensible Softwares Pvt. Ltd, India. (http://bootstraptoday.com)  
 *  
 * Licensed under the MIT License. (http://opensource.org/licenses/mit-license.php)  
 *  
 */  
 var special_key_map = { 'enter': 13, 'esc': 27}  
 ko.bindingHandlers.shortcut = {  
   init: function(element, valueAccessor, allBindingsAccessor,viewModel) {  
     var key = valueAccessor();  
     key = key.toLowerCase();  
     var match = key.match(/ctrl\+/gi);    
     var ctrl_modifier = Boolean(match && match.length > 0);  
     match = key.match(/alt\+/gi);  
     var alt_modifier = Boolean(match && match.length > 0);  
     key = key.replace(/(alt\+|ctrl\+)/gi,'');  
     var keycode = null;  
     if( key in special_key_map) {  
       keycode = special_key_map[key];  
     }else {  
       keycode = key.charCodeAt(0);  
     }  
     // if no modifiers are specified in the shortcut (.e.g shortcut is just 'n')  
     // in such cases, do not trigger the shortcut if the focus is on  
     // form field.  
     // if modifier are specified, then even if focus is on form field  
     // trigger the shortcut (e.g. ctrl+enter)  
     var ignore_form_input=Boolean(ctrl_modifier || alt_modifier || key in special_key_map);  
     var handler = function(event) {  
       //first check if the element is visible. Do not trigger clicks  
       // on invisible elements. This way I can add short cuts on  
       // drop down menus.  
       var $element = $(element);  
       var $target = $(event.target);  
       var is_forminput = Boolean($target.is('button')==false && $target.is(':input')==true)  
       if($element.is(':visible') && (ignore_form_input==true || is_forminput==false)) {  
         var modifier_match = ( ctrl_modifier == (event.metaKey || event.ctrlKey))  
           && ( alt_modifier == event.altKey );  
          if( modifier_match && (event.charCode == keycode || event.keyCode == keycode)) {  
           event.preventDefault();   
           event.stopPropagation();  
           $element.click();  
           // event is handled so return false so that any further propagation is stopped.  
           return false;    
         }  
       }  
       // event is not handled. Hence return true so that propagation continues.  
       return true;  
     }  
     var eventname='keypress';  
     if( key in special_key_map) {    
       eventname = 'keydown';  
     }  
     $('body').on(eventname, handler);  
     var removeHandlerCallback = function() {    
       $('body').off(eventname, handler);  
     }  
     // Now add a callback on the element so that when the element is 'disposed'  
     // we can remove the event handler from the 'body'  
     ko.utils.domNodeDisposal.addDisposeCallback(element, removeHandlerCallback);    
   }  
 }  

That's the final version. So far it's working out very nicely in BootStrapToday. If we find any bugs or enhancements we will update here. Please feel free to suggest improvements.

You can check live by signing up for free from here.

License : Shortcut binding code above is licensed under MIT License.Same as KnockoutJS. So feel free to use it anyway that you want.

Wednesday, August 08, 2012

Useful code snippets for knockoutjs - Part 1

1. Function 'deferComputed' to create a computed observable with deferred evaluation.

Many times we want to create  'computed' observable with deferred evaluation. The syntax to create it is somewhat complex. So this is just a convenience function.

 deferedComputed = function(readfunc){  
   return ko.computed({read:readfunc, deferEvaluation:true});  
 };  

Now to create deferred computed observable, you can use var
 deferedObs = deferedComputed(function() { /* code to compute the observables value */ });  

2. yes/no binding:

Suppose you have observable that contains a Boolean value (true/false), many times it is not appropriate to display this value as 'true/false'. It is better to display this value as 'yes or no'.  'YesNo' binding converts a boolean variable into 'yes' or 'no' text.

 ko.bindingHandlers.yesno = {  
   update: function(element,valueAccessor){  
     var text = 'no';  
     var value = ko.utils.unwrapObservable(valueAccessor());  
     if(value) { text = 'yes'; }  
     $(element).text(text);  
   }  
 };  

Wednesday, July 11, 2012

Django connection pooling using sqlalchemy connection pool

As you know, Django uses new database connection for each request. This works well initially. However as the load on the server increases, creating/destroying connections to database starts taking significant amount of time.  You will find many questions about using some kind of connection pooling for Django on sites like StackOverflow . For example, Django persistent database connection. 

At BootStrapToday we use sqlalchemy's connection pooling mechanism with Django for pooling the database connections. We use variation of approach by Igor Katson described in http://dumpz.org/67550/.  Igor's approach requires patching Django which we wanted to avoid. Hence we created a small function that we import in one of __init__.py (or models.py) (i.e. some file which gets imported early in the application startup).


import sqlalchemy.pool as pool
pool_initialized=False

def init_pool():
     if not globals().get('pool_initialized', False):
         global pool_initialized
         pool_initialized = True
         try:
             backendname = settings.DATABASES['default']['ENGINE']
             backend = load_backend(backendname)

             #replace the database object with a proxy.
             backend.Database = pool.manage(backend.Database)

             backend.DatabaseError = backend.Database.DatabaseError
             backend.IntegrityError = backend.Database.IntegrityError
             logging.info("Connection Pool initialized")
         except:
             logging.exception("Connection Pool initialization error")

#Now call init_pool function to initialize the connection pool. No change required in the
# Django code.
init_pool()

So far this seems to be working quite well.

Tuesday, June 19, 2012

CSS and Icon sprites - tips and tricks

[NOTE : This post was originally published on  BootStrapToday blog as "CSS and Icon sprites – tips and tricks"]

We used image sprites for icons on bootstraptoday.com for version 2.0 and also in the latest version that we are working on (version 3). Quickly I realized that making sure that the icons looks same on major browsers is a task in itself.  For example, when you have an empty 'span' element which is supposed to display the icons, different browser will treat it slightly differently. Some browsers will give it a height/width of 1 character, some browsers height same as line height but width will be 0. If your icons are not arranged properly then putting those icons on buttons with consistent look & feel is a nightmare.  So here are few tips to define the icon image sprites and to use them effectively.

  1. First and most important tip is to have single sized icons in one sprite and arrange them in a grid. So if you have two icon sizes (e.g. 16px and 24px), make two sprites. One for 16px icons arranged on 16px X 16px grid. Another for 24px icons arranged on 24px X 24px grid.  Check the twitter-bootstrap icons.

  2. Use LessCSS or (some other equivalent) to define the icons css.

  3. Use span as 'display:inline-block'.  Typically span elements are inline elements. And you cannot define width/height of an inline element. Since we need to place the icons inline but need the flexibility of defining width/height, use 'display:inline-block'.

  4. Usually set the 'vertical-align:text-top'. This will align the icons to text.

  5. Use content:"". It will satisfy browsers which need to see text inside the span.
Here is a sample .less css fragment to be used with an icon sprite and
@icon-sprite-path:url(../images/icongrid.png);     /* url of the image path */
@icon-grid-size:16px;

.icongrid {
background-image:@icon-sprite-path:
background-repeat:no-repeat;

/* the element should be placed as 'inline' but we need flexibility to define width/height, padding etc*/
display:inline-block;

/* to ensure that each span is 'icon-grid-size' by 'icon-grid-size' square */
padding:@icon-grid-size/2;

/* to satisfy browsers which don't like empty elements */
content:"";

/* align the icons with text */
vertical-align:text-top;

}

/* define individual icon positions in sprite */
.testicon { background-position:0 -16px; }

Now you can use the icons with spans. For example to append the 'test icon' to some text, use
<div> ... your text here
<span class='icongrid testicon"></span>
</div>

Acknowledgement : I picked up some of these ideas by going over the twitter-bootstrap css and icon sprites.

Sunday, April 22, 2012

Teaching mindmapping to 10th Standard Students of Millenium National School

I learned mindmapping about 10-12 years back from Tony Buzan's Mindmap Book. For me Mindmaps work and i have used for everything from documenting software design, planning customer visits, preparing for training sessions/presentations etc etc.  Few years back, I taught mindmapping to my daughters. My elder daughter is now a regular mindmap user and she studies all the subjects using mindmaps. 

Many years I have been thinking that mindmapping will be an excellent life skill if we teach it our students at around 8th-9th grade. So I approached my daughters' school. Millenium National School and asked if I can teach mindmapping to 10th standard students.  School's director Arpita Karakare ma'am and Radhika teacher (coordinator) , Smita teacher were very enthusiastic about the idea. (BTW, I think this enthusiasm about trying out new ideas that can potentially benefit students is the distinguishing character of Millenium school.). Arpita ma'am and few Millenium teachers were already using mindmaps. Hence the concept was not new to school. 

We decided on following format 
  1. 4 hour introductory session for each division
  2. At the end of session give 4-5 topics (from science, history/civics, maths, geography) and students have to submit these 4-5 mindmaps in about 8-10 days time.
  3. I will evaluate these mindmaps and give suggestions for improvements.
So far I have done many corporate trainings on various topics. This was my first experience of teaching students. It was GREAT experience. Students enjoyed it. Some teachers also attended sessions. 

Interestingly many 'C' Division students made really Good mindmaps. 'A'  division students had many more questions/doubts and quickly wanted to try out different ideas. Also many 'A' division students tried mindmapping topics other than the topics for experiences. During followup sessions I could see the gradual improvements in mindmaps as students practiced more. And Mindmapping does require practice. Even after 12 years of using mindmaps, I still have to revise my mindmaps multiple times to completely organize my thoughts about a subject.

I don't know how of these students will remain regular mindmap users. But even if few of them use it regularly, it will give me great satisfaction.

In fact, Arpita ma'am told me about one student. His father called her and asked her that his son is suddenly very enthusiastic study and he is drawing all these pictures/maps. And is that ok ??.  She assured him that 'yes it is ok'. Its a 'great feeling' to be a part of such transformations.

Thanks Team Millennium for the opportunity and your support. (especially Radhika teacher, Smita teacher and Arpita ma'am and all the 10th Standard Students).

As usual here are few good links about Mindmapping.
  1. Tony Buzan's Mindmap Book on Google Books
  2. Tony Buzan giving a quick introduction to Mindmaps
  3. How to mindmap a Text book 
  4. 7 mind-mapping uses for Students. 
  5. Mindmap Art - Have some great examples of mindmaps.
 Some good Mindmap Software:
  1. MindManager Easy to use and has great MS Office integration
  2. iMindmap is developed by Tony Buzan. The iMindmap mindmaps look great.
  3. XMind - Open Source available in Linux, Windows, Mac. Good software to start.
  4. FreeMind -

Thursday, January 26, 2012

Comparison of Emberjs vs Knockoutjs

Recently I am experimenting with two Javascript MVC frameworks. Emberjs and Knockoutjs. Mainly to select the framework for the new UI design of BootStrapToday.
Yesterday I wrote a blog article about the experiences of using Emberjs and Knockoutjs with Django web framework.

Emberjs vs Knockoujs for Django projects

Monday, January 23, 2012

Emberjs vs Knockoutjs

Originally Published on BootstrapToday Blog

BootStrapToday is around for about 2 years now. Recently we have been working on making it faster. We have done many small changes and will continue to make improvements. We are also working on redesigning the user interface to make it simpler for the user and more maintainable for us.

Some background:

BootStrapToday uses django and postgresql on the backend. On the browser side, we have used jquery and a lot of custom javascript and ajax calls. All this custom javascript is slowly becoming difficult to maintain. Also making sure everything works on all major browsers is difficult. For example, today when a user uses ‘quick edit’ to edit a ticket and submits it, updating the status of tickets in the ticket list requires an ajax call to server to get updated list. This  increases load on server. Later this year we are also planning on creating a mobile app.

Hence we are  redesigning the UI and have some idea of how things will look like. We are also  looking around for a javascript framework that can help in making these ideas into reality. I started by looking around and got a useful comparison of various javascript MVC frameworks.  After studying for some more time, I decided to do a quick prototype of ticket list and ticket details+edit display using the Emberjs(SproutCore 2.0) and Knockoutjs frameworks. I am not an expert in Javascript. Hence it took me some time to create two prototypes. The code is probably not the ‘best examples’ of using Emberjs or Knockoutjs but it gave us an insight into what will work for us.

Specifically we were looking for following features.

  • UI Bindings: Client side Template, declarative bindings to models and auto updating views.

  • Works well with Django.

  • Works with jquery and other existing components.

  • Ajax.

EmberJs (SproutCore 2.0):

Ember is javascript MVC framework. As the Ember introduction says
Ember makes it easy to divide your application into models, views, and controllers, which improves testability, makes code more modular, and helps new developers on the project quickly understand how everything fits together. The days of callback spaghetti are over.

Ember also supplies built-in support for state management, so you'll have a way to describe how your application moves through various nested states (like signed-out, signed-in, viewing-post, and viewing-comment) out of the box.

First problem I faced with Ember is the ‘template syntax’. Ember uses Handlebars as template engine. At places Handlebar template syntax is similar to Django template syntax. So Django tries to parse this template and interpret it.  So the possible solutions were:

  • Use a different template system than Dajngo’s default template system. This was not a viable option since it meant that we  throw away all existing templates and also  educate the team on different template syntax.

  • Needed a way to tell Django ‘don’t interpret’ this part of the template. Unfortunately there is no good standard way to do this in Django. I ended up in using the ‘raw’ template tag described in ‘http://www.holovaty.com/writing/django-two-phased-rendering/’. However, this code is GPL licensed. We can use it for prototyping but we cannot include it in our product.

BootStrapToday uses slightly older version of jquery. It seems Ember requires jquery
1.71.6+  (Edit : Peter Wagenet has clarified that Emberjs works with jquery 1.6+ ).

Ember properties and computed properties worked well. Also, I implemented a computed property which when called, queried the necessary data from server using an ajax call. However, it means every time when a property value is queried, it will result in an ajax call. Obviously that’s not a very good idea. However, Ember has a nice touch that you can make a property ‘cacheable’. Once you marked a property as cacheable(), it stores the last returned value and reuses that instead of computing it again. That worked well for reducing the number of ajax calls.

Then I tried to implement Ticket edit functionality using the existing Django form. Currently Ember documentation is very limited on how to use various HTML input fields, and there is no information on using existing html forms with Ember properties. I could not figure out how to reuse the existing  Django forms. It means I had to re-implement the forms as Handlebars templates and input field ids etc. have to match with ids that Django expects. Other option was to write custom form fields which will generate the Handlebars template code rather than HTML generated by default Django fields.  This means a lot of work and not much benefit. This is one area where Knockoutjs declarative data-binding shines.

KnockoutJS

Knockout (KO)  is javascript MVVM framework.  KO Observables page has a small introduction to MVVM pattern. Key features of KO as described on the KO Introduction page are:


  • 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  complex dynamic UIs easily using arbitrarily nested binding contexts

  • Trivially extensible - implement custom behaviours as new declarative bindings for easy reuse in just a few lines of code.


The big advantage that KO has over Ember is the documentation. The documentation and Live Examples are a GREAT way to learn and experiment with KO.

KO template syntax is different than Django templates. So using KO with Django templates is simple.

KO Observables is somewhat equivalent to Ember properties. However there are few key differences. In Ember, the dependencies of properties are defined by the developer. In KO Observables, dependencies among observables are automatically determined.  Now this is good and bad. The good part is that as a developer you don’t have to worry about explicitly determining and defining dependencies.

KO Computed Observables documentation says following about the dependency tracking.

It’s actually very simple and rather lovely. The tracking algorithm goes like this:

  1. Whenever you declare a computed observable, KO immediately invokes its evaluator function to get its initial value.

  2. While your evaluator function is running, KO keeps a log of any observables (or computed observables) that your evaluator reads the value of.

  3. When your evaluator is finished, KO sets up subscriptions to each of the observables (or computed observables) that you’ve touched. The subscription callback is set to cause your evaluator to run again, looping the whole process back to step 1 (disposing of any old subscriptions that no longer apply).

  4. KO notifies any subscribers about the new value of your computed observable.

The line in bold has a side effect.  Let us suppose that I want to load some property from server (like description of a ticket) when it is accessed first time. Now since KO invokes the evaluator function immediately, it means it will trigger an ajax query to the server even though user may not need the property. Since KO invokes evaluator function, to get the dependencies of Computed Observable, if there is some way to manually define the dependencies then this evaluator call is not required. I could not find a way to do this. Hence I have to do some tricks to load make necessary data from server when user needs it. Basically I load the data in some click handling functions.

Also I could not find anything equivalent to ‘cacheable’ in Ember.

At this point loading a ticket list from server and displaying the details when a ticket is selected from list was working using KO and Ember.

Then I started implementing ticket edit functionality and here KO has significant advantage over Ember for our needs.  Because KO uses declarative data binding, attaching KO observables to an existing Django form was trivial and I could reuse existing Ticket edit form.  For testing I used a simple function like the one given below to add ‘data-bind’ attribute to various form fields. Then I called the ‘form.as_table’ in template and the bindings worked like charm.
def add_databinding(form, fld_observable_map):
'''
add data binding attribute to all form fields.
'''
    for name, field in form.fields.items():
        if name in fld_observable_map:
            field.widget.attrs['data-bind'] = "value:%s" % fld_observable_map[name]

Both KO and Ember are useful and interesting frameworks (something you should keep an eye on). However, today KO satisfies our needs better than Ember.

Now we are working on a django app to simplify using KO with Django. I will keep you updated on any interesting things that happen along the way.
Updates: BootStrapToday new design is based on Knockoutjs. You can watch the video below to see how new design based on KO looks like.




You can also signup for Free to test drive new design by clicking below

Signup for Free