Improving Application Usability with Ext JS Keyboard Handling
September 23, 2008 by Rich Waters
As Enterprise applications begin moving to the web instead of the desktop many developers may forget about providing key bindings for their applications. Most web applications use the keyboard only for text entry and do not associate particular key combinations with user actions. By providing this type of key handling, particularly for applications which require a lot of data entry, we can improve the end-user experience.
While at a recent client engagement, we wanted to provide a smooth transition for users skilled at working with a legacy ‘green screen’ application to using a new Ext JS version. Part of this transition involved enabling power users to continue navigate the application with the same key handling. By the end-users not having to remove their hands from the keyboard, their efficiency increases substantially. Here’s some insight into how we accomplished the task at hand.
Ext.KeyMap
Ext provides several components that support keyboard navigation out of the box such as GridPanel, ComboBox, and TreePanel. To implement custom keyboard handling, developers can use the Ext.KeyMap and Ext.KeyNav classes to attach keyboard bindings to any component or element they wish.
The first set of keys we wanted to handle was all of the Function keys (F1-12). While most browsers reserve some/all of these keys, with some ext-pertise, we are able to override the default function if need be for our application. The application we were working with was completely dynamic and server driven, so we really couldn’t define all of the handlers ahead of time. This led to us dynamically building an array of key handler configuration objects and passing them all through to our new Ext.KeyMap object.
var keys = []; for(var i = 0;i < buttons.length;i++) { var btn = buttons[i]; // fkey property contains a string referencing the Ext constants (ie: Ext.EventObject.F1) var fk = eval(button.fkey); btn.handler = this.handleKey.createDelegate(this, [fk]); keys.push({ key: fk, handler: this.handleKey.createDelegate(this, [fk]), stopEvent: true, scope: this }); }
This implementation demonstrates creating a toolbar and assigning function keys that would perform the same action when the button was clicked or when using the mouse. buttons is an array of button configurations that we pulled from the Json response from the server. The server is sending over a string which references some constants built into the Ext.EventObject for function keys. Since the data comes over as a string we can simply eval it and get the resulting number.
We use a generic handler for all of the click and keypress functions since it is all controlled from the server. createDelegate lets us pass along the key that was pressed so that we can share the same handler function regardless of if the event was a click or a keypress. With the keys array built and our handlers added into the buttons array, we are able to toss these into our Panel configuration and it will do the heavy lifting for us.
tabPanel.add({ title: 'Test Panel', tbar: buttons, keys: keys ... });
With our layout in place, adding a tab with our key handlers is pretty simple. The tbar parameter takes our array of Ext.Button configs that were server generated (aside from the handler), and the keys parameter takes an array to pass along to the Ext.KeyMap object.
Ext.KeyNav
The next set of key handling added was some additions to the grid keyboard navigation. The GridPanel has built in key navigation from the RowSelectionModel that it creates. Check out this grid example and select a row, you can then use the arrow keys to move up/down and even hold shift and press down to select a range of rows. We added a simple way to navigate through a large paged data set by extending GridPanel. The PagingToolbar provides keyboard handling once you’ve focused within the built-in TextField, but we wanted to allow the users to just hit ‘page down’ or ‘end’ when focus was anywhere within the GridPanel and ensure it functions as expected.
MyGrid = Ext.extend(Ext.grid.GridPanel,{ ... afterRender : function() { MyGrid.superclass.afterRender.call(this); this.nav = new Ext.KeyNav(this.getEl(),{ pageDown: this.pagingNav.createDelegate(this,['next']), pageUp: this.pagingNav.createDelegate(this, ['prev']), home: this.pagingNav.createDelegate(this,['first']), end: this.pagingNav.createDelegate(this,['last']), scope: this }); }, pagingNav: function(page) { var pt = this.getBottomToolbar(); if (!pt[page].disabled) { pt.onClick(page); } }, ... });
This is a snippet from an extended GridPanel class, and it assumes that there is an Ext.PagingToolbar in place and it is the bottom toolbar (bbar). We could certainly write this code without the PagingToolbar, but it has already done the work to calculate page sizes and has handlers in place for determining the proper load call when skipping backwards/forwards in pages. We create our new Ext.KeyNav object and apply it to the GridPanel’s underlying Ext.Element. KeyNav does the work of assigning handlers to the proper key codes and calls our pagingNav function with the parameter that we bound to it using createDelegate. The pagingNav function merely checks to see if that particular button is disabled, for instance if you’re on the last page, you cannot press the next button again, so we don’t let them “page down” again either. As long as that button is not disabled we act as if the user clicked on the page next button and let the PagingToolbar do it’s magic and load the proper page.
Utilizing these techniques we were able to provide a seamless keyboard navigation experience for our client and their customers migrating from the legacy application to the web application
Getting Started
As you can see, adding custom key handling within an Ext JS application is quite easy. For any custom keys, including function keys, alpha keys with or without modifiers (alt/shift/ctrl) there is Ext.KeyMap. For navigation, arrows, paging, home/end there is Ext.KeyNav. There’s some more handy example code available for each right within the API documentation if you need any further help getting started.

Posted on September 24th, 2008 at 6:28 am
[...] first class citizen for your applications, including on the Web. Thus, I was interested to read how Ext JS has keyboard handling that ties into the entire system: [...]
Posted on September 24th, 2008 at 6:56 am
How did you override the Function keys in EVERY browser?
Posted on September 24th, 2008 at 9:09 am
[...] first class citizen for your applications, including on the Web. Thus, I was interested to read how Ext JS has keyboard handling that ties into the entire system: [...]
Posted on September 24th, 2008 at 9:50 am
Does this work with Opera?
In the past, I tryed to make Fx keys work with Opera but some are reserved.
And more generaly, canceling a key event in Opera proved to be impossible!
So you can’t bind F5 to any JavaScript function: page will reload.
For a JavaScript game, I have to make sure the page has no scrollbar because using the direction keys will also scroll the page…
Posted on September 24th, 2008 at 10:11 am
[...] Ext JS Blog.) Posted by outaTiME Filed in ExtJS, [...]
Posted on September 24th, 2008 at 10:14 am
[...] first class citizen for your applications, including on the Web. Thus, I was interested to read how Ext JS has keyboard handling that ties into the entire [...]
Posted on September 24th, 2008 at 10:16 am
Thanks for this wonderful blog post. This will make my application much more user-friendly.
Some people had questions about overriding the default keys of a browser. I, however, had no problem with overriding the default keys.
This is what I’ve done:
[CODE]
var map = new Ext.KeyMap(element, [{
key: Ext.EventObject.F1,
stopEvent: true,
fn: function() { alert('f1 was pressed'); }
});
[/CODE]
The most important thing here is the stopEvent property. The code above works for me in Firefox 3. I would like to know whether this works in IE, Safari and Opera as well…
Posted on September 24th, 2008 at 11:02 am
// string referencing the Ext constants (ie:Ext.EventObject.F1)
var fk = eval(button.fkey);
It is possible to avoid the eval call, which is safter and more performant. For example by doing:
var fk = eval(Ext.EventObject[button.fkey]);
where button.fkey would instead be e.g. “F1″.
/Karl
Posted on September 24th, 2008 at 8:37 pm
[...] first class citizen for your applications, including on the Web. Thus, I was interested to read how Ext JS has keyboard handling that ties into the entire system: [...]
Posted on September 25th, 2008 at 10:57 am
Great stuff. For many users, the partner to keyboard handling is WAI-ARIA support. Does anyone know if Ext has plans to support this emerging W3C standard for making DHTML apps accessible? (Dojo has support, jQuery is adding it, all major browsers have ot are adding support)
http://mindforks.blogspot.com/2008/05/accessible-web-interactivity-today.html
D
Posted on September 27th, 2008 at 1:01 pm
[...] Ext JS - Improving Application Usability with Ext JS Keyboard Handling - As you can see, adding custom key handling within an Ext JS application is quite easy. For any custom keys, including function keys, alpha keys with or without modifiers (alt/shift/ctrl) there is Ext.KeyMap. For navigation, arrows, paging, home/end there is Ext.KeyNav. [...]
Posted on October 19th, 2008 at 4:16 pm
Теперь этот форум принадлежит мне. Все вопросы и предложения рассматриваются в icq 477345812
Posted on October 21st, 2008 at 4:20 am
Там, где наблюдается высокий уровень городского шума, и вместе с тем есть насущная необходимость “делать надолго, качественно и красиво”, настоящим избавлением стали пластиковые окна, Москва в этом плане исключением не является. Пластиковые окна ПВХ завоевали признание среди самых широких масс населения и стали пользоваться большой популярностью как у простых потребителей, так и у профессионалов - строительных и проектных организаций, и касается это не только таких крупных городов, как Москва, Берлин или Нью-Йорк, а всего мира в целом. Легкие, прочные, удобные в эксплуатации, прекрасно зарекомендовавшие себя с самых разных сторон, пластиковые окна стали необходимым атрибутом комфортной жизни. Строгий четкий контур, устойчивость к погодным явлениям и легкость в уходе сначала сделали пластиковые окна ПВХ идеальной деталью офисного или производственного интерьера, но затем, с совершенствованием технологии их изготовления, они пришли и в жилые дома. И если раньше еще могли оставаться какие-то сомнения по поводу того, пускать или не пускать в дом профили ПВХ, то сегодня их нет - современные пластиковые окна не только красивы и высококачественны, но и абсолютно безопасны в экологическом плане.
окна пвх московская область
Posted on October 28th, 2008 at 4:33 pm
Posted on October 29th, 2008 at 6:07 pm
Продажа Садовой мебели из тика со склада в Москве, парковая мебель из тика, мебель для кафе .
Раскладные Шезлонги, лежаки, столики, стулья, кресла. Раздвижные столы. Обработано натуральным тиковым маслом. Доступные цены,
супер качество, прямые поставки со склада. (495) 5435811
Posted on November 18th, 2008 at 11:07 am
we are trying to use KeyMap and wanted to override the alt + d trigger and execute the user defined function. It works in IE6,FF3.0 properly and DO NOT WORK in IE7.
What could be the reason?
Following is the code snippet used..
var map = new Ext.KeyMap(document, [
{
key: 'd',
alt: true,
fn: function(){ alert("D was pressed"); }
}, {
key: "abc",
fn: function(){ alert('a, b or c was pressed'); }
}, {
key: "\t",
ctrl:true,
shift: false,
fn: function(){ alert('Control + shift + tab was pressed.'); }
}
]);