Bug 1265759 - Create an HTML replacement for inspector Search Box;r=gl

MozReview-Commit-ID: Elt4NGNh3Pf
This commit is contained in:
gasolin 2016-07-27 12:08:01 +08:00
Родитель bf696aae6c
Коммит 40b39ddc7b
12 изменённых файлов: 175 добавлений и 149 удалений

Просмотреть файл

@ -213,7 +213,7 @@ InspectorPanel.prototype = {
this.updateDebuggerPausedWarning = () => {
let notificationBox = this._toolbox.getNotificationBox();
let notification =
notificationBox.getNotificationWithValue("inspector-script-paused");
notificationBox.getNotificationWithValue("inspector-script-paused");
if (!notification && this._toolbox.currentToolId == "inspector" &&
this._toolbox.threadClient.paused) {
let message = strings.GetStringFromName("debuggerPausedWarning.message");
@ -353,9 +353,10 @@ InspectorPanel.prototype = {
*/
setupSearchBox: function () {
this.searchBox = this.panelDoc.getElementById("inspector-searchbox");
this.searchClearButton = this.panelDoc.getElementById("inspector-searchinput-clear");
this.searchResultsLabel = this.panelDoc.getElementById("inspector-searchlabel");
this.search = new InspectorSearch(this, this.searchBox);
this.search = new InspectorSearch(this, this.searchBox, this.searchClearButton);
this.search.on("search-cleared", this._updateSearchResultsLabel);
this.search.on("search-result", this._updateSearchResultsLabel);
@ -1456,7 +1457,8 @@ InspectorPanel.prototype = {
/**
* Paste the contents of the clipboard as adjacent HTML to the selected Node.
* @param position The position as specified for Element.insertAdjacentHTML
* @param position
* The position as specified for Element.insertAdjacentHTML
* (i.e. "beforeBegin", "afterBegin", "beforeEnd", "afterEnd").
*/
pasteAdjacentHTML: function (position) {
@ -1516,8 +1518,8 @@ InspectorPanel.prototype = {
/**
* Copy the content of a longString (via a promise resolving a
* LongStringActor) to the clipboard
* @param {Promise} longStringActorPromise promise expected to
* resolve a LongStringActor instance
* @param {Promise} longStringActorPromise
* promise expected to resolve a LongStringActor instance
* @return {Promise} promise resolving (with no argument) when the
* string is sent to the clipboard
*/
@ -1529,8 +1531,8 @@ InspectorPanel.prototype = {
/**
* Retrieve the content of a longString (via a promise resolving a LongStringActor)
* @param {Promise} longStringActorPromise promise expected to
* resolve a LongStringActor instance
* @param {Promise} longStringActorPromise
* promise expected to resolve a LongStringActor instance
* @return {Promise} promise resolving with the retrieved string as argument
*/
_getLongString: function (longStringActorPromise) {

Просмотреть файл

@ -4,9 +4,6 @@
"use strict";
/* eslint-disable mozilla/reject-some-requires */
const {Ci} = require("chrome");
/* eslint-enable mozilla/reject-some-requires */
const promise = require("promise");
const {Task} = require("devtools/shared/task");
@ -20,24 +17,33 @@ const MAX_SUGGESTIONS = 15;
/**
* Converts any input field into a document search box.
*
* @param {InspectorPanel} inspector The InspectorPanel whose `walker` attribute
* should be used for document traversal.
* @param {DOMNode} input The input element to which the panel will be attached
* and from where search input will be taken.
* @param {InspectorPanel} inspector
* The InspectorPanel whose `walker` attribute should be used for
* document traversal.
* @param {DOMNode} input
* The input element to which the panel will be attached and from where
* search input will be taken.
* @param {DOMNode} clearBtn
* The clear button in the input field that will clear the input value.
*
* Emits the following events:
* - search-cleared: when the search box is emptied
* - search-result: when a search is made and a result is selected
*/
function InspectorSearch(inspector, input) {
function InspectorSearch(inspector, input, clearBtn) {
this.inspector = inspector;
this.searchBox = input;
this.searchClearButton = clearBtn;
this._lastSearched = null;
this.searchClearButton.hidden = true;
this._onKeyDown = this._onKeyDown.bind(this);
this._onCommand = this._onCommand.bind(this);
this._onInput = this._onInput.bind(this);
this._onClearSearch = this._onClearSearch.bind(this);
this.searchBox.addEventListener("keydown", this._onKeyDown, true);
this.searchBox.addEventListener("command", this._onCommand, true);
this.searchBox.addEventListener("input", this._onInput, true);
this.searchClearButton.addEventListener("click", this._onClearSearch);
// For testing, we need to be able to wait for the most recent node request
// to finish. Tests can watch this promise for that.
@ -56,8 +62,10 @@ InspectorSearch.prototype = {
destroy: function () {
this.searchBox.removeEventListener("keydown", this._onKeyDown, true);
this.searchBox.removeEventListener("command", this._onCommand, true);
this.searchBox.removeEventListener("input", this._onInput, true);
this.searchClearButton.removeEventListener("click", this._onClearSearch);
this.searchBox = null;
this.searchClearButton = null;
this.autocompleter.destroy();
},
@ -97,7 +105,7 @@ InspectorSearch.prototype = {
}
}),
_onCommand: function () {
_onInput: function () {
if (this.searchBox.value.length === 0) {
this._onSearch();
}
@ -105,8 +113,10 @@ InspectorSearch.prototype = {
_onKeyDown: function (event) {
if (this.searchBox.value.length === 0) {
this.searchClearButton.hidden = true;
this.searchBox.removeAttribute("filled");
} else {
this.searchClearButton.hidden = false;
this.searchBox.setAttribute("filled", true);
}
if (event.keyCode === event.DOM_VK_RETURN) {
@ -115,10 +125,15 @@ InspectorSearch.prototype = {
const modifierKey = system.constants.platform === "macosx"
? event.metaKey : event.ctrlKey;
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_G && modifierKey) {
if (event.keyCode === event.DOM_VK_G && modifierKey) {
this._onSearch(event.shiftKey);
event.preventDefault();
}
},
_onClearSearch: function () {
this.searchBox.value = "";
this.searchClearButton.hidden = true;
}
};

Просмотреть файл

@ -40,14 +40,15 @@
class="devtools-button" />
<html:div class="devtools-toolbar-spacer" />
<html:span id="inspector-searchlabel" />
<textbox id="inspector-searchbox"
type="search"
timeout="50"
class="devtools-searchinput"
placeholder="&inspectorSearchHTML.label3;"/>
<html:div id="inspector-search" class="devtools-searchbox">
<html:input id="inspector-searchbox" class="devtools-searchinput"
type="search"
placeholder="&inspectorSearchHTML.label3;"/>
<html:button id="inspector-searchinput-clear" class="devtools-searchinput-clear" tabindex="-1"></html:button>
</html:div>
<html:button id="inspector-eyedropper-toggle"
title="&inspectorEyeDropper.label;"
class="devtools-button command-button-invertable" />
title="&inspectorEyeDropper.label;"
class="devtools-button command-button-invertable" />
<div xmlns="http://www.w3.org/1999/xhtml"
id="inspector-sidebar-toggle-box" />
</html:div>

Просмотреть файл

@ -141,7 +141,7 @@ add_task(function* () {
for (let { key, suggestions } of TEST_DATA) {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
let command = once(searchBox, "command");
let command = once(searchBox, "input");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;

Просмотреть файл

@ -222,7 +222,7 @@ add_task(function* () {
for (let { key, suggestions } of TEST_DATA) {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
let command = once(searchBox, "command");
let command = once(searchBox, "input");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;

Просмотреть файл

@ -84,7 +84,7 @@ add_task(function* () {
for (let {key, suggestions} of TEST_DATA) {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
let command = once(searchBox, "command");
let command = once(searchBox, "input");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;

Просмотреть файл

@ -1,49 +1,49 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that searching for classes on SVG elements does work (see bug 1219920).
const TEST_URL = URL_ROOT + "doc_inspector_search-svg.html";
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
const TEST_DATA = [{
key: "c",
suggestions: ["circle", "clipPath", ".class1", ".class2"]
}, {
key: "VK_BACK_SPACE",
suggestions: []
}, {
key: ".",
suggestions: [".class1", ".class2"]
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URL);
let {searchBox} = inspector;
let popup = inspector.searchSuggestions.searchPopup;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
for (let {key, suggestions} of TEST_DATA) {
info("Pressing " + key + " to get " + suggestions);
let command = once(searchBox, "command");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;
info("Waiting for search query to complete and getting the suggestions");
yield inspector.searchSuggestions._lastQuery;
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length : 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(actualSuggestions[i].label, suggestions[i],
"The suggestion at " + i + "th index is correct.");
}
}
});
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that searching for classes on SVG elements does work (see bug 1219920).
const TEST_URL = URL_ROOT + "doc_inspector_search-svg.html";
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
const TEST_DATA = [{
key: "c",
suggestions: ["circle", "clipPath", ".class1", ".class2"]
}, {
key: "VK_BACK_SPACE",
suggestions: []
}, {
key: ".",
suggestions: [".class1", ".class2"]
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URL);
let {searchBox} = inspector;
let popup = inspector.searchSuggestions.searchPopup;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
for (let {key, suggestions} of TEST_DATA) {
info("Pressing " + key + " to get " + suggestions);
let command = once(searchBox, "input");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;
info("Waiting for search query to complete and getting the suggestions");
yield inspector.searchSuggestions._lastQuery;
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length : 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(actualSuggestions[i].label, suggestions[i],
"The suggestion at " + i + "th index is correct.");
}
}
});

Просмотреть файл

@ -1,64 +1,64 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that searching for namespaced elements does work.
const XHTML = `
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<body>
<svg:svg width="100" height="100">
<svg:clipPath>
<svg:rect x="0" y="0" width="10" height="5"></svg:rect>
</svg:clipPath>
<svg:circle cx="0" cy="0" r="5"></svg:circle>
</svg:svg>
</body>
</html>
`;
const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
const TEST_DATA = [{
key: "c",
suggestions: ["circle", "clipPath"]
}, {
key: "VK_BACK_SPACE",
suggestions: []
}, {
key: "s",
suggestions: ["svg"]
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URI);
let {searchBox} = inspector;
let popup = inspector.searchSuggestions.searchPopup;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
for (let {key, suggestions} of TEST_DATA) {
info("Pressing " + key + " to get " + suggestions.join(", "));
let command = once(searchBox, "command");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;
info("Waiting for search query to complete and getting the suggestions");
yield inspector.searchSuggestions._lastQuery;
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length : 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(actualSuggestions[i].label, suggestions[i],
"The suggestion at " + i + "th index is correct.");
}
}
});
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that searching for namespaced elements does work.
const XHTML = `
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<body>
<svg:svg width="100" height="100">
<svg:clipPath>
<svg:rect x="0" y="0" width="10" height="5"></svg:rect>
</svg:clipPath>
<svg:circle cx="0" cy="0" r="5"></svg:circle>
</svg:svg>
</body>
</html>
`;
const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
const TEST_DATA = [{
key: "c",
suggestions: ["circle", "clipPath"]
}, {
key: "VK_BACK_SPACE",
suggestions: []
}, {
key: "s",
suggestions: ["svg"]
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URI);
let {searchBox} = inspector;
let popup = inspector.searchSuggestions.searchPopup;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
for (let {key, suggestions} of TEST_DATA) {
info("Pressing " + key + " to get " + suggestions.join(", "));
let command = once(searchBox, "input");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;
info("Waiting for search query to complete and getting the suggestions");
yield inspector.searchSuggestions._lastQuery;
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length : 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(actualSuggestions[i].label, suggestions[i],
"The suggestion at " + i + "th index is correct.");
}
}
});

Просмотреть файл

@ -104,7 +104,7 @@ add_task(function* () {
for (let { key, suggestions } of TEST_DATA) {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
let command = once(searchBox, "command");
let command = once(searchBox, "input");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;

Просмотреть файл

@ -62,7 +62,7 @@ add_task(function* () {
info("pressing key " + key + " to get suggestions " +
JSON.stringify(expectedSuggestions));
let onCommand = once(searchBox, "command", true);
let onCommand = once(searchBox, "input", true);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield onCommand;

Просмотреть файл

@ -27,6 +27,18 @@
#inspector-searchlabel {
overflow: hidden;
margin-inline-end: 2px;
}
#inspector-search {
flex: unset;
}
/* TODO: bug 1265759: should apply to .devtools-searchinput once all searchbox
is converted to html*/
#inspector-searchbox {
flex: 1;
width: 100%;
}
/* Make sure the text is vertically centered in Inspector's

Просмотреть файл

@ -26,9 +26,7 @@
let inspector = toolbox.getPanel("inspector");
inspector.searchBox.focus();
// Use the binding element since inspector.searchBox is a XUL element.
let activeElement = getActiveElement(inspector.panelDoc);
activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
is(activeElement, inspector.searchBox, "Search box is focused");
yield toolbox.openSplitConsole();
@ -45,9 +43,7 @@
info("Making sure that the search box is refocused after closing the " +
"split console");
// Use the binding element since inspector.searchBox is a XUL element.
activeElement = getActiveElement(inspector.panelDoc);
activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
is(activeElement, inspector.searchBox, "Search box is focused");
yield toolbox.destroy();