summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/CSSStyleDeclaration.js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/CSSStyleDeclaration.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/CSSStyleDeclaration.js310
1 files changed, 310 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/CSSStyleDeclaration.js b/Source/WebInspectorUI/UserInterface/CSSStyleDeclaration.js
new file mode 100644
index 000000000..eaab18787
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/CSSStyleDeclaration.js
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2013 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.CSSStyleDeclaration = function(nodeStyles, ownerStyleSheet, id, type, node, inherited, text, properties, styleSheetTextRange)
+{
+ WebInspector.Object.call(this);
+
+ console.assert(nodeStyles);
+ this._nodeStyles = nodeStyles;
+
+ this._ownerRule = null;
+
+ this._ownerStyleSheet = ownerStyleSheet || null;
+ this._id = id || null;
+ this._type = type || null;
+ this._node = node || null;
+ this._inherited = inherited || false;
+
+ this._pendingProperties = [];
+ this._propertyNameMap = {};
+
+ this.update(text, properties, styleSheetTextRange, true);
+};
+
+WebInspector.Object.addConstructorFunctions(WebInspector.CSSStyleDeclaration);
+
+WebInspector.CSSStyleDeclaration.Event = {
+ PropertiesChanged: "css-style-declaration-properties-changed"
+};
+
+WebInspector.CSSStyleDeclaration.Type = {
+ Rule: "css-style-declaration-type-rule",
+ Inline: "css-style-declaration-type-inline",
+ Attribute: "css-style-declaration-type-attribute",
+ Computed: "css-style-declaration-type-computed"
+};
+
+WebInspector.CSSStyleDeclaration.prototype = {
+ constructor: WebInspector.CSSStyleDeclaration,
+
+ // Public
+
+ get id()
+ {
+ return this._id;
+ },
+
+ get ownerStyleSheet()
+ {
+ return this._ownerStyleSheet;
+ },
+
+ get type()
+ {
+ return this._type;
+ },
+
+ get inherited()
+ {
+ return this._inherited;
+ },
+
+ get node()
+ {
+ return this._node;
+ },
+
+ get editable()
+ {
+ return !!this._id && ((this._type === WebInspector.CSSStyleDeclaration.Type.Rule && this._ownerRule && this._ownerRule.editable) || this._type === WebInspector.CSSStyleDeclaration.Type.Inline);
+ },
+
+ update: function(text, properties, styleSheetTextRange, dontFireEvents)
+ {
+ text = text || "";
+ properties = properties || [];
+
+ var oldProperties = this._properties || [];
+ var oldText = this._text;
+
+ this._text = text;
+ this._properties = properties;
+ this._styleSheetTextRange = styleSheetTextRange;
+ this._propertyNameMap = {};
+
+ delete this._visibleProperties;
+
+ var editable = this.editable;
+
+ for (var i = 0; i < this._properties.length; ++i) {
+ var property = this._properties[i];
+ property.ownerStyle = this;
+
+ // Store the property in a map if we arn't editable. This
+ // allows for quick lookup for computed style. Editable
+ // styles don't use the map since they need to account for
+ // overridden properties.
+ if (!editable)
+ this._propertyNameMap[property.name] = property;
+ else {
+ // Remove from pendingProperties (if it was pending).
+ this._pendingProperties.remove(property);
+ }
+ }
+
+ var removedProperties = [];
+ for (var i = 0; i < oldProperties.length; ++i) {
+ var oldProperty = oldProperties[i];
+
+ if (!this._properties.contains(oldProperty)) {
+ // Clear the index, since it is no longer valid.
+ oldProperty.index = NaN;
+
+ removedProperties.push(oldProperty);
+
+ // Keep around old properties in pending in case they
+ // are needed again during editing.
+ if (editable)
+ this._pendingProperties.push(oldProperty);
+ }
+ }
+
+ if (dontFireEvents)
+ return;
+
+ var addedProperties = [];
+ for (var i = 0; i < this._properties.length; ++i) {
+ if (!oldProperties.contains(this._properties[i]))
+ addedProperties.push(this._properties[i]);
+ }
+
+ // Don't fire the event if there is text and it hasn't changed.
+ if (oldText && this._text && oldText === this._text) {
+ // We shouldn't have any added or removed properties in this case.
+ console.assert(!addedProperties.length && !removedProperties.length);
+ if (!addedProperties.length && !removedProperties.length)
+ return;
+ }
+
+ function delayed()
+ {
+ this.dispatchEventToListeners(WebInspector.CSSStyleDeclaration.Event.PropertiesChanged, {addedProperties: addedProperties, removedProperties: removedProperties});
+ }
+
+ // Delay firing the PropertiesChanged event so DOMNodeStyles has a chance to mark overridden and associated properties.
+ setTimeout(delayed.bind(this), 0);
+ },
+
+ get ownerRule()
+ {
+ return this._ownerRule;
+ },
+
+ set ownerRule(rule)
+ {
+ this._ownerRule = rule || null;
+ },
+
+ get text()
+ {
+ return this._text;
+ },
+
+ set text(text)
+ {
+ if (this._text === text)
+ return;
+
+ this._nodeStyles.changeStyleText(this, text);
+ },
+
+ get properties()
+ {
+ return this._properties;
+ },
+
+ get visibleProperties()
+ {
+ if (this._visibleProperties)
+ return this._visibleProperties;
+
+ this._visibleProperties = this._properties.filter(function(property) {
+ return !!property.styleDeclarationTextRange;
+ });
+
+ return this._visibleProperties;
+ },
+
+ get pendingProperties()
+ {
+ return this._pendingProperties;
+ },
+
+ get styleSheetTextRange()
+ {
+ return this._styleSheetTextRange;
+ },
+
+ propertyForName: function(name, dontCreateIfMissing)
+ {
+ console.assert(name);
+ if (!name)
+ return null;
+
+ if (!this.editable)
+ return this._propertyNameMap[name] || null;
+
+ // Editable styles don't use the map since they need to
+ // account for overridden properties.
+
+ function findMatch(properties)
+ {
+ for (var i = 0; i < properties.length; ++i) {
+ var property = properties[i];
+ if (property.canonicalName !== name && property.name !== name)
+ continue;
+ if (bestMatchProperty && !bestMatchProperty.overridden && property.overridden)
+ continue;
+ bestMatchProperty = property;
+ }
+ }
+
+ var bestMatchProperty = null;
+
+ findMatch(this._properties);
+
+ if (bestMatchProperty)
+ return bestMatchProperty;
+
+ if (dontCreateIfMissing || !this.editable)
+ return null;
+
+ findMatch(this._pendingProperties, true);
+
+ if (bestMatchProperty)
+ return bestMatchProperty;
+
+ var newProperty = new WebInspector.CSSProperty(NaN, null, name);
+ newProperty.ownerStyle = this;
+
+ this._pendingProperties.push(newProperty);
+
+ return newProperty;
+ },
+
+ addProperty: function(property)
+ {
+ console.assert(property);
+ if (!property)
+ return;
+
+ console.assert(property.ownerStyle === this);
+ if (property.ownerStyle !== this)
+ return;
+
+ console.assert(this.editable);
+ if (!this.editable)
+ return;
+
+ this._nodeStyles.addProperty(property);
+ },
+
+ removeProperty: function(property)
+ {
+ console.assert(property);
+ if (!property)
+ return;
+
+ console.assert(property.ownerStyle === this);
+ if (property.ownerStyle !== this)
+ return;
+
+ console.assert(this.editable);
+ if (!this.editable)
+ return;
+
+ this._nodeStyles.removeProperty(property);
+ },
+
+ // Protected
+
+ get nodeStyles()
+ {
+ return this._nodeStyles;
+ }
+};
+
+WebInspector.CSSStyleDeclaration.prototype.__proto__ = WebInspector.Object.prototype;