209 lines
6.3 KiB
JavaScript
209 lines
6.3 KiB
JavaScript
/**
|
|
* @class YAHOO.ext.util.CSS
|
|
* Class for manipulating CSS Rules
|
|
* @singleton
|
|
*/
|
|
YAHOO.ext.util.CSS = new function(){
|
|
var rules = null;
|
|
|
|
var toCamel = function(property) {
|
|
var convert = function(prop) {
|
|
var test = /(-[a-z])/i.exec(prop);
|
|
return prop.replace(RegExp.$1, RegExp.$1.substr(1).toUpperCase());
|
|
};
|
|
while(property.indexOf('-') > -1) {
|
|
property = convert(property);
|
|
}
|
|
return property;
|
|
};
|
|
|
|
/**
|
|
* Very simple dynamic creation of stylesheets from a text blob of rules.
|
|
* @param {String} cssText The text containing the css rules
|
|
* @return {StyleSheet}
|
|
*/
|
|
this.createStyleSheet = function(cssText){
|
|
var ss;
|
|
if(YAHOO.ext.util.Browser.isIE){
|
|
ss = document.createStyleSheet();
|
|
ss.cssText = cssText;
|
|
}else{
|
|
var head = document.getElementsByTagName("head")[0];
|
|
var rules = document.createElement('style');
|
|
rules.setAttribute('type', 'text/css');
|
|
try{
|
|
rules.appendChild(document.createTextNode(cssText));
|
|
}catch(e){
|
|
rules.cssText = cssText;
|
|
}
|
|
head.appendChild(rules);
|
|
ss = document.styleSheets[document.styleSheets.length-1];
|
|
}
|
|
this.cacheStyleSheet(ss);
|
|
return ss;
|
|
};
|
|
|
|
this.removeStyleSheet = function(id){
|
|
var existing = document.getElementById(id);
|
|
if(existing){
|
|
existing.parentNode.removeChild(existing);
|
|
}
|
|
};
|
|
|
|
this.swapStyleSheet = function(id, url){
|
|
this.removeStyleSheet(id);
|
|
var ss = document.createElement('link');
|
|
ss.setAttribute('rel', 'stylesheet');
|
|
ss.setAttribute('type', 'text/css');
|
|
ss.setAttribute('id', id);
|
|
ss.setAttribute('href', url);
|
|
document.getElementsByTagName("head")[0].appendChild(ss);
|
|
};
|
|
|
|
/**
|
|
* Refresh the rule cache if you have dynamically added stylesheets
|
|
* @return {Object} An object (hash) of rules indexed by selector
|
|
*/
|
|
this.refreshCache = function(){
|
|
return this.getRules(true);
|
|
};
|
|
|
|
this.cacheStyleSheet = function(ss){
|
|
try{// try catch for cross domain access issue
|
|
var ssRules = ss.cssRules || ss.rules;
|
|
for(var j = ssRules.length-1; j >= 0; --j){
|
|
rules[ssRules[j].selectorText] = ssRules[j];
|
|
}
|
|
}catch(e){}
|
|
};
|
|
|
|
/**
|
|
* Gets all css rules for the document
|
|
* @param {Boolean} refreshCache true to refresh the internal cache
|
|
* @return {Object} An object (hash) of rules indexed by selector
|
|
*/
|
|
this.getRules = function(refreshCache){
|
|
if(rules == null || refreshCache){
|
|
rules = {};
|
|
var ds = document.styleSheets;
|
|
for(var i =0, len = ds.length; i < len; i++){
|
|
try{
|
|
this.cacheStyleSheet(ds[i]);
|
|
}catch(e){}
|
|
}
|
|
}
|
|
return rules;
|
|
};
|
|
|
|
/**
|
|
* Gets an an individual CSS rule by selector(s)
|
|
* @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
|
|
* @param {Boolean} refreshCache true to refresh the internal cache
|
|
* @return {CSSRule} The CSS rule or null if one is not found
|
|
*/
|
|
this.getRule = function(selector, refreshCache){
|
|
var rs = this.getRules(refreshCache);
|
|
if(!(selector instanceof Array)){
|
|
return rs[selector];
|
|
}
|
|
for(var i = 0; i < selector.length; i++){
|
|
if(rs[selector[i]]){
|
|
return rs[selector[i]];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
|
|
/**
|
|
* Updates a rule property
|
|
* @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
|
|
* @param {String} property The css property
|
|
* @param {String} value The new value for the property
|
|
* @return {Boolean} true if a rule was found and updated
|
|
*/
|
|
this.updateRule = function(selector, property, value){
|
|
if(!(selector instanceof Array)){
|
|
var rule = this.getRule(selector);
|
|
if(rule){
|
|
rule.style[toCamel(property)] = value;
|
|
return true;
|
|
}
|
|
}else{
|
|
for(var i = 0; i < selector.length; i++){
|
|
if(this.updateRule(selector[i], property, value)){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Applies a rule to an element without adding the class
|
|
* @param {HTMLElement} el The element
|
|
* @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
|
|
* @return {Boolean} true if a rule was found and applied
|
|
*/
|
|
this.apply = function(el, selector){
|
|
if(!(selector instanceof Array)){
|
|
var rule = this.getRule(selector);
|
|
if(rule){
|
|
var s = rule.style;
|
|
for(var key in s){
|
|
if(typeof s[key] != 'function'){
|
|
if(s[key] && String(s[key]).indexOf(':') < 0 && s[key] != 'false'){
|
|
try{el.style[key] = s[key];}catch(e){}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}else{
|
|
for(var i = 0; i < selector.length; i++){
|
|
if(this.apply(el, selector[i])){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
this.applyFirst = function(el, id, selector){
|
|
var selectors = [
|
|
'#' + id + ' ' + selector,
|
|
selector
|
|
];
|
|
return this.apply(el, selectors);
|
|
};
|
|
|
|
this.revert = function(el, selector){
|
|
if(!(selector instanceof Array)){
|
|
var rule = this.getRule(selector);
|
|
if(rule){
|
|
for(key in rule.style){
|
|
if(rule.style[key] && String(rule.style[key]).indexOf(':') < 0 && rule.style[key] != 'false'){
|
|
try{el.style[key] = '';}catch(e){}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}else{
|
|
for(var i = 0; i < selector.length; i++){
|
|
if(this.revert(el, selector[i])){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
this.revertFirst = function(el, id, selector){
|
|
var selectors = [
|
|
'#' + id + ' ' + selector,
|
|
selector
|
|
];
|
|
return this.revert(el, selectors);
|
|
};
|
|
}();
|