mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 05:08:36 +02:00
Bug 1110767 - Instantly show the search engine when it is selected in the search bar header text. r=florian
This commit is contained in:
parent
2773a89419
commit
109759719f
5 changed files with 183 additions and 2 deletions
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
141
browser/components/search/test/browser_oneOffHeader.js
Normal file
141
browser/components/search/test/browser_oneOffHeader.js
Normal 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;
|
||||||
|
});
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue