telegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchat
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.
276 lines
9.7 KiB
276 lines
9.7 KiB
9 years ago
|
/**
|
||
|
* 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];
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
});
|