| |
| /* |
| * weinre is available under *either* the terms of the modified BSD license *or* the |
| * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text. |
| * |
| * Copyright (c) 2010, 2011 IBM Corporation |
| */ |
| |
| requireClass ../common/IDGenerator |
| requireClass ../common/Weinre |
| |
| //----------------------------------------------------------------------------- |
| class CSSStore |
| this.styleSheetMap = {} |
| this.styleRuleMap = {} |
| this.styleDeclMap = {} |
| this.testElement = document.createElement("div") |
| |
| //----------------------------------------------------------------------------- |
| init |
| var Properties = [] |
| |
| //----------------------------------------------------------------------------- |
| static method addCSSProperties(properties) |
| Properties = properties |
| |
| //----------------------------------------------------------------------------- |
| method getInlineStyle(node) |
| var styleObject = this._buildMirrorForStyle(node.style, true) |
| for (var i=0; i<styleObject.cssProperties.length; i++) { |
| styleObject.cssProperties[i].status = "style" |
| } |
| return styleObject |
| |
| //----------------------------------------------------------------------------- |
| method getComputedStyle(node) |
| if (!node) return {} |
| if (node.nodeType != Node.ELEMENT_NODE) return {} |
| |
| var styleObject = this._buildMirrorForStyle(window.getComputedStyle(node), false) |
| return styleObject |
| |
| //----------------------------------------------------------------------------- |
| method getMatchedCSSRules(node) |
| var result = [] |
| |
| for (var i=0; i<document.styleSheets.length; i++) { |
| var styleSheet = document.styleSheets[i] |
| |
| if (!styleSheet.cssRules) continue |
| |
| for (var j=0; j<styleSheet.cssRules.length; j++) { |
| var cssRule = styleSheet.cssRules[j] |
| |
| if (!_elementMatchesSelector(node, cssRule.selectorText)) continue |
| |
| var object = {} |
| |
| object.ruleId = this._getStyleRuleId(cssRule) |
| object.selectorText = cssRule.selectorText |
| object.style = this._buildMirrorForStyle(cssRule.style, true) |
| result.push(object) |
| } |
| } |
| |
| return result |
| |
| //----------------------------------------------------------------------------- |
| method getStyleAttributes(node) |
| var result = {} |
| |
| return result |
| |
| //----------------------------------------------------------------------------- |
| method getPseudoElements(node) |
| var result = [] |
| |
| return result |
| |
| //----------------------------------------------------------------------------- |
| method setPropertyText(styleId, propertyIndex, text, overwrite) |
| var styleDecl = Weinre.cssStore._getStyleDecl(styleId) |
| |
| if (!styleDecl) { |
| Weinre.logWarning("requested style not available: " + styleId) |
| return null |
| } |
| |
| var mirror = styleDecl.__weinre__mirror |
| if (!mirror) { |
| Weinre.logWarning("requested mirror not available: " + styleId) |
| return null |
| } |
| |
| var properties = mirror.cssProperties |
| |
| // parse the css text |
| var propertyMirror = this._parseProperty(text) |
| |
| // remove property |
| if (null == propertyMirror) { |
| this._removePropertyFromMirror(mirror, propertyIndex) |
| properties = mirror.cssProperties |
| } |
| |
| // add or replace property |
| else { |
| // if replacing, remove the old one |
| this._removePropertyFromMirror(mirror, propertyIndex) |
| properties = mirror.cssProperties |
| |
| // index properties by name |
| var propertyIndices = {} |
| for (var i=0; i<properties.length; i++) { |
| propertyIndices[properties[i].name] = i |
| } |
| |
| // add the new ones, or replacing ones |
| for (var i=0; i<propertyMirror.cssProperties.length; i++) { |
| if (propertyIndices[propertyMirror.cssProperties[i].name] != null) { |
| // property already exists, just replace it |
| properties[propertyIndices[propertyMirror.cssProperties[i].name]] = propertyMirror.cssProperties[i] |
| } |
| else { |
| // new property, add it |
| properties.push(propertyMirror.cssProperties[i]) |
| } |
| } |
| |
| for (var key in propertyMirror.shorthandValues) { |
| mirror.shorthandValues[key] = propertyMirror.shorthandValues[key] |
| } |
| } |
| |
| properties.sort(function(p1,p2) { |
| if (p1.name < p2.name) return -1 |
| else if (p1.name > p2.name) return 1 |
| else return 0 |
| }) |
| |
| this._setStyleFromMirror(styleDecl) |
| |
| return mirror |
| |
| //----------------------------------------------------------------------------- |
| method _removePropertyFromMirror(mirror, index) |
| var properties = mirror.cssProperties |
| |
| if (index >= properties.length) return |
| |
| var property = properties[index] |
| |
| properties[index] = null |
| |
| if (mirror.shorthandValues[property.name]) { |
| delete mirror.shorthandValues[property.name] |
| |
| for (var i=0; i<properties.length; i++) { |
| if (properties[i]) { |
| if (properties[i].shorthandName == property.name) { |
| properties[i] = null |
| } |
| } |
| } |
| } |
| |
| var newProperties = [] |
| |
| for (var i=0; i<properties.length; i++) { |
| if (properties[i]) newProperties.push(properties[i]) |
| } |
| |
| mirror.cssProperties = newProperties |
| |
| //----------------------------------------------------------------------------- |
| method toggleProperty(styleId, propertyIndex, disable) |
| var styleDecl = Weinre.cssStore._getStyleDecl(styleId) |
| |
| if (!styleDecl) { |
| Weinre.logWarning("requested style not available: " + styleId) |
| return null |
| } |
| |
| var mirror = styleDecl.__weinre__mirror |
| if (!mirror) { |
| Weinre.logWarning("requested mirror not available: " + styleId) |
| return null |
| } |
| |
| var cssProperty = mirror.cssProperties[propertyIndex] |
| if (!cssProperty) { |
| Weinre.logWarning("requested property not available: " + styleId + ": " + propertyIndex) |
| return null |
| } |
| |
| if (disable) { |
| cssProperty.status = "disabled" |
| } |
| |
| else { |
| cssProperty.status = "active" |
| } |
| |
| this._setStyleFromMirror(styleDecl) |
| |
| return mirror |
| |
| //----------------------------------------------------------------------------- |
| method _setStyleFromMirror(styleDecl) |
| var cssText = [] |
| |
| var cssProperties = styleDecl.__weinre__mirror.cssProperties |
| |
| var cssText = "" |
| for (var i=0; i<cssProperties.length; i++) { |
| var property = cssProperties[i] |
| |
| if (!property.parsedOk) continue |
| if (property.status == "disabled") continue |
| if (property.shorthandName) continue |
| |
| cssText += property.name + ": " + property.value |
| if (property.priority == "important") { |
| cssText += " !important; " |
| } |
| else { |
| cssText += "; " |
| } |
| } |
| |
| styleDecl.cssText = cssText |
| |
| //----------------------------------------------------------------------------- |
| method _buildMirrorForStyle(styleDecl, bind) |
| var result = { |
| properties: {}, |
| cssProperties: [] |
| } |
| |
| if (!styleDecl) return result |
| |
| if (bind) { |
| result.styleId = this._getStyleDeclId(styleDecl) |
| styleDecl.__weinre__mirror = result |
| } |
| |
| result.properties.width = styleDecl.getPropertyValue("width") || "" |
| result.properties.height = styleDecl.getPropertyValue("height") || "" |
| result.cssText = styleDecl.cssText |
| |
| result.shorthandValues = {} |
| |
| var properties = [] |
| |
| if (styleDecl) { |
| for (var i=0; i < styleDecl.length; i++) { |
| var property = {} |
| var name = styleDecl.item(i) |
| |
| property.name = name |
| property.priority = styleDecl.getPropertyPriority(name) |
| property.implicit = styleDecl.isPropertyImplicit(name) |
| property.shorthandName = styleDecl.getPropertyShorthand(name) || "" |
| property.status = property.shorthandName ? "style" : "active" |
| property.parsedOk = true |
| property.value = styleDecl.getPropertyValue(name) |
| |
| properties.push(property); |
| |
| if (property.shorthandName) { |
| var shorthandName = property.shorthandName |
| if (!result.shorthandValues[shorthandName]) { |
| result.shorthandValues[shorthandName] = styleDecl.getPropertyValue(shorthandName) |
| |
| property = {} |
| property.name = shorthandName |
| property.priority = styleDecl.getPropertyPriority(shorthandName) |
| property.implicit = styleDecl.isPropertyImplicit(shorthandName) |
| property.shorthandName = "" |
| property.status = "active" |
| property.parsedOk = true |
| property.value = styleDecl.getPropertyValue(name) |
| |
| properties.push(property); |
| } |
| } |
| } |
| } |
| |
| properties.sort(function(p1,p2) { |
| if (p1.name < p2.name) return -1 |
| else if (p1.name > p2.name) return 1 |
| else return 0 |
| }) |
| |
| result.cssProperties = properties |
| |
| return result |
| |
| //----------------------------------------------------------------------------- |
| method _parseProperty(string) |
| var testStyleDecl = this.testElement.style |
| |
| try { |
| testStyleDecl.cssText = string |
| |
| if (testStyleDecl.cssText != "") { |
| return this._buildMirrorForStyle(testStyleDecl, false) |
| } |
| } |
| catch(e) { |
| } |
| |
| var propertyPattern = /\s*(.+)\s*:\s*(.+)\s*(!important)?\s*;/ |
| var match = propertyPattern.exec(string) |
| if (!match) return null |
| |
| match[3] = (match[3] == "!important") ? "important" : "" |
| |
| var property = {} |
| |
| property.name = match[1] |
| property.priority = match[3] |
| property.implicit = true |
| property.shorthandName = "" |
| property.status = "inactive" |
| property.parsedOk = false |
| property.value = match[2] |
| |
| var result = {} |
| |
| result.width = 0 |
| result.height = 0 |
| result.shorthandValues = 0 |
| result.cssProperties = [ property ] |
| |
| return result |
| |
| //----------------------------------------------------------------------------- |
| method _getStyleSheet(id) |
| return _getMappableObject(id, this.styleSheetMap) |
| |
| //----------------------------------------------------------------------------- |
| method _getStyleSheetId(styleSheet) |
| return _getMappableId(styleSheet, this.styleSheetMap) |
| |
| //----------------------------------------------------------------------------- |
| method _getStyleRule(id) |
| return _getMappableObject(id, this.styleRuleMap) |
| |
| //----------------------------------------------------------------------------- |
| method _getStyleRuleId(styleRule) |
| return _getMappableId(styleRule, this.styleRuleMap) |
| |
| //----------------------------------------------------------------------------- |
| method _getStyleDecl(id) |
| return _getMappableObject(id, this.styleDeclMap) |
| |
| //----------------------------------------------------------------------------- |
| method _getStyleDeclId(styleDecl) |
| return _getMappableId(styleDecl, this.styleDeclMap) |
| |
| //----------------------------------------------------------------------------- |
| function _getMappableObject(id, map) |
| return map[id] |
| |
| //----------------------------------------------------------------------------- |
| function _getMappableId(object, map) |
| return IDGenerator.getId(object, map) |
| |
| //----------------------------------------------------------------------------- |
| function _mozMatchesSelector(element, selector) |
| if (!element.mozMatchesSelector) return false |
| return element.mozMatchesSelector(selector) |
| |
| //----------------------------------------------------------------------------- |
| function _webkitMatchesSelector(element, selector) |
| if (!element.webkitMatchesSelector) return false |
| return element.webkitMatchesSelector(selector) |
| |
| //----------------------------------------------------------------------------- |
| function _fallbackMatchesSelector(element, selector) |
| return false |
| |
| //----------------------------------------------------------------------------- |
| init |
| var _elementMatchesSelector |
| |
| if (Element.prototype.webkitMatchesSelector) _elementMatchesSelector = _webkitMatchesSelector |
| else if (Element.prototype.mozMatchesSelector) _elementMatchesSelector = _mozMatchesSelector |
| else _elementMatchesSelector = _fallbackMatchesSelector |