зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset c5798de806e2 (bug 1521280) for crashing when searching about:config for upcoming beta (bug 1551013)
--HG-- extra : rebase_source : 8f936159c23d09bf227ce4f5eb6f2d96d33bbff1
This commit is contained in:
Родитель
66831165d4
Коммит
cc280c4be9
|
@ -112,9 +112,9 @@
|
|||
<textbox id="readonly_textbox" readonly="true"/>
|
||||
<textbox id="disabled_textbox" disabled="true"/>
|
||||
|
||||
<textbox id="searchbox" flex="1" is="search-textbox" results="historyTree"/>
|
||||
<textbox id="searchbox" flex="1" type="search" results="historyTree"/>
|
||||
<textbox id="searchfield" placeholder="Search all add-ons"
|
||||
is="search-textbox" searchbutton="true"/>
|
||||
type="search" searchbutton="true"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</window>
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
accTree =
|
||||
{ SECTION: [
|
||||
{ ENTRY: [ { TEXT_LEAF: [] } ] },
|
||||
{ MENUPOPUP: [] }
|
||||
] };
|
||||
testAccessibleTree("txc_search", accTree);
|
||||
|
||||
|
@ -52,12 +53,14 @@
|
|||
accTree =
|
||||
{ SECTION: [
|
||||
{ ENTRY: [ { TEXT_LEAF: [] } ] },
|
||||
{ MENUPOPUP: [] }
|
||||
] };
|
||||
} else {
|
||||
accTree =
|
||||
{ SECTION: [
|
||||
{ ENTRY: [ { TEXT_LEAF: [] } ] },
|
||||
{ PUSHBUTTON: [] },
|
||||
{ MENUPOPUP: [] }
|
||||
] };
|
||||
}
|
||||
|
||||
|
@ -153,8 +156,8 @@
|
|||
|
||||
<vbox flex="1">
|
||||
<textbox id="txc" value="hello"/>
|
||||
<textbox id="txc_search" is="search-textbox" value="hello"/>
|
||||
<textbox id="txc_search_searchbutton" searchbutton="true" is="search-textbox" value="hello"/>
|
||||
<textbox id="txc_search" type="search" value="hello"/>
|
||||
<textbox id="txc_search_searchbutton" searchbutton="true" type="search" value="hello"/>
|
||||
<textbox id="txc_number" type="number" value="44"/>
|
||||
<textbox id="txc_password" type="password" value="hello"/>
|
||||
<textbox id="txc_autocomplete" type="autocomplete" value="hello"/>
|
||||
|
|
|
@ -640,7 +640,7 @@ async function performSelectSearchTests(win) {
|
|||
let selectPopup = win.document.getElementById("ContentSelectDropdown").menupopup;
|
||||
await openSelectPopup(selectPopup, false, "select", win);
|
||||
|
||||
let searchElement = selectPopup.querySelector(".contentSelectDropdown-searchbox");
|
||||
let searchElement = selectPopup.querySelector("textbox");
|
||||
searchElement.focus();
|
||||
|
||||
EventUtils.synthesizeKey("O", {}, win);
|
||||
|
|
|
@ -28,9 +28,9 @@ add_task(async function test_focus_on_search_shouldnt_close_popup() {
|
|||
await BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
|
||||
await popupShownPromise;
|
||||
|
||||
let searchInput = selectPopup.querySelector(".contentSelectDropdown-searchbox");
|
||||
let searchInput = selectPopup.querySelector("textbox[type='search']");
|
||||
searchInput.scrollIntoView();
|
||||
let searchFocused = BrowserTestUtils.waitForEvent(searchInput, "focus", true);
|
||||
let searchFocused = BrowserTestUtils.waitForEvent(searchInput, "focus");
|
||||
await EventUtils.synthesizeMouseAtCenter(searchInput, {}, window);
|
||||
await searchFocused;
|
||||
|
||||
|
@ -39,3 +39,4 @@ add_task(async function test_focus_on_search_shouldnt_close_popup() {
|
|||
await hideSelectPopup(selectPopup, "escape");
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include bookmarksHistoryTooltip.inc.xul
|
||||
|
||||
<hbox id="sidebar-search-container" align="center">
|
||||
<textbox id="search-box" flex="1" is="search-textbox"
|
||||
<textbox id="search-box" flex="1" type="search"
|
||||
placeholder="&bookmarksSearch.placeholder;"
|
||||
aria-controls="bookmarks-view"
|
||||
oncommand="searchBookmarks(this.value);"/>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include bookmarksHistoryTooltip.inc.xul
|
||||
|
||||
<hbox id="sidebar-search-container">
|
||||
<textbox id="search-box" flex="1" is="search-textbox"
|
||||
<textbox id="search-box" flex="1" type="search"
|
||||
placeholder="&historySearch.placeholder;"
|
||||
aria-controls="historyTree"
|
||||
oncommand="searchHistory(this.value);"/>
|
||||
|
|
|
@ -333,7 +333,7 @@
|
|||
|
||||
<textbox id="searchFilter"
|
||||
flex="1"
|
||||
is="search-textbox"
|
||||
type="search"
|
||||
aria-controls="placeContent"
|
||||
oncommand="PlacesSearchBox.search(this.value);"
|
||||
collection="bookmarks">
|
||||
|
|
|
@ -383,7 +383,7 @@
|
|||
<label><html:h2 data-l10n-id="applications-header"/></label>
|
||||
<description data-l10n-id="applications-description"/>
|
||||
<textbox id="filter" flex="1"
|
||||
is="search-textbox"
|
||||
type="search"
|
||||
data-l10n-id="applications-filter"
|
||||
aria-controls="handlersView"/>
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
</hbox>
|
||||
</hbox>
|
||||
<textbox
|
||||
is="search-textbox" id="searchInput"
|
||||
type="search" id="searchInput"
|
||||
data-l10n-id="search-input-box"
|
||||
data-l10n-attrs="style"
|
||||
hidden="true" clickSelectsAll="true"/>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<separator class="thin"/>
|
||||
|
||||
<hbox id="searchBoxContainer">
|
||||
<textbox id="searchBox" is="search-textbox" flex="1"
|
||||
<textbox id="searchBox" type="search" flex="1"
|
||||
data-l10n-id="site-data-search-textbox"/>
|
||||
</hbox>
|
||||
<separator class="thin"/>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<separator class="thin"/>
|
||||
<hbox align="start">
|
||||
<textbox id="searchBox" flex="1" data-l10n-id="permissions-searchbox"
|
||||
is="search-textbox" oncommand="gSitePermissionsManager.buildPermissionsList();"/>
|
||||
type="search" oncommand="gSitePermissionsManager.buildPermissionsList();"/>
|
||||
</hbox>
|
||||
<separator class="thin"/>
|
||||
<listheader>
|
||||
|
|
|
@ -7,6 +7,6 @@
|
|||
|
||||
<script type="text/javascript" src="platform.js"/>
|
||||
|
||||
<textbox is="search-textbox"/>
|
||||
<textbox type="search"/>
|
||||
|
||||
</window>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<window title="mirrored searchfield"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<hbox>
|
||||
<textbox is="search-textbox" width="200" id="searchbox" style="-moz-transform: scaleX(-1);"/>
|
||||
<textbox type="search" width="200" id="searchbox" style="-moz-transform: scaleX(-1);"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
</window>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<window title="RTL searchfield"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<hbox>
|
||||
<textbox is="search-textbox" width="200" id="searchbox" style="direction: rtl;"/>
|
||||
<textbox type="search" width="200" id="searchbox" style="direction: rtl;"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
</window>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<vbox id="savedsignons" class="contentPane" flex="1">
|
||||
<!-- filter -->
|
||||
<hbox align="center">
|
||||
<textbox id="filter" flex="1" is="search-textbox"
|
||||
<textbox id="filter" flex="1" type="search"
|
||||
aria-controls="signonsTree"
|
||||
oncommand="FilterPasswords();"
|
||||
data-l10n-id="search-filter"/>
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<vbox flex="1">
|
||||
<hbox id="filterRow" align="center">
|
||||
<label data-l10n-id="config-search-prefs" control="textbox"/>
|
||||
<textbox id="textbox" flex="1" is="search-textbox"
|
||||
<textbox id="textbox" flex="1" type="search"
|
||||
aria-controls="configTree"
|
||||
oncommand="FilterPrefs();"/>
|
||||
</hbox>
|
||||
|
|
|
@ -668,7 +668,6 @@ if (!isDummyDocument) {
|
|||
for (let [tag, script] of [
|
||||
["findbar", "chrome://global/content/elements/findbar.js"],
|
||||
["menulist", "chrome://global/content/elements/menulist.js"],
|
||||
["search-textbox", "chrome://global/content/elements/search-textbox.js"],
|
||||
["stringbundle", "chrome://global/content/elements/stringbundle.js"],
|
||||
["printpreview-toolbar", "chrome://global/content/printPreviewToolbar.js"],
|
||||
["editor", "chrome://global/content/elements/editor.js"],
|
||||
|
|
|
@ -60,13 +60,12 @@ window.addEventListener("DOMContentLoaded", () => {
|
|||
|
||||
// Support context menus on html textareas in the parent process:
|
||||
window.addEventListener("contextmenu", (e) => {
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
// Note that there's not a risk of e.target being XBL anonymous content for <textbox> (which manages
|
||||
// its own context menu), because e.target will be the XBL binding parent in that case.
|
||||
let needsContextMenu = e.target.ownerDocument == document && !e.defaultPrevented && (
|
||||
(e.target.localName == "textarea" && e.target.namespaceURI == HTML_NS)
|
||||
|| e.target.closest("textbox[is='search-textbox']")
|
||||
);
|
||||
let needsContextMenu = e.target.ownerDocument == document &&
|
||||
!e.defaultPrevented &&
|
||||
e.target.localName == "textarea" &&
|
||||
e.target.namespaceURI == "http://www.w3.org/1999/xhtml";
|
||||
|
||||
if (!needsContextMenu) {
|
||||
return;
|
||||
|
|
|
@ -98,7 +98,6 @@ toolkit.jar:
|
|||
content/global/elements/marquee.js (widgets/marquee.js)
|
||||
content/global/elements/menulist.js (widgets/menulist.js)
|
||||
content/global/elements/popupnotification.js (widgets/popupnotification.js)
|
||||
content/global/elements/search-textbox.js (widgets/search-textbox.js)
|
||||
content/global/elements/stringbundle.js (widgets/stringbundle.js)
|
||||
content/global/elements/tabbox.js (widgets/tabbox.js)
|
||||
content/global/elements/text.js (widgets/text.js)
|
||||
|
|
|
@ -25,6 +25,4 @@
|
|||
|
||||
<html:textarea />
|
||||
|
||||
<textbox is="search-textbox"/>
|
||||
|
||||
</window>
|
||||
|
|
|
@ -19,25 +19,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1513343
|
|||
await new Promise(r => win.addEventListener("load", r, { once: true}));
|
||||
await SimpleTest.promiseFocus(win);
|
||||
|
||||
const elements = [
|
||||
win.document.querySelector("textarea"),
|
||||
win.document.querySelector("textbox[is='search-textbox']"),
|
||||
];
|
||||
for (const element of elements) {
|
||||
await testElement(element, win);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
async function testElement(element, win) {
|
||||
ok(element, "element exists");
|
||||
let textarea = win.document.querySelector("textarea");
|
||||
ok(textarea, "textarea exists");
|
||||
|
||||
info("Synthesizing a key so 'Undo' will be enabled");
|
||||
element.focus();
|
||||
textarea.focus();
|
||||
synthesizeKey("x", {}, win);
|
||||
is(element.value, "x", "initial value");
|
||||
is(textarea.value, "x", "initial value");
|
||||
|
||||
element.select();
|
||||
textarea.select();
|
||||
synthesizeKey("c", { accelKey: true }, win); // copy to clipboard
|
||||
synthesizeKey("KEY_ArrowRight", {}, win); // drop selection to disable cut and copy context menu items
|
||||
|
||||
|
@ -45,11 +35,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1513343
|
|||
info("Calling prevent default on the first contextmenu event");
|
||||
e.preventDefault();
|
||||
}, { once: true });
|
||||
synthesizeMouseAtCenter(element, {type: "contextmenu"}, win);
|
||||
synthesizeMouseAtCenter(textarea, {type: "contextmenu"}, win);
|
||||
ok(!win.document.getElementById("textbox-contextmenu"), "contextmenu with preventDefault() doesn't run");
|
||||
|
||||
let popupshown = new Promise(r => win.addEventListener("popupshown", r, { once: true }));
|
||||
synthesizeMouseAtCenter(element, {type: "contextmenu"}, win);
|
||||
synthesizeMouseAtCenter(textarea, {type: "contextmenu"}, win);
|
||||
let contextmenu = win.document.getElementById("textbox-contextmenu");
|
||||
ok(contextmenu, "context menu exists after right click");
|
||||
await popupshown;
|
||||
|
@ -62,14 +52,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1513343
|
|||
ok(!contextmenu.querySelector("[command=cmd_selectAll]").hasAttribute("disabled"), "select all enabled");
|
||||
|
||||
contextmenu.querySelector("[command=cmd_undo]").click();
|
||||
is(element.value, "", "undo worked");
|
||||
is(textarea.value, "", "undo worked");
|
||||
|
||||
// Close the context menu to avoid affecting next test
|
||||
let popuphidden = new Promise(r => win.addEventListener("popuphidden", r, { once: true }));
|
||||
contextmenu.hidePopup();
|
||||
await popuphidden;
|
||||
contextmenu.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest()">
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<hbox>
|
||||
<textbox id="searchbox"
|
||||
is="search-textbox"
|
||||
type="search"
|
||||
oncommand="doSearch(this.value);"
|
||||
placeholder="random placeholder"
|
||||
timeout="1"/>
|
||||
|
@ -30,9 +30,9 @@ var gLastTest;
|
|||
|
||||
function doTests() {
|
||||
var textbox = $("searchbox");
|
||||
var icons = textbox.querySelector(".textbox-search-icons");
|
||||
var searchIcon = icons.querySelector(".textbox-search-icon");
|
||||
var clearIcon = icons.querySelector(".textbox-search-clear");
|
||||
var icons = document.getAnonymousElementByAttribute(textbox, "anonid", "search-icons");
|
||||
var searchIcon = document.getAnonymousElementByAttribute(textbox, "class", "textbox-search-icon");
|
||||
var clearIcon = document.getAnonymousElementByAttribute(textbox, "class", "textbox-search-clear");
|
||||
|
||||
ok(icons, "icon deck found");
|
||||
ok(searchIcon, "search icon found");
|
||||
|
|
|
@ -1,225 +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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// This is loaded into all XUL windows. Wrap in a block to prevent
|
||||
// leaking to window scope.
|
||||
{
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
class MozSearchTextbox extends MozXULElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.inputField = document.createElementNS(HTML_NS, "input");
|
||||
|
||||
const METHODS = ["focus", "blur", "select", "setUserInput", "setSelectionRange"];
|
||||
for (const method of METHODS) {
|
||||
this[method] = (...args) => this.inputField[method](...args);
|
||||
}
|
||||
|
||||
const READ_WRITE_PROPERTIES = ["defaultValue", "placeholder", "readOnly",
|
||||
"size", "selectionStart", "selectionEnd"];
|
||||
for (const property of READ_WRITE_PROPERTIES) {
|
||||
Object.defineProperty(this, property, {
|
||||
enumerable: true,
|
||||
get() {
|
||||
return this.inputField[property];
|
||||
},
|
||||
set(val) {
|
||||
return this.inputField[property] = val;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.addEventListener("input", (event) => {
|
||||
if (this.searchButton) {
|
||||
this._searchIcons.selectedIndex = 0;
|
||||
return;
|
||||
}
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this);
|
||||
this._searchIcons.selectedIndex = this.value ? 1 : 0;
|
||||
});
|
||||
|
||||
this.addEventListener("keypress", (event) => {
|
||||
switch (event.keyCode) {
|
||||
case KeyEvent.DOM_VK_ESCAPE:
|
||||
if (this._clearSearch()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
break;
|
||||
case KeyEvent.DOM_VK_RETURN:
|
||||
this._enterSearch();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static get inheritedAttributes() {
|
||||
return {
|
||||
".textbox-input": "value,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint,spellcheck",
|
||||
".textbox-search-icon": "src=image,label=searchbuttonlabel,searchbutton,disabled",
|
||||
".textbox-search-clear": "disabled",
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (this.delayConnectedCallback()) {
|
||||
return;
|
||||
}
|
||||
this.textContent = "";
|
||||
|
||||
const textboxSign = document.createXULElement("image");
|
||||
textboxSign.className = "textbox-search-sign";
|
||||
|
||||
const input = this.inputField;
|
||||
input.className = "textbox-input";
|
||||
input.setAttribute("mozactionhint", "search");
|
||||
input.addEventListener("focus", () => this.setAttribute("focused", "true"));
|
||||
input.addEventListener("blur", () => this.removeAttribute("focused"));
|
||||
|
||||
const searchBtn = this._searchButtonIcon = document.createXULElement("image");
|
||||
searchBtn.className = "textbox-search-icon";
|
||||
searchBtn.addEventListener("click", (e) => this._iconClick(e));
|
||||
|
||||
// TODO: Bug 1534799 - Convert string to Fluent and use manual DOM construction
|
||||
let clearBtn = MozXULElement.parseXULToFragment(`
|
||||
<image class="textbox-search-clear" label="&searchTextBox.clear.label;"/>
|
||||
`, ["chrome://global/locale/textcontext.dtd"]);
|
||||
clearBtn = this._searchClearIcon = clearBtn.querySelector(".textbox-search-clear");
|
||||
clearBtn.addEventListener("click", () => this._clearSearch());
|
||||
|
||||
const deck = this._searchIcons = document.createXULElement("deck");
|
||||
deck.className = "textbox-search-icons";
|
||||
deck.append(searchBtn, clearBtn);
|
||||
this.append(textboxSign, input, deck);
|
||||
|
||||
this._timer = null;
|
||||
|
||||
// Ensure the button state is up to date:
|
||||
this.searchButton = this.searchButton;
|
||||
|
||||
// Set is attribute for styling
|
||||
this.setAttribute("is", "search-textbox");
|
||||
|
||||
this.initializeAttributeInheritance();
|
||||
}
|
||||
|
||||
set timeout(val) {
|
||||
this.setAttribute("timeout", val);
|
||||
return val;
|
||||
}
|
||||
|
||||
get timeout() {
|
||||
return parseInt(this.getAttribute("timeout")) || 500;
|
||||
}
|
||||
|
||||
set searchButton(val) {
|
||||
if (val) {
|
||||
this.setAttribute("searchbutton", "true");
|
||||
this.removeAttribute("aria-autocomplete");
|
||||
// Hack for the button to get the right accessible:
|
||||
this._searchButtonIcon.setAttribute("onclick", "true");
|
||||
} else {
|
||||
this.removeAttribute("searchbutton");
|
||||
this._searchButtonIcon.removeAttribute("onclick");
|
||||
this.setAttribute("aria-autocomplete", "list");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
get searchButton() {
|
||||
return this.getAttribute("searchbutton") == "true";
|
||||
}
|
||||
|
||||
set value(val) {
|
||||
this.inputField.value = val;
|
||||
|
||||
if (val) {
|
||||
this._searchIcons.selectedIndex = this.searchButton ? 0 : 1;
|
||||
} else {
|
||||
this._searchIcons.selectedIndex = 0;
|
||||
}
|
||||
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this.inputField.value;
|
||||
}
|
||||
|
||||
get editor() {
|
||||
return this.inputField.editor;
|
||||
}
|
||||
|
||||
set disabled(val) {
|
||||
this.inputField.disabled = val;
|
||||
if (val) this.setAttribute("disabled", "true");
|
||||
else this.removeAttribute("disabled");
|
||||
return val;
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return this.inputField.disabled;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.value = this.defaultValue;
|
||||
// XXX: Is this still needed ?
|
||||
try {
|
||||
this.editor.transactionManager.clear();
|
||||
return true;
|
||||
} catch (e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
_fireCommand(me) {
|
||||
if (me._timer) {
|
||||
clearTimeout(me._timer);
|
||||
}
|
||||
me._timer = null;
|
||||
me.doCommand();
|
||||
}
|
||||
|
||||
_iconClick() {
|
||||
if (this.searchButton) {
|
||||
this._enterSearch();
|
||||
} else {
|
||||
this.focus();
|
||||
}
|
||||
}
|
||||
|
||||
_enterSearch() {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
if (this.searchButton && this.value && !this.readOnly) {
|
||||
this._searchIcons.selectedIndex = 1;
|
||||
}
|
||||
this._fireCommand(this);
|
||||
}
|
||||
|
||||
_clearSearch() {
|
||||
if (!this.disabled && !this.readOnly && this.value) {
|
||||
this.value = "";
|
||||
this._fireCommand(this);
|
||||
this._searchIcons.selectedIndex = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("search-textbox", MozSearchTextbox, { extends: "textbox" });
|
||||
}
|
|
@ -261,4 +261,138 @@
|
|||
#endif
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="search-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
|
||||
<content>
|
||||
<children/>
|
||||
<xul:moz-input-box anonid="moz-input-box" flex="1" xbl:inherits="context,spellcheck" align="center">
|
||||
<xul:image class="textbox-search-sign"/>
|
||||
<html:input class="textbox-input" anonid="input" mozactionhint="search"
|
||||
xbl:inherits="value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint,spellcheck"/>
|
||||
<xul:deck class="textbox-search-icons" anonid="search-icons">
|
||||
<xul:image class="textbox-search-icon" anonid="searchbutton-icon"
|
||||
xbl:inherits="src=image,label=searchbuttonlabel,searchbutton,disabled"/>
|
||||
<xul:image class="textbox-search-clear"
|
||||
onclick="document.getBindingParent(this)._clearSearch();"
|
||||
label="&searchTextBox.clear.label;"
|
||||
xbl:inherits="disabled"/>
|
||||
</xul:deck>
|
||||
</xul:moz-input-box>
|
||||
</content>
|
||||
<implementation>
|
||||
<field name="_timer">null</field>
|
||||
<field name="_searchIcons">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "search-icons");
|
||||
</field>
|
||||
<field name="_searchButtonIcon">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "searchbutton-icon");
|
||||
</field>
|
||||
<property name="timeout"
|
||||
onset="this.setAttribute('timeout', val); return val;"
|
||||
onget="return parseInt(this.getAttribute('timeout')) || 500;"/>
|
||||
<property name="searchButton"
|
||||
onget="return this.getAttribute('searchbutton') == 'true';">
|
||||
<setter><![CDATA[
|
||||
if (val) {
|
||||
this.setAttribute("searchbutton", "true");
|
||||
this.removeAttribute("aria-autocomplete");
|
||||
// Hack for the button to get the right accessible:
|
||||
this._searchButtonIcon.setAttribute("onclick", "true");
|
||||
} else {
|
||||
this.removeAttribute("searchbutton");
|
||||
this._searchButtonIcon.removeAttribute("onclick");
|
||||
this.setAttribute("aria-autocomplete", "list");
|
||||
}
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
<property name="value"
|
||||
onget="return this.inputField.value;">
|
||||
<setter><![CDATA[
|
||||
this.inputField.value = val;
|
||||
|
||||
if (val)
|
||||
this._searchIcons.selectedIndex = this.searchButton ? 0 : 1;
|
||||
else
|
||||
this._searchIcons.selectedIndex = 0;
|
||||
|
||||
if (this._timer)
|
||||
clearTimeout(this._timer);
|
||||
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
<constructor><![CDATA[
|
||||
// Ensure the button state is up to date:
|
||||
this.searchButton = this.searchButton;
|
||||
this._searchButtonIcon.addEventListener("click", (e) => this._iconClick(e));
|
||||
]]></constructor>
|
||||
<method name="_fireCommand">
|
||||
<parameter name="me"/>
|
||||
<body><![CDATA[
|
||||
if (me._timer)
|
||||
clearTimeout(me._timer);
|
||||
me._timer = null;
|
||||
me.doCommand();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_iconClick">
|
||||
<body><![CDATA[
|
||||
if (this.searchButton)
|
||||
this._enterSearch();
|
||||
else
|
||||
this.focus();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_enterSearch">
|
||||
<body><![CDATA[
|
||||
if (this.disabled)
|
||||
return;
|
||||
if (this.searchButton && this.value && !this.readOnly)
|
||||
this._searchIcons.selectedIndex = 1;
|
||||
this._fireCommand(this);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_clearSearch">
|
||||
<body><![CDATA[
|
||||
if (!this.disabled && !this.readOnly && this.value) {
|
||||
this.value = "";
|
||||
this._fireCommand(this);
|
||||
this._searchIcons.selectedIndex = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
<handlers>
|
||||
<handler event="input">
|
||||
<![CDATA[
|
||||
if (this.searchButton) {
|
||||
this._searchIcons.selectedIndex = 0;
|
||||
return;
|
||||
}
|
||||
if (this._timer)
|
||||
clearTimeout(this._timer);
|
||||
this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this);
|
||||
this._searchIcons.selectedIndex = this.value ? 1 : 0;
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="keypress" keycode="VK_ESCAPE">
|
||||
<![CDATA[
|
||||
if (this._clearSearch()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="keypress" keycode="VK_RETURN">
|
||||
<![CDATA[
|
||||
this._enterSearch();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
|
|
@ -458,8 +458,8 @@ textbox {
|
|||
text-shadow: none;
|
||||
}
|
||||
|
||||
textbox[is="search-textbox"] {
|
||||
-moz-binding: none;
|
||||
textbox[type="search"] {
|
||||
-moz-binding: url("chrome://global/content/bindings/textbox.xml#search-textbox");
|
||||
}
|
||||
|
||||
/* Prefix with (xul|*):root to workaround HTML tests loading xul.css */
|
||||
|
|
|
@ -436,13 +436,11 @@ function populateChildren(menulist, options, uniqueOptionStyles, selectedIndex,
|
|||
if (Services.prefs.getBoolPref("dom.forms.selectSearch") && addSearch
|
||||
&& element.childElementCount > SEARCH_MINIMUM_ELEMENTS) {
|
||||
// Add a search text field as the first element of the dropdown
|
||||
let searchbox = element.ownerDocument.createXULElement("textbox", {
|
||||
is: "search-textbox",
|
||||
});
|
||||
searchbox.className = "contentSelectDropdown-searchbox";
|
||||
let searchbox = element.ownerDocument.createXULElement("textbox");
|
||||
searchbox.setAttribute("type", "search");
|
||||
searchbox.addEventListener("input", onSearchInput);
|
||||
searchbox.inputField.addEventListener("focus", onSearchFocus);
|
||||
searchbox.inputField.addEventListener("blur", onSearchBlur);
|
||||
searchbox.addEventListener("focus", onSearchFocus);
|
||||
searchbox.addEventListener("blur", onSearchBlur);
|
||||
searchbox.addEventListener("command", onSearchInput);
|
||||
|
||||
// Handle special keys for exiting search
|
||||
|
@ -544,7 +542,7 @@ function onSearchInput() {
|
|||
|
||||
function onSearchFocus() {
|
||||
let searchObj = this;
|
||||
let menupopup = searchObj.closest("menupopup");
|
||||
let menupopup = searchObj.parentElement;
|
||||
menupopup.parentElement.activeChild = null;
|
||||
menupopup.setAttribute("ignorekeys", "true");
|
||||
currentBrowser.messageManager.sendAsyncMessage("Forms:SearchFocused", {});
|
||||
|
@ -552,6 +550,6 @@ function onSearchFocus() {
|
|||
|
||||
function onSearchBlur() {
|
||||
let searchObj = this;
|
||||
let menupopup = searchObj.closest("menupopup");
|
||||
let menupopup = searchObj.parentElement;
|
||||
menupopup.setAttribute("ignorekeys", "false");
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@
|
|||
class="warning" data-l10n-id="show-unsigned-extensions-button"
|
||||
command="cmd_showUnsignedExtensions"/>
|
||||
<label id="search-label" control="header-search"/>
|
||||
<textbox id="header-search" is="search-textbox" searchbutton="true"
|
||||
<textbox id="header-search" type="search" searchbutton="true"
|
||||
data-l10n-id="search-header"
|
||||
data-l10n-attrs="searchbuttonlabel" maxlength="100"/>
|
||||
</hbox>
|
||||
|
|
|
@ -10,9 +10,7 @@ var focusCount = 0;
|
|||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// The discovery pane does not display the about:addons searchbox,
|
||||
// open the extensions pane instead.
|
||||
let aWindow = await open_manager("addons://list/extension");
|
||||
let aWindow = await open_manager(null);
|
||||
gManagerWindow = aWindow;
|
||||
|
||||
var searchBox = gManagerWindow.document.getElementById("header-search");
|
||||
|
@ -20,10 +18,10 @@ async function test() {
|
|||
searchBox.blur();
|
||||
focusCount++;
|
||||
}
|
||||
searchBox.inputField.addEventListener("focus", focusHandler);
|
||||
searchBox.addEventListener("focus", focusHandler);
|
||||
f_key_test();
|
||||
slash_key_test();
|
||||
searchBox.inputField.removeEventListener("focus", focusHandler);
|
||||
searchBox.removeEventListener("focus", focusHandler);
|
||||
end_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ textbox.plain html|*.textbox-input {
|
|||
|
||||
/* ::::: search textbox ::::: */
|
||||
|
||||
textbox:not([searchbutton]) > .textbox-search-sign {
|
||||
textbox:not([searchbutton]) > moz-input-box > .textbox-search-sign {
|
||||
list-style-image: url(chrome://global/skin/icons/search-textbox.svg);
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
|
|
@ -68,13 +68,13 @@ xul|radio[focused="true"] > .radio-check {
|
|||
-moz-outline-radius: 100%;
|
||||
}
|
||||
|
||||
textbox[is="search-textbox"] {
|
||||
textbox[type="search"] {
|
||||
-moz-appearance: none;
|
||||
padding-inline-start: 8px;
|
||||
padding-inline-end: 8px;
|
||||
}
|
||||
|
||||
xul|textbox[is="search-textbox"] > .textbox-search-sign {
|
||||
xul|textbox[type="search"] > moz-input-box > .textbox-search-sign {
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: currentColor;
|
||||
fill-opacity: 0.8;
|
||||
|
|
|
@ -60,7 +60,7 @@ textbox.plain html|*.textbox-input {
|
|||
|
||||
/* ::::: search box ::::: */
|
||||
|
||||
textbox[is="search-textbox"] {
|
||||
textbox[type="search"] {
|
||||
-moz-appearance: searchfield;
|
||||
padding: 1px;
|
||||
font-size: 12px;
|
||||
|
|
|
@ -76,7 +76,7 @@ textbox.plain html|*.textbox-input {
|
|||
|
||||
/* ::::: search textbox ::::: */
|
||||
|
||||
textbox:not([searchbutton]) > .textbox-search-sign {
|
||||
textbox:not([searchbutton]) > moz-input-box > .textbox-search-sign {
|
||||
list-style-image: url(chrome://global/skin/icons/search-textbox.svg);
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче