Skip to content

Instantly share code, notes, and snippets.

@paceaux
Last active October 29, 2020 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paceaux/144a977fa8beed3de4fab2d7c3f7f0f4 to your computer and use it in GitHub Desktop.
Save paceaux/144a977fa8beed3de4fab2d7c3f7f0f4 to your computer and use it in GitHub Desktop.
JSCSS, The quick and easy way to do CSS in the DOM
/**
* 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