index.mustache revision 5f9cae5c825d76bdc95b78301e460a46ec5fbdf4
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<div class="intro">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove When designing widgets that manage a set of descendant controls (i.e. buttons
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove in a toolbar, tabs in a tablist, menuitems in a menu, etc.) it is important to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove limit the number of descendants in the browser's default tab flow. The fewer
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove number of descendants in the default tab flow, the easier it is for keyboard
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove users to navigate between widgets by pressing the tab key. When a widget has
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove focus it should provide a set of shortcut keys (typically the arrow keys)
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove to move focus among its descendants.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove To this end, the Focus Manager Node Plugin makes it easy to define a Node's
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove focusable descendants, define which descendant should be in the default tab
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove flow, and define the keys that move focus among each descendant.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove Additionally, as the CSS
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <a href="http://www.w3.org/TR/CSS21/selector.html#x38"><code>:focus</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove pseudo class is not supported on all elements in all browsers,
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove the Focus Manager Node Plugin provides an easy, cross-browser means of
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove styling focus.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove{{>getting-started}}
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<h2>Using the Focus Manager Node Plugin</h2>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveTo use the Focus Manager Node Plugin, start by identifying the parent element
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveof the elements whose focus is to be managed. For example, consider the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovefollowing toolbar HTML:
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<div id="toolbar-1">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-add" value="Add">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-edit" value="Edit">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-print" value="Print">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-delete" value="Delete">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-open" value="Open">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-save" value="Save">
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveTo manage the focus of each button in the toolbar, start by retrieving a
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="../node">Node</a> instance representing the toolbar's root element
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove(<code><div id="toolbar-1"></code>).
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveNext, call the Node's
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/Node.html#method_plug"><code>plug</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovemethod, passing in a reference to the Focus Manager Node Plugin
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove(<code>Y.Plugin.NodeFocusManager</code>) as the first argument, followed by an
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveobject literal of configuration attributes as the second.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute to specify the child nodes of the root node whose
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovefocus is to be managed. The
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute accepts a string representing a CSS selector, making it
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevery easy to identify the elements whose focus should be managed. For the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovetoolbar, a value of "input" will be passed as the value of the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_keys"><code>keys</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute to identify which keys move focus between each of the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovespecified descendant Nodes. The
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_keys"><code>keys</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute accepts an object literal, the format of which is
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code>{ next: "down:40", previous: "down:38" }</code>. The value for the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code>next</code> and <code>previous</code> sub attributes are used to attach
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="../event/index.html#keylistener"><code>key</code></a> event listeners. Each
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevalue represents the type of event
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove("down" for <code>mousedown</code>, "up" for <code>mouseup</code>, and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove"press" for <code>keypress</code>) and key codes ("40" for the down arrow key)
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveto use to navigate to the next/previous descendant. For the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_keys"><code>keys</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute will be set to a value of
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code>{ next: "down:39", previous: "down:37" }</code>, enabling the user to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovemove focus among each button using the left and right arrows keys.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovethe <a href="../event/index.html#keylistener">Using the key Event</a> section of
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovethe Event documentation for more information on "key" event listeners.)
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" }
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_circular"><code>circular</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute to indicate that focus should be directed to the first
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveor last descendant when the user has navigated to the first or last descendant.
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" },
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove circular: true
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<h3 id="activedescendant-attribute">The <code>activeDescendant</code> Attribute</h3>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveThe <a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveattribute represents which of the Focus Manager's
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a> is either
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovecurrently focused or is focusable (<code>tabIndex</code> attribute is set to 0).
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveAs the user moves focus among the Focus Manager's defined descendants, the <a href="../api/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute is updated to remain in sync with the currently
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovefocused descendant.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute can be set two different ways: via markup or via
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovescript. To set the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute via markup, simply set the <code>tabIndex</code>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveattribute to 0 for the element that should be considered the active descendant.
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveIf the <code>tabIndex</code> attribute isn't set on any of the descendants
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovethe active descendant will be set to 0, or the index of the first
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveenabled descendant. The following example shows how to make the second button
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovein the toolbar the active descendant.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<div id="toolbar-1">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-add" value="Add">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" tabindex="0" name="btn-edit" value="Edit">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-print" value="Print">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-delete" value="Delete">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-open" value="Open">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove <input type="button" name="btn-save" value="Save">
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute can also be set via the object literal of configuration
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveattributes passed to the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/Node.html#method_plug"><code>plug</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" },
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Make the second button in the toolbar the active descendant
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove activeDescendant: 1
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute can also be set at runtime via the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/Attribute.html#method_set"><code>set</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" }
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Make the second button in the toolbar the active descendant
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovetoolbar.focusManager.set("activeDescendant", 1);
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<h3 id="styling-focus">Styling Focus</h3>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveOne of the challenges to styling the focus state of HTML elements is that
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovesupport for the CSS
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="http://www.w3.org/TR/CSS21/selector.html#x38"><code>:focus</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovepseudo class is limited to the <code>a</code> element in Internet Explorer.
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveTo fix this problem, the Focus Manager Node Plugin provides a
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute that makes it easy to style focus across <em>all</em>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveelements in <em>all</em> browsers</a>.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute can be used one of two ways. The first way is to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovesimply pass a string representing the class name to be applied to the currently
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovefocused descendant Node instance. For example, to apply a class of "focus" to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveeach button in the toolbar, set the the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute to a value of "focus":
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" },
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove focusClass: "focus"
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveOften styling focusable elements such as <code><input></code>s
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groverequires wrapping them in decorator elements, since <code><input></code>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveelements cannot have children. In such cases, it is likely the class name used
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveto style focus would be applied to the element decorating the focused
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovedescendant, rather than the descendant itself. For this reason, it is also
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovepossible to pass an object literal as the value of the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute that defines not only the class name to be used to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveindicate focus, but a function used to retrieve the Node instance to which
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovethe class name should be applied. For example, if each button in the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovewhere decorated by a <code><span></code>, the "focus" class could be
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveapplied to the parent <code><span></code> of the focused
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code><input></code> using the following code:
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" },
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove focusClass: {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove className: "focus", // The class name to use
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove fn: function (node) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // The Node instance to which the class should be applied
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove return node.get("parentNode");
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveAs demonstrated in the example, the function passed as the value of the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code>fn</code> property is passed a reference to the currently focused
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovedescendant. That Node reference is then used to return the Node to which the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveclass name is to be applied.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<h3 id="managing-focus">Managing Focus</h3>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveThe Focus Manager Node Plugin manages focus among its defined descendants as an
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveatomic operation: the Focus Manager's
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_focused"><code>focused</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute is set to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code>true</code> the first time any descendant is focused, and is set to
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<code>false</code> the first time no descendant is focused. The
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#config_focused"><code>focused</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveconfiguration attribute is read only, and is set either via user interaction
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove(the user focuses one of the defined descendant elements using either the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovekeyboard or the mouse), or programmatically via the
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#method_focus"><code>focus</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="{{apiDocs}}/classes/plugin.NodeFocusManager.html#method_blur"><code>blur</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovemethods, as illustrated in the following example:
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveYUI().use("node-focusmanager", function(Y) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Retrieve the Node instance representing the toolbar
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (<div id="toolbar">) and call the "plug" method
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// passing in a reference to the Focus Manager Node Plugin.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovevar toolbar = Y.one("#toolbar-1");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // CSS Selector indicating the descendant Nodes whose focus to manage
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove descendants: "input",
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // Move focus the buttons in the toolbar by pressing the left and
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove // right arrow keys
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove keys: { next: "down:39", previous: "down:37" }
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Listen for when the "focused" attribute changes
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovetoolbar.focusManager.after("focusedChange", function (event) {
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove Y.log("The toolbar has focus");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove Y.log("The toolbar has lost focus");
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Focus the current active descendant, setting the "focused" attribute to true
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Focus the second descendant in the toolbar, making it the active descendant
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// (this won't change the "focused" attribute, meaning the "focusedChange"
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// event handler won't be called.)
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// Blur the current active descendant, setting the "focused" attribute to false
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove// and causing the "focusedChange" event handler to be called.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<h3 id="best-practices">Best Practices</h3>
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveWhile it is possible to use the Focus Manager Node Plugin to manage focus
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveamong descendants of any type, it is recommended to use it with elements that
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveare natively in the the browser's default tab flow. Doing so provides two primary
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovebenefits: The first is that your code will work in all popular browsers, since some browsers don't support
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex" title="Forms in HTML documents"><code>tabIndex</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveattribute on all elements. Sticking with the elements that natively support <a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex" title="Forms in HTML documents"><code>tabIndex</code></a>
4e95ab13203fb7559acec02713acf9e41e1444faRyan Groveas defined in the HTML 4.01 specification will ensure better cross-browser
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovekeyboard support.
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grove<p>The second benefit is that by using the set of natively
4e95ab13203fb7559acec02713acf9e41e1444faRyan Grovefocusable HTML elements, users of screen readers will still perceive the
4e95ab13203fb7559acec02713acf9e41e1444faRyan GroveFocus Manager's defined descendants as actionable/clickable elements.</p>