зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1561894 - Implement simplified one-off search button design. r=dao
Differential Revision: https://phabricator.services.mozilla.com/D39751 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d64c589ac1
Коммит
661a4df8a1
|
@ -18,24 +18,13 @@ class SearchOneOffs {
|
|||
this.container.appendChild(
|
||||
MozXULElement.parseXULToFragment(
|
||||
`
|
||||
<deck class="search-panel-one-offs-header search-panel-header search-panel-current-input">
|
||||
<label class="searchbar-oneoffheader-search" value="&searchWithHeader.label;"/>
|
||||
<hbox class="search-panel-searchforwith search-panel-current-input">
|
||||
<label value="&searchFor.label;"/>
|
||||
<label class="searchbar-oneoffheader-searchtext search-panel-input-value" flex="1" crop="end"/>
|
||||
<label flex="10000" value="&searchWith.label;"/>
|
||||
</hbox>
|
||||
<hbox class="search-panel-searchonengine search-panel-current-input">
|
||||
<label value="&search.label;"/>
|
||||
<label class="searchbar-oneoffheader-engine search-panel-input-value" flex="1" crop="end"/>
|
||||
<label flex="10000" value="&searchAfter.label;"/>
|
||||
</hbox>
|
||||
</deck>
|
||||
<description role="group" class="search-panel-one-offs">
|
||||
<button class="searchbar-engine-one-off-item search-setting-button-compact" tooltiptext="&changeSearchSettings.tooltip;"/>
|
||||
</description>
|
||||
<div class="search-panel-one-offs-header search-panel-header search-panel-current-input">
|
||||
<label class="searchbar-oneoffheader-search" value="&searchWithDesc.label;"/>
|
||||
</div>
|
||||
<div class="search-panel-one-offs"/>
|
||||
<vbox class="search-add-engines"/>
|
||||
<button class="search-setting-button search-panel-header" label="&changeSearchSettings.button;"/>
|
||||
<button class="searchbar-engine-one-off-item search-setting-button-compact" tooltiptext="&changeSearchSettings.tooltip;"/>
|
||||
<button class="search-setting-button" label="&changeSearchSettings.button;"/>
|
||||
<menupopup class="search-one-offs-context-menu">
|
||||
<menuitem class="search-one-offs-context-open-in-new-tab" label="&searchInNewTab.label;" accesskey="&searchInNewTab.accesskey;"/>
|
||||
<menuitem class="search-one-offs-context-set-default" label="&searchSetAsDefault.label;" accesskey="&searchSetAsDefault.accesskey;"/>
|
||||
|
@ -179,12 +168,17 @@ class SearchOneOffs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Width in pixels of the one-off buttons. 49px is the min-width of
|
||||
* each search engine button, adapt this const when changing the css.
|
||||
* It's actually 48px + 1px of right border.
|
||||
* Width in pixels of the one-off buttons.
|
||||
*/
|
||||
get buttonWidth() {
|
||||
return 49;
|
||||
return this.compact ? 40 : 48;
|
||||
}
|
||||
|
||||
/**
|
||||
* Height in pixels of the one-off buttons.
|
||||
*/
|
||||
get buttonHeight() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -274,7 +268,14 @@ class SearchOneOffs {
|
|||
(this._view && this._view.isOpen) ||
|
||||
(this.popup && this.popup.popupOpen)
|
||||
) {
|
||||
this._updateAfterQueryChanged();
|
||||
let isOneOffSelected =
|
||||
this.selectedButton &&
|
||||
this.selectedButton.classList.contains("searchbar-engine-one-off-item");
|
||||
// Typing de-selects the settings or opensearch buttons at the bottom
|
||||
// of the search panel, as typing shows the user intends to search.
|
||||
if (this.selectedButton && !isOneOffSelected) {
|
||||
this.selectedButton = null;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -291,10 +292,6 @@ class SearchOneOffs {
|
|||
* The selected one-off button. Null if no one-off is selected.
|
||||
*/
|
||||
set selectedButton(val) {
|
||||
if (val && val.classList.contains("dummy")) {
|
||||
// Never select dummy buttons.
|
||||
val = null;
|
||||
}
|
||||
let previousButton = this._selectedButton;
|
||||
if (previousButton) {
|
||||
previousButton.removeAttribute("selected");
|
||||
|
@ -392,43 +389,6 @@ class SearchOneOffs {
|
|||
this._engines = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the parts of the UI that show the query string.
|
||||
*/
|
||||
_updateAfterQueryChanged() {
|
||||
let headerSearchText = this.querySelector(
|
||||
".searchbar-oneoffheader-searchtext"
|
||||
);
|
||||
headerSearchText.setAttribute("value", this.query);
|
||||
let groupText;
|
||||
let isOneOffSelected =
|
||||
this.selectedButton &&
|
||||
this.selectedButton.classList.contains("searchbar-engine-one-off-item");
|
||||
// Typing de-selects the settings or opensearch buttons at the bottom
|
||||
// of the search panel, as typing shows the user intends to search.
|
||||
if (this.selectedButton && !isOneOffSelected) {
|
||||
this.selectedButton = null;
|
||||
}
|
||||
if (this.query) {
|
||||
groupText =
|
||||
headerSearchText.previousElementSibling.value +
|
||||
'"' +
|
||||
headerSearchText.value +
|
||||
'"' +
|
||||
headerSearchText.nextElementSibling.value;
|
||||
if (!isOneOffSelected) {
|
||||
this.header.selectedIndex = 1;
|
||||
}
|
||||
} else {
|
||||
let noSearchHeader = this.querySelector(".searchbar-oneoffheader-search");
|
||||
groupText = noSearchHeader.value;
|
||||
if (!isOneOffSelected) {
|
||||
this.header.selectedIndex = 0;
|
||||
}
|
||||
}
|
||||
this.buttons.setAttribute("aria-label", groupText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Infallible, non-re-entrant version of `__rebuild()`.
|
||||
*/
|
||||
|
@ -454,9 +414,6 @@ class SearchOneOffs {
|
|||
this.selectedButton = null;
|
||||
this._contextEngine = null;
|
||||
|
||||
// Update the 'Search for <keywords> with:" header.
|
||||
this._updateAfterQueryChanged();
|
||||
|
||||
// Handle opensearch items. This needs to be done before building the
|
||||
// list of one off providers, as that code will return early if all the
|
||||
// alternative engines are hidden.
|
||||
|
@ -480,15 +437,14 @@ class SearchOneOffs {
|
|||
}
|
||||
|
||||
// Finally, build the list of one-off buttons.
|
||||
while (this.buttons.firstElementChild != this.settingsButtonCompact) {
|
||||
while (this.buttons.firstElementChild) {
|
||||
this.buttons.firstElementChild.remove();
|
||||
}
|
||||
|
||||
// Remove the trailing empty text node introduced by the binding's
|
||||
// content markup above.
|
||||
if (this.settingsButtonCompact.nextElementSibling) {
|
||||
this.settingsButtonCompact.nextElementSibling.remove();
|
||||
}
|
||||
let headerText = this.header.querySelector(
|
||||
".searchbar-oneoffheader-search"
|
||||
);
|
||||
this.buttons.setAttribute("aria-label", headerText.value);
|
||||
|
||||
let engines = await this.getEngines();
|
||||
let defaultEngine = await Services.search.getDefault();
|
||||
|
@ -508,7 +464,10 @@ class SearchOneOffs {
|
|||
return;
|
||||
}
|
||||
|
||||
let panelWidth = parseInt((this.popup || this._view.panel).clientWidth);
|
||||
// this.buttonWidth is for the compact settings button.
|
||||
let buttonsWidth = this.compact
|
||||
? this._textboxWidth - this.buttonWidth - this.header.clientWidth
|
||||
: this.popup.clientWidth;
|
||||
|
||||
// There's one weird thing to guard against: when layout pixels
|
||||
// aren't an integral multiple of device pixels, the last button
|
||||
|
@ -519,33 +478,41 @@ class SearchOneOffs {
|
|||
// As a workaround, decrement the width if the scale is not an integer.
|
||||
let scale = window.windowUtils.screenPixelsPerCSSPixel;
|
||||
if (Math.floor(scale) != scale) {
|
||||
--panelWidth;
|
||||
--buttonsWidth;
|
||||
}
|
||||
|
||||
// The + 1 is because the last button doesn't have a right border.
|
||||
let enginesPerRow = Math.floor((panelWidth + 1) / this.buttonWidth);
|
||||
let buttonWidth = Math.floor(panelWidth / enginesPerRow);
|
||||
// There will be an emtpy area of:
|
||||
// panelWidth - enginesPerRow * buttonWidth px
|
||||
// If the header string is very long, then the searchbar buttons will
|
||||
// overflow their container unless max-width is set.
|
||||
this.buttons.style.setProperty(
|
||||
this.compact ? "width" : "max-width",
|
||||
`${buttonsWidth}px`
|
||||
);
|
||||
|
||||
// 24: 12px left padding + 12px right padding.
|
||||
if (this.compact) {
|
||||
buttonsWidth -= 24;
|
||||
}
|
||||
|
||||
// In very narrow windows, we should always have at least one button
|
||||
// per row.
|
||||
buttonsWidth = Math.max(buttonsWidth, this.buttonWidth);
|
||||
|
||||
let enginesPerRow = Math.floor(buttonsWidth / this.buttonWidth);
|
||||
// There will be an empty area of:
|
||||
// buttonsWidth - enginesPerRow * this.buttonWidth px
|
||||
// at the end of each row.
|
||||
|
||||
// If the <description> tag with the list of search engines doesn't have
|
||||
// If the <div> with the list of search engines doesn't have
|
||||
// a fixed height, the panel will be sized incorrectly, causing the bottom
|
||||
// of the suggestion <tree> to be hidden.
|
||||
if (this.compact) {
|
||||
++oneOffCount;
|
||||
}
|
||||
let rowCount = Math.ceil(oneOffCount / enginesPerRow);
|
||||
let height = rowCount * 33; // 32px per row, 1px border.
|
||||
this.buttons.setAttribute("height", height + "px");
|
||||
|
||||
let height = rowCount * this.buttonHeight;
|
||||
this.buttons.style.setProperty("height", `${height}px`);
|
||||
// Ensure we can refer to the settings buttons by ID:
|
||||
let origin = this.telemetryOrigin;
|
||||
this.settingsButton.id = origin + "-anon-search-settings";
|
||||
this.settingsButtonCompact.id = origin + "-anon-search-settings-compact";
|
||||
|
||||
let dummyItems =
|
||||
enginesPerRow - (oneOffCount % enginesPerRow || enginesPerRow);
|
||||
for (let i = 0; i < engines.length; ++i) {
|
||||
let engine = engines[i];
|
||||
let button = document.createXULElement("button");
|
||||
|
@ -557,53 +524,9 @@ class SearchOneOffs {
|
|||
button.setAttribute("image", uri);
|
||||
button.setAttribute("class", "searchbar-engine-one-off-item");
|
||||
button.setAttribute("tooltiptext", engine.name);
|
||||
button.setAttribute("width", buttonWidth);
|
||||
button.engine = engine;
|
||||
|
||||
if ((i + 1) % enginesPerRow == 0) {
|
||||
button.classList.add("last-of-row");
|
||||
}
|
||||
|
||||
if (i + 1 == engines.length) {
|
||||
button.classList.add("last-engine");
|
||||
}
|
||||
|
||||
if (i >= oneOffCount + dummyItems - enginesPerRow) {
|
||||
button.classList.add("last-row");
|
||||
}
|
||||
|
||||
this.buttons.insertBefore(button, this.settingsButtonCompact);
|
||||
}
|
||||
|
||||
let hasDummyItems = !!dummyItems;
|
||||
while (dummyItems) {
|
||||
let button = document.createXULElement("button");
|
||||
button.setAttribute(
|
||||
"class",
|
||||
"searchbar-engine-one-off-item dummy last-row"
|
||||
);
|
||||
button.setAttribute("width", buttonWidth);
|
||||
|
||||
if (!--dummyItems) {
|
||||
button.classList.add("last-of-row");
|
||||
}
|
||||
|
||||
this.buttons.insertBefore(button, this.settingsButtonCompact);
|
||||
}
|
||||
|
||||
if (this.compact) {
|
||||
this.settingsButtonCompact.setAttribute("width", buttonWidth);
|
||||
if (rowCount == 1 && hasDummyItems) {
|
||||
// When there's only one row, make the compact settings button
|
||||
// hug the right edge of the panel. It may not due to the panel's
|
||||
// width not being an integral multiple of the button width. (See
|
||||
// the "There will be an emtpy area" comment above.) Increase the
|
||||
// width of the last dummy item by the remainder.
|
||||
let remainder = panelWidth - enginesPerRow * buttonWidth;
|
||||
let width = remainder + buttonWidth;
|
||||
let lastDummyItem = this.settingsButtonCompact.previousElementSibling;
|
||||
lastDummyItem.setAttribute("width", width);
|
||||
}
|
||||
this.buttons.appendChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,37 +655,16 @@ class SearchOneOffs {
|
|||
_updateStateForButton(mousedOverButton) {
|
||||
let button = mousedOverButton;
|
||||
|
||||
// Ignore dummy buttons.
|
||||
if (button && button.classList.contains("dummy")) {
|
||||
button = null;
|
||||
}
|
||||
|
||||
// If there's no moused-over button, then the one-offs should reflect
|
||||
// the selected button, if any.
|
||||
button = button || this.selectedButton;
|
||||
|
||||
if (!button) {
|
||||
this.header.selectedIndex = this.query ? 1 : 0;
|
||||
if (this.textbox) {
|
||||
this.textbox.removeAttribute("aria-activedescendant");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
button.classList.contains("searchbar-engine-one-off-item") &&
|
||||
button.engine
|
||||
) {
|
||||
let headerEngineText = this.querySelector(
|
||||
".searchbar-oneoffheader-engine"
|
||||
);
|
||||
this.header.selectedIndex = 2;
|
||||
headerEngineText.value = button.engine.name;
|
||||
} else {
|
||||
this.header.selectedIndex = this.query ? 1 : 0;
|
||||
}
|
||||
if (this.textbox) {
|
||||
this.textbox.setAttribute("aria-activedescendant", button.id);
|
||||
if (!button) {
|
||||
this.textbox.removeAttribute("aria-activedescendant");
|
||||
} else {
|
||||
this.textbox.setAttribute("aria-activedescendant", button.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -773,19 +675,7 @@ class SearchOneOffs {
|
|||
oneOff;
|
||||
oneOff = oneOff.nextElementSibling
|
||||
) {
|
||||
// oneOff may be a text node since the list xul:description contains
|
||||
// whitespace and the compact settings button. See the markup
|
||||
// above. _rebuild removes text nodes, but it may not have been
|
||||
// called yet (because e.g. the popup hasn't been opened yet).
|
||||
if (oneOff.nodeType == Node.ELEMENT_NODE) {
|
||||
if (
|
||||
oneOff.classList.contains("dummy") ||
|
||||
oneOff.classList.contains("search-setting-button-compact")
|
||||
) {
|
||||
break;
|
||||
}
|
||||
buttons.push(oneOff);
|
||||
}
|
||||
buttons.push(oneOff);
|
||||
}
|
||||
|
||||
if (aIncludeNonEngineButtons) {
|
||||
|
@ -850,7 +740,7 @@ class SearchOneOffs {
|
|||
* If true, the index is incremented, and if false, the index is
|
||||
* decremented.
|
||||
* @param {boolean} aIncludeNonEngineButtons
|
||||
* If true, non-dummy buttons that do not have engines are included.
|
||||
* If true, buttons that do not have engines are included.
|
||||
* These buttons include the OpenSearch and settings buttons. For
|
||||
* example, if the currently selected button is an engine button,
|
||||
* the next button is the settings button, and you pass true for
|
||||
|
@ -1202,9 +1092,7 @@ class SearchOneOffs {
|
|||
return;
|
||||
}
|
||||
|
||||
let isOneOff =
|
||||
target.classList.contains("searchbar-engine-one-off-item") &&
|
||||
!target.classList.contains("dummy");
|
||||
let isOneOff = target.classList.contains("searchbar-engine-one-off-item");
|
||||
if (
|
||||
isOneOff ||
|
||||
target.classList.contains("addengine-item") ||
|
||||
|
@ -1349,8 +1237,7 @@ class SearchOneOffs {
|
|||
// Prevent the context menu from appearing except on the one off buttons.
|
||||
if (
|
||||
!target.classList.contains("searchbar-engine-one-off-item") ||
|
||||
target.classList.contains("search-setting-button-compact") ||
|
||||
target.classList.contains("dummy")
|
||||
target.classList.contains("search-setting-button-compact")
|
||||
) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
|
|
|
@ -39,8 +39,6 @@ skip-if = (verify && debug && (os == 'win' || os == 'linux'))
|
|||
[browser_oneOffContextMenu.js]
|
||||
skip-if = verify
|
||||
[browser_oneOffContextMenu_setDefault.js]
|
||||
[browser_oneOffHeader.js]
|
||||
skip-if = os == "mac" #1421238
|
||||
[browser_private_search_perwindowpb.js]
|
||||
[browser_searchbar_openpopup.js]
|
||||
skip-if = os == "linux" # Linux has different focus behaviours.
|
||||
|
|
|
@ -189,16 +189,23 @@ async function openPopupAndGetEngineButton(
|
|||
}
|
||||
|
||||
const contextMenu = oneOffInstance.contextMenuPopup;
|
||||
const oneOffButtons = oneOffInstance.buttons;
|
||||
let oneOffButton = oneOffInstance.buttons;
|
||||
|
||||
// Get the one-off button for the test engine.
|
||||
let oneOffButton;
|
||||
for (let node of oneOffButtons.children) {
|
||||
if (node.engine && node.engine.name == TEST_ENGINE_NAME) {
|
||||
oneOffButton = node;
|
||||
for (
|
||||
oneOffButton = oneOffButton.firstChild;
|
||||
oneOffButton;
|
||||
oneOffButton = oneOffButton.nextSibling
|
||||
) {
|
||||
if (
|
||||
oneOffButton.nodeType == Node.ELEMENT_NODE &&
|
||||
oneOffButton.engine &&
|
||||
oneOffButton.engine.name == TEST_ENGINE_NAME
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.notEqual(
|
||||
oneOffButton,
|
||||
undefined,
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
/* 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 searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
|
||||
const oneOffsContainer = searchPopup.searchOneOffsContainer;
|
||||
const searchSettings = oneOffsContainer.querySelector(".search-setting-button");
|
||||
|
||||
var header = oneOffsContainer.querySelector(".search-panel-one-offs-header");
|
||||
|
||||
function getHeaderText() {
|
||||
let headerChild = header.selectedPanel;
|
||||
while (headerChild.hasChildNodes()) {
|
||||
headerChild = headerChild.firstElementChild;
|
||||
}
|
||||
let headerStrings = [];
|
||||
for (let label = headerChild; label; label = label.nextElementSibling) {
|
||||
headerStrings.push(label.value);
|
||||
}
|
||||
return headerStrings.join("");
|
||||
}
|
||||
|
||||
const msg = isMac ? 5 : 1;
|
||||
const utils = window.windowUtils;
|
||||
const scale = utils.screenPixelsPerCSSPixel;
|
||||
function synthesizeNativeMouseMove(aElement) {
|
||||
let rect = aElement.getBoundingClientRect();
|
||||
let win = aElement.ownerGlobal;
|
||||
let x = win.mozInnerScreenX + (rect.left + rect.right) / 2;
|
||||
let y = win.mozInnerScreenY + (rect.top + rect.bottom) / 2;
|
||||
|
||||
// Wait for the mousemove event to occur before continuing.
|
||||
return new Promise((resolve, reject) => {
|
||||
function eventOccurred(e) {
|
||||
aElement.removeEventListener("mousemove", eventOccurred, true);
|
||||
SimpleTest.executeSoon(resolve);
|
||||
}
|
||||
|
||||
aElement.addEventListener("mousemove", eventOccurred, true);
|
||||
|
||||
utils.sendNativeMouseEvent(x * scale, y * scale, msg, 0, null);
|
||||
});
|
||||
}
|
||||
|
||||
let searchbar;
|
||||
let searchIcon;
|
||||
|
||||
add_task(async function init() {
|
||||
searchbar = await gCUITestUtils.addSearchBar();
|
||||
registerCleanupFunction(() => {
|
||||
gCUITestUtils.removeSearchBar();
|
||||
});
|
||||
searchIcon = searchbar.querySelector(".searchbar-search-button");
|
||||
|
||||
await promiseNewEngine("testEngine.xml");
|
||||
});
|
||||
|
||||
add_task(async function test_notext() {
|
||||
let promise = promiseEvent(searchPopup, "popupshown");
|
||||
info("Opening search panel");
|
||||
EventUtils.synthesizeMouseAtCenter(searchIcon, {});
|
||||
await 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"
|
||||
);
|
||||
|
||||
await 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();
|
||||
await 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("KEY_Escape");
|
||||
await promise;
|
||||
});
|
||||
|
||||
add_task(async function test_text() {
|
||||
searchbar.textbox.value = "foo";
|
||||
|
||||
let promise = promiseEvent(searchPopup, "popupshown");
|
||||
info("Opening search panel");
|
||||
SimpleTest.executeSoon(() => {
|
||||
EventUtils.synthesizeMouseAtCenter(searchIcon, {});
|
||||
});
|
||||
await 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();
|
||||
await 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."
|
||||
);
|
||||
|
||||
await 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."
|
||||
);
|
||||
|
||||
// Click the "Foo Search" header at the top of the popup and make sure it
|
||||
// loads the search results.
|
||||
let searchbarEngine = searchPopup.searchbarEngine;
|
||||
await synthesizeNativeMouseMove(searchbarEngine);
|
||||
SimpleTest.executeSoon(() => {
|
||||
EventUtils.synthesizeMouseAtCenter(searchbarEngine, {});
|
||||
});
|
||||
|
||||
let url = (await Services.search.getDefault()).getSubmission(
|
||||
searchbar.textbox.value
|
||||
).uri.spec;
|
||||
await promiseTabLoadEvent(gBrowser.selectedTab, url);
|
||||
|
||||
// Move the cursor out of the panel area to avoid messing with other tests.
|
||||
await synthesizeNativeMouseMove(searchbar);
|
||||
});
|
||||
|
||||
add_task(async function cleanup() {
|
||||
searchbar.textbox.value = "";
|
||||
});
|
|
@ -207,12 +207,6 @@ function getOneOffs() {
|
|||
let oneOff = oneOffsContainer.querySelector(".search-panel-one-offs");
|
||||
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
|
||||
if (oneOff.nodeType == Node.ELEMENT_NODE) {
|
||||
if (
|
||||
oneOff.classList.contains("dummy") ||
|
||||
oneOff.classList.contains("search-setting-button-compact")
|
||||
) {
|
||||
break;
|
||||
}
|
||||
oneOffs.push(oneOff);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -431,26 +431,11 @@ convenience of Safari and Chrome users on macOS. See bug 1398988. -->
|
|||
<!ENTITY searchInput.placeholder "Search">
|
||||
<!ENTITY searchIcon.tooltip "Search">
|
||||
|
||||
<!-- LOCALIZATION NOTE (searchFor.label, searchWith.label):
|
||||
These two strings are used to build the header above the list of one-click
|
||||
search providers: "Search for <used typed keywords> with:" -->
|
||||
<!ENTITY searchFor.label "Search for ">
|
||||
<!ENTITY searchWith.label " with:">
|
||||
<!-- LOCALIZATION NOTE (searchWithDesc.label):
|
||||
This string prompts the user to use the list of one-click search engines in
|
||||
the Urlbar and searchbar. -->
|
||||
<!ENTITY searchWithDesc.label "This time, search 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):
|
||||
The wording of this string should be as close as possible to
|
||||
searchFor.label and searchWith.label. This string will be used instead of
|
||||
them when the user has not typed any keyword. -->
|
||||
<!ENTITY searchWithHeader.label "Search with:">
|
||||
<!-- LOCALIZATION NOTE (changeSearchSettings.button):
|
||||
This string won't wrap, so if the translated string is longer,
|
||||
consider translating it as if it said only "Search Settings". -->
|
||||
|
|
|
@ -315,7 +315,7 @@ notification[value="translation"] menulist > .menulist-dropmarker {
|
|||
border-top: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#urlbarView-results {
|
||||
#urlbar-results {
|
||||
font-size: 1.05em;
|
||||
}
|
||||
|
||||
|
|
|
@ -318,7 +318,7 @@
|
|||
border-top: 1px solid #C7C7C7;
|
||||
}
|
||||
|
||||
#urlbarView-results {
|
||||
#urlbar-results {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
|
||||
%include ../shared/searchbar.inc.css
|
||||
|
||||
.search-panel-header,
|
||||
.addengine-item {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.searchbar-popup {
|
||||
margin-top: 4px;
|
||||
margin-inline-start: 3px;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
.search-one-offs {
|
||||
-moz-box-orient: vertical;
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,36 +51,27 @@
|
|||
|
||||
.search-panel-header {
|
||||
font-weight: normal;
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
margin: 0;
|
||||
padding: 3px 6px;
|
||||
padding: 3px;
|
||||
color: var(--panel-disabled-color);
|
||||
}
|
||||
|
||||
:root[lwt-popup-brighttext] .search-panel-header {
|
||||
color: var(--autocomplete-popup-color);
|
||||
}
|
||||
|
||||
.search-panel-header > label {
|
||||
margin-top: 2px !important;
|
||||
margin-bottom: 1px !important;
|
||||
}
|
||||
|
||||
.search-panel-current-input > label {
|
||||
margin: 2px 0 !important;
|
||||
}
|
||||
|
||||
.search-panel-input-value {
|
||||
color: var(--autocomplete-popup-color);
|
||||
}
|
||||
|
||||
.search-panel-one-offs {
|
||||
margin: 0 !important;
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
/* Bug 1108841: prevent font-size from affecting the layout */
|
||||
line-height: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.searchbar-engine-one-off-item {
|
||||
|
@ -88,35 +81,10 @@
|
|||
height: 32px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: linear-gradient(transparent 15%, var(--panel-separator-color) 15%, var(--panel-separator-color) 85%, transparent 85%);
|
||||
background-size: 1px auto;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
color: var(--panel-disabled-color);
|
||||
}
|
||||
|
||||
.searchbar-engine-one-off-item:-moz-locale-dir(rtl) {
|
||||
background-position-x: left;
|
||||
}
|
||||
|
||||
.searchbar-engine-one-off-item:not(.last-row) {
|
||||
box-sizing: content-box;
|
||||
border-bottom: 1px solid var(--panel-separator-color);
|
||||
}
|
||||
|
||||
.search-setting-button-compact {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.search-one-offs:not([compact=true]) .searchbar-engine-one-off-item.last-of-row,
|
||||
.search-one-offs[compact=true] .searchbar-engine-one-off-item.last-of-row:not(.dummy),
|
||||
.search-one-offs[compact=true] .searchbar-engine-one-off-item.dummy:not(.last-of-row),
|
||||
.search-one-offs[compact=true] .searchbar-engine-one-off-item.last-engine,
|
||||
.search-setting-button-compact {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.searchbar-engine-one-off-item:not([selected]):not(.dummy):hover,
|
||||
.searchbar-engine-one-off-item:not([selected]):hover,
|
||||
.addengine-item:hover {
|
||||
background-color: var(--arrowpanel-dimmed-further);
|
||||
color: inherit;
|
||||
|
@ -124,7 +92,6 @@
|
|||
|
||||
.searchbar-engine-one-off-item[selected] {
|
||||
background-color: var(--autocomplete-popup-highlight-background);
|
||||
background-image: none;
|
||||
color: var(--autocomplete-popup-highlight-color);
|
||||
}
|
||||
|
||||
|
@ -143,10 +110,6 @@
|
|||
height: 16px;
|
||||
}
|
||||
|
||||
.search-add-engines {
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
}
|
||||
|
||||
.addengine-item {
|
||||
-moz-appearance: none;
|
||||
color: inherit;
|
||||
|
@ -238,6 +201,13 @@
|
|||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
min-height: 32px;
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
color: var(--panel-disabled-color);
|
||||
}
|
||||
|
||||
.search-setting-button-compact {
|
||||
max-height: 32px;
|
||||
}
|
||||
|
||||
.search-setting-button:hover,
|
||||
|
|
|
@ -248,6 +248,33 @@
|
|||
color: var(--autocomplete-popup-highlight-background);
|
||||
}
|
||||
|
||||
/* Search one-offs. */
|
||||
#urlbar-results > .search-one-offs {
|
||||
-moz-box-orient: horizontal;
|
||||
padding-inline-start: var(--item-padding-start, 5px);
|
||||
padding-inline-end: var(--item-padding-end, 5px);
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
#urlbar-results .search-panel-one-offs {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
#urlbar-results .search-panel-header {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#urlbar-results .searchbar-engine-one-off-item {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
/* search bar popup */
|
||||
|
||||
#PopupSearchAutoComplete {
|
||||
|
|
|
@ -609,7 +609,7 @@ menuitem.bookmark-item {
|
|||
%include ../shared/autocomplete.inc.css
|
||||
%include ../shared/urlbar-autocomplete.inc.css
|
||||
|
||||
#urlbarView-results {
|
||||
#urlbar-results {
|
||||
font-size: 1.15em;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче