Cross Reference: /yui3/src/node-focusmanager/docs/partials/node-focusmanager-3-source.mustache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright<link rel="stylesheet" href="{{componentAssets}}/menubutton.css">
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove<div class="yui3-menubutton-loading">
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove <a id="button-1" href="#menu-1"><span><span>Move To</span></span></a>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove <div id="menu-1">
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove <ul>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove <li><input type="button" name="button-1" value="Inbox"></li>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove <li><input type="button" name="button-2" value="Archive"></li>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove <li><input type="button" name="button-3" value="Trash"></li>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove </ul>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove </div>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove</div>
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove<script>
64e210505dea375c7663112bb34ae4f378a27e29Derek GathrightYUI().use("node-focusmanager", "node-event-simulate", "overlay", function(Y){
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var menuButton = Y.one("#button-1"),
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu;
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var initMenu = function () {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu = new Y.Overlay({
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright contentBox: "#menu-1",
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright visible: false,
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright tabIndex: null
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.render();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright Y.one("#menu-1").setStyle("display", "");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var boundingBox = menu.get("boundingBox"),
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright contentBox = menu.get("contentBox");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.addClass("yui3-buttonmenu");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright contentBox.addClass("yui3-buttonmenu-content");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Append a decorator element to the bounding box to render the shadow.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.append('<div class="yui3-menu-shadow"></div>');
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Apply the ARIA roles, states and properties to the menu.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.setAttrs({
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright role: "menu",
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright "aria-labelledby": menuLabelID
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.all("input").set("role", "menuitem");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // For NVDA: Add the role of "presentation" to each LI
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // element to prevent NVDA from announcing the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // "listitem" role.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.all("div,ul,li").set("role", "presentation");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Use the FocusManager Node Plugin to manage the focusability
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // of each menuitem in the menu.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright contentBox.plug(Y.Plugin.NodeFocusManager, {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright descendants: "input",
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright keys: { next: "down:40", // Down arrow
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright previous: "down:38" }, // Up arrow
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright focusClass: {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright className: "yui3-menuitem-active",
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright fn: function (node) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright return node.get("parentNode");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright },
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright circular: true
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Subscribe to the change event for the "focused" attribute
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // to listen for when the menu initially gains focus, and
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // when the menu has lost focus completely.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright contentBox.focusManager.after("focusedChange", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (!event.newVal) { // The menu has lost focus
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Set the "activeDescendant" attribute to 0 when the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // menu is hidden so that the user can tab from the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // button to the first item in the menu the next time
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // the menu is made visible.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright this.set("activeDescendant", 0);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Hide the button's menu if the user presses the escape key
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // while focused either on the button or its menu.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright Y.on("key", function () {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.hide();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.focus();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }, [menuButton, boundingBox] ,"down:27");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (Y.UA.ie === 6) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Set the width and height of the menu's bounding box -
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // this is necessary for IE 6 so that the CSS for the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // shadow element can simply set the shadow's width and
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // height to 100% to ensure that dimensions of the shadow
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // are always sync'd to the that of its parent menu.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.on("visibleChange", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (event.newVal) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.setStyles({ height: "", width: "" });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.setStyles({
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright height: (boundingBox.get("offsetHeight") + "px"),
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright width: (boundingBox.get("offsetWidth") + "px") });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.after("visibleChange", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var bVisible = event.newVal;
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Focus the first item when the menu is made visible
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // to allow users to navigate the menu via the keyboard
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (bVisible) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Need to set focus via a timer for Webkit and Opera
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright Y.Lang.later(0, contentBox.focusManager, contentBox.focusManager.focus);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.set("aria-hidden", (!bVisible));
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Hide the menu when one of menu items is clicked.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.delegate("click", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright alert("You clicked " + this.one("input").get("value"));
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright contentBox.focusManager.blur();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.hide();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }, "li");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Focus each menuitem as the user moves the mouse over
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // the menu.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.delegate("mouseenter", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var focusManager = contentBox.focusManager;
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (focusManager.get("focused")) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright focusManager.focus(this.one("input"));
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }, "li");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Hide the menu if the user clicks outside of it or if the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // user doesn't click on the button
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright boundingBox.get("ownerDocument").on("mousedown", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var oTarget = event.target;
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (!oTarget.compareTo(menuButton) &&
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright !menuButton.contains(oTarget) &&
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright !oTarget.compareTo(boundingBox) &&
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright !boundingBox.contains(oTarget)) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.hide();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright };
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.addClass("yui3-menubutton");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Hide the list until it is transformed into a menu
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright Y.one("#menu-1").setStyle("display", "none");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Remove the "yui3-menubutton-loading" class from the parent container
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // now that the necessary YUI dependencies are loaded and the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // menu button has been skinned.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.ancestor(".yui3-menubutton-loading").removeClass("yui3-menubutton-loading");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Apply the ARIA roles, states and properties to the anchor.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.setAttrs({
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright role: "button",
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright "aria-haspopup": true
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Remove the "href" attribute from the anchor element to
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // prevent JAWS and NVDA from reading the value of the "href"
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // attribute when the anchor is focused.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if ((Y.UA.gecko || Y.UA.ie) && navigator.userAgent.indexOf("Windows") > -1) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.removeAttribute("href");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Since the anchor's "href" attribute has been removed, the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // element will not fire the click event in Firefox when the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // user presses the enter key. To fix this, dispatch the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // "click" event to the anchor when the user presses the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // enter key.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright Y.on("key", function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.simulate("click");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }, menuButton, "down:13");
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Set the "tabIndex" attribute of the anchor element to 0 to
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // place it in the browser's default tab flow. This is
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // necessary since 1) anchor elements are not in the default
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // tab flow in Opera and 2) removing the "href" attribute
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // prevents the anchor from firing its "click" event
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // in Firefox.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.set("tabIndex", 0);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Since there is some intermediary markup (<span>s) between the anchor element with the role
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // of "button" applied and the text label for the anchor - we need to use the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // "aria-labelledby" attribute to ensure that screen readers announce the text label for the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // button.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var menuLabel = menuButton.one("span span"),
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuLabelID = Y.stamp(menuLabel);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuLabel.set("id", menuLabelID);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.set("aria-labelledby", menuLabelID);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright var showMenu = function (event) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // For performance: Defer the creation of the menu until
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // the first time the button is clicked.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (!menu) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright initMenu();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright if (!menu.get("visible")) {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.set("align", {
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright node: menuButton,
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright points: [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright });
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menu.show();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright }
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Prevent the anchor element from being focused
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // when the users mouses down on it.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright event.preventDefault();
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright };
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // Bind both a "mousedown" and "click" event listener to
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // ensure the button's menu can be invoked using both the
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright // mouse and the keyboard.
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright menuButton.on(["mousedown", "click"], showMenu);
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright
64e210505dea375c7663112bb34ae4f378a27e29Derek Gathright});
5f9cae5c825d76bdc95b78301e460a46ec5fbdf4Ryan Grove</script>