blob: 1c0c548b973922db373c302ef50ebcb6f66d3c5c [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// 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
3// found in the LICENSE file.
Tim van der Lippe97611c92020-02-12 16:56:584
Jan Scheffler29905852021-04-14 11:30:315/* eslint-disable rulesdir/no_underscored_properties */
6
Tim van der Lippe76961572021-04-06 10:48:077import * as Common from '../../core/common/common.js';
Tim van der Lippebb352e62021-04-01 17:57:288import * as i18n from '../../core/i18n/i18n.js';
Tim van der Lippeaa1ed7a2021-03-31 14:38:279import * as Platform from '../../core/platform/platform.js';
Tim van der Lippee00b92f2021-03-31 16:52:1710import * as SDK from '../../core/sdk/sdk.js';
Tim van der Lippeaa61faf2021-04-07 15:32:0711import * as UI from '../../ui/legacy/legacy.js';
Tim van der Lippe97611c92020-02-12 16:56:5812
Kriti Sapra40ca8da2021-07-20 09:33:5913import classesPaneWidgetStyles from './classesPaneWidget.css.js';
Tim van der Lippeaabc8302019-12-10 15:34:4514import {ElementsPanel} from './ElementsPanel.js';
15
Simon Zündfbfd1072021-03-01 07:38:5316const UIStrings = {
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4917 /**
Peter Marshallcc995412021-02-19 08:07:4318 * @description Prompt text for a text field in the Classes Pane Widget of the Elements panel.
19 * Class refers to a CSS class.
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4920 */
21 addNewClass: 'Add new class',
22 /**
Peter Marshallcc995412021-02-19 08:07:4323 * @description Screen reader announcement string when adding a CSS class via the Classes Pane Widget.
24 * @example {vbox flex-auto} PH1
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4925 */
Peter Marshallcc995412021-02-19 08:07:4326 classesSAdded: 'Classes {PH1} added',
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4927 /**
Peter Marshallcc995412021-02-19 08:07:4328 * @description Screen reader announcement string when adding a class via the Classes Pane Widget.
29 * @example {title-container} PH1
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4930 */
Peter Marshallcc995412021-02-19 08:07:4331 classSAdded: 'Class {PH1} added',
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4932 /**
Peter Marshallcc995412021-02-19 08:07:4333 * @description Accessible title read by screen readers for the Classes Pane Widget of the Elements
34 * panel. Element is a HTML DOM Element and classes refers to CSS classes.
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4935 */
36 elementClasses: 'Element Classes',
37};
Jan Scheffler29905852021-04-14 11:30:3138const str_ = i18n.i18n.registerUIStrings('panels/elements/ClassesPaneWidget.ts', UIStrings);
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4939const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
Tim van der Lippe97611c92020-02-12 16:56:5840export class ClassesPaneWidget extends UI.Widget.Widget {
Jan Scheffler29905852021-04-14 11:30:3141 _input: HTMLElement;
42 _classesContainer: HTMLElement;
43 _prompt: ClassNamePrompt;
44 _mutatingNodes: Set<SDK.DOMModel.DOMNode>;
45 _pendingNodeClasses: Map<SDK.DOMModel.DOMNode, string>;
46 _updateNodeThrottler: Common.Throttler.Throttler;
47 _previousTarget: SDK.DOMModel.DOMNode|null;
48
Blink Reformat4c46d092018-04-07 15:32:3749 constructor() {
50 super(true);
Blink Reformat4c46d092018-04-07 15:32:3751 this.contentElement.className = 'styles-element-classes-pane';
52 const container = this.contentElement.createChild('div', 'title-container');
53 this._input = container.createChild('div', 'new-class-input monospace');
54 this.setDefaultFocusedElement(this._input);
55 this._classesContainer = this.contentElement.createChild('div', 'source-code');
56 this._classesContainer.classList.add('styles-element-classes-container');
Tim van der Lippe13f71fb2019-11-29 11:17:3957 this._prompt = new ClassNamePrompt(this._nodeClasses.bind(this));
Blink Reformat4c46d092018-04-07 15:32:3758 this._prompt.setAutocompletionTimeout(0);
59 this._prompt.renderAsBlock();
60
Jan Scheffler29905852021-04-14 11:30:3161 const proxyElement = (this._prompt.attach(this._input) as HTMLElement);
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:4962 this._prompt.setPlaceholder(i18nString(UIStrings.addNewClass));
Blink Reformat4c46d092018-04-07 15:32:3763 this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._onTextChanged, this);
64 proxyElement.addEventListener('keydown', this._onKeyDown.bind(this), false);
65
Sigurd Schneiderb9f6c792021-05-31 10:57:2466 SDK.TargetManager.TargetManager.instance().addModelListener(
Tim van der Lippe97611c92020-02-12 16:56:5867 SDK.DOMModel.DOMModel, SDK.DOMModel.Events.DOMMutated, this._onDOMMutated, this);
Blink Reformat4c46d092018-04-07 15:32:3768 this._mutatingNodes = new Set();
Blink Reformat4c46d092018-04-07 15:32:3769 this._pendingNodeClasses = new Map();
Tim van der Lippe97611c92020-02-12 16:56:5870 this._updateNodeThrottler = new Common.Throttler.Throttler(0);
Blink Reformat4c46d092018-04-07 15:32:3771 this._previousTarget = null;
Tim van der Lipped1a00aa2020-08-19 16:03:5672 UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this._onSelectedNodeChanged, this);
Blink Reformat4c46d092018-04-07 15:32:3773 }
74
Jan Scheffler29905852021-04-14 11:30:3175 _splitTextIntoClasses(text: string): string[] {
Mathias Bynens3abc0952020-04-20 14:15:5276 return text.split(/[,\s]/).map(className => className.trim()).filter(className => className.length);
Blink Reformat4c46d092018-04-07 15:32:3777 }
78
Jan Scheffler29905852021-04-14 11:30:3179 _onKeyDown(event: KeyboardEvent): void {
Tim van der Lippebcd6b5c2021-01-13 12:31:5180 if (!(event.key === 'Enter') && !isEscKey(event)) {
Blink Reformat4c46d092018-04-07 15:32:3781 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3482 }
Blink Reformat4c46d092018-04-07 15:32:3783
Tim van der Lippebcd6b5c2021-01-13 12:31:5184 if (event.key === 'Enter') {
Blink Reformat4c46d092018-04-07 15:32:3785 event.consume();
Tim van der Lippe1d6e57a2019-09-30 11:55:3486 if (this._prompt.acceptAutoComplete()) {
Blink Reformat4c46d092018-04-07 15:32:3787 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3488 }
Blink Reformat4c46d092018-04-07 15:32:3789 }
90
Jan Scheffler29905852021-04-14 11:30:3191 const eventTarget = (event.target as HTMLElement);
92 let text: ''|string = (eventTarget.textContent as string);
Blink Reformat4c46d092018-04-07 15:32:3793 if (isEscKey(event)) {
Simon Zündda7058f2020-02-28 13:57:2894 if (!Platform.StringUtilities.isWhitespace(text)) {
Blink Reformat4c46d092018-04-07 15:32:3795 event.consume(true);
Tim van der Lippe1d6e57a2019-09-30 11:55:3496 }
Blink Reformat4c46d092018-04-07 15:32:3797 text = '';
98 }
99
100 this._prompt.clearAutocomplete();
Tim van der Lippe32f760f2020-10-01 10:52:15101 eventTarget.textContent = '';
Blink Reformat4c46d092018-04-07 15:32:37102
Tim van der Lipped1a00aa2020-08-19 16:03:56103 const node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34104 if (!node) {
Blink Reformat4c46d092018-04-07 15:32:37105 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34106 }
Blink Reformat4c46d092018-04-07 15:32:37107
108 const classNames = this._splitTextIntoClasses(text);
Michael Liaocafccfd2020-04-02 17:11:59109 if (!classNames.length) {
Patrick Brosset78fa1f52020-08-17 14:33:48110 this._installNodeClasses(node);
Michael Liaocafccfd2020-04-02 17:11:59111 return;
112 }
113
Tim van der Lippe1d6e57a2019-09-30 11:55:34114 for (const className of classNames) {
Blink Reformat4c46d092018-04-07 15:32:37115 this._toggleClass(node, className, true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34116 }
Michael Liaocafccfd2020-04-02 17:11:59117
118 // annoucementString is used for screen reader to announce that the class(es) has been added successfully.
119 const joinClassString = classNames.join(' ');
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:49120 const announcementString = classNames.length > 1 ? i18nString(UIStrings.classesSAdded, {PH1: joinClassString}) :
121 i18nString(UIStrings.classSAdded, {PH1: joinClassString});
Michael Liao7322dee2021-04-07 18:33:30122 UI.ARIAUtils.alert(announcementString);
Michael Liaocafccfd2020-04-02 17:11:59123
Blink Reformat4c46d092018-04-07 15:32:37124 this._installNodeClasses(node);
125 this._update();
126 }
127
Jan Scheffler29905852021-04-14 11:30:31128 _onTextChanged(): void {
Tim van der Lipped1a00aa2020-08-19 16:03:56129 const node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34130 if (!node) {
Blink Reformat4c46d092018-04-07 15:32:37131 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34132 }
Blink Reformat4c46d092018-04-07 15:32:37133 this._installNodeClasses(node);
134 }
135
Simon Zünd37cf1f52021-07-30 09:53:35136 _onDOMMutated(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void {
137 const node = event.data;
Tim van der Lippe1d6e57a2019-09-30 11:55:34138 if (this._mutatingNodes.has(node)) {
Blink Reformat4c46d092018-04-07 15:32:37139 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34140 }
Tim van der Lippe32f760f2020-10-01 10:52:15141 cachedClassesMap.delete(node);
Blink Reformat4c46d092018-04-07 15:32:37142 this._update();
143 }
144
Jan Scheffler29905852021-04-14 11:30:31145 _onSelectedNodeChanged(event: Common.EventTarget.EventTargetEvent): void {
Blink Reformat4c46d092018-04-07 15:32:37146 if (this._previousTarget && this._prompt.text()) {
147 this._input.textContent = '';
148 this._installNodeClasses(this._previousTarget);
149 }
Jan Scheffler29905852021-04-14 11:30:31150 this._previousTarget = (event.data as SDK.DOMModel.DOMNode | null);
Blink Reformat4c46d092018-04-07 15:32:37151 this._update();
152 }
153
Jan Scheffler29905852021-04-14 11:30:31154 wasShown(): void {
Kriti Saprab2b29f22021-06-29 12:59:56155 super.wasShown();
Blink Reformat4c46d092018-04-07 15:32:37156 this._update();
Kriti Sapra40ca8da2021-07-20 09:33:59157 this.registerCSSFiles([classesPaneWidgetStyles]);
Blink Reformat4c46d092018-04-07 15:32:37158 }
159
Jan Scheffler29905852021-04-14 11:30:31160 _update(): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34161 if (!this.isShowing()) {
Blink Reformat4c46d092018-04-07 15:32:37162 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34163 }
Blink Reformat4c46d092018-04-07 15:32:37164
Tim van der Lipped1a00aa2020-08-19 16:03:56165 let node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34166 if (node) {
Blink Reformat4c46d092018-04-07 15:32:37167 node = node.enclosingElementOrSelf();
Tim van der Lippe1d6e57a2019-09-30 11:55:34168 }
Blink Reformat4c46d092018-04-07 15:32:37169
170 this._classesContainer.removeChildren();
Tim van der Lippe32f760f2020-10-01 10:52:15171 // @ts-ignore this._input is a div, not an input element. So this line makes no sense at all
Blink Reformat4c46d092018-04-07 15:32:37172 this._input.disabled = !node;
173
Tim van der Lippe1d6e57a2019-09-30 11:55:34174 if (!node) {
Blink Reformat4c46d092018-04-07 15:32:37175 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34176 }
Blink Reformat4c46d092018-04-07 15:32:37177
178 const classes = this._nodeClasses(node);
Simon Zündf27be3d2020-02-11 14:46:27179 const keys = [...classes.keys()];
Tim van der Lippe32f760f2020-10-01 10:52:15180 keys.sort(Platform.StringUtilities.caseInsensetiveComparator);
181 for (const className of keys) {
Tim van der Lippe97611c92020-02-12 16:56:58182 const label = UI.UIUtils.CheckboxLabel.create(className, classes.get(className));
Blink Reformat4c46d092018-04-07 15:32:37183 label.classList.add('monospace');
184 label.checkboxElement.addEventListener('click', this._onClick.bind(this, className), false);
185 this._classesContainer.appendChild(label);
186 }
187 }
188
Jan Scheffler29905852021-04-14 11:30:31189 _onClick(className: string, event: Event): void {
Tim van der Lipped1a00aa2020-08-19 16:03:56190 const node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34191 if (!node) {
Blink Reformat4c46d092018-04-07 15:32:37192 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34193 }
Jan Scheffler29905852021-04-14 11:30:31194 const enabled = (event.target as HTMLInputElement).checked;
Blink Reformat4c46d092018-04-07 15:32:37195 this._toggleClass(node, className, enabled);
196 this._installNodeClasses(node);
197 }
198
Jan Scheffler29905852021-04-14 11:30:31199 _nodeClasses(node: SDK.DOMModel.DOMNode): Map<string, boolean> {
Tim van der Lippe32f760f2020-10-01 10:52:15200 let result = cachedClassesMap.get(node);
Blink Reformat4c46d092018-04-07 15:32:37201 if (!result) {
202 const classAttribute = node.getAttribute('class') || '';
203 const classes = classAttribute.split(/\s/);
204 result = new Map();
205 for (let i = 0; i < classes.length; ++i) {
206 const className = classes[i].trim();
Tim van der Lippe1d6e57a2019-09-30 11:55:34207 if (!className.length) {
Blink Reformat4c46d092018-04-07 15:32:37208 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34209 }
Blink Reformat4c46d092018-04-07 15:32:37210 result.set(className, true);
211 }
Tim van der Lippe32f760f2020-10-01 10:52:15212 cachedClassesMap.set(node, result);
Blink Reformat4c46d092018-04-07 15:32:37213 }
214 return result;
215 }
216
Jan Scheffler29905852021-04-14 11:30:31217 _toggleClass(node: SDK.DOMModel.DOMNode, className: string, enabled: boolean): void {
Blink Reformat4c46d092018-04-07 15:32:37218 const classes = this._nodeClasses(node);
219 classes.set(className, enabled);
220 }
221
Jan Scheffler29905852021-04-14 11:30:31222 _installNodeClasses(node: SDK.DOMModel.DOMNode): void {
Blink Reformat4c46d092018-04-07 15:32:37223 const classes = this._nodeClasses(node);
Jan Scheffler29905852021-04-14 11:30:31224 const activeClasses = new Set<string>();
Blink Reformat4c46d092018-04-07 15:32:37225 for (const className of classes.keys()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34226 if (classes.get(className)) {
Blink Reformat4c46d092018-04-07 15:32:37227 activeClasses.add(className);
Tim van der Lippe1d6e57a2019-09-30 11:55:34228 }
Blink Reformat4c46d092018-04-07 15:32:37229 }
230
231 const additionalClasses = this._splitTextIntoClasses(this._prompt.textWithCurrentSuggestion());
Tim van der Lippe1d6e57a2019-09-30 11:55:34232 for (const className of additionalClasses) {
Blink Reformat4c46d092018-04-07 15:32:37233 activeClasses.add(className);
Tim van der Lippe1d6e57a2019-09-30 11:55:34234 }
Blink Reformat4c46d092018-04-07 15:32:37235
Simon Zünda0d40622020-02-12 13:16:42236 const newClasses = [...activeClasses.values()].sort();
Blink Reformat4c46d092018-04-07 15:32:37237
238 this._pendingNodeClasses.set(node, newClasses.join(' '));
239 this._updateNodeThrottler.schedule(this._flushPendingClasses.bind(this));
240 }
241
Jan Scheffler29905852021-04-14 11:30:31242 async _flushPendingClasses(): Promise<void> {
Blink Reformat4c46d092018-04-07 15:32:37243 const promises = [];
244 for (const node of this._pendingNodeClasses.keys()) {
245 this._mutatingNodes.add(node);
Jan Scheffler29905852021-04-14 11:30:31246 const promise = node.setAttributeValuePromise('class', (this._pendingNodeClasses.get(node) as string))
Blink Reformat4c46d092018-04-07 15:32:37247 .then(onClassValueUpdated.bind(this, node));
248 promises.push(promise);
249 }
250 this._pendingNodeClasses.clear();
Tim van der Lippe32f760f2020-10-01 10:52:15251 await Promise.all(promises);
Blink Reformat4c46d092018-04-07 15:32:37252
Jan Scheffler29905852021-04-14 11:30:31253 function onClassValueUpdated(this: ClassesPaneWidget, node: SDK.DOMModel.DOMNode): void {
Blink Reformat4c46d092018-04-07 15:32:37254 this._mutatingNodes.delete(node);
255 }
256 }
Tim van der Lippe13f71fb2019-11-29 11:17:39257}
Blink Reformat4c46d092018-04-07 15:32:37258
Jan Scheffler29905852021-04-14 11:30:31259const cachedClassesMap = new WeakMap<SDK.DOMModel.DOMNode, Map<string, boolean>>();
Blink Reformat4c46d092018-04-07 15:32:37260
Jan Scheffler29905852021-04-14 11:30:31261let buttonProviderInstance: ButtonProvider;
Andres Olivares43c2d9f2021-02-10 16:48:39262
Jan Scheffler29905852021-04-14 11:30:31263export class ButtonProvider implements UI.Toolbar.Provider {
264 _button: UI.Toolbar.ToolbarToggle;
265 _view: ClassesPaneWidget;
266 private constructor() {
Vidal Guillermo Diazleal Ortega0cfa0ed2021-02-17 20:35:49267 this._button = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.elementClasses), '');
Blink Reformat4c46d092018-04-07 15:32:37268 this._button.setText('.cls');
269 this._button.element.classList.add('monospace');
Tim van der Lippe97611c92020-02-12 16:56:58270 this._button.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._clicked, this);
Tim van der Lippe13f71fb2019-11-29 11:17:39271 this._view = new ClassesPaneWidget();
Blink Reformat4c46d092018-04-07 15:32:37272 }
273
Jan Scheffler29905852021-04-14 11:30:31274 static instance(opts: {
275 forceNew: boolean|null,
276 } = {forceNew: null}): ButtonProvider {
Andres Olivares43c2d9f2021-02-10 16:48:39277 const {forceNew} = opts;
278 if (!buttonProviderInstance || forceNew) {
279 buttonProviderInstance = new ButtonProvider();
280 }
281
282 return buttonProviderInstance;
283 }
284
Jan Scheffler29905852021-04-14 11:30:31285 _clicked(): void {
Tim van der Lippeaabc8302019-12-10 15:34:45286 ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null, this._button);
Blink Reformat4c46d092018-04-07 15:32:37287 }
288
Jan Scheffler29905852021-04-14 11:30:31289 item(): UI.Toolbar.ToolbarItem {
Blink Reformat4c46d092018-04-07 15:32:37290 return this._button;
291 }
Tim van der Lippe13f71fb2019-11-29 11:17:39292}
Blink Reformat4c46d092018-04-07 15:32:37293
Tim van der Lippe97611c92020-02-12 16:56:58294export class ClassNamePrompt extends UI.TextPrompt.TextPrompt {
Jan Scheffler29905852021-04-14 11:30:31295 _nodeClasses: (arg0: SDK.DOMModel.DOMNode) => Map<string, boolean>;
296 _selectedFrameId: string|null;
297 _classNamesPromise: Promise<string[]>|null;
298 constructor(nodeClasses: (arg0: SDK.DOMModel.DOMNode) => Map<string, boolean>) {
Blink Reformat4c46d092018-04-07 15:32:37299 super();
300 this._nodeClasses = nodeClasses;
301 this.initialize(this._buildClassNameCompletions.bind(this), ' ');
302 this.disableDefaultSuggestionForEmptyInput();
303 this._selectedFrameId = '';
304 this._classNamesPromise = null;
305 }
306
Jan Scheffler29905852021-04-14 11:30:31307 async _getClassNames(selectedNode: SDK.DOMModel.DOMNode): Promise<string[]> {
Blink Reformat4c46d092018-04-07 15:32:37308 const promises = [];
Jan Scheffler29905852021-04-14 11:30:31309 const completions = new Set<string>();
Blink Reformat4c46d092018-04-07 15:32:37310 this._selectedFrameId = selectedNode.frameId();
311
312 const cssModel = selectedNode.domModel().cssModel();
313 const allStyleSheets = cssModel.allStyleSheets();
314 for (const stylesheet of allStyleSheets) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34315 if (stylesheet.frameId !== this._selectedFrameId) {
Blink Reformat4c46d092018-04-07 15:32:37316 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34317 }
Mathias Bynens3abc0952020-04-20 14:15:52318 const cssPromise = cssModel.classNamesPromise(stylesheet.id).then(classes => {
319 for (const className of classes) {
320 completions.add(className);
321 }
322 });
Blink Reformat4c46d092018-04-07 15:32:37323 promises.push(cssPromise);
324 }
325
Jan Scheffler29905852021-04-14 11:30:31326 const ownerDocumentId = ((selectedNode.ownerDocument as SDK.DOMModel.DOMDocument).id);
Tim van der Lippe32f760f2020-10-01 10:52:15327
328 const domPromise = selectedNode.domModel().classNamesPromise(ownerDocumentId).then(classes => {
Mathias Bynens3abc0952020-04-20 14:15:52329 for (const className of classes) {
330 completions.add(className);
331 }
332 });
Blink Reformat4c46d092018-04-07 15:32:37333 promises.push(domPromise);
Mathias Bynens3abc0952020-04-20 14:15:52334 await Promise.all(promises);
335 return [...completions];
Blink Reformat4c46d092018-04-07 15:32:37336 }
337
Jan Scheffler29905852021-04-14 11:30:31338 async _buildClassNameCompletions(expression: string, prefix: string, force?: boolean):
339 Promise<UI.SuggestBox.Suggestions> {
Tim van der Lippe1d6e57a2019-09-30 11:55:34340 if (!prefix || force) {
Blink Reformat4c46d092018-04-07 15:32:37341 this._classNamesPromise = null;
Tim van der Lippe1d6e57a2019-09-30 11:55:34342 }
Blink Reformat4c46d092018-04-07 15:32:37343
Tim van der Lipped1a00aa2020-08-19 16:03:56344 const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34345 if (!selectedNode || (!prefix && !force && !expression.trim())) {
Mathias Bynens41ea2632020-12-24 05:52:49346 return [];
Tim van der Lippe1d6e57a2019-09-30 11:55:34347 }
Blink Reformat4c46d092018-04-07 15:32:37348
Tim van der Lippe1d6e57a2019-09-30 11:55:34349 if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.frameId()) {
Blink Reformat4c46d092018-04-07 15:32:37350 this._classNamesPromise = this._getClassNames(selectedNode);
Tim van der Lippe1d6e57a2019-09-30 11:55:34351 }
Blink Reformat4c46d092018-04-07 15:32:37352
Jan Scheffler29905852021-04-14 11:30:31353 let completions: string[] = await this._classNamesPromise;
354 const classesMap = this._nodeClasses((selectedNode as SDK.DOMModel.DOMNode));
Mathias Bynens41ea2632020-12-24 05:52:49355 completions = completions.filter(value => !classesMap.get(value));
Blink Reformat4c46d092018-04-07 15:32:37356
Mathias Bynens41ea2632020-12-24 05:52:49357 if (prefix[0] === '.') {
358 completions = completions.map(value => '.' + value);
359 }
360 return completions.filter(value => value.startsWith(prefix)).sort().map(completion => {
361 return {
362 text: completion,
363 title: undefined,
364 subtitle: undefined,
365 iconType: undefined,
366 priority: undefined,
367 isSecondary: undefined,
368 subtitleRenderer: undefined,
369 selectionRange: undefined,
370 hideGhostText: undefined,
371 iconElement: undefined,
372 };
Blink Reformat4c46d092018-04-07 15:32:37373 });
374 }
Tim van der Lippe13f71fb2019-11-29 11:17:39375}