Bug 1835687 - Use HTML search-bar widget in quick filter bar. r=aleca
Differential Revision: https://phabricator.services.mozilla.com/D190713 --HG-- rename : mail/components/unifiedtoolbar/content/search-bar.mjs => mail/base/content/widgets/search-bar.mjs rename : mail/components/unifiedtoolbar/test/browser/browser_searchBar.js => mail/base/test/browser/browser_searchBar.js rename : mail/components/unifiedtoolbar/test/browser/files/searchBar.xhtml => mail/base/test/browser/files/searchBar.xhtml extra : amend_source : d2c17892f8717285cd887107bcb1428107e9d2dc
This commit is contained in:
Родитель
cf8cb52c4c
Коммит
451150f825
|
@ -2,18 +2,24 @@
|
|||
# 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/.
|
||||
|
||||
#include ./widgets/search-bar.inc.xhtml
|
||||
<div id="quick-filter-bar" class="themeable-brighttext" hidden="hidden">
|
||||
<div id="quickFilterBarContainer">
|
||||
<button is="toggle-button" id="qfb-sticky"
|
||||
class="button icon-button icon-only check-button"
|
||||
data-l10n-id="quick-filter-bar-sticky">
|
||||
</button>
|
||||
<xul:search-textbox id="qfb-qs-textbox"
|
||||
class="themeableSearchBox"
|
||||
timeout="500"
|
||||
maxlength="192"
|
||||
data-l10n-id="quick-filter-bar-textbox"
|
||||
data-l10n-attrs="placeholder" />
|
||||
<search-bar id="qfb-qs-textbox"
|
||||
maxlength="192"
|
||||
data-l10n-id="quick-filter-bar-search"
|
||||
data-l10n-attrs="label"
|
||||
aria-keyshortcuts="Control+Shift+K">
|
||||
<span slot="placeholder" data-l10n-id="quick-filter-bar-search-placeholder-with-key" class="kbd-container"></span>
|
||||
<img data-l10n-id="quick-filter-bar-search-button"
|
||||
slot="button"
|
||||
class="qfb-search-button-icon"
|
||||
src="" />
|
||||
</search-bar>
|
||||
<button id="qfd-dropdown"
|
||||
class="button button-flat icon-button icon-only"
|
||||
data-l10n-id="quick-filter-bar-dropdown">
|
||||
|
|
|
@ -15,6 +15,8 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
QuickFilterState: "resource:///modules/QuickFilterManager.jsm",
|
||||
});
|
||||
|
||||
import("chrome://messenger/content/search-bar.mjs");
|
||||
|
||||
class ToggleButton extends HTMLButtonElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -106,13 +108,13 @@ var quickFilterBar = {
|
|||
if (!this.filterer.visible) {
|
||||
this._showFilterBar(true);
|
||||
}
|
||||
document.getElementById(QuickFilterManager.textBoxDomId).select();
|
||||
document.getElementById(QuickFilterManager.textBoxDomId).focus();
|
||||
});
|
||||
commandController.registerCallback("cmd_toggleQuickFilterBar", () => {
|
||||
let show = !this.filterer.visible;
|
||||
this._showFilterBar(show);
|
||||
if (show) {
|
||||
document.getElementById(QuickFilterManager.textBoxDomId).select();
|
||||
document.getElementById(QuickFilterManager.textBoxDomId).focus();
|
||||
}
|
||||
});
|
||||
window.addEventListener("keypress", event => {
|
||||
|
@ -317,8 +319,12 @@ var quickFilterBar = {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (domNode.namespaceURI == document.documentElement.namespaceURI) {
|
||||
if (domNode.tagName === "search-bar") {
|
||||
domNode.addEventListener("autocomplete", handlerDomId);
|
||||
domNode.addEventListener("search", handlerDomId);
|
||||
} else if (
|
||||
domNode.namespaceURI == document.documentElement.namespaceURI
|
||||
) {
|
||||
domNode.addEventListener("click", handlerDomId);
|
||||
} else {
|
||||
domNode.addEventListener("command", handlerDomId);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# 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/.
|
||||
|
||||
<template id="searchBarTemplate"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
<form>
|
||||
<input type="search" placeholder="" required="required" />
|
||||
<div aria-hidden="true"><slot name="placeholder"></slot></div>
|
||||
<button class="button button-flat icon-button"><slot name="button"></slot></button>
|
||||
</form>
|
||||
</template>
|
|
@ -4,18 +4,20 @@
|
|||
|
||||
/**
|
||||
* Search input with customizable search button and placeholder.
|
||||
* Attributes:
|
||||
* - label: Search field label for accessibility tree.
|
||||
* - disabled: When present, disable the search field and button.
|
||||
* Slots in template (#searchBarTemplate):
|
||||
* - placeholder: Content displayed as placeholder. When not provided, the value
|
||||
* of the label attribute is shown as placeholder.
|
||||
* - button: Content displayed on the search button.
|
||||
* Template ID: #searchBarTemplate (from search-bar.inc.xhtml)
|
||||
*
|
||||
* @emits search: Event when a search should be executed. detail holds the
|
||||
* search term.
|
||||
* @emits autocomplte: Auto complete update. detail holds the current search
|
||||
* term.
|
||||
* @tagname search-bar
|
||||
* @attribute {string} label - Search field label for accessibility tree.
|
||||
* @attribute {boolean} disabled - When present, disable the search field and
|
||||
* button.
|
||||
* @attribute {number} maxlength - Max length of the input in the search field.
|
||||
* @slot placeholder - Content displayed as placeholder. When not provided, the
|
||||
* value of the label attribute is shown as placeholder.
|
||||
* @slot button - Content displayed on the search button.
|
||||
* @fires {CustomEvent} search - Event when a search should be executed. detail
|
||||
* holds the search term.
|
||||
* @fires {CustomEvent} autocomplete - Auto complete update. detail holds the
|
||||
* current search term.
|
||||
*/
|
||||
export class SearchBar extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
|
@ -71,14 +73,16 @@ export class SearchBar extends HTMLElement {
|
|||
this.#input = template.querySelector("input");
|
||||
this.#button = template.querySelector("button");
|
||||
|
||||
template.querySelector("form").addEventListener("submit", this.#onSubmit, {
|
||||
template.querySelector("form").addEventListener("submit", this, {
|
||||
passive: false,
|
||||
});
|
||||
|
||||
this.#input.setAttribute("aria-label", this.getAttribute("label"));
|
||||
this.#input.setAttribute("maxlength", this.getAttribute("maxlength"));
|
||||
template.querySelector("slot[name=placeholder]").textContent =
|
||||
this.getAttribute("label");
|
||||
this.#input.addEventListener("input", this.#onInput);
|
||||
this.#input.addEventListener("input", this);
|
||||
this.#input.addEventListener("keyup", this);
|
||||
|
||||
const styles = document.createElement("link");
|
||||
styles.setAttribute("rel", "stylesheet");
|
||||
|
@ -107,8 +111,30 @@ export class SearchBar extends HTMLElement {
|
|||
}
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "submit":
|
||||
this.#onSubmit(event);
|
||||
break;
|
||||
case "input":
|
||||
this.#onInput(event);
|
||||
break;
|
||||
case "keyup":
|
||||
if (event.key === "Escape" && this.#input.value) {
|
||||
this.reset();
|
||||
this.#onInput();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.#input.focus();
|
||||
if (this.#input.value) {
|
||||
this.#input.select();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
|
@ -103,6 +103,7 @@ messenger.jar:
|
|||
content/messenger/header-fields.js (content/widgets/header-fields.js)
|
||||
content/messenger/mailWidgets.js (content/widgets/mailWidgets.js)
|
||||
content/messenger/pane-splitter.js (content/widgets/pane-splitter.js)
|
||||
content/messenger/search-bar.mjs (content/widgets/search-bar.mjs)
|
||||
content/messenger/statuspanel.js (content/widgets/statuspanel.js)
|
||||
content/messenger/tabmail-tab.js (content/widgets/tabmail-tab.js)
|
||||
content/messenger/tabmail-tabs.js (content/widgets/tabmail-tabs.js)
|
||||
|
|
|
@ -44,6 +44,7 @@ skip-if = os == 'mac'
|
|||
[browser_paneFocus.js]
|
||||
[browser_paneSplitter.js]
|
||||
[browser_preferDisplayName.js]
|
||||
[browser_searchBar.js]
|
||||
[browser_searchMessages.js]
|
||||
[browser_spacesToolbar.js]
|
||||
[browser_spacesToolbarCustomize.js]
|
||||
|
|
|
@ -74,8 +74,8 @@ function is_visible(element) {
|
|||
}
|
||||
|
||||
add_setup(async function () {
|
||||
let tab = tabmail.openTab("contentTab", {
|
||||
url: "chrome://mochitests/content/browser/comm/mail/components/unifiedtoolbar/test/browser/files/searchBar.xhtml",
|
||||
const tab = tabmail.openTab("contentTab", {
|
||||
url: "chrome://mochitests/content/browser/comm/mail/base/test/browser/files/searchBar.xhtml",
|
||||
});
|
||||
|
||||
await BrowserTestUtils.browserLoaded(tab.browser);
|
||||
|
@ -112,6 +112,20 @@ add_task(async function test_focus() {
|
|||
input,
|
||||
"Input is focused when search bar is focused"
|
||||
);
|
||||
|
||||
input.blur();
|
||||
input.value = "foo";
|
||||
|
||||
searchBar.focus();
|
||||
is(
|
||||
searchBar.shadowRoot.activeElement,
|
||||
input,
|
||||
"Input is focused when search bar is focused"
|
||||
);
|
||||
is(input.selectionStart, 0, "Selection at the beginning");
|
||||
is(input.selectionEnd, 3, "Selection to the end");
|
||||
|
||||
searchBar.reset();
|
||||
});
|
||||
|
||||
add_task(async function test_autocompleteEvent() {
|
||||
|
@ -261,3 +275,17 @@ add_task(async function test_disabled() {
|
|||
ok(!input.disabled, "Input enabled again");
|
||||
ok(!button.disabled, "Button enabled again");
|
||||
});
|
||||
|
||||
add_task(async function test_clearWithEscape() {
|
||||
const input = searchBar.shadowRoot.querySelector("input");
|
||||
|
||||
searchBar.focus();
|
||||
input.value = "foo bar";
|
||||
|
||||
const eventPromise = BrowserTestUtils.waitForEvent(searchBar, "autocomplete");
|
||||
await BrowserTestUtils.synthesizeKey("KEY_Escape", {}, browser);
|
||||
const event = await eventPromise;
|
||||
|
||||
is(event.detail, "", "Autocomplete event with empty value");
|
||||
is(input.value, "", "Input was cleared");
|
||||
});
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Search bar element test</title>
|
||||
<script type="module" src="chrome://messenger/content/unifiedtoolbar/search-bar.mjs"></script>
|
||||
<script type="module" src="chrome://messenger/content/search-bar.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<template id="searchBarTemplate">
|
|
@ -46,3 +46,12 @@ window.MozXULElement = {
|
|||
|
||||
// Enable props tables documentation.
|
||||
setCustomElementsManifest(customElementsManifest);
|
||||
|
||||
// Stop typing on a keyboard inside the sandbox from messing with the storybook
|
||||
// UI
|
||||
const stopEvent = event => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
document.addEventListener("keydown", stopEvent);
|
||||
document.addEventListener("keypress", stopEvent);
|
||||
document.addEventListener("keyup", stopEvent);
|
||||
|
|
|
@ -4,14 +4,25 @@
|
|||
|
||||
import { html } from "lit";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import "mail/components/unifiedtoolbar/content/search-bar.mjs"; //eslint-disable-line import/no-unassigned-import
|
||||
/* eslint-disable import/no-unassigned-import */
|
||||
import "mail/base/content/widgets/search-bar.mjs";
|
||||
import "mail/themes/shared/mail/colors.css";
|
||||
import "mail/themes/shared/mail/layout.css";
|
||||
import "mail/themes/shared/mail/widgets.css";
|
||||
/* eslint-enable import/no-unassigned-import */
|
||||
|
||||
export default {
|
||||
title: "Widgets/Search Bar",
|
||||
component: "search-bar",
|
||||
argTypes: {
|
||||
disabled: {
|
||||
control: "boolean",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const SearchBar = () => html`
|
||||
const Template = ({ label, disabled }) => html`
|
||||
<!-- #include mail/base/content/widgets/search-bar.inc.xhtml -->
|
||||
<template id="searchBarTemplate">
|
||||
<form>
|
||||
<input type="search" placeholder="" required="required" />
|
||||
|
@ -24,8 +35,10 @@ export const SearchBar = () => html`
|
|||
<search-bar
|
||||
@search="${action("search")}"
|
||||
@autocomplete="${action("autocomplete")}"
|
||||
label="${label}"
|
||||
?disabled="${disabled}"
|
||||
>
|
||||
<span slot="placeholder"
|
||||
<span slot="placeholder" class="kbd-container"
|
||||
>Search Field Placeholder <kbd>Ctrl</kbd> + <kbd>K</kbd>
|
||||
</span>
|
||||
<img
|
||||
|
@ -36,3 +49,8 @@ export const SearchBar = () => html`
|
|||
/>
|
||||
</search-bar>
|
||||
`;
|
||||
export const SearchBar = Template.bind({});
|
||||
SearchBar.args = {
|
||||
label: "",
|
||||
disabled: false,
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
import { SearchBar } from "chrome://messenger/content/unifiedtoolbar/search-bar.mjs";
|
||||
import { SearchBar } from "chrome://messenger/content/search-bar.mjs";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
|
@ -101,24 +101,49 @@ class GlobalSearchBar extends SearchBar {
|
|||
// Need to call this after the shadow root test, since this will always set
|
||||
// up a shadow root.
|
||||
super.connectedCallback();
|
||||
this.addEventListener("search", this.#handleSearch);
|
||||
this.addEventListener("autocomplete", this.#handleAutocomplete);
|
||||
this.addEventListener("search", this);
|
||||
this.addEventListener("autocomplete", this);
|
||||
// Capturing to avoid the default cursor movements inside the input.
|
||||
this.addEventListener("keydown", this.#handleKeydown, {
|
||||
this.addEventListener("keydown", this, {
|
||||
capture: true,
|
||||
});
|
||||
this.addEventListener("focus", this.#handleFocus);
|
||||
this.addEventListener("focus", this);
|
||||
this.addEventListener("blur", this);
|
||||
this.addEventListener("drop", this.#handleDrop, { capture: true });
|
||||
this.addEventListener("drop", this, { capture: true });
|
||||
}
|
||||
|
||||
#popupWasOpenAtDown = false;
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "search":
|
||||
this.#handleSearch(event);
|
||||
break;
|
||||
case "autocomplete":
|
||||
this.#handleAutocomplete(event);
|
||||
break;
|
||||
case "keydown":
|
||||
this.#handleKeydown(event);
|
||||
this.#popupWasOpenAtDown = this.popup.mPopupOpen;
|
||||
break;
|
||||
case "focus":
|
||||
this.#handleFocus(event);
|
||||
break;
|
||||
case "drop":
|
||||
this.#handleDrop(event);
|
||||
break;
|
||||
case "keyup":
|
||||
if (!this.#popupWasOpenAtDown || event.key !== "Escape") {
|
||||
super.handleEvent(event);
|
||||
}
|
||||
break;
|
||||
case "blur":
|
||||
if (this.popup.mPopupOpen) {
|
||||
this.popup.closePopup();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
import "./search-bar.mjs"; // eslint-disable-line import/no-unassigned-import
|
||||
import "chrome://messenger/content/search-bar.mjs"; // eslint-disable-line import/no-unassigned-import
|
||||
import "./customization-palette.mjs"; // eslint-disable-line import/no-unassigned-import
|
||||
import "./customization-target.mjs"; // eslint-disable-line import/no-unassigned-import
|
||||
import {
|
||||
|
|
|
@ -96,10 +96,22 @@ class UnifiedToolbarCustomization extends HTMLElement {
|
|||
this.initialize();
|
||||
this.append(template);
|
||||
this.#updateResetToDefault();
|
||||
this.addEventListener("keyup", this.#handleKeyboard);
|
||||
this.addEventListener("keyup", this.#closeByKeyboard);
|
||||
this.addEventListener("keypress", this.#handleKeyboard);
|
||||
this.addEventListener("keydown", this.#handleKeyboard);
|
||||
this.addEventListener("keyup", this);
|
||||
this.addEventListener("keypress", this);
|
||||
this.addEventListener("keydown", this);
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "keyup":
|
||||
this.#handleKeyboard(event);
|
||||
this.#closeByKeyboard(event);
|
||||
break;
|
||||
case "keypress":
|
||||
case "keydown":
|
||||
this.#handleKeyboard(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#handleItemChange = event => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<global-search-bar data-l10n-id="search-bar-item"
|
||||
data-l10n-attrs="label"
|
||||
aria-keyshortcuts="Control+K">
|
||||
<span slot="placeholder" data-l10n-id="search-bar-placeholder-with-key2"></span>
|
||||
<span slot="placeholder" data-l10n-id="search-bar-placeholder-with-key2" class="kbd-container"></span>
|
||||
<img data-l10n-id="search-bar-button"
|
||||
slot="button"
|
||||
class="search-button-icon"
|
||||
|
|
|
@ -3,15 +3,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include ./unifiedToolbarCustomizableItems.inc.xhtml
|
||||
|
||||
<html:template id="searchBarTemplate"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
<form>
|
||||
<input type="search" placeholder="" required="required" />
|
||||
<div aria-hidden="true"><slot name="placeholder"></slot></div>
|
||||
<button class="button button-flat icon-button"><slot name="button"></slot></button>
|
||||
</form>
|
||||
</html:template>
|
||||
#include ../../../base/content/widgets/search-bar.inc.xhtml
|
||||
|
||||
<html:template id="unifiedToolbarTemplate">
|
||||
# Required for placing the window controls in the proper place without having
|
||||
|
|
|
@ -20,7 +20,6 @@ messenger.jar:
|
|||
content/messenger/unifiedtoolbar/extension-action-button.mjs (content/extension-action-button.mjs)
|
||||
content/messenger/unifiedtoolbar/list-box-selection.mjs (content/list-box-selection.mjs)
|
||||
content/messenger/unifiedtoolbar/mail-tab-button.mjs (content/mail-tab-button.mjs)
|
||||
content/messenger/unifiedtoolbar/search-bar.mjs (content/search-bar.mjs)
|
||||
content/messenger/unifiedtoolbar/unified-toolbar.mjs (content/unified-toolbar.mjs)
|
||||
content/messenger/unifiedtoolbar/unified-toolbar-button.mjs (content/unified-toolbar-button.mjs)
|
||||
content/messenger/unifiedtoolbar/unified-toolbar-customization.mjs (content/unified-toolbar-customization.mjs)
|
||||
|
|
|
@ -11,7 +11,6 @@ subsuite = thunderbird
|
|||
support-files = files/**
|
||||
|
||||
[browser_customizableItems.js]
|
||||
[browser_searchBar.js]
|
||||
[browser_toolbarMigration.js]
|
||||
[browser_unifiedToolbar.js]
|
||||
[browser_unifiedToolbarCustomization.js]
|
||||
|
|
|
@ -122,20 +122,26 @@ quick-filter-bar-results =
|
|||
*[other] { $count } messages
|
||||
}
|
||||
|
||||
quick-filter-bar-search =
|
||||
.label = Filter messages:
|
||||
|
||||
# Keyboard shortcut for the text search box.
|
||||
# This should match quick-filter-bar-show in messenger.ftl.
|
||||
quick-filter-bar-textbox-shortcut =
|
||||
{ PLATFORM() ->
|
||||
[macos] ⇧ ⌘ K
|
||||
*[other] Ctrl+Shift+K
|
||||
}
|
||||
quick-filter-bar-search-shortcut = {
|
||||
PLATFORM() ->
|
||||
[macos] <kbd>⇧</kbd> <kbd>⌘</kbd> <kbd>K</kbd>
|
||||
*[other] <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd>
|
||||
}
|
||||
|
||||
# This is the empty text for the text search box.
|
||||
# The goal is to convey to the user that typing in the box will filter
|
||||
# the messages and that there is a hotkey they can press to get to the
|
||||
# box faster.
|
||||
quick-filter-bar-textbox =
|
||||
.placeholder = Filter these messages <{ quick-filter-bar-textbox-shortcut }>
|
||||
# The goal is to convey to the user that typing in the box will filter the
|
||||
# messages and that there is a hotkey they can press to get to the box faster.
|
||||
quick-filter-bar-search-placeholder-with-key = Filter messages… { quick-filter-bar-search-shortcut }
|
||||
|
||||
# Label of the search button in the quick filter bar text box. Clicking it will
|
||||
# launch a global search.
|
||||
quick-filter-bar-search-button =
|
||||
.alt = Search everywhere
|
||||
|
||||
# Tooltip of the Any-of/All-of tagging mode selector.
|
||||
quick-filter-bar-boolean-mode =
|
||||
|
|
|
@ -466,7 +466,7 @@ quick-filter-bar-toggle =
|
|||
.accesskey = Q
|
||||
|
||||
# This is the key used to show the quick filter bar.
|
||||
# This should match quick-filter-bar-textbox-shortcut in about3Pane.ftl.
|
||||
# This should match quick-filter-bar-search-shortcut in about3Pane.ftl.
|
||||
quick-filter-bar-show =
|
||||
.key = k
|
||||
|
||||
|
|
|
@ -1169,24 +1169,24 @@ var MessageTextFilter = {
|
|||
},
|
||||
|
||||
onCommand(aState, aNode, aEvent, aDocument) {
|
||||
let text = aNode.value.length ? aNode.value : null;
|
||||
if (text == aState.text) {
|
||||
let text = aEvent.detail || null;
|
||||
const isSearch = aEvent.type === "search";
|
||||
if (isSearch) {
|
||||
let upsell = aDocument.getElementById("qfb-text-search-upsell");
|
||||
if (upsell.state == "open") {
|
||||
upsell.hidePopup();
|
||||
let tabmail =
|
||||
aDocument.ownerGlobal.top.document.getElementById("tabmail");
|
||||
tabmail.openTab("glodaFacet", {
|
||||
searcher: new lazy.GlodaMsgSearcher(null, aState.text),
|
||||
});
|
||||
}
|
||||
return [aState, false];
|
||||
let tabmail =
|
||||
aDocument.ownerGlobal.top.document.getElementById("tabmail");
|
||||
tabmail.openTab("glodaFacet", {
|
||||
searcher: new lazy.GlodaMsgSearcher(null, aState.text),
|
||||
});
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
|
||||
aState.text = text;
|
||||
aDocument.getElementById("quick-filter-bar-filter-text-bar").hidden =
|
||||
text == null;
|
||||
return [aState, true];
|
||||
aDocument.getElementById("quick-filter-bar-filter-text-bar").hidden = !text;
|
||||
return [aState, !isSearch];
|
||||
},
|
||||
|
||||
reflectInDOM(aNode, aFilterValue, aDocument, aMuxer, aFromPFP) {
|
||||
|
@ -1228,11 +1228,10 @@ var MessageTextFilter = {
|
|||
panel.hidePopup();
|
||||
}
|
||||
|
||||
// Update the text if it has changed (linux does weird things with empty
|
||||
// text if we're transitioning emptytext to emptytext).
|
||||
// Propagate a cleared text filter to the search bar input.
|
||||
let desiredValue = aFilterValue.text || "";
|
||||
if (aNode.value != desiredValue && aNode != aMuxer.activeElement) {
|
||||
aNode.value = desiredValue;
|
||||
if (!desiredValue) {
|
||||
aNode.reset();
|
||||
}
|
||||
|
||||
// Update our expanded filters buttons.
|
||||
|
|
|
@ -134,7 +134,6 @@ add_task(async function test_escape_rules() {
|
|||
add_task(async function test_control_shift_k_shows_quick_filter_bar() {
|
||||
let about3Pane = get_about_3pane();
|
||||
|
||||
let dispatcha = document.commandDispatcher;
|
||||
let qfbTextbox = about3Pane.document.getElementById("qfb-qs-textbox");
|
||||
|
||||
// focus explicitly on the thread pane so we know where the focus is.
|
||||
|
@ -144,37 +143,42 @@ add_task(async function test_control_shift_k_shows_quick_filter_bar() {
|
|||
|
||||
// hit control-shift-k to get in the quick filter box
|
||||
EventUtils.synthesizeKey("k", { accelKey: true, shiftKey: true });
|
||||
if (dispatcha.focusedElement != qfbTextbox.inputField) {
|
||||
throw new Error("control-shift-k did not focus quick filter textbox");
|
||||
}
|
||||
Assert.strictEqual(
|
||||
about3Pane.document.activeElement,
|
||||
qfbTextbox,
|
||||
"control-shift-k did not focus quick filter textbox"
|
||||
);
|
||||
|
||||
await set_filter_text("search string");
|
||||
|
||||
// hit control-shift-k to select the text in the quick filter box
|
||||
EventUtils.synthesizeKey("k", { accelKey: true, shiftKey: true });
|
||||
if (dispatcha.focusedElement != qfbTextbox.inputField) {
|
||||
throw new Error(
|
||||
"second control-shift-k did not keep focus on filter textbox"
|
||||
);
|
||||
}
|
||||
if (
|
||||
qfbTextbox.inputField.selectionStart != 0 ||
|
||||
qfbTextbox.inputField.selectionEnd != qfbTextbox.inputField.textLength
|
||||
) {
|
||||
throw new Error(
|
||||
"second control-shift-k did not select text in filter textbox"
|
||||
);
|
||||
}
|
||||
Assert.strictEqual(
|
||||
about3Pane.document.activeElement,
|
||||
qfbTextbox,
|
||||
"second control-shift-k did not keep focus on filter textbox"
|
||||
);
|
||||
const input = qfbTextbox.shadowRoot.querySelector("input");
|
||||
Assert.equal(
|
||||
input.selectionStart,
|
||||
0,
|
||||
"Selection starts at the beginning of the input"
|
||||
);
|
||||
Assert.equal(
|
||||
input.selectionEnd,
|
||||
"search string".length,
|
||||
"Selection ends at the end of the input"
|
||||
);
|
||||
|
||||
// hit escape and make sure the text is cleared, but the quick filter bar is
|
||||
// still open.
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
EventUtils.synthesizeKey("KEY_Escape", {});
|
||||
assert_quick_filter_bar_visible(true);
|
||||
assert_filter_text("");
|
||||
|
||||
// hit escape one more time and make sure we finally collapsed the quick
|
||||
// filter bar.
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
EventUtils.synthesizeKey("KEY_Escape", {});
|
||||
assert_quick_filter_bar_visible(false);
|
||||
teardownTest();
|
||||
});
|
||||
|
|
|
@ -333,14 +333,18 @@ function assert_text_constraints_checked(...aArgs) {
|
|||
async function set_filter_text(aText) {
|
||||
// We're not testing the reliability of the textbox widget; just poke our text
|
||||
// in and trigger the command logic.
|
||||
let textbox = about3Pane.document.getElementById("qfb-qs-textbox");
|
||||
let textbox = about3Pane.document
|
||||
.getElementById("qfb-qs-textbox")
|
||||
.shadowRoot.querySelector("input");
|
||||
textbox.value = aText;
|
||||
textbox.doCommand();
|
||||
textbox.dispatchEvent(new Event("input"));
|
||||
await wait_for_all_messages_to_load(mc);
|
||||
}
|
||||
|
||||
function assert_filter_text(aText) {
|
||||
let textbox = get_about_3pane().document.getElementById("qfb-qs-textbox");
|
||||
let textbox = get_about_3pane()
|
||||
.document.getElementById("qfb-qs-textbox")
|
||||
.shadowRoot.querySelector("input");
|
||||
if (textbox.value != aText) {
|
||||
throw new Error(
|
||||
"Expected text filter value of '" +
|
||||
|
|
|
@ -61,12 +61,14 @@
|
|||
|
||||
#qfb-qs-textbox {
|
||||
flex: 1;
|
||||
height: unset;
|
||||
margin: 3px;
|
||||
padding-block: 3px;
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.qfb-search-button-icon {
|
||||
content: var(--icon-search);
|
||||
}
|
||||
|
||||
@container threadPane (max-width: 499px) {
|
||||
#qfb-qs-textbox {
|
||||
min-width: 200px;
|
||||
|
|
|
@ -12,7 +12,6 @@ form {
|
|||
position: relative;
|
||||
min-height: max(1.2em, calc(1.2em + 2 * var(--padding-block)));
|
||||
height: 100%;
|
||||
max-height: 2em;
|
||||
}
|
||||
|
||||
input {
|
||||
|
|
|
@ -167,23 +167,6 @@ global-search-bar:not([hidden]):-moz-lwtheme {
|
|||
text-shadow: none;
|
||||
}
|
||||
|
||||
kbd {
|
||||
background-color: var(--layout-background-3);
|
||||
color: var(--layout-color-2);
|
||||
text-transform: uppercase;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
box-shadow: inset 0px -1px 0px var(--layout-border-2);
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
kbd:first-of-type {
|
||||
margin-inline-start: 6px;
|
||||
}
|
||||
|
||||
span[slot="placeholder"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -396,3 +396,20 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kbd-container kbd {
|
||||
background-color: var(--layout-background-3);
|
||||
color: var(--layout-color-2);
|
||||
text-transform: uppercase;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
box-shadow: inset 0px -1px 0px var(--layout-border-2);
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
padding: 2px 4px;
|
||||
|
||||
&:first-of-type {
|
||||
margin-inline-start: 6px;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче