windowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinux
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
9.7 KiB
275 lines
9.7 KiB
/** |
|
* Utility class for manipulating CSS rules |
|
* @singleton |
|
*/ |
|
Ext.define('Ext.util.CSS', function() { |
|
var CSS, |
|
rules = null, |
|
doc = document, |
|
camelRe = /(-[a-z])/gi, |
|
camelFn = function(m, a){ return a.charAt(1).toUpperCase(); }; |
|
|
|
return { |
|
|
|
singleton: true, |
|
|
|
rules: rules, |
|
|
|
initialized: false, |
|
|
|
/** |
|
* @private |
|
*/ |
|
constructor: function() { |
|
// Cache a reference to the singleton |
|
CSS = this; |
|
}, |
|
|
|
/** |
|
* Creates a stylesheet from a text blob of rules. |
|
* These rules will be wrapped in a STYLE tag and appended to the HEAD of the document. |
|
* @param {String} cssText The text containing the css rules |
|
* @param {String} id An id to add to the stylesheet for later removal |
|
* @return {CSSStyleSheet} |
|
*/ |
|
createStyleSheet: function (cssText, id) { |
|
var ss, |
|
head = doc.getElementsByTagName('head')[0], |
|
styleEl = doc.createElement('style'); |
|
|
|
styleEl.setAttribute('type', 'text/css'); |
|
|
|
if (id) { |
|
styleEl.setAttribute('id', id); |
|
} |
|
|
|
// Feature detect old IE |
|
ss = styleEl.styleSheet; |
|
if (ss) { |
|
head.appendChild(styleEl); |
|
ss.cssText = cssText; |
|
} else { |
|
styleEl.appendChild(doc.createTextNode(cssText)); |
|
head.appendChild(styleEl); |
|
ss = styleEl.sheet; |
|
} |
|
|
|
CSS.cacheStyleSheet(ss); |
|
return ss; |
|
}, |
|
|
|
/** |
|
* Removes a style or link tag by id |
|
* @param {String} id The id of the tag |
|
*/ |
|
removeStyleSheet : function(id) { |
|
var existing = doc.getElementById(id); |
|
if (existing) { |
|
existing.parentNode.removeChild(existing); |
|
} |
|
}, |
|
|
|
/** |
|
* Dynamically swaps an existing stylesheet reference for a new one |
|
* @param {String} id The id of an existing link tag to remove |
|
* @param {String} url The href of the new stylesheet to include |
|
*/ |
|
swapStyleSheet : function(id, url) { |
|
var ss; |
|
CSS.removeStyleSheet(id); |
|
ss = doc.createElement("link"); |
|
ss.setAttribute("rel", "stylesheet"); |
|
ss.setAttribute("type", "text/css"); |
|
ss.setAttribute("id", id); |
|
ss.setAttribute("href", url); |
|
doc.getElementsByTagName("head")[0].appendChild(ss); |
|
}, |
|
|
|
// @private |
|
cacheStyleSheet : function(ss) { |
|
if (!rules) { |
|
rules = CSS.rules = {}; |
|
} |
|
try {// try catch for cross domain access issue |
|
var ssRules = ss.cssRules || ss.rules, |
|
i = ssRules.length - 1, |
|
imports = ss.imports, |
|
len = imports ? imports.length : 0, |
|
rule, j; |
|
|
|
// Old IE has a different way of handling imports |
|
for (j = 0; j < len; ++j) { |
|
CSS.cacheStyleSheet(imports[j]); |
|
} |
|
|
|
for (; i >= 0; --i) { |
|
rule = ssRules[i]; |
|
// If it's an @import rule, import its stylesheet |
|
if (rule.styleSheet) { |
|
CSS.cacheStyleSheet(rule.styleSheet); |
|
} |
|
CSS.cacheRule(rule, ss); |
|
} |
|
} catch(e) {} |
|
}, |
|
|
|
cacheRule: function(cssRule, styleSheet) { |
|
// If it's an @import rule, import its stylesheet |
|
if (cssRule.styleSheet) { |
|
return CSS.cacheStyleSheet(cssRule.styleSheet); |
|
} |
|
|
|
var selectorText = cssRule.selectorText, |
|
selectorCount, j; |
|
|
|
if (selectorText) { |
|
|
|
// Split in case there are multiple, comma-delimited selectors |
|
selectorText = selectorText.split(','); |
|
selectorCount = selectorText.length; |
|
for (j = 0; j < selectorCount; j++) { |
|
// IE<8 does not keep a reference to parentStyleSheet in the rule, so we |
|
// must cache an object like this until IE<8 is deprecated. |
|
rules[Ext.String.trim(selectorText[j]).toLowerCase()] = { |
|
parentStyleSheet: styleSheet, |
|
cssRule: cssRule |
|
}; |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* 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 |
|
*/ |
|
getRules : function(refreshCache) { |
|
var result = {}, |
|
selector; |
|
|
|
if (rules === null || refreshCache) { |
|
CSS.refreshCache(); |
|
} |
|
for (selector in rules) { |
|
result[selector] = rules[selector].cssRule; |
|
} |
|
return result; |
|
}, |
|
|
|
/** |
|
* Refresh the rule cache if you have dynamically added stylesheets |
|
* @return {Object} An object (hash) of rules indexed by selector |
|
*/ |
|
refreshCache: function() { |
|
var ds = doc.styleSheets, |
|
i = 0, |
|
len = ds.length; |
|
|
|
rules = CSS.rules = {}; |
|
for (; i < len; i++) { |
|
try { |
|
if (!ds[i].disabled) { |
|
CSS.cacheStyleSheet(ds[i]); |
|
} |
|
} catch(e) {} |
|
} |
|
}, |
|
|
|
/** |
|
* Gets an an individual CSS rule by selector(s) |
|
* @param {String/String[]} 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 if you have recently updated any rules or added styles dynamically |
|
* @return {CSSStyleRule} The CSS rule or null if one is not found |
|
*/ |
|
getRule: function(selector, refreshCache, rawCache) { |
|
var i, result; |
|
|
|
if (!rules || refreshCache) { |
|
CSS.refreshCache(); |
|
} |
|
if (!Ext.isArray(selector)) { |
|
result = rules[selector.toLowerCase()]; |
|
if (result && !rawCache) { |
|
result = result.cssRule; |
|
} |
|
return result || null; |
|
} |
|
for (i = 0; i < selector.length; i++) { |
|
if (rules[selector[i]]) { |
|
return rawCache ? rules[selector[i].toLowerCase()] : rules[selector[i].toLowerCase()].cssRule; |
|
} |
|
} |
|
return null; |
|
}, |
|
|
|
/** |
|
* Creates a rule. |
|
* @param {CSSStyleSheet} styleSheet The StyleSheet to create the rule in as returned from {@link #createStyleSheet}. |
|
* @param {String} selector The selector to target the rule. |
|
* @param {String} property The cssText specification eg `"color:red;font-weight:bold;text-decoration:underline"` |
|
* @return {CSSStyleRule} The created rule |
|
*/ |
|
createRule: function(styleSheet, selector, cssText) { |
|
var result, |
|
ruleSet = styleSheet.cssRules || styleSheet.rules, |
|
index = ruleSet.length; |
|
|
|
if (styleSheet.insertRule) { |
|
styleSheet.insertRule(selector + ' {' + cssText + '}', index); |
|
} else { |
|
styleSheet.addRule(selector, cssText||' '); |
|
} |
|
CSS.cacheRule(result = ruleSet[index], styleSheet); |
|
return result; |
|
}, |
|
|
|
/** |
|
* Updates a rule property |
|
* @param {String/String[]} 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 or a cssText specification eg `"color:red;font-weight:bold;text-decoration:underline"` |
|
* @param {String} value The new value for the property |
|
* @return {Boolean} true If a rule was found and updated |
|
*/ |
|
updateRule : function(selector, property, value) { |
|
var rule, i, styles; |
|
if (!Ext.isArray(selector)) { |
|
rule = CSS.getRule(selector); |
|
if (rule) { |
|
// 2 arg form means cssText sent, so parse it and update each style |
|
if (arguments.length === 2) { |
|
styles = Ext.Element.parseStyles(property); |
|
for (property in styles) { |
|
rule.style[property.replace(camelRe, camelFn)] = styles[property]; |
|
} |
|
} else { |
|
rule.style[property.replace(camelRe, camelFn)] = value; |
|
} |
|
return true; |
|
} |
|
} else { |
|
for (i = 0; i < selector.length; i++) { |
|
if (CSS.updateRule(selector[i], property, value)) { |
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
}, |
|
|
|
deleteRule: function(selector) { |
|
var rule = CSS.getRule(selector, false, true), |
|
styleSheet, index; |
|
|
|
if (rule) { |
|
styleSheet = rule.parentStyleSheet; |
|
index = Ext.Array.indexOf(styleSheet.cssRules || styleSheet.rules, rule.cssRule); |
|
if (styleSheet.deleteRule) { |
|
styleSheet.deleteRule(index); |
|
} else { |
|
styleSheet.removeRule(index); |
|
} |
|
delete rules[selector]; |
|
} |
|
} |
|
}; |
|
});
|
|
|