9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke SmithYUI.add('stylesheet', function(Y) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith/**
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith * The StyleSheet component is a module for creating and modifying CSS
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith * stylesheets.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @module stylesheet
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smithvar d = Y.config.doc,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith p = d.createElement('p'), // Have to hold the node (see notes)
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith workerStyle = p.style, // worker style collection
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith isString = Y.Lang.isString,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith selectors = {},
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith sheets = {},
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith floatAttr = ('cssFloat' in workerStyle) ? 'cssFloat' : 'styleFloat',
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _toCssText,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _unsetOpacity,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith _unsetProperty,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith OPACITY = 'opacity',
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith FLOAT = 'float',
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith EMPTY = '';
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith// Normalizes the removal of an assigned style for opacity. IE uses the filter
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith// property.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith_unsetOpacity = (OPACITY in workerStyle) ?
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith function (style) { style.opacity = EMPTY; } :
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith function (style) { style.filter = EMPTY; };
0c9749c3ca70539e41104900fede9cbfa4328678Adam Moore
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith// Normalizes the removal of an assigned style for a given property. Expands
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith// shortcut properties if necessary and handles the various names for the float
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith// property.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke SmithworkerStyle.border = "1px solid red";
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke SmithworkerStyle.border = EMPTY; // IE doesn't unset child properties
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith_unsetProperty = workerStyle.borderLeft ?
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith function (style,prop) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith var p;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (prop !== floatAttr && prop.toLowerCase().indexOf(FLOAT) != -1) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith prop = floatAttr;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (isString(style[prop])) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith switch (prop) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith case OPACITY:
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith case 'filter' : _unsetOpacity(style); break;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith case 'font' :
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style.font = style.fontStyle = style.fontVariant =
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style.fontWeight = style.fontSize = style.lineHeight =
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith style.fontFamily = EMPTY;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith break;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith default :
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith for (p in style) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (p.indexOf(prop) === 0) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith style[p] = EMPTY;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith } :
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith function (style,prop) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (prop !== floatAttr && prop.toLowerCase().indexOf(FLOAT) != -1) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith prop = floatAttr;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (isString(style[prop])) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (prop === OPACITY) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _unsetOpacity(style);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith } else {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith style[prop] = EMPTY;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith };
0c9749c3ca70539e41104900fede9cbfa4328678Adam Moore
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith/**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Create an instance of StyleSheet to encapsulate a css stylesheet.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * The constructor can be called using function or constructor syntax.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <pre><code>var sheet = Y.StyleSheet(..);</pre></code>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * or
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <pre><code>var sheet = new Y.StyleSheet(..);</pre></code>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * The first parameter passed can be any of the following things:
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <ul>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>The desired string name to register a new empty sheet</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>The string name of an existing StyleSheet instance</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>The unique guid generated for an existing StyleSheet instance</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>The id of an existing <code>&lt;link&gt;</code> or <code>&lt;style&gt;</code> node</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>The node reference for an existing <code>&lt;link&gt;</code> or <code>&lt;style&gt;</code> node</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>The Y.Node instance wrapping an existing <code>&lt;link&gt;</code> or <code>&lt;style&gt;</code> node</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <li>A chunk of css text to create a new stylesheet from</li>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * </ul>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>If a string is passed, StyleSheet will first look in its static name
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * registry for an existing sheet, then in the DOM for an element with that id.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * If neither are found and the string contains the { character, it will be
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * used as a the initial cssText for a new StyleSheet. Otherwise, a new empty
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * StyleSheet is created, assigned the string value as a name, and registered
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * statically by that name.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>The optional second parameter is a string name to register the sheet as.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * This param is largely useful when providing a node id/ref or chunk of css
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * text to create a populated instance.</p>
0c9749c3ca70539e41104900fede9cbfa4328678Adam Moore *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @class StyleSheet
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @constructor
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param seed {String|HTMLElement|Node} a style or link node, its id, or a
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * name or guid of a StyleSheet, or a string of css text
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @param name {String} (optional) name to register instance for future static
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * access
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smithfunction StyleSheet(seed, name) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith var head,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith node,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith sheet,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith cssRules = {},
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _rules,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _insertRule,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith _deleteRule,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith i,r,sel;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // Factory or constructor
0c9749c3ca70539e41104900fede9cbfa4328678Adam Moore if (!(Y.instanceOf(this, StyleSheet))) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return new StyleSheet(seed,name);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Extract the DOM node from Node instances
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (seed) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (Y.Node && seed instanceof Y.Node) {
9c3b58447f02e078df9a578dacf1363da9f43758Luke Smith node = seed._node;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith } else if (seed.nodeName) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith node = seed;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // capture the DOM node if the string is an id
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith } else if (isString(seed)) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (seed && sheets[seed]) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return sheets[seed];
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith node = d.getElementById(seed.replace(/^#/,EMPTY));
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Check for the StyleSheet in the static registry
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (node && sheets[Y.stamp(node)]) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return sheets[Y.stamp(node)];
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Create a style node if necessary
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith if (!node || !/^(?:style|link)$/i.test(node.nodeName)) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith node = d.createElement('style');
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith node.type = 'text/css';
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (isString(seed)) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // Create entire sheet from seed cssText
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith if (seed.indexOf('{') != -1) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // Not a load-time fork because low run-time impact and IE fails
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // test for s.styleSheet at page load time (oddly)
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith if (node.styleSheet) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith node.styleSheet.cssText = seed;
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith } else {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith node.appendChild(d.createTextNode(seed));
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith } else if (!name) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith name = seed;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Make sure the node is attached to the appropriate head element
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (!node.parentNode || node.parentNode.nodeName.toLowerCase() !== 'head') {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith head = (node.ownerDocument || d).getElementsByTagName('head')[0];
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // styleSheet isn't available on the style node in FF2 until appended
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // to the head element. style nodes appended to body do not affect
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // change in Safari.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith head.appendChild(node);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Begin setting up private aliases to the important moving parts
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // 1. The stylesheet object
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // IE stores StyleSheet under the "styleSheet" property
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Safari doesn't populate sheet for xdomain link elements
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith sheet = node.sheet || node.styleSheet;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // 2. The style rules collection
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // IE stores the rules collection under the "rules" property
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith _rules = sheet && ('cssRules' in sheet) ? 'cssRules' : 'rules';
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // 3. The method to remove a rule from the stylesheet
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // IE supports removeRule
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _deleteRule = ('deleteRule' in sheet) ?
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith function (i) { sheet.deleteRule(i); } :
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith function (i) { sheet.removeRule(i); };
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // 4. The method to add a new rule to the stylesheet
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // IE supports addRule with different signature
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _insertRule = ('insertRule' in sheet) ?
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith function (sel,css,i) { sheet.insertRule(sel+' {'+css+'}',i); } :
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith function (sel,css,i) { sheet.addRule(sel,css,i); };
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // 5. Initialize the cssRules map from the node
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // xdomain link nodes forbid access to the cssRules collection, so this
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // will throw an error.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // TODO: research alternate stylesheet, @media
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith for (i = sheet[_rules].length - 1; i >= 0; --i) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith r = sheet[_rules][i];
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith sel = r.selectorText;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (cssRules[sel]) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith cssRules[sel].style.cssText += ';' + r.style.cssText;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _deleteRule(i);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith } else {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith cssRules[sel] = r;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Cache the instance by the generated Id
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith StyleSheet.register(Y.stamp(node),this);
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Register the instance by name if provided or defaulted from seed
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (name) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith StyleSheet.register(name,this);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith // Public API
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith Y.mix(this,{
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Get the unique stamp for this StyleSheet instance
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method getId
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @return {Number} the static id
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith getId : function () { return Y.stamp(node); },
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Enable all the rules in the sheet
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method enable
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @return {StyleSheet}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @chainable
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith enable : function () { sheet.disabled = false; return this; },
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Disable all the rules in the sheet. Rules may be changed while the
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * StyleSheet is disabled.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method disable
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @return {StyleSheet}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @chainable
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith disable : function () { sheet.disabled = true; return this; },
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith * Returns false if the StyleSheet is disabled. Otherwise true.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method isEnabled
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @return {Boolean}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith isEnabled : function () { return !sheet.disabled; },
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>Set style properties for a provided selector string.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * If the selector includes commas, it will be split into individual
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * selectors and applied accordingly. If the selector string does not
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * have a corresponding rule in the sheet, it will be added.</p>
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>The object properties in the second parameter must be the JavaScript
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * names of style properties. E.g. fontSize rather than font-size.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>The float style property will be set by any of &quot;float&quot;,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * &quot;styleFloat&quot;, or &quot;cssFloat&quot;.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method set
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param sel {String} the selector string to apply the changes to
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param css {Object} Object literal of style properties and new values
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @return {StyleSheet}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @chainable
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith */
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith set : function (sel,css) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith var rule = cssRules[sel],
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith multi = sel.split(/\s*,\s*/),i,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith idx;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // IE's addRule doesn't support multiple comma delimited selectors
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith if (multi.length > 1) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith for (i = multi.length - 1; i >= 0; --i) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith this.set(multi[i], css);
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith return this;
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // Some selector values can cause IE to hang
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith if (!StyleSheet.isValidSelector(sel)) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith Y.log("Invalid selector '"+sel+"' passed to set (ignoring).",'error','StyleSheet');
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith return this;
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // Opera throws an error if there's a syntax error in assigned
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // cssText. Avoid this using a worker style collection, then
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith // assigning the resulting cssText.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (rule) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith rule.style.cssText = StyleSheet.toCssText(css,rule.style.cssText);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith } else {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith idx = sheet[_rules].length;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith css = StyleSheet.toCssText(css);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // IE throws an error when attempting to addRule(sel,'',n)
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // which would crop up if no, or only invalid values are used
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (css) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith _insertRule(sel, css, idx);
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Safari replaces the rules collection, but maintains the
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // rule instances in the new collection when rules are
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // added/removed
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith cssRules[sel] = sheet[_rules][idx];
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith return this;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith },
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>Unset style properties for a provided selector string, removing
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * their effect from the style cascade.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>If the selector includes commas, it will be split into individual
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * selectors and applied accordingly. If there are no properties
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * remaining in the rule after unsetting, the rule is removed.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>The style property or properties in the second parameter must be the
93388caa22c79f6102627197c1a7c95f3503a0d6Luke Smith * JavaScript style property names. E.g. fontSize rather than font-size.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>The float style property will be unset by any of &quot;float&quot;,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * &quot;styleFloat&quot;, or &quot;cssFloat&quot;.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method unset
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param sel {String} the selector string to apply the changes to
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param css {String|Array} style property name or Array of names
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @return {StyleSheet}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @chainable
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith unset : function (sel,css) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith var rule = cssRules[sel],
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith multi = sel.split(/\s*,\s*/),
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith remove = !css,
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith rules, i;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // IE's addRule doesn't support multiple comma delimited selectors
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // so rules are mapped internally by atomic selectors
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (multi.length > 1) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith for (i = multi.length - 1; i >= 0; --i) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith this.unset(multi[i], css);
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return this;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (rule) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (!remove) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith css = Y.Array(css);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith workerStyle.cssText = rule.style.cssText;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith for (i = css.length - 1; i >= 0; --i) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith _unsetProperty(workerStyle,css[i]);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (workerStyle.cssText) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith rule.style.cssText = workerStyle.cssText;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith } else {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith remove = true;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
0c9749c3ca70539e41104900fede9cbfa4328678Adam Moore
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (remove) { // remove the rule altogether
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith rules = sheet[_rules];
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith for (i = rules.length - 1; i >= 0; --i) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (rules[i] === rule) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith delete cssRules[sel];
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith _deleteRule(i);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith break;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith return this;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith },
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Get the current cssText for a rule or the entire sheet. If the
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * selector param is supplied, only the cssText for that rule will be
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * returned, if found. If the selector string targets multiple
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * selectors separated by commas, the cssText of the first rule only
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * will be returned. If no selector string, the stylesheet's full
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * cssText will be returned.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @method getCssText
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param sel {String} Selector string
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @return {String}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith getCssText : function (sel) {
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith var rule, css, selector;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (isString(sel)) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // IE's addRule doesn't support multiple comma delimited
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // selectors so rules are mapped internally by atomic selectors
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith rule = cssRules[sel.split(/\s*,\s*/)[0]];
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return rule ? rule.style.cssText : null;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith } else {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith css = [];
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith for (selector in cssRules) {
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith if (cssRules.hasOwnProperty(selector)) {
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith rule = cssRules[selector];
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith css.push(rule.selectorText+" {"+rule.style.cssText+"}");
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return css.join("\n");
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith });
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith}
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith_toCssText = function (css,base) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith var f = css.styleFloat || css.cssFloat || css[FLOAT],
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith trim = Y.Lang.trim,
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith prop;
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith // A very difficult to repro/isolate IE 9 beta (and Platform Preview 7) bug
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith // was reduced to this line throwing the error:
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith // "Invalid this pointer used as target for method call"
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith // It appears that the style collection is corrupted. The error is
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith // catchable, so in a best effort to work around it, replace the
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith // p and workerStyle and try the assignment again.
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith try {
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith workerStyle.cssText = base || EMPTY;
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith } catch (e) {
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith Y.log("Worker style collection corrupted. Replacing.", "warn", "StyleSheet");
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith p = d.createElement('p');
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith workerStyle = p.style;
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith workerStyle.cssText = base || EMPTY;
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (f && !css[floatAttr]) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith css = Y.merge(css);
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith delete css.styleFloat; delete css.cssFloat; delete css[FLOAT];
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith css[floatAttr] = f;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith for (prop in css) {
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith if (css.hasOwnProperty(prop)) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith try {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // IE throws Invalid Value errors and doesn't like whitespace
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // in values ala ' red' or 'red '
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith workerStyle[prop] = trim(css[prop]);
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith catch (ex) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith Y.log('Error assigning property "'+prop+'" to "'+css[prop]+
fb79432117c7c5808d478bda90dfce5f819cb3fbLuke Smith "\" (ignored):\n"+ex.message,'warn','StyleSheet');
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return workerStyle.cssText;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith};
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke SmithY.mix(StyleSheet, {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>Converts an object literal of style properties and values into a string
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * of css text. This can then be assigned to el.style.cssText.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>The optional second parameter is a cssText string representing the
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * starting state of the style prior to alterations. This is most often
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * extracted from the eventual target's current el.style.cssText.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @method toCssText
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param css {Object} object literal of style properties and values
95349902f8b51ea8c984383a3ef8e5825341b10eLuke Smith * @param cssText {String} (optional) starting cssText value
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @return {String} the resulting cssText string
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @static
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith toCssText : ((OPACITY in workerStyle) ? _toCssText :
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // Wrap IE's toCssText to catch opacity. The copy/merge is to preserve
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // the input object's integrity, but if float and opacity are set, the
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // input will be copied twice in IE. Is there a way to avoid this
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // without increasing the byte count?
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith function (css, cssText) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (OPACITY in css) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith css = Y.merge(css,{
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith filter: 'alpha(opacity='+(css.opacity*100)+')'
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith });
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith delete css.opacity;
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith return _toCssText(css,cssText);
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }),
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Registers a StyleSheet instance in the static registry by the given name
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @method register
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param name {String} the name to assign the StyleSheet in the registry
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param sheet {StyleSheet} The StyleSheet instance
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @return {Boolean} false if no name or sheet is not a StyleSheet
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * instance. true otherwise.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @static
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith register : function (name,sheet) {
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith return !!(name && sheet instanceof StyleSheet &&
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith !sheets[name] && (sheets[name] = sheet));
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith },
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith /**
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>Determines if a selector string is safe to use. Used internally
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * in set to prevent IE from locking up when attempting to add a rule for a
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * &quot;bad selector&quot;.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * <p>Bad selectors are considered to be any string containing unescaped
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * `~!@$%^&()+=|{}[];'"?< or space. Also forbidden are . or # followed by
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * anything other than an alphanumeric. Additionally -abc or .-abc or
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * #_abc or '# ' all fail. There are likely more failure cases, so
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * please file a bug if you encounter one.</p>
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith *
10d8bafc5c24f3a4285cf6060a1935ba5cfc4b85Luke Smith * @method isValidSelector
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @param sel {String} the selector string
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @return {Boolean}
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * @static
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith */
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith isValidSelector : function (sel) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith var valid = false;
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (sel && isString(sel)) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith if (!selectors.hasOwnProperty(sel)) {
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // TEST: there should be nothing but white-space left after
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // these destructive regexs
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith selectors[sel] = !/\S/.test(
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // combinators
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith sel.replace(/\s+|\s*[+~>]\s*/g,' ').
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // attribute selectors (contents not validated)
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith replace(/([^ ])\[.*?\]/g,'$1').
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // pseudo-class|element selectors (contents of parens
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // such as :nth-of-type(2) or :not(...) not validated)
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith replace(/([^ ])::?[a-z][a-z\-]+[a-z](?:\(.*?\))?/ig,'$1').
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // element tags
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith replace(/(?:^| )[a-z0-6]+/ig,' ').
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // escaped characters
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith replace(/\\./g,EMPTY).
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith // class and id identifiers
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith replace(/[.#]\w[\w\-]*/g,EMPTY));
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith valid = selectors[sel];
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith return valid;
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith }
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith},true);
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
00f5227c72bff2a1b314aff7ee1829c303e74462Luke SmithY.StyleSheet = StyleSheet;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith/*
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke SmithNOTES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Style node must be added to the head element. Safari does not honor styles
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith applied to StyleSheet objects on style nodes in the body.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * StyleSheet object is created on the style node when the style node is added
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith to the head element in Firefox 2 (and maybe 3?)
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * The cssRules collection is replaced after insertRule/deleteRule calls in
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith Safari 3.1. Existing Rules are used in the new collection, so the collection
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith cannot be cached, but the rules can be.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Opera requires that the index be passed with insertRule.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Same-domain restrictions prevent modifying StyleSheet objects attached to
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith link elements with remote href (or "about:blank" or "javascript:false")
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Same-domain restrictions prevent reading StyleSheet cssRules/rules
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith collection of link elements with remote href (or "about:blank" or
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith "javascript:false")
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * Same-domain restrictions result in Safari not populating node.sheet property
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith for link elements with remote href (et.al)
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * IE names StyleSheet related properties and methods differently (see code)
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * IE converts tag names to upper case in the Rule's selectorText
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * IE converts empty string assignment to complex properties to value settings
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith for all child properties. E.g. style.background = '' sets non-'' values on
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style.backgroundPosition, style.backgroundColor, etc. All else clear
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style.background and all child properties.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * IE assignment style.filter = '' will result in style.cssText == 'FILTER:'
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * All browsers support Rule.style.cssText as a read/write property, leaving
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith only opacity needing to be accounted for.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Benchmarks of style.property = value vs style.cssText += 'property: value'
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith indicate cssText is slightly slower for single property assignment. For
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith multiple property assignment, cssText speed stays relatively the same where
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style.property speed decreases linearly by the number of properties set.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith Exception being Opera 9.27, where style.property is always faster than
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style.cssText.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Opera 9.5b throws a syntax error when assigning cssText with a syntax error.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Opera 9.5 doesn't honor rule.style.cssText = ''. Previous style persists.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith You have to remove the rule altogether.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Stylesheet properties set with !important will trump inline style set on an
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith element or in el.style.property.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Creating a worker style collection like document.createElement('p').style;
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith will fail after a time in FF (~5secs of inactivity). Property assignments
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith will not alter the property or cssText. It may be the generated node is
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith garbage collected and the style collection becomes inert (speculation).
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith * IE locks up when attempting to add a rule with a selector including at least
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith characters {[]}~`!@%^&*()+=|? (unescaped) and leading _ or -
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith such as addRule('-foo','{ color: red }') or addRule('._abc','{...}')
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith * IE's addRule doesn't support comma separated selectors such as
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith addRule('.foo, .bar','{..}')
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith * IE throws an error on valid values with leading/trailing white space.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * When creating an entire sheet at once, only FF2/3 & Opera allow creating a
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith style node, setting its innerHTML and appending to head.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * When creating an entire sheet at once, Safari requires the style node to be
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith created with content in innerHTML of another element.
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * When creating an entire sheet at once, IE requires the style node content to
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith be set via node.styleSheet.cssText
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * When creating an entire sheet at once in IE, styleSheet.cssText can't be
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith written until node.type = 'text/css'; is performed.
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith * When creating an entire sheet at once in IE, load-time fork on
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith var styleNode = d.createElement('style'); _method = styleNode.styleSheet ?..
00f5227c72bff2a1b314aff7ee1829c303e74462Luke Smith fails (falsey). During run-time, the test for .styleSheet works fine
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith * Setting complex properties in cssText will SOMETIMES allow child properties
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith to be unset
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith set unset FF2 FF3 S3.1 IE6 IE7 Op9.27 Op9.5
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith ---------- ----------------- --- --- ---- --- --- ------ -----
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith border -top NO NO YES YES YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -top-color NO NO YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -color NO NO NO NO NO
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith background -color NO NO YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -position NO NO YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -position-x NO NO NO NO NO
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith font line-height YES YES NO NO NO NO YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -style YES YES NO YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -size YES YES NO YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -size-adjust ??? ??? n/a n/a n/a ??? ???
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith padding -top NO NO YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith margin -top NO NO YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith list-style -type YES YES YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith -position YES YES YES YES YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith overflow -x NO NO YES n/a YES
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith ??? - unsetting font-size-adjust has the same effect as unsetting font-size
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * FireFox and WebKit populate rule.cssText as "SELECTOR { CSSTEXT }", but
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith Opera and IE do not.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * IE6 and IE7 silently ignore the { and } if passed into addRule('.foo','{
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith color:#000}',0). IE8 does not and creates an empty rule.
ddbbe6cfe718a63c7931e5847bf76dfe7c0942f3Luke Smith * IE6-8 addRule('.foo','',n) throws an error. Must supply *some* cssText
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith*/
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
9706f76f9e56f413801eb2ff719cfbb6bdd3e841Luke Smith
b0ab788daf32aca249320825ecbdcef36aa0c052Dav Glass}, '@VERSION@' ,{requires:['yui-base']});