Bug 1110767 - Instantly show the search engine when it is selected in the search bar header text. r=florian

This commit is contained in:
Chris 2015-04-13 14:52:42 -07:00
parent 2773a89419
commit 109759719f
5 changed files with 183 additions and 2 deletions

View file

@ -1044,6 +1044,14 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<xul:label anonid="searchbar-oneoffheader-searchtext" flex="1" crop="end" class="search-panel-input-value"/> <xul:label anonid="searchbar-oneoffheader-searchtext" flex="1" crop="end" class="search-panel-input-value"/>
<xul:label anonid="searchbar-oneoffheader-after" flex="10000" value="&searchWith.label;"/> <xul:label anonid="searchbar-oneoffheader-after" flex="10000" value="&searchWith.label;"/>
</xul:hbox> </xul:hbox>
<xul:hbox anonid="search-panel-searchonengine"
class="search-panel-current-input">
<xul:label anonid="searchbar-oneoffheader-beforeengine" value="&search.label;"/>
<xul:label anonid="searchbar-oneoffheader-engine" flex="1" crop="end"
class="search-panel-input-value"/>
<xul:label anonid="searchbar-oneoffheader-afterengine" flex="10000"
value="&searchAfter.label;"/>
</xul:hbox>
</xul:deck> </xul:deck>
<xul:description anonid="search-panel-one-offs" <xul:description anonid="search-panel-one-offs"
role="group" role="group"
@ -1140,19 +1148,24 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
let inputHandler = function() { let inputHandler = function() {
headerSearchText.setAttribute("value", textbox.value); headerSearchText.setAttribute("value", textbox.value);
let groupText; let groupText;
let isOneOffSelected =
this.selectedButton &&
this.selectedButton.classList.contains("searchbar-engine-one-off-item");
if (textbox.value) { if (textbox.value) {
self.removeAttribute("showonlysettings"); self.removeAttribute("showonlysettings");
groupText = headerSearchText.previousSibling.value + groupText = headerSearchText.previousSibling.value +
'"' + headerSearchText.value + '"' + '"' + headerSearchText.value + '"' +
headerSearchText.nextSibling.value; headerSearchText.nextSibling.value;
headerPanel.selectedIndex = 1; if (!isOneOffSelected)
headerPanel.selectedIndex = 1;
} }
else { else {
let noSearchHeader = let noSearchHeader =
document.getAnonymousElementByAttribute(self, "anonid", document.getAnonymousElementByAttribute(self, "anonid",
"searchbar-oneoffheader-search"); "searchbar-oneoffheader-search");
groupText = noSearchHeader.value; groupText = noSearchHeader.value;
headerPanel.selectedIndex = 0; if (!isOneOffSelected)
headerPanel.selectedIndex = 0;
} }
list.setAttribute("aria-label", groupText); list.setAttribute("aria-label", groupText);
}; };

View file

@ -1021,14 +1021,29 @@
if (this._selectedButton) if (this._selectedButton)
this._selectedButton.removeAttribute("selected"); this._selectedButton.removeAttribute("selected");
let textbox = document.getBindingParent(this).textbox;
let header =
document.getAnonymousElementByAttribute(this.popup, "anonid",
"search-panel-one-offs-header");
// Avoid selecting dummy buttons. // Avoid selecting dummy buttons.
if (val && !val.classList.contains("dummy")) { if (val && !val.classList.contains("dummy")) {
val.setAttribute("selected", "true"); val.setAttribute("selected", "true");
this._selectedButton = val; this._selectedButton = val;
if (val.classList.contains("searchbar-engine-one-off-item")) {
let headerEngineText =
document.getAnonymousElementByAttribute(this.popup, "anonid",
"searchbar-oneoffheader-engine");
header.selectedIndex = 2;
headerEngineText.value = val.engine.name;
}
else {
header.selectedIndex = textbox.value ? 1 : 0;
}
this.setAttribute("aria-activedescendant", val.id); this.setAttribute("aria-activedescendant", val.id);
return; return;
} }
header.selectedIndex = textbox.value ? 1 : 0;
this.removeAttribute("aria-activedescendant"); this.removeAttribute("aria-activedescendant");
this._selectedButton = null; this._selectedButton = null;
]]></setter> ]]></setter>

View file

@ -36,6 +36,8 @@ skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Err
[browser_healthreport.js] [browser_healthreport.js]
[browser_hiddenOneOffs_cleanup.js] [browser_hiddenOneOffs_cleanup.js]
[browser_hiddenOneOffs_diacritics.js] [browser_hiddenOneOffs_diacritics.js]
[browser_oneOffHeader.js]
skip-if = e10s # bug ?????? - Test alters the searchbar textbox value which causes issues with other tests in e10s.
[browser_private_search_perwindowpb.js] [browser_private_search_perwindowpb.js]
skip-if = e10s # Bug ?????? - Test uses load event and checks event.target. skip-if = e10s # Bug ?????? - Test uses load event and checks event.target.
[browser_yahoo.js] [browser_yahoo.js]

View file

@ -0,0 +1,141 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Tests that keyboard navigation in the search panel works as designed.
const isMac = ("nsILocalFileMac" in Ci);
const searchbar = document.getElementById("searchbar");
const textbox = searchbar._textbox;
const searchPopup = document.getElementById("PopupSearchAutoComplete");
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid",
"searchbar-search-button");
const searchSettings =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-settings");
let header =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-panel-one-offs-header");
function getHeaderText() {
let headerChild = header.selectedPanel;
while (headerChild.hasChildNodes()) {
headerChild = headerChild.firstChild;
}
let headerStrings = [];
for (let label = headerChild; label; label = label.nextSibling) {
headerStrings.push(label.value);
}
return headerStrings.join("");
}
// Get an array of the one-off buttons.
function getOneOffs() {
let oneOffs = [];
let oneOff =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-panel-one-offs");
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
if (oneOff.classList.contains("dummy"))
break;
oneOffs.push(oneOff);
}
return oneOffs;
}
const msg = isMac ? 5 : 1;
const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
const scale = utils.screenPixelsPerCSSPixel;
function* synthesizeNativeMouseMove(aElement) {
let rect = aElement.getBoundingClientRect();
let win = aElement.ownerDocument.defaultView;
let x = win.mozInnerScreenX + (rect.left + rect.right) / 2;
let y = win.mozInnerScreenY + (rect.top + rect.bottom) / 2;
// Wait for the mouseup event to occur before continuing.
return new Promise((resolve, reject) => {
function eventOccurred(e)
{
aElement.removeEventListener("mouseover", eventOccurred, true);
resolve();
}
aElement.addEventListener("mouseover", eventOccurred, true);
utils.sendNativeMouseEvent(x * scale, y * scale, msg, 0, null);
});
}
add_task(function* init() {
yield promiseNewEngine("testEngine.xml");
});
add_task(function* test_notext() {
let promise = promiseEvent(searchPopup, "popupshown");
info("Opening search panel");
EventUtils.synthesizeMouseAtCenter(searchIcon, {});
yield promise;
is(header.getAttribute("selectedIndex"), 0,
"Header has the correct index selected with no search terms.");
is(getHeaderText(), "Search with:",
"Search header string is correct when no search terms have been entered");
yield synthesizeNativeMouseMove(searchSettings);
is(header.getAttribute("selectedIndex"), 0,
"Header has the correct index when no search terms have been entered and the Change Search Settings button is selected.");
is(getHeaderText(), "Search with:",
"Header has the correct text when no search terms have been entered and the Change Search Settings button is selected.");
let buttons = getOneOffs();
yield synthesizeNativeMouseMove(buttons[0]);
is(header.getAttribute("selectedIndex"), 2,
"Header has the correct index selected when a search engine has been selected");
is(getHeaderText(), "Search " + buttons[0].engine.name,
"Is the header text correct when a search engine is selected and no terms have been entered.");
promise = promiseEvent(searchPopup, "popuphidden");
info("Closing search panel");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
});
add_task(function* test_text() {
textbox.value = "foo";
registerCleanupFunction(() => {
textbox.value = "";
});
let promise = promiseEvent(searchPopup, "popupshown");
info("Opening search panel");
SimpleTest.executeSoon(() => {
EventUtils.synthesizeMouseAtCenter(searchIcon, {});
});
yield promise;
is(header.getAttribute("selectedIndex"), 1,
"Header has the correct index selected with a search term.");
is(getHeaderText(), "Search for foo with:",
"Search header string is correct when a search term has been entered");
let buttons = getOneOffs();
yield synthesizeNativeMouseMove(buttons[0]);
is(header.getAttribute("selectedIndex"), 2,
"Header has the correct index selected when a search engine has been selected");
is(getHeaderText(), "Search " + buttons[0].engine.name,
"Is the header text correct when search terms are entered after a search engine has been selected.");
yield synthesizeNativeMouseMove(searchSettings);
is(header.getAttribute("selectedIndex"), 1,
"Header has the correct index selected when search terms have been entered and the Change Search Settings button is selected.");
is(getHeaderText(), "Search for foo with:",
"Header has the correct text when search terms have been entered and the Change Search Settings button is selected.");
promise = promiseEvent(searchPopup, "popuphidden");
info("Closing search panel");
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promise;
});

View file

@ -423,6 +423,16 @@ These should match what Safari and other Apple applications use on OS X Lion. --
search providers: "Search for <used typed keywords> with:" --> search providers: "Search for <used typed keywords> with:" -->
<!ENTITY searchFor.label "Search for "> <!ENTITY searchFor.label "Search for ">
<!ENTITY searchWith.label " with:"> <!ENTITY searchWith.label " with:">
<!-- LOCALIZATION NOTE (search.label, searchAfter.label):
This string is used to build the header above the list of one-click search
providers when a one off engine has been selected. The searchAfter text is
intentionally left empty for en-US and can be used by other localizations to
display a string after the search engine name. This string will be displayed
as: "Search <selected engine name><searchAfter.label text>" -->
<!ENTITY search.label "Search ">
<!ENTITY searchAfter.label "">
<!-- LOCALIZATION NOTE (searchWithHeader.label): <!-- LOCALIZATION NOTE (searchWithHeader.label):
The wording of this string should be as close as possible to The wording of this string should be as close as possible to
searchFor.label and searchWith.label. This string will be used instead of searchFor.label and searchWith.label. This string will be used instead of