256 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			256 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 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 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;
 |