OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @constructor | |
7 * @param {!WebInspector.CSSStyleModel.MatchedStyleResult} matchedStyles | |
8 * @param {!Array<!WebInspector.CSSStyleDeclaration>} styles | |
9 */ | |
10 WebInspector.SectionCascade = function(matchedStyles, styles) | |
11 { | |
12 this._matchedStyles = matchedStyles; | |
13 this._styles = styles; | |
14 this.resetActiveProperties(); | |
15 } | |
16 | |
17 /** | |
18 * @param {!WebInspector.CSSStyleModel.MatchedStyleResult} matchedStyles | |
19 * @return {!{matched: !WebInspector.SectionCascade, pseudo: !Map.<number, !WebI
nspector.SectionCascade>}} | |
20 */ | |
21 WebInspector.SectionCascade.fromMatchedStyles = function(matchedStyles) | |
22 { | |
23 var matched = new WebInspector.SectionCascade(matchedStyles, matchedStyles.n
odeStyles()); | |
24 var pseudo = new Map(); | |
25 | |
26 var pseudoStyles = matchedStyles.pseudoStyles(); | |
27 var pseudoElements = pseudoStyles.keysArray(); | |
28 for (var i = 0; i < pseudoElements.length; ++i) { | |
29 var pseudoElement = pseudoElements[i]; | |
30 var pseudoCascade = new WebInspector.SectionCascade(matchedStyles, /** @
type {!Array<!WebInspector.CSSStyleDeclaration>} */(pseudoStyles.get(pseudoEleme
nt))); | |
31 pseudo.set(pseudoElement, pseudoCascade); | |
32 } | |
33 | |
34 return { | |
35 matched: matched, | |
36 pseudo: pseudo | |
37 }; | |
38 } | |
39 | |
40 WebInspector.SectionCascade.prototype = { | |
41 /** | |
42 * @param {!WebInspector.CSSStyleDeclaration} style | |
43 * @return {boolean} | |
44 */ | |
45 hasMatchingSelectors: function(style) | |
46 { | |
47 return style.parentRule ? style.parentRule.matchingSelectors && style.pa
rentRule.matchingSelectors.length > 0 && this.mediaMatches(style) : true; | |
48 }, | |
49 | |
50 /** | |
51 * @param {!WebInspector.CSSStyleDeclaration} style | |
52 * @return {boolean} | |
53 */ | |
54 mediaMatches: function(style) | |
55 { | |
56 var media = style.parentRule ? style.parentRule.media : []; | |
57 for (var i = 0; media && i < media.length; ++i) { | |
58 if (!media[i].active()) | |
59 return false; | |
60 } | |
61 return true; | |
62 }, | |
63 | |
64 /** | |
65 * @param {!WebInspector.CSSStyleDeclaration} style | |
66 * @return {?WebInspector.DOMNode} | |
67 */ | |
68 nodeForStyle: function(style) | |
69 { | |
70 return this._matchedStyles.nodeForStyle(style); | |
71 }, | |
72 | |
73 /** | |
74 * @param {!WebInspector.CSSStyleDeclaration} style | |
75 * @return {boolean} | |
76 */ | |
77 isInherited: function(style) | |
78 { | |
79 return this._matchedStyles.isInherited(style); | |
80 }, | |
81 | |
82 /** | |
83 * @return {!Array.<!WebInspector.CSSStyleDeclaration>} | |
84 */ | |
85 styles: function() | |
86 { | |
87 return this._styles; | |
88 }, | |
89 | |
90 /** | |
91 * @param {!WebInspector.CSSProperty} property | |
92 * @return {?WebInspector.SectionCascade.PropertyState} | |
93 */ | |
94 propertyState: function(property) | |
95 { | |
96 if (this._propertiesState.size === 0) | |
97 this._propertiesState = this._computeActiveProperties(); | |
98 return this._propertiesState.get(property) || null; | |
99 }, | |
100 | |
101 resetActiveProperties: function() | |
102 { | |
103 /** @type {!Map<!WebInspector.CSSProperty, !WebInspector.SectionCascade.
PropertyState>} */ | |
104 this._propertiesState = new Map(); | |
105 }, | |
106 | |
107 /** | |
108 * @return {!Map<!WebInspector.CSSProperty, !WebInspector.SectionCascade.Pro
pertyState>} | |
109 */ | |
110 _computeActiveProperties: function() | |
111 { | |
112 /** @type {!Set.<string>} */ | |
113 var foundImportantProperties = new Set(); | |
114 /** @type {!Map.<string, !Map<string, !WebInspector.CSSProperty>>} */ | |
115 var propertyToEffectiveRule = new Map(); | |
116 /** @type {!Map.<string, !WebInspector.DOMNode>} */ | |
117 var inheritedPropertyToNode = new Map(); | |
118 /** @type {!Set<string>} */ | |
119 var allUsedProperties = new Set(); | |
120 var result = new Map(); | |
121 for (var i = 0; i < this._styles.length; ++i) { | |
122 var style = this._styles[i]; | |
123 if (!this.hasMatchingSelectors(style)) | |
124 continue; | |
125 | |
126 /** @type {!Map<string, !WebInspector.CSSProperty>} */ | |
127 var styleActiveProperties = new Map(); | |
128 var allProperties = style.allProperties; | |
129 for (var j = 0; j < allProperties.length; ++j) { | |
130 var property = allProperties[j]; | |
131 | |
132 // Do not pick non-inherited properties from inherited styles. | |
133 var inherited = this._matchedStyles.isInherited(style); | |
134 if (inherited && !WebInspector.CSSMetadata.isPropertyInherited(p
roperty.name)) | |
135 continue; | |
136 | |
137 if (!property.activeInStyle()) { | |
138 result.set(property, WebInspector.SectionCascade.PropertySta
te.Overloaded); | |
139 continue; | |
140 } | |
141 | |
142 var canonicalName = WebInspector.CSSMetadata.canonicalPropertyNa
me(property.name); | |
143 if (foundImportantProperties.has(canonicalName)) { | |
144 result.set(property, WebInspector.SectionCascade.PropertySta
te.Overloaded); | |
145 continue; | |
146 } | |
147 | |
148 if (!property.important && allUsedProperties.has(canonicalName))
{ | |
149 result.set(property, WebInspector.SectionCascade.PropertySta
te.Overloaded); | |
150 continue; | |
151 } | |
152 | |
153 var isKnownProperty = propertyToEffectiveRule.has(canonicalName)
; | |
154 var inheritedFromNode = inherited ? this._matchedStyles.nodeForS
tyle(style) : null; | |
155 if (!isKnownProperty && inheritedFromNode && !inheritedPropertyT
oNode.has(canonicalName)) | |
156 inheritedPropertyToNode.set(canonicalName, inheritedFromNode
); | |
157 | |
158 if (property.important) { | |
159 if (inherited && isKnownProperty && inheritedFromNode !== in
heritedPropertyToNode.get(canonicalName)) { | |
160 result.set(property, WebInspector.SectionCascade.Propert
yState.Overloaded); | |
161 continue; | |
162 } | |
163 | |
164 foundImportantProperties.add(canonicalName); | |
165 if (isKnownProperty) { | |
166 var overloaded = propertyToEffectiveRule.get(canonicalNa
me).get(canonicalName); | |
167 result.set(overloaded, WebInspector.SectionCascade.Prope
rtyState.Overloaded); | |
168 propertyToEffectiveRule.get(canonicalName).delete(canoni
calName); | |
169 } | |
170 } | |
171 | |
172 styleActiveProperties.set(canonicalName, property); | |
173 allUsedProperties.add(canonicalName); | |
174 propertyToEffectiveRule.set(canonicalName, styleActiveProperties
); | |
175 result.set(property, WebInspector.SectionCascade.PropertyState.A
ctive); | |
176 } | |
177 | |
178 // If every longhand of the shorthand is not active, then the shorth
and is not active too. | |
179 for (var property of style.leadingProperties()) { | |
180 var canonicalName = WebInspector.CSSMetadata.canonicalPropertyNa
me(property.name); | |
181 if (!styleActiveProperties.has(canonicalName)) | |
182 continue; | |
183 var longhands = style.longhandProperties(property.name); | |
184 if (!longhands.length) | |
185 continue; | |
186 var notUsed = true; | |
187 for (var longhand of longhands) { | |
188 var longhandCanonicalName = WebInspector.CSSMetadata.canonic
alPropertyName(longhand.name); | |
189 notUsed = notUsed && !styleActiveProperties.has(longhandCano
nicalName); | |
190 } | |
191 if (!notUsed) | |
192 continue; | |
193 styleActiveProperties.delete(canonicalName); | |
194 allUsedProperties.delete(canonicalName); | |
195 result.set(property, WebInspector.SectionCascade.PropertyState.O
verloaded); | |
196 } | |
197 } | |
198 return result; | |
199 } | |
200 } | |
201 | |
202 /** @enum {string} */ | |
203 WebInspector.SectionCascade.PropertyState = { | |
204 Active: "Active", | |
205 Overloaded: "Overloaded" | |
206 } | |
OLD | NEW |