|
1 /* |
|
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved. |
|
3 Code licensed under the BSD License: |
|
4 http://developer.yahoo.net/yui/license.txt |
|
5 version: 3.0.0 |
|
6 build: 1549 |
|
7 */ |
|
8 YUI.add('stylesheet', function(Y) { |
|
9 |
|
10 /** |
|
11 * The StyleSheet component is a module for creating and modifying CSS |
|
12 * stylesheets. |
|
13 * |
|
14 * @module stylesheet |
|
15 */ |
|
16 var d = Y.config.doc, |
|
17 p = d.createElement('p'), // Have to hold the node (see notes) |
|
18 workerStyle = p.style, // worker style collection |
|
19 isString = Y.Lang.isString, |
|
20 selectors = {}, |
|
21 sheets = {}, |
|
22 floatAttr = ('cssFloat' in workerStyle) ? 'cssFloat' : 'styleFloat', |
|
23 _toCssText, |
|
24 _unsetOpacity, |
|
25 _unsetProperty, |
|
26 OPACITY = 'opacity', |
|
27 FLOAT = 'float', |
|
28 EMPTY = ''; |
|
29 |
|
30 // Normalizes the removal of an assigned style for opacity. IE uses the filter |
|
31 // property. |
|
32 _unsetOpacity = (OPACITY in workerStyle) ? |
|
33 function (style) { style.opacity = EMPTY; } : |
|
34 function (style) { style.filter = EMPTY; }; |
|
35 |
|
36 // Normalizes the removal of an assigned style for a given property. Expands |
|
37 // shortcut properties if necessary and handles the various names for the float |
|
38 // property. |
|
39 workerStyle.border = "1px solid red"; |
|
40 workerStyle.border = EMPTY; // IE doesn't unset child properties |
|
41 _unsetProperty = workerStyle.borderLeft ? |
|
42 function (style,prop) { |
|
43 var p; |
|
44 if (prop !== floatAttr && prop.toLowerCase().indexOf(FLOAT) != -1) { |
|
45 prop = floatAttr; |
|
46 } |
|
47 if (isString(style[prop])) { |
|
48 switch (prop) { |
|
49 case OPACITY: |
|
50 case 'filter' : _unsetOpacity(style); break; |
|
51 case 'font' : |
|
52 style.font = style.fontStyle = style.fontVariant = |
|
53 style.fontWeight = style.fontSize = style.lineHeight = |
|
54 style.fontFamily = EMPTY; |
|
55 break; |
|
56 default : |
|
57 for (p in style) { |
|
58 if (p.indexOf(prop) === 0) { |
|
59 style[p] = EMPTY; |
|
60 } |
|
61 } |
|
62 } |
|
63 } |
|
64 } : |
|
65 function (style,prop) { |
|
66 if (prop !== floatAttr && prop.toLowerCase().indexOf(FLOAT) != -1) { |
|
67 prop = floatAttr; |
|
68 } |
|
69 if (isString(style[prop])) { |
|
70 if (prop === OPACITY) { |
|
71 _unsetOpacity(style); |
|
72 } else { |
|
73 style[prop] = EMPTY; |
|
74 } |
|
75 } |
|
76 }; |
|
77 |
|
78 /** |
|
79 * Create an instance of StyleSheet to encapsulate a css stylesheet. |
|
80 * The constructor can be called using function or constructor syntax. |
|
81 * <pre><code>var sheet = Y.StyleSheet(..);</pre></code> |
|
82 * or |
|
83 * <pre><code>var sheet = new Y.StyleSheet(..);</pre></code> |
|
84 * |
|
85 * The first parameter passed can be any of the following things: |
|
86 * <ul> |
|
87 * <li>The desired string name to register a new empty sheet</li> |
|
88 * <li>The string name of an existing StyleSheet instance</li> |
|
89 * <li>The unique guid generated for an existing StyleSheet instance</li> |
|
90 * <li>The id of an existing <code><link></code> or <code><style></code> node</li> |
|
91 * <li>The node reference for an existing <code><link></code> or <code><style></code> node</li> |
|
92 * <li>The Y.Node instance wrapping an existing <code><link></code> or <code><style></code> node</li> |
|
93 * <li>A chunk of css text to create a new stylesheet from</li> |
|
94 * </ul> |
|
95 * |
|
96 * <p>If a string is passed, StyleSheet will first look in its static name |
|
97 * registry for an existing sheet, then in the DOM for an element with that id. |
|
98 * If neither are found and the string contains the { character, it will be |
|
99 * used as a the initial cssText for a new StyleSheet. Otherwise, a new empty |
|
100 * StyleSheet is created, assigned the string value as a name, and registered |
|
101 * statically by that name.</p> |
|
102 * |
|
103 * <p>The optional second parameter is a string name to register the sheet as. |
|
104 * This param is largely useful when providing a node id/ref or chunk of css |
|
105 * text to create a populated instance.</p> |
|
106 * |
|
107 * @class StyleSheet |
|
108 * @constructor |
|
109 * @param seed {String|HTMLElement|Node} a style or link node, its id, or a |
|
110 * name or guid of a StyleSheet, or a string of css text |
|
111 * @param name {String} (optional) name to register instance for future static |
|
112 * access |
|
113 */ |
|
114 function StyleSheet(seed, name) { |
|
115 var head, |
|
116 node, |
|
117 sheet, |
|
118 cssRules = {}, |
|
119 _rules, |
|
120 _insertRule, |
|
121 _deleteRule, |
|
122 i,r,sel; |
|
123 |
|
124 // Factory or constructor |
|
125 if (!(this instanceof StyleSheet)) { |
|
126 return new StyleSheet(seed,name); |
|
127 } |
|
128 |
|
129 // Extract the DOM node from Node instances |
|
130 if (seed) { |
|
131 if (Y.Node && seed instanceof Y.Node) { |
|
132 node = Y.Node.getDOMNode(seed); |
|
133 } else if (seed.nodeName) { |
|
134 node = seed; |
|
135 // capture the DOM node if the string is an id |
|
136 } else if (isString(seed)) { |
|
137 if (seed && sheets[seed]) { |
|
138 return sheets[seed]; |
|
139 } |
|
140 node = d.getElementById(seed.replace(/^#/,EMPTY)); |
|
141 } |
|
142 |
|
143 // Check for the StyleSheet in the static registry |
|
144 if (node && sheets[Y.stamp(node)]) { |
|
145 return sheets[Y.stamp(node)]; |
|
146 } |
|
147 } |
|
148 |
|
149 |
|
150 // Create a style node if necessary |
|
151 if (!node || !/^(?:style|link)$/i.test(node.nodeName)) { |
|
152 node = d.createElement('style'); |
|
153 node.type = 'text/css'; |
|
154 } |
|
155 |
|
156 if (isString(seed)) { |
|
157 // Create entire sheet from seed cssText |
|
158 if (seed.indexOf('{') != -1) { |
|
159 // Not a load-time fork because low run-time impact and IE fails |
|
160 // test for s.styleSheet at page load time (oddly) |
|
161 if (node.styleSheet) { |
|
162 node.styleSheet.cssText = seed; |
|
163 } else { |
|
164 node.appendChild(d.createTextNode(seed)); |
|
165 } |
|
166 } else if (!name) { |
|
167 name = seed; |
|
168 } |
|
169 } |
|
170 |
|
171 // Make sure the node is attached to the appropriate head element |
|
172 if (!node.parentNode || node.parentNode.nodeName.toLowerCase() !== 'head') { |
|
173 head = (node.ownerDocument || d).getElementsByTagName('head')[0]; |
|
174 // styleSheet isn't available on the style node in FF2 until appended |
|
175 // to the head element. style nodes appended to body do not affect |
|
176 // change in Safari. |
|
177 head.appendChild(node); |
|
178 } |
|
179 |
|
180 // Begin setting up private aliases to the important moving parts |
|
181 // 1. The stylesheet object |
|
182 // IE stores StyleSheet under the "styleSheet" property |
|
183 // Safari doesn't populate sheet for xdomain link elements |
|
184 sheet = node.sheet || node.styleSheet; |
|
185 |
|
186 // 2. The style rules collection |
|
187 // IE stores the rules collection under the "rules" property |
|
188 _rules = sheet && ('cssRules' in sheet) ? 'cssRules' : 'rules'; |
|
189 |
|
190 // 3. The method to remove a rule from the stylesheet |
|
191 // IE supports removeRule |
|
192 _deleteRule = ('deleteRule' in sheet) ? |
|
193 function (i) { sheet.deleteRule(i); } : |
|
194 function (i) { sheet.removeRule(i); }; |
|
195 |
|
196 // 4. The method to add a new rule to the stylesheet |
|
197 // IE supports addRule with different signature |
|
198 _insertRule = ('insertRule' in sheet) ? |
|
199 function (sel,css,i) { sheet.insertRule(sel+' {'+css+'}',i); } : |
|
200 function (sel,css,i) { sheet.addRule(sel,css,i); }; |
|
201 |
|
202 // 5. Initialize the cssRules map from the node |
|
203 // xdomain link nodes forbid access to the cssRules collection, so this |
|
204 // will throw an error. |
|
205 // TODO: research alternate stylesheet, @media |
|
206 for (i = sheet[_rules].length - 1; i >= 0; --i) { |
|
207 r = sheet[_rules][i]; |
|
208 sel = r.selectorText; |
|
209 |
|
210 if (cssRules[sel]) { |
|
211 cssRules[sel].style.cssText += ';' + r.style.cssText; |
|
212 _deleteRule(i); |
|
213 } else { |
|
214 cssRules[sel] = r; |
|
215 } |
|
216 } |
|
217 |
|
218 // Cache the instance by the generated Id |
|
219 StyleSheet.register(Y.stamp(node),this); |
|
220 |
|
221 // Register the instance by name if provided or defaulted from seed |
|
222 if (name) { |
|
223 StyleSheet.register(name,this); |
|
224 } |
|
225 |
|
226 // Public API |
|
227 Y.mix(this,{ |
|
228 /** |
|
229 * Get the unique stamp for this StyleSheet instance |
|
230 * |
|
231 * @method getId |
|
232 * @return {Number} the static id |
|
233 */ |
|
234 getId : function () { return Y.stamp(node); }, |
|
235 |
|
236 /** |
|
237 * Enable all the rules in the sheet |
|
238 * |
|
239 * @method enable |
|
240 * @return {StyleSheet} |
|
241 * @chainable |
|
242 */ |
|
243 enable : function () { sheet.disabled = false; return this; }, |
|
244 |
|
245 /** |
|
246 * Disable all the rules in the sheet. Rules may be changed while the |
|
247 * StyleSheet is disabled. |
|
248 * |
|
249 * @method disable |
|
250 * @return {StyleSheet} |
|
251 * @chainable |
|
252 */ |
|
253 disable : function () { sheet.disabled = true; return this; }, |
|
254 |
|
255 /** |
|
256 * Returns false if the StyleSheet is disabled. Otherwise true. |
|
257 * |
|
258 * @method isEnabled |
|
259 * @return {Boolean} |
|
260 */ |
|
261 isEnabled : function () { return !sheet.disabled; }, |
|
262 |
|
263 /** |
|
264 * <p>Set style properties for a provided selector string. |
|
265 * If the selector includes commas, it will be split into individual |
|
266 * selectors and applied accordingly. If the selector string does not |
|
267 * have a corresponding rule in the sheet, it will be added.</p> |
|
268 * |
|
269 * <p>The object properties in the second parameter must be the JavaScript |
|
270 * names of style properties. E.g. fontSize rather than font-size.</p> |
|
271 * |
|
272 * <p>The float style property will be set by any of "float", |
|
273 * "styleFloat", or "cssFloat".</p> |
|
274 * |
|
275 * @method set |
|
276 * @param sel {String} the selector string to apply the changes to |
|
277 * @param css {Object} Object literal of style properties and new values |
|
278 * @return {StyleSheet} |
|
279 * @chainable |
|
280 */ |
|
281 set : function (sel,css) { |
|
282 var rule = cssRules[sel], |
|
283 multi = sel.split(/\s*,\s*/),i, |
|
284 idx; |
|
285 |
|
286 // IE's addRule doesn't support multiple comma delimited selectors |
|
287 if (multi.length > 1) { |
|
288 for (i = multi.length - 1; i >= 0; --i) { |
|
289 this.set(multi[i], css); |
|
290 } |
|
291 return this; |
|
292 } |
|
293 |
|
294 // Some selector values can cause IE to hang |
|
295 if (!StyleSheet.isValidSelector(sel)) { |
|
296 Y.log("Invalid selector '"+sel+"' passed to set (ignoring).",'error','StyleSheet'); |
|
297 return this; |
|
298 } |
|
299 |
|
300 // Opera throws an error if there's a syntax error in assigned |
|
301 // cssText. Avoid this using a worker style collection, then |
|
302 // assigning the resulting cssText. |
|
303 if (rule) { |
|
304 rule.style.cssText = StyleSheet.toCssText(css,rule.style.cssText); |
|
305 } else { |
|
306 idx = sheet[_rules].length; |
|
307 css = StyleSheet.toCssText(css); |
|
308 |
|
309 // IE throws an error when attempting to addRule(sel,'',n) |
|
310 // which would crop up if no, or only invalid values are used |
|
311 if (css) { |
|
312 _insertRule(sel, css, idx); |
|
313 |
|
314 // Safari replaces the rules collection, but maintains the |
|
315 // rule instances in the new collection when rules are |
|
316 // added/removed |
|
317 cssRules[sel] = sheet[_rules][idx]; |
|
318 } |
|
319 } |
|
320 return this; |
|
321 }, |
|
322 |
|
323 /** |
|
324 * <p>Unset style properties for a provided selector string, removing |
|
325 * their effect from the style cascade.</p> |
|
326 * |
|
327 * <p>If the selector includes commas, it will be split into individual |
|
328 * selectors and applied accordingly. If there are no properties |
|
329 * remaining in the rule after unsetting, the rule is removed.</p> |
|
330 * |
|
331 * <p>The style property or properties in the second parameter must be the |
|
332 * JavaScript style property names. E.g. fontSize rather than font-size.</p> |
|
333 * |
|
334 * <p>The float style property will be unset by any of "float", |
|
335 * "styleFloat", or "cssFloat".</p> |
|
336 * |
|
337 * @method unset |
|
338 * @param sel {String} the selector string to apply the changes to |
|
339 * @param css {String|Array} style property name or Array of names |
|
340 * @return {StyleSheet} |
|
341 * @chainable |
|
342 */ |
|
343 unset : function (sel,css) { |
|
344 var rule = cssRules[sel], |
|
345 multi = sel.split(/\s*,\s*/), |
|
346 remove = !css, |
|
347 rules, i; |
|
348 |
|
349 // IE's addRule doesn't support multiple comma delimited selectors |
|
350 // so rules are mapped internally by atomic selectors |
|
351 if (multi.length > 1) { |
|
352 for (i = multi.length - 1; i >= 0; --i) { |
|
353 this.unset(multi[i], css); |
|
354 } |
|
355 return this; |
|
356 } |
|
357 |
|
358 if (rule) { |
|
359 if (!remove) { |
|
360 css = Y.Array(css); |
|
361 |
|
362 workerStyle.cssText = rule.style.cssText; |
|
363 for (i = css.length - 1; i >= 0; --i) { |
|
364 _unsetProperty(workerStyle,css[i]); |
|
365 } |
|
366 |
|
367 if (workerStyle.cssText) { |
|
368 rule.style.cssText = workerStyle.cssText; |
|
369 } else { |
|
370 remove = true; |
|
371 } |
|
372 } |
|
373 |
|
374 if (remove) { // remove the rule altogether |
|
375 rules = sheet[_rules]; |
|
376 for (i = rules.length - 1; i >= 0; --i) { |
|
377 if (rules[i] === rule) { |
|
378 delete cssRules[sel]; |
|
379 _deleteRule(i); |
|
380 break; |
|
381 } |
|
382 } |
|
383 } |
|
384 } |
|
385 return this; |
|
386 }, |
|
387 |
|
388 /** |
|
389 * Get the current cssText for a rule or the entire sheet. If the |
|
390 * selector param is supplied, only the cssText for that rule will be |
|
391 * returned, if found. If the selector string targets multiple |
|
392 * selectors separated by commas, the cssText of the first rule only |
|
393 * will be returned. If no selector string, the stylesheet's full |
|
394 * cssText will be returned. |
|
395 * |
|
396 * @method getCssText |
|
397 * @param sel {String} Selector string |
|
398 * @return {String} |
|
399 */ |
|
400 getCssText : function (sel) { |
|
401 var rule,css; |
|
402 |
|
403 if (isString(sel)) { |
|
404 // IE's addRule doesn't support multiple comma delimited |
|
405 // selectors so rules are mapped internally by atomic selectors |
|
406 rule = cssRules[sel.split(/\s*,\s*/)[0]]; |
|
407 |
|
408 return rule ? rule.style.cssText : null; |
|
409 } else { |
|
410 css = []; |
|
411 for (sel in cssRules) { |
|
412 if (cssRules.hasOwnProperty(sel)) { |
|
413 rule = cssRules[sel]; |
|
414 css.push(rule.selectorText+" {"+rule.style.cssText+"}"); |
|
415 } |
|
416 } |
|
417 return css.join("\n"); |
|
418 } |
|
419 } |
|
420 }); |
|
421 |
|
422 } |
|
423 |
|
424 _toCssText = function (css,base) { |
|
425 var f = css.styleFloat || css.cssFloat || css[FLOAT], |
|
426 trim = Y.Lang.trim, |
|
427 prop; |
|
428 |
|
429 workerStyle.cssText = base || EMPTY; |
|
430 |
|
431 if (f && !css[floatAttr]) { |
|
432 css = Y.merge(css); |
|
433 delete css.styleFloat; delete css.cssFloat; delete css[FLOAT]; |
|
434 css[floatAttr] = f; |
|
435 } |
|
436 |
|
437 for (prop in css) { |
|
438 if (css.hasOwnProperty(prop)) { |
|
439 try { |
|
440 // IE throws Invalid Value errors and doesn't like whitespace |
|
441 // in values ala ' red' or 'red ' |
|
442 workerStyle[prop] = trim(css[prop]); |
|
443 } |
|
444 catch (e) { |
|
445 Y.log('Error assigning property "'+prop+'" to "'+css[prop]+ |
|
446 "\" (ignored):\n"+e.message,'warn','StyleSheet'); |
|
447 } |
|
448 } |
|
449 } |
|
450 return workerStyle.cssText; |
|
451 }; |
|
452 |
|
453 Y.mix(StyleSheet, { |
|
454 /** |
|
455 * <p>Converts an object literal of style properties and values into a string |
|
456 * of css text. This can then be assigned to el.style.cssText.</p> |
|
457 * |
|
458 * <p>The optional second parameter is a cssText string representing the |
|
459 * starting state of the style prior to alterations. This is most often |
|
460 * extracted from the eventual target's current el.style.cssText.</p> |
|
461 * |
|
462 * @method StyleSheet.toCssText |
|
463 * @param css {Object} object literal of style properties and values |
|
464 * @param cssText {String} (optional) starting cssText value |
|
465 * @return {String} the resulting cssText string |
|
466 * @static |
|
467 */ |
|
468 toCssText : ((OPACITY in workerStyle) ? _toCssText : |
|
469 // Wrap IE's toCssText to catch opacity. The copy/merge is to preserve |
|
470 // the input object's integrity, but if float and opacity are set, the |
|
471 // input will be copied twice in IE. Is there a way to avoid this |
|
472 // without increasing the byte count? |
|
473 function (css, cssText) { |
|
474 if (OPACITY in css) { |
|
475 css = Y.merge(css,{ |
|
476 filter: 'alpha(opacity='+(css.opacity*100)+')' |
|
477 }); |
|
478 delete css.opacity; |
|
479 } |
|
480 return _toCssText(css,cssText); |
|
481 }), |
|
482 |
|
483 /** |
|
484 * Registers a StyleSheet instance in the static registry by the given name |
|
485 * |
|
486 * @method StyleSheet.register |
|
487 * @param name {String} the name to assign the StyleSheet in the registry |
|
488 * @param sheet {StyleSheet} The StyleSheet instance |
|
489 * @return {Boolean} false if no name or sheet is not a StyleSheet |
|
490 * instance. true otherwise. |
|
491 * @static |
|
492 */ |
|
493 register : function (name,sheet) { |
|
494 return !!(name && sheet instanceof StyleSheet && |
|
495 !sheets[name] && (sheets[name] = sheet)); |
|
496 }, |
|
497 |
|
498 /** |
|
499 * <p>Determines if a selector string is safe to use. Used internally |
|
500 * in set to prevent IE from locking up when attempting to add a rule for a |
|
501 * "bad selector".</p> |
|
502 * |
|
503 * <p>Bad selectors are considered to be any string containing unescaped |
|
504 * `~!@$%^&()+=|{}[];'"?< or space. Also forbidden are . or # followed by |
|
505 * anything other than an alphanumeric. Additionally -abc or .-abc or |
|
506 * #_abc or '# ' all fail. There are likely more failure cases, so |
|
507 * please file a bug if you encounter one.</p> |
|
508 * |
|
509 * @method StyleSheet.isValidSelector |
|
510 * @param sel {String} the selector string |
|
511 * @return {Boolean} |
|
512 * @static |
|
513 */ |
|
514 isValidSelector : function (sel) { |
|
515 var valid = false; |
|
516 |
|
517 if (sel && isString(sel)) { |
|
518 |
|
519 if (!selectors.hasOwnProperty(sel)) { |
|
520 // TEST: there should be nothing but white-space left after |
|
521 // these destructive regexs |
|
522 selectors[sel] = !/\S/.test( |
|
523 // combinators |
|
524 sel.replace(/\s+|\s*[+~>]\s*/g,' '). |
|
525 // attribute selectors (contents not validated) |
|
526 replace(/([^ ])\[.*?\]/g,'$1'). |
|
527 // pseudo-class|element selectors (contents of parens |
|
528 // such as :nth-of-type(2) or :not(...) not validated) |
|
529 replace(/([^ ])::?[a-z][a-z\-]+[a-z](?:\(.*?\))?/ig,'$1'). |
|
530 // element tags |
|
531 replace(/(?:^| )[a-z0-6]+/ig,' '). |
|
532 // escaped characters |
|
533 replace(/\\./g,EMPTY). |
|
534 // class and id identifiers |
|
535 replace(/[.#]\w[\w\-]*/g,EMPTY)); |
|
536 } |
|
537 |
|
538 valid = selectors[sel]; |
|
539 } |
|
540 |
|
541 return valid; |
|
542 } |
|
543 },true); |
|
544 |
|
545 Y.StyleSheet = StyleSheet; |
|
546 |
|
547 /* |
|
548 |
|
549 NOTES |
|
550 * Style node must be added to the head element. Safari does not honor styles |
|
551 applied to StyleSheet objects on style nodes in the body. |
|
552 * StyleSheet object is created on the style node when the style node is added |
|
553 to the head element in Firefox 2 (and maybe 3?) |
|
554 * The cssRules collection is replaced after insertRule/deleteRule calls in |
|
555 Safari 3.1. Existing Rules are used in the new collection, so the collection |
|
556 cannot be cached, but the rules can be. |
|
557 * Opera requires that the index be passed with insertRule. |
|
558 * Same-domain restrictions prevent modifying StyleSheet objects attached to |
|
559 link elements with remote href (or "about:blank" or "javascript:false") |
|
560 * Same-domain restrictions prevent reading StyleSheet cssRules/rules |
|
561 collection of link elements with remote href (or "about:blank" or |
|
562 "javascript:false") |
|
563 * Same-domain restrictions result in Safari not populating node.sheet property |
|
564 for link elements with remote href (et.al) |
|
565 * IE names StyleSheet related properties and methods differently (see code) |
|
566 * IE converts tag names to upper case in the Rule's selectorText |
|
567 * IE converts empty string assignment to complex properties to value settings |
|
568 for all child properties. E.g. style.background = '' sets non-'' values on |
|
569 style.backgroundPosition, style.backgroundColor, etc. All else clear |
|
570 style.background and all child properties. |
|
571 * IE assignment style.filter = '' will result in style.cssText == 'FILTER:' |
|
572 * All browsers support Rule.style.cssText as a read/write property, leaving |
|
573 only opacity needing to be accounted for. |
|
574 * Benchmarks of style.property = value vs style.cssText += 'property: value' |
|
575 indicate cssText is slightly slower for single property assignment. For |
|
576 multiple property assignment, cssText speed stays relatively the same where |
|
577 style.property speed decreases linearly by the number of properties set. |
|
578 Exception being Opera 9.27, where style.property is always faster than |
|
579 style.cssText. |
|
580 * Opera 9.5b throws a syntax error when assigning cssText with a syntax error. |
|
581 * Opera 9.5 doesn't honor rule.style.cssText = ''. Previous style persists. |
|
582 You have to remove the rule altogether. |
|
583 * Stylesheet properties set with !important will trump inline style set on an |
|
584 element or in el.style.property. |
|
585 * Creating a worker style collection like document.createElement('p').style; |
|
586 will fail after a time in FF (~5secs of inactivity). Property assignments |
|
587 will not alter the property or cssText. It may be the generated node is |
|
588 garbage collected and the style collection becomes inert (speculation). |
|
589 * IE locks up when attempting to add a rule with a selector including at least |
|
590 characters {[]}~`!@%^&*()+=|? (unescaped) and leading _ or - |
|
591 such as addRule('-foo','{ color: red }') or addRule('._abc','{...}') |
|
592 * IE's addRule doesn't support comma separated selectors such as |
|
593 addRule('.foo, .bar','{..}') |
|
594 * IE throws an error on valid values with leading/trailing white space. |
|
595 * When creating an entire sheet at once, only FF2/3 & Opera allow creating a |
|
596 style node, setting its innerHTML and appending to head. |
|
597 * When creating an entire sheet at once, Safari requires the style node to be |
|
598 created with content in innerHTML of another element. |
|
599 * When creating an entire sheet at once, IE requires the style node content to |
|
600 be set via node.styleSheet.cssText |
|
601 * When creating an entire sheet at once in IE, styleSheet.cssText can't be |
|
602 written until node.type = 'text/css'; is performed. |
|
603 * When creating an entire sheet at once in IE, load-time fork on |
|
604 var styleNode = d.createElement('style'); _method = styleNode.styleSheet ?.. |
|
605 fails (falsey). During run-time, the test for .styleSheet works fine |
|
606 * Setting complex properties in cssText will SOMETIMES allow child properties |
|
607 to be unset |
|
608 set unset FF2 FF3 S3.1 IE6 IE7 Op9.27 Op9.5 |
|
609 ---------- ----------------- --- --- ---- --- --- ------ ----- |
|
610 border -top NO NO YES YES YES YES YES |
|
611 -top-color NO NO YES YES YES |
|
612 -color NO NO NO NO NO |
|
613 background -color NO NO YES YES YES |
|
614 -position NO NO YES YES YES |
|
615 -position-x NO NO NO NO NO |
|
616 font line-height YES YES NO NO NO NO YES |
|
617 -style YES YES NO YES YES |
|
618 -size YES YES NO YES YES |
|
619 -size-adjust ??? ??? n/a n/a n/a ??? ??? |
|
620 padding -top NO NO YES YES YES |
|
621 margin -top NO NO YES YES YES |
|
622 list-style -type YES YES YES YES YES |
|
623 -position YES YES YES YES YES |
|
624 overflow -x NO NO YES n/a YES |
|
625 |
|
626 ??? - unsetting font-size-adjust has the same effect as unsetting font-size |
|
627 * FireFox and WebKit populate rule.cssText as "SELECTOR { CSSTEXT }", but |
|
628 Opera and IE do not. |
|
629 * IE6 and IE7 silently ignore the { and } if passed into addRule('.foo','{ |
|
630 color:#000}',0). IE8 does not and creates an empty rule. |
|
631 * IE6-8 addRule('.foo','',n) throws an error. Must supply *some* cssText |
|
632 */ |
|
633 |
|
634 |
|
635 |
|
636 }, '3.0.0' ); |