зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1124904 - cleanup keyboard navigation in the new search panel - simplify the 'selected' attribute handling, r=Mossop.
This commit is contained in:
Родитель
a98e61e293
Коммит
6c7c393499
|
@ -1137,6 +1137,7 @@
|
|||
"search-panel-one-offs")
|
||||
while (list.firstChild)
|
||||
list.firstChild.remove();
|
||||
textbox._selectedButton = null;
|
||||
|
||||
let hiddenList;
|
||||
try {
|
||||
|
|
|
@ -509,7 +509,7 @@
|
|||
let type = "unknown";
|
||||
if (aEvent instanceof KeyboardEvent) {
|
||||
type = "key";
|
||||
if (this._textbox.getSelectedOneOff()) {
|
||||
if (this._textbox.selectedButton) {
|
||||
source = "oneoff";
|
||||
}
|
||||
} else if (aEvent instanceof MouseEvent) {
|
||||
|
@ -989,7 +989,7 @@
|
|||
var evt = aEvent || this.mEnterEvent;
|
||||
|
||||
let engine;
|
||||
let oneOff = this.getSelectedOneOff();
|
||||
let oneOff = this.selectedButton;
|
||||
if (oneOff)
|
||||
engine = oneOff.engine;
|
||||
if (this.mEnterEvent && this._selectionDetails &&
|
||||
|
@ -1003,22 +1003,22 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="getSelectedOneOff">
|
||||
<body><![CDATA[
|
||||
let list = document.getAnonymousElementByAttribute(this.popup, "anonid",
|
||||
"search-panel-one-offs");
|
||||
if (!list)
|
||||
return null;
|
||||
<field name="_selectedButton"/>
|
||||
<property name="selectedButton" onget="return this._selectedButton;">
|
||||
<setter><![CDATA[
|
||||
if (this._selectedButton)
|
||||
this._selectedButton.removeAttribute("selected");
|
||||
|
||||
for (let button = list.firstChild; button; button = button.nextSibling) {
|
||||
if (button.hasAttribute("selected"))
|
||||
return button;
|
||||
// Avoid selecting dummy buttons.
|
||||
if (val && !val.classList.contains("dummy")) {
|
||||
val.setAttribute("selected", "true");
|
||||
this._selectedButton = val;
|
||||
return;
|
||||
}
|
||||
|
||||
return null;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
this._selectedButton = null;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="handleKeyboardNavigation">
|
||||
<parameter name="aEvent"/>
|
||||
|
@ -1054,7 +1054,7 @@
|
|||
#endif
|
||||
return;
|
||||
|
||||
let selectedButton = this.getSelectedOneOff();
|
||||
let selectedButton = this.selectedButton;
|
||||
|
||||
// Alt + up/down is very similar to (shift +) tab but differs in that
|
||||
// it loops through the list, whereas tab will move the focus out.
|
||||
|
@ -1064,29 +1064,23 @@
|
|||
let forward = aEvent.keyCode == KeyEvent.DOM_VK_DOWN;
|
||||
if (selectedButton) {
|
||||
// cycle though the list of one-off buttons.
|
||||
selectedButton.removeAttribute("selected");
|
||||
if (forward)
|
||||
selectedButton = selectedButton.nextSibling;
|
||||
this.selectedButton = selectedButton.nextSibling;
|
||||
else
|
||||
selectedButton = selectedButton.previousSibling;
|
||||
|
||||
// Avoid selecting dummy buttons.
|
||||
if (selectedButton && selectedButton.classList.contains("dummy"))
|
||||
selectedButton = null;
|
||||
this.selectedButton = selectedButton.previousSibling;
|
||||
}
|
||||
else {
|
||||
// If no selection, select the first or last one-off button.
|
||||
if (forward) {
|
||||
selectedButton = list.firstChild;
|
||||
this.selectedButton = list.firstChild;
|
||||
}
|
||||
else {
|
||||
selectedButton = list.lastChild;
|
||||
while (selectedButton.classList.contains("dummy"))
|
||||
selectedButton = selectedButton.previousSibling;
|
||||
this.selectedButton = selectedButton;
|
||||
}
|
||||
}
|
||||
if (selectedButton)
|
||||
selectedButton.setAttribute("selected", "true");
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
|
@ -1096,11 +1090,7 @@
|
|||
// If the last suggestion is selected, DOWN selects the first one-off.
|
||||
if (aEvent.keyCode == KeyEvent.DOM_VK_DOWN &&
|
||||
popup.selectedIndex + 1 == popup.view.rowCount) {
|
||||
if (selectedButton)
|
||||
selectedButton.removeAttribute("selected");
|
||||
selectedButton = list.firstChild;
|
||||
if (selectedButton)
|
||||
selectedButton.setAttribute("selected", "true");
|
||||
this.selectedButton = list.firstChild;
|
||||
}
|
||||
|
||||
// If no suggestion is selected and a one-off is selected,
|
||||
|
@ -1108,17 +1098,12 @@
|
|||
if (popup.selectedIndex == -1 && selectedButton &&
|
||||
(aEvent.keyCode == KeyEvent.DOM_VK_DOWN ||
|
||||
aEvent.keyCode == KeyEvent.DOM_VK_UP)) {
|
||||
selectedButton.removeAttribute("selected");
|
||||
if (aEvent.keyCode == KeyEvent.DOM_VK_DOWN)
|
||||
selectedButton = selectedButton.nextSibling;
|
||||
this.selectedButton = selectedButton.nextSibling;
|
||||
else
|
||||
selectedButton = selectedButton.previousSibling;
|
||||
if (selectedButton && selectedButton.classList.contains("dummy"))
|
||||
selectedButton = null;
|
||||
|
||||
if (selectedButton) {
|
||||
selectedButton.setAttribute("selected", "true");
|
||||
this.selectedButton = selectedButton.previousSibling;
|
||||
|
||||
if (this.selectedButton) {
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
}
|
||||
|
@ -1139,7 +1124,7 @@
|
|||
selectedButton = list.lastChild;
|
||||
while (selectedButton.classList.contains("dummy"))
|
||||
selectedButton = selectedButton.previousSibling;
|
||||
selectedButton.setAttribute("selected", "true");
|
||||
this.selectedButton = selectedButton;
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
|
@ -1148,18 +1133,13 @@
|
|||
if (aEvent.keyCode == KeyEvent.DOM_VK_TAB) {
|
||||
if (selectedButton) {
|
||||
// TAB cycles though the list of one-off buttons.
|
||||
selectedButton.removeAttribute("selected");
|
||||
if (aEvent.shiftKey)
|
||||
selectedButton = selectedButton.previousSibling;
|
||||
this.selectedButton = selectedButton.previousSibling;
|
||||
else
|
||||
selectedButton = selectedButton.nextSibling;
|
||||
|
||||
// Avoid selecting dummy buttons.
|
||||
if (selectedButton && selectedButton.classList.contains("dummy"))
|
||||
selectedButton = null;
|
||||
this.selectedButton = selectedButton.nextSibling;
|
||||
|
||||
// If we are out of the list, revert the text field to what the user typed.
|
||||
if (!selectedButton) {
|
||||
if (!this.selectedButton) {
|
||||
// Set the selectedIndex to something that will make
|
||||
// handleKeyNavigation (called by autocomplete.xml's onKeyPress
|
||||
// method) reset the text field value to what the user typed.
|
||||
|
@ -1173,9 +1153,8 @@
|
|||
return;
|
||||
|
||||
// and select the first one-off button for <tab>.
|
||||
selectedButton = list.firstChild;
|
||||
this.selectedButton = list.firstChild;
|
||||
}
|
||||
selectedButton.setAttribute("selected", "true");
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
|
|
|
@ -77,7 +77,7 @@ add_task(function* test_arrows() {
|
|||
let oneOffs = getOneOffs();
|
||||
ok(oneOffs.length >= 4, "we have at least 4 one-off buttons displayed")
|
||||
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
// The down arrow should first go through the suggestions.
|
||||
for (let i = 0; i < kValues.length; ++i) {
|
||||
|
@ -97,27 +97,27 @@ add_task(function* test_arrows() {
|
|||
|
||||
// now cycle through the one-off items, the first one is already selected.
|
||||
for (let i = 0; i < oneOffs.length; ++i) {
|
||||
is(textbox.getSelectedOneOff(), oneOffs[i],
|
||||
is(textbox.selectedButton, oneOffs[i],
|
||||
"the one-off button #" + (i + 1) + " should be selected");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
}
|
||||
|
||||
// We should now be back to the initial situation.
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
info("now test the up arrow key");
|
||||
// cycle through the one-off items, the first one is already selected.
|
||||
for (let i = oneOffs.length; i; --i) {
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[i - 1],
|
||||
is(textbox.selectedButton, oneOffs[i - 1],
|
||||
"the one-off button #" + i + " should be selected");
|
||||
}
|
||||
|
||||
// Another press on up should clear the one-off selection and select the
|
||||
// last suggestion.
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
for (let i = kValues.length - 1; i >= 0; --i) {
|
||||
is(searchPopup.selectedIndex, i,
|
||||
|
@ -137,13 +137,13 @@ add_task(function* test_tab() {
|
|||
"the search bar should be focused"); // from the previous test.
|
||||
|
||||
let oneOffs = getOneOffs();
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
// Pressing tab should select the first one-off without selecting suggestions.
|
||||
// now cycle through the one-off items, the first one is already selected.
|
||||
for (let i = 0; i < oneOffs.length; ++i) {
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[i],
|
||||
is(textbox.selectedButton, oneOffs[i],
|
||||
"the one-off button #" + (i + 1) + " should be selected");
|
||||
}
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
|
@ -168,14 +168,14 @@ add_task(function* test_shift_tab() {
|
|||
yield promise;
|
||||
|
||||
let oneOffs = getOneOffs();
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
// Press up once to select the last one-off button.
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
|
||||
// Pressing shift+tab should cycle through the one-off items.
|
||||
for (let i = oneOffs.length - 1; i >= 0; --i) {
|
||||
is(textbox.getSelectedOneOff(), oneOffs[i],
|
||||
is(textbox.selectedButton, oneOffs[i],
|
||||
"the one-off button #" + (i + 1) + " should be selected");
|
||||
if (i)
|
||||
EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
|
||||
|
@ -211,7 +211,7 @@ add_task(function* test_alt_down() {
|
|||
yield promise;
|
||||
|
||||
// ... and does nothing else.
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
is(textbox.value, kUserValue, "the textfield value should be unmodified");
|
||||
|
||||
|
@ -220,18 +220,18 @@ add_task(function* test_alt_down() {
|
|||
let oneOffs = getOneOffs();
|
||||
for (let i = 0; i < oneOffs.length; ++i) {
|
||||
EventUtils.synthesizeKey("VK_DOWN", {altKey: true});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[i],
|
||||
is(textbox.selectedButton, oneOffs[i],
|
||||
"the one-off button #" + (i + 1) + " should be selected");
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
}
|
||||
|
||||
// One more alt+down keypress and nothing should be selected.
|
||||
EventUtils.synthesizeKey("VK_DOWN", {altKey: true});
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
// another one and the first one-off should be selected.
|
||||
EventUtils.synthesizeKey("VK_DOWN", {altKey: true});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[0],
|
||||
is(textbox.selectedButton, oneOffs[0],
|
||||
"the first one-off button should be selected");
|
||||
});
|
||||
|
||||
|
@ -247,7 +247,7 @@ add_task(function* test_alt_up() {
|
|||
yield promise;
|
||||
|
||||
// ... and does nothing else.
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
is(textbox.value, kUserValue, "the textfield value should be unmodified");
|
||||
|
||||
|
@ -256,28 +256,28 @@ add_task(function* test_alt_up() {
|
|||
let oneOffs = getOneOffs();
|
||||
for (let i = oneOffs.length - 1; i >= 0; --i) {
|
||||
EventUtils.synthesizeKey("VK_UP", {altKey: true});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[i],
|
||||
is(textbox.selectedButton, oneOffs[i],
|
||||
"the one-off button #" + (i + 1) + " should be selected");
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
}
|
||||
|
||||
// One more alt+down keypress and nothing should be selected.
|
||||
EventUtils.synthesizeKey("VK_UP", {altKey: true});
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
// another one and the last one-off should be selected.
|
||||
EventUtils.synthesizeKey("VK_UP", {altKey: true});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[oneOffs.length - 1],
|
||||
is(textbox.selectedButton, oneOffs[oneOffs.length - 1],
|
||||
"the last one-off button should be selected");
|
||||
|
||||
// Cleanup for the next test.
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off should be selected anymore");
|
||||
ok(!textbox.selectedButton, "no one-off should be selected anymore");
|
||||
});
|
||||
|
||||
add_task(function* test_tab_and_arrows() {
|
||||
// Check the initial state is as expected.
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
is(textbox.value, kUserValue, "the textfield value should be unmodified");
|
||||
|
||||
|
@ -285,27 +285,27 @@ add_task(function* test_tab_and_arrows() {
|
|||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
is(searchPopup.selectedIndex, 0, "first suggestion should be selected");
|
||||
is(textbox.value, kValues[0], "the textfield value should have changed");
|
||||
ok(!textbox.getSelectedOneOff(), "no one-off button should be selected");
|
||||
ok(!textbox.selectedButton, "no one-off button should be selected");
|
||||
|
||||
// After pressing tab, the first one-off should be selected,
|
||||
// and the first suggestion still selected.
|
||||
let oneOffs = getOneOffs();
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[0],
|
||||
is(textbox.selectedButton, oneOffs[0],
|
||||
"the first one-off button should be selected");
|
||||
is(searchPopup.selectedIndex, 0, "first suggestion should still be selected");
|
||||
|
||||
// After pressing down, the second suggestion should be selected,
|
||||
// and the first one-off still selected.
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[0],
|
||||
is(textbox.selectedButton, oneOffs[0],
|
||||
"the first one-off button should still be selected");
|
||||
is(searchPopup.selectedIndex, 1, "second suggestion should be selected");
|
||||
|
||||
// After pressing up, the first suggestion should be selected again,
|
||||
// and the first one-off still selected.
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[0],
|
||||
is(textbox.selectedButton, oneOffs[0],
|
||||
"the first one-off button should still be selected");
|
||||
is(searchPopup.selectedIndex, 0, "second suggestion should be selected again");
|
||||
|
||||
|
@ -316,12 +316,12 @@ add_task(function* test_tab_and_arrows() {
|
|||
is(searchPopup.selectedIndex, -1, "no suggestion should be selected");
|
||||
is(textbox.value, kUserValue,
|
||||
"the textfield value should be back to user typed value");
|
||||
is(textbox.getSelectedOneOff(), oneOffs[0],
|
||||
is(textbox.selectedButton, oneOffs[0],
|
||||
"the first one-off button should still be selected");
|
||||
|
||||
// Now pressing down should select the second one-off.
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
is(textbox.getSelectedOneOff(), oneOffs[1],
|
||||
is(textbox.selectedButton, oneOffs[1],
|
||||
"the second one-off button should be selected");
|
||||
is(searchPopup.selectedIndex, -1, "there should still be no selected suggestion");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче