| OLD | NEW |
| 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 * @unrestricted | 5 * @unrestricted |
| 6 */ | 6 */ |
| 7 WebInspector.ClassesPaneWidget = class extends WebInspector.Widget { | 7 Elements.ClassesPaneWidget = class extends UI.Widget { |
| 8 constructor() { | 8 constructor() { |
| 9 super(); | 9 super(); |
| 10 this.element.className = 'styles-element-classes-pane'; | 10 this.element.className = 'styles-element-classes-pane'; |
| 11 var container = this.element.createChild('div', 'title-container'); | 11 var container = this.element.createChild('div', 'title-container'); |
| 12 this._input = container.createChild('div', 'new-class-input monospace'); | 12 this._input = container.createChild('div', 'new-class-input monospace'); |
| 13 this._input.setAttribute('placeholder', WebInspector.UIString('Add new class
')); | 13 this._input.setAttribute('placeholder', Common.UIString('Add new class')); |
| 14 this.setDefaultFocusedElement(this._input); | 14 this.setDefaultFocusedElement(this._input); |
| 15 this._classesContainer = this.element.createChild('div', 'source-code'); | 15 this._classesContainer = this.element.createChild('div', 'source-code'); |
| 16 this._classesContainer.classList.add('styles-element-classes-container'); | 16 this._classesContainer.classList.add('styles-element-classes-container'); |
| 17 this._prompt = new WebInspector.ClassesPaneWidget.ClassNamePrompt(); | 17 this._prompt = new Elements.ClassesPaneWidget.ClassNamePrompt(); |
| 18 this._prompt.setAutocompletionTimeout(0); | 18 this._prompt.setAutocompletionTimeout(0); |
| 19 this._prompt.renderAsBlock(); | 19 this._prompt.renderAsBlock(); |
| 20 | 20 |
| 21 var proxyElement = this._prompt.attach(this._input); | 21 var proxyElement = this._prompt.attach(this._input); |
| 22 proxyElement.addEventListener('keydown', this._onKeyDown.bind(this), false); | 22 proxyElement.addEventListener('keydown', this._onKeyDown.bind(this), false); |
| 23 | 23 |
| 24 WebInspector.targetManager.addModelListener( | 24 SDK.targetManager.addModelListener( |
| 25 WebInspector.DOMModel, WebInspector.DOMModel.Events.DOMMutated, this._on
DOMMutated, this); | 25 SDK.DOMModel, SDK.DOMModel.Events.DOMMutated, this._onDOMMutated, this); |
| 26 /** @type {!Set<!WebInspector.DOMNode>} */ | 26 /** @type {!Set<!SDK.DOMNode>} */ |
| 27 this._mutatingNodes = new Set(); | 27 this._mutatingNodes = new Set(); |
| 28 WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._upd
ate, this); | 28 UI.context.addFlavorChangeListener(SDK.DOMNode, this._update, this); |
| 29 } | 29 } |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * @param {!Event} event | 32 * @param {!Event} event |
| 33 */ | 33 */ |
| 34 _onKeyDown(event) { | 34 _onKeyDown(event) { |
| 35 var text = event.target.textContent; | 35 var text = event.target.textContent; |
| 36 if (isEscKey(event)) { | 36 if (isEscKey(event)) { |
| 37 event.target.textContent = ''; | 37 event.target.textContent = ''; |
| 38 if (!text.isWhitespace()) | 38 if (!text.isWhitespace()) |
| 39 event.consume(true); | 39 event.consume(true); |
| 40 return; | 40 return; |
| 41 } | 41 } |
| 42 | 42 |
| 43 if (!isEnterKey(event)) | 43 if (!isEnterKey(event)) |
| 44 return; | 44 return; |
| 45 var node = WebInspector.context.flavor(WebInspector.DOMNode); | 45 var node = UI.context.flavor(SDK.DOMNode); |
| 46 if (!node) | 46 if (!node) |
| 47 return; | 47 return; |
| 48 | 48 |
| 49 this._prompt.clearAutocomplete(); | 49 this._prompt.clearAutocomplete(); |
| 50 event.target.textContent = ''; | 50 event.target.textContent = ''; |
| 51 var classNames = text.split(/[.,\s]/); | 51 var classNames = text.split(/[.,\s]/); |
| 52 for (var className of classNames) { | 52 for (var className of classNames) { |
| 53 var className = className.trim(); | 53 var className = className.trim(); |
| 54 if (!className.length) | 54 if (!className.length) |
| 55 continue; | 55 continue; |
| 56 this._toggleClass(node, className, true); | 56 this._toggleClass(node, className, true); |
| 57 } | 57 } |
| 58 this._installNodeClasses(node); | 58 this._installNodeClasses(node); |
| 59 this._update(); | 59 this._update(); |
| 60 event.consume(true); | 60 event.consume(true); |
| 61 } | 61 } |
| 62 | 62 |
| 63 /** | 63 /** |
| 64 * @param {!WebInspector.Event} event | 64 * @param {!Common.Event} event |
| 65 */ | 65 */ |
| 66 _onDOMMutated(event) { | 66 _onDOMMutated(event) { |
| 67 var node = /** @type {!WebInspector.DOMNode} */ (event.data); | 67 var node = /** @type {!SDK.DOMNode} */ (event.data); |
| 68 if (this._mutatingNodes.has(node)) | 68 if (this._mutatingNodes.has(node)) |
| 69 return; | 69 return; |
| 70 delete node[WebInspector.ClassesPaneWidget._classesSymbol]; | 70 delete node[Elements.ClassesPaneWidget._classesSymbol]; |
| 71 this._update(); | 71 this._update(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 /** | 74 /** |
| 75 * @override | 75 * @override |
| 76 */ | 76 */ |
| 77 wasShown() { | 77 wasShown() { |
| 78 this._update(); | 78 this._update(); |
| 79 } | 79 } |
| 80 | 80 |
| 81 _update() { | 81 _update() { |
| 82 if (!this.isShowing()) | 82 if (!this.isShowing()) |
| 83 return; | 83 return; |
| 84 | 84 |
| 85 var node = WebInspector.context.flavor(WebInspector.DOMNode); | 85 var node = UI.context.flavor(SDK.DOMNode); |
| 86 if (node) | 86 if (node) |
| 87 node = node.enclosingElementOrSelf(); | 87 node = node.enclosingElementOrSelf(); |
| 88 | 88 |
| 89 this._classesContainer.removeChildren(); | 89 this._classesContainer.removeChildren(); |
| 90 this._input.disabled = !node; | 90 this._input.disabled = !node; |
| 91 | 91 |
| 92 if (!node) | 92 if (!node) |
| 93 return; | 93 return; |
| 94 | 94 |
| 95 var classes = this._nodeClasses(node); | 95 var classes = this._nodeClasses(node); |
| 96 var keys = classes.keysArray(); | 96 var keys = classes.keysArray(); |
| 97 keys.sort(String.caseInsensetiveComparator); | 97 keys.sort(String.caseInsensetiveComparator); |
| 98 for (var i = 0; i < keys.length; ++i) { | 98 for (var i = 0; i < keys.length; ++i) { |
| 99 var className = keys[i]; | 99 var className = keys[i]; |
| 100 var label = createCheckboxLabel(className, classes.get(className)); | 100 var label = createCheckboxLabel(className, classes.get(className)); |
| 101 label.visualizeFocus = true; | 101 label.visualizeFocus = true; |
| 102 label.classList.add('monospace'); | 102 label.classList.add('monospace'); |
| 103 label.checkboxElement.addEventListener('click', this._onClick.bind(this, c
lassName), false); | 103 label.checkboxElement.addEventListener('click', this._onClick.bind(this, c
lassName), false); |
| 104 this._classesContainer.appendChild(label); | 104 this._classesContainer.appendChild(label); |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 | 107 |
| 108 /** | 108 /** |
| 109 * @param {string} className | 109 * @param {string} className |
| 110 * @param {!Event} event | 110 * @param {!Event} event |
| 111 */ | 111 */ |
| 112 _onClick(className, event) { | 112 _onClick(className, event) { |
| 113 var node = WebInspector.context.flavor(WebInspector.DOMNode); | 113 var node = UI.context.flavor(SDK.DOMNode); |
| 114 if (!node) | 114 if (!node) |
| 115 return; | 115 return; |
| 116 var enabled = event.target.checked; | 116 var enabled = event.target.checked; |
| 117 this._toggleClass(node, className, enabled); | 117 this._toggleClass(node, className, enabled); |
| 118 this._installNodeClasses(node); | 118 this._installNodeClasses(node); |
| 119 } | 119 } |
| 120 | 120 |
| 121 /** | 121 /** |
| 122 * @param {!WebInspector.DOMNode} node | 122 * @param {!SDK.DOMNode} node |
| 123 * @return {!Map<string, boolean>} | 123 * @return {!Map<string, boolean>} |
| 124 */ | 124 */ |
| 125 _nodeClasses(node) { | 125 _nodeClasses(node) { |
| 126 var result = node[WebInspector.ClassesPaneWidget._classesSymbol]; | 126 var result = node[Elements.ClassesPaneWidget._classesSymbol]; |
| 127 if (!result) { | 127 if (!result) { |
| 128 var classAttribute = node.getAttribute('class') || ''; | 128 var classAttribute = node.getAttribute('class') || ''; |
| 129 var classes = classAttribute.split(/\s/); | 129 var classes = classAttribute.split(/\s/); |
| 130 result = new Map(); | 130 result = new Map(); |
| 131 for (var i = 0; i < classes.length; ++i) { | 131 for (var i = 0; i < classes.length; ++i) { |
| 132 var className = classes[i].trim(); | 132 var className = classes[i].trim(); |
| 133 if (!className.length) | 133 if (!className.length) |
| 134 continue; | 134 continue; |
| 135 result.set(className, true); | 135 result.set(className, true); |
| 136 } | 136 } |
| 137 node[WebInspector.ClassesPaneWidget._classesSymbol] = result; | 137 node[Elements.ClassesPaneWidget._classesSymbol] = result; |
| 138 } | 138 } |
| 139 return result; | 139 return result; |
| 140 } | 140 } |
| 141 | 141 |
| 142 /** | 142 /** |
| 143 * @param {!WebInspector.DOMNode} node | 143 * @param {!SDK.DOMNode} node |
| 144 * @param {string} className | 144 * @param {string} className |
| 145 * @param {boolean} enabled | 145 * @param {boolean} enabled |
| 146 */ | 146 */ |
| 147 _toggleClass(node, className, enabled) { | 147 _toggleClass(node, className, enabled) { |
| 148 var classes = this._nodeClasses(node); | 148 var classes = this._nodeClasses(node); |
| 149 classes.set(className, enabled); | 149 classes.set(className, enabled); |
| 150 } | 150 } |
| 151 | 151 |
| 152 /** | 152 /** |
| 153 * @param {!WebInspector.DOMNode} node | 153 * @param {!SDK.DOMNode} node |
| 154 */ | 154 */ |
| 155 _installNodeClasses(node) { | 155 _installNodeClasses(node) { |
| 156 var classes = this._nodeClasses(node); | 156 var classes = this._nodeClasses(node); |
| 157 var activeClasses = new Set(); | 157 var activeClasses = new Set(); |
| 158 for (var className of classes.keys()) { | 158 for (var className of classes.keys()) { |
| 159 if (classes.get(className)) | 159 if (classes.get(className)) |
| 160 activeClasses.add(className); | 160 activeClasses.add(className); |
| 161 } | 161 } |
| 162 | 162 |
| 163 var newClasses = activeClasses.valuesArray(); | 163 var newClasses = activeClasses.valuesArray(); |
| 164 newClasses.sort(); | 164 newClasses.sort(); |
| 165 this._mutatingNodes.add(node); | 165 this._mutatingNodes.add(node); |
| 166 node.setAttributeValue('class', newClasses.join(' '), onClassNameUpdated.bin
d(this)); | 166 node.setAttributeValue('class', newClasses.join(' '), onClassNameUpdated.bin
d(this)); |
| 167 | 167 |
| 168 /** | 168 /** |
| 169 * @this {WebInspector.ClassesPaneWidget} | 169 * @this {Elements.ClassesPaneWidget} |
| 170 */ | 170 */ |
| 171 function onClassNameUpdated() { | 171 function onClassNameUpdated() { |
| 172 this._mutatingNodes.delete(node); | 172 this._mutatingNodes.delete(node); |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 }; | 175 }; |
| 176 | 176 |
| 177 WebInspector.ClassesPaneWidget._classesSymbol = Symbol('WebInspector.ClassesPane
Widget._classesSymbol'); | 177 Elements.ClassesPaneWidget._classesSymbol = Symbol('Elements.ClassesPaneWidget._
classesSymbol'); |
| 178 | 178 |
| 179 /** | 179 /** |
| 180 * @implements {WebInspector.ToolbarItem.Provider} | 180 * @implements {UI.ToolbarItem.Provider} |
| 181 * @unrestricted | 181 * @unrestricted |
| 182 */ | 182 */ |
| 183 WebInspector.ClassesPaneWidget.ButtonProvider = class { | 183 Elements.ClassesPaneWidget.ButtonProvider = class { |
| 184 constructor() { | 184 constructor() { |
| 185 this._button = new WebInspector.ToolbarToggle(WebInspector.UIString('Element
Classes'), ''); | 185 this._button = new UI.ToolbarToggle(Common.UIString('Element Classes'), ''); |
| 186 this._button.setText('.cls'); | 186 this._button.setText('.cls'); |
| 187 this._button.element.classList.add('monospace'); | 187 this._button.element.classList.add('monospace'); |
| 188 this._button.addEventListener('click', this._clicked, this); | 188 this._button.addEventListener('click', this._clicked, this); |
| 189 this._view = new WebInspector.ClassesPaneWidget(); | 189 this._view = new Elements.ClassesPaneWidget(); |
| 190 } | 190 } |
| 191 | 191 |
| 192 _clicked() { | 192 _clicked() { |
| 193 WebInspector.ElementsPanel.instance().showToolbarPane(!this._view.isShowing(
) ? this._view : null, this._button); | 193 Elements.ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ?
this._view : null, this._button); |
| 194 } | 194 } |
| 195 | 195 |
| 196 /** | 196 /** |
| 197 * @override | 197 * @override |
| 198 * @return {!WebInspector.ToolbarItem} | 198 * @return {!UI.ToolbarItem} |
| 199 */ | 199 */ |
| 200 item() { | 200 item() { |
| 201 return this._button; | 201 return this._button; |
| 202 } | 202 } |
| 203 }; | 203 }; |
| 204 | 204 |
| 205 /** | 205 /** |
| 206 * @unrestricted | 206 * @unrestricted |
| 207 */ | 207 */ |
| 208 WebInspector.ClassesPaneWidget.ClassNamePrompt = class extends WebInspector.Text
Prompt { | 208 Elements.ClassesPaneWidget.ClassNamePrompt = class extends UI.TextPrompt { |
| 209 constructor() { | 209 constructor() { |
| 210 super(); | 210 super(); |
| 211 this.initialize(this._buildClassNameCompletions.bind(this), ' '); | 211 this.initialize(this._buildClassNameCompletions.bind(this), ' '); |
| 212 this.setSuggestBoxEnabled(true); | 212 this.setSuggestBoxEnabled(true); |
| 213 this.disableDefaultSuggestionForEmptyInput(); | 213 this.disableDefaultSuggestionForEmptyInput(); |
| 214 this._selectedFrameId = ''; | 214 this._selectedFrameId = ''; |
| 215 this._classNamesPromise = null; | 215 this._classNamesPromise = null; |
| 216 } | 216 } |
| 217 | 217 |
| 218 /** | 218 /** |
| 219 * @param {!WebInspector.DOMNode} selectedNode | 219 * @param {!SDK.DOMNode} selectedNode |
| 220 * @return {!Promise.<!Array.<string>>} | 220 * @return {!Promise.<!Array.<string>>} |
| 221 */ | 221 */ |
| 222 _getClassNames(selectedNode) { | 222 _getClassNames(selectedNode) { |
| 223 var promises = []; | 223 var promises = []; |
| 224 var completions = new Set(); | 224 var completions = new Set(); |
| 225 this._selectedFrameId = selectedNode.frameId(); | 225 this._selectedFrameId = selectedNode.frameId(); |
| 226 | 226 |
| 227 var cssModel = WebInspector.CSSModel.fromTarget(selectedNode.target()); | 227 var cssModel = SDK.CSSModel.fromTarget(selectedNode.target()); |
| 228 var allStyleSheets = cssModel.allStyleSheets(); | 228 var allStyleSheets = cssModel.allStyleSheets(); |
| 229 for (var stylesheet of allStyleSheets) { | 229 for (var stylesheet of allStyleSheets) { |
| 230 if (stylesheet.frameId !== this._selectedFrameId) | 230 if (stylesheet.frameId !== this._selectedFrameId) |
| 231 continue; | 231 continue; |
| 232 var cssPromise = cssModel.classNamesPromise(stylesheet.id).then(classes =>
completions.addAll(classes)); | 232 var cssPromise = cssModel.classNamesPromise(stylesheet.id).then(classes =>
completions.addAll(classes)); |
| 233 promises.push(cssPromise); | 233 promises.push(cssPromise); |
| 234 } | 234 } |
| 235 | 235 |
| 236 var domPromise = selectedNode.domModel() | 236 var domPromise = selectedNode.domModel() |
| 237 .classNamesPromise(selectedNode.ownerDocument.id) | 237 .classNamesPromise(selectedNode.ownerDocument.id) |
| 238 .then(classes => completions.addAll(classes)); | 238 .then(classes => completions.addAll(classes)); |
| 239 promises.push(domPromise); | 239 promises.push(domPromise); |
| 240 return Promise.all(promises).then(() => completions.valuesArray()); | 240 return Promise.all(promises).then(() => completions.valuesArray()); |
| 241 } | 241 } |
| 242 | 242 |
| 243 /** | 243 /** |
| 244 * @param {!Element} proxyElement | 244 * @param {!Element} proxyElement |
| 245 * @param {!Range} wordRange | 245 * @param {!Range} wordRange |
| 246 * @param {boolean} force | 246 * @param {boolean} force |
| 247 * @param {function(!Array.<string>, number=)} completionsReadyCallback | 247 * @param {function(!Array.<string>, number=)} completionsReadyCallback |
| 248 */ | 248 */ |
| 249 _buildClassNameCompletions(proxyElement, wordRange, force, completionsReadyCal
lback) { | 249 _buildClassNameCompletions(proxyElement, wordRange, force, completionsReadyCal
lback) { |
| 250 var prefix = wordRange.toString(); | 250 var prefix = wordRange.toString(); |
| 251 if (!prefix || force) | 251 if (!prefix || force) |
| 252 this._classNamesPromise = null; | 252 this._classNamesPromise = null; |
| 253 | 253 |
| 254 var selectedNode = WebInspector.context.flavor(WebInspector.DOMNode); | 254 var selectedNode = UI.context.flavor(SDK.DOMNode); |
| 255 if (!selectedNode || (!prefix && !force && !proxyElement.textContent.length)
) { | 255 if (!selectedNode || (!prefix && !force && !proxyElement.textContent.length)
) { |
| 256 completionsReadyCallback([]); | 256 completionsReadyCallback([]); |
| 257 return; | 257 return; |
| 258 } | 258 } |
| 259 | 259 |
| 260 if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.frame
Id()) | 260 if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.frame
Id()) |
| 261 this._classNamesPromise = this._getClassNames(selectedNode); | 261 this._classNamesPromise = this._getClassNames(selectedNode); |
| 262 | 262 |
| 263 this._classNamesPromise.then(completions => { | 263 this._classNamesPromise.then(completions => { |
| 264 if (prefix[0] === '.') | 264 if (prefix[0] === '.') |
| 265 completions = completions.map(value => '.' + value); | 265 completions = completions.map(value => '.' + value); |
| 266 var results = completions.filter(value => value.startsWith(prefix)); | 266 var results = completions.filter(value => value.startsWith(prefix)); |
| 267 completionsReadyCallback(results, 0); | 267 completionsReadyCallback(results, 0); |
| 268 }); | 268 }); |
| 269 } | 269 } |
| 270 }; | 270 }; |
| OLD | NEW |