CSSStyleRule.js
  1  //.CommonJS
  2  var CSSOM = {
  3  	CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
  4  	CSSRule: require("./CSSRule").CSSRule
  5  };
  6  ///CommonJS
  7  
  8  
  9  /**
 10   * @constructor
 11   * @see http://dev.w3.org/csswg/cssom/#cssstylerule
 12   * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule
 13   */
 14  CSSOM.CSSStyleRule = function CSSStyleRule() {
 15  	CSSOM.CSSRule.call(this);
 16  	this.selectorText = "";
 17  	this.style = new CSSOM.CSSStyleDeclaration();
 18  	this.style.parentRule = this;
 19  };
 20  
 21  CSSOM.CSSStyleRule.prototype = new CSSOM.CSSRule();
 22  CSSOM.CSSStyleRule.prototype.constructor = CSSOM.CSSStyleRule;
 23  CSSOM.CSSStyleRule.prototype.type = 1;
 24  
 25  Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
 26  	get: function() {
 27  		var text;
 28  		if (this.selectorText) {
 29  			text = this.selectorText + " {" + this.style.cssText + "}";
 30  		} else {
 31  			text = "";
 32  		}
 33  		return text;
 34  	},
 35  	set: function(cssText) {
 36  		var rule = CSSOM.CSSStyleRule.parse(cssText);
 37  		this.style = rule.style;
 38  		this.selectorText = rule.selectorText;
 39  	}
 40  });
 41  
 42  
 43  /**
 44   * NON-STANDARD
 45   * lightweight version of parse.js.
 46   * @param {string} ruleText
 47   * @return CSSStyleRule
 48   */
 49  CSSOM.CSSStyleRule.parse = function(ruleText) {
 50  	var i = 0;
 51  	var state = "selector";
 52  	var index;
 53  	var j = i;
 54  	var buffer = "";
 55  
 56  	var SIGNIFICANT_WHITESPACE = {
 57  		"selector": true,
 58  		"value": true
 59  	};
 60  
 61  	var styleRule = new CSSOM.CSSStyleRule();
 62  	var name, priority="";
 63  
 64  	for (var character; (character = ruleText.charAt(i)); i++) {
 65  
 66  		switch (character) {
 67  
 68  		case " ":
 69  		case "\t":
 70  		case "\r":
 71  		case "\n":
 72  		case "\f":
 73  			if (SIGNIFICANT_WHITESPACE[state]) {
 74  				// Squash 2 or more white-spaces in the row into 1
 75  				switch (ruleText.charAt(i - 1)) {
 76  					case " ":
 77  					case "\t":
 78  					case "\r":
 79  					case "\n":
 80  					case "\f":
 81  						break;
 82  					default:
 83  						buffer += " ";
 84  						break;
 85  				}
 86  			}
 87  			break;
 88  
 89  		// String
 90  		case '"':
 91  			j = i + 1;
 92  			index = ruleText.indexOf('"', j) + 1;
 93  			if (!index) {
 94  				throw '" is missing';
 95  			}
 96  			buffer += ruleText.slice(i, index);
 97  			i = index - 1;
 98  			break;
 99  
100  		case "'":
101  			j = i + 1;
102  			index = ruleText.indexOf("'", j) + 1;
103  			if (!index) {
104  				throw "' is missing";
105  			}
106  			buffer += ruleText.slice(i, index);
107  			i = index - 1;
108  			break;
109  
110  		// Comment
111  		case "/":
112  			if (ruleText.charAt(i + 1) === "*") {
113  				i += 2;
114  				index = ruleText.indexOf("*/", i);
115  				if (index === -1) {
116  					throw new SyntaxError("Missing */");
117  				} else {
118  					i = index + 1;
119  				}
120  			} else {
121  				buffer += character;
122  			}
123  			break;
124  
125  		case "{":
126  			if (state === "selector") {
127  				styleRule.selectorText = buffer.trim();
128  				buffer = "";
129  				state = "name";
130  			}
131  			break;
132  
133  		case ":":
134  			if (state === "name") {
135  				name = buffer.trim();
136  				buffer = "";
137  				state = "value";
138  			} else {
139  				buffer += character;
140  			}
141  			break;
142  
143  		case "!":
144  			if (state === "value" && ruleText.indexOf("!important", i) === i) {
145  				priority = "important";
146  				i += "important".length;
147  			} else {
148  				buffer += character;
149  			}
150  			break;
151  
152  		case ";":
153  			if (state === "value") {
154  				styleRule.style.setProperty(name, buffer.trim(), priority);
155  				priority = "";
156  				buffer = "";
157  				state = "name";
158  			} else {
159  				buffer += character;
160  			}
161  			break;
162  
163  		case "}":
164  			if (state === "value") {
165  				styleRule.style.setProperty(name, buffer.trim(), priority);
166  				priority = "";
167  				buffer = "";
168  			} else if (state === "name") {
169  				break;
170  			} else {
171  				buffer += character;
172  			}
173  			state = "selector";
174  			break;
175  
176  		default:
177  			buffer += character;
178  			break;
179  
180  		}
181  	}
182  
183  	return styleRule;
184  
185  };
186  
187  
188  //.CommonJS
189  exports.CSSStyleRule = CSSOM.CSSStyleRule;
190  ///CommonJS