80 lines
2.5 KiB
JavaScript
80 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
/* eslint-env browser */
|
|
|
|
/** @namespace cssInjector */
|
|
|
|
/**
|
|
* @summary Insert base stylesheet into DOM
|
|
*
|
|
* @desc Creates a new `<style>...</style>` element from the named text string(s) and inserts it but only if it does not already exist in the specified container as per `referenceElement`.
|
|
*
|
|
* > Caveat: If stylesheet is for use in a shadow DOM, you must specify a local `referenceElement`.
|
|
*
|
|
* @returns A reference to the newly created `<style>...</style>` element.
|
|
*
|
|
* @param {string|string[]} cssRules
|
|
* @param {string} [ID]
|
|
* @param {undefined|null|Element|string} [referenceElement] - Container for insertion. Overloads:
|
|
* * `undefined` type (or omitted): injects stylesheet at top of `<head>...</head>` element
|
|
* * `null` value: injects stylesheet at bottom of `<head>...</head>` element
|
|
* * `Element` type: injects stylesheet immediately before given element, wherever it is found.
|
|
* * `string` type: injects stylesheet immediately before given first element found that matches the given css selector.
|
|
*
|
|
* @memberOf cssInjector
|
|
*/
|
|
function cssInjector(cssRules, ID, referenceElement) {
|
|
if (typeof referenceElement === 'string') {
|
|
referenceElement = document.querySelector(referenceElement);
|
|
if (!referenceElement) {
|
|
throw 'Cannot find reference element for CSS injection.';
|
|
}
|
|
} else if (referenceElement && !(referenceElement instanceof Element)) {
|
|
throw 'Given value not a reference element.';
|
|
}
|
|
|
|
var container = referenceElement && referenceElement.parentNode || document.head || document.getElementsByTagName('head')[0];
|
|
|
|
if (ID) {
|
|
ID = cssInjector.idPrefix + ID;
|
|
|
|
if (container.querySelector('#' + ID)) {
|
|
return; // stylesheet already in DOM
|
|
}
|
|
}
|
|
|
|
var style = document.createElement('style');
|
|
style.type = 'text/css';
|
|
if (ID) {
|
|
style.id = ID;
|
|
}
|
|
if (cssRules instanceof Array) {
|
|
cssRules = cssRules.join('\n');
|
|
}
|
|
cssRules = '\n' + cssRules + '\n';
|
|
if (style.styleSheet) {
|
|
style.styleSheet.cssText = cssRules;
|
|
} else {
|
|
style.appendChild(document.createTextNode(cssRules));
|
|
}
|
|
|
|
if (referenceElement === undefined) {
|
|
referenceElement = container.firstChild;
|
|
}
|
|
|
|
container.insertBefore(style, referenceElement);
|
|
|
|
return style;
|
|
}
|
|
|
|
/**
|
|
* @summary Optional prefix for `<style>` tag IDs.
|
|
* @desc Defaults to `'injected-stylesheet-'`.
|
|
* @type {string}
|
|
* @memberOf cssInjector
|
|
*/
|
|
cssInjector.idPrefix = 'injected-stylesheet-';
|
|
|
|
// Interface
|
|
module.exports = cssInjector;
|