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