|
1 <?xml version="1.0"?> |
|
2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?> |
|
3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" |
|
4 type="text/css"?> |
|
5 <!-- |
|
6 This test checks focus in various ways |
|
7 --> |
|
8 <window id="outer-document" title="Focus Test" width="600" height="550" |
|
9 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|
10 <script type="application/javascript" |
|
11 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> |
|
12 <script type="application/javascript" |
|
13 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> |
|
14 |
|
15 <body xmlns="http://www.w3.org/1999/xhtml"/> |
|
16 |
|
17 <script type="application/javascript"><![CDATA[ |
|
18 |
|
19 var fm = Components.classes["@mozilla.org/focus-manager;1"]. |
|
20 getService(Components.interfaces.nsIFocusManager); |
|
21 |
|
22 const kChildDocumentRootIndex = 13; |
|
23 const kBeforeTabboxIndex = 34; |
|
24 const kTabbableSteps = 38; |
|
25 const kFocusSteps = 26; |
|
26 const kNoFocusSteps = 7; |
|
27 const kOverflowElementIndex = 27; |
|
28 |
|
29 var gTestStarted = false; |
|
30 var gPartialTabbing = false; |
|
31 var gMoveToFocusFrame = false; |
|
32 var gLastFocus = null; |
|
33 var gLastFocusWindow = window; |
|
34 var gLastFocusMethod = -1; |
|
35 var gEvents = ""; |
|
36 var gExpectedEvents = ""; |
|
37 var gEventMatched = true; |
|
38 var gShowOutput = false; |
|
39 var gChildWindow = null; |
|
40 |
|
41 var gOldExpectedWindow = null; |
|
42 var gNewExpectedWindow = null; |
|
43 |
|
44 function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); } |
|
45 function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); } |
|
46 |
|
47 function initEvents(target) |
|
48 { |
|
49 target.addEventListener("focus", eventOccured, true); |
|
50 target.addEventListener("blur", eventOccured, true); |
|
51 getTopWindow(target).addEventListener("activate", eventOccured, true); |
|
52 getTopWindow(target).addEventListener("deactivate", eventOccured, true); |
|
53 } |
|
54 |
|
55 function eventOccured(event) |
|
56 { |
|
57 // iframes should never receive focus or blur events directly |
|
58 if (event.target instanceof Element && event.target.localName == "iframe") |
|
59 ok(false, "iframe " + event.type + "occured"); |
|
60 |
|
61 var id; |
|
62 if (gOldExpectedWindow && event.type == "blur") { |
|
63 if (event.target instanceof Window) |
|
64 id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-window"; |
|
65 else if (event.target instanceof Document) |
|
66 id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-document"; |
|
67 else |
|
68 id = event.originalTarget.id; |
|
69 } |
|
70 else if (gNewExpectedWindow && event.type == "focus") { |
|
71 if (event.target instanceof Window) |
|
72 id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-window"; |
|
73 else if (event.target instanceof Document) |
|
74 id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-document"; |
|
75 else |
|
76 id = event.originalTarget.id; |
|
77 } |
|
78 else if (event.type == "activate" || event.type == "deactivate") |
|
79 id = event.target.document.documentElement.id + "-window"; |
|
80 else if (event.target instanceof Window) |
|
81 id = (event.target == window) ? "outer-window" : "child-window"; |
|
82 else if (event.target instanceof Document) |
|
83 id = (event.target == document) ? "outer-document" : "child-document"; |
|
84 else |
|
85 id = event.originalTarget.id; |
|
86 |
|
87 if (gEvents) |
|
88 gEvents += " "; |
|
89 gEvents += event.type + ": " + id; |
|
90 } |
|
91 |
|
92 function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid) |
|
93 { |
|
94 if (expectedWindow == null) |
|
95 expectedWindow = expectedElement ? |
|
96 expectedElement.ownerDocument.defaultView : |
|
97 gLastFocusWindow; |
|
98 |
|
99 var expectedEvents = ""; |
|
100 if (focusChanged) { |
|
101 var id; |
|
102 if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) { |
|
103 id = getTopWindow(gLastFocusWindow).document.documentElement.id; |
|
104 expectedEvents += "deactivate: " + id + "-window"; |
|
105 } |
|
106 |
|
107 if (gLastFocus && gLastFocus.id != "t" + kChildDocumentRootIndex && |
|
108 (!gOldExpectedWindow || gOldExpectedWindow.document.documentElement != gLastFocus)) { |
|
109 if (expectedEvents) |
|
110 expectedEvents += " "; |
|
111 if (!gOldExpectedWindow) |
|
112 expectedEvents += "commandupdate: cu "; |
|
113 expectedEvents += "blur: " + gLastFocus.id; |
|
114 } |
|
115 |
|
116 if (gLastFocusWindow && gLastFocusWindow != expectedWindow) { |
|
117 if (!gMoveToFocusFrame) { |
|
118 if (gOldExpectedWindow) |
|
119 id = "frame-" + gOldExpectedWindow.document.documentElement.id; |
|
120 else |
|
121 id = (gLastFocusWindow == window) ? "outer" : "child"; |
|
122 if (expectedEvents) |
|
123 expectedEvents += " "; |
|
124 expectedEvents += "blur: " + id + "-document " + |
|
125 "blur: " + id + "-window"; |
|
126 } |
|
127 } |
|
128 |
|
129 if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) { |
|
130 id = getTopWindow(expectedWindow).document.documentElement.id; |
|
131 if (expectedEvents) |
|
132 expectedEvents += " "; |
|
133 expectedEvents += "activate: " + id + "-window"; |
|
134 } |
|
135 |
|
136 if (expectedWindow && gLastFocusWindow != expectedWindow) { |
|
137 if (gNewExpectedWindow) |
|
138 id = "frame-" + gNewExpectedWindow.document.documentElement.id; |
|
139 else |
|
140 id = (expectedWindow == window) ? "outer" : "child"; |
|
141 if (expectedEvents) |
|
142 expectedEvents += " "; |
|
143 expectedEvents += "focus: " + id + "-document " + |
|
144 "focus: " + id + "-window"; |
|
145 } |
|
146 |
|
147 // for this test which fires a mouse event on a label, the document will |
|
148 // be focused first and then the label code will focus the related |
|
149 // control. This doesn't result in different focus events, but a command |
|
150 // update will occur for the document and then a secon command update will |
|
151 // occur when the control is focused. |
|
152 if (testid == "mouse on html label with content inside") |
|
153 expectedEvents += " commandupdate: cu"; |
|
154 |
|
155 if (expectedElement && |
|
156 (!gNewExpectedWindow || gNewExpectedWindow.document.documentElement != expectedElement)) { |
|
157 if (!gNewExpectedWindow) { |
|
158 if (expectedEvents) |
|
159 expectedEvents += " "; |
|
160 expectedEvents += "commandupdate: cu"; |
|
161 } |
|
162 if (expectedElement.id != "t" + kChildDocumentRootIndex) { |
|
163 if (expectedEvents) |
|
164 expectedEvents += " "; |
|
165 expectedEvents += "focus: " + expectedElement.id; |
|
166 } |
|
167 } |
|
168 else if (expectedWindow && gLastFocusWindow != expectedWindow && |
|
169 !expectedElement) { |
|
170 if (expectedEvents) |
|
171 expectedEvents += " "; |
|
172 expectedEvents += "commandupdate: cu"; |
|
173 } |
|
174 } |
|
175 |
|
176 gLastFocus = expectedElement; |
|
177 gLastFocusWindow = expectedWindow; |
|
178 |
|
179 callback(); |
|
180 |
|
181 compareEvents(expectedEvents, expectedWindow, expectedElement, testid); |
|
182 } |
|
183 |
|
184 function compareEvents(expectedEvents, expectedWindow, expectedElement, testid) |
|
185 { |
|
186 if (!gShowOutput) { |
|
187 gEvents = ""; |
|
188 return; |
|
189 } |
|
190 |
|
191 is(gEvents, expectedEvents, testid + " events"); |
|
192 gEvents = ""; |
|
193 |
|
194 var doc; |
|
195 if (expectedWindow == window) |
|
196 doc = "outer-document"; |
|
197 else if (expectedWindow == gChildWindow) |
|
198 doc = "inner-document"; |
|
199 else if (gNewExpectedWindow) |
|
200 doc = gNewExpectedWindow.document.body ? gNewExpectedWindow.document.body.id : |
|
201 gNewExpectedWindow.document.documentElement.id; |
|
202 else |
|
203 doc = "other-document"; |
|
204 |
|
205 var focusedElement = fm.focusedElement; |
|
206 is(focusedElement ? focusedElement.id : "none", |
|
207 expectedElement ? expectedElement.id : "none", testid + " focusedElement"); |
|
208 is(fm.focusedWindow, expectedWindow, testid + " focusedWindow"); |
|
209 var focusedWindow = {}; |
|
210 is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow), |
|
211 expectedElement, testid + " getFocusedElementForWindow"); |
|
212 is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame"); |
|
213 is(expectedWindow.document.hasFocus(), true, testid + " hasFocus"); |
|
214 is(expectedWindow.document.activeElement ? expectedWindow.document.activeElement.id : "none", |
|
215 expectedElement ? expectedElement.id : doc, testid + " activeElement"); |
|
216 var cdwindow = getTopWindow(expectedWindow); |
|
217 if (cdwindow.document.commandDispatcher) { |
|
218 is(cdwindow.document.commandDispatcher.focusedWindow, expectedWindow, testid + " commandDispatcher focusedWindow"); |
|
219 is(cdwindow.document.commandDispatcher.focusedElement, focusedElement, testid + " commandDispatcher focusedElement"); |
|
220 } |
|
221 |
|
222 if (gLastFocusMethod != -1) { |
|
223 is(fm.getLastFocusMethod(null), gLastFocusMethod, testid + " lastFocusMethod null"); |
|
224 is(fm.getLastFocusMethod(expectedWindow), gLastFocusMethod, testid + " lastFocusMethod window"); |
|
225 } |
|
226 |
|
227 // the parent should have the iframe focused |
|
228 if (doc == "inner-document") { |
|
229 is(document.hasFocus(), true, testid + " hasFocus"); |
|
230 is(fm.getFocusedElementForWindow(window, false, focusedWindow), |
|
231 $("childframe"), testid + " getFocusedElementForWindow for parent"); |
|
232 is(focusedWindow.value, window, testid + " getFocusedElementForWindow for parent frame"); |
|
233 is(fm.getFocusedElementForWindow(window, true, focusedWindow), |
|
234 expectedElement, testid + " getFocusedElementForWindow deep for parent"); |
|
235 is(focusedWindow.value, gChildWindow, testid + " getFocusedElementForWindow deep for parent frame"); |
|
236 is(document.activeElement.id, "childframe", testid + " activeElement for parent"); |
|
237 } |
|
238 |
|
239 // compare the selection for the child window. Skip mouse tests as the caret |
|
240 // is adjusted by the selection code for mouse clicks, and not the focus code. |
|
241 if (expectedWindow == window) { |
|
242 var selection = window.getSelection(); |
|
243 ok(selection.focusNode == null && selection.focusOffset == 0 && |
|
244 selection.anchorNode == null && selection.anchorOffset == 0, testid + " selection"); |
|
245 } |
|
246 else if ((expectedWindow == gChildWindow) && !testid.indexOf("mouse") == -1) { |
|
247 checkSelection(expectedElement, testid); |
|
248 } |
|
249 } |
|
250 |
|
251 function checkSelection(node, testid) |
|
252 { |
|
253 var selection = gChildWindow.getSelection(); |
|
254 |
|
255 var range = gChildWindow.document.createRange(); |
|
256 range.selectNodeContents(node); |
|
257 if (!node.firstChild || node.localName == "input" || |
|
258 node.localName == "select" || node.localName == "button") { |
|
259 range.setStartBefore(node); |
|
260 range.setEndBefore(node); |
|
261 } |
|
262 |
|
263 if (node.firstChild) |
|
264 range.setEnd(range.startContainer, range.startOffset); |
|
265 |
|
266 is(selection.focusNode, range.startContainer, testid + " selection focusNode"); |
|
267 is(selection.focusOffset, range.startOffset, testid + " selection focusOffset"); |
|
268 is(selection.anchorNode, range.endContainer, testid + " selection anchorNode"); |
|
269 is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset"); |
|
270 } |
|
271 |
|
272 function getTopWindow(win) |
|
273 { |
|
274 return win.QueryInterface(Components.interfaces.nsIInterfaceRequestor). |
|
275 getInterface(Components.interfaces.nsIWebNavigation). |
|
276 QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem. |
|
277 QueryInterface(Components.interfaces.nsIInterfaceRequestor). |
|
278 getInterface(Components.interfaces.nsIDOMWindow); |
|
279 } |
|
280 |
|
281 function mouseOnElement(element, expectedElement, focusChanged, testid) |
|
282 { |
|
283 var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window; |
|
284 // on Mac, form elements are not focused when clicking, except for lists and textboxes. |
|
285 var noFocusOnMouse = (navigator.platform.indexOf("Mac") == 0); |
|
286 if (noFocusOnMouse) { |
|
287 if (element.namespaceURI == "http://www.w3.org/1999/xhtml") { |
|
288 // links are special. They can be focused but show no focus ring |
|
289 if (element.localName == "a" || element.localName == "div" || |
|
290 element.localName == "select" || |
|
291 element.localName == "input" && (element.type == "text" || |
|
292 element.type == "password")) { |
|
293 noFocusOnMouse = false; |
|
294 } |
|
295 } |
|
296 else if (element.localName == "listbox") { |
|
297 noFocusOnMouse = false; |
|
298 } |
|
299 } |
|
300 |
|
301 if (noFocusOnMouse) { |
|
302 // no focus so the last focus method will be 0 |
|
303 gLastFocusMethod = 0; |
|
304 expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView), |
|
305 expectedWindow, null, true, testid); |
|
306 gLastFocusMethod = fm.FLAG_BYMOUSE; |
|
307 } |
|
308 else { |
|
309 expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView), |
|
310 element.ownerDocument.defaultView, |
|
311 expectedElement, focusChanged, testid); |
|
312 } |
|
313 } |
|
314 |
|
315 function done() |
|
316 { |
|
317 var opener = window.opener; |
|
318 window.close(); |
|
319 opener.wrappedJSObject.SimpleTest.finish(); |
|
320 } |
|
321 |
|
322 var pressTab = function () synthesizeKey("VK_TAB", { }); |
|
323 |
|
324 function setFocusTo(id, fwindow) |
|
325 { |
|
326 gLastFocus = getById(id); |
|
327 gLastFocusWindow = fwindow; |
|
328 if (gLastFocus) |
|
329 gLastFocus.focus(); |
|
330 else |
|
331 fm.clearFocus(fwindow); |
|
332 gEvents = ""; |
|
333 } |
|
334 |
|
335 function getById(id) |
|
336 { |
|
337 if (gNewExpectedWindow) |
|
338 return gNewExpectedWindow.document.getElementById(id); |
|
339 var element = $(id); |
|
340 if (!element) |
|
341 element = $("childframe").contentDocument.getElementById(id); |
|
342 return element; |
|
343 } |
|
344 |
|
345 function startTest() |
|
346 { |
|
347 if (gTestStarted) |
|
348 return; |
|
349 gTestStarted = true; |
|
350 |
|
351 gChildWindow = $("childframe").contentWindow; |
|
352 gShowOutput = true; |
|
353 |
|
354 // synthesize a mousemove over the image to ensure that the imagemap data is |
|
355 // created. Otherwise, the special imagemap frames might not exist, and |
|
356 // won't be focusable. |
|
357 synthesizeMouse(getById("image"), 4, 4, { type: "mousemove" }, gChildWindow); |
|
358 |
|
359 initEvents(window); |
|
360 |
|
361 is(fm.activeWindow, window, "activeWindow"); |
|
362 is(gChildWindow.document.hasFocus(), false, " child document hasFocus"); |
|
363 |
|
364 // test to see if the Mac Full Keyboard Access setting is set. If t3 is |
|
365 // focused after tab is pressed, then it is set to textboxes and lists only. |
|
366 // Otherwise, all elements are in the tab order. |
|
367 pressTab(); |
|
368 |
|
369 if (fm.focusedElement.id == "t3") |
|
370 gPartialTabbing = true; |
|
371 else |
|
372 is(fm.focusedElement.id, "t1", "initial tab key"); |
|
373 |
|
374 is(fm.getLastFocusMethod(null), fm.FLAG_BYKEY, "last focus method null start"); |
|
375 is(fm.getLastFocusMethod(window), fm.FLAG_BYKEY, "last focus method window start"); |
|
376 |
|
377 fm.clearFocus(window); |
|
378 gEvents = ""; |
|
379 |
|
380 gLastFocusMethod = fm.FLAG_BYKEY; |
|
381 if (gPartialTabbing) { |
|
382 var partialTabList = ["t3", "t5", "t9", "t10", "t11", "t12", "t13", "t14", "t15", |
|
383 "t16", "t19", "t20", "t21", "t22", "t26", "t27", "t28", "t29", "t30"]; |
|
384 for (var idx = 0; idx < partialTabList.length; idx++) { |
|
385 expectFocusShift(pressTab, null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]); |
|
386 } |
|
387 setFocusTo("last", window); |
|
388 expectFocusShift(pressTab, null, getById(partialTabList[0]), true, "partial tab key wrap to start"); |
|
389 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
390 null, getById("last"), true, "partial shift tab key wrap to end"); |
|
391 for (var idx = partialTabList.length - 1; idx >= 0; idx--) { |
|
392 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
393 null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]); |
|
394 } |
|
395 } |
|
396 else { |
|
397 // TAB key |
|
398 for (var idx = 1; idx <= kTabbableSteps; idx++) { |
|
399 expectFocusShift(pressTab, null, getById("t" + idx), true, "tab key t" + idx); |
|
400 } |
|
401 |
|
402 // wrapping around at end with TAB key |
|
403 setFocusTo("last", window); |
|
404 expectFocusShift(pressTab, null, getById("t1"), true, "tab key wrap to start"); |
|
405 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
406 null, getById("last"), true, "shift tab key wrap to end"); |
|
407 |
|
408 // Shift+TAB key |
|
409 setFocusTo("o5", window); |
|
410 for (idx = kTabbableSteps; idx > 0; idx--) { |
|
411 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
412 null, getById("t" + idx), true, "shift tab key t" + idx); |
|
413 } |
|
414 } |
|
415 |
|
416 var t19 = getById("t19"); |
|
417 is(t19.selectionStart, 0, "input focused from tab key selectionStart"); |
|
418 is(t19.selectionEnd, 5, "input focused from tab key selectionEnd"); |
|
419 t19.setSelectionRange(0, 0); |
|
420 |
|
421 gLastFocusMethod = 0; |
|
422 var selectFired = false; |
|
423 function selectListener() { selectFired = true; } |
|
424 t19.addEventListener("select", selectListener, false); |
|
425 expectFocusShift(function() t19.select(), |
|
426 null, getById("t" + 19), true, "input.select()"); |
|
427 t19.removeEventListener("select", selectListener, false); |
|
428 ok(selectFired, "select event fires for input"); |
|
429 |
|
430 // mouse clicking |
|
431 gLastFocusMethod = fm.FLAG_BYMOUSE; |
|
432 for (idx = kTabbableSteps; idx >= 1; idx--) { |
|
433 // skip the document root and the overflow element |
|
434 if (idx == kChildDocumentRootIndex || idx == kOverflowElementIndex) |
|
435 continue; |
|
436 if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1)) |
|
437 continue; |
|
438 |
|
439 var element = getById("t" + idx); |
|
440 // skip area elements, as getBoundingClientRect doesn't return their actual coordinates |
|
441 if (element.localName == "area") |
|
442 continue; |
|
443 |
|
444 mouseOnElement(element, getById("t" + idx), true, "mouse on element t" + idx); |
|
445 var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window; |
|
446 if (element.localName == "listbox" && expectedWindow == window && |
|
447 navigator.platform.indexOf("Mac") == 0) { |
|
448 // after focusing a listbox on Mac, clear the focus before continuing. |
|
449 setFocusTo(null, window); |
|
450 } |
|
451 } |
|
452 |
|
453 is(t19.selectionStart, 0, "input focused from mouse selectionStart"); |
|
454 is(t19.selectionEnd, 0, "input focused from mouse selectionEnd"); |
|
455 |
|
456 // mouse clicking on elements that are not tabbable |
|
457 for (idx = 1; idx <= kFocusSteps; idx++) { |
|
458 var element = getById("o" + (idx % 2 ? idx : idx - 1)); |
|
459 |
|
460 mouseOnElement(element, element, idx % 2, |
|
461 "mouse on non-tabbable element o" + idx); |
|
462 } |
|
463 |
|
464 // mouse clicking on elements that are not tabbable and have user-focus: none |
|
465 // or are not focusable for other reasons (for instance, being disabled) |
|
466 // These elements will clear the focus when clicked. |
|
467 for (idx = 1; idx <= kNoFocusSteps; idx++) { |
|
468 var element = getById("n" + idx); |
|
469 gLastFocusMethod = idx % 2 ? 0 : fm.FLAG_BYMOUSE; |
|
470 |
|
471 mouseOnElement(element, idx % 2 ? null: element, true, "mouse on unfocusable element n" + idx); |
|
472 } |
|
473 |
|
474 if (idx == kOverflowElementIndex) { |
|
475 gLastFocusMethod = fm.FLAG_BYMOUSE; |
|
476 var element = getById("t" + idx); |
|
477 expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView), |
|
478 window, null, true, "mouse on scrollable element"); |
|
479 } |
|
480 |
|
481 // focus() method |
|
482 gLastFocusMethod = 0; |
|
483 for (idx = kTabbableSteps; idx >= 1; idx--) { |
|
484 if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1)) |
|
485 continue; |
|
486 expectFocusShift(function () getById("t" + idx).focus(), |
|
487 null, getById("t" + idx), true, "focus method on element t" + idx); |
|
488 } |
|
489 |
|
490 $("t1").focus(); |
|
491 ok(gEvents === "", "focusing element that is already focused"); |
|
492 |
|
493 $("t2").blur(); |
|
494 $("t7").blur(); |
|
495 ok(gEvents === "", "blurring element that is not focused"); |
|
496 is(document.activeElement, $("t1"), "old element still focused after blur() on another element"); |
|
497 |
|
498 // focus() method on elements that are not tabbable |
|
499 for (idx = 1; idx <= kFocusSteps; idx++) { |
|
500 var expected = getById("o" + (idx % 2 ? idx : idx - 1)); |
|
501 expectFocusShift(function () getById("o" + idx).focus(), |
|
502 expected.ownerDocument.defaultView, |
|
503 expected, idx % 2, "focus method on non-tabbable element o" + idx); |
|
504 } |
|
505 |
|
506 // focus() method on elements that are not tabbable and have user-focus: none |
|
507 // or are not focusable for other reasons (for instance, being disabled) |
|
508 for (idx = 1; idx <= kNoFocusSteps; idx++) { |
|
509 var expected = getById("o" + (idx % 2 ? idx : idx - 1)); |
|
510 expectFocusShift(function () getById("o" + idx).focus(), |
|
511 expected.ownerDocument.defaultView, |
|
512 expected, idx % 2, "focus method on unfocusable element n" + idx); |
|
513 } |
|
514 |
|
515 // the focus() method on the legend element should focus the legend if it is |
|
516 // focusable, or the first element after the legend if it is not focusable. |
|
517 if (!gPartialTabbing) { |
|
518 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; |
|
519 var legend = getById("legend"); |
|
520 expectFocusShift(function () legend.focus(), |
|
521 null, getById("t28"), true, "focus method on unfocusable legend"); |
|
522 gLastFocusMethod = 0; |
|
523 legend.tabIndex = "0"; |
|
524 expectFocusShift(function () legend.focus(), |
|
525 null, getById("legend"), true, "focus method on focusable legend"); |
|
526 legend.tabIndex = "-1"; |
|
527 } |
|
528 |
|
529 var accessKeyDetails = (navigator.platform.indexOf("Mac") >= 0) ? |
|
530 { ctrlKey : true } : { altKey : true }; |
|
531 |
|
532 // test accesskeys |
|
533 var keys = ["t26", "t19", "t22", "t29", "t15", "t17", "n6", |
|
534 "t4", "o1", "o9", "n4"]; |
|
535 for (var k = 0; k < keys.length; k++) { |
|
536 var key = String.fromCharCode(65 + k); |
|
537 |
|
538 // accesskeys D and G are for labels so get redirected |
|
539 gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY; |
|
540 |
|
541 // on Windows and Linux, the shift key must be pressed for content area access keys |
|
542 // and on Mac, the alt key must be pressed for content area access keys |
|
543 var isContent = (getById(keys[k]).ownerDocument.defaultView == gChildWindow); |
|
544 if (navigator.platform.indexOf("Mac") == -1) { |
|
545 accessKeyDetails.shiftKey = isContent; |
|
546 } else { |
|
547 accessKeyDetails.altKey = isContent; |
|
548 } |
|
549 |
|
550 expectFocusShift(function () synthesizeKey(key, accessKeyDetails), |
|
551 null, getById(keys[k]), true, "accesskey " + key); |
|
552 } |
|
553 |
|
554 // clicking on the labels |
|
555 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; |
|
556 expectFocusShift(function () synthesizeMouse(getById("ad"), 2, 2, { }, gChildWindow), |
|
557 null, getById("t29"), true, "mouse on html label with content inside"); |
|
558 expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow), |
|
559 null, getById("n6"), true, "mouse on html label with for attribute"); |
|
560 gLastFocusMethod = 0; |
|
561 expectFocusShift(function () synthesizeMouse(getById("aj"), 2, 2, { }), |
|
562 null, getById("o9"), true, "mouse on xul label with content inside"); |
|
563 expectFocusShift(function () synthesizeMouse(getById("ak"), 2, 2, { }), |
|
564 null, getById("n4"), true, "mouse on xul label with control attribute"); |
|
565 |
|
566 // test accesskeys that shouldn't work |
|
567 k = "o".charCodeAt(0); |
|
568 while (k++ < "v".charCodeAt(0)) { |
|
569 var key = String.fromCharCode(k); |
|
570 expectFocusShift(function () synthesizeKey(key, accessKeyDetails), |
|
571 window, getById("n4"), false, "non accesskey " + key); |
|
572 } |
|
573 gLastFocusMethod = -1; |
|
574 |
|
575 // should focus the for element when using the focus method on a label as well |
|
576 expectFocusShift(function () getById("ad").focus(), |
|
577 null, getById("t29"), true, "mouse on html label using focus method"); |
|
578 |
|
579 // make sure that the text is selected when clicking a label associated with an input |
|
580 getById("ag").htmlFor = "t19"; |
|
581 expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow), |
|
582 null, getById("t19"), true, "mouse on html label with for attribute changed"); |
|
583 is(t19.selectionStart, 0, "input focused from label, selectionStart"); |
|
584 is(t19.selectionEnd, 5, "input focused from label, selectionEnd"); |
|
585 |
|
586 // switch to another panel in a tabbox and ensure that tabbing moves between |
|
587 // elements on the new panel. |
|
588 $("tabbox").selectedIndex = 1; |
|
589 expectFocusShift(function () getById("t" + kBeforeTabboxIndex).focus(), |
|
590 null, getById("t" + kBeforeTabboxIndex), true, "focus method on element before tabbox"); |
|
591 |
|
592 if (!gPartialTabbing) { |
|
593 expectFocusShift(pressTab, null, getById("tab2"), true, "focus method on tab"); |
|
594 expectFocusShift(pressTab, null, getById("htab1"), true, "tab key switch tabpanel 1"); |
|
595 expectFocusShift(pressTab, null, getById("htab2"), true, "tab key switch tabpanel 2"); |
|
596 expectFocusShift(pressTab, null, getById("t" + (kBeforeTabboxIndex + 4)), true, "tab key switch tabpanel 3"); |
|
597 } |
|
598 $("tabbox").selectedIndex = 0; |
|
599 |
|
600 // ---- the following checks when the focus changes during a blur or focus event ---- |
|
601 |
|
602 var o5 = $("o5"); |
|
603 var o9 = $("o9"); |
|
604 var t3 = $("t3"); |
|
605 var t17 = getById("t17"); |
|
606 var t19 = getById("t19"); |
|
607 var shiftFocusParentDocument = function() o9.focus(); |
|
608 var shiftFocusChildDocument = function() t17.focus(); |
|
609 |
|
610 var trapBlur = function (element, eventListener, blurFunction) |
|
611 { |
|
612 element.focus(); |
|
613 gEvents = ""; |
|
614 element.addEventListener("blur", eventListener, false); |
|
615 blurFunction(); |
|
616 element.removeEventListener("blur", eventListener, false); |
|
617 } |
|
618 |
|
619 var functions = [ |
|
620 function(element) element.focus(), |
|
621 function(element) synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView) |
|
622 ]; |
|
623 |
|
624 // first, check cases where the focus is adjusted during the blur event. Iterate twice, |
|
625 // once with the focus method and then focusing by mouse clicking |
|
626 for (var l = 0; l < 2; l++) { |
|
627 var adjustFocus = functions[l]; |
|
628 var mod = (l == 1) ? " with mouse" : ""; |
|
629 |
|
630 // an attempt is made to switch the focus from one element (o5) to another |
|
631 // element (t3) within the same document, yet the focus is shifted to a |
|
632 // third element (o9) in the same document during the blur event for the |
|
633 // first element. |
|
634 trapBlur(o5, shiftFocusParentDocument, function () adjustFocus(t3)); |
|
635 compareEvents("commandupdate: cu blur: o5 commandupdate: cu focus: o9", |
|
636 window, o9, "change focus to sibling during element blur, attempted sibling" + mod); |
|
637 |
|
638 // similar, but the third element (t17) is in a child document |
|
639 trapBlur(o9, shiftFocusChildDocument, function () adjustFocus(t3)); |
|
640 compareEvents("commandupdate: cu blur: o9 blur: outer-document blur: outer-window " + |
|
641 "focus: child-document focus: child-window commandupdate: cu focus: t17", |
|
642 gChildWindow, t17, "change focus to child document during element blur, attempted sibling" + mod); |
|
643 |
|
644 // similar, but an attempt to switch focus within the same document, but the |
|
645 // third element (t17) is in a parent document |
|
646 trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t19)); |
|
647 compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " + |
|
648 "focus: outer-document focus: outer-window commandupdate: cu focus: o9", |
|
649 window, o9, "change focus to parent document during element blur, attempted sibling" + mod); |
|
650 |
|
651 // similar, but blur is called instead of switching focus |
|
652 trapBlur(t3, shiftFocusParentDocument, function () t3.blur()); |
|
653 compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9", |
|
654 window, o9, "change focus to same document during clear focus" + mod); |
|
655 |
|
656 // check when an element in the same document is focused during the |
|
657 // element's blur event, but an attempt was made to focus an element in the |
|
658 // child document. In this case, the focus in the parent document should be |
|
659 // what was set during the blur event, but the actual focus should still |
|
660 // move to the child document. |
|
661 trapBlur(t3, shiftFocusParentDocument, function () adjustFocus(t17)); |
|
662 compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9 " + |
|
663 "blur: outer-document blur: outer-window " + |
|
664 "focus: child-document focus: child-window commandupdate: cu focus: t17", |
|
665 gChildWindow, t17, "change focus to sibling during element blur, attempted child" + mod); |
|
666 is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"), |
|
667 "change focus to sibling during element blur, attempted child, focused in parent" + mod); |
|
668 |
|
669 // similar, but with a parent |
|
670 trapBlur(t19, shiftFocusChildDocument, function () adjustFocus(t3)); |
|
671 compareEvents("commandupdate: cu blur: t19 commandupdate: cu focus: t17 " + |
|
672 "blur: child-document blur: child-window " + |
|
673 "focus: outer-document focus: outer-window commandupdate: cu focus: t3", |
|
674 window, t3, "change focus to sibling during element blur, attempted parent" + mod); |
|
675 is(fm.getFocusedElementForWindow(gChildWindow, false, {}), t17, |
|
676 "change focus to sibling during element blur, attempted child, focused in child" + mod); |
|
677 |
|
678 // similar, with a child, but the blur event focuses a child element also |
|
679 trapBlur(t3, shiftFocusChildDocument, function () adjustFocus(t19)); |
|
680 compareEvents("commandupdate: cu blur: t3 blur: outer-document blur: outer-window " + |
|
681 "focus: child-document focus: child-window commandupdate: cu focus: t17", |
|
682 gChildWindow, t17, "change focus to child during element blur, attempted child" + mod); |
|
683 |
|
684 // similar, with a parent, where the blur event focuses a parent element also |
|
685 trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t3)); |
|
686 compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " + |
|
687 "focus: outer-document focus: outer-window commandupdate: cu focus: o9", |
|
688 window, o9, "change focus to parent during element blur, attempted parent" + mod); |
|
689 } |
|
690 |
|
691 var trapFocus = function (element, eventListener) |
|
692 { |
|
693 element.addEventListener("focus", eventListener, false); |
|
694 element.focus(); |
|
695 element.removeEventListener("focus", eventListener, false); |
|
696 } |
|
697 |
|
698 fm.clearFocus(window); |
|
699 gEvents = ""; |
|
700 |
|
701 // next, check cases where the focus is adjusted during the focus event |
|
702 |
|
703 // switch focus to an element in the same document |
|
704 trapFocus(o5, shiftFocusParentDocument); |
|
705 compareEvents("commandupdate: cu focus: o5 commandupdate: cu blur: o5 commandupdate: cu focus: o9", |
|
706 window, o9, "change focus to sibling during element focus"); |
|
707 |
|
708 // similar, but the new element (t17) is in a child document |
|
709 trapFocus(o5, shiftFocusChildDocument); |
|
710 compareEvents("commandupdate: cu blur: o9 " + |
|
711 "commandupdate: cu focus: o5 commandupdate: cu blur: o5 " + |
|
712 "blur: outer-document blur: outer-window " + |
|
713 "focus: child-document focus: child-window commandupdate: cu focus: t17", |
|
714 gChildWindow, t17, "change focus to child document during element focus"); |
|
715 |
|
716 // similar, but the new element (o9) is in a parent document. |
|
717 trapFocus(t19, shiftFocusParentDocument); |
|
718 compareEvents("commandupdate: cu blur: t17 " + |
|
719 "commandupdate: cu focus: t19 commandupdate: cu blur: t19 " + |
|
720 "blur: child-document blur: child-window " + |
|
721 "focus: outer-document focus: outer-window commandupdate: cu focus: o9", |
|
722 window, o9, "change focus to parent document during element focus"); |
|
723 |
|
724 // clear the focus during the focus event |
|
725 trapFocus(t3, function () fm.clearFocus(window)); |
|
726 compareEvents("commandupdate: cu blur: o9 commandupdate: cu focus: t3 commandupdate: cu blur: t3", |
|
727 window, null, "clear focus during focus event"); |
|
728 |
|
729 if (!gPartialTabbing) |
|
730 doCommandDispatcherTests(); |
|
731 |
|
732 testMoveFocus(); |
|
733 |
|
734 doRemoveTests(); |
|
735 |
|
736 // tests various focus manager apis for null checks |
|
737 var exh = false; |
|
738 try { |
|
739 fm.clearFocus(null); |
|
740 } |
|
741 catch (ex) { exh = true; } |
|
742 is(exh, true, "clearFocus with null window causes exception"); |
|
743 |
|
744 var exh = false; |
|
745 try { |
|
746 fm.getFocusedElementForWindow(null, false, focusedWindow); |
|
747 } |
|
748 catch (ex) { exh = true; } |
|
749 is(exh, true, "getFocusedElementForWindow with null window causes exception"); |
|
750 |
|
751 // just make sure that this doesn't crash |
|
752 fm.moveCaretToFocus(null); |
|
753 |
|
754 // ---- tests for the FLAG_NOSWITCHFRAME flag |
|
755 getById("o5").focus(); |
|
756 gLastFocusMethod = 0; |
|
757 gEvents = ""; |
|
758 // focus is being shifted in a child, so the focus should not change |
|
759 expectFocusShift(function () fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME), |
|
760 window, getById("o5"), false, "no switch frame focus to child"); |
|
761 setFocusTo("t20", gChildWindow); |
|
762 |
|
763 // here, however, focus is being shifted in a parent, which will have to blur |
|
764 // the child, so the focus will always change |
|
765 expectFocusShift(function () fm.setFocus(getById("o5"), fm.FLAG_NOSWITCHFRAME), |
|
766 window, getById("o5"), true, "no switch frame focus to parent"); |
|
767 |
|
768 expectFocusShift(function () fm.setFocus(getById("t1"), fm.FLAG_NOSWITCHFRAME), |
|
769 window, getById("t1"), true, "no switch frame focus to same window"); |
|
770 |
|
771 // ---- tests for focus and scrolling into view ---- |
|
772 var inscroll = getById("inscroll"); |
|
773 inscroll.tabIndex = 0; |
|
774 is(inscroll.parentNode.scrollTop, 0, "scroll position before focus"); |
|
775 inscroll.focus(); |
|
776 ok(inscroll.parentNode.scrollTop > 5, "scroll position after focus"); |
|
777 inscroll.parentNode.scrollTop = 0; |
|
778 fm.setFocus(inscroll, fm.FLAG_NOSCROLL); |
|
779 is(inscroll.parentNode.scrollTop, 0, "scroll position after noscroll focus"); |
|
780 |
|
781 getById("t9").focus(); |
|
782 getById("inpopup1").focus(); |
|
783 is(fm.focusedElement, getById("t9"), "focus in closed popup"); |
|
784 |
|
785 // ---- tests to check if tabbing out of a textbox works |
|
786 |
|
787 setFocusTo("t1", window); |
|
788 |
|
789 var textbox1 = document.createElement("textbox"); |
|
790 $("innerbox").appendChild(textbox1); |
|
791 |
|
792 var textbox2 = document.createElement("textbox"); |
|
793 $("innerbox").appendChild(textbox2); |
|
794 |
|
795 gLastFocusMethod = 0; |
|
796 expectFocusShift(function () textbox2.focus(), |
|
797 null, textbox2.inputField, true, "focus on textbox"); |
|
798 gLastFocusMethod = fm.FLAG_BYKEY; |
|
799 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
800 null, textbox1.inputField, true, "shift+tab on textbox"); |
|
801 |
|
802 textbox1.tabIndex = 2; |
|
803 textbox2.tabIndex = 2; |
|
804 gLastFocusMethod = 0; |
|
805 expectFocusShift(function () textbox2.focus(), |
|
806 null, textbox2.inputField, true, "focus on textbox with tabindex set"); |
|
807 gLastFocusMethod = fm.FLAG_BYKEY; |
|
808 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
809 null, textbox1.inputField, true, "shift+tab on textbox with tabindex set"); |
|
810 |
|
811 // ---- test for bug 618907 which ensures that canceling the mousedown event still focuses the |
|
812 // right frame |
|
813 |
|
814 var childContentFrame = document.getElementById("ifa") |
|
815 childContentFrame.style.MozUserFocus = ""; |
|
816 |
|
817 var frab = childContentFrame.contentDocument.getElementById("fra-b"); |
|
818 var mouseDownListener = function(event) event.preventDefault(); |
|
819 frab.addEventListener("mousedown", mouseDownListener, false); |
|
820 |
|
821 var childElementToFocus = childContentFrame.contentDocument.getElementById("fra"); |
|
822 gLastFocus = childElementToFocus; |
|
823 gLastFocusWindow = childContentFrame.contentWindow; |
|
824 gLastFocus.focus(); |
|
825 gEvents = ""; |
|
826 |
|
827 setFocusTo("t1", window); |
|
828 |
|
829 gLastFocusMethod = -1; |
|
830 expectFocusShift(function () synthesizeMouse(frab, 5, 5, { }, childContentFrame.contentWindow), |
|
831 null, childElementToFocus, true, |
|
832 "mousedown event canceled - chrome to content"); |
|
833 |
|
834 frab.removeEventListener("mousedown", mouseDownListener, false); |
|
835 |
|
836 var t5 = getById("t5"); |
|
837 t5.addEventListener("mousedown", mouseDownListener, false); |
|
838 synthesizeMouse(t5, 10, 10, { }) |
|
839 t5.removeEventListener("mousedown", mouseDownListener, false); |
|
840 is(fm.focusedElement, childElementToFocus, |
|
841 "mousedown event cancelled - content to chrome - element"); |
|
842 is(fm.focusedWindow, childContentFrame.contentWindow, "mousedown event cancelled - content to chrome - window"); |
|
843 |
|
844 // ---- test to check that refocusing an element during a blur event doesn't succeed |
|
845 |
|
846 var t1 = getById("t1"); |
|
847 t1.addEventListener("blur", function() t1.focus(), true); |
|
848 t1.focus(); |
|
849 var t3 = getById("t3"); |
|
850 synthesizeMouse(t3, 2, 2, { }); |
|
851 is(fm.focusedElement, t3, "focus during blur"); |
|
852 |
|
853 setFocusTo("t9", window); |
|
854 gLastFocusMethod = -1; |
|
855 window.openDialog("focus_window2.xul", "_blank", "chrome", otherWindowFocused); |
|
856 } |
|
857 |
|
858 function doCommandDispatcherTests() |
|
859 { |
|
860 var t19 = getById("t19"); |
|
861 t19.focus(); |
|
862 gLastFocusWindow = gChildWindow; |
|
863 gLastFocus = t19; |
|
864 gEvents = ""; |
|
865 |
|
866 expectFocusShift(function () document.commandDispatcher.focusedElement = getById("o9"), |
|
867 null, getById("o9"), true, "command dispatcher set focusedElement"); |
|
868 expectFocusShift(function () document.commandDispatcher.advanceFocus(), |
|
869 null, getById("o13"), true, "command dispatcher advanceFocus"); |
|
870 expectFocusShift(function () document.commandDispatcher.rewindFocus(), |
|
871 null, getById("o9"), true, "command dispatcher rewindFocus"); |
|
872 expectFocusShift(function () document.commandDispatcher.focusedElement = null, |
|
873 null, null, true, "command dispatcher set focusedElement to null"); |
|
874 expectFocusShift(function () document.commandDispatcher.focusedWindow = gChildWindow, |
|
875 null, getById("t19"), true, "command dispatcher set focusedElement to null"); |
|
876 expectFocusShift(function () document.commandDispatcher.focusedElement = null, |
|
877 gChildWindow, null, true, "command dispatcher set focusedElement to null in child"); |
|
878 expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("t19")), |
|
879 null, getById("t20"), true, "command dispatcher advanceFocusIntoSubtree child"); |
|
880 expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(null), |
|
881 null, getById("t21"), true, "command dispatcher advanceFocusIntoSubtree null child"); |
|
882 expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("o9").parentNode), |
|
883 null, getById("o9"), true, "command dispatcher advanceFocusIntoSubtree parent"); |
|
884 } |
|
885 |
|
886 function doRemoveTests() |
|
887 { |
|
888 // next, some tests which remove elements |
|
889 var t19 = getById("t19"); |
|
890 t19.focus(); |
|
891 t19.parentNode.removeChild(t19); |
|
892 |
|
893 is(fm.focusedElement, null, "removed element focusedElement"); |
|
894 is(fm.focusedWindow, gChildWindow, "removed element focusedWindow"); |
|
895 is(gChildWindow.document.hasFocus(), true, "removed element hasFocus"); |
|
896 is(gChildWindow.document.activeElement, getById("inner-document"), "removed element activeElement"); |
|
897 |
|
898 getById("t15").focus(); |
|
899 var abs = getById("abs"); |
|
900 abs.parentNode.removeChild(abs); |
|
901 |
|
902 is(fm.focusedElement, null, "removed ancestor focusedElement"); |
|
903 is(fm.focusedWindow, gChildWindow, "removed ancestor focusedWindow"); |
|
904 is(gChildWindow.document.hasFocus(), true, "removed ancestor hasFocus"); |
|
905 is(gChildWindow.document.activeElement, getById("inner-document"), "removed ancestor activeElement"); |
|
906 } |
|
907 |
|
908 // tests for the FocusManager moveFocus method |
|
909 function testMoveFocus() |
|
910 { |
|
911 setFocusTo("t6", window); |
|
912 |
|
913 // moving focus while an element is already focused |
|
914 var newFocus; |
|
915 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; |
|
916 var expectedFirst = getById(gPartialTabbing ? "t3" : "t1"); |
|
917 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0), |
|
918 window, expectedFirst, true, "moveFocus to first null window null content"); |
|
919 is(newFocus, fm.focusedElement, "moveFocus to first null window null content return value"); |
|
920 |
|
921 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0), |
|
922 window, getById("last"), true, "moveFocus to last null window null content"); |
|
923 is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value"); |
|
924 |
|
925 gLastFocusMethod = 0; |
|
926 newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0); |
|
927 is(newFocus, null, "moveFocus to root null window null content return value"); |
|
928 is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow"); |
|
929 is(fm.focusedElement, null, "moveFocus to root null window null content focusedElement"); |
|
930 |
|
931 // moving focus while no element is focused |
|
932 fm.clearFocus(window); |
|
933 gEvents = ""; |
|
934 gLastFocus = null; |
|
935 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; |
|
936 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0), |
|
937 window, expectedFirst, true, "moveFocus to first null window null content no focus"); |
|
938 is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value"); |
|
939 fm.clearFocus(window); |
|
940 gEvents = ""; |
|
941 gLastFocus = null; |
|
942 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0), |
|
943 window, getById("last"), true, "moveFocus to last null window null content no focus"); |
|
944 is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value"); |
|
945 fm.clearFocus(window); |
|
946 gEvents = ""; |
|
947 gLastFocusMethod = 0; |
|
948 newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0); |
|
949 is(newFocus, null, "moveFocus to root null window null content no focus return value"); |
|
950 is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow"); |
|
951 is(fm.focusedElement, null, "moveFocus to root null window null content no focus focusedElement"); |
|
952 |
|
953 // moving focus from a specified element |
|
954 setFocusTo("t6", window); |
|
955 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; |
|
956 expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0), |
|
957 window, getById("t3"), true, "moveFocus to first null window with content"); |
|
958 // XXXndeakin P3 this doesn't work |
|
959 // expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_LAST, 0), |
|
960 // window, getById("o3"), true, "moveFocus to last null window with content"); |
|
961 |
|
962 // move focus to first in child window |
|
963 expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_FIRST, 0), |
|
964 gChildWindow, getById("t" + (kChildDocumentRootIndex + 1)), true, |
|
965 "moveFocus to first child window null content"); |
|
966 is(newFocus, getById("t" + (kChildDocumentRootIndex + 1)), |
|
967 "moveFocus to first child window null content return value"); |
|
968 |
|
969 // move focus to last in child window |
|
970 setFocusTo("t6", window); |
|
971 var expectedLast = getById(gPartialTabbing ? "t30" : "t" + (kBeforeTabboxIndex - 1)); |
|
972 expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_LAST, 0), |
|
973 gChildWindow, expectedLast, true, |
|
974 "moveFocus to last child window null content"); |
|
975 is(newFocus, getById(expectedLast), |
|
976 "moveFocus to last child window null content return value"); |
|
977 |
|
978 // move focus to root in child window |
|
979 setFocusTo("t6", window); |
|
980 var childroot = getById("t" + kChildDocumentRootIndex); |
|
981 gLastFocusMethod = 0; |
|
982 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0), |
|
983 is(newFocus, childroot, "moveFocus to root child window null content return value"); |
|
984 is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow"); |
|
985 is(fm.focusedElement, childroot, "moveFocus to root child window null content focusedElement"); |
|
986 |
|
987 // MOVEFOCUS_CARET tests |
|
988 getById("t20").focus(); |
|
989 gEvents = ""; |
|
990 |
|
991 var selection = gChildWindow.getSelection(); |
|
992 selection.removeAllRanges(); |
|
993 |
|
994 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0); |
|
995 is(newFocus, null, "move caret when at document root"); |
|
996 is(fm.focusedElement, null, "move caret when at document root"); |
|
997 |
|
998 var node = getById("t16").firstChild; |
|
999 var range = gChildWindow.document.createRange(); |
|
1000 range.setStart(node, 3); |
|
1001 range.setEnd(node, 3); |
|
1002 selection.addRange(range); |
|
1003 |
|
1004 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0); |
|
1005 is(newFocus, null, "move caret to non-link return value"); |
|
1006 is(fm.focusedElement, null, "move caret to non-link"); |
|
1007 |
|
1008 var t25 = getById("t25"); |
|
1009 var node = t25.firstChild; |
|
1010 range.setStart(node, 1); |
|
1011 range.setEnd(node, 1); |
|
1012 newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0); |
|
1013 |
|
1014 is(newFocus, t25, "move caret to link return value"); |
|
1015 is(fm.focusedElement, t25, "move caret to link focusedElement"); |
|
1016 |
|
1017 // enable caret browsing temporarily to test caret movement |
|
1018 var prefs = Components.classes["@mozilla.org/preferences-service;1"]. |
|
1019 getService(Components.interfaces.nsIPrefBranch); |
|
1020 prefs.setBoolPref("accessibility.browsewithcaret", true); |
|
1021 |
|
1022 synthesizeKey("VK_LEFT", { }, gChildWindow); |
|
1023 synthesizeKey("VK_LEFT", { }, gChildWindow); |
|
1024 is(fm.focusedElement, null, "move caret away from link"); |
|
1025 |
|
1026 synthesizeKey("VK_LEFT", { }, gChildWindow); |
|
1027 is(fm.focusedElement, getById("t24"), "move caret away onto link"); |
|
1028 |
|
1029 prefs.setBoolPref("accessibility.browsewithcaret", false); |
|
1030 |
|
1031 // cases where focus in on a content node with no frame |
|
1032 |
|
1033 if (!gPartialTabbing) { |
|
1034 getById("t24").blur(); |
|
1035 gEvents = ""; |
|
1036 gLastFocus = null; |
|
1037 gLastFocusWindow = gChildWindow; |
|
1038 gLastFocusMethod = fm.FLAG_BYKEY; |
|
1039 |
|
1040 selection.selectAllChildren(getById("hiddenspan")); |
|
1041 expectFocusShift(function () synthesizeKey("VK_TAB", { }), |
|
1042 gChildWindow, getById("t26"), true, "tab with selection on hidden content"); |
|
1043 |
|
1044 setFocusTo($("o15"), window); |
|
1045 $("o15").hidden = true; |
|
1046 document.documentElement.getBoundingClientRect(); // flush after hiding |
|
1047 expectFocusShift(function () synthesizeKey("VK_TAB", { }), |
|
1048 window, $("o17"), true, "tab with focus on hidden content"); |
|
1049 |
|
1050 $("o17").hidden = true; |
|
1051 document.documentElement.getBoundingClientRect(); |
|
1052 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), |
|
1053 window, $("o13"), true, "shift+tab with focus on hidden content"); |
|
1054 } |
|
1055 |
|
1056 // cases with selection in an <input> |
|
1057 |
|
1058 var t19 = getById("t19"); |
|
1059 t19.setSelectionRange(0, 0); |
|
1060 setFocusTo("t18", gChildWindow); |
|
1061 |
|
1062 gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; |
|
1063 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0), |
|
1064 gChildWindow, t19, true, "moveFocus to next textbox"); |
|
1065 is(t19.selectionStart, 0, "input focused after moveFocus selectionStart"); |
|
1066 is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd"); |
|
1067 |
|
1068 t19.setSelectionRange(0, 0); |
|
1069 setFocusTo("t18", gChildWindow); |
|
1070 gLastFocusMethod = fm.FLAG_BYKEY; |
|
1071 expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY), |
|
1072 gChildWindow, t19, true, "moveFocus to next textbox by key"); |
|
1073 is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart"); |
|
1074 is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd"); |
|
1075 } |
|
1076 |
|
1077 function otherWindowFocused(otherWindow) |
|
1078 { |
|
1079 var expectedElement = getById("t9"); |
|
1080 |
|
1081 is(fm.activeWindow, otherWindow, "other activeWindow"); |
|
1082 is(fm.focusedWindow, otherWindow, "other focusedWindow"); |
|
1083 is(window.document.hasFocus(), false, "when lowered document hasFocus"); |
|
1084 var focusedWindow = {}; |
|
1085 is(fm.getFocusedElementForWindow(window, false, focusedWindow), |
|
1086 expectedElement, "when lowered getFocusedElementForWindow"); |
|
1087 is(focusedWindow.value, window, "when lowered getFocusedElementForWindow frame"); |
|
1088 is(document.activeElement.id, expectedElement.id, "when lowered activeElement"); |
|
1089 is(window.document.commandDispatcher.focusedWindow, window, " commandDispatcher in other window focusedWindow"); |
|
1090 is(window.document.commandDispatcher.focusedElement, expectedElement, " commandDispatcher in other window focusedElement"); |
|
1091 |
|
1092 compareEvents("deactivate: outer-document-window blur: t9 blur: outer-document blur: outer-window", |
|
1093 otherWindow, null, "other window opened"); |
|
1094 |
|
1095 otherWindow.document.getElementById("other").focus(); |
|
1096 |
|
1097 for (var idx = kTabbableSteps; idx >= 1; idx--) { |
|
1098 expectedElement = getById("t" + idx); |
|
1099 if (!expectedElement) // skip elements that were removed in doRemoveTests() |
|
1100 continue; |
|
1101 if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1)) |
|
1102 continue; |
|
1103 |
|
1104 expectedElement.focus(); |
|
1105 |
|
1106 is(fm.focusedElement.id, "other", "when lowered focusedElement t" + idx); |
|
1107 is(fm.focusedWindow, otherWindow, "when lowered focusedWindow t" + idx); |
|
1108 |
|
1109 var checkWindow = expectedElement.ownerDocument.defaultView; |
|
1110 is(fm.getFocusedElementForWindow(checkWindow, false, {}).id, expectedElement.id, |
|
1111 "when lowered getFocusedElementForWindow t" + idx); |
|
1112 is(checkWindow.document.activeElement.id, expectedElement.id, "when lowered activeElement t" + idx); |
|
1113 if (checkWindow != window) { |
|
1114 is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"), |
|
1115 "when lowered parent getFocusedElementForWindow t" + idx); |
|
1116 is(document.activeElement.id, "childframe", |
|
1117 "when lowered parent activeElement t" + idx); |
|
1118 } |
|
1119 } |
|
1120 |
|
1121 gEvents = gEvents.replace(/commandupdate: cu\s?/g, ""); |
|
1122 is(gEvents, "", "when lowered no events fired"); |
|
1123 |
|
1124 var other = otherWindow.document.getElementById("other"); |
|
1125 other.focus(); |
|
1126 is(fm.focusedElement, other, "focus method in second window"); |
|
1127 |
|
1128 otherWindow.close(); |
|
1129 |
|
1130 getById("n2").focus(); |
|
1131 |
|
1132 // next, check modal dialogs |
|
1133 // XXXndeakin Bug 621399 - the modal dialog test as well as later tests sometime fail |
|
1134 // on Windows 8 so just end the test here. |
|
1135 if (navigator.userAgent.indexOf("Windows NT 6.2") >= 0) { |
|
1136 done(); |
|
1137 } |
|
1138 else { |
|
1139 window.openDialog("focus_window2.xul", "_blank", "chrome,modal", modalWindowOpened); |
|
1140 } |
|
1141 } |
|
1142 |
|
1143 function modalWindowOpened(modalWindow) |
|
1144 { |
|
1145 var elem = modalWindow.document.getElementById("other"); |
|
1146 if (gPartialTabbing) |
|
1147 elem.focus(); |
|
1148 else |
|
1149 synthesizeKey("VK_TAB", { }, modalWindow); |
|
1150 is(fm.activeWindow, modalWindow, "modal activeWindow"); |
|
1151 is(fm.focusedElement, elem, "modal focusedElement"); |
|
1152 |
|
1153 modalWindow.close(); |
|
1154 SimpleTest.waitForFocus(modalWindowClosed); |
|
1155 } |
|
1156 |
|
1157 function modalWindowClosed() |
|
1158 { |
|
1159 is(fm.activeWindow, window, "modal window closed activeWindow"); |
|
1160 is(fm.focusedElement, getById("n2"), "modal window closed focusedElement"); |
|
1161 |
|
1162 window.open("focus_frameset.html", "_blank", "width=400,height=400,toolbar=no"); |
|
1163 } |
|
1164 |
|
1165 function framesetWindowLoaded(framesetWindow) |
|
1166 { |
|
1167 gLastFocus = null; |
|
1168 gLastFocusWindow = framesetWindow; |
|
1169 gEvents = ""; |
|
1170 |
|
1171 is(fm.activeWindow, getTopWindow(framesetWindow), "frameset window active"); |
|
1172 gOldExpectedWindow = getTopWindow(framesetWindow); |
|
1173 |
|
1174 gMoveToFocusFrame = true; |
|
1175 for (var idx = 1; idx <= 8; idx++) { |
|
1176 gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1]; |
|
1177 if (idx % 2) |
|
1178 initEvents(gNewExpectedWindow); |
|
1179 expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow), |
|
1180 gNewExpectedWindow, getById("f" + idx), true, "frameset tab key f" + idx); |
|
1181 gMoveToFocusFrame = false; |
|
1182 gOldExpectedWindow = gNewExpectedWindow; |
|
1183 } |
|
1184 |
|
1185 gNewExpectedWindow = framesetWindow.frames[0]; |
|
1186 expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow), |
|
1187 gNewExpectedWindow, getById("f1"), true, "frameset tab key wrap to start"); |
|
1188 gOldExpectedWindow = gNewExpectedWindow; |
|
1189 gNewExpectedWindow = framesetWindow.frames[3]; |
|
1190 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow), |
|
1191 gNewExpectedWindow, getById("f8"), true, "frameset shift tab key wrap to end"); |
|
1192 |
|
1193 for (idx = 7; idx >= 1; idx--) { |
|
1194 gOldExpectedWindow = gNewExpectedWindow; |
|
1195 gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1]; |
|
1196 expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow), |
|
1197 gNewExpectedWindow, getById("f" + idx), true, "frameset shift tab key f" + idx); |
|
1198 } |
|
1199 |
|
1200 // document shifting |
|
1201 // XXXndeakin P3 ctrl+tab doesn't seem to be testable currently for some reason |
|
1202 gNewExpectedWindow = framesetWindow.frames[1]; |
|
1203 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow), |
|
1204 gNewExpectedWindow, getById("f3"), true, "switch document forward with f6"); |
|
1205 gOldExpectedWindow = gNewExpectedWindow; |
|
1206 gNewExpectedWindow = framesetWindow.frames[2]; |
|
1207 expectFocusShift(function () synthesizeKey("VK_F6", { }, framesetWindow), |
|
1208 gNewExpectedWindow, getById("f5"), true, "switch document forward with ctrl+tab"); |
|
1209 gOldExpectedWindow = gNewExpectedWindow; |
|
1210 gNewExpectedWindow = framesetWindow.frames[3]; |
|
1211 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow), |
|
1212 gNewExpectedWindow, getById("f7"), true, "switch document forward with ctrl+f6"); |
|
1213 gOldExpectedWindow = gNewExpectedWindow; |
|
1214 gNewExpectedWindow = framesetWindow.frames[0]; |
|
1215 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow), |
|
1216 gNewExpectedWindow, getById("f1"), true, "switch document forward and wrap"); |
|
1217 |
|
1218 // going backwards by document and wrapping doesn't currently work, but didn't work |
|
1219 // before the focus reworking either |
|
1220 |
|
1221 /* |
|
1222 gOldExpectedWindow = gNewExpectedWindow; |
|
1223 gNewExpectedWindow = framesetWindow.frames[3]; |
|
1224 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), |
|
1225 gNewExpectedWindow, getById("f7"), true, "switch document backward and wrap"); |
|
1226 */ |
|
1227 |
|
1228 fm.moveFocus(framesetWindow.frames[3], null, fm.MOVEFOCUS_ROOT, 0); |
|
1229 gEvents = ""; |
|
1230 |
|
1231 gOldExpectedWindow = gNewExpectedWindow; |
|
1232 gNewExpectedWindow = framesetWindow.frames[2]; |
|
1233 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), |
|
1234 gNewExpectedWindow, getById("f5"), true, "switch document backward with f6"); |
|
1235 gOldExpectedWindow = gNewExpectedWindow; |
|
1236 gNewExpectedWindow = framesetWindow.frames[1]; |
|
1237 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), |
|
1238 gNewExpectedWindow, getById("f3"), true, "switch document backward with ctrl+tab"); |
|
1239 gOldExpectedWindow = gNewExpectedWindow; |
|
1240 gNewExpectedWindow = framesetWindow.frames[0]; |
|
1241 expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), |
|
1242 gNewExpectedWindow, getById("f1"), true, "switch document backward with ctrl+f6"); |
|
1243 |
|
1244 // skip the window switching tests for now on Linux, as raising and lowering |
|
1245 // a window is asynchronous there |
|
1246 if (navigator.platform.indexOf("Linux") == -1) { |
|
1247 window.openDialog("focus_window2.xul", "_blank", "chrome", switchWindowTest, framesetWindow); |
|
1248 } |
|
1249 else { |
|
1250 gOldExpectedWindow = null; |
|
1251 gNewExpectedWindow = null; |
|
1252 framesetWindow.close(); |
|
1253 SimpleTest.waitForFocus(doWindowNoRootTest); |
|
1254 } |
|
1255 } |
|
1256 |
|
1257 // test switching between two windows |
|
1258 function switchWindowTest(otherWindow, framesetWindow) |
|
1259 { |
|
1260 initEvents(otherWindow); |
|
1261 var otherElement = otherWindow.document.getElementById("other"); |
|
1262 otherElement.focus(); |
|
1263 |
|
1264 framesetWindow.frames[1].document.getElementById("f4").focus(); |
|
1265 |
|
1266 is(fm.focusedElement, otherElement, "focus after inactive window focus"); |
|
1267 |
|
1268 gLastFocus = otherElement; |
|
1269 gLastFocusWindow = otherWindow; |
|
1270 gEvents = ""; |
|
1271 gOldExpectedWindow = otherWindow; |
|
1272 gNewExpectedWindow = framesetWindow.frames[1]; |
|
1273 |
|
1274 expectFocusShift(function () gNewExpectedWindow.focus(), |
|
1275 gNewExpectedWindow, getById("f4"), true, "switch to frame in another window"); |
|
1276 is(fm.getFocusedElementForWindow(otherWindow, false, {}).id, "other", "inactive window has focused element"); |
|
1277 |
|
1278 gOldExpectedWindow = framesetWindow.frames[1]; |
|
1279 gNewExpectedWindow = otherWindow; |
|
1280 expectFocusShift(function () otherWindow.focus(), |
|
1281 gNewExpectedWindow, getById("other"), true, "switch to another window"); |
|
1282 |
|
1283 var exh = false; |
|
1284 try { |
|
1285 fm.activeWindow = framesetWindow.frames[0]; |
|
1286 } |
|
1287 catch (ex) { exh = true; } |
|
1288 is(exh, true, "activeWindow set to non top-level window"); |
|
1289 |
|
1290 exh = false; |
|
1291 try { |
|
1292 fm.activeWindow = null; |
|
1293 } |
|
1294 catch (ex) { exh = true; } |
|
1295 is(exh, true, "activeWindow set to null"); |
|
1296 is(fm.activeWindow, otherWindow, "window not changed when activeWindow set to null"); |
|
1297 |
|
1298 var topWindow = getTopWindow(framesetWindow); |
|
1299 |
|
1300 ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"), |
|
1301 "getControllerForCommand for focused window set"); |
|
1302 ok(otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"), |
|
1303 "getControllerForCommand for non-focused window set"); |
|
1304 ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy") != |
|
1305 otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"), |
|
1306 "getControllerForCommand for two windows different"); |
|
1307 ok(topWindow.document.commandDispatcher.getControllers() != |
|
1308 otherWindow.document.commandDispatcher.getControllers(), |
|
1309 "getControllers for two windows different"); |
|
1310 |
|
1311 gOldExpectedWindow = otherWindow; |
|
1312 gNewExpectedWindow = framesetWindow.frames[1]; |
|
1313 expectFocusShift(function () fm.activeWindow = topWindow, |
|
1314 gNewExpectedWindow, getById("f4"), true, "switch to frame activeWindow"); |
|
1315 |
|
1316 fm.clearFocus(otherWindow); |
|
1317 gOldExpectedWindow = gNewExpectedWindow; |
|
1318 gNewExpectedWindow = otherWindow; |
|
1319 expectFocusShift(function () fm.setFocus(otherElement, fm.FLAG_RAISE), |
|
1320 gNewExpectedWindow, getById("other"), true, "switch to window with raise"); |
|
1321 |
|
1322 getTopWindow(framesetWindow).document.commandDispatcher.focusedWindow = gOldExpectedWindow; |
|
1323 is(fm.activeWindow, gNewExpectedWindow, "setting commandDispatcher focusedWindow doesn't raise window"); |
|
1324 |
|
1325 fm.moveFocus(otherWindow, null, fm.MOVEFOCUS_FORWARD, 0); |
|
1326 var otherTextbox = otherWindow.document.getElementById("other-textbox"); |
|
1327 otherTextbox.setSelectionRange(2, 3); |
|
1328 fm.activeWindow = topWindow; |
|
1329 fm.activeWindow = otherWindow; |
|
1330 is(otherTextbox.selectionStart, 2, "selectionStart after textbox focus and window raise"); |
|
1331 is(otherTextbox.selectionEnd, 3, "selectionEnd after textbox focus and window raise"); |
|
1332 is(fm.getLastFocusMethod(null), fm.FLAG_BYMOVEFOCUS, "last focus method after textbox focus and window raise"); |
|
1333 |
|
1334 fm.clearFocus(otherWindow); |
|
1335 |
|
1336 // test to ensure that a synthetic event works |
|
1337 var synevent = document.createEvent("Event"); |
|
1338 synevent.initEvent("focus", false, false); |
|
1339 otherTextbox.inputField.dispatchEvent(synevent); |
|
1340 is(synevent.type, "focus", "event.type after synthetic focus event"); |
|
1341 is(synevent.target, otherTextbox, "event.target after synthetic focus event"); |
|
1342 is(fm.focusedElement, null, "focusedElement after synthetic focus event"); |
|
1343 is(otherWindow.document.activeElement, otherWindow.document.documentElement, |
|
1344 "document.activeElement after synthetic focus event"); |
|
1345 |
|
1346 // check accessing a focus event after the event has finishing firing |
|
1347 function continueTest(event) { |
|
1348 is(event.type, "focus", "event.type after accessing focus event in timeout"); |
|
1349 is(event.target, otherTextbox, "event.target after accessing focus event in timeout"); |
|
1350 |
|
1351 gOldExpectedWindow = null; |
|
1352 gNewExpectedWindow = null; |
|
1353 otherWindow.close(); |
|
1354 framesetWindow.close(); |
|
1355 |
|
1356 SimpleTest.waitForFocus(doWindowNoRootTest); |
|
1357 } |
|
1358 |
|
1359 function textboxFocused(event) { |
|
1360 otherTextbox.removeEventListener("focus", textboxFocused, true); |
|
1361 setTimeout(continueTest, 0, event); |
|
1362 } |
|
1363 |
|
1364 otherTextbox.addEventListener("focus", textboxFocused, true); |
|
1365 otherTextbox.focus(); |
|
1366 } |
|
1367 |
|
1368 // open a window with no root element |
|
1369 var noRootWindow = null; |
|
1370 function doWindowNoRootTest() |
|
1371 { |
|
1372 var data = "data:application/vnd.mozilla.xul+xml," + unescape( |
|
1373 "<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" + |
|
1374 " style='-moz-user-focus: normal;'>" + |
|
1375 "<script>function dostuff() { setTimeout(function() { " + |
|
1376 "document.documentElement.focus(); document.removeChild(document.documentElement);" + |
|
1377 "window.opener.focus(); }, 100); }</script></window>"); |
|
1378 |
|
1379 addEventListener("focus", doFrameSwitchingTests, true); |
|
1380 noRootWindow = window.open(data, "_blank", "chrome,width=100,height=100"); |
|
1381 } |
|
1382 |
|
1383 // these tests check when focus is moved between a tree of frames to ensure |
|
1384 // that the focus is in the right place at each event step. |
|
1385 function doFrameSwitchingTests() |
|
1386 { |
|
1387 removeEventListener("focus", doFrameSwitchingTests, true); |
|
1388 noRootWindow.close(); |
|
1389 |
|
1390 var framea = document.getElementById("ifa"); |
|
1391 var frameb = document.getElementById("ifb"); |
|
1392 framea.style.MozUserFocus = ""; |
|
1393 frameb.style.MozUserFocus = ""; |
|
1394 |
|
1395 window.removeEventListener("focus", eventOccured, true); |
|
1396 window.removeEventListener("blur", eventOccured, true); |
|
1397 |
|
1398 var inputa = framea.contentDocument.body.firstChild; |
|
1399 inputa.focus(); |
|
1400 |
|
1401 addFrameSwitchingListeners(framea); |
|
1402 addFrameSwitchingListeners(frameb); |
|
1403 var framec = framea.contentDocument.body.lastChild; |
|
1404 addFrameSwitchingListeners(framec); |
|
1405 |
|
1406 var framed = framec.contentDocument.body.lastChild; |
|
1407 addFrameSwitchingListeners(framed); |
|
1408 |
|
1409 var inputc = framec.contentDocument.body.firstChild; |
|
1410 |
|
1411 var expectedMainWindowFocus = framea; |
|
1412 |
|
1413 // An element in the immediate parent frame is focused. Focus an element in |
|
1414 // the child. The child should be focused and the parent's current focus should |
|
1415 // be the child iframe. |
|
1416 gEventMatched = true; |
|
1417 is(fm.getFocusedElementForWindow(window, false, {}), expectedMainWindowFocus, |
|
1418 "parent of framea has iframe focused"); |
|
1419 gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea], |
|
1420 [framea.contentDocument, "blur", null, null, window, framea], |
|
1421 [framea.contentWindow, "blur", null, null, window, framea], |
|
1422 [framec.contentDocument, "focus", null, framec.contentWindow, window, framea], |
|
1423 [framec.contentWindow, "focus", null, framec.contentWindow, window, framea], |
|
1424 [inputc, "focus", inputc, framec.contentWindow, window, framea]]; |
|
1425 inputc.focus(); |
|
1426 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from parent input to child input" + gExpectedEvents); |
|
1427 |
|
1428 // An element in a child is focused. Focus an element in the immediate |
|
1429 // parent. |
|
1430 gEventMatched = true; |
|
1431 gExpectedEvents = [[inputc, "blur", null, framec.contentWindow, window, framea], |
|
1432 [framec.contentDocument, "blur", null, null, window, framea], |
|
1433 [framec.contentWindow, "blur", null, null, window, framea], |
|
1434 [framea.contentDocument, "focus", null, framea.contentWindow, window, framea], |
|
1435 [framea.contentWindow, "focus", null, framea.contentWindow, window, framea], |
|
1436 [inputa, "focus", inputa, framea.contentWindow, window, framea]]; |
|
1437 inputa.focus(); |
|
1438 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to parent input"); |
|
1439 |
|
1440 // An element in a frame is focused. Focus an element in a sibling frame. |
|
1441 // The common ancestor of the two frames should have its focused node |
|
1442 // cleared after the element is blurred. |
|
1443 var inputb = frameb.contentDocument.body.firstChild; |
|
1444 |
|
1445 gEventMatched = true; |
|
1446 gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea], |
|
1447 [framea.contentDocument, "blur", null, null, window, null], |
|
1448 [framea.contentWindow, "blur", null, null, window, null], |
|
1449 [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb], |
|
1450 [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb], |
|
1451 [inputb, "focus", inputb, frameb.contentWindow, window, frameb]]; |
|
1452 inputb.focus(); |
|
1453 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling frame"); |
|
1454 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), inputa, |
|
1455 "blurred frame still has input as focus"); |
|
1456 |
|
1457 // focus a descendant in a sibling |
|
1458 var inputd = framed.contentDocument.body.firstChild; |
|
1459 gEventMatched = true; |
|
1460 gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb], |
|
1461 [frameb.contentDocument, "blur", null, null, window, null], |
|
1462 [frameb.contentWindow, "blur", null, null, window, null], |
|
1463 [framed.contentDocument, "focus", null, framed.contentWindow, window, framea], |
|
1464 [framed.contentWindow, "focus", null, framed.contentWindow, window, framea], |
|
1465 [inputd, "focus", inputd, framed.contentWindow, window, framea]]; |
|
1466 inputd.focus(); |
|
1467 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling descendant"); |
|
1468 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec, |
|
1469 "sibling parent focus has shifted to frame"); |
|
1470 |
|
1471 // focus an ancestor |
|
1472 gEventMatched = true; |
|
1473 gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea], |
|
1474 [framed.contentDocument, "blur", null, null, window, framea], |
|
1475 [framed.contentWindow, "blur", null, null, window, framea], |
|
1476 [framea.contentDocument, "focus", null, framea.contentWindow, window, framea], |
|
1477 [framea.contentWindow, "focus", null, framea.contentWindow, window, framea], |
|
1478 [inputa, "focus", inputa, framea.contentWindow, window, framea]]; |
|
1479 inputa.focus(); |
|
1480 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor"); |
|
1481 |
|
1482 // focus a descendant |
|
1483 gEventMatched = true; |
|
1484 gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea], |
|
1485 [framea.contentDocument, "blur", null, null, window, framea], |
|
1486 [framea.contentWindow, "blur", null, null, window, framea], |
|
1487 [framed.contentDocument, "focus", null, framed.contentWindow, window, framea], |
|
1488 [framed.contentWindow, "focus", null, framed.contentWindow, window, framea], |
|
1489 [inputd, "focus", inputd, framed.contentWindow, window, framea]]; |
|
1490 inputd.focus(); |
|
1491 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor"); |
|
1492 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec, |
|
1493 "parent focus has shifted to frame"); |
|
1494 |
|
1495 // focus a sibling frame by setting focusedWindow |
|
1496 gEventMatched = true; |
|
1497 gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea], |
|
1498 [framed.contentDocument, "blur", null, null, window, null], |
|
1499 [framed.contentWindow, "blur", null, null, window, null], |
|
1500 [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb], |
|
1501 [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb], |
|
1502 [inputb, "focus", inputb, frameb.contentWindow, window, frameb]]; |
|
1503 fm.focusedWindow = frameb.contentWindow; |
|
1504 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow"); |
|
1505 |
|
1506 // clear the focus in an unfocused frame |
|
1507 gEventMatched = true; |
|
1508 gExpectedEvents = []; |
|
1509 fm.clearFocus(framec.contentWindow); |
|
1510 ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused frame"); |
|
1511 |
|
1512 // focus a sibling frame by setting focusedWindow when no element is focused in that frame |
|
1513 gEventMatched = true; |
|
1514 gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb], |
|
1515 [frameb.contentDocument, "blur", null, null, window, null], |
|
1516 [frameb.contentWindow, "blur", null, null, window, null], |
|
1517 [framec.contentDocument, "focus", null, framec.contentWindow, window, framea], |
|
1518 [framec.contentWindow, "focus", null, framec.contentWindow, window, framea]]; |
|
1519 fm.focusedWindow = framec.contentWindow; |
|
1520 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow with no element focused"); |
|
1521 is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec, |
|
1522 "parent focus has shifted to frame using focusedWindow"); |
|
1523 |
|
1524 // focus the parent frame by setting focusedWindow. This should have no effect. |
|
1525 gEventMatched = true; |
|
1526 gExpectedEvents = []; |
|
1527 fm.focusedWindow = framea.contentWindow; |
|
1528 ok(gEventMatched && gExpectedEvents.length == 0, "frame switch to parent using focusedWindow"); |
|
1529 |
|
1530 // clear the focus in the parent frame |
|
1531 gEventMatched = true; |
|
1532 gExpectedEvents = [[framec.contentDocument, "blur", null, null, window, framea], |
|
1533 [framec.contentWindow, "blur", null, null, window, framea], |
|
1534 [framea.contentDocument, "focus", null, framea.contentWindow, window, framea], |
|
1535 [framea.contentWindow, "focus", null, framea.contentWindow, window, framea]]; |
|
1536 fm.clearFocus(framea.contentWindow); |
|
1537 ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in parent frame"); |
|
1538 |
|
1539 // clear the focus in an unfocused child frame |
|
1540 gEventMatched = true; |
|
1541 gExpectedEvents = []; |
|
1542 fm.clearFocus(framed.contentWindow); |
|
1543 ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused child frame"); |
|
1544 |
|
1545 var exh = false; |
|
1546 try { |
|
1547 fm.focusedWindow = null; |
|
1548 } |
|
1549 catch (ex) { exh = true; } |
|
1550 is(exh, true, "focusedWindow set to null"); |
|
1551 is(fm.focusedWindow, framea.contentWindow, "window not changed when focusedWindow set to null"); |
|
1552 |
|
1553 doFrameHistoryTests() |
|
1554 } |
|
1555 |
|
1556 function doFrameHistoryTests() |
|
1557 { |
|
1558 var t20 = getById("t20"); |
|
1559 t20.focus(); |
|
1560 |
|
1561 gChildWindow.addEventListener("focus", |
|
1562 function(event) { |
|
1563 if (event.target == t20) { |
|
1564 is(fm.focusedElement, t20, "focus restored after history back"); done(); |
|
1565 } |
|
1566 }, true); |
|
1567 |
|
1568 // make sure that loading a new page and then going back maintains the focus |
|
1569 gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () {window.back();}, 0);}</script>"; |
|
1570 } |
|
1571 |
|
1572 function addFrameSwitchingListeners(frame) |
|
1573 { |
|
1574 frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false); |
|
1575 frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false); |
|
1576 frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false); |
|
1577 frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false); |
|
1578 |
|
1579 var node = frame.contentDocument.body.firstChild; |
|
1580 node.addEventListener("focus", frameSwitchingEventOccured, false); |
|
1581 node.addEventListener("blur", frameSwitchingEventOccured, false); |
|
1582 } |
|
1583 |
|
1584 function frameSwitchingEventOccured(event) |
|
1585 { |
|
1586 if (!gExpectedEvents.length) { |
|
1587 gEventMatched = false; |
|
1588 return; |
|
1589 } |
|
1590 |
|
1591 try { |
|
1592 var events = gExpectedEvents.shift(); |
|
1593 is(event.target, events[0], "event target"); |
|
1594 is(event.type, events[1], "event type"); |
|
1595 is(fm.focusedElement, events[2], "focused element"); |
|
1596 is(fm.focusedWindow, events[3], "focused frame"); |
|
1597 if (events[4]) |
|
1598 is(fm.getFocusedElementForWindow(events[4], false, {}), events[5], "focused element in frame"); |
|
1599 |
|
1600 if (gEventMatched && event.target == events[0] && event.type == events[1] && |
|
1601 fm.focusedElement == events[2] && fm.focusedWindow == events[3]) { |
|
1602 if (!events[4] || fm.getFocusedElementForWindow(events[4], false, {}) == events[5]) |
|
1603 return; |
|
1604 } |
|
1605 } catch (ex) { ok(ex, "exception"); } |
|
1606 |
|
1607 gEventMatched = false; |
|
1608 } |
|
1609 |
|
1610 SimpleTest.waitForExplicitFinish(); |
|
1611 SimpleTest.waitForFocus(startTest); |
|
1612 |
|
1613 ]]> |
|
1614 </script> |
|
1615 |
|
1616 <commandset id="cu" |
|
1617 commandupdater="true" |
|
1618 events="focus" |
|
1619 oncommandupdate="eventOccured(event)"/> |
|
1620 |
|
1621 <!-- |
|
1622 The elements with ids starting with t are focusable and in the taborder. |
|
1623 The elements with ids starting with o are: |
|
1624 odd numbered ids - focusable but not part of the tab order |
|
1625 even numbered ids - not focusable with -moz-user-focus: ignore or disabled |
|
1626 The elements with ids starting with n are: |
|
1627 odd numbered ids - not focusable with -moz-user-focus: none |
|
1628 even numbered ids - focusable but not part of the tab order |
|
1629 --> |
|
1630 <vbox id="buttonbox"> |
|
1631 <hbox id="innerbox"> |
|
1632 <button id="t4" accesskey="h" label="no tabindex"/> |
|
1633 <button id="o1" accesskey="i" label="tabindex = -1" tabindex="-1"/> |
|
1634 <listbox id="t5" label="tabindex = 0" tabindex="0" rows="1"> |
|
1635 <listitem/> |
|
1636 </listbox> |
|
1637 <button id="t1" label="tabindex = 2" tabindex="2"/> |
|
1638 </hbox> |
|
1639 <hbox> |
|
1640 <button id="o2" accesskey="o" style="-moz-user-focus: ignore;" label="no tabindex"/> |
|
1641 <button id="o4" style="-moz-user-focus: ignore;" label="tabindex = -1" tabindex="-1"/> |
|
1642 <button id="t6" style="-moz-user-focus: ignore;" label="tabindex = 0" tabindex="0"/> |
|
1643 <button id="t2" style="-moz-user-focus: ignore;" label="tabindex = 2" tabindex="2"/> |
|
1644 </hbox> |
|
1645 <hbox id="specialroot"> |
|
1646 <button id="t7" style="-moz-user-focus: normal;" label="no tabindex"/> |
|
1647 <button id="o3" style="-moz-user-focus: normal;" label="tabindex = -1" tabindex="-1"/> |
|
1648 <button id="t8" style="-moz-user-focus: normal;" label="tabindex = 0" tabindex="0"/> |
|
1649 <listbox id="t3" style="-moz-user-focus: normal;" label="tabindex = 2" tabindex="2" rows="1"> |
|
1650 <listitem/> |
|
1651 </listbox> |
|
1652 </hbox> |
|
1653 <hbox> |
|
1654 <button accesskey="p" style="display: none;"/> <button accesskey="q" style="visibility: collapse;"/> |
|
1655 <button style="display: none;" tabindex="2"/> <button style="visibility: collapse;" tabindex="2"/> |
|
1656 </hbox> |
|
1657 <hbox> |
|
1658 <button id="o20" accesskey="s" label="no tabindex" disabled="true"/> |
|
1659 <button id="o22" label="tabindex = -1" tabindex="-1" disabled="true"/> |
|
1660 <button id="o24" label="tabindex = 0" tabindex="0" disabled="true"/> |
|
1661 <button id="o26" label="tabindex = 2" tabindex="2" disabled="true"/> |
|
1662 </hbox> |
|
1663 </vbox> |
|
1664 <vbox> |
|
1665 <hbox> |
|
1666 <dropmarker id="o6" value="no tabindex"/> |
|
1667 <dropmarker id="o8" value="tabindex = -1" tabindex="-1"/> |
|
1668 <dropmarker id="o10" value="tabindex = 0" tabindex="0"/> |
|
1669 <dropmarker id="o12" value="tabindex = 2" tabindex="2"/> |
|
1670 <dropmarker id="t9" accesskey="r" style="-moz-user-focus: normal;" value="no tabindex" /> |
|
1671 <dropmarker id="t10" style="-moz-user-focus: normal;" value="tabindex = -1" tabindex="-1" /> |
|
1672 <dropmarker id="t11" style="-moz-user-focus: normal;" value="tabindex = 0" tabindex="0" /> |
|
1673 <dropmarker id="t12" style="-moz-user-focus: normal;" value="tabindex = 2" tabindex="2" /> |
|
1674 <dropmarker id="o14" style="-moz-user-focus: ignore;" value="no tabindex"/> |
|
1675 <dropmarker id="o16" style="-moz-user-focus: ignore;" value="tabindex = -1" tabindex="-1"/> |
|
1676 <dropmarker id="n1" style="-moz-user-focus: none;" value="tabindex = 0" tabindex="0"/> |
|
1677 <dropmarker id="n3" style="-moz-user-focus: none;" value="tabindex = 2" tabindex="2"/> |
|
1678 </hbox> |
|
1679 </vbox> |
|
1680 <browser id="childframe" type="content" src="child_focus_frame.html" width="300" height="195"/> |
|
1681 <button id="t34"/> |
|
1682 <tabbox id="tabbox"> |
|
1683 <tabs><tab id="t35" label="One"/><tab id="tab2" label="Two"/></tabs> |
|
1684 <tabpanels> |
|
1685 <tabpanel> |
|
1686 <checkbox id="t36"/> |
|
1687 <button id="t37"/> |
|
1688 </tabpanel> |
|
1689 <tabpanel> |
|
1690 <checkbox id="htab1"/> |
|
1691 <button id="nohtab2" tabindex="7"/> |
|
1692 <checkbox id="htab2" tabindex="0"/> |
|
1693 </tabpanel> |
|
1694 </tabpanels> |
|
1695 </tabbox> |
|
1696 <hbox> |
|
1697 <panel> |
|
1698 <button id="inpopup1" label="One"/> |
|
1699 <textbox label="Two"/> |
|
1700 </panel> |
|
1701 <description label="o" accesskey="v"/> |
|
1702 <button id="t38"/> |
|
1703 <!-- The 't' element tests end here so it doesn't matter that these elements are tabbable --> |
|
1704 <label id="aj" value="j" accesskey="j" control="o9"/> |
|
1705 <label id="ak" accesskey="k" control="n4">k</label> |
|
1706 <checkbox id="o5"/><checkbox id="o7"/><hbox><checkbox id="o9"/></hbox> |
|
1707 <checkbox id="o13"/><checkbox id="o15"/><checkbox id="o17"/><checkbox id="o19"/><checkbox id="o21"/><checkbox id="o23"/><checkbox id="o25"/> |
|
1708 <checkbox id="n2"/><checkbox id="n4"/> |
|
1709 <listbox id="last" width="20" rows="1"/> |
|
1710 |
|
1711 <iframe id="ifa" width="40" height="60" style="-moz-user-focus: ignore;" type="content" |
|
1712 src="data:text/html,<input id=fra size='2'><input id='fra-b' size='2'> |
|
1713 <iframe src='data:text/html,<input id=frc><iframe src="data:text/html,<input id=frd>"></iframe>'></iframe>"/> |
|
1714 <iframe id="ifb" width="20" height="20" style="-moz-user-focus: ignore;" |
|
1715 src="data:text/html,<input id=frd></iframe>"/> |
|
1716 |
|
1717 </hbox> |
|
1718 </window> |