1 | define([ |
---|
2 | "dojo/_base/array", // array.forEach |
---|
3 | "dojo/_base/declare", // declare |
---|
4 | "dojo/dom-attr", // domAttr.set |
---|
5 | "dojo/_base/kernel", // kernel.deprecated |
---|
6 | "dojo/keys", // keys.END keys.HOME |
---|
7 | "dojo/_base/lang", // lang.hitch |
---|
8 | "./registry", |
---|
9 | "./_Container", |
---|
10 | "./_FocusMixin", |
---|
11 | "./_KeyNavMixin" |
---|
12 | ], function(array, declare, domAttr, kernel, keys, lang, registry, _Container, _FocusMixin, _KeyNavMixin){ |
---|
13 | |
---|
14 | |
---|
15 | // module: |
---|
16 | // dijit/_KeyNavContainer |
---|
17 | |
---|
18 | return declare("dijit._KeyNavContainer", [_FocusMixin, _KeyNavMixin, _Container], { |
---|
19 | // summary: |
---|
20 | // A _Container with keyboard navigation of its children. |
---|
21 | // description: |
---|
22 | // Provides normalized keyboard and focusing code for Container widgets. |
---|
23 | // To use this mixin, call connectKeyNavHandlers() in postCreate(). |
---|
24 | // Also, child widgets must implement a focus() method. |
---|
25 | |
---|
26 | connectKeyNavHandlers: function(/*keys[]*/ prevKeyCodes, /*keys[]*/ nextKeyCodes){ |
---|
27 | // summary: |
---|
28 | // Deprecated. You can call this in postCreate() to attach the keyboard handlers to the container, |
---|
29 | // but the preferred method is to override _onLeftArrow() and _onRightArrow(), or |
---|
30 | // _onUpArrow() and _onDownArrow(), to call focusPrev() and focusNext(). |
---|
31 | // prevKeyCodes: keys[] |
---|
32 | // Key codes for navigating to the previous child. |
---|
33 | // nextKeyCodes: keys[] |
---|
34 | // Key codes for navigating to the next child. |
---|
35 | // tags: |
---|
36 | // protected |
---|
37 | |
---|
38 | // TODO: remove for 2.0, and make subclasses override _onLeftArrow, _onRightArrow etc. instead. |
---|
39 | |
---|
40 | var keyCodes = (this._keyNavCodes = {}); |
---|
41 | var prev = lang.hitch(this, "focusPrev"); |
---|
42 | var next = lang.hitch(this, "focusNext"); |
---|
43 | array.forEach(prevKeyCodes, function(code){ |
---|
44 | keyCodes[code] = prev; |
---|
45 | }); |
---|
46 | array.forEach(nextKeyCodes, function(code){ |
---|
47 | keyCodes[code] = next; |
---|
48 | }); |
---|
49 | keyCodes[keys.HOME] = lang.hitch(this, "focusFirstChild"); |
---|
50 | keyCodes[keys.END] = lang.hitch(this, "focusLastChild"); |
---|
51 | }, |
---|
52 | |
---|
53 | startupKeyNavChildren: function(){ |
---|
54 | kernel.deprecated("startupKeyNavChildren() call no longer needed", "", "2.0"); |
---|
55 | }, |
---|
56 | |
---|
57 | startup: function(){ |
---|
58 | this.inherited(arguments); |
---|
59 | array.forEach(this.getChildren(), lang.hitch(this, "_startupChild")); |
---|
60 | }, |
---|
61 | |
---|
62 | addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){ |
---|
63 | this.inherited(arguments); |
---|
64 | this._startupChild(widget); |
---|
65 | }, |
---|
66 | |
---|
67 | _startupChild: function(/*dijit/_WidgetBase*/ widget){ |
---|
68 | // summary: |
---|
69 | // Setup for each child widget. |
---|
70 | // description: |
---|
71 | // Sets tabIndex=-1 on each child, so that the tab key will |
---|
72 | // leave the container rather than visiting each child. |
---|
73 | // |
---|
74 | // Note: if you add children by a different method than addChild(), then need to call this manually |
---|
75 | // or at least make sure the child's tabIndex is -1. |
---|
76 | // |
---|
77 | // Note: see also _LayoutWidget.setupChild(), which is also called for each child widget. |
---|
78 | // tags: |
---|
79 | // private |
---|
80 | |
---|
81 | widget.set("tabIndex", "-1"); |
---|
82 | }, |
---|
83 | |
---|
84 | _getFirst: function(){ |
---|
85 | // summary: |
---|
86 | // Returns the first child. |
---|
87 | // tags: |
---|
88 | // abstract extension |
---|
89 | var children = this.getChildren(); |
---|
90 | return children.length ? children[0] : null; |
---|
91 | }, |
---|
92 | |
---|
93 | _getLast: function(){ |
---|
94 | // summary: |
---|
95 | // Returns the last descendant. |
---|
96 | // tags: |
---|
97 | // abstract extension |
---|
98 | var children = this.getChildren(); |
---|
99 | return children.length ? children[children.length - 1] : null; |
---|
100 | }, |
---|
101 | |
---|
102 | focusNext: function(){ |
---|
103 | // summary: |
---|
104 | // Focus the next widget |
---|
105 | // tags: |
---|
106 | // protected |
---|
107 | this.focusChild(this._getNextFocusableChild(this.focusedChild, 1)); |
---|
108 | }, |
---|
109 | |
---|
110 | focusPrev: function(){ |
---|
111 | // summary: |
---|
112 | // Focus the last focusable node in the previous widget |
---|
113 | // (ex: go to the ComboButton icon section rather than button section) |
---|
114 | // tags: |
---|
115 | // protected |
---|
116 | this.focusChild(this._getNextFocusableChild(this.focusedChild, -1), true); |
---|
117 | }, |
---|
118 | |
---|
119 | childSelector: function(/*DOMNode*/ node){ |
---|
120 | // Implement _KeyNavMixin.childSelector, to identify focusable child nodes. |
---|
121 | // If we allowed a dojo/query dependency from this module this could more simply be a string "> *" |
---|
122 | // instead of this function. |
---|
123 | |
---|
124 | var node = registry.byNode(node); |
---|
125 | return node && node.getParent() == this; |
---|
126 | } |
---|
127 | }); |
---|
128 | }); |
---|