Last active
October 29, 2020 16:25
-
-
Save paceaux/144a977fa8beed3de4fab2d7c3f7f0f4 to your computer and use it in GitHub Desktop.
JSCSS, The quick and easy way to do CSS in the DOM
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
/** | |
* Class for adding CSS with JavaScript that relies on the CSSOM | |
*/ | |
class JSCSS { | |
/** | |
* @param {string} cssText Text for a stylesheet. Rulesets, queries, and all | |
*/ | |
constructor(cssText = '') { | |
const sheet = JSCSS.addStyleSheet(); | |
this.stylesheet = JSCSS.getStyleSheet(sheet.title); | |
JSCSS.insertRules(sheet, cssText); | |
} | |
/** adds CSS text to a stylesheet | |
* @param {CSSStyleSheet} sheet the CSSStyleSheet on to which the rules will be added | |
* @param {string} rules plain text CSS rules | |
* | |
* @static | |
*/ | |
static insertRules(sheet, rules) { | |
const rulesArray = rules.split('}'); | |
rulesArray.forEach((rule)=>{ | |
if (rule.indexOf('{') !== -1) sheet.insertRule(rule, 0); | |
}); | |
}; | |
/** Adds a single CSS rule to the stylesheet | |
* @param {string} rule valid CSS rule | |
* @param {number} insertLocation position in the stylesheet to insert the rule | |
* | |
* @method | |
*/ | |
insertRule(rule, insertLocation=0) { | |
this.stylesheet.insertRule(rule, insertLocation); | |
} | |
/** | |
* adds many CSS rules to the stylesheet | |
* @param {string} cssRules | |
*/ | |
insertRules(cssRules) { | |
JSCSS.insertRules(this.stylesheet, cssRules); | |
} | |
/** Finds a rule in any CSSRuleList by the selector | |
* @param {CSSRuleList} rules the rules to search | |
* @param {string} selector, a valid CSS Selector to search by | |
* @param {boolean} isFuzzy=false use to indicate a partial match | |
*/ | |
static findBySelector(rules, selector, isFuzzy = false) { | |
if (!rules || !selector) return null; | |
let results = []; | |
for (let rule of rules) { | |
if (isFuzzy && rule.selectorText.search(selector) !== -1) { | |
results.push(rule); | |
} | |
if (!isFuzzy && rule.selectorText === selector) { | |
results.push(rule); | |
} | |
} | |
return results; | |
}; | |
/** finds a rule in the stylesheet's rules by selector. | |
* @param {string} selector valid CSS selector | |
* @param {boolean} isFuzzy=false indicates a partial match | |
* | |
* @method | |
*/ | |
findBySelector(selector, isFuzzy = false) { | |
return JSCSS.findBySelector(this.stylesheet.rules, selector, isFuzzy); | |
} | |
/** Gets a stylesheet by title. | |
* @param {string} title | |
* @returns {CSSStyleSheet} | |
* @static | |
*/ | |
static getStyleSheet (title) { | |
if (!title) return | |
let styleSheet; | |
for (var i = 0; i < document.styleSheets.length; i++) { | |
if (document.styleSheets[i].title === title) styleSheet = document.styleSheets[i]; | |
} | |
return styleSheet; | |
}; | |
/** Creates a new stylesheet and appends to the <head> | |
* @param {string} title=`jscss-${Date.now()}` a unique name for the stylesheet | |
* @returns {CSSStyleSheet} | |
* @static | |
*/ | |
static addStyleSheet(title = `jscss-${Date.now()}`) { | |
const styleSheet = document.createElement('style'); | |
styleSheet.title = title; | |
document.head.append(styleSheet); | |
const CSSStyleSheet = JSCSS.getStyleSheet(title); | |
return CSSStyleSheet; | |
} | |
/** Removes a stylesheet from the DOM | |
* @param {string} title stylesheet to remove from the dom | |
* @returns {CSSStyleSheet} | |
* | |
* @static | |
*/ | |
static removeStyleSheet(title) { | |
if (!title) return; | |
let sheetNode; | |
for (let styleSheet in document.styleSheets) { | |
if (document.styleSheets[styleSheet].title && document.styleSheets[styleSheet].title === title) { | |
sheetNode = document.styleSheets[styleSheet].ownerNode; | |
sheetNode.remove(sheetNode); | |
} | |
} | |
return sheetNode; | |
} | |
/** Removes the stylesheet from the dom | |
* @returns {CSSStyleSheet} | |
*/ | |
remove() { | |
return JSCSS.removeStyleSheet(this.stylesheet.title); | |
} | |
/** Sets ONE stylesheet to be the main, all others to be alternates | |
* @param {string} title | |
* @returns {CSSStyleSheet} | |
*/ | |
static preferStyleSheet(title) { | |
if (!title) return; | |
for (let styleSheet in document.styleSheets) { | |
if (document.styleSheets[styleSheet].title && !document.styleSheets.title === title) { | |
document.styleSheets[styleSheet].rel = document.styleSheets[styleSheet].rel + ' alternate'; | |
} | |
if (document.styleSheets[styleSheet].title === title) { | |
return styleSheet; | |
} | |
} | |
} | |
/** | |
* Sets the stylesheet to be preferred | |
* | |
* @method | |
*/ | |
prefer() { | |
return JSCSS.preferStyleSheet(this.stylesheet.title); | |
} | |
/** the reverse of preferStyleSheet. Removes the "alternate" status from all stylesheets | |
* @param {string} title unique name of the stylesheet | |
* | |
* @method | |
*/ | |
static unPreferStyleSheet (title) { | |
if (!title) return; | |
for (let styleSheet in document.styleSheets) { | |
if (document.styleSheets[styleSheet].rel && !document.styleSheets.rel.indexOf('alternate')!== -1 ) { | |
document.styleSheets[styleSheet].rel.replace(' alternate', ''); | |
} | |
} | |
} | |
/** | |
* reverse of prefer. Removes the "alternate" status from the stylesheet | |
* | |
* @method | |
*/ | |
unprefer() { | |
return JSCSS.unPreferStyleSheet(this.stylesheet.title); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment