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

Side by Side 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, 2 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @constructor 6 * @constructor
7 * @extends {WebInspector.Widget} 7 * @extends {WebInspector.Widget}
8 */ 8 */
9 WebInspector.ClassesPaneWidget = function() 9 WebInspector.ClassesPaneWidget = function()
10 { 10 {
11 WebInspector.Widget.call(this); 11 WebInspector.Widget.call(this);
12 this.element.className = "styles-element-classes-pane"; 12 this.element.className = "styles-element-classes-pane";
13 var container = this.element.createChild("div", "title-container"); 13 var container = this.element.createChild("div", "title-container");
14 this._input = container.createChild("input", "new-class-input monospace"); 14 this._input = container.createChild("div", "new-class-input monospace");
15 this._input.placeholder = WebInspector.UIString("Add new class"); 15 this._input.setAttribute("placeholder", WebInspector.UIString("Add new class "));
16 this._input.addEventListener("keydown", this._onKeyDown.bind(this), false);
17 this.setDefaultFocusedElement(this._input); 16 this.setDefaultFocusedElement(this._input);
18 this._classesContainer = this.element.createChild("div", "source-code"); 17 this._classesContainer = this.element.createChild("div", "source-code");
19 this._classesContainer.classList.add("styles-element-classes-container"); 18 this._classesContainer.classList.add("styles-element-classes-container");
19 this._prompt = new WebInspector.ClassesPaneWidget.ClassNamePrompt();
20 this._prompt.setAutocompletionTimeout(0);
21 this._prompt.renderAsBlock();
22
23 var proxyElement = this._prompt.attach(this._input);
24 proxyElement.addEventListener("keydown", this._onKeyDown.bind(this), false);
20 25
21 WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspec tor.DOMModel.Events.DOMMutated, this._onDOMMutated, this); 26 WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspec tor.DOMModel.Events.DOMMutated, this._onDOMMutated, this);
22 /** @type {!Set<!WebInspector.DOMNode>} */ 27 /** @type {!Set<!WebInspector.DOMNode>} */
23 this._mutatingNodes = new Set(); 28 this._mutatingNodes = new Set();
24 WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._upd ate, this); 29 WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._upd ate, this);
25 } 30 }
26 31
27 WebInspector.ClassesPaneWidget._classesSymbol = Symbol("WebInspector.ClassesPane Widget._classesSymbol"); 32 WebInspector.ClassesPaneWidget._classesSymbol = Symbol("WebInspector.ClassesPane Widget._classesSymbol");
28 33
29 WebInspector.ClassesPaneWidget.prototype = { 34 WebInspector.ClassesPaneWidget.prototype = {
30 /** 35 /**
31 * @param {!Event} event 36 * @param {!Event} event
32 */ 37 */
33 _onKeyDown: function(event) 38 _onKeyDown: function(event)
34 { 39 {
35 var text = event.target.value; 40 var text = event.target.textContent;
36 if (isEscKey(event)) { 41 if (isEscKey(event)) {
37 event.target.value = ""; 42 event.target.textContent = "";
38 if (!text.isWhitespace()) 43 if (!text.isWhitespace())
39 event.consume(true); 44 event.consume(true);
40 return; 45 return;
41 } 46 }
42 47
43 if (!isEnterKey(event)) 48 if (!isEnterKey(event))
44 return; 49 return;
45 var node = WebInspector.context.flavor(WebInspector.DOMNode); 50 var node = WebInspector.context.flavor(WebInspector.DOMNode);
46 if (!node) 51 if (!node)
47 return; 52 return;
48 53
49 event.target.value = ""; 54 this._prompt.clearAutocomplete();
55 event.target.textContent = "";
50 var classNames = text.split(/[.,\s]/); 56 var classNames = text.split(/[.,\s]/);
51 for (var className of classNames) { 57 for (var className of classNames) {
52 var className = className.trim(); 58 var className = className.trim();
53 if (!className.length) 59 if (!className.length)
54 continue; 60 continue;
55 this._toggleClass(node, className, true); 61 this._toggleClass(node, className, true);
56 } 62 }
57 this._installNodeClasses(node); 63 this._installNodeClasses(node);
58 this._update(); 64 this._update();
59 event.consume(true); 65 event.consume(true);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 210
205 /** 211 /**
206 * @override 212 * @override
207 * @return {!WebInspector.ToolbarItem} 213 * @return {!WebInspector.ToolbarItem}
208 */ 214 */
209 item: function() 215 item: function()
210 { 216 {
211 return this._button; 217 return this._button;
212 } 218 }
213 } 219 }
220
221 /**
222 * @constructor
223 * @extends {WebInspector.TextPrompt}
224 */
225 WebInspector.ClassesPaneWidget.ClassNamePrompt = function()
226 {
227 WebInspector.TextPrompt.call(this, this._buildClassNameCompletions.bind(this ), " ");
228 this.setSuggestBoxEnabled(true);
229 this.disableDefaultSuggestionForEmptyInput();
230 this._selectedFrameId = "";
231 this._classNamesPromise = null;
232 }
233
234 WebInspector.ClassesPaneWidget.ClassNamePrompt.prototype = {
235 _getClassNames: function()
lushnikov 2016/09/29 21:01:50 let's add jsdoc and pass in selectedNode. This wil
ahmetemirercin 2016/09/30 17:38:40 Done.
236 {
237 var promises = [];
238 var completions = new Set();
239 var selectedNode = WebInspector.context.flavor(WebInspector.DOMNode);
240 this._selectedFrameId = selectedNode.frameId() || WebInspector.ResourceT reeModel.fromTarget(selectedNode.target()).mainFrame.id;
lushnikov 2016/09/29 21:01:50 you can drop "|| WebInspector.ResourceTreeModel.."
ahmetemirercin 2016/09/30 17:38:40 Done.
241
242 var cssModel = WebInspector.CSSModel.fromTarget(selectedNode.target());
243 var allStyleSheets = cssModel.allStyleSheets();
244 for (var stylesheet of allStyleSheets) {
245 if (stylesheet.frameId !== this._selectedFrameId)
246 continue;
247 var cssPromise = cssModel.classNamesPromise(stylesheet.id).then(clas ses => completions.addAll(classes));
248 promises.push(cssPromise);
249 }
250
251 var domPromise = selectedNode.domModel().classNamesPromise(selectedNode. ownerDocument.id).then(classes => completions.addAll(classes));
252 promises.push(domPromise);
253 return Promise.all(promises).then(() => completions.valuesArray());
254 },
255
256 /**
257 * @param {!Element} proxyElement
258 * @param {!Range} wordRange
259 * @param {boolean} force
260 * @param {function(!Array.<string>, number=)} completionsReadyCallback
261 */
262 _buildClassNameCompletions: function(proxyElement, wordRange, force, complet ionsReadyCallback)
263 {
264 var prefix = wordRange.toString();
265 if (!prefix || force)
lushnikov 2016/09/29 21:01:50 let's embed this in the "if" on line 269
ahmetemirercin 2016/09/30 17:38:40 We can't embed this with that if while expecting f
lushnikov 2016/09/30 18:05:54 ah, indeed!
266 this._classNamesPromise = null;
267
268 var selectedNode = WebInspector.context.flavor(WebInspector.DOMNode);
269 if (!selectedNode || (!prefix && !force && !proxyElement.textContent.len gth)) {
270 completionsReadyCallback([]);
271 return;
272 }
273
274 if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.f rameId())
275 this._classNamesPromise = this._getClassNames();
276
277 this._classNamesPromise.then(completions => {
278 var results = [];
279 completions.forEach(value => {
280 if (prefix.substring(0, 1) === ".")
lushnikov 2016/09/29 21:01:50 let's filter/map if (prefix[0] === ".") compl
ahmetemirercin 2016/09/30 17:38:40 Done.
281 value = "." + value;
282 if (value.startsWith(prefix))
283 results.push(value);
284 });
285 completionsReadyCallback(results, 0);
286 });
287 },
288
289 __proto__: WebInspector.TextPrompt.prototype
290 }
OLDNEW
« 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