blob: e2aa6b3c85fbf8732f512558ff3929426929e29d [file] [log] [blame]
#---------------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#---------------------------------------------------------------------------------
IDGenerator = require('../common/IDGenerator')
Weinre = require('../common/Weinre')
_elementMatchesSelector = null
#-------------------------------------------------------------------------------
module.exports = class CSSStore
#---------------------------------------------------------------------------
constructor: ->
@styleSheetMap = {}
@styleRuleMap = {}
@styleDeclMap = {}
@testElement = document.createElement("div")
#---------------------------------------------------------------------------
getInlineStyle: (node) ->
styleObject = @_buildMirrorForStyle(node.style, true)
for cssProperty in styleObject.cssProperties
cssProperty.status = "style"
styleObject
#---------------------------------------------------------------------------
getComputedStyle: (node) ->
return {} unless node
return {} unless node.nodeType == Node.ELEMENT_NODE
styleObject = @_buildMirrorForStyle(window.getComputedStyle(node), false)
styleObject
#---------------------------------------------------------------------------
getMatchedCSSRules: (node) ->
result = []
for styleSheet in document.styleSheets
continue unless styleSheet.cssRules
for cssRule in styleSheet.cssRules
continue unless _elementMatchesSelector(node, cssRule.selectorText)
object = {}
object.ruleId = @_getStyleRuleId(cssRule)
object.selectorText = cssRule.selectorText
object.style = @_buildMirrorForStyle(cssRule.style, true)
result.push object
result
#---------------------------------------------------------------------------
getStyleAttributes: (node) ->
result = {}
result
#---------------------------------------------------------------------------
getPseudoElements: (node) ->
result = []
result
#---------------------------------------------------------------------------
setPropertyText: (styleId, propertyIndex, text, overwrite) ->
styleDecl = Weinre.cssStore._getStyleDecl(styleId)
unless styleDecl
Weinre.logWarning "requested style not available: " + styleId
return null
mirror = styleDecl.__weinre__mirror
unless mirror
Weinre.logWarning "requested mirror not available: " + styleId
return null
properties = mirror.cssProperties
propertyMirror = @_parseProperty(text)
if null == propertyMirror
@_removePropertyFromMirror mirror, propertyIndex
properties = mirror.cssProperties
else
@_removePropertyFromMirror mirror, propertyIndex
properties = mirror.cssProperties
propertyIndices = {}
i = 0
while i < properties.length
propertyIndices[properties[i].name] = i
i++
i = 0
while i < propertyMirror.cssProperties.length
if propertyIndices[propertyMirror.cssProperties[i].name]?
properties[propertyIndices[propertyMirror.cssProperties[i].name]] = propertyMirror.cssProperties[i]
else
properties.push propertyMirror.cssProperties[i]
i++
for key of propertyMirror.shorthandValues
mirror.shorthandValues[key] = propertyMirror.shorthandValues[key]
properties.sort compare = (p1, p2) ->
if p1.name < p2.name
-1
else if p1.name > p2.name
1
else
0
@_setStyleFromMirror styleDecl
mirror
#---------------------------------------------------------------------------
_removePropertyFromMirror: (mirror, index) ->
properties = mirror.cssProperties
return if index >= properties.length
property = properties[index]
properties[index] = null
if mirror.shorthandValues[property.name]
delete mirror.shorthandValues[property.name]
i = 0
while i < properties.length
if properties[i]
if properties[i].shorthandName == property.name
properties[i] = null
i++
newProperties = []
i = 0
while i < properties.length
newProperties.push properties[i] if properties[i]
i++
mirror.cssProperties = newProperties
#---------------------------------------------------------------------------
toggleProperty: (styleId, propertyIndex, disable) ->
styleDecl = Weinre.cssStore._getStyleDecl(styleId)
unless styleDecl
Weinre.logWarning "requested style not available: " + styleId
return null
mirror = styleDecl.__weinre__mirror
unless mirror
Weinre.logWarning "requested mirror not available: " + styleId
return null
cssProperty = mirror.cssProperties[propertyIndex]
unless cssProperty
Weinre.logWarning "requested property not available: #{styleId}: " + propertyIndex
return null
if disable
cssProperty.status = "disabled"
else
cssProperty.status = "active"
@_setStyleFromMirror styleDecl
mirror
#---------------------------------------------------------------------------
_setStyleFromMirror: (styleDecl) ->
cssText = []
cssProperties = styleDecl.__weinre__mirror.cssProperties
cssText = ""
for property in cssProperties
continue unless property.parsedOk
continue if property.status == "disabled"
continue if property.shorthandName
cssText += property.name + ": " + property.value
if property.priority == "important"
cssText += " !important; "
else
cssText += "; "
styleDecl.cssText = cssText
#---------------------------------------------------------------------------
_buildMirrorForStyle: (styleDecl, bind) ->
result =
properties: {}
cssProperties: []
return result unless styleDecl
if bind
result.styleId = @_getStyleDeclId(styleDecl)
styleDecl.__weinre__mirror = result
result.properties.width = styleDecl.getPropertyValue("width") or ""
result.properties.height = styleDecl.getPropertyValue("height") or ""
result.cssText = styleDecl.cssText
result.shorthandValues = {}
properties = []
if styleDecl
i = 0
while i < styleDecl.length
property = {}
name = styleDecl.item(i)
property.name = name
property.priority = styleDecl.getPropertyPriority(name)
property.implicit = styleDecl.isPropertyImplicit(name)
property.shorthandName = styleDecl.getPropertyShorthand(name) or ""
property.status = (if property.shorthandName then "style" else "active")
property.parsedOk = true
property.value = styleDecl.getPropertyValue(name)
properties.push property
if property.shorthandName
shorthandName = property.shorthandName
unless 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
i++
properties.sort (p1, p2) ->
if p1.name < p2.name
-1
else if p1.name > p2.name
1
else
0
result.cssProperties = properties
result
#---------------------------------------------------------------------------
_parseProperty: (string) ->
testStyleDecl = @testElement.style
try
testStyleDecl.cssText = string
unless testStyleDecl.cssText == ""
return @_buildMirrorForStyle(testStyleDecl, false)
propertyPattern = /\s*(.+)\s*:\s*(.+)\s*(!important)?\s*;/
match = propertyPattern.exec(string)
return null unless match
match[3] = (if (match[3] == "!important") then "important" else "")
property = {}
property.name = match[1]
property.priority = match[3]
property.implicit = true
property.shorthandName = ""
property.status = "inactive"
property.parsedOk = false
property.value = match[2]
result = {}
result.width = 0
result.height = 0
result.shorthandValues = 0
result.cssProperties = [ property ]
result
#---------------------------------------------------------------------------
_getStyleSheet: (id) ->
_getMappableObject id, @styleSheetMap
#---------------------------------------------------------------------------
_getStyleSheetId: (styleSheet) ->
_getMappableId styleSheet, @styleSheetMap
#---------------------------------------------------------------------------
_getStyleRule: (id) ->
_getMappableObject id, @styleRuleMap
#---------------------------------------------------------------------------
_getStyleRuleId: (styleRule) ->
_getMappableId styleRule, @styleRuleMap
#---------------------------------------------------------------------------
_getStyleDecl: (id) ->
_getMappableObject id, @styleDeclMap
#---------------------------------------------------------------------------
_getStyleDeclId: (styleDecl) ->
_getMappableId styleDecl, @styleDeclMap
#-------------------------------------------------------------------------------
_getMappableObject = (id, map) ->
map[id]
#-------------------------------------------------------------------------------
_getMappableId = (object, map) ->
IDGenerator.getId object, map
#-------------------------------------------------------------------------------
_mozMatchesSelector = (element, selector) ->
return false unless element.mozMatchesSelector
element.mozMatchesSelector selector
#-------------------------------------------------------------------------------
_webkitMatchesSelector = (element, selector) ->
return false unless element.webkitMatchesSelector
element.webkitMatchesSelector selector
#-------------------------------------------------------------------------------
_fallbackMatchesSelector = (element, selector) ->
false
#-------------------------------------------------------------------------------
if (Element.prototype.webkitMatchesSelector)
_elementMatchesSelector = _webkitMatchesSelector
else if (Element.prototype.mozMatchesSelector)
_elementMatchesSelector = _mozMatchesSelector
else
_elementMatchesSelector = _fallbackMatchesSelector
#-------------------------------------------------------------------------------
require("../common/MethodNamer").setNamesForClass(module.exports)