Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js

Issue 2343773002: DevTools: Autocomplete class names in ClassesPaneWidget (Closed)
Patch Set: Reviewed Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
index b0bada022b10ab39a9c8379afb97d078f1c7817a..d0e5b0f9e9140c83114f9dfe3c9150f614cfb87b 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -11,12 +11,17 @@ WebInspector.ClassesPaneWidget = function()
WebInspector.Widget.call(this);
this.element.className = "styles-element-classes-pane";
var container = this.element.createChild("div", "title-container");
- this._input = container.createChild("input", "new-class-input monospace");
- this._input.placeholder = WebInspector.UIString("Add new class");
- this._input.addEventListener("keydown", this._onKeyDown.bind(this), false);
+ this._input = container.createChild("div", "new-class-input monospace");
+ this._input.setAttribute("placeholder", WebInspector.UIString("Add new class"));
this.setDefaultFocusedElement(this._input);
this._classesContainer = this.element.createChild("div", "source-code");
this._classesContainer.classList.add("styles-element-classes-container");
+ this._prompt = new WebInspector.ClassesPaneWidget.ClassNamePrompt();
+ this._prompt.setAutocompletionTimeout(0);
+ this._prompt.renderAsBlock();
+
+ var proxyElement = this._prompt.attach(this._input);
+ proxyElement.addEventListener("keydown", this._onKeyDown.bind(this), false);
WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.DOMMutated, this._onDOMMutated, this);
/** @type {!Set<!WebInspector.DOMNode>} */
@@ -32,9 +37,9 @@ WebInspector.ClassesPaneWidget.prototype = {
*/
_onKeyDown: function(event)
{
- var text = event.target.value;
+ var text = event.target.textContent;
if (isEscKey(event)) {
- event.target.value = "";
+ event.target.textContent = "";
if (!text.isWhitespace())
event.consume(true);
return;
@@ -46,7 +51,8 @@ WebInspector.ClassesPaneWidget.prototype = {
if (!node)
return;
- event.target.value = "";
+ this._prompt.clearAutocomplete();
+ event.target.textContent = "";
var classNames = text.split(/[.,\s]/);
for (var className of classNames) {
var className = className.trim();
@@ -211,3 +217,67 @@ WebInspector.ClassesPaneWidget.ButtonProvider.prototype = {
return this._button;
}
}
+
+/**
+ * @constructor
+ * @extends {WebInspector.TextPrompt}
+ */
+WebInspector.ClassesPaneWidget.ClassNamePrompt = function()
+{
+ WebInspector.TextPrompt.call(this, this._buildClassNameCompletions.bind(this), " ");
+ this.setSuggestBoxEnabled(true);
+ this.disableDefaultSuggestionForEmptyInput();
+ this._lastQuery = "";
+ this._selectedFrameId = "";
+ this._completions = new Set();
+}
+
+WebInspector.ClassesPaneWidget.ClassNamePrompt.prototype = {
+ /**
+ * @param {!Element} proxyElement
+ * @param {!Range} wordRange
+ * @param {boolean} force
+ * @param {function(!Array.<string>, number=)} completionsReadyCallback
+ */
+ _buildClassNameCompletions: function(proxyElement, wordRange, force, completionsReadyCallback)
+ {
+ var prefix = wordRange.toString();
+ var selectedNode = WebInspector.context.flavor(WebInspector.DOMNode);
+ if (!selectedNode || (!prefix && !force && !proxyElement.textContent.length)) {
+ completionsReadyCallback([]);
+ return;
+ }
+
+ var promises = [];
+ if (this._selectedFrameId !== selectedNode.frameId() || !prefix.startsWith(this._lastQuery)) {
+ this._completions = new Set();
lushnikov 2016/09/29 16:03:15 We usually employ promises to cache values. One gr
ahmetemirercin 2016/09/29 19:25:36 I just see that promises are used like this after
+ this._selectedFrameId = selectedNode.frameId() || WebInspector.ResourceTreeModel.fromTarget(selectedNode.target()).mainFrame.id;
+
+ var cssModel = WebInspector.CSSModel.fromTarget(selectedNode.target());
+ var allStyleSheets = cssModel.allStyleSheets();
+ for (var stylesheet of allStyleSheets) {
+ if (stylesheet.frameId !== this._selectedFrameId)
+ continue;
+ var cssPromise = cssModel.classNamesPromise(stylesheet.id).then(classes => this._completions.addAll(classes));
+ promises.push(cssPromise);
+ }
+
+ var domPromise = selectedNode.domModel().classNamesPromise(selectedNode.ownerDocument.id).then(classes => this._completions.addAll(classes));
+ promises.push(domPromise);
+ }
+ this._lastQuery = prefix;
+
+ Promise.all(promises).then(() => {
+ var results = [];
+ this._completions.valuesArray().forEach((value) => {
+ if (prefix.substring(0, 1) === ".")
+ value = "." + value;
lushnikov 2016/09/29 16:03:15 i agree with this
+ if (value.startsWith(prefix))
+ results.push(value);
+ });
+ completionsReadyCallback(results, 0);
+ });
+ },
+
+ __proto__: WebInspector.TextPrompt.prototype
+}
« no previous file with comments | « no previous file | third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698