node-focusmanager.js revision 33238af221f82ed28e0724a5ca7fbf93b241157a
10139N/A* <p>The Focus Manager Node Plugin makes it easy to manage focus among 10139N/A* a Node's descendants. Primarily intended to help with widget development, 10139N/A* the Focus Manager Node Plugin can be used to improve the keyboard 10139N/A* When designing widgets that manage a set of descendant controls (i.e. buttons 10139N/A* in a toolbar, tabs in a tablist, menuitems in a menu, etc.) it is important to 10139N/A* limit the number of descendants in the browser's default tab flow. The fewer 10139N/A* number of descendants in the default tab flow, the easier it is for keyboard 10139N/A* users to navigate between widgets by pressing the tab key. When a widget has 10139N/A* focus it should provide a set of shortcut keys (typically the arrow keys) 10139N/A* to move focus among its descendants. 10139N/A* To this end, the Focus Manager Node Plugin makes it easy to define a Node's 10139N/A* focusable descendants, define which descendant should be in the default tab 10139N/A* flow, and define the keys that move focus among each descendant. 10139N/A* pseudo class is not supported on all elements in all 10139N/A* the Focus Manager Node Plugin provides an easy, cross-browser means of 10139N/A // Collection of keys that, when pressed, cause the browser viewport 10139N/A* The NodeFocusManager class is a plugin for a Node instance. The class is used 10139N/A* via the <a href="Node.html#method_plug"><code>plug</code></a> method of Node 10139N/A* and should not be instantiated directly. 11904N/A * Boolean indicating that one of the descendants is focused. 10139N/A * String representing the CSS selector used to define the descendant Nodes 10139N/A * whose focus should be managed. 10139N/A * <p>Node, or index of the Node, representing the descendant that is either 10139N/A * focused or is focusable (<code>tabIndex</code> attribute is set to 0). 10139N/A * The value cannot represent a disabled descendant Node. Use a value of -1 18745N/A * to remove all descendant Nodes from the default tab flow. 10139N/A * If no value is specified, the active descendant will be inferred using 10139N/A * <li>Examining the <code>tabIndex</code> attribute of each descendant and 10139N/A * using the first descendant whose <code>tabIndex</code> attribute is set 10139N/A * <li>If no default can be inferred then the value is set to either 0 or 10139N/A * the index of the first enabled descendant.</li> // The user passed a reference to a Node that wasn't one // Setting the "activeDescendant" attribute to the index // of a disabled descendant is invalid. * Object literal representing the keys to be used to navigate between the * next/previous decendant. The format for the attribute's value is * <code>{ next: "down:40", previous: "down:38" }</code>. The value for the * "next" and "previous" properties are used to attach * <a href="event/#keylistener"><code>key</code></a> event listeners. See * the <a href="event/#keylistener">Using the key Event</a> section of * the Event documentation for more information on "key" event listeners. * String representing the CSS class name used to indicate the Node instance * that currently has DOM focus. * Boolean indicating if focus should be set to the first/last descendant * when the end or beginning of the descendants has been reached. // Boolean indicating if the NodeFocusManager is active. // NodeList representing the descendants selected via the // "descendants" attribute. // Object literal mapping the IDs of each descendant to its index in the // "_descendants" NodeList. // Reference to the Node instance to which the focused CSS class (defined // by the "focusClass" attribute) is currently applied. // Number representing the index of the last descendant Node. // Array of handles for event handlers used for a NodeFocusManager instance. * @method _initDescendants * @description Sets the <code>tabIndex</code> attribute of all of the * descendants to -1, except the active descendant, whose * <code>tabIndex</code> attribute is set to 0. // If the user didn't specify a value for the // "activeDescendant" attribute try to infer it from // If the user didn't specify a value for the // "activeDescendant" attribute and no default value could be // determined from the markup, then default to 0. // Check to make sure the active descendant isn't disabled, // and fall back to the first enabled descendant if it is. // Need to set the "tabIndex" attribute here, since the // "activeDescendantChange" event handler used to manage // the setting of the "tabIndex" attribute isn't wired up yet. * @description Determines if the specified Node instance is a descendant * managed by the Focus Manager. * @param node {Node} Node instance to be checked. * @return {Boolean} Boolean indicating if the specified Node instance is a * descendant managed by the Focus Manager. * @method _removeFocusClass * @description Removes the CSS class representing focus (as specified by * the "focusClass" attribute) from the Node instance to which it is * @method _detachKeyHandler * @description Detaches the "key" event handlers used to support the "keys" * @description Prevents the viewport from scolling when the user presses * the up, down, left, or right key. * @method _attachKeyHandler * @description Attaches the "key" event handlers used to support the "keys" // For Opera and Firefox 2: In these browsers it is necessary to // call the "preventDefault" method on a "keypress" event in order // to prevent the viewport from scrolling. * @method _detachEventHandlers * @description Detaches all event handlers used by the Focus Manager. * @method _detachEventHandlers * @description Attaches all event handlers used by the Focus Manager. // For performance: defer attaching all event handlers until the // first time one of the specified descendants receives focus // Protected event handlers * @method _onDocMouseDown * @description "mousedown" event handler for the owner document of the * @param event {Object} Object representing the DOM event. // Fix general problem in Webkit: mousing down on a button or an // anchor element doesn't focus it. // For all browsers: makes sure that the descendant that // was the target of the mousedown event is now considered the // Document doesn't receive focus in Webkit when the user mouses // down on it, so the "hasFocus" attribute won't get set to the * @description "focus" event handler for the owner document of the * @param event {Object} Object representing the DOM event. // The target is a descendant of the root Node. // The user has focused a focusable descendant. // The user has focused a child of the root Node that is // not one of the descendants managed by this Focus Manager // so clear the currently focused descendant. // The target is some other node in the document. * @description Keydown event handler that moves focus to the next * @param event {Object} Object representing the DOM event. * @param activeDescendant {Number} Number representing the index of the * next descendant to be focused * @description Keydown event handler that moves focus to the previous * @param event {Object} Object representing the DOM event. * @param activeDescendant {Number} Number representing the index of the * next descendant to be focused. * @method _afterActiveDescendantChange * @description afterChange event handler for the * "activeDescendant" attribute. * @param event {Object} Object representing the change event. * @description Focuses the active descendant and sets the * <code>hasFocus</code> attribute to true. * @param index {Number} Optional. Number representing the index of the * descendant to be set as the active descendant. * @param index {Node} Optional. Node instance representing the * descendant to be set as the active descendant. // In Opera focusing a <BUTTON> element programmatically // will result in the document object getting focus first, // immediately followed by the <BUTTON> element. // This results in the "_onDocFocus" handler incorrectly // setting the "hasFocus" Attribute to false. To fix this, // set a flag ("_focusTarget") that the "_onDocFocus" method // can look for to properly handle this edge case. * @description Blurs the current active descendant and sets the * <code>hasFocus</code> attribute to false. // For Opera and Webkit: Blurring an element in either browser // doesn't result in another element (such as the document) // being focused. Therefore, the "_onDocFocus" method // responsible for managing the application and removal of the // focus indicator CSS class name is never called. * @description Enables the Focus Manager. * @description Disables the Focus Manager by detaching all event handlers. * @description Refreshes the Focus Manager's descendants by re-executing the * CSS selector query specified by the <code>descendants</code> attribute. },
'@VERSION@' ,{
requires:[
'node',
'plugin']});