You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
7.0 KiB
260 lines
7.0 KiB
/********************************************************************* |
|
* This is a fork from the CSS Style Declaration part of |
|
* https://github.com/NV/CSSOM |
|
********************************************************************/ |
|
'use strict'; |
|
var CSSOM = require('cssom'); |
|
var allProperties = require('./allProperties'); |
|
var allExtraProperties = require('./allExtraProperties'); |
|
var implementedProperties = require('./implementedProperties'); |
|
var { dashedToCamelCase } = require('./parsers'); |
|
var getBasicPropertyDescriptor = require('./utils/getBasicPropertyDescriptor'); |
|
|
|
/** |
|
* @constructor |
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration |
|
*/ |
|
var CSSStyleDeclaration = function CSSStyleDeclaration(onChangeCallback) { |
|
this._values = {}; |
|
this._importants = {}; |
|
this._length = 0; |
|
this._onChange = |
|
onChangeCallback || |
|
function() { |
|
return; |
|
}; |
|
}; |
|
CSSStyleDeclaration.prototype = { |
|
constructor: CSSStyleDeclaration, |
|
|
|
/** |
|
* |
|
* @param {string} name |
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue |
|
* @return {string} the value of the property if it has been explicitly set for this declaration block. |
|
* Returns the empty string if the property has not been set. |
|
*/ |
|
getPropertyValue: function(name) { |
|
if (!this._values.hasOwnProperty(name)) { |
|
return ''; |
|
} |
|
return this._values[name].toString(); |
|
}, |
|
|
|
/** |
|
* |
|
* @param {string} name |
|
* @param {string} value |
|
* @param {string} [priority=null] "important" or null |
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty |
|
*/ |
|
setProperty: function(name, value, priority) { |
|
if (value === undefined) { |
|
return; |
|
} |
|
if (value === null || value === '') { |
|
this.removeProperty(name); |
|
return; |
|
} |
|
var isCustomProperty = name.indexOf('--') === 0; |
|
if (isCustomProperty) { |
|
this._setProperty(name, value, priority); |
|
return; |
|
} |
|
var lowercaseName = name.toLowerCase(); |
|
if (!allProperties.has(lowercaseName) && !allExtraProperties.has(lowercaseName)) { |
|
return; |
|
} |
|
|
|
this[lowercaseName] = value; |
|
this._importants[lowercaseName] = priority; |
|
}, |
|
_setProperty: function(name, value, priority) { |
|
if (value === undefined) { |
|
return; |
|
} |
|
if (value === null || value === '') { |
|
this.removeProperty(name); |
|
return; |
|
} |
|
if (this._values[name]) { |
|
// Property already exist. Overwrite it. |
|
var index = Array.prototype.indexOf.call(this, name); |
|
if (index < 0) { |
|
this[this._length] = name; |
|
this._length++; |
|
} |
|
} else { |
|
// New property. |
|
this[this._length] = name; |
|
this._length++; |
|
} |
|
this._values[name] = value; |
|
this._importants[name] = priority; |
|
this._onChange(this.cssText); |
|
}, |
|
|
|
/** |
|
* |
|
* @param {string} name |
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty |
|
* @return {string} the value of the property if it has been explicitly set for this declaration block. |
|
* Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property. |
|
*/ |
|
removeProperty: function(name) { |
|
if (!this._values.hasOwnProperty(name)) { |
|
return ''; |
|
} |
|
|
|
var prevValue = this._values[name]; |
|
delete this._values[name]; |
|
delete this._importants[name]; |
|
|
|
var index = Array.prototype.indexOf.call(this, name); |
|
if (index < 0) { |
|
return prevValue; |
|
} |
|
|
|
// That's what WebKit and Opera do |
|
Array.prototype.splice.call(this, index, 1); |
|
|
|
// That's what Firefox does |
|
//this[index] = "" |
|
|
|
this._onChange(this.cssText); |
|
return prevValue; |
|
}, |
|
|
|
/** |
|
* |
|
* @param {String} name |
|
*/ |
|
getPropertyPriority: function(name) { |
|
return this._importants[name] || ''; |
|
}, |
|
|
|
getPropertyCSSValue: function() { |
|
//FIXME |
|
return; |
|
}, |
|
|
|
/** |
|
* element.style.overflow = "auto" |
|
* element.style.getPropertyShorthand("overflow-x") |
|
* -> "overflow" |
|
*/ |
|
getPropertyShorthand: function() { |
|
//FIXME |
|
return; |
|
}, |
|
|
|
isPropertyImplicit: function() { |
|
//FIXME |
|
return; |
|
}, |
|
|
|
/** |
|
* http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-item |
|
*/ |
|
item: function(index) { |
|
index = parseInt(index, 10); |
|
if (index < 0 || index >= this._length) { |
|
return ''; |
|
} |
|
return this[index]; |
|
}, |
|
}; |
|
|
|
Object.defineProperties(CSSStyleDeclaration.prototype, { |
|
cssText: { |
|
get: function() { |
|
var properties = []; |
|
var i; |
|
var name; |
|
var value; |
|
var priority; |
|
for (i = 0; i < this._length; i++) { |
|
name = this[i]; |
|
value = this.getPropertyValue(name); |
|
priority = this.getPropertyPriority(name); |
|
if (priority !== '') { |
|
priority = ' !' + priority; |
|
} |
|
properties.push([name, ': ', value, priority, ';'].join('')); |
|
} |
|
return properties.join(' '); |
|
}, |
|
set: function(value) { |
|
var i; |
|
this._values = {}; |
|
Array.prototype.splice.call(this, 0, this._length); |
|
this._importants = {}; |
|
var dummyRule; |
|
try { |
|
dummyRule = CSSOM.parse('#bogus{' + value + '}').cssRules[0].style; |
|
} catch (err) { |
|
// malformed css, just return |
|
return; |
|
} |
|
var rule_length = dummyRule.length; |
|
var name; |
|
for (i = 0; i < rule_length; ++i) { |
|
name = dummyRule[i]; |
|
this.setProperty( |
|
dummyRule[i], |
|
dummyRule.getPropertyValue(name), |
|
dummyRule.getPropertyPriority(name) |
|
); |
|
} |
|
this._onChange(this.cssText); |
|
}, |
|
enumerable: true, |
|
configurable: true, |
|
}, |
|
parentRule: { |
|
get: function() { |
|
return null; |
|
}, |
|
enumerable: true, |
|
configurable: true, |
|
}, |
|
length: { |
|
get: function() { |
|
return this._length; |
|
}, |
|
/** |
|
* This deletes indices if the new length is less then the current |
|
* length. If the new length is more, it does nothing, the new indices |
|
* will be undefined until set. |
|
**/ |
|
set: function(value) { |
|
var i; |
|
for (i = value; i < this._length; i++) { |
|
delete this[i]; |
|
} |
|
this._length = value; |
|
}, |
|
enumerable: true, |
|
configurable: true, |
|
}, |
|
}); |
|
|
|
require('./properties')(CSSStyleDeclaration.prototype); |
|
|
|
allProperties.forEach(function(property) { |
|
if (!implementedProperties.has(property)) { |
|
var declaration = getBasicPropertyDescriptor(property); |
|
Object.defineProperty(CSSStyleDeclaration.prototype, property, declaration); |
|
Object.defineProperty(CSSStyleDeclaration.prototype, dashedToCamelCase(property), declaration); |
|
} |
|
}); |
|
|
|
allExtraProperties.forEach(function(property) { |
|
if (!implementedProperties.has(property)) { |
|
var declaration = getBasicPropertyDescriptor(property); |
|
Object.defineProperty(CSSStyleDeclaration.prototype, property, declaration); |
|
Object.defineProperty(CSSStyleDeclaration.prototype, dashedToCamelCase(property), declaration); |
|
} |
|
}); |
|
|
|
exports.CSSStyleDeclaration = CSSStyleDeclaration;
|
|
|