Fix #6913 - add more documentation to code
[roojs1] / Roo / util / CSS.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11
12  
13 /**
14  * @class Roo.util.CSS
15  * Utility class for manipulating CSS rules
16  * @static
17
18  */
19 Roo.util.CSS = function(){
20         var rules = null;
21         var doc = document;
22
23     var camelRe = /(-[a-z])/gi;
24     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
25
26    return {
27    /**
28     * Very simple dynamic creation of stylesheets from a text blob of rules.  The text will wrapped in a style
29     * tag and appended to the HEAD of the document.
30     * @param {String|Object} cssText The text containing the css rules
31     * @param {String} id An id to add to the stylesheet for later removal
32     * @return {StyleSheet}
33     */
34     createStyleSheet : function(cssText, id){
35         var ss;
36         var head = doc.getElementsByTagName("head")[0];
37         var nrules = doc.createElement("style");
38         nrules.setAttribute("type", "text/css");
39         if(id){
40             nrules.setAttribute("id", id);
41         }
42         if (typeof(cssText) != 'string') {
43             // support object maps..
44             // not sure if this a good idea.. 
45             // perhaps it should be merged with the general css handling
46             // and handle js style props.
47             var cssTextNew = [];
48             for(var n in cssText) {
49                 var citems = [];
50                 for(var k in cssText[n]) {
51                     citems.push( k + ' : ' +cssText[n][k] + ';' );
52                 }
53                 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
54                 
55             }
56             cssText = cssTextNew.join("\n");
57             
58         }
59        
60        
61        if(Roo.isIE){
62            head.appendChild(nrules);
63            ss = nrules.styleSheet;
64            ss.cssText = cssText;
65        }else{
66            try{
67                 nrules.appendChild(doc.createTextNode(cssText));
68            }catch(e){
69                nrules.cssText = cssText; 
70            }
71            head.appendChild(nrules);
72            ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
73        }
74        this.cacheStyleSheet(ss);
75        return ss;
76    },
77
78    /**
79     * Removes a style or link tag by id
80     * @param {String} id The id of the tag
81     */
82    removeStyleSheet : function(id){
83        var existing = doc.getElementById(id);
84        if(existing){
85            existing.parentNode.removeChild(existing);
86        }
87    },
88
89    /**
90     * Dynamically swaps an existing stylesheet reference for a new one
91     * @param {String} id The id of an existing link tag to remove
92     * @param {String} url The href of the new stylesheet to include
93     */
94    swapStyleSheet : function(id, url){
95        this.removeStyleSheet(id);
96        var ss = doc.createElement("link");
97        ss.setAttribute("rel", "stylesheet");
98        ss.setAttribute("type", "text/css");
99        ss.setAttribute("id", id);
100        ss.setAttribute("href", url);
101        doc.getElementsByTagName("head")[0].appendChild(ss);
102    },
103    
104    /**
105     * Refresh the rule cache if you have dynamically added stylesheets
106     * @return {Object} An object (hash) of rules indexed by selector
107     */
108    refreshCache : function(){
109        return this.getRules(true);
110    },
111
112    // private
113    cacheStyleSheet : function(stylesheet){
114        if(!rules){
115            rules = {};
116        }
117        try{// try catch for cross domain access issue
118            var ssRules = stylesheet.cssRules || stylesheet.rules;
119            for(var j = ssRules.length-1; j >= 0; --j){
120                rules[ssRules[j].selectorText] = ssRules[j];
121            }
122        }catch(e){}
123    },
124    
125    /**
126     * Gets all css rules for the document
127     * @param {Boolean} refreshCache true to refresh the internal cache
128     * @return {Object} An object (hash) of rules indexed by selector
129     */
130    getRules : function(refreshCache){
131                 if(rules == null || refreshCache){
132                         rules = {};
133                         var ds = doc.styleSheets;
134                         for(var i =0, len = ds.length; i < len; i++){
135                             try{
136                         this.cacheStyleSheet(ds[i]);
137                     }catch(e){} 
138                 }
139                 }
140                 return rules;
141         },
142         
143         /**
144     * Gets an an individual CSS rule by selector(s)
145     * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
146     * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
147     * @return {CSSRule} The CSS rule or null if one is not found
148     */
149    getRule : function(selector, refreshCache){
150                 var rs = this.getRules(refreshCache);
151                 if(!(selector instanceof Array)){
152                     return rs[selector];
153                 }
154                 for(var i = 0; i < selector.length; i++){
155                         if(rs[selector[i]]){
156                                 return rs[selector[i]];
157                         }
158                 }
159                 return null;
160         },
161         
162         
163         /**
164     * Updates a rule property
165     * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
166     * @param {String} property The css property
167     * @param {String} value The new value for the property
168     * @return {Boolean} true If a rule was found and updated
169     */
170    updateRule : function(selector, property, value){
171                 if(!(selector instanceof Array)){
172                         var rule = this.getRule(selector);
173                         if(rule){
174                                 rule.style[property.replace(camelRe, camelFn)] = value;
175                                 return true;
176                         }
177                 }else{
178                         for(var i = 0; i < selector.length; i++){
179                                 if(this.updateRule(selector[i], property, value)){
180                                         return true;
181                                 }
182                         }
183                 }
184                 return false;
185         }
186    };   
187 }();