define([ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/_base/kernel", // kernel.deprecated "dojo/keys", // keys.END keys.HOME "dojo/_base/lang", // lang.hitch "./registry", "./_Container", "./_FocusMixin", "./_KeyNavMixin" ], function(array, declare, domAttr, kernel, keys, lang, registry, _Container, _FocusMixin, _KeyNavMixin){ // module: // dijit/_KeyNavContainer return declare("dijit._KeyNavContainer", [_FocusMixin, _KeyNavMixin, _Container], { // summary: // A _Container with keyboard navigation of its children. // description: // Provides normalized keyboard and focusing code for Container widgets. // To use this mixin, call connectKeyNavHandlers() in postCreate(). // Also, child widgets must implement a focus() method. connectKeyNavHandlers: function(/*keys[]*/ prevKeyCodes, /*keys[]*/ nextKeyCodes){ // summary: // Deprecated. You can call this in postCreate() to attach the keyboard handlers to the container, // but the preferred method is to override _onLeftArrow() and _onRightArrow(), or // _onUpArrow() and _onDownArrow(), to call focusPrev() and focusNext(). // prevKeyCodes: keys[] // Key codes for navigating to the previous child. // nextKeyCodes: keys[] // Key codes for navigating to the next child. // tags: // protected // TODO: remove for 2.0, and make subclasses override _onLeftArrow, _onRightArrow etc. instead. var keyCodes = (this._keyNavCodes = {}); var prev = lang.hitch(this, "focusPrev"); var next = lang.hitch(this, "focusNext"); array.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; }); array.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; }); keyCodes[keys.HOME] = lang.hitch(this, "focusFirstChild"); keyCodes[keys.END] = lang.hitch(this, "focusLastChild"); }, startupKeyNavChildren: function(){ kernel.deprecated("startupKeyNavChildren() call no longer needed", "", "2.0"); }, startup: function(){ this.inherited(arguments); array.forEach(this.getChildren(), lang.hitch(this, "_startupChild")); }, addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){ this.inherited(arguments); this._startupChild(widget); }, _startupChild: function(/*dijit/_WidgetBase*/ widget){ // summary: // Setup for each child widget. // description: // Sets tabIndex=-1 on each child, so that the tab key will // leave the container rather than visiting each child. // // Note: if you add children by a different method than addChild(), then need to call this manually // or at least make sure the child's tabIndex is -1. // // Note: see also _LayoutWidget.setupChild(), which is also called for each child widget. // tags: // private widget.set("tabIndex", "-1"); }, _getFirst: function(){ // summary: // Returns the first child. // tags: // abstract extension var children = this.getChildren(); return children.length ? children[0] : null; }, _getLast: function(){ // summary: // Returns the last descendant. // tags: // abstract extension var children = this.getChildren(); return children.length ? children[children.length - 1] : null; }, focusNext: function(){ // summary: // Focus the next widget // tags: // protected this.focusChild(this._getNextFocusableChild(this.focusedChild, 1)); }, focusPrev: function(){ // summary: // Focus the last focusable node in the previous widget // (ex: go to the ComboButton icon section rather than button section) // tags: // protected this.focusChild(this._getNextFocusableChild(this.focusedChild, -1), true); }, childSelector: function(/*DOMNode*/ node){ // Implement _KeyNavMixin.childSelector, to identify focusable child nodes. // If we allowed a dojo/query dependency from this module this could more simply be a string "> *" // instead of this function. var node = registry.byNode(node); return node && node.getParent() == this; } }); });