234 lines
6.8 KiB
JavaScript
234 lines
6.8 KiB
JavaScript
|
/*********************************************************************
|
||
|
* This is a fork from the CSS Style Declaration part of
|
||
|
* https://github.com/NV/CSSOM
|
||
|
********************************************************************/
|
||
|
"use strict";
|
||
|
var CSSOM = require('cssom');
|
||
|
var fs = require('fs');
|
||
|
var path = require('path');
|
||
|
|
||
|
var camelToDashed = require('./parsers').camelToDashed;
|
||
|
var dashedToCamelCase = require('./parsers').dashedToCamelCase;
|
||
|
|
||
|
/**
|
||
|
* @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 camel_case = dashedToCamelCase(name);
|
||
|
this[camel_case] = value;
|
||
|
this._importants[name] = 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
|
||
|
},
|
||
|
'float': {
|
||
|
get: function () { return this.cssFloat; },
|
||
|
set: function (value) {
|
||
|
this.cssFloat = value;
|
||
|
},
|
||
|
enumerable: true,
|
||
|
configurable: true
|
||
|
}
|
||
|
});
|
||
|
|
||
|
require('./properties')(CSSStyleDeclaration.prototype);
|
||
|
|
||
|
exports.CSSStyleDeclaration = CSSStyleDeclaration;
|