| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 | /********************************************************************* * 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;
 |