diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js b/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js new file mode 100644 index 000000000..c03d89f94 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.RulesStyleDetailsPanel = class RulesStyleDetailsPanel extends WebInspector.StyleDetailsPanel +{ + constructor(delegate) + { + super(delegate, "rules", "rules", WebInspector.UIString("Styles \u2014 Rules")); + + this._sections = []; + this._inspectorSection = null; + this._isInspectorSectionPendingFocus = false; + this._ruleMediaAndInherticanceList = []; + this._propertyToSelectAndHighlight = null; + + this._emptyFilterResultsElement = document.createElement("div"); + this._emptyFilterResultsElement.classList.add("no-filter-results"); + + this._emptyFilterResultsMessage = document.createElement("div"); + this._emptyFilterResultsMessage.classList.add("no-filter-results-message"); + this._emptyFilterResultsMessage.textContent = WebInspector.UIString("No Results Found"); + this._emptyFilterResultsElement.appendChild(this._emptyFilterResultsMessage); + + this._boundRemoveSectionWithActiveEditor = this._removeSectionWithActiveEditor.bind(this); + } + + // Public + + refresh(significantChange) + { + // We only need to do a rebuild on significant changes. Other changes are handled + // by the sections and text editors themselves. + if (!significantChange) { + super.refresh(); + return; + } + + if (!this._forceSignificantChange) { + this._sectionWithActiveEditor = null; + for (var section of this._sections) { + if (!section.editorActive) + continue; + + this._sectionWithActiveEditor = section; + break; + } + + if (this._sectionWithActiveEditor) { + this._sectionWithActiveEditor.addEventListener(WebInspector.CSSStyleDeclarationSection.Event.Blurred, this._boundRemoveSectionWithActiveEditor); + return; + } + } + + var newSections = []; + var newDOMFragment = document.createDocumentFragment(); + + var previousMediaList = []; + var previousSection = null; + + var pseudoElements = this.nodeStyles.pseudoElements; + var pseudoElementsStyle = []; + for (var pseudoIdentifier in pseudoElements) + pseudoElementsStyle = pseudoElementsStyle.concat(pseudoElements[pseudoIdentifier].orderedStyles); + + var orderedPseudoStyles = uniqueOrderedStyles(pseudoElementsStyle); + // Reverse the array to allow ensure that splicing the array will not mess with the order. + if (orderedPseudoStyles.length) + orderedPseudoStyles.reverse(); + + function mediaListsEqual(a, b) + { + a = a || []; + b = b || []; + + if (a.length !== b.length) + return false; + + for (var i = 0; i < a.length; ++i) { + var aMedia = a[i]; + var bMedia = b[i]; + + if (aMedia.type !== bMedia.type) + return false; + + if (aMedia.text !== bMedia.text) + return false; + + if (!aMedia.sourceCodeLocation && bMedia.sourceCodeLocation) + return false; + + if (aMedia.sourceCodeLocation && !aMedia.sourceCodeLocation.isEqual(bMedia.sourceCodeLocation)) + return false; + } + + return true; + } + + function uniqueOrderedStyles(orderedStyles) + { + var uniqueStyles = []; + + for (var style of orderedStyles) { + var rule = style.ownerRule; + if (!rule) { + uniqueStyles.push(style); + continue; + } + + var found = false; + for (var existingStyle of uniqueStyles) { + if (rule.isEqualTo(existingStyle.ownerRule)) { + found = true; + break; + } + } + if (!found) + uniqueStyles.push(style); + } + + return uniqueStyles; + } + + function appendStyleSection(style) + { + var section = style.__rulesSection; + + if (!section) { + section = new WebInspector.CSSStyleDeclarationSection(this, style); + style.__rulesSection = section; + } else + section.refresh(); + + if (this._isInspectorSectionPendingFocus && style.isInspectorRule()) + this._inspectorSection = section; + + // Reset lastInGroup in case the order/grouping changed. + section.lastInGroup = false; + + newDOMFragment.appendChild(section.element); + newSections.push(section); + + previousSection = section; + } + + function insertMediaOrInheritanceLabel(style) + { + if (previousSection && previousSection.style.type === WebInspector.CSSStyleDeclaration.Type.Inline) + previousSection.lastInGroup = true; + + var hasMediaOrInherited = []; + + if (previousSection && previousSection.style.node !== style.node) { + previousSection.lastInGroup = true; + + var prefixElement = document.createElement("strong"); + prefixElement.textContent = WebInspector.UIString("Inherited From: "); + + var inheritedLabel = document.createElement("div"); + inheritedLabel.className = "label"; + inheritedLabel.appendChild(prefixElement); + inheritedLabel.appendChild(WebInspector.linkifyNodeReference(style.node, 100)); + newDOMFragment.appendChild(inheritedLabel); + + hasMediaOrInherited.push(inheritedLabel); + } + + // Only include the media list if it is different from the previous media list shown. + var currentMediaList = (style.ownerRule && style.ownerRule.mediaList) || []; + if (!mediaListsEqual(previousMediaList, currentMediaList)) { + previousMediaList = currentMediaList; + + // Break the section group even if the media list is empty. That way the user knows + // the previous displayed media list does not apply to the next section. + if (previousSection) + previousSection.lastInGroup = true; + + for (var media of currentMediaList) { + var prefixElement = document.createElement("strong"); + prefixElement.textContent = WebInspector.UIString("Media: "); + + var mediaLabel = document.createElement("div"); + mediaLabel.className = "label"; + mediaLabel.append(prefixElement, media.text); + + if (media.sourceCodeLocation) + mediaLabel.append(" \u2014 ", WebInspector.createSourceCodeLocationLink(media.sourceCodeLocation, true)); + + newDOMFragment.appendChild(mediaLabel); + + hasMediaOrInherited.push(mediaLabel); + } + } + + if (!hasMediaOrInherited.length && style.type !== WebInspector.CSSStyleDeclaration.Type.Inline) { + if (previousSection && !previousSection.lastInGroup) + hasMediaOrInherited = this._ruleMediaAndInherticanceList.lastValue; + else { + var prefixElement = document.createElement("strong"); + prefixElement.textContent = WebInspector.UIString("Media: "); + + var mediaLabel = document.createElement("div"); + mediaLabel.className = "label"; + mediaLabel.append(prefixElement, "all"); + + newDOMFragment.appendChild(mediaLabel); + hasMediaOrInherited.push(mediaLabel); + } + } + + this._ruleMediaAndInherticanceList.push(hasMediaOrInherited); + } + + function insertAllMatchingPseudoStyles(force) + { + if (!orderedPseudoStyles.length) + return; + + if (force) { + for (var j = orderedPseudoStyles.length - 1; j >= 0; --j) { + var pseudoStyle = orderedPseudoStyles[j]; + insertMediaOrInheritanceLabel.call(this, pseudoStyle); + appendStyleSection.call(this, pseudoStyle); + } + orderedPseudoStyles = []; + } + + if (!previousSection) + return; + + var ownerRule = previousSection.style.ownerRule; + if (!ownerRule) + return; + + for (var j = orderedPseudoStyles.length - 1; j >= 0; --j) { + var pseudoStyle = orderedPseudoStyles[j]; + if (!pseudoStyle.ownerRule.selectorIsGreater(ownerRule.mostSpecificSelector)) + continue; + + insertMediaOrInheritanceLabel.call(this, pseudoStyle); + appendStyleSection.call(this, pseudoStyle); + ownerRule = pseudoStyle.ownerRule; + orderedPseudoStyles.splice(j, 1); + } + } + + this._ruleMediaAndInherticanceList = []; + var orderedStyles = uniqueOrderedStyles(this.nodeStyles.orderedStyles); + for (var style of orderedStyles) { + var isUserAgentStyle = style.ownerRule && style.ownerRule.type === WebInspector.CSSStyleSheet.Type.UserAgent; + insertAllMatchingPseudoStyles.call(this, isUserAgentStyle || style.inherited); + + insertMediaOrInheritanceLabel.call(this, style); + appendStyleSection.call(this, style); + } + + // Just in case there are any pseudo-selectors left that haven't been added. + insertAllMatchingPseudoStyles.call(this, true); + + if (previousSection) + previousSection.lastInGroup = true; + + this.element.removeChildren(); + this.element.appendChild(newDOMFragment); + this.element.appendChild(this._emptyFilterResultsElement); + + this._sections = newSections; + + for (var i = 0; i < this._sections.length; ++i) + this._sections[i].updateLayout(); + + super.refresh(); + } + + scrollToSectionAndHighlightProperty(property) + { + if (!this._visible) { + this._propertyToSelectAndHighlight = property; + return false; + } + + for (var section of this._sections) { + if (section.highlightProperty(property)) + return true; + } + + return false; + } + + cssStyleDeclarationSectionEditorFocused(focusedSection) + { + for (let section of this._sections) { + if (section !== focusedSection) + section.clearSelection(); + } + } + + cssStyleDeclarationSectionEditorNextRule(currentSection) + { + currentSection.clearSelection(); + + var index = this._sections.indexOf(currentSection); + this._sections[index < this._sections.length - 1 ? index + 1 : 0].focusRuleSelector(); + } + + cssStyleDeclarationSectionEditorPreviousRule(currentSection, selectLastProperty) { + currentSection.clearSelection(); + + if (selectLastProperty || !currentSection.selectorEditable) { + var index = this._sections.indexOf(currentSection); + index = index > 0 ? index - 1 : this._sections.length - 1; + + var section = this._sections[index]; + while (section.locked) { + index = index > 0 ? index - 1 : this._sections.length - 1; + section = this._sections[index]; + } + + section.focus(); + section.selectLastProperty(); + return; + } + + currentSection.focusRuleSelector(true); + } + + filterDidChange(filterBar) + { + for (var labels of this._ruleMediaAndInherticanceList) { + for (var i = 0; i < labels.length; ++i) { + labels[i].classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName, filterBar.hasActiveFilters()); + + if (i === labels.length - 1) + labels[i].classList.toggle("filter-matching-label", filterBar.hasActiveFilters()); + } + } + + var matchFound = !filterBar.hasActiveFilters(); + for (var i = 0; i < this._sections.length; ++i) { + var section = this._sections[i]; + + if (section.findMatchingPropertiesAndSelectors(filterBar.filters.text) && filterBar.hasActiveFilters()) { + if (this._ruleMediaAndInherticanceList[i].length) { + for (var label of this._ruleMediaAndInherticanceList[i]) + label.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName); + } else + section.element.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName); + + matchFound = true; + } + } + + this.element.classList.toggle("filter-non-matching", !matchFound); + } + + newRuleButtonClicked() + { + if (this.nodeStyles.node.isInUserAgentShadowTree()) + return; + + for (let existingRule of this.nodeStyles.rulesForSelector()) { + if (this.focusEmptySectionWithStyle(existingRule.style)) + return; + } + + this._isInspectorSectionPendingFocus = true; + let newInspectorRuleSelector = this.nodeStyles.node.appropriateSelectorFor(true); + this.nodeStyles.addRule(newInspectorRuleSelector); + } + + sectionForStyle(style) + { + if (style.__rulesSection) + return style.__rulesSection; + + for (let section of this._sections) { + if (section.style === style) + return section; + } + return null; + } + + focusEmptySectionWithStyle(style) + { + if (style.hasProperties()) + return false; + + let section = this.sectionForStyle(style); + if (!section) + return false; + + section.focus(); + return true; + } + + // Protected + + shown() + { + super.shown(); + + // Associate the style and section objects so they can be reused. + // Also update the layout in case we changed widths while hidden. + for (var i = 0; i < this._sections.length; ++i) { + var section = this._sections[i]; + section.style.__rulesSection = section; + section.updateLayout(); + } + } + + hidden() + { + super.hidden(); + + // Disconnect the style and section objects so they have a chance + // to release their objects when this panel is not visible. + for (var i = 0; i < this._sections.length; ++i) + delete this._sections[i].style.__rulesSection; + } + + sizeDidChange() + { + for (var i = 0; i < this._sections.length; ++i) + this._sections[i].updateLayout(); + } + + nodeStylesRefreshed(event) + { + super.nodeStylesRefreshed(event); + + if (this._propertyToSelectAndHighlight) { + this.scrollToSectionAndHighlightProperty(this._propertyToSelectAndHighlight); + this._propertyToSelectAndHighlight = null; + } + + if (this._isInspectorSectionPendingFocus) { + this._isInspectorSectionPendingFocus = false; + + if (this._inspectorSection) { + this._inspectorSection.focus(); + this._inspectorSection = null; + } + } + } + + // Private + + _removeSectionWithActiveEditor(event) + { + this._sectionWithActiveEditor.removeEventListener(WebInspector.CSSStyleDeclarationSection.Event.Blurred, this._boundRemoveSectionWithActiveEditor); + this.refresh(true); + } +}; |