Changeset 195432 in webkit
- Timestamp:
- Jan 21, 2016 6:06:49 PM (8 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r195376 r195432 1 2016-01-21 Devin Rousso <dcrousso+webkit@gmail.com> 2 3 Web Inspector: Add toggle-able list of classes for each element 4 https://bugs.webkit.org/show_bug.cgi?id=152678 5 6 Reviewed by Timothy Hatcher. 7 8 Adds a button to the CSS sidebar that, when toggled, displays a section 9 directly above it containing all the classes for the selected node that, 10 when toggled, adds or removes the class from the node. 11 12 * Localizations/en.lproj/localizedStrings.js: 13 14 * UserInterface/Protocol/RemoteObject.js: 15 (WebInspector.RemoteObject.prototype.callFunction.mycallback): 16 (WebInspector.RemoteObject.prototype.callFunction): 17 Add extra handling of arguments to allow nicer looking calls by other classes. 18 19 * UserInterface/Views/CSSStyleDetailsSidebarPanel.css: 20 Changed next-sibling selector (+) to general-sibling selector (~). 21 22 (.sidebar > .panel.details.css-style > .content ~ :matches(.options-container, .class-list-container)): 23 (.sidebar > .panel.details.css-style > .content:not(.supports-new-rule, .has-filter-bar) ~ :matches(.options-container, .class-list-container)): 24 (.sidebar > .panel.details.css-style > .content ~ .options-container > .toggle-class-toggle): 25 (.sidebar > .panel.details.css-style > .content ~ .options-container > .toggle-class-toggle.selected): 26 (.sidebar > .panel.details.css-style > .content ~ .options-container > .toggle-class-toggle:not(.selected):hover): 27 (.sidebar > .panel.details.css-style > .content ~ .class-list-container): 28 (.sidebar > .panel.details.css-style > .content ~ .class-list-container[hidden]): 29 (.sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class): 30 (.sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class > input[type="checkbox"]): 31 (.sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class > .add-class-icon): 32 (.sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class > .class-name-input): 33 (.sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class:not(.active) > .class-name-input): 34 (.sidebar > .panel.details.css-style > .content ~ .class-list-container > *:matches(.new-class, .class-toggle)): 35 36 * UserInterface/Views/CSSStyleDetailsSidebarPanel.js: 37 (WebInspector.CSSStyleDetailsSidebarPanel): 38 Also changed the few instances of "var" to "let". 39 40 (WebInspector.CSSStyleDetailsSidebarPanel.prototype.refresh): 41 (WebInspector.CSSStyleDetailsSidebarPanel.prototype.addEventListeners): 42 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._handleNodeAttributeModified): 43 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._handleNodeAttributeRemoved): 44 Adds listeners to the DOMNode specifically listening for changes to the 45 class attribute and repopulates the class toggle list if fired. 46 47 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._classToggleButtonClicked): 48 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._addClassContainerClicked): 49 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._addClassInputKeyPressed): 50 If the Enter key is pressed, add a new class equal to the input value. 51 52 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._addClassInputBlur): 53 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._populateClassToggles): 54 Loops through all the classes, including previously removed ones, for the 55 selected node and creates a toggle for each. 56 57 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._createToggleForClassName.classNameToggleChanged): 58 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._createToggleForClassName): 59 Creates a toggle element for the given className and adds it to the container. 60 61 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._toggleClass.resolvedNode.toggleClass): 62 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._toggleClass.resolvedNode): 63 (WebInspector.CSSStyleDetailsSidebarPanel.prototype._toggleClass): 64 Uses the Element.classList to toggle the given className on the selected node. 65 1 66 2016-01-20 Saam barati <sbarati@apple.com> 2 67 -
trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
r195376 r195432 54 54 localizedStrings["Add New Probe Expression"] = "Add New Probe Expression"; 55 55 localizedStrings["Add New Watch Expression"] = "Add New Watch Expression"; 56 localizedStrings["Add a Class"] = "Add a Class"; 56 57 localizedStrings["Add new breakpoint action after this action"] = "Add new breakpoint action after this action"; 57 58 localizedStrings["Add probe expression"] = "Add probe expression"; … … 117 118 localizedStrings["Child Layers"] = "Child Layers"; 118 119 localizedStrings["Children"] = "Children"; 120 localizedStrings["Classes"] = "Classes"; 119 121 localizedStrings["Clear"] = "Clear"; 120 122 localizedStrings["Clear Log"] = "Clear Log"; … … 267 269 localizedStrings["Encoding"] = "Encoding"; 268 270 localizedStrings["End Capturing"] = "End Capturing"; 271 localizedStrings["Enter Class Name"] = "Enter Class Name"; 269 272 localizedStrings["Enter a Gradient"] = "Enter a Gradient"; 270 273 localizedStrings["Enter a URL"] = "Enter a URL"; … … 648 651 localizedStrings["Timestamp \u2014 %s"] = "Timestamp \u2014 %s"; 649 652 localizedStrings["Timing"] = "Timing"; 653 localizedStrings["Toggle Classes"] = "Toggle Classes"; 650 654 localizedStrings["Top"] = "Top"; 651 655 localizedStrings["Total Time"] = "Total Time"; -
trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js
r194311 r195432 417 417 { 418 418 result = result ? WebInspector.RemoteObject.fromPayload(result) : null; 419 callback(error, result, wasThrown); 419 420 if (callback && typeof callback === "function") 421 callback(error, result, wasThrown); 420 422 } 421 423 … … 423 425 args = args.map(WebInspector.RemoteObject.createCallArgument); 424 426 425 RuntimeAgent.callFunctionOn(this._objectId, appendWebInspectorSourceURL(functionDeclaration.toString()), args, true, undefined, generatePreview, mycallback);427 RuntimeAgent.callFunctionOn(this._objectId, appendWebInspectorSourceURL(functionDeclaration.toString()), args, true, undefined, !!generatePreview, mycallback); 426 428 } 427 429 -
trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.css
r189733 r195432 66 66 } 67 67 68 .sidebar > .panel.details.css-style > .content + .options-container{68 .sidebar > .panel.details.css-style > .content ~ :matches(.options-container, .class-list-container) { 69 69 display: flex; 70 70 align-items: center; 71 71 position: absolute; 72 bottom: 0;73 72 width: 100%; 74 height: 29px;75 73 background-color: white; 76 74 border-top: 1px solid hsl(0, 0%, 70%); 77 75 } 78 76 79 .sidebar > .panel.details.css-style > .content:not(.supports-new-rule, .has-filter-bar) + .options-container { 77 .sidebar > .panel.details.css-style > .content ~ .options-container { 78 bottom: 0; 79 height: 30px; 80 } 81 82 .sidebar > .panel.details.css-style > .content:not(.supports-new-rule, .has-filter-bar) ~ :matches(.options-container, .class-list-container) { 80 83 display: none; 81 84 } 82 85 83 .sidebar > .panel.details.css-style > .content +.options-container > .new-rule {86 .sidebar > .panel.details.css-style > .content ~ .options-container > .new-rule { 84 87 width: 15px; 85 88 min-width: 15px; … … 90 93 } 91 94 92 .sidebar > .panel.details.css-style > .content +.options-container > .filter-bar {95 .sidebar > .panel.details.css-style > .content ~ .options-container > .filter-bar { 93 96 width: -webkit-fill-available; 94 97 background-color: transparent; 95 98 } 96 99 97 .sidebar > .panel.details.css-style > .content:not(.supports-new-rule) + .options-container > .new-rule, 98 .sidebar > .panel.details.css-style > .content:not(.has-filter-bar) + .options-container > .filter-bar { 100 .sidebar > .panel.details.css-style > .content ~ .options-container > .toggle-class-toggle { 101 margin: 0 5px 1px 0; 102 padding: 2px 4px 3px; 103 background: none; 104 border: none; 105 border-radius: 3px; 106 -webkit-appearance: none; 107 } 108 109 .sidebar > .panel.details.css-style > .content ~ .options-container > .toggle-class-toggle.selected { 110 color: white; 111 background-color: hsl(212, 92%, 54%); 112 } 113 114 .sidebar > .panel.details.css-style > .content ~ .options-container > .toggle-class-toggle:not(.selected):hover { 115 color: white; 116 background-color: hsla(212, 92%, 54%, 0.5); 117 } 118 119 .sidebar > .panel.details.css-style > .content:not(.supports-new-rule) ~ .options-container > .new-rule, 120 .sidebar > .panel.details.css-style > .content:not(.has-filter-bar) ~ .options-container > .filter-bar { 99 121 display: none; 122 } 123 124 .sidebar > .panel.details.css-style > .content ~ .class-list-container { 125 flex-wrap: wrap; 126 bottom: 30px; 127 max-height: 65px; 128 padding: 3px 2px; 129 overflow-y: scroll; 130 } 131 132 /* FIXME: <https://webkit.org/b/152674> Elements with the "hidden" attribute still show up if "display: flex;" */ 133 .sidebar > .panel.details.css-style > .content ~ .class-list-container[hidden] { 134 display: none; 135 } 136 137 .sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class { 138 display: flex; 139 align-items: center; 140 } 141 142 .sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class > input[type="checkbox"] { 143 pointer-events: none; 144 } 145 146 .sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class > .add-class-icon { 147 width: 12px; 148 height: 12px; 149 } 150 151 .sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class > .class-name-input { 152 width: 100px; 153 height: 18px; 154 margin: 0 0 0 2px; 155 } 156 157 .sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class.active > .add-class-icon, 158 .sidebar > .panel.details.css-style > .content ~ .class-list-container > .new-class:not(.active) > .class-name-input { 159 display: none; 160 } 161 162 .sidebar > .panel.details.css-style > .content ~ .class-list-container > *:matches(.new-class, .class-toggle) { 163 margin: 1px 3px; 100 164 } 101 165 -
trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js
r194116 r195432 38 38 this._forcedPseudoClassContainer.className = "pseudo-classes"; 39 39 40 vargroupElement = null;40 let groupElement = null; 41 41 42 42 WebInspector.CSSStyleManager.ForceablePseudoClasses.forEach(function(pseudoClass) { 43 43 // We don't localize the label since it is a CSS pseudo-class from the CSS standard. 44 varlabel = pseudoClass.capitalize();45 46 varlabelElement = document.createElement("label");47 48 varcheckboxElement = document.createElement("input");44 let label = pseudoClass.capitalize(); 45 46 let labelElement = document.createElement("label"); 47 48 let checkboxElement = document.createElement("input"); 49 49 checkboxElement.addEventListener("change", this._forcedPseudoClassCheckboxChanged.bind(this, pseudoClass)); 50 50 checkboxElement.type = "checkbox"; … … 88 88 this._navigationItem.addEventListener(WebInspector.ScopeRadioButtonNavigationItem.Event.SelectedItemChanged, this._handleSelectedItemChanged, this); 89 89 90 var optionsContainer = document.createElement("div"); 91 optionsContainer.classList.add("options-container"); 92 93 var newRuleButton = document.createElement("img"); 94 newRuleButton.classList.add("new-rule"); 90 let optionsContainer = this.element.createChild("div", "options-container"); 91 92 let newRuleButton = optionsContainer.createChild("img", "new-rule"); 95 93 newRuleButton.title = WebInspector.UIString("New Rule"); 96 94 newRuleButton.addEventListener("click", this._newRuleButtonClicked.bind(this)); 97 optionsContainer.appendChild(newRuleButton);98 95 99 96 this._filterBar = new WebInspector.FilterBar; … … 102 99 optionsContainer.appendChild(this._filterBar.element); 103 100 101 this._classToggleButton = optionsContainer.createChild("button", "toggle-class-toggle"); 102 this._classToggleButton.textContent = WebInspector.UIString("Classes"); 103 this._classToggleButton.title = WebInspector.UIString("Toggle Classes"); 104 this._classToggleButton.addEventListener("click", this._classToggleButtonClicked.bind(this)); 105 106 this._classListContainer = this.element.createChild("div", "class-list-container"); 107 this._classListContainer.hidden = true; 108 109 this._addClassContainer = this._classListContainer.createChild("div", "new-class"); 110 this._addClassContainer.title = WebInspector.UIString("Add a Class"); 111 this._addClassContainer.addEventListener("click", this._addClassContainerClicked.bind(this)); 112 113 let addClassCheckbox = this._addClassContainer.createChild("input"); 114 addClassCheckbox.type = "checkbox"; 115 addClassCheckbox.checked = true; 116 117 let addClassIcon = useSVGSymbol("Images/Plus13.svg", "add-class-icon"); 118 this._addClassContainer.appendChild(addClassIcon); 119 120 this._addClassInput = this._addClassContainer.createChild("input", "class-name-input"); 121 this._addClassInput.setAttribute("placeholder", WebInspector.UIString("Enter Class Name")); 122 this._addClassInput.addEventListener("keypress", this._addClassInputKeyPressed.bind(this)); 123 this._addClassInput.addEventListener("blur", this._addClassInputBlur.bind(this)); 124 104 125 WebInspector.cssStyleManager.addEventListener(WebInspector.CSSStyleManager.Event.StyleSheetAdded, this.refresh, this); 105 126 WebInspector.cssStyleManager.addEventListener(WebInspector.CSSStyleManager.Event.StyleSheetRemoved, this.refresh, this); 106 107 this.element.appendChild(optionsContainer);108 127 } 109 128 … … 117 136 refresh() 118 137 { 119 vardomNode = this.domNode;138 let domNode = this.domNode; 120 139 if (!domNode) 121 140 return; … … 123 142 this.contentView.element.scrollTop = this._initialScrollOffset; 124 143 125 for ( varpanel of this._panels) {144 for (let panel of this._panels) { 126 145 panel.element._savedScrollTop = undefined; 127 146 panel.markAsNeedsRefresh(domNode); … … 129 148 130 149 this._updatePseudoClassCheckboxes(); 150 151 if (!this._classListContainer.hidden) 152 this._populateClassToggles(); 131 153 } 132 154 … … 169 191 addEventListeners() 170 192 { 171 vareffectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;193 let effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode; 172 194 if (!effectiveDOMNode) 173 195 return; 174 196 175 197 effectiveDOMNode.addEventListener(WebInspector.DOMNode.Event.EnabledPseudoClassesChanged, this._updatePseudoClassCheckboxes, this); 198 effectiveDOMNode.addEventListener(WebInspector.DOMNode.Event.AttributeModified, this._handleNodeAttributeModified, this); 199 effectiveDOMNode.addEventListener(WebInspector.DOMNode.Event.AttributeRemoved, this._handleNodeAttributeRemoved, this); 176 200 } 177 201 178 202 removeEventListeners() 179 203 { 180 vareffectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;204 let effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode; 181 205 if (!effectiveDOMNode) 182 206 return; … … 202 226 _panelMatchingIdentifier(identifier) 203 227 { 204 var selectedPanel 205 206 for (var panel of this._panels) { 228 let selectedPanel = null; 229 for (let panel of this._panels) { 207 230 if (panel.navigationInfo.identifier !== identifier) 208 231 continue; … … 217 240 _handleSelectedItemChanged() 218 241 { 219 varselectedIdentifier = this._navigationItem.selectedItemIdentifier;220 varselectedPanel = this._panelMatchingIdentifier(selectedIdentifier);242 let selectedIdentifier = this._navigationItem.selectedItemIdentifier; 243 let selectedPanel = this._panelMatchingIdentifier(selectedIdentifier); 221 244 this._switchPanels(selectedPanel); 222 245 } … … 259 282 return; 260 283 261 vareffectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;284 let effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode; 262 285 263 286 effectiveDOMNode.setPseudoClassEnabled(pseudoClass, event.target.checked); … … 269 292 return; 270 293 271 vareffectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;272 273 varenabledPseudoClasses = effectiveDOMNode.enabledPseudoClasses;274 275 for ( varpseudoClass in this._forcedPseudoClassCheckboxes) {276 varcheckboxElement = this._forcedPseudoClassCheckboxes[pseudoClass];294 let effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode; 295 296 let enabledPseudoClasses = effectiveDOMNode.enabledPseudoClasses; 297 298 for (let pseudoClass in this._forcedPseudoClassCheckboxes) { 299 let checkboxElement = this._forcedPseudoClassCheckboxes[pseudoClass]; 277 300 checkboxElement.checked = enabledPseudoClasses.includes(pseudoClass); 278 301 } 279 302 } 303 304 _handleNodeAttributeModified(event) 305 { 306 if (event && event.data && event.data.name === "class") 307 this._populateClassToggles(); 308 } 309 310 _handleNodeAttributeRemoved(event) 311 { 312 if (event && event.data && event.data.name === "class") 313 this._populateClassToggles(); 314 } 315 280 316 281 317 _newRuleButtonClicked() … … 283 319 if (this._selectedPanel && typeof this._selectedPanel.newRuleButtonClicked === "function") 284 320 this._selectedPanel.newRuleButtonClicked(); 321 } 322 323 _classToggleButtonClicked(event) 324 { 325 this._classToggleButton.classList.toggle("selected"); 326 this._classListContainer.hidden = !this._classListContainer.hidden; 327 if (this._classListContainer.hidden) 328 return; 329 330 this._populateClassToggles(); 331 } 332 333 _addClassContainerClicked(event) 334 { 335 this._addClassContainer.classList.add("active"); 336 this._addClassInput.focus(); 337 } 338 339 _addClassInputKeyPressed(event) 340 { 341 if (event.keyCode !== WebInspector.KeyboardShortcut.Key.Enter.keyCode) 342 return; 343 344 this._addClassInput.blur(); 345 } 346 347 _addClassInputBlur(event) 348 { 349 this._toggleClass.call(this, this._addClassInput.value, true); 350 this._addClassContainer.classList.remove("active"); 351 this._addClassInput.value = null; 352 } 353 354 _populateClassToggles() 355 { 356 this._classListContainer.removeChildren(); 357 this._classListContainer.appendChild(this._addClassContainer); 358 359 let classes = this.domNode.getAttribute("class"); 360 let classToggledMap = this.domNode[WebInspector.CSSStyleDetailsSidebarPanel.ToggledClassesSymbol]; 361 if (!classToggledMap) 362 classToggledMap = this.domNode[WebInspector.CSSStyleDetailsSidebarPanel.ToggledClassesSymbol] = new Map; 363 364 if (classes && classes.length) { 365 for (let className of classes.split(/\s+/)) 366 classToggledMap.set(className, true); 367 } 368 369 for (let [className, toggled] of classToggledMap) { 370 if ((toggled && !classes.includes(className)) || (!toggled && classes.includes(className))) { 371 toggled = !toggled; 372 classToggledMap.set(className, toggled); 373 } 374 375 this._createToggleForClassName(className); 376 } 377 } 378 379 _createToggleForClassName(className) 380 { 381 if (!className || !className.length) 382 return; 383 384 let classToggledMap = this.domNode[WebInspector.CSSStyleDetailsSidebarPanel.ToggledClassesSymbol]; 385 if (!classToggledMap) 386 return; 387 388 if (!classToggledMap.has(className)) 389 classToggledMap.set(className, true); 390 391 let toggled = classToggledMap.get(className); 392 393 let classNameContainer = document.createElement("div"); 394 classNameContainer.classList.add("class-toggle"); 395 396 let classNameToggle = classNameContainer.createChild("input"); 397 classNameToggle.type = "checkbox"; 398 classNameToggle.checked = toggled; 399 400 let classNameTitle = classNameContainer.createChild("span"); 401 classNameTitle.textContent = className; 402 403 function classNameToggleChanged(event) { 404 this._toggleClass.call(this, className, classNameToggle.checked); 405 classToggledMap.set(className, classNameToggle.checked); 406 } 407 408 classNameToggle.addEventListener("click", classNameToggleChanged.bind(this)); 409 classNameTitle.addEventListener("click", (event) => { 410 classNameToggle.checked = !classNameToggle.checked; 411 classNameToggleChanged.call(this); 412 }); 413 414 this._classListContainer.appendChild(classNameContainer); 415 } 416 417 _toggleClass(className, flag) 418 { 419 if (!className || !className.length) 420 return; 421 422 let effectiveNode = this.domNode; 423 if (effectiveNode && effectiveNode.isPseudoElement()) 424 effectiveNode = effectiveNode.parentNode; 425 426 console.assert(effectiveNode); 427 if (!effectiveNode) 428 return; 429 430 if (effectiveNode.nodeType() !== Node.ELEMENT_NODE) 431 return; 432 433 function resolvedNode(object) 434 { 435 if (!object) 436 return; 437 438 function toggleClass(className, flag) 439 { 440 this.classList.toggle(className, flag); 441 } 442 443 object.callFunction(toggleClass, [className, flag]); 444 object.release(); 445 } 446 447 WebInspector.RemoteObject.resolveNode(effectiveNode, "", resolvedNode); 285 448 } 286 449 … … 300 463 WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName = "filter-property-non-matching"; 301 464 465 WebInspector.CSSStyleDetailsSidebarPanel.ToggledClassesSymbol = Symbol("css-style-details-sidebar-panel-toggled-classes-symbol");
Note: See TracChangeset
for help on using the changeset viewer.