Version 7, changed by morris 07/17/2006. Show version history
This page is about the proposal to introduce one class and two global objects to provide centric hotkeys handling and focus management. The class introduced is Generic Hotkey Management Class (dojo.hotkeys), which provides per widget shortcuts support. One instance of dojo.hotkeys will be created in global namespace to handle global hotkeys (in a browser environment, no matter which widget is focused, registered global hotkeys will be triggered if pressed). Another global object, dojo.widget.FocusManager will be introduced to manage current focused widget and dispatch key events to it for per widget shortcuts supports.
This class can handle a widget's shortcuts: shortcuts can be registered/removed (and customized through a dedicated shortcuts editor in the future).
API to be discussed
This object is an instance of dojo.hotkeys. Widgets can manage (register/remove) global shortcuts with it. In addition, it can also detect shortcuts conficts.
API to be discussed
By default only form elements and A (link) element can have focus in a html page, however most widgets do not contain any of those so it is impossible for have them focused.
On the other hand, a parent of a widget where bubbling keyevents should go is not necessarily the DOM parent (such as in PopupMenu2 case), which makes a custom key bubbling support necessary.
dojo.widget.FocusManager object manages focused widgets and dispatches key events to the focused widget. Bubbling of key events is also handled by this object.
There are 2 possible approaches:
The first one was provided by David in an email to the dojo-interest list. It is the focus manager which keeps track of a list of focused widgets: It essentially stores an ordered list of focused components that would receive key events. Quoted from the email:
"Every time a component was selected with the mouse, it would go on top of the list and when it was closed (like a menu or panel), it would be removed from the list. When to focusmanager recieves a key event, it would fire the onKeyPressed(e) method of the first component in the list, check afterwards if the component allowed the event to bubble through, and if so, give the event to the next component on the list, etc. etc."
Another possible implementation, which is a generalized form of the PopupManager (used to be Menu2Manager), is to only maintain the current focused widget in the focus manager. A function of the widget class (let's call it widget.parentFocusWidget() for now) returns the parent widget which should receive key events if the current focused widget decides to allow the event to bubble through its parents.
Personally, I think the second approach is more object oriented and provides better granule for extensibility and maintenance.
FocusManager should also understand browser native focus event (such as using tab key to move focus on elements in the pages) and set the correct focused widget (if any) accordingly.
One other option is to use the native browser focus abilities. I (Morris) have looked a little bit into how this can be used - it almost works in IE6 and Firefox but there are some issues that need to be worked around.
Both IE6 and Firefox support a tabIndex property on the element (not in CSS) to allow elements to be tabbed to. Setting this to -1 disables normal tabbing focus. Setting this to a non-zero value allows the element to be tabbed to (e.g. look at how the TabContainer? widget allows keyboard navigation). I suspect Safari/KHTML supports this, but Opera 8.53 doesn't.
The focus halo can be disabled by setting the CSS property outline:none; so you can allow an element to get the focus without showing the dotted border around the element.
Using a suitable div in the widget template and giving it a tabIndex can solve some keyboard focus issues.One problem I have found with Firefox is that an element with overflow:auto; can also get the focus and it can't be disabled even by setting tabIndex=-1 or -moz-user-focus:ignore; and also I noticed a problem with focus causing scrollbars appearring due to the focus halo in some circumstances (I haven't made a test file for this - but it definitely happens for a widget I am developing). I noticed a problem with shift-tab and overflow:auto as well in Firefox, but I need to make a test file.
See http://morrisjohns.
There are quite a few IE specific features that may be useful to workaround IE problems e.g. onbeforedeactivate , document.activeElement, event.toElement, hideFocus, hasFocus, onactivate, onfocusin, onfocusout etc.
One problem with using the native focus primitives, is that under some circumstances the focus can shift to an element even though you want the keep the focus on a particular element (usually when clicking e.g. when clicking on an item in a dropdown for the combobox you want the focus to stay on the input and not move). Although you can move the focus back, the onblur event occurs, making the onblur event difficult to use (event cancelling may help but I didn't have much luck in Firefox). In IE an element that gets the focus is scrolled into view. This can be very troublesome for a page because the scrolling is unexpected, also if overflow is hidden then things just go pear shaped.