summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js474
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);
+ }
+};