01 August 2014

eyeglasses in the hand over blurred background

When using KnockoutJS, the hasFocus binding is a smooth and sweet inclusion.  Using it in combination with the css binding simplifies some user interaction that could otherwise be a bit complex and error prone and require a lot more code.

In an application I am developing at the moment, I am designing it with sophisticated users in mind – those who use the keyboard as their primary means of user input and reserve the mouse for edge cases.  This doesn’t mean, though, that I can make that experience exclusive.  I also need to be able to support users clicking on user interface elements to move around in the application.  Because of my need and desire to have a heavy keyboard-centric user experience, I need to have a lot of code that responds to keyboard events.  Also, to make the user interface snazzy, I have styling that makes textboxes look like spans when a particular element doesn’t have focus and like a textbox when it does.  (I am aware that using the “not” pseudo-selector means this will not work in Internet Explorer 8 and older and I am fine with that in this application and for this usage.)

input:not(.editing) {     
border: none; }

 

At first, when thinking about wanting to have multiple textboxes on a user interface in the browser and styling that should apply only to the one currently under edit, one starts to think about having multiple events to have to worry about to make sure to handle gaining and losing focus and having to apply styling and responding to events.  This can become pretty painful.  With KnockoutJS, it’s a snap.  The key to the simplicity with which a knockout application can handle these changes is in the nature of the two-way binding that is the bread and butter of KnockoutJS in the first place.  By using hasFocus and binding it to a property of the viewmodel that is also bound to a CSS class, changes to the model or changes in the user interface cause focus and classes to change.  This means that simply through declarative binding in my markup, I’m able to handle changes to style, changes to focus, and respond to keyboard (and mouse) events.  In order to support the multiple things I’d like to see happen when a user interface input element gains or loses focus, I need to do nothing more than use KnockoutJS bindings.  Here is a sample of what a textbox looks like in my markup:

<input type="text" id="title" data-bind="value:title, css: {editing: editingTitle}, hasfocus:editingTitle, event: { 'keyup': $root.textboxKeyup }">

In this example, when a textbox gains focus, the editingTitle property gets changed to false as a result of the write portion of the two-way binding.  This notifies that css binding of an update to the viewmodel such that the “editing” class gets added to the input.  If one textbox has focus and the user clicks on another, the textbox with focus in the beginning loses it, causing an update to the viewmodel and a notification that results in a removal of the class and the newly focused textbox has the opposite result and both are now properly styled and with correct focus.  Therefore, the styling of elements and the status of the focus are kept in lock-step, regardless of whether focus changed because of mouse clicks, viewmodel code, or keyboard event handlers.  This is a slick and simple way of handling something that otherwise could be hairy and prone to bugs and due to missing event handlers and overlooked cases.

In the viewmodel, I have something like this:

function ViewModel(durationSeconds) {
     var self = this;
     self.title = ko.observable('');
     self.editingTitle = ko.observable(false);
     self.headline = ko.observable('');
     self.editingHeadline = ko.observable(false);
     ... }

 

There is nothing particularly exciting about this code – it’s pretty run-of-the-mill knockout viewmodel source.  I included it here merely for completeness in showing what this example looks like.

Complicated or simple.

So there you have it – binding the same property for an input to both a css class and to hasFocus makes it simple to declaratively emphasize the selected user interface element with whatever styling you choose and to not have to worry about remembering to remove that styling when the control blurs.



blog comments powered by Disqus