Last active
December 3, 2019 09:28
-
-
Save Sjeiti/11355844 to your computer and use it in GitHub Desktop.
Javascript to manipulate existing stylesheets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Manipulate existing stylesheets. | |
* @name rootStyle | |
*/ | |
window.rootStyle = (function() { | |
'use strict'; | |
// StyleSheet.addRule shim | |
if (document.styleSheets[0].addRule===undefined) { | |
window.StyleSheet.prototype.addRule = function(selector,value){ | |
return this.insertRule(selector + '{' + value + '}', this.cssRules.length); | |
}; | |
} | |
var forEach = Array.prototype.forEach | |
,aoStyleSheets = document.styleSheets | |
,bReversedSelectors = (function(){ | |
// creates a new selector and checks if the rule comes out in reverse | |
var oSheet = aoStyleSheets[0] | |
,aRules = oSheet.cssRules | |
,iNumRules = aRules.length | |
,sSelector = 'span#a.c.d.b' | |
,sSelectorResult | |
,bIsReversed | |
; | |
oSheet.addRule(sSelector, 'font-weight:inherit'); | |
sSelectorResult = aRules[iNumRules].selectorText; | |
bIsReversed = sSelectorResult!=sSelector; | |
oSheet.deleteRule(iNumRules); | |
return bIsReversed; | |
})() | |
; | |
/** | |
* Reverses a selector (because IE rearanges selectors) | |
* Turns span#a.c.d.b into span.b.c.d#a | |
* @param {String} selector | |
* @returns {String} Reversed selector | |
*/ | |
function getReverse(selector){ | |
var oSheet = aoStyleSheets[0] | |
,aRules = oSheet.cssRules | |
,iNumRules = aRules.length | |
,sSelectorResult | |
; | |
oSheet.addRule(selector, 'font-weight:inherit'); | |
sSelectorResult = aRules[iNumRules].selectorText; | |
oSheet.deleteRule(iNumRules); | |
return sSelectorResult; | |
} | |
/** | |
* Get an array of CSSStyleRules for the selector string. | |
* @param {String} selector | |
* @returns {iddqd.style.rule} | |
*/ | |
function select(selector){ | |
selector = bReversedSelectors?getReverse(parseSelector(selector)):parseSelector(selector); | |
var aStyles = rule(); | |
forEach.apply(aoStyleSheets,[function(styleSheet){ | |
var aRules = styleSheet.cssRules; | |
aRules && forEach.apply(aRules,[function (oRule) { | |
if (oRule.constructor===window.CSSStyleRule) { | |
if (oRule.selectorText.split(' {').shift()==selector) { | |
aStyles.push(oRule); | |
} | |
} | |
}]); | |
}]); | |
return aStyles; | |
} | |
/** | |
* Parse a selector string correctly | |
* @param {string} selector | |
* @returns {string} | |
*/ | |
function parseSelector(selector) { | |
return selector.replace('>',' > ').replace(' ',' '); | |
} | |
/** | |
* Change an existing selector with the rules parsed in the object. | |
* @param {String} selector | |
* @param {Object} rules | |
* @returns {CSSStyleRule[]} The Array created by select | |
*/ | |
function changeRule(selector,rules) { | |
return select(selector).set(rules); | |
} | |
/** | |
* Adds a new rule to the selector | |
* @param selector | |
* @param rules | |
* @returns {CssRule} | |
*/ | |
function addRule(selector,rules) { | |
var oSheet,sRules = ''; | |
iddqd.loop(rules,function(prop,val){sRules+=prop+':'+val+';';}); | |
oSheet = aoStyleSheets[0]; | |
oSheet.addRule(selector,sRules); | |
return oSheet.cssRules[oSheet.cssRules.length-1]; | |
} | |
/** | |
* A array of CSSStyleRules enhanced with some methods. | |
* @returns {CSSStyleRule[]} | |
*/ | |
function rule() { | |
var aStyles = []; | |
aStyles.set = function (key,prop) { | |
if (typeof key==='string') { | |
set.apply(aStyles,[key,prop]); | |
} else { | |
for (var s in key) { | |
set.apply(aStyles,[s,key[s]]); | |
} | |
} | |
}; | |
function set(key,prop) { | |
aStyles.forEach(function (rule) { | |
var oStyle = rule.style; | |
oStyle.removeProperty(key); | |
oStyle[key] = prop; | |
}); | |
} | |
return aStyles; | |
} | |
// Expose private methods | |
return { | |
toString: function(){return '[object rootStyle]';} | |
,select: select | |
,changeRule: changeRule | |
,addRule: addRule | |
}; | |
})(); |
Changing existing prototypes is generally considered bad practice.
Plus these days spreading also makes it a little easier to read and write: [...styleSheets].forEach(styleSheet=>{})
probably... [...styleSheets].forEach(styleSheet=>{}) is easier to write even if a little less compatible...
perhaps Array.prototype.forEach.apply(document.styleSheets,[(ss)=>ss.ownerNode.parentNode.removeChild(ss.ownerNode)]);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think it's easier to write:
StyleSheetList.prototype.forEach=Array.prototype.forEach
and then
document.styleSheets.forEach(console.log)