Webby thoughts, most about around interesting applications of ecmascript in relation to other open web standards. I live in Mountain View, California, and spend some of my spare time co-maintaining Greasemonkey together with Anthony Lieuallen.

2006-02-18

I was just peeking at the BSD licensed YAHOO.util.Event library, wondering when there will show up a Javascript library that wraps keyboard event handling, taking key repeat into consideration. (This post is one ideal spot to announce and market your such a library, should you write or have happen upon one.)

The Google Maps API (v1) has most of this, but doesn't expose it to user level, and especially not so with real names for identifiers, documentation or any other bits to make it usable for an applications level developer.

To interface the keyboard as a control device for an application, you basically want these features:

keydown, keyup and keypress event callbacks for specific keys, keypress being fired on consecutive keydown and keyup events for the key in question, and not being fired by the host operating system's keyrepeat features

not triggering said callbacks when some text input field has keyboard focus

additional bonus points for allowing polling consumption of keypress events rather than just by way of fired callbacks right when the event is fired

Note that I am not talking about custom text input controls now; that is a separate use case issue the HTML input and textarea tags should hopefully suffice for, even though I know they don't as soon as you want to do anything advanced, such as handling selections, cut and paste and the like. I leave any such issues now, though; this article only concerns keyboard controls for full screen type applications, such as games for instance, or presentations.

Google Maps is an excellent example of an application that makes good use for these controls. When run with keyboard controls on, you can pan the map using the arrow keys, for instance, or whole pages using Page Up, Page Down, Home and End. (The Maps API does not enable this by default, but you can add them fairly easily add it -- if I remember correctly, it's done using map.registerKeyHandlers(window.document).)

A naïve implementation, registering with the DOM to receive keypress all events, would buffer up a busload of keypresses (due to key repeat, as set up in the end user's operating system) when a user keeps an arrow key down to scroll the map continuously, and keep processing queued-up events for some length of time after the user releases the key, which is clearly not what you want. Similarly, an application for a set top box interface I wrote at work last year, where icons scroll into view on pressing the remote control keys for "next" and "previous", had the same problem:

If you tap a key four times, you expect an action to be performed four times.

If you keep a key pressed, you expect some action to be performed continuously until you let go of the key

A keyboard handling library should leverage this mode of operation expected by the user, enabling you to easily realize that model. It is neither trivial nor very difficult, but it does need some base support along the lines of those discussed above. For the sake of fleshing out the details of the APIs, let's discuss how such an application would handle input (shamelessly modelled on one that the company I work for sells; feel free to contact sales@easyview.org if interested).

Pressing right or left scrolls the next icon into focus, rolling the line of icons one step in either direction. When in a "moving" state, we react instantly to events that would reverse scroll direction, but do not process events that would move in the same direction again, until the completion of one move step. When there, we consume a keypress, if enqueued, or keep scrolling, if we were told that the key is still in a pressed state. If no keys were on the input queue, and no key was still pressed down, we stop scrolling at the icon we ended up on.

As always, the best way of encouraging the broad masses to do good user interface design, is to show how it's done, and to make doing it really easy. The first is what tutorials and articles (such as this one) do, the second what libraries do. (Finally, making it possible at all is what the W3C does.) Your help in bringing about better overall design of new things coming is greatly appreciated, whichever end of the spectrum you contribute to.

I was just peeking at the BSD licensed YAHOO.util.Event library, wondering when there will show up a Javascript library that wraps keyboard event handling, taking key repeat into consideration. (This post is one ideal spot to announce and market your such a library, should you write or have happen upon one.)

The Google Maps API (v1) has most of this, but doesn't expose it to user level, and especially not so with real names for identifiers, documentation or any other bits to make it usable for an applications level developer.

To interface the keyboard as a control device for an application, you basically want these features:

keydown, keyup and keypress event callbacks for specific keys, keypress being fired on consecutive keydown and keyup events for the key in question, and not being fired by the host operating system's keyrepeat features

not triggering said callbacks when some text input field has keyboard focus

additional bonus points for allowing polling consumption of keypress events rather than just by way of fired callbacks right when the event is fired

Note that I am not talking about custom text input controls now; that is a separate use case issue the HTML input and textarea tags should hopefully suffice for, even though I know they don't as soon as you want to do anything advanced, such as handling selections, cut and paste and the like. I leave any such issues now, though; this article only concerns keyboard controls for full screen type applications, such as games for instance, or presentations.

Google Maps is an excellent example of an application that makes good use for these controls. When run with keyboard controls on, you can pan the map using the arrow keys, for instance, or whole pages using Page Up, Page Down, Home and End. (The Maps API does not enable this by default, but you can add them fairly easily add it -- if I remember correctly, it's done using map.registerKeyHandlers(window.document).)

A naïve implementation, registering with the DOM to receive keypress all events, would buffer up a busload of keypresses (due to key repeat, as set up in the end user's operating system) when a user keeps an arrow key down to scroll the map continuously, and keep processing queued-up events for some length of time after the user releases the key, which is clearly not what you want. Similarly, an application for a set top box interface I wrote at work last year, where icons scroll into view on pressing the remote control keys for "next" and "previous", had the same problem:

If you tap a key four times, you expect an action to be performed four times.

If you keep a key pressed, you expect some action to be performed continuously until you let go of the key

A keyboard handling library should leverage this mode of operation expected by the user, enabling you to easily realize that model. It is neither trivial nor very difficult, but it does need some base support along the lines of those discussed above. For the sake of fleshing out the details of the APIs, let's discuss how such an application would handle input (shamelessly modelled on one that the company I work for sells; feel free to contact sales@easyview.org if interested).

Pressing right or left scrolls the next icon into focus, rolling the line of icons one step in either direction. When in a "moving" state, we react instantly to events that would reverse scroll direction, but do not process events that would move in the same direction again, until the completion of one move step. When there, we consume a keypress, if enqueued, or keep scrolling, if we were told that the key is still in a pressed state. If no keys were on the input queue, and no key was still pressed down, we stop scrolling at the icon we ended up on.

As always, the best way of encouraging the broad masses to do good user interface design, is to show how it's done, and to make doing it really easy. The first is what tutorials and articles (such as this one) do, the second what libraries do. (Finally, making it possible at all is what the W3C does.) Your help in bringing about better overall design of new things coming is greatly appreciated, whichever end of the spectrum you contribute to.