Changeset 243264 in webkit
- Timestamp:
- Mar 20, 2019 5:22:06 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r243262 r243264 1 2019-03-20 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Styles Redesign: Editing selector should not hide the rule 4 https://bugs.webkit.org/show_bug.cgi?id=178489 5 <rdar://problem/35062434> 6 7 Reviewed by Timothy Hatcher. 8 9 * inspector/unit-tests/multimap.html: Added. 10 * inspector/unit-tests/multimap-expected.txt: Added. 11 1 12 2019-03-20 Ryan Haddad <ryanhaddad@apple.com> 2 13 -
trunk/Source/WebInspectorUI/ChangeLog
r243260 r243264 1 2019-03-20 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Styles Redesign: Editing selector should not hide the rule 4 https://bugs.webkit.org/show_bug.cgi?id=178489 5 <rdar://problem/35062434> 6 7 Reviewed by Timothy Hatcher. 8 9 Extracts the selector payload parsing logic inside `WI.DOMNodeStyles` into static functions 10 so that when the user changes the selector of a `WI.CSSRule`, it's able to process and 11 update itself with the new selector. This is mainly useful in the case where the `WI.CSSRule` 12 no longer applies to the selected node (meaning it won't be part of that node's 13 `WI.DOMNodeStyles`) in that it allows the `WI.SpreadsheetCSSStyleDeclarationSection` to 14 display the new selector text and the owner `WI.SpreadsheetRulesStyleDetailsPanel` to keep 15 that section visible even though it isn't applicable to the current node anymore. 16 17 * UserInterface/Models/DOMNodeStyles.js: 18 (WI.DOMNodeStyles): 19 (WI.DOMNodeStyles.parseSelectorListPayload): Added. 20 (WI.DOMNodeStyles.createSourceCodeLocation): Added. 21 (WI.DOMNodeStyles.prototype.refresh): 22 (WI.DOMNodeStyles.prototype.refresh.fetchedMatchedStyles): 23 (WI.DOMNodeStyles.prototype.refresh.fetchedInlineStyles): 24 (WI.DOMNodeStyles.prototype.refresh.fetchedComputedStyle): 25 (WI.DOMNodeStyles.prototype._parseStyleDeclarationPayload): 26 (WI.DOMNodeStyles.prototype._parseRulePayload): 27 (WI.DOMNodeStyles.prototype._styleSheetContentDidChange): 28 (WI.DOMNodeStyles.prototype.refresh.parseRuleMatchArrayPayload): Deleted. 29 (WI.DOMNodeStyles.prototype._createSourceCodeLocation): Deleted. 30 (WI.DOMNodeStyles.prototype._parseSelectorListPayload): Deleted. 31 Keep track of all `WI.CSSRule` and `WI.CSSStyleDeclaration` that have ever been associated 32 with this object, so that if a rule's selector is changed to no longer match, and then is 33 changed back to match again, we are able to update that rule instead of creating a new one. 34 35 * UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js: 36 (WI.SpreadsheetRulesStyleDetailsPanel.prototype.layout): 37 (WI.SpreadsheetRulesStyleDetailsPanel.prototype._handleSectionFilterApplied): 38 (WI.SpreadsheetRulesStyleDetailsPanel.prototype._handleSectionSelectorWillChange): Added. 39 Attempt to preserve the position of any sections that are changed and no longer apply to the 40 current node. 41 42 * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js: 43 (WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetSelectorFieldDidChange): 44 (WI.SpreadsheetCSSStyleDeclarationSection.prototype._renderSelector): 45 Drive-by: remove unused CSS classes. 46 47 * UserInterface/Models/CSSRule.js: 48 (WI.CSSRule.prototype.update): 49 (WI.CSSRule.prototype._selectorResolved): 50 Drive-by: remove unused event. 51 52 * UserInterface/Base/Multimap.js: 53 (Multimap.prototype.has): Added. 54 (Multimap.prototype.sets): Added. 55 (Multimap.prototype.copy): Added. 56 1 57 2019-03-20 Devin Rousso <drousso@apple.com> 2 58 -
trunk/Source/WebInspectorUI/UserInterface/Base/Multimap.js
r242743 r243264 35 35 36 36 // Public 37 38 has(key, value) 39 { 40 let valueSet = this._map.get(key); 41 if (!valueSet) 42 return false; 43 return value === undefined || valueSet.has(value); 44 } 37 45 38 46 get(key) … … 89 97 } 90 98 99 sets() 100 { 101 return this._map.entries(); 102 } 103 91 104 *[Symbol.iterator]() 92 105 { … … 97 110 } 98 111 112 copy() 113 { 114 return new Multimap(this.toJSON()); 115 } 116 99 117 toJSON() 100 118 { -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSRule.js
r243038 r243264 56 56 } 57 57 58 update(sourceCodeLocation, selectorText, selectors, matchedSelectorIndices, style, mediaList , dontFireEvents)58 update(sourceCodeLocation, selectorText, selectors, matchedSelectorIndices, style, mediaList) 59 59 { 60 60 sourceCodeLocation = sourceCodeLocation || null; … … 64 64 style = style || null; 65 65 mediaList = mediaList || []; 66 67 var changed = false;68 if (!dontFireEvents) {69 changed = this._selectorText !== selectorText || !Array.shallowEqual(this._selectors, selectors) ||70 !Array.shallowEqual(this._matchedSelectorIndices, matchedSelectorIndices) || this._style !== style ||71 !!this._sourceCodeLocation !== !!sourceCodeLocation || this._mediaList.length !== mediaList.length;72 // FIXME: Look for differences in the media list arrays.73 }74 66 75 67 if (this._style) … … 85 77 if (this._style) 86 78 this._style.ownerRule = this; 87 88 if (changed)89 this.dispatchEventToListeners(WI.CSSRule.Event.Changed);90 79 } 91 80 … … 163 152 _selectorResolved(rulePayload) 164 153 { 154 if (rulePayload) { 155 let selectorText = rulePayload.selectorList.text; 156 if (selectorText !== this._selectorText) { 157 let selectors = WI.DOMNodeStyles.parseSelectorListPayload(rulePayload.selectorList); 158 159 let sourceCodeLocation = null; 160 let sourceRange = rulePayload.selectorList.range; 161 if (sourceRange) { 162 sourceCodeLocation = WI.DOMNodeStyles.createSourceCodeLocation(rulePayload.sourceURL, { 163 line: sourceRange.startLine, 164 column: sourceRange.startColumn, 165 documentNode: this._nodeStyles.node.ownerDocument, 166 }); 167 } 168 169 if (this._ownerStyleSheet) { 170 if (!sourceCodeLocation && this._ownerStyleSheet.isInspectorStyleSheet()) 171 sourceCodeLocation = this._ownerStyleSheet.createSourceCodeLocation(sourceRange.startLine, sourceRange.startColumn); 172 173 sourceCodeLocation = this._ownerStyleSheet.offsetSourceCodeLocation(sourceCodeLocation); 174 } 175 176 this.update(sourceCodeLocation, selectorText, selectors, [], this._style, this._mediaList); 177 } 178 } 179 165 180 this.dispatchEventToListeners(WI.CSSRule.Event.SelectorChanged, {valid: !!rulePayload}); 166 181 } … … 168 183 169 184 WI.CSSRule.Event = { 170 Changed: "css-rule-changed",171 185 SelectorChanged: "css-rule-invalid-selector" 172 186 }; -
trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js
r242939 r243264 33 33 this._node = node || null; 34 34 35 this._rulesMap = {};36 this._style DeclarationsMap = {};35 this._rulesMap = new Map; 36 this._stylesMap = new Multimap; 37 37 38 38 this._matchedRules = []; … … 52 52 // Static 53 53 54 static parseSelectorListPayload(selectorList) 55 { 56 let selectors = selectorList.selectors; 57 if (!selectors.length) 58 return []; 59 60 // COMPATIBILITY (iOS 8): The selectorList payload was an array of selector text strings. 61 // Now they are CSSSelector objects with multiple properties. 62 if (typeof selectors[0] === "string") { 63 return selectors.map(function(selectorText) { 64 return new WI.CSSSelector(selectorText); 65 }); 66 } 67 68 return selectors.map(function(selectorPayload) { 69 return new WI.CSSSelector(selectorPayload.text, selectorPayload.specificity, selectorPayload.dynamic); 70 }); 71 } 72 73 static createSourceCodeLocation(sourceURL, {line, column, documentNode} = {}) 74 { 75 if (!sourceURL) 76 return null; 77 78 let sourceCode = null; 79 80 // Try to use the node to find the frame which has the correct resource first. 81 if (documentNode) { 82 let mainResource = WI.networkManager.resourceForURL(documentNode.documentURL); 83 if (mainResource) { 84 let parentFrame = mainResource.parentFrame; 85 sourceCode = parentFrame.resourceForURL(sourceURL); 86 } 87 } 88 89 // If that didn't find the resource, then search all frames. 90 if (!sourceCode) 91 sourceCode = WI.networkManager.resourceForURL(sourceURL); 92 93 if (!sourceCode) 94 return null; 95 96 return sourceCode.createSourceCodeLocation(line || 0, column || 0); 97 } 98 54 99 static uniqueOrderedStyles(orderedStyles) 55 100 { … … 104 149 105 150 this._needsRefresh = false; 151 152 let previousStylesMap = this._stylesMap.copy(); 106 153 107 154 let fetchedMatchedStylesPromise = new WI.WrappedPromise; … … 121 168 } 122 169 123 function parseRuleMatchArrayPayload(matchArray, node, inherited) 124 { 170 let parseRuleMatchArrayPayload = (matchArray, node, inherited, pseudoId) => { 125 171 var result = []; 126 172 … … 128 174 var ruleOccurrences = {}; 129 175 for (var i = matchArray.length - 1; i >= 0; --i) { 130 var rule = this._parseRulePayload(matchArray[i].rule, matchArray[i].matchingSelectors, node, inherited, ruleOccurrences);176 var rule = this._parseRulePayload(matchArray[i].rule, matchArray[i].matchingSelectors, node, inherited, pseudoId, ruleOccurrences); 131 177 if (!rule) 132 178 continue; … … 135 181 136 182 return result; 137 } 183 }; 138 184 139 185 function fetchedMatchedStyles(error, matchedRulesPayload, pseudoElementRulesPayload, inheritedRulesPayload) … … 143 189 inheritedRulesPayload = inheritedRulesPayload || []; 144 190 145 // Move the current maps to previous. 146 this._previousRulesMap = this._rulesMap; 147 this._previousStyleDeclarationsMap = this._styleDeclarationsMap; 148 149 // Clear the current maps. 150 this._rulesMap = {}; 151 this._styleDeclarationsMap = {}; 152 153 this._matchedRules = parseRuleMatchArrayPayload.call(this, matchedRulesPayload, this._node); 191 this._matchedRules = parseRuleMatchArrayPayload(matchedRulesPayload, this._node); 154 192 155 193 this._pseudoElements.clear(); 156 for ( var pseudoElementRulePayloadof pseudoElementRulesPayload) {157 var pseudoElementRules = parseRuleMatchArrayPayload.call(this, pseudoElementRulePayload.matches, this._node);158 this._pseudoElements.set(pseudo ElementRulePayload.pseudoId, {matchedRules: pseudoElementRules});194 for (let {pseudoId, matches} of pseudoElementRulesPayload) { 195 let pseudoElementRules = parseRuleMatchArrayPayload(matches, this._node, false, pseudoId); 196 this._pseudoElements.set(pseudoId, {matchedRules: pseudoElementRules}); 159 197 } 160 198 … … 167 205 168 206 var inheritedRuleInfo = {node: currentNode}; 169 inheritedRuleInfo.inlineStyle = inheritedRulePayload.inlineStyle ? this._parseStyleDeclarationPayload(inheritedRulePayload.inlineStyle, currentNode, true, WI.CSSStyleDeclaration.Type.Inline) : null;170 inheritedRuleInfo.matchedRules = inheritedRulePayload.matchedCSSRules ? parseRuleMatchArrayPayload .call(this,inheritedRulePayload.matchedCSSRules, currentNode, true) : [];207 inheritedRuleInfo.inlineStyle = inheritedRulePayload.inlineStyle ? this._parseStyleDeclarationPayload(inheritedRulePayload.inlineStyle, currentNode, true, null, WI.CSSStyleDeclaration.Type.Inline) : null; 208 inheritedRuleInfo.matchedRules = inheritedRulePayload.matchedCSSRules ? parseRuleMatchArrayPayload(inheritedRulePayload.matchedCSSRules, currentNode, true) : []; 171 209 172 210 if (inheritedRuleInfo.inlineStyle || inheritedRuleInfo.matchedRules.length) … … 182 220 function fetchedInlineStyles(error, inlineStylePayload, attributesStylePayload) 183 221 { 184 this._inlineStyle = inlineStylePayload ? this._parseStyleDeclarationPayload(inlineStylePayload, this._node, false, WI.CSSStyleDeclaration.Type.Inline) : null;185 this._attributesStyle = attributesStylePayload ? this._parseStyleDeclarationPayload(attributesStylePayload, this._node, false, WI.CSSStyleDeclaration.Type.Attribute) : null;222 this._inlineStyle = inlineStylePayload ? this._parseStyleDeclarationPayload(inlineStylePayload, this._node, false, null, WI.CSSStyleDeclaration.Type.Inline) : null; 223 this._attributesStyle = attributesStylePayload ? this._parseStyleDeclarationPayload(attributesStylePayload, this._node, false, null, WI.CSSStyleDeclaration.Type.Attribute) : null; 186 224 187 225 this._updateStyleCascade(); … … 211 249 212 250 let significantChange = false; 213 for (let key in this._styleDeclarationsMap) { 214 // Check if the same key exists in the previous map and has the same style objects. 215 if (key in this._previousStyleDeclarationsMap) { 216 if (Array.shallowEqual(this._styleDeclarationsMap[key], this._previousStyleDeclarationsMap[key])) 217 continue; 218 251 for (let [key, styles] of this._stylesMap.sets()) { 252 let previousStyles = previousStylesMap.get(key); 253 if (previousStyles) { 219 254 // Some styles have selectors such that they will match with the DOM node twice (for example "::before, ::after"). 220 255 // In this case a second style for a second matching may be generated and added which will cause the shallowEqual 221 256 // to not return true, so in this case we just want to ensure that all the current styles existed previously. 222 257 let styleFound = false; 223 for (let style of this._styleDeclarationsMap[key]) {224 if ( this._previousStyleDeclarationsMap[key].includes(style)) {258 for (let style of styles) { 259 if (previousStyles.has(style)) { 225 260 styleFound = true; 226 261 break; … … 234 269 if (!this._includeUserAgentRulesOnNextRefresh) { 235 270 // We can assume all the styles with the same key are from the same stylesheet and rule, so we only check the first. 236 let firstStyle = this._styleDeclarationsMap[key][0];271 let firstStyle = styles.firstValue; 237 272 if (firstStyle && firstStyle.ownerRule && firstStyle.ownerRule.type === WI.CSSStyleSheet.Type.UserAgent) { 238 273 // User Agent styles get different identifiers after some edits. This would cause us to fire a significant refreshed … … 249 284 250 285 if (!significantChange) { 251 for ( var key in this._previousStyleDeclarationsMap) {286 for (let [key, previousStyles] of previousStylesMap.sets()) { 252 287 // Check if the same key exists in current map. If it does exist it was already checked for equality above. 253 if ( key in this._styleDeclarationsMap)288 if (this._stylesMap.has(key)) 254 289 continue; 255 290 256 291 if (!this._includeUserAgentRulesOnNextRefresh) { 257 292 // See above for why we skip user agent style rules. 258 var firstStyle = this._previousStyleDeclarationsMap[key][0];293 let firstStyle = previousStyles.firstValue; 259 294 if (firstStyle && firstStyle.ownerRule && firstStyle.ownerRule.type === WI.CSSStyleSheet.Type.UserAgent) 260 295 continue; … … 267 302 } 268 303 269 delete this._includeUserAgentRulesOnNextRefresh; 270 271 // Delete the previous maps now that any reused rules and style have been moved over. 272 delete this._previousRulesMap; 273 delete this._previousStyleDeclarationsMap; 304 this._includeUserAgentRulesOnNextRefresh = false 274 305 275 306 this.dispatchEventToListeners(WI.DOMNodeStyles.Event.Refreshed, {significantChange}); … … 480 511 481 512 // Private 482 483 _createSourceCodeLocation(sourceURL, sourceLine, sourceColumn)484 {485 if (!sourceURL)486 return null;487 488 var sourceCode;489 490 // Try to use the node to find the frame which has the correct resource first.491 if (this._node.ownerDocument) {492 var mainResource = WI.networkManager.resourceForURL(this._node.ownerDocument.documentURL);493 if (mainResource) {494 var parentFrame = mainResource.parentFrame;495 sourceCode = parentFrame.resourceForURL(sourceURL);496 }497 }498 499 // If that didn't find the resource, then search all frames.500 if (!sourceCode)501 sourceCode = WI.networkManager.resourceForURL(sourceURL);502 503 if (!sourceCode)504 return null;505 506 return sourceCode.createSourceCodeLocation(sourceLine || 0, sourceColumn || 0);507 }508 513 509 514 _parseSourceRangePayload(payload) … … 591 596 } 592 597 593 _parseStyleDeclarationPayload(payload, node, inherited, type, rule, updateAllStyles)598 _parseStyleDeclarationPayload(payload, node, inherited, pseudoId, type, rule) 594 599 { 595 600 if (!payload) … … 601 606 var id = payload.styleId; 602 607 var mapKey = id ? id.styleSheetId + ":" + id.ordinal : null; 603 608 if (pseudoId) 609 mapKey += ":" + pseudoId; 604 610 if (type === WI.CSSStyleDeclaration.Type.Attribute) 605 mapKey = node.id + ":attribute"; 606 607 var styleDeclaration = rule ? rule.style : null; 608 var styleDeclarations = []; 609 610 // Look for existing styles in the previous map if there is one, otherwise use the current map. 611 var previousStyleDeclarationsMap = this._previousStyleDeclarationsMap || this._styleDeclarationsMap; 612 if (mapKey && mapKey in previousStyleDeclarationsMap) { 613 styleDeclarations = previousStyleDeclarationsMap[mapKey]; 614 615 // If we need to update all styles, then stop here and call _parseStyleDeclarationPayload for each style. 616 // We need to parse multiple times so we reuse the right properties from each style. 617 if (updateAllStyles && styleDeclarations.length) { 618 for (var i = 0; i < styleDeclarations.length; ++i) { 619 var styleDeclaration = styleDeclarations[i]; 620 this._parseStyleDeclarationPayload(payload, styleDeclaration.node, styleDeclaration.inherited, styleDeclaration.type, styleDeclaration.ownerRule); 621 } 622 623 return null; 624 } 625 626 if (!styleDeclaration) { 627 var filteredStyleDeclarations = styleDeclarations.filter(function(styleDeclaration) { 628 // This case only applies for styles that are not part of a rule. 629 if (styleDeclaration.ownerRule) { 630 console.assert(!rule); 631 return false; 632 } 633 634 if (styleDeclaration.node !== node) 635 return false; 636 637 if (styleDeclaration.inherited !== inherited) 638 return false; 639 640 return true; 641 }); 642 643 console.assert(filteredStyleDeclarations.length <= 1); 644 styleDeclaration = filteredStyleDeclarations[0] || null; 645 } 646 } 647 648 if (previousStyleDeclarationsMap !== this._styleDeclarationsMap) { 649 // If the previous and current maps differ then make sure the found styleDeclaration is added to the current map. 650 styleDeclarations = mapKey && mapKey in this._styleDeclarationsMap ? this._styleDeclarationsMap[mapKey] : []; 651 652 if (styleDeclaration && !styleDeclarations.includes(styleDeclaration)) { 653 styleDeclarations.push(styleDeclaration); 654 this._styleDeclarationsMap[mapKey] = styleDeclarations; 655 } 656 } 611 mapKey += ":" + node.id + ":attribute"; 612 613 let style = rule ? rule.style : null; 614 615 let existingStyles = this._stylesMap.get(mapKey); 616 if (existingStyles && !style) { 617 for (let existingStyle of existingStyles) { 618 if (existingStyle.node === node && existingStyle.inherited === inherited) { 619 style = existingStyle; 620 break; 621 } 622 } 623 } 624 625 if (style) 626 this._stylesMap.add(mapKey, style); 657 627 658 628 var shorthands = {}; … … 671 641 ++inheritedPropertyCount; 672 642 673 let property = this._parseStylePropertyPayload(propertyPayload, i, style Declaration);643 let property = this._parseStylePropertyPayload(propertyPayload, i, style); 674 644 properties.push(property); 675 645 } … … 678 648 var styleSheetTextRange = this._parseSourceRangePayload(payload.range); 679 649 680 if (style Declaration) {681 style Declaration.update(text, properties, styleSheetTextRange);682 return style Declaration;650 if (style) { 651 style.update(text, properties, styleSheetTextRange); 652 return style; 683 653 } 684 654 … … 693 663 return null; 694 664 695 styleDeclaration = new WI.CSSStyleDeclaration(this, styleSheet, id, type, node, inherited, text, properties, styleSheetTextRange); 696 697 if (mapKey) { 698 styleDeclarations.push(styleDeclaration); 699 this._styleDeclarationsMap[mapKey] = styleDeclarations; 700 } 701 702 return styleDeclaration; 703 } 704 705 _parseSelectorListPayload(selectorList) 706 { 707 var selectors = selectorList.selectors; 708 if (!selectors.length) 709 return []; 710 711 // COMPATIBILITY (iOS 8): The selectorList payload was an array of selector text strings. 712 // Now they are CSSSelector objects with multiple properties. 713 if (typeof selectors[0] === "string") { 714 return selectors.map(function(selectorText) { 715 return new WI.CSSSelector(selectorText); 716 }); 717 } 718 719 return selectors.map(function(selectorPayload) { 720 return new WI.CSSSelector(selectorPayload.text, selectorPayload.specificity, selectorPayload.dynamic); 721 }); 722 } 723 724 _parseRulePayload(payload, matchedSelectorIndices, node, inherited, ruleOccurrences) 665 style = new WI.CSSStyleDeclaration(this, styleSheet, id, type, node, inherited, text, properties, styleSheetTextRange); 666 667 if (mapKey) 668 this._stylesMap.add(mapKey, style); 669 670 return style; 671 } 672 673 _parseRulePayload(payload, matchedSelectorIndices, node, inherited, pseudoId, ruleOccurrences) 725 674 { 726 675 if (!payload) … … 733 682 var id = payload.ruleId || payload.style.styleId; 734 683 735 var mapKey = id ? id.styleSheetId + ":" + id.ordinal + ":" + (inherited ? "I" : "N") + ":" + node.id : null;684 var mapKey = id ? id.styleSheetId + ":" + id.ordinal + ":" + (inherited ? "I" : "N") + ":" + (pseudoId ? pseudoId + ":" : "") + node.id : null; 736 685 737 686 // Rules can match multiple times if they have multiple selectors or because of inheritance. We keep a count … … 748 697 } 749 698 750 var rule = null; 751 752 // Look for existing rules in the previous map if there is one, otherwise use the current map. 753 var previousRulesMap = this._previousRulesMap || this._rulesMap; 754 if (mapKey && mapKey in previousRulesMap) { 755 rule = previousRulesMap[mapKey]; 756 757 if (previousRulesMap !== this._rulesMap) { 758 // If the previous and current maps differ then make sure the found rule is added to the current map. 759 this._rulesMap[mapKey] = rule; 760 } 761 } 762 763 var style = this._parseStyleDeclarationPayload(payload.style, node, inherited, WI.CSSStyleDeclaration.Type.Rule, rule); 699 let rule = this._rulesMap.get(mapKey); 700 701 var style = this._parseStyleDeclarationPayload(payload.style, node, inherited, pseudoId, WI.CSSStyleDeclaration.Type.Rule, rule); 764 702 if (!style) 765 703 return null; … … 768 706 769 707 var selectorText = payload.selectorList.text; 770 var selectors = this._parseSelectorListPayload(payload.selectorList);708 let selectors = DOMNodeStyles.parseSelectorListPayload(payload.selectorList); 771 709 var type = WI.CSSManager.protocolStyleSheetOriginToEnum(payload.origin); 772 710 773 711 var sourceCodeLocation = null; 774 712 var sourceRange = payload.selectorList.range; 775 if (sourceRange) 776 sourceCodeLocation = this._createSourceCodeLocation(payload.sourceURL, sourceRange.startLine, sourceRange.startColumn); 777 else { 713 if (sourceRange) { 714 sourceCodeLocation = DOMNodeStyles.createSourceCodeLocation(payload.sourceURL, { 715 line: sourceRange.startLine, 716 column: sourceRange.startColumn, 717 documentNode: this._node.ownerDocument, 718 }); 719 } else { 778 720 // FIXME: Is it possible for a CSSRule to have a sourceLine without its selectorList having a sourceRange? Fall back just in case. 779 sourceCodeLocation = this._createSourceCodeLocation(payload.sourceURL, payload.sourceLine); 721 sourceCodeLocation = DOMNodeStyles.createSourceCodeLocation(payload.sourceURL, { 722 line: payload.sourceLine, 723 documentNode: this._node.ownerDocument, 724 }); 780 725 } 781 726 … … 792 737 var mediaType = WI.CSSManager.protocolMediaSourceToEnum(mediaItem.source); 793 738 var mediaText = mediaItem.text; 794 var mediaSourceCodeLocation = this._createSourceCodeLocation(mediaItem.sourceURL, mediaItem.sourceLine);739 let mediaSourceCodeLocation = DOMNodeStyles.createSourceCodeLocation(mediaItem.sourceURL, {line: mediaItem.sourceLine}); 795 740 if (styleSheet) 796 741 mediaSourceCodeLocation = styleSheet.offsetSourceCodeLocation(mediaSourceCodeLocation); … … 810 755 811 756 if (mapKey) 812 this._rulesMap [mapKey] = rule;757 this._rulesMap.set(mapKey, rule); 813 758 814 759 return rule; … … 830 775 // Ignore the stylesheet we know we just changed and handled above. 831 776 if (styleSheet === this._ignoreNextContentDidChangeForStyleSheet) { 832 delete this._ignoreNextContentDidChangeForStyleSheet;777 this._ignoreNextContentDidChangeForStyleSheet = null; 833 778 return; 834 779 } -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js
r242622 r243264 175 175 this._discardSelectorChange(); 176 176 else { 177 this.dispatchEventToListeners(WI.SpreadsheetCSSStyleDeclarationSection.Event.SelectorWillChange); 177 178 this._style.ownerRule.singleFireEventListener(WI.CSSRule.Event.SelectorChanged, this._renderSelector, this); 178 179 this._style.ownerRule.selectorText = selectorText; … … 303 304 var selectors = this._style.ownerRule.selectors; 304 305 var matchedSelectorIndices = this._style.ownerRule.matchedSelectorIndices; 305 var alwaysMatch = !matchedSelectorIndices.length;306 306 if (selectors.length) { 307 let hasMatchingPseudoElementSelector = false;308 307 for (let i = 0; i < selectors.length; ++i) { 309 appendSelector(selectors[i], alwaysMatch ||matchedSelectorIndices.includes(i));308 appendSelector(selectors[i], matchedSelectorIndices.includes(i)); 310 309 if (i < selectors.length - 1) 311 310 this._selectorElement.append(", "); 312 313 if (matchedSelectorIndices.includes(i) && selectors[i].isPseudoElementSelector())314 hasMatchingPseudoElementSelector = true;315 311 } 316 this._element.classList.toggle("pseudo-element-selector", hasMatchingPseudoElementSelector);317 312 } else 318 313 appendSelectorTextKnownToMatch(this._style.ownerRule.selectorText); … … 545 540 WI.SpreadsheetCSSStyleDeclarationSection.Event = { 546 541 FilterApplied: "spreadsheet-css-style-declaration-section-filter-applied", 542 SelectorWillChange: "spreadsheet-css-style-declaration-section-selector-will-change", 547 543 }; 548 544 -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js
r242939 r243264 215 215 this._shouldRefreshSubviews = false; 216 216 217 this.removeAllSubviews(); 217 let oldSections = this._sections.slice(); 218 let preservedSections = oldSections.filter((section) => { 219 if (section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol] !== this.nodeStyles.node) { 220 section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol] = null; 221 section[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] = -1; 222 } 223 return section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol]; 224 }); 225 226 if (preservedSections.length) { 227 for (let section of oldSections) { 228 if (!preservedSections.includes(section)) 229 this.removeSubview(section); 230 } 231 for (let header of this._headerMap.values()) 232 header.remove(); 233 } else 234 this.removeAllSubviews(); 218 235 219 236 let previousStyle = null; 237 let currentHeader = null; 220 238 this._headerMap.clear(); 221 239 this._sections = []; 222 240 223 let createHeader = (text, nodeOrPseudoId) => {224 let header = this.element.appendChild(document.createElement("h2"));225 header.classList.add("section-header");226 header.append(text);241 let addHeader = (text, nodeOrPseudoId) => { 242 currentHeader = this.element.appendChild(document.createElement("h2")); 243 currentHeader.classList.add("section-header"); 244 currentHeader.append(text); 227 245 228 246 if (nodeOrPseudoId) { 229 247 if (nodeOrPseudoId instanceof WI.DOMNode) { 230 header.append(" ", WI.linkifyNodeReference(nodeOrPseudoId, {248 currentHeader.append(" ", WI.linkifyNodeReference(nodeOrPseudoId, { 231 249 maxLength: 100, 232 250 excludeRevealElement: true, 233 251 })); 234 252 } else 235 header.append(" ", WI.CSSManager.displayNameForPseudoId(nodeOrPseudoId)); 236 237 this._headerMap.set(nodeOrPseudoId, header); 253 currentHeader.append(" ", WI.CSSManager.displayNameForPseudoId(nodeOrPseudoId)); 238 254 } 239 255 }; 240 256 257 let addSection = (section) => { 258 if (section.style.inherited && (!previousStyle || previousStyle.node !== section.style.node)) 259 addHeader(WI.UIString("Inherited From"), section.style.node); 260 261 if (!section.isDescendantOf(this)) { 262 let referenceView = this.subviews[this._sections.length]; 263 if (!referenceView || referenceView[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] === this._sections.length) 264 this.addSubview(section); 265 else 266 this.insertSubviewBefore(section, referenceView); 267 } 268 269 this._sections.push(section); 270 section.needsLayout(); 271 272 if (currentHeader) 273 this._headerMap.set(section.style, currentHeader); 274 275 previousStyle = section.style; 276 }; 277 241 278 let createSection = (style) => { 242 let section = style[ WI.SpreadsheetRulesStyleDetailsPanel.RuleSection];279 let section = style[SpreadsheetRulesStyleDetailsPanel.StyleSectionSymbol]; 243 280 if (!section) { 244 281 section = new WI.SpreadsheetCSSStyleDeclarationSection(this, style); 245 s tyle[WI.SpreadsheetRulesStyleDetailsPanel.RuleSection] = section;246 }247 248 section.addEventListener(WI.SpreadsheetCSSStyleDeclarationSection.Event.FilterApplied, this._handleSectionFilterApplied, this);282 section.addEventListener(WI.SpreadsheetCSSStyleDeclarationSection.Event.FilterApplied, this._handleSectionFilterApplied, this); 283 section.addEventListener(WI.SpreadsheetCSSStyleDeclarationSection.Event.SelectorWillChange, this._handleSectionSelectorWillChange, this); 284 style[SpreadsheetRulesStyleDetailsPanel.StyleSectionSymbol] = section; 285 } 249 286 250 287 if (this._newRuleSelector === style.selectorText && style.enabledProperties.length === 0) 251 288 section.startEditingRuleSelector(); 252 289 253 this.addSubview(section); 254 section.needsLayout(); 255 this._sections.push(section); 256 257 previousStyle = style; 258 259 return section; 290 addSection(section); 291 292 let preservedSection = preservedSections.find((sectionToPreserve) => sectionToPreserve[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] === this._sections.length - 1); 293 if (preservedSection) 294 addSection(preservedSection); 260 295 }; 261 296 262 for (let style of this.nodeStyles.uniqueOrderedStyles) { 263 if (style.inherited && (!previousStyle || previousStyle.node !== style.node)) 264 createHeader(WI.UIString("Inherited From"), style.node); 265 297 for (let style of this.nodeStyles.uniqueOrderedStyles) 266 298 createSection(style); 267 }268 299 269 300 let beforePseudoId = null; … … 278 309 } 279 310 311 280 312 for (let [pseudoId, pseudoElementInfo] of this.nodeStyles.pseudoElements) { 281 let nodeOrPseudoId= null;313 let pseudoElement = null; 282 314 if (pseudoId === beforePseudoId) 283 nodeOrPseudoId= this.nodeStyles.node.beforePseudoElement();315 pseudoElement = this.nodeStyles.node.beforePseudoElement(); 284 316 else if (pseudoId === afterPseudoId) 285 nodeOrPseudoId = this.nodeStyles.node.afterPseudoElement(); 286 else 287 nodeOrPseudoId = pseudoId; 288 289 createHeader(WI.UIString("Pseudo-Element"), nodeOrPseudoId); 290 291 for (let style of WI.DOMNodeStyles.uniqueOrderedStyles(pseudoElementInfo.orderedStyles)) { 292 let section = createSection(style); 293 294 if (nodeOrPseudoId === pseudoId) 295 section.__pseudoId = pseudoId; 296 } 317 pseudoElement = this.nodeStyles.node.afterPseudoElement(); 318 addHeader(WI.UIString("Pseudo-Element"), pseudoElement || pseudoId); 319 320 for (let style of WI.DOMNodeStyles.uniqueOrderedStyles(pseudoElementInfo.orderedStyles)) 321 createSection(style); 297 322 } 298 323 … … 321 346 this.element.classList.remove("filter-non-matching"); 322 347 323 let header = this._headerMap.get(event.target. __pseudoId || event.target.style.node);348 let header = this._headerMap.get(event.target.style); 324 349 if (header) 325 350 header.classList.remove(WI.GeneralStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName); … … 336 361 this.nodeStyles.addRule(this._newRuleSelector, text, stylesheetId); 337 362 } 363 364 _handleSectionSelectorWillChange(event) 365 { 366 let section = event.target; 367 section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol] = this.nodeStyles.node; 368 section[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] = this._sections.indexOf(section); 369 console.assert(section[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] >= 0); 370 } 338 371 }; 339 372 340 WI.SpreadsheetRulesStyleDetailsPanel.RuleSection = Symbol("rule-section"); 373 WI.SpreadsheetRulesStyleDetailsPanel.StyleSectionSymbol = Symbol("style-section"); 374 WI.SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol = Symbol("style-showing-for-node"); 375 WI.SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol = Symbol("style-index");
Note: See TracChangeset
for help on using the changeset viewer.