| /* |
| * 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.CSSProperty = function(index, text, name, value, priority, enabled, overridden, implicit, anonymous, valid, styleSheetTextRange, styleDeclarationTextRange) |
| { |
| WebInspector.Object.call(this); |
| |
| this._ownerStyle = null; |
| this._index = index; |
| |
| this.update(text, name, value, priority, enabled, overridden, implicit, anonymous, valid, styleSheetTextRange, styleDeclarationTextRange, true); |
| }; |
| |
| WebInspector.Object.addConstructorFunctions(WebInspector.CSSProperty); |
| |
| WebInspector.CSSProperty.Event = { |
| Changed: "css-property-changed", |
| OverriddenStatusChanged: "css-property-overridden-status-changed" |
| }; |
| |
| WebInspector.CSSProperty.prototype = { |
| constructor: WebInspector.CSSProperty, |
| |
| // Public |
| |
| get ownerStyle() |
| { |
| return this._ownerStyle; |
| }, |
| |
| set ownerStyle(ownerStyle) |
| { |
| this._ownerStyle = ownerStyle || null; |
| }, |
| |
| get index() |
| { |
| return this._index; |
| }, |
| |
| set index(index) |
| { |
| this._index = index; |
| }, |
| |
| update: function(text, name, value, priority, enabled, overridden, implicit, anonymous, valid, styleSheetTextRange, styleDeclarationTextRange, dontFireEvents) |
| { |
| text = text || ""; |
| name = name || ""; |
| value = value || ""; |
| priority = priority || ""; |
| enabled = enabled || false; |
| overridden = overridden || false; |
| implicit = implicit || false; |
| anonymous = anonymous || false; |
| valid = valid || false; |
| |
| var changed = false; |
| |
| if (!dontFireEvents) { |
| changed = this._name !== name || this._value !== value || this._priority !== priority || |
| this._enabled !== enabled || this._implicit !== implicit || this._anonymous !== anonymous || this._valid !== valid; |
| } |
| |
| // Use the setter for overridden if we want to fire events since the |
| // OverriddenStatusChanged event coalesces changes before it fires. |
| if (!dontFireEvents) |
| this.overridden = overridden; |
| else |
| this._overridden = overridden; |
| |
| this._text = text; |
| this._name = name; |
| this._value = value; |
| this._priority = priority; |
| this._enabled = enabled; |
| this._implicit = implicit; |
| this._anonymous = anonymous; |
| this._inherited = name in WebInspector.CSSKeywordCompletions.InheritedProperties; |
| this._valid = valid; |
| this._styleSheetTextRange = styleSheetTextRange || null; |
| |
| if (styleDeclarationTextRange) |
| this._styleDeclarationTextRange = styleDeclarationTextRange; |
| else |
| delete this._styleDeclarationTextRange; |
| |
| this._relatedShorthandProperty = null; |
| this._relatedLonghandProperties = []; |
| |
| delete this._canonicalName; |
| delete this._hasOtherVendorNameOrKeyword; |
| |
| if (!this._updatePropertySoonTimeout) { |
| delete this._pendingName; |
| delete this._pendingValue; |
| delete this._pendingPriority; |
| } |
| |
| if (changed) |
| this.dispatchEventToListeners(WebInspector.CSSProperty.Event.Changed); |
| }, |
| |
| get synthesizedText() |
| { |
| var name = this.name; |
| if (!name) |
| return ""; |
| |
| var priority = this.priority; |
| return name + ": " + this.value.trim() + (priority ? " !" + priority : "") + ";"; |
| }, |
| |
| get text() |
| { |
| return this._text || this.synthesizedText; |
| }, |
| |
| set text(text) |
| { |
| if (!this._ownerStyle || !this._ownerStyle.editable) |
| return; |
| |
| if (this._text === text) |
| return; |
| |
| if (isNaN(this._index)) { |
| this._text = text || ""; |
| |
| // Clear the name, value and priority since they might not match the text now. |
| this._name = ""; |
| this._value = ""; |
| this._priority = ""; |
| |
| // Ditto for the canonical and pending properties. |
| delete this._canonicalName; |
| delete this._pendingName; |
| delete this._pendingValue; |
| delete this._pendingPriority; |
| |
| return; |
| } |
| |
| this._cancelPendingUpdate(); |
| this._ownerStyle.nodeStyles.changePropertyText(this, text); |
| }, |
| |
| get name() |
| { |
| if (isNaN(this._index)) |
| return this._pendingName || this._name; |
| return this._name; |
| }, |
| |
| set name(name) |
| { |
| if (!this._ownerStyle || !this._ownerStyle.editable) |
| return; |
| |
| if (this._name === name) |
| return; |
| |
| if (isNaN(this._index)) { |
| this._name = name; |
| this._text = ""; |
| |
| delete this._canonicalName; |
| } else { |
| this._pendingName = name; |
| this._updatePropertySoon(); |
| } |
| }, |
| |
| get canonicalName() |
| { |
| if (this._canonicalName) |
| return this._canonicalName; |
| |
| this._canonicalName = WebInspector.cssStyleManager.canonicalNameForPropertyName(this.name); |
| |
| return this._canonicalName; |
| }, |
| |
| get value() |
| { |
| if (isNaN(this._index)) |
| return this._pendingValue || this._value; |
| return this._value; |
| }, |
| |
| set value(value) |
| { |
| if (!this._ownerStyle || !this._ownerStyle.editable) |
| return; |
| |
| if (this._value === value) |
| return; |
| |
| if (isNaN(this._index)) { |
| this._value = value; |
| this._text = ""; |
| } else { |
| this._pendingValue = value; |
| this._updatePropertySoon(); |
| } |
| }, |
| |
| get important() |
| { |
| return this.priority === "important"; |
| }, |
| |
| set important(important) |
| { |
| this.priority = important ? "important" : ""; |
| }, |
| |
| get priority() |
| { |
| if (isNaN(this._index)) |
| return this._pendingPriority || this._priority; |
| return this._priority; |
| }, |
| |
| set priority(priority) |
| { |
| if (!this._ownerStyle || !this._ownerStyle.editable) |
| return; |
| |
| if (this._priority === priority) |
| return; |
| |
| if (isNaN(this._index)) { |
| this._priority = priority; |
| this._text = ""; |
| } else { |
| this._pendingPriority = priority; |
| this._updatePropertySoon(); |
| } |
| }, |
| |
| get enabled() |
| { |
| return this._enabled && this._ownerStyle && (!isNaN(this._index) || this._ownerStyle.type === WebInspector.CSSStyleDeclaration.Type.Computed); |
| }, |
| |
| set enabled(enabled) |
| { |
| if (!this._ownerStyle || !this._ownerStyle.editable) |
| return; |
| |
| this._ownerStyle.nodeStyles.changePropertyEnabledState(this, enabled); |
| }, |
| |
| get overridden() |
| { |
| return this._overridden; |
| }, |
| |
| set overridden(overridden) |
| { |
| overridden = overridden || false; |
| |
| if (this._overridden === overridden) |
| return; |
| |
| var previousOverridden = this._overridden; |
| |
| this._overridden = overridden; |
| |
| if (this._overriddenStatusChangedTimeout) |
| return; |
| |
| function delayed() |
| { |
| delete this._overriddenStatusChangedTimeout; |
| |
| if (this._overridden === previousOverridden) |
| return; |
| |
| this.dispatchEventToListeners(WebInspector.CSSProperty.Event.OverriddenStatusChanged); |
| } |
| |
| this._overriddenStatusChangedTimeout = setTimeout(delayed.bind(this), 0); |
| }, |
| |
| get implicit() |
| { |
| return this._implicit; |
| }, |
| |
| get anonymous() |
| { |
| return this._anonymous; |
| }, |
| |
| get inherited() |
| { |
| return this._inherited; |
| }, |
| |
| get valid() |
| { |
| return this._valid; |
| }, |
| |
| get styleSheetTextRange() |
| { |
| return this._styleSheetTextRange; |
| }, |
| |
| get styleDeclarationTextRange() |
| { |
| if ("_styleDeclarationTextRange" in this) |
| return this._styleDeclarationTextRange; |
| |
| if (!this._ownerStyle || !this._styleSheetTextRange) |
| return null; |
| |
| var styleTextRange = this._ownerStyle.styleSheetTextRange; |
| if (!styleTextRange) |
| return null; |
| |
| var startLine = this._styleSheetTextRange.startLine - styleTextRange.startLine; |
| var endLine = this._styleSheetTextRange.endLine - styleTextRange.startLine; |
| |
| var startColumn = this._styleSheetTextRange.startColumn; |
| if (!startLine) |
| startColumn -= styleTextRange.startColumn; |
| |
| var endColumn = this._styleSheetTextRange.endColumn; |
| if (!endLine) |
| endColumn -= styleTextRange.startColumn; |
| |
| this._styleDeclarationTextRange = new WebInspector.TextRange(startLine, startColumn, endLine, endColumn); |
| |
| return this._styleDeclarationTextRange; |
| }, |
| |
| get relatedShorthandProperty() |
| { |
| return this._relatedShorthandProperty; |
| }, |
| |
| set relatedShorthandProperty(property) |
| { |
| this._relatedShorthandProperty = property || null; |
| }, |
| |
| get relatedLonghandProperties() |
| { |
| return this._relatedLonghandProperties; |
| }, |
| |
| addRelatedLonghandProperty: function(property) |
| { |
| this._relatedLonghandProperties.push(property); |
| }, |
| |
| clearRelatedLonghandProperties: function(property) |
| { |
| this._relatedLonghandProperties = []; |
| }, |
| |
| hasOtherVendorNameOrKeyword: function() |
| { |
| if ("_hasOtherVendorNameOrKeyword" in this) |
| return this._hasOtherVendorNameOrKeyword; |
| |
| this._hasOtherVendorNameOrKeyword = WebInspector.cssStyleManager.propertyNameHasOtherVendorPrefix(this.name) || WebInspector.cssStyleManager.propertyValueHasOtherVendorKeyword(this.value); |
| |
| return this._hasOtherVendorNameOrKeyword; |
| }, |
| |
| add: function() |
| { |
| // We can only add if the index is NaN. Return early otherwise. |
| if (!this._ownerStyle || !this._ownerStyle.editable || !isNaN(this._index)) |
| return; |
| |
| this._cancelPendingUpdate(); |
| this._ownerStyle.addProperty(this); |
| }, |
| |
| remove: function() |
| { |
| // We can only remove if the index is not NaN. Return early otherwise. |
| if (!this._ownerStyle || !this._ownerStyle.editable || isNaN(this._index)) |
| return; |
| |
| this._cancelPendingUpdate(); |
| this._ownerStyle.removeProperty(this); |
| }, |
| |
| // Private |
| |
| _updatePropertySoon: function() |
| { |
| if (!this._ownerStyle || isNaN(this._index) || this._updatePropertySoonTimeout) |
| return; |
| |
| function performUpdate() |
| { |
| delete this._updatePropertySoonTimeout; |
| |
| if (!this._ownerStyle || isNaN(this._index)) |
| return; |
| |
| var name = "_pendingName" in this ? this._pendingName : this._name; |
| var value = "_pendingValue" in this ? this._pendingValue : this._value; |
| var priority = "_pendingPriority" in this ? this._pendingPriority : this._priority; |
| |
| delete this._pendingName; |
| delete this._pendingValue; |
| delete this._pendingPriority; |
| |
| this._ownerStyle.nodeStyles.changeProperty(this, name, value, priority); |
| } |
| |
| this._updatePropertySoonTimeout = setTimeout(performUpdate.bind(this), 0); |
| }, |
| |
| _cancelPendingUpdate: function() |
| { |
| if (!this._updatePropertySoonTimeout) |
| return; |
| clearTimeout(this._updatePropertySoonTimeout); |
| delete this._updatePropertySoonTimeout; |
| } |
| }; |
| |
| WebInspector.CSSProperty.prototype.__proto__ = WebInspector.Object.prototype; |