зеркало из https://github.com/mozilla/pjs.git
1711 строки
74 KiB
XML
1711 строки
74 KiB
XML
<?xml version="1.0"?>
|
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
|
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
|
type="text/css"?>
|
|
<!--
|
|
This test checks focus in various ways
|
|
-->
|
|
<window id="outer-document" title="Focus Test" width="600" height="550"
|
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
<script type="application/javascript"
|
|
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
|
<script type="application/javascript"
|
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
<script type="application/javascript"
|
|
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
|
|
|
<body xmlns="http://www.w3.org/1999/xhtml"/>
|
|
|
|
<script type="application/javascript"><![CDATA[
|
|
|
|
var fm = Components.classes["@mozilla.org/focus-manager;1"].
|
|
getService(Components.interfaces.nsIFocusManager);
|
|
|
|
const kChildDocumentRootIndex = 13;
|
|
const kBeforeTabboxIndex = 34;
|
|
const kTabbableSteps = 38;
|
|
const kFocusSteps = 18;
|
|
const kNoFocusSteps = 15;
|
|
const kOverflowElementIndex = 27;
|
|
|
|
var gTestStarted = false;
|
|
var gPartialTabbing = false;
|
|
var gMoveToFocusFrame = false;
|
|
var gLastFocus = null;
|
|
var gLastFocusWindow = window;
|
|
var gLastFocusMethod = -1;
|
|
var gEvents = "";
|
|
var gExpectedEvents = "";
|
|
var gEventMatched = true;
|
|
var gShowOutput = false;
|
|
var gChildWindow = null;
|
|
|
|
var gOldExpectedWindow = null;
|
|
var gNewExpectedWindow = null;
|
|
|
|
function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
|
|
function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
|
|
|
|
function initEvents(target)
|
|
{
|
|
target.addEventListener("focus", eventOccured, true);
|
|
target.addEventListener("blur", eventOccured, true);
|
|
getTopWindow(target).addEventListener("activate", eventOccured, true);
|
|
getTopWindow(target).addEventListener("deactivate", eventOccured, true);
|
|
}
|
|
|
|
function eventOccured(event)
|
|
{
|
|
// iframes should never receive focus or blur events directly
|
|
if (event.target instanceof Element && event.target.localName == "iframe")
|
|
ok(false, "iframe " + event.type + "occured");
|
|
|
|
var id;
|
|
if (gOldExpectedWindow && event.type == "blur") {
|
|
if (event.target instanceof Window)
|
|
id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-window";
|
|
else if (event.target instanceof Document)
|
|
id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-document";
|
|
else
|
|
id = event.originalTarget.id;
|
|
}
|
|
else if (gNewExpectedWindow && event.type == "focus") {
|
|
if (event.target instanceof Window)
|
|
id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-window";
|
|
else if (event.target instanceof Document)
|
|
id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-document";
|
|
else
|
|
id = event.originalTarget.id;
|
|
}
|
|
else if (event.type == "activate" || event.type == "deactivate")
|
|
id = event.target.document.documentElement.id + "-window";
|
|
else if (event.target instanceof Window)
|
|
id = (event.target == window) ? "outer-window" : "child-window";
|
|
else if (event.target instanceof Document)
|
|
id = (event.target == document) ? "outer-document" : "child-document";
|
|
else
|
|
id = event.originalTarget.id;
|
|
|
|
if (gEvents)
|
|
gEvents += " ";
|
|
gEvents += event.type + ": " + id;
|
|
}
|
|
|
|
function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid)
|
|
{
|
|
if (expectedWindow == null)
|
|
expectedWindow = expectedElement ?
|
|
expectedElement.ownerDocument.defaultView :
|
|
gLastFocusWindow;
|
|
|
|
var expectedEvents = "";
|
|
if (focusChanged) {
|
|
var id;
|
|
if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
|
|
id = getTopWindow(gLastFocusWindow).document.documentElement.id;
|
|
expectedEvents += "deactivate: " + id + "-window";
|
|
}
|
|
|
|
if (gLastFocus && gLastFocus.id != "t" + kChildDocumentRootIndex &&
|
|
(!gOldExpectedWindow || gOldExpectedWindow.document.documentElement != gLastFocus)) {
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
if (!gOldExpectedWindow)
|
|
expectedEvents += "commandupdate: cu ";
|
|
expectedEvents += "blur: " + gLastFocus.id;
|
|
}
|
|
|
|
if (gLastFocusWindow && gLastFocusWindow != expectedWindow) {
|
|
if (!gMoveToFocusFrame) {
|
|
if (gOldExpectedWindow)
|
|
id = "frame-" + gOldExpectedWindow.document.documentElement.id;
|
|
else
|
|
id = (gLastFocusWindow == window) ? "outer" : "child";
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
expectedEvents += "blur: " + id + "-document " +
|
|
"blur: " + id + "-window";
|
|
}
|
|
}
|
|
|
|
if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
|
|
id = getTopWindow(expectedWindow).document.documentElement.id;
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
expectedEvents += "activate: " + id + "-window";
|
|
}
|
|
|
|
if (expectedWindow && gLastFocusWindow != expectedWindow) {
|
|
if (gNewExpectedWindow)
|
|
id = "frame-" + gNewExpectedWindow.document.documentElement.id;
|
|
else
|
|
id = (expectedWindow == window) ? "outer" : "child";
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
expectedEvents += "focus: " + id + "-document " +
|
|
"focus: " + id + "-window";
|
|
}
|
|
|
|
// for this test which fires a mouse event on a label, the document will
|
|
// be focused first and then the label code will focus the related
|
|
// control. This doesn't result in different focus events, but a command
|
|
// update will occur for the document and then a secon command update will
|
|
// occur when the control is focused.
|
|
if (testid == "mouse on html label with content inside")
|
|
expectedEvents += " commandupdate: cu";
|
|
|
|
if (expectedElement &&
|
|
(!gNewExpectedWindow || gNewExpectedWindow.document.documentElement != expectedElement)) {
|
|
if (!gNewExpectedWindow) {
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
expectedEvents += "commandupdate: cu";
|
|
}
|
|
if (expectedElement.id != "t" + kChildDocumentRootIndex) {
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
expectedEvents += "focus: " + expectedElement.id;
|
|
}
|
|
}
|
|
else if (expectedWindow && gLastFocusWindow != expectedWindow &&
|
|
!expectedElement) {
|
|
if (expectedEvents)
|
|
expectedEvents += " ";
|
|
expectedEvents += "commandupdate: cu";
|
|
}
|
|
}
|
|
|
|
gLastFocus = expectedElement;
|
|
gLastFocusWindow = expectedWindow;
|
|
|
|
callback();
|
|
|
|
compareEvents(expectedEvents, expectedWindow, expectedElement, testid);
|
|
}
|
|
|
|
function compareEvents(expectedEvents, expectedWindow, expectedElement, testid)
|
|
{
|
|
if (!gShowOutput) {
|
|
gEvents = "";
|
|
return;
|
|
}
|
|
|
|
is(gEvents, expectedEvents, testid + " events");
|
|
gEvents = "";
|
|
|
|
var doc;
|
|
if (expectedWindow == window)
|
|
doc = "outer-document";
|
|
else if (expectedWindow == gChildWindow)
|
|
doc = "inner-document";
|
|
else if (gNewExpectedWindow)
|
|
doc = gNewExpectedWindow.document.body ? gNewExpectedWindow.document.body.id :
|
|
gNewExpectedWindow.document.documentElement.id;
|
|
else
|
|
doc = "other-document";
|
|
|
|
var focusedElement = fm.focusedElement;
|
|
is(focusedElement ? focusedElement.id : "none",
|
|
expectedElement ? expectedElement.id : "none", testid + " focusedElement");
|
|
is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
|
|
var focusedWindow = {};
|
|
is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
|
|
expectedElement, testid + " getFocusedElementForWindow");
|
|
is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame");
|
|
is(expectedWindow.document.hasFocus(), true, testid + " hasFocus");
|
|
is(expectedWindow.document.activeElement ? expectedWindow.document.activeElement.id : "none",
|
|
expectedElement ? expectedElement.id : doc, testid + " activeElement");
|
|
var cdwindow = getTopWindow(expectedWindow);
|
|
if (cdwindow.document.commandDispatcher) {
|
|
is(cdwindow.document.commandDispatcher.focusedWindow, expectedWindow, testid + " commandDispatcher focusedWindow");
|
|
is(cdwindow.document.commandDispatcher.focusedElement, focusedElement, testid + " commandDispatcher focusedElement");
|
|
}
|
|
|
|
if (gLastFocusMethod != -1) {
|
|
is(fm.getLastFocusMethod(null), gLastFocusMethod, testid + " lastFocusMethod null");
|
|
is(fm.getLastFocusMethod(expectedWindow), gLastFocusMethod, testid + " lastFocusMethod window");
|
|
}
|
|
|
|
// the parent should have the iframe focused
|
|
if (doc == "inner-document") {
|
|
is(document.hasFocus(), true, testid + " hasFocus");
|
|
is(fm.getFocusedElementForWindow(window, false, focusedWindow),
|
|
$("childframe"), testid + " getFocusedElementForWindow for parent");
|
|
is(focusedWindow.value, window, testid + " getFocusedElementForWindow for parent frame");
|
|
is(fm.getFocusedElementForWindow(window, true, focusedWindow),
|
|
expectedElement, testid + " getFocusedElementForWindow deep for parent");
|
|
is(focusedWindow.value, gChildWindow, testid + " getFocusedElementForWindow deep for parent frame");
|
|
is(document.activeElement.id, "childframe", testid + " activeElement for parent");
|
|
}
|
|
|
|
// compare the selection for the child window. Skip mouse tests as the caret
|
|
// is adjusted by the selection code for mouse clicks, and not the focus code.
|
|
if (expectedWindow == window) {
|
|
var selection = window.getSelection();
|
|
ok(selection.focusNode == null && selection.focusOffset == 0 &&
|
|
selection.anchorNode == null && selection.anchorOffset == 0, testid + " selection");
|
|
}
|
|
else if ((expectedWindow == gChildWindow) && !testid.indexOf("mouse") == -1) {
|
|
checkSelection(expectedElement, testid);
|
|
}
|
|
}
|
|
|
|
function checkSelection(node, testid)
|
|
{
|
|
var selection = gChildWindow.getSelection();
|
|
|
|
var range = gChildWindow.document.createRange();
|
|
range.selectNodeContents(node);
|
|
if (!node.firstChild || node.localName == "input" ||
|
|
node.localName == "select" || node.localName == "button") {
|
|
range.setStartBefore(node);
|
|
range.setEndBefore(node);
|
|
}
|
|
|
|
if (node.firstChild)
|
|
range.setEnd(range.startContainer, range.startOffset);
|
|
|
|
is(selection.focusNode, range.startContainer, testid + " selection focusNode");
|
|
is(selection.focusOffset, range.startOffset, testid + " selection focusOffset");
|
|
is(selection.anchorNode, range.endContainer, testid + " selection anchorNode");
|
|
is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset");
|
|
}
|
|
|
|
function getTopWindow(win)
|
|
{
|
|
return win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
|
getInterface(Components.interfaces.nsIWebNavigation).
|
|
QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem.
|
|
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
|
getInterface(Components.interfaces.nsIDOMWindow);
|
|
}
|
|
|
|
function mouseOnElement(element, expectedElement, focusChanged, testid)
|
|
{
|
|
var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window;
|
|
// on Mac, form elements are not focused when clicking, except for lists and textboxes.
|
|
var noFocusOnMouse = (navigator.platform.indexOf("Mac") == 0);
|
|
if (noFocusOnMouse) {
|
|
if (element.namespaceURI == "http://www.w3.org/1999/xhtml") {
|
|
// links are special. They can be focused but show no focus ring
|
|
if (element.localName == "a" || element.localName == "div" ||
|
|
element.localName == "select" ||
|
|
element.localName == "input" && (element.type == "text" ||
|
|
element.type == "password")) {
|
|
noFocusOnMouse = false;
|
|
}
|
|
}
|
|
else if (element.localName == "listbox") {
|
|
noFocusOnMouse = false;
|
|
}
|
|
}
|
|
|
|
if (noFocusOnMouse) {
|
|
// no focus so the last focus method will be 0
|
|
gLastFocusMethod = 0;
|
|
expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
|
|
expectedWindow, null, true, testid);
|
|
gLastFocusMethod = fm.FLAG_BYMOUSE;
|
|
}
|
|
else {
|
|
expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
|
|
element.ownerDocument.defaultView,
|
|
expectedElement, focusChanged, testid);
|
|
}
|
|
}
|
|
|
|
function done()
|
|
{
|
|
var opener = window.opener;
|
|
window.close();
|
|
opener.wrappedJSObject.SimpleTest.finish();
|
|
}
|
|
|
|
var pressTab = function () synthesizeKey("VK_TAB", { });
|
|
|
|
function setFocusTo(id, fwindow)
|
|
{
|
|
gLastFocus = getById(id);
|
|
gLastFocusWindow = fwindow;
|
|
if (gLastFocus)
|
|
gLastFocus.focus();
|
|
else
|
|
fm.clearFocus(fwindow);
|
|
gEvents = "";
|
|
}
|
|
|
|
function getById(id)
|
|
{
|
|
if (gNewExpectedWindow)
|
|
return gNewExpectedWindow.document.getElementById(id);
|
|
var element = $(id);
|
|
if (!element)
|
|
element = $("childframe").contentDocument.getElementById(id);
|
|
return element;
|
|
}
|
|
|
|
function startTest()
|
|
{
|
|
if (gTestStarted)
|
|
return;
|
|
gTestStarted = true;
|
|
|
|
gChildWindow = $("childframe").contentWindow;
|
|
gShowOutput = true;
|
|
|
|
// synthesize a mousemove over the image to ensure that the imagemap data is
|
|
// created. Otherwise, the special imagemap frames might not exist, and
|
|
// won't be focusable.
|
|
synthesizeMouse(getById("image"), 4, 4, { type: "mousemove" }, gChildWindow);
|
|
|
|
initEvents(window);
|
|
|
|
is(fm.activeWindow, window, "activeWindow");
|
|
is(gChildWindow.document.hasFocus(), false, " child document hasFocus");
|
|
|
|
// test to see if the Mac Full Keyboard Access setting is set. If t3 is
|
|
// focused after tab is pressed, then it is set to textboxes and lists only.
|
|
// Otherwise, all elements are in the tab order.
|
|
pressTab();
|
|
|
|
if (fm.focusedElement.id == "t3")
|
|
gPartialTabbing = true;
|
|
else
|
|
is(fm.focusedElement.id, "t1", "initial tab key");
|
|
|
|
is(fm.getLastFocusMethod(null), fm.FLAG_BYKEY, "last focus method null start");
|
|
is(fm.getLastFocusMethod(window), fm.FLAG_BYKEY, "last focus method window start");
|
|
|
|
fm.clearFocus(window);
|
|
gEvents = "";
|
|
|
|
gLastFocusMethod = fm.FLAG_BYKEY;
|
|
if (gPartialTabbing) {
|
|
var partialTabList = ["t3", "t5", "t9", "t10", "t11", "t12", "t13", "t14", "t15",
|
|
"t16", "t19", "t20", "t21", "t22", "t26", "t27", "t28", "t29", "t30"];
|
|
for (var idx = 0; idx < partialTabList.length; idx++) {
|
|
expectFocusShift(pressTab, null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
|
|
}
|
|
setFocusTo("last", window);
|
|
expectFocusShift(pressTab, null, getById(partialTabList[0]), true, "partial tab key wrap to start");
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
null, getById("last"), true, "partial shift tab key wrap to end");
|
|
for (var idx = partialTabList.length - 1; idx >= 0; idx--) {
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
|
|
}
|
|
}
|
|
else {
|
|
// TAB key
|
|
for (var idx = 1; idx <= kTabbableSteps; idx++) {
|
|
expectFocusShift(pressTab, null, getById("t" + idx), true, "tab key t" + idx);
|
|
}
|
|
|
|
// wrapping around at end with TAB key
|
|
setFocusTo("last", window);
|
|
expectFocusShift(pressTab, null, getById("t1"), true, "tab key wrap to start");
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
null, getById("last"), true, "shift tab key wrap to end");
|
|
|
|
// Shift+TAB key
|
|
setFocusTo("o5", window);
|
|
for (idx = kTabbableSteps; idx > 0; idx--) {
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
null, getById("t" + idx), true, "shift tab key t" + idx);
|
|
}
|
|
}
|
|
|
|
var t19 = getById("t19");
|
|
is(t19.selectionStart, 0, "input focused from tab key selectionStart");
|
|
is(t19.selectionEnd, 5, "input focused from tab key selectionEnd");
|
|
t19.setSelectionRange(0, 0);
|
|
|
|
gLastFocusMethod = 0;
|
|
var selectFired = false;
|
|
function selectListener() { selectFired = true; }
|
|
t19.addEventListener("select", selectListener, false);
|
|
expectFocusShift(function() t19.select(),
|
|
null, getById("t" + 19), true, "input.select()");
|
|
t19.removeEventListener("select", selectListener, false);
|
|
ok(selectFired, "select event fires for input");
|
|
|
|
// mouse clicking
|
|
gLastFocusMethod = fm.FLAG_BYMOUSE;
|
|
for (idx = kTabbableSteps; idx >= 1; idx--) {
|
|
// skip the document root and the overflow element
|
|
if (idx == kChildDocumentRootIndex || idx == kOverflowElementIndex)
|
|
continue;
|
|
if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
|
|
continue;
|
|
|
|
var element = getById("t" + idx);
|
|
// skip area elements, as getBoundingClientRect doesn't return their actual coordinates
|
|
if (element.localName == "area")
|
|
continue;
|
|
|
|
mouseOnElement(element, getById("t" + idx), true, "mouse on element t" + idx);
|
|
var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window;
|
|
if (element.localName == "listbox" && expectedWindow == window &&
|
|
navigator.platform.indexOf("Mac") == 0) {
|
|
// after focusing a listbox on Mac, clear the focus before continuing.
|
|
setFocusTo(null, window);
|
|
}
|
|
}
|
|
|
|
is(t19.selectionStart, 0, "input focused from mouse selectionStart");
|
|
is(t19.selectionEnd, 0, "input focused from mouse selectionEnd");
|
|
|
|
// mouse clicking on elements that are not tabbable
|
|
for (idx = 1; idx <= kFocusSteps; idx++) {
|
|
var element = getById("o" + (idx % 2 ? idx : idx - 1));
|
|
|
|
mouseOnElement(element, element, idx % 2,
|
|
"mouse on non-tabbable element o" + idx);
|
|
}
|
|
|
|
// mouse clicking on elements that are not tabbable and have user-focus: none
|
|
// or are not focusable for other reasons (for instance, being disabled)
|
|
// These elements will clear the focus when clicked.
|
|
for (idx = 1; idx <= kNoFocusSteps; idx++) {
|
|
var element = getById("n" + idx);
|
|
gLastFocusMethod = idx % 2 ? 0 : fm.FLAG_BYMOUSE;
|
|
|
|
mouseOnElement(element, idx % 2 ? null: element, true, "mouse on unfocusable element n" + idx);
|
|
}
|
|
|
|
if (idx == kOverflowElementIndex) {
|
|
gLastFocusMethod = fm.FLAG_BYMOUSE;
|
|
var element = getById("t" + idx);
|
|
expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
|
|
window, null, true, "mouse on scrollable element");
|
|
}
|
|
|
|
// focus() method
|
|
gLastFocusMethod = 0;
|
|
for (idx = kTabbableSteps; idx >= 1; idx--) {
|
|
if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
|
|
continue;
|
|
expectFocusShift(function () getById("t" + idx).focus(),
|
|
null, getById("t" + idx), true, "focus method on element t" + idx);
|
|
}
|
|
|
|
$("t1").focus();
|
|
ok(gEvents === "", "focusing element that is already focused");
|
|
|
|
$("t2").blur();
|
|
ok(gEvents === "", "blurring element that is not focused");
|
|
|
|
// focus() method on elements that are not tabbable
|
|
for (idx = 1; idx <= kFocusSteps; idx++) {
|
|
var expected = getById("o" + (idx % 2 ? idx : idx - 1));
|
|
expectFocusShift(function () getById("o" + idx).focus(),
|
|
expected.ownerDocument.defaultView,
|
|
expected, idx % 2, "focus method on non-tabbable element o" + idx);
|
|
}
|
|
|
|
// focus() method on elements that are not tabbable and have user-focus: none
|
|
// or are not focusable for other reasons (for instance, being disabled)
|
|
for (idx = 1; idx <= kNoFocusSteps; idx++) {
|
|
var expected = getById("o" + (idx % 2 ? idx : idx - 1));
|
|
expectFocusShift(function () getById("o" + idx).focus(),
|
|
expected.ownerDocument.defaultView,
|
|
expected, idx % 2, "focus method on unfocusable element n" + idx);
|
|
}
|
|
|
|
// the focus() method on the legend element should focus the legend if it is
|
|
// focusable, or the first element after the legend if it is not focusable.
|
|
if (!gPartialTabbing) {
|
|
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
|
var legend = getById("legend");
|
|
expectFocusShift(function () legend.focus(),
|
|
null, getById("t28"), true, "focus method on unfocusable legend");
|
|
gLastFocusMethod = 0;
|
|
legend.tabIndex = "0";
|
|
expectFocusShift(function () legend.focus(),
|
|
null, getById("legend"), true, "focus method on focusable legend");
|
|
legend.tabIndex = "-1";
|
|
}
|
|
|
|
var accessKeyDetails = (navigator.platform.indexOf("Mac") >= 0) ?
|
|
{ ctrlKey : true } : { altKey : true };
|
|
|
|
// test accesskeys
|
|
var keys = ["t26", "t19", "t22", "t29", "t15", "t17", "n14",
|
|
"t4", "o1", "o9", "n6"];
|
|
for (var k = 0; k < keys.length; k++) {
|
|
var key = String.fromCharCode(65 + k);
|
|
|
|
// accesskeys D and G are for labels so get redirected
|
|
gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY;
|
|
|
|
// on Windows and Linux, the shift key must be pressed for content area access keys
|
|
if (navigator.platform.indexOf("Mac") == -1)
|
|
accessKeyDetails.shiftKey = (getById(keys[k]).ownerDocument.defaultView == gChildWindow);
|
|
|
|
expectFocusShift(function () synthesizeKey(key, accessKeyDetails),
|
|
null, getById(keys[k]), true, "accesskey " + key);
|
|
}
|
|
|
|
// clicking on the labels
|
|
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
|
expectFocusShift(function () synthesizeMouse(getById("ad"), 2, 2, { }, gChildWindow),
|
|
null, getById("t29"), true, "mouse on html label with content inside");
|
|
expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
|
|
null, getById("n14"), true, "mouse on html label with for attribute");
|
|
gLastFocusMethod = 0;
|
|
expectFocusShift(function () synthesizeMouse(getById("aj"), 2, 2, { }),
|
|
null, getById("o9"), true, "mouse on xul label with content inside");
|
|
expectFocusShift(function () synthesizeMouse(getById("ak"), 2, 2, { }),
|
|
null, getById("n6"), true, "mouse on xul label with control attribute");
|
|
|
|
// test accesskeys that shouldn't work
|
|
k = "o".charCodeAt(0);
|
|
while (k++ < "v".charCodeAt(0)) {
|
|
var key = String.fromCharCode(k);
|
|
expectFocusShift(function () synthesizeKey(key, accessKeyDetails),
|
|
window, getById("n6"), false, "non accesskey " + key);
|
|
}
|
|
gLastFocusMethod = -1;
|
|
|
|
// should focus the for element when using the focus method on a label as well
|
|
expectFocusShift(function () getById("ad").focus(),
|
|
null, getById("t29"), true, "mouse on html label using focus method");
|
|
|
|
// make sure that the text is selected when clicking a label associated with an input
|
|
getById("ag").htmlFor = "t19";
|
|
expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
|
|
null, getById("t19"), true, "mouse on html label with for attribute changed");
|
|
is(t19.selectionStart, 0, "input focused from label, selectionStart");
|
|
is(t19.selectionEnd, 5, "input focused from label, selectionEnd");
|
|
|
|
// switch to another panel in a tabbox and ensure that tabbing moves between
|
|
// elements on the new panel.
|
|
$("tabbox").selectedIndex = 1;
|
|
expectFocusShift(function () getById("t" + kBeforeTabboxIndex).focus(),
|
|
null, getById("t" + kBeforeTabboxIndex), true, "focus method on element before tabbox");
|
|
|
|
if (!gPartialTabbing) {
|
|
expectFocusShift(pressTab, null, getById("tab2"), true, "focus method on tab");
|
|
expectFocusShift(pressTab, null, getById("htab1"), true, "tab key switch tabpanel 1");
|
|
expectFocusShift(pressTab, null, getById("htab2"), true, "tab key switch tabpanel 2");
|
|
expectFocusShift(pressTab, null, getById("t" + (kBeforeTabboxIndex + 4)), true, "tab key switch tabpanel 3");
|
|
}
|
|
$("tabbox").selectedIndex = 0;
|
|
|
|
// ---- the following checks when the focus changes during a blur or focus event ----
|
|
|
|
var o5 = $("o5");
|
|
var o9 = $("o9");
|
|
var t3 = $("t3");
|
|
var t17 = getById("t17");
|
|
var t19 = getById("t19");
|
|
var shiftFocusParentDocument = function() o9.focus();
|
|
var shiftFocusChildDocument = function() t17.focus();
|
|
|
|
var trapBlur = function (element, eventListener, blurFunction)
|
|
{
|
|
element.focus();
|
|
gEvents = "";
|
|
element.addEventListener("blur", eventListener, false);
|
|
blurFunction();
|
|
element.removeEventListener("blur", eventListener, false);
|
|
}
|
|
|
|
var functions = [
|
|
function(element) element.focus(),
|
|
function(element) synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView)
|
|
];
|
|
|
|
// first, check cases where the focus is adjusted during the blur event. Iterate twice,
|
|
// once with the focus method and then focusing by mouse clicking
|
|
for (var l = 0; l < 2; l++) {
|
|
var adjustFocus = functions[l];
|
|
var mod = (l == 1) ? " with mouse" : "";
|
|
|
|
// an attempt is made to switch the focus from one element (o5) to another
|
|
// element (t3) within the same document, yet the focus is shifted to a
|
|
// third element (o9) in the same document during the blur event for the
|
|
// first element.
|
|
trapBlur(o5, shiftFocusParentDocument, function () adjustFocus(t3));
|
|
compareEvents("commandupdate: cu blur: o5 commandupdate: cu focus: o9",
|
|
window, o9, "change focus to sibling during element blur, attempted sibling" + mod);
|
|
|
|
// similar, but the third element (t17) is in a child document
|
|
trapBlur(o9, shiftFocusChildDocument, function () adjustFocus(t3));
|
|
compareEvents("commandupdate: cu blur: o9 blur: outer-document blur: outer-window " +
|
|
"focus: child-document focus: child-window commandupdate: cu focus: t17",
|
|
gChildWindow, t17, "change focus to child document during element blur, attempted sibling" + mod);
|
|
|
|
// similar, but an attempt to switch focus within the same document, but the
|
|
// third element (t17) is in a parent document
|
|
trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t19));
|
|
compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
|
|
"focus: outer-document focus: outer-window commandupdate: cu focus: o9",
|
|
window, o9, "change focus to parent document during element blur, attempted sibling" + mod);
|
|
|
|
// similar, but blur is called instead of switching focus
|
|
trapBlur(t3, shiftFocusParentDocument, function () t3.blur());
|
|
compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9",
|
|
window, o9, "change focus to same document during clear focus" + mod);
|
|
|
|
// check when an element in the same document is focused during the
|
|
// element's blur event, but an attempt was made to focus an element in the
|
|
// child document. In this case, the focus in the parent document should be
|
|
// what was set during the blur event, but the actual focus should still
|
|
// move to the child document.
|
|
trapBlur(t3, shiftFocusParentDocument, function () adjustFocus(t17));
|
|
compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9 " +
|
|
"blur: outer-document blur: outer-window " +
|
|
"focus: child-document focus: child-window commandupdate: cu focus: t17",
|
|
gChildWindow, t17, "change focus to sibling during element blur, attempted child" + mod);
|
|
is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
|
|
"change focus to sibling during element blur, attempted child, focused in parent" + mod);
|
|
|
|
// similar, but with a parent
|
|
trapBlur(t19, shiftFocusChildDocument, function () adjustFocus(t3));
|
|
compareEvents("commandupdate: cu blur: t19 commandupdate: cu focus: t17 " +
|
|
"blur: child-document blur: child-window " +
|
|
"focus: outer-document focus: outer-window commandupdate: cu focus: t3",
|
|
window, t3, "change focus to sibling during element blur, attempted parent" + mod);
|
|
is(fm.getFocusedElementForWindow(gChildWindow, false, {}), t17,
|
|
"change focus to sibling during element blur, attempted child, focused in child" + mod);
|
|
|
|
// similar, with a child, but the blur event focuses a child element also
|
|
trapBlur(t3, shiftFocusChildDocument, function () adjustFocus(t19));
|
|
compareEvents("commandupdate: cu blur: t3 blur: outer-document blur: outer-window " +
|
|
"focus: child-document focus: child-window commandupdate: cu focus: t17",
|
|
gChildWindow, t17, "change focus to child during element blur, attempted child" + mod);
|
|
|
|
// similar, with a parent, where the blur event focuses a parent element also
|
|
trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t3));
|
|
compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
|
|
"focus: outer-document focus: outer-window commandupdate: cu focus: o9",
|
|
window, o9, "change focus to parent during element blur, attempted parent" + mod);
|
|
}
|
|
|
|
var trapFocus = function (element, eventListener)
|
|
{
|
|
element.addEventListener("focus", eventListener, false);
|
|
element.focus();
|
|
element.removeEventListener("focus", eventListener, false);
|
|
}
|
|
|
|
fm.clearFocus(window);
|
|
gEvents = "";
|
|
|
|
// next, check cases where the focus is adjusted during the focus event
|
|
|
|
// switch focus to an element in the same document
|
|
trapFocus(o5, shiftFocusParentDocument);
|
|
compareEvents("commandupdate: cu focus: o5 commandupdate: cu blur: o5 commandupdate: cu focus: o9",
|
|
window, o9, "change focus to sibling during element focus");
|
|
|
|
// similar, but the new element (t17) is in a child document
|
|
trapFocus(o5, shiftFocusChildDocument);
|
|
compareEvents("commandupdate: cu blur: o9 " +
|
|
"commandupdate: cu focus: o5 commandupdate: cu blur: o5 " +
|
|
"blur: outer-document blur: outer-window " +
|
|
"focus: child-document focus: child-window commandupdate: cu focus: t17",
|
|
gChildWindow, t17, "change focus to child document during element focus");
|
|
|
|
// similar, but the new element (o9) is in a parent document.
|
|
trapFocus(t19, shiftFocusParentDocument);
|
|
compareEvents("commandupdate: cu blur: t17 " +
|
|
"commandupdate: cu focus: t19 commandupdate: cu blur: t19 " +
|
|
"blur: child-document blur: child-window " +
|
|
"focus: outer-document focus: outer-window commandupdate: cu focus: o9",
|
|
window, o9, "change focus to parent document during element focus");
|
|
|
|
// clear the focus during the focus event
|
|
trapFocus(t3, function () fm.clearFocus(window));
|
|
compareEvents("commandupdate: cu blur: o9 commandupdate: cu focus: t3 commandupdate: cu blur: t3",
|
|
window, null, "clear focus during focus event");
|
|
|
|
if (!gPartialTabbing)
|
|
doCommandDispatcherTests();
|
|
|
|
testMoveFocus();
|
|
|
|
doRemoveTests();
|
|
|
|
// tests various focus manager apis for null checks
|
|
var exh = false;
|
|
try {
|
|
fm.clearFocus(null);
|
|
}
|
|
catch (ex) { exh = true; }
|
|
is(exh, true, "clearFocus with null window causes exception");
|
|
|
|
var exh = false;
|
|
try {
|
|
fm.getFocusedElementForWindow(null, false, focusedWindow);
|
|
}
|
|
catch (ex) { exh = true; }
|
|
is(exh, true, "getFocusedElementForWindow with null window causes exception");
|
|
|
|
// just make sure that this doesn't crash
|
|
fm.moveCaretToFocus(null);
|
|
|
|
// ---- tests for the FLAG_NOSWITCHFRAME flag
|
|
getById("o5").focus();
|
|
gLastFocusMethod = 0;
|
|
gEvents = "";
|
|
// focus is being shifted in a child, so the focus should not change
|
|
expectFocusShift(function () fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME),
|
|
window, getById("o5"), false, "no switch frame focus to child");
|
|
setFocusTo("t20", gChildWindow);
|
|
|
|
// here, however, focus is being shifted in a parent, which will have to blur
|
|
// the child, so the focus will always change
|
|
expectFocusShift(function () fm.setFocus(getById("o5"), fm.FLAG_NOSWITCHFRAME),
|
|
window, getById("o5"), true, "no switch frame focus to parent");
|
|
|
|
expectFocusShift(function () fm.setFocus(getById("t1"), fm.FLAG_NOSWITCHFRAME),
|
|
window, getById("t1"), true, "no switch frame focus to same window");
|
|
|
|
// ---- tests for focus and scrolling into view ----
|
|
var inscroll = getById("inscroll");
|
|
inscroll.tabIndex = 0;
|
|
is(inscroll.parentNode.scrollTop, 0, "scroll position before focus");
|
|
inscroll.focus();
|
|
ok(inscroll.parentNode.scrollTop > 5, "scroll position after focus");
|
|
inscroll.parentNode.scrollTop = 0;
|
|
fm.setFocus(inscroll, fm.FLAG_NOSCROLL);
|
|
is(inscroll.parentNode.scrollTop, 0, "scroll position after noscroll focus");
|
|
|
|
getById("t9").focus();
|
|
getById("inpopup1").focus();
|
|
is(fm.focusedElement, getById("t9"), "focus in closed popup");
|
|
|
|
// ---- tests to check if tabbing out of a textbox works
|
|
|
|
setFocusTo("t1", window);
|
|
|
|
var textbox1 = document.createElement("textbox");
|
|
$("innerbox").appendChild(textbox1);
|
|
|
|
var textbox2 = document.createElement("textbox");
|
|
$("innerbox").appendChild(textbox2);
|
|
|
|
gLastFocusMethod = 0;
|
|
expectFocusShift(function () textbox2.focus(),
|
|
null, textbox2.inputField, true, "focus on textbox");
|
|
gLastFocusMethod = fm.FLAG_BYKEY;
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
null, textbox1.inputField, true, "shift+tab on textbox");
|
|
|
|
textbox1.tabIndex = 2;
|
|
textbox2.tabIndex = 2;
|
|
gLastFocusMethod = 0;
|
|
expectFocusShift(function () textbox2.focus(),
|
|
null, textbox2.inputField, true, "focus on textbox with tabindex set");
|
|
gLastFocusMethod = fm.FLAG_BYKEY;
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
null, textbox1.inputField, true, "shift+tab on textbox with tabindex set");
|
|
|
|
// ---- test for bug 618907 which ensures that canceling the mousedown event still focuses the
|
|
// right frame
|
|
|
|
var childContentFrame = document.getElementById("ifa")
|
|
childContentFrame.style.MozUserFocus = "";
|
|
|
|
var frab = childContentFrame.contentDocument.getElementById("fra-b");
|
|
var mouseDownListener = function(event) event.preventDefault();
|
|
frab.addEventListener("mousedown", mouseDownListener, false);
|
|
|
|
var childElementToFocus = childContentFrame.contentDocument.getElementById("fra");
|
|
gLastFocus = childElementToFocus;
|
|
gLastFocusWindow = childContentFrame.contentWindow;
|
|
gLastFocus.focus();
|
|
gEvents = "";
|
|
|
|
setFocusTo("t1", window);
|
|
|
|
gLastFocusMethod = -1;
|
|
expectFocusShift(function () synthesizeMouse(frab, 5, 5, { }, childContentFrame.contentWindow),
|
|
null, childElementToFocus, true,
|
|
"mousedown event canceled - chrome to content");
|
|
|
|
frab.removeEventListener("mousedown", mouseDownListener, false);
|
|
|
|
var t5 = getById("t5");
|
|
t5.addEventListener("mousedown", mouseDownListener, false);
|
|
synthesizeMouse(t5, 10, 10, { })
|
|
t5.removeEventListener("mousedown", mouseDownListener, false);
|
|
is(fm.focusedElement, childElementToFocus,
|
|
"mousedown event cancelled - content to chrome - element");
|
|
is(fm.focusedWindow, childContentFrame.contentWindow, "mousedown event cancelled - content to chrome - window");
|
|
|
|
// ---- test to check that refocusing an element during a blur event doesn't succeed
|
|
|
|
var t1 = getById("t1");
|
|
t1.addEventListener("blur", function() t1.focus(), true);
|
|
t1.focus();
|
|
var t3 = getById("t3");
|
|
synthesizeMouse(t3, 2, 2, { });
|
|
is(fm.focusedElement, t3, "focus during blur");
|
|
|
|
setFocusTo("t9", window);
|
|
gLastFocusMethod = -1;
|
|
window.openDialog("focus_window2.xul", "_blank", "chrome", otherWindowFocused);
|
|
}
|
|
|
|
function doCommandDispatcherTests()
|
|
{
|
|
var t19 = getById("t19");
|
|
t19.focus();
|
|
gLastFocusWindow = gChildWindow;
|
|
gLastFocus = t19;
|
|
gEvents = "";
|
|
|
|
expectFocusShift(function () document.commandDispatcher.focusedElement = getById("o9"),
|
|
null, getById("o9"), true, "command dispatcher set focusedElement");
|
|
expectFocusShift(function () document.commandDispatcher.advanceFocus(),
|
|
null, getById("o13"), true, "command dispatcher advanceFocus");
|
|
expectFocusShift(function () document.commandDispatcher.rewindFocus(),
|
|
null, getById("o9"), true, "command dispatcher rewindFocus");
|
|
expectFocusShift(function () document.commandDispatcher.focusedElement = null,
|
|
null, null, true, "command dispatcher set focusedElement to null");
|
|
expectFocusShift(function () document.commandDispatcher.focusedWindow = gChildWindow,
|
|
null, getById("t19"), true, "command dispatcher set focusedElement to null");
|
|
expectFocusShift(function () document.commandDispatcher.focusedElement = null,
|
|
gChildWindow, null, true, "command dispatcher set focusedElement to null in child");
|
|
expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("t19")),
|
|
null, getById("t20"), true, "command dispatcher advanceFocusIntoSubtree child");
|
|
expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(null),
|
|
null, getById("t21"), true, "command dispatcher advanceFocusIntoSubtree null child");
|
|
expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("o9").parentNode),
|
|
null, getById("o9"), true, "command dispatcher advanceFocusIntoSubtree parent");
|
|
}
|
|
|
|
function doRemoveTests()
|
|
{
|
|
// next, some tests which remove elements
|
|
var t19 = getById("t19");
|
|
t19.focus();
|
|
t19.parentNode.removeChild(t19);
|
|
|
|
is(fm.focusedElement, null, "removed element focusedElement");
|
|
is(fm.focusedWindow, gChildWindow, "removed element focusedWindow");
|
|
is(gChildWindow.document.hasFocus(), true, "removed element hasFocus");
|
|
is(gChildWindow.document.activeElement, getById("inner-document"), "removed element activeElement");
|
|
|
|
getById("t15").focus();
|
|
var abs = getById("abs");
|
|
abs.parentNode.removeChild(abs);
|
|
|
|
is(fm.focusedElement, null, "removed ancestor focusedElement");
|
|
is(fm.focusedWindow, gChildWindow, "removed ancestor focusedWindow");
|
|
is(gChildWindow.document.hasFocus(), true, "removed ancestor hasFocus");
|
|
is(gChildWindow.document.activeElement, getById("inner-document"), "removed ancestor activeElement");
|
|
}
|
|
|
|
// tests for the FocusManager moveFocus method
|
|
function testMoveFocus()
|
|
{
|
|
setFocusTo("t6", window);
|
|
|
|
// moving focus while an element is already focused
|
|
var newFocus;
|
|
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
|
var expectedFirst = getById(gPartialTabbing ? "t3" : "t1");
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
|
|
window, expectedFirst, true, "moveFocus to first null window null content");
|
|
is(newFocus, fm.focusedElement, "moveFocus to first null window null content return value");
|
|
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
|
|
window, getById("last"), true, "moveFocus to last null window null content");
|
|
is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value");
|
|
|
|
gLastFocusMethod = 0;
|
|
newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
|
|
is(newFocus, null, "moveFocus to root null window null content return value");
|
|
is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow");
|
|
is(fm.focusedElement, null, "moveFocus to root null window null content focusedElement");
|
|
|
|
// moving focus while no element is focused
|
|
fm.clearFocus(window);
|
|
gEvents = "";
|
|
gLastFocus = null;
|
|
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
|
|
window, expectedFirst, true, "moveFocus to first null window null content no focus");
|
|
is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value");
|
|
fm.clearFocus(window);
|
|
gEvents = "";
|
|
gLastFocus = null;
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
|
|
window, getById("last"), true, "moveFocus to last null window null content no focus");
|
|
is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value");
|
|
fm.clearFocus(window);
|
|
gEvents = "";
|
|
gLastFocusMethod = 0;
|
|
newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
|
|
is(newFocus, null, "moveFocus to root null window null content no focus return value");
|
|
is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow");
|
|
is(fm.focusedElement, null, "moveFocus to root null window null content no focus focusedElement");
|
|
|
|
// moving focus from a specified element
|
|
setFocusTo("t6", window);
|
|
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0),
|
|
window, getById("t3"), true, "moveFocus to first null window with content");
|
|
// XXXndeakin P3 this doesn't work
|
|
// expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_LAST, 0),
|
|
// window, getById("o3"), true, "moveFocus to last null window with content");
|
|
|
|
// move focus to first in child window
|
|
expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_FIRST, 0),
|
|
gChildWindow, getById("t" + (kChildDocumentRootIndex + 1)), true,
|
|
"moveFocus to first child window null content");
|
|
is(newFocus, getById("t" + (kChildDocumentRootIndex + 1)),
|
|
"moveFocus to first child window null content return value");
|
|
|
|
// move focus to last in child window
|
|
setFocusTo("t6", window);
|
|
var expectedLast = getById(gPartialTabbing ? "t30" : "t" + (kBeforeTabboxIndex - 1));
|
|
expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_LAST, 0),
|
|
gChildWindow, expectedLast, true,
|
|
"moveFocus to last child window null content");
|
|
is(newFocus, getById(expectedLast),
|
|
"moveFocus to last child window null content return value");
|
|
|
|
// move focus to root in child window
|
|
setFocusTo("t6", window);
|
|
var childroot = getById("t" + kChildDocumentRootIndex);
|
|
gLastFocusMethod = 0;
|
|
newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0),
|
|
is(newFocus, childroot, "moveFocus to root child window null content return value");
|
|
is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow");
|
|
is(fm.focusedElement, childroot, "moveFocus to root child window null content focusedElement");
|
|
|
|
// MOVEFOCUS_CARET tests
|
|
getById("t20").focus();
|
|
gEvents = "";
|
|
|
|
var selection = gChildWindow.getSelection();
|
|
selection.removeAllRanges();
|
|
|
|
newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
|
|
is(newFocus, null, "move caret when at document root");
|
|
is(fm.focusedElement, null, "move caret when at document root");
|
|
|
|
var node = getById("t16").firstChild;
|
|
var range = gChildWindow.document.createRange();
|
|
range.setStart(node, 3);
|
|
range.setEnd(node, 3);
|
|
selection.addRange(range);
|
|
|
|
newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
|
|
is(newFocus, null, "move caret to non-link return value");
|
|
is(fm.focusedElement, null, "move caret to non-link");
|
|
|
|
var t25 = getById("t25");
|
|
var node = t25.firstChild;
|
|
range.setStart(node, 1);
|
|
range.setEnd(node, 1);
|
|
newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
|
|
|
|
is(newFocus, t25, "move caret to link return value");
|
|
is(fm.focusedElement, t25, "move caret to link focusedElement");
|
|
|
|
// enable caret browsing temporarily to test caret movement
|
|
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
|
getService(Components.interfaces.nsIPrefBranch);
|
|
prefs.setBoolPref("accessibility.browsewithcaret", true);
|
|
|
|
synthesizeKey("VK_LEFT", { }, gChildWindow);
|
|
synthesizeKey("VK_LEFT", { }, gChildWindow);
|
|
is(fm.focusedElement, null, "move caret away from link");
|
|
|
|
synthesizeKey("VK_LEFT", { }, gChildWindow);
|
|
is(fm.focusedElement, getById("t24"), "move caret away onto link");
|
|
|
|
prefs.setBoolPref("accessibility.browsewithcaret", false);
|
|
|
|
// cases where focus in on a content node with no frame
|
|
|
|
if (!gPartialTabbing) {
|
|
getById("t24").blur();
|
|
gEvents = "";
|
|
gLastFocus = null;
|
|
gLastFocusWindow = gChildWindow;
|
|
gLastFocusMethod = fm.FLAG_BYKEY;
|
|
|
|
selection.selectAllChildren(getById("hiddenspan"));
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { }),
|
|
gChildWindow, getById("t26"), true, "tab with selection on hidden content");
|
|
|
|
setFocusTo($("o15"), window);
|
|
$("o15").hidden = true;
|
|
document.documentElement.getBoundingClientRect(); // flush after hiding
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { }),
|
|
window, $("o17"), true, "tab with focus on hidden content");
|
|
|
|
$("o17").hidden = true;
|
|
document.documentElement.getBoundingClientRect();
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
|
window, $("o13"), true, "shift+tab with focus on hidden content");
|
|
}
|
|
|
|
// cases with selection in an <input>
|
|
|
|
var t19 = getById("t19");
|
|
t19.setSelectionRange(0, 0);
|
|
setFocusTo("t18", gChildWindow);
|
|
|
|
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0),
|
|
gChildWindow, t19, true, "moveFocus to next textbox");
|
|
is(t19.selectionStart, 0, "input focused after moveFocus selectionStart");
|
|
is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd");
|
|
|
|
t19.setSelectionRange(0, 0);
|
|
setFocusTo("t18", gChildWindow);
|
|
gLastFocusMethod = fm.FLAG_BYKEY;
|
|
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY),
|
|
gChildWindow, t19, true, "moveFocus to next textbox by key");
|
|
is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart");
|
|
is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd");
|
|
}
|
|
|
|
function otherWindowFocused(otherWindow)
|
|
{
|
|
var expectedElement = getById("t9");
|
|
|
|
is(fm.activeWindow, otherWindow, "other activeWindow");
|
|
is(fm.focusedWindow, otherWindow, "other focusedWindow");
|
|
is(window.document.hasFocus(), false, "when lowered document hasFocus");
|
|
var focusedWindow = {};
|
|
is(fm.getFocusedElementForWindow(window, false, focusedWindow),
|
|
expectedElement, "when lowered getFocusedElementForWindow");
|
|
is(focusedWindow.value, window, "when lowered getFocusedElementForWindow frame");
|
|
is(document.activeElement.id, expectedElement.id, "when lowered activeElement");
|
|
is(window.document.commandDispatcher.focusedWindow, window, " commandDispatcher in other window focusedWindow");
|
|
is(window.document.commandDispatcher.focusedElement, expectedElement, " commandDispatcher in other window focusedElement");
|
|
|
|
compareEvents("deactivate: outer-document-window blur: t9 blur: outer-document blur: outer-window",
|
|
otherWindow, null, "other window opened");
|
|
|
|
otherWindow.document.getElementById("other").focus();
|
|
|
|
for (var idx = kTabbableSteps; idx >= 1; idx--) {
|
|
expectedElement = getById("t" + idx);
|
|
if (!expectedElement) // skip elements that were removed in doRemoveTests()
|
|
continue;
|
|
if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
|
|
continue;
|
|
|
|
expectedElement.focus();
|
|
|
|
is(fm.focusedElement.id, "other", "when lowered focusedElement t" + idx);
|
|
is(fm.focusedWindow, otherWindow, "when lowered focusedWindow t" + idx);
|
|
|
|
var checkWindow = expectedElement.ownerDocument.defaultView;
|
|
is(fm.getFocusedElementForWindow(checkWindow, false, {}).id, expectedElement.id,
|
|
"when lowered getFocusedElementForWindow t" + idx);
|
|
is(checkWindow.document.activeElement.id, expectedElement.id, "when lowered activeElement t" + idx);
|
|
if (checkWindow != window) {
|
|
is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
|
|
"when lowered parent getFocusedElementForWindow t" + idx);
|
|
is(document.activeElement.id, "childframe",
|
|
"when lowered parent activeElement t" + idx);
|
|
}
|
|
}
|
|
|
|
gEvents = gEvents.replace(/commandupdate: cu\s?/g, "");
|
|
is(gEvents, "", "when lowered no events fired");
|
|
|
|
var other = otherWindow.document.getElementById("other");
|
|
other.focus();
|
|
is(fm.focusedElement, other, "focus method in second window");
|
|
|
|
otherWindow.close();
|
|
|
|
// next, check modal dialogs
|
|
getById("n2").focus();
|
|
var nextWindow = window.openDialog("focus_window2.xul", "_blank", "chrome,modal", modalWindowOpened);
|
|
}
|
|
|
|
function modalWindowOpened(modalWindow)
|
|
{
|
|
var elem = modalWindow.document.getElementById("other");
|
|
if (gPartialTabbing)
|
|
elem.focus();
|
|
else
|
|
synthesizeKey("VK_TAB", { }, modalWindow);
|
|
is(fm.activeWindow, modalWindow, "modal activeWindow");
|
|
is(fm.focusedElement, elem, "modal focusedElement");
|
|
|
|
modalWindow.close();
|
|
SimpleTest.waitForFocus(modalWindowClosed);
|
|
}
|
|
|
|
function modalWindowClosed()
|
|
{
|
|
is(fm.activeWindow, window, "modal window closed activeWindow");
|
|
is(fm.focusedElement, getById("n2"), "modal window closed focusedElement");
|
|
|
|
window.open("focus_frameset.html", "_blank", "width=400,height=400,toolbar=no");
|
|
}
|
|
|
|
function framesetWindowLoaded(framesetWindow)
|
|
{
|
|
gLastFocus = null;
|
|
gLastFocusWindow = framesetWindow;
|
|
gEvents = "";
|
|
|
|
is(fm.activeWindow, getTopWindow(framesetWindow), "frameset window active");
|
|
gOldExpectedWindow = getTopWindow(framesetWindow);
|
|
|
|
gMoveToFocusFrame = true;
|
|
for (var idx = 1; idx <= 8; idx++) {
|
|
gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
|
|
if (idx % 2)
|
|
initEvents(gNewExpectedWindow);
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow),
|
|
gNewExpectedWindow, getById("f" + idx), true, "frameset tab key f" + idx);
|
|
gMoveToFocusFrame = false;
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
}
|
|
|
|
gNewExpectedWindow = framesetWindow.frames[0];
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow),
|
|
gNewExpectedWindow, getById("f1"), true, "frameset tab key wrap to start");
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[3];
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f8"), true, "frameset shift tab key wrap to end");
|
|
|
|
for (idx = 7; idx >= 1; idx--) {
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
|
|
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f" + idx), true, "frameset shift tab key f" + idx);
|
|
}
|
|
|
|
// document shifting
|
|
// XXXndeakin P3 ctrl+tab doesn't seem to be testable currently for some reason
|
|
gNewExpectedWindow = framesetWindow.frames[1];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f3"), true, "switch document forward with f6");
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[2];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { }, framesetWindow),
|
|
gNewExpectedWindow, getById("f5"), true, "switch document forward with ctrl+tab");
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[3];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f7"), true, "switch document forward with ctrl+f6");
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[0];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f1"), true, "switch document forward and wrap");
|
|
|
|
// going backwards by document and wrapping doesn't currently work, but didn't work
|
|
// before the focus reworking either
|
|
|
|
/*
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[3];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f7"), true, "switch document backward and wrap");
|
|
*/
|
|
|
|
fm.moveFocus(framesetWindow.frames[3], null, fm.MOVEFOCUS_ROOT, 0);
|
|
gEvents = "";
|
|
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[2];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f5"), true, "switch document backward with f6");
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[1];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f3"), true, "switch document backward with ctrl+tab");
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[0];
|
|
expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
|
|
gNewExpectedWindow, getById("f1"), true, "switch document backward with ctrl+f6");
|
|
|
|
// skip the window switching tests for now on Linux, as raising and lowering
|
|
// a window is asynchronous there
|
|
if (navigator.platform.indexOf("Linux") == -1) {
|
|
window.openDialog("focus_window2.xul", "_blank", "chrome", switchWindowTest, framesetWindow);
|
|
}
|
|
else {
|
|
gOldExpectedWindow = null;
|
|
gNewExpectedWindow = null;
|
|
framesetWindow.close();
|
|
SimpleTest.waitForFocus(doWindowNoRootTest);
|
|
}
|
|
}
|
|
|
|
// test switching between two windows
|
|
function switchWindowTest(otherWindow, framesetWindow)
|
|
{
|
|
initEvents(otherWindow);
|
|
var otherElement = otherWindow.document.getElementById("other");
|
|
otherElement.focus();
|
|
|
|
framesetWindow.frames[1].document.getElementById("f4").focus();
|
|
|
|
is(fm.focusedElement, otherElement, "focus after inactive window focus");
|
|
|
|
gLastFocus = otherElement;
|
|
gLastFocusWindow = otherWindow;
|
|
gEvents = "";
|
|
gOldExpectedWindow = otherWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[1];
|
|
|
|
expectFocusShift(function () gNewExpectedWindow.focus(),
|
|
gNewExpectedWindow, getById("f4"), true, "switch to frame in another window");
|
|
is(fm.getFocusedElementForWindow(otherWindow, false, {}).id, "other", "inactive window has focused element");
|
|
|
|
gOldExpectedWindow = framesetWindow.frames[1];
|
|
gNewExpectedWindow = otherWindow;
|
|
expectFocusShift(function () otherWindow.focus(),
|
|
gNewExpectedWindow, getById("other"), true, "switch to another window");
|
|
|
|
var exh = false;
|
|
try {
|
|
fm.activeWindow = framesetWindow.frames[0];
|
|
}
|
|
catch (ex) { exh = true; }
|
|
is(exh, true, "activeWindow set to non top-level window");
|
|
|
|
exh = false;
|
|
try {
|
|
fm.activeWindow = null;
|
|
}
|
|
catch (ex) { exh = true; }
|
|
is(exh, true, "activeWindow set to null");
|
|
is(fm.activeWindow, otherWindow, "window not changed when activeWindow set to null");
|
|
|
|
var topWindow = getTopWindow(framesetWindow);
|
|
|
|
ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
|
|
"getControllerForCommand for focused window set");
|
|
ok(otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
|
|
"getControllerForCommand for non-focused window set");
|
|
ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy") !=
|
|
otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
|
|
"getControllerForCommand for two windows different");
|
|
ok(topWindow.document.commandDispatcher.getControllers() !=
|
|
otherWindow.document.commandDispatcher.getControllers(),
|
|
"getControllers for two windows different");
|
|
|
|
gOldExpectedWindow = otherWindow;
|
|
gNewExpectedWindow = framesetWindow.frames[1];
|
|
expectFocusShift(function () fm.activeWindow = topWindow,
|
|
gNewExpectedWindow, getById("f4"), true, "switch to frame activeWindow");
|
|
|
|
fm.clearFocus(otherWindow);
|
|
gOldExpectedWindow = gNewExpectedWindow;
|
|
gNewExpectedWindow = otherWindow;
|
|
expectFocusShift(function () fm.setFocus(otherElement, fm.FLAG_RAISE),
|
|
gNewExpectedWindow, getById("other"), true, "switch to window with raise");
|
|
|
|
getTopWindow(framesetWindow).document.commandDispatcher.focusedWindow = gOldExpectedWindow;
|
|
is(fm.activeWindow, gNewExpectedWindow, "setting commandDispatcher focusedWindow doesn't raise window");
|
|
|
|
fm.moveFocus(otherWindow, null, fm.MOVEFOCUS_FORWARD, 0);
|
|
var otherTextbox = otherWindow.document.getElementById("other-textbox");
|
|
otherTextbox.setSelectionRange(2, 3);
|
|
fm.activeWindow = topWindow;
|
|
fm.activeWindow = otherWindow;
|
|
is(otherTextbox.selectionStart, 2, "selectionStart after textbox focus and window raise");
|
|
is(otherTextbox.selectionEnd, 3, "selectionEnd after textbox focus and window raise");
|
|
is(fm.getLastFocusMethod(null), fm.FLAG_BYMOVEFOCUS, "last focus method after textbox focus and window raise");
|
|
|
|
fm.clearFocus(otherWindow);
|
|
|
|
// test to ensure that a synthetic event works
|
|
var synevent = document.createEvent("Event");
|
|
synevent.initEvent("focus", false, false);
|
|
otherTextbox.inputField.dispatchEvent(synevent);
|
|
is(synevent.type, "focus", "event.type after synthetic focus event");
|
|
is(synevent.target, otherTextbox, "event.target after synthetic focus event");
|
|
is(fm.focusedElement, null, "focusedElement after synthetic focus event");
|
|
is(otherWindow.document.activeElement, otherWindow.document.documentElement,
|
|
"document.activeElement after synthetic focus event");
|
|
|
|
// check accessing a focus event after the event has finishing firing
|
|
function continueTest(event) {
|
|
is(event.type, "focus", "event.type after accessing focus event in timeout");
|
|
is(event.target, otherTextbox, "event.target after accessing focus event in timeout");
|
|
|
|
gOldExpectedWindow = null;
|
|
gNewExpectedWindow = null;
|
|
otherWindow.close();
|
|
framesetWindow.close();
|
|
|
|
SimpleTest.waitForFocus(doWindowNoRootTest);
|
|
}
|
|
|
|
function textboxFocused(event) {
|
|
otherTextbox.removeEventListener("focus", textboxFocused, true);
|
|
setTimeout(continueTest, 0, event);
|
|
}
|
|
|
|
otherTextbox.addEventListener("focus", textboxFocused, true);
|
|
otherTextbox.focus();
|
|
}
|
|
|
|
// open a window with no root element
|
|
var noRootWindow = null;
|
|
function doWindowNoRootTest()
|
|
{
|
|
var data = "data:application/vnd.mozilla.xul+xml," + unescape(
|
|
"<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
|
|
" style='-moz-user-focus: normal;'>" +
|
|
"<script>function dostuff() { setTimeout(function() { " +
|
|
"document.documentElement.focus(); document.removeChild(document.documentElement);" +
|
|
"window.opener.focus(); }, 100); }</script></window>");
|
|
|
|
addEventListener("focus", doFrameSwitchingTests, true);
|
|
noRootWindow = window.open(data, "_blank", "chrome,width=100,height=100");
|
|
}
|
|
|
|
// these tests check when focus is moved between a tree of frames to ensure
|
|
// that the focus is in the right place at each event step.
|
|
function doFrameSwitchingTests()
|
|
{
|
|
removeEventListener("focus", doFrameSwitchingTests, true);
|
|
noRootWindow.close();
|
|
|
|
var framea = document.getElementById("ifa");
|
|
var frameb = document.getElementById("ifb");
|
|
framea.style.MozUserFocus = "";
|
|
frameb.style.MozUserFocus = "";
|
|
|
|
window.removeEventListener("focus", eventOccured, true);
|
|
window.removeEventListener("blur", eventOccured, true);
|
|
|
|
var inputa = framea.contentDocument.body.firstChild;
|
|
inputa.focus();
|
|
|
|
addFrameSwitchingListeners(framea);
|
|
addFrameSwitchingListeners(frameb);
|
|
var framec = framea.contentDocument.body.lastChild;
|
|
addFrameSwitchingListeners(framec);
|
|
|
|
var framed = framec.contentDocument.body.lastChild;
|
|
addFrameSwitchingListeners(framed);
|
|
|
|
var inputc = framec.contentDocument.body.firstChild;
|
|
|
|
var expectedMainWindowFocus = framea;
|
|
|
|
// An element in the immediate parent frame is focused. Focus an element in
|
|
// the child. The child should be focused and the parent's current focus should
|
|
// be the child iframe.
|
|
gEventMatched = true;
|
|
is(fm.getFocusedElementForWindow(window, false, {}), expectedMainWindowFocus,
|
|
"parent of framea has iframe focused");
|
|
gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
|
|
[framea.contentDocument, "blur", null, null, window, framea],
|
|
[framea.contentWindow, "blur", null, null, window, framea],
|
|
[framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
|
|
[framec.contentWindow, "focus", null, framec.contentWindow, window, framea],
|
|
[inputc, "focus", inputc, framec.contentWindow, window, framea]];
|
|
inputc.focus();
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from parent input to child input" + gExpectedEvents);
|
|
|
|
// An element in a child is focused. Focus an element in the immediate
|
|
// parent.
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputc, "blur", null, framec.contentWindow, window, framea],
|
|
[framec.contentDocument, "blur", null, null, window, framea],
|
|
[framec.contentWindow, "blur", null, null, window, framea],
|
|
[framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
|
|
[framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
|
|
[inputa, "focus", inputa, framea.contentWindow, window, framea]];
|
|
inputa.focus();
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to parent input");
|
|
|
|
// An element in a frame is focused. Focus an element in a sibling frame.
|
|
// The common ancestor of the two frames should have its focused node
|
|
// cleared after the element is blurred.
|
|
var inputb = frameb.contentDocument.body.firstChild;
|
|
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
|
|
[framea.contentDocument, "blur", null, null, window, null],
|
|
[framea.contentWindow, "blur", null, null, window, null],
|
|
[frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
|
|
[frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
|
|
[inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
|
|
inputb.focus();
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling frame");
|
|
is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), inputa,
|
|
"blurred frame still has input as focus");
|
|
|
|
// focus a descendant in a sibling
|
|
var inputd = framed.contentDocument.body.firstChild;
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
|
|
[frameb.contentDocument, "blur", null, null, window, null],
|
|
[frameb.contentWindow, "blur", null, null, window, null],
|
|
[framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
|
|
[framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
|
|
[inputd, "focus", inputd, framed.contentWindow, window, framea]];
|
|
inputd.focus();
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling descendant");
|
|
is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
|
|
"sibling parent focus has shifted to frame");
|
|
|
|
// focus an ancestor
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
|
|
[framed.contentDocument, "blur", null, null, window, framea],
|
|
[framed.contentWindow, "blur", null, null, window, framea],
|
|
[framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
|
|
[framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
|
|
[inputa, "focus", inputa, framea.contentWindow, window, framea]];
|
|
inputa.focus();
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor");
|
|
|
|
// focus a descendant
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
|
|
[framea.contentDocument, "blur", null, null, window, framea],
|
|
[framea.contentWindow, "blur", null, null, window, framea],
|
|
[framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
|
|
[framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
|
|
[inputd, "focus", inputd, framed.contentWindow, window, framea]];
|
|
inputd.focus();
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor");
|
|
is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
|
|
"parent focus has shifted to frame");
|
|
|
|
// focus a sibling frame by setting focusedWindow
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
|
|
[framed.contentDocument, "blur", null, null, window, null],
|
|
[framed.contentWindow, "blur", null, null, window, null],
|
|
[frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
|
|
[frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
|
|
[inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
|
|
fm.focusedWindow = frameb.contentWindow;
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow");
|
|
|
|
// clear the focus in an unfocused frame
|
|
gEventMatched = true;
|
|
gExpectedEvents = [];
|
|
fm.clearFocus(framec.contentWindow);
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused frame");
|
|
|
|
// focus a sibling frame by setting focusedWindow when no element is focused in that frame
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
|
|
[frameb.contentDocument, "blur", null, null, window, null],
|
|
[frameb.contentWindow, "blur", null, null, window, null],
|
|
[framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
|
|
[framec.contentWindow, "focus", null, framec.contentWindow, window, framea]];
|
|
fm.focusedWindow = framec.contentWindow;
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow with no element focused");
|
|
is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
|
|
"parent focus has shifted to frame using focusedWindow");
|
|
|
|
// focus the parent frame by setting focusedWindow. This should have no effect.
|
|
gEventMatched = true;
|
|
gExpectedEvents = [];
|
|
fm.focusedWindow = framea.contentWindow;
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "frame switch to parent using focusedWindow");
|
|
|
|
// clear the focus in the parent frame
|
|
gEventMatched = true;
|
|
gExpectedEvents = [[framec.contentDocument, "blur", null, null, window, framea],
|
|
[framec.contentWindow, "blur", null, null, window, framea],
|
|
[framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
|
|
[framea.contentWindow, "focus", null, framea.contentWindow, window, framea]];
|
|
fm.clearFocus(framea.contentWindow);
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in parent frame");
|
|
|
|
// clear the focus in an unfocused child frame
|
|
gEventMatched = true;
|
|
gExpectedEvents = [];
|
|
fm.clearFocus(framed.contentWindow);
|
|
ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused child frame");
|
|
|
|
var exh = false;
|
|
try {
|
|
fm.focusedWindow = null;
|
|
}
|
|
catch (ex) { exh = true; }
|
|
is(exh, true, "focusedWindow set to null");
|
|
is(fm.focusedWindow, framea.contentWindow, "window not changed when focusedWindow set to null");
|
|
|
|
doFrameHistoryTests()
|
|
}
|
|
|
|
function doFrameHistoryTests()
|
|
{
|
|
var t20 = getById("t20");
|
|
t20.focus();
|
|
|
|
addEventListener("message", function() { $("childframe").goBack(); }, true);
|
|
gChildWindow.addEventListener("focus",
|
|
function(event) {
|
|
if (event.target == t20) {
|
|
is(fm.focusedElement, t20, "focus restored after history back"); done();
|
|
}
|
|
}, true);
|
|
|
|
// make sure that loading a new page and then going back maintains the focus
|
|
gChildWindow.location = "data:text/html,<html><body onload='window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)." +
|
|
"getInterface(Components.interfaces.nsIWebNavigation)." +
|
|
"QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem." +
|
|
"QueryInterface(Components.interfaces.nsIInterfaceRequestor)." +
|
|
"getInterface(Components.interfaces.nsIDOMWindow).postMessage(\"content loaded\", \"*\");'>Next</body></html>";
|
|
}
|
|
|
|
function addFrameSwitchingListeners(frame)
|
|
{
|
|
frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false);
|
|
frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false);
|
|
frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false);
|
|
frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false);
|
|
|
|
var node = frame.contentDocument.body.firstChild;
|
|
node.addEventListener("focus", frameSwitchingEventOccured, false);
|
|
node.addEventListener("blur", frameSwitchingEventOccured, false);
|
|
}
|
|
|
|
function frameSwitchingEventOccured(event)
|
|
{
|
|
if (!gExpectedEvents.length) {
|
|
gEventMatched = false;
|
|
return;
|
|
}
|
|
|
|
try {
|
|
var events = gExpectedEvents.shift();
|
|
is(event.target, events[0], "event target");
|
|
is(event.type, events[1], "event type");
|
|
is(fm.focusedElement, events[2], "focused element");
|
|
is(fm.focusedWindow, events[3], "focused frame");
|
|
if (events[4])
|
|
is(fm.getFocusedElementForWindow(events[4], false, {}), events[5], "focused element in frame");
|
|
|
|
if (gEventMatched && event.target == events[0] && event.type == events[1] &&
|
|
fm.focusedElement == events[2] && fm.focusedWindow == events[3]) {
|
|
if (!events[4] || fm.getFocusedElementForWindow(events[4], false, {}) == events[5])
|
|
return;
|
|
}
|
|
} catch (ex) { ok(ex, "exception"); }
|
|
|
|
gEventMatched = false;
|
|
}
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
SimpleTest.waitForFocus(startTest);
|
|
|
|
]]>
|
|
</script>
|
|
|
|
<commandset id="cu"
|
|
commandupdater="true"
|
|
events="focus"
|
|
oncommandupdate="eventOccured(event)"/>
|
|
|
|
<!--
|
|
The elements with ids starting with t are focusable and in the taborder.
|
|
The elements with ids starting with o are:
|
|
odd numbered ids - focusable but not part of the tab order
|
|
even numbered ids - not focusable with -moz-user-focus: ignore
|
|
The elements with ids starting with n are:
|
|
odd numbered ids - not focusable with -moz-user-focus: none
|
|
even numbered ids - focusable but not part of the tab order
|
|
-->
|
|
<vbox id="buttonbox">
|
|
<hbox id="innerbox">
|
|
<button id="t4" accesskey="h" label="no tabindex"/>
|
|
<button id="o1" accesskey="i" label="tabindex = -1" tabindex="-1"/>
|
|
<listbox id="t5" label="tabindex = 0" tabindex="0" rows="1">
|
|
<listitem/>
|
|
</listbox>
|
|
<button id="t1" label="tabindex = 2" tabindex="2"/>
|
|
</hbox>
|
|
<hbox>
|
|
<button id="o2" accesskey="o" style="-moz-user-focus: ignore;" label="no tabindex"/>
|
|
<button id="o4" style="-moz-user-focus: ignore;" label="tabindex = -1" tabindex="-1"/>
|
|
<button id="t6" style="-moz-user-focus: ignore;" label="tabindex = 0" tabindex="0"/>
|
|
<button id="t2" style="-moz-user-focus: ignore;" label="tabindex = 2" tabindex="2"/>
|
|
</hbox>
|
|
<hbox id="specialroot">
|
|
<button id="t7" style="-moz-user-focus: normal;" label="no tabindex"/>
|
|
<button id="o3" style="-moz-user-focus: normal;" label="tabindex = -1" tabindex="-1"/>
|
|
<button id="t8" style="-moz-user-focus: normal;" label="tabindex = 0" tabindex="0"/>
|
|
<listbox id="t3" style="-moz-user-focus: normal;" label="tabindex = 2" tabindex="2" rows="1">
|
|
<listitem/>
|
|
</listbox>
|
|
</hbox>
|
|
<hbox>
|
|
<button accesskey="p" style="display: none;"/> <button accesskey="q" style="visibility: collapse;"/>
|
|
<button style="display: none;" tabindex="2"/> <button style="visibility: collapse;" tabindex="2"/>
|
|
</hbox>
|
|
<hbox>
|
|
<button id="n5" accesskey="s" label="no tabindex" disabled="true"/>
|
|
<button id="n7" label="tabindex = -1" tabindex="-1" disabled="true"/>
|
|
<button id="n9" label="tabindex = 0" tabindex="0" disabled="true"/>
|
|
<button id="n11" label="tabindex = 2" tabindex="2" disabled="true"/>
|
|
</hbox>
|
|
</vbox>
|
|
<vbox>
|
|
<hbox>
|
|
<dropmarker id="o6" value="no tabindex"/>
|
|
<dropmarker id="o8" value="tabindex = -1" tabindex="-1"/>
|
|
<dropmarker id="o10" value="tabindex = 0" tabindex="0"/>
|
|
<dropmarker id="o12" value="tabindex = 2" tabindex="2"/>
|
|
<dropmarker id="t9" accesskey="r" style="-moz-user-focus: normal;" value="no tabindex" />
|
|
<dropmarker id="t10" style="-moz-user-focus: normal;" value="tabindex = -1" tabindex="-1" />
|
|
<dropmarker id="t11" style="-moz-user-focus: normal;" value="tabindex = 0" tabindex="0" />
|
|
<dropmarker id="t12" style="-moz-user-focus: normal;" value="tabindex = 2" tabindex="2" />
|
|
<dropmarker id="o14" style="-moz-user-focus: ignore;" value="no tabindex"/>
|
|
<dropmarker id="o16" style="-moz-user-focus: ignore;" value="tabindex = -1" tabindex="-1"/>
|
|
<dropmarker id="n1" style="-moz-user-focus: none;" value="tabindex = 0" tabindex="0"/>
|
|
<dropmarker id="n3" style="-moz-user-focus: none;" value="tabindex = 2" tabindex="2"/>
|
|
</hbox>
|
|
</vbox>
|
|
<browser id="childframe" type="content" src="child_focus_frame.html" width="300" height="195"/>
|
|
<button id="t34"/>
|
|
<tabbox id="tabbox">
|
|
<tabs><tab id="t35" label="One"/><tab id="tab2" label="Two"/></tabs>
|
|
<tabpanels>
|
|
<tabpanel>
|
|
<checkbox id="t36"/>
|
|
<button id="t37"/>
|
|
</tabpanel>
|
|
<tabpanel>
|
|
<checkbox id="htab1"/>
|
|
<button id="nohtab2" tabindex="7"/>
|
|
<checkbox id="htab2" tabindex="0"/>
|
|
</tabpanel>
|
|
</tabpanels>
|
|
</tabbox>
|
|
<hbox>
|
|
<panel>
|
|
<button id="inpopup1" label="One"/>
|
|
<textbox label="Two"/>
|
|
</panel>
|
|
<description label="o" accesskey="v"/>
|
|
<button id="t38"/>
|
|
<!-- The 't' element tests end here so it doesn't matter that these elements are tabbable -->
|
|
<label id="aj" value="j" accesskey="j" control="o9"/>
|
|
<label id="ak" accesskey="k" control="n6">k</label>
|
|
<checkbox id="o5"/><checkbox id="o7"/><hbox><checkbox id="o9"/></hbox>
|
|
<checkbox id="o13"/><checkbox id="o15"/><checkbox id="o17"/>
|
|
<checkbox id="n2"/><checkbox id="n4"/><checkbox id="n6"/><checkbox id="n8"/><checkbox id="n10"/><checkbox id="n12"/>
|
|
<listbox id="last" width="20" rows="1"/>
|
|
|
|
<iframe id="ifa" width="40" height="60" style="-moz-user-focus: ignore;" type="content"
|
|
src="data:text/html,<input id=fra size='2'><input id='fra-b' size='2'>
|
|
<iframe src='data:text/html,<input id=frc><iframe src="data:text/html,<input id=frd>"></iframe>'></iframe>"/>
|
|
<iframe id="ifb" width="20" height="20" style="-moz-user-focus: ignore;"
|
|
src="data:text/html,<input id=frd></iframe>"/>
|
|
|
|
</hbox>
|
|
</window>
|