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.
204 lines
7.6 KiB
204 lines
7.6 KiB
/**
|
|
* This file is part of the jps-like-websites lib
|
|
* URL: https://git.labos.goip.de/chris/jpc-like-websites
|
|
* @copyright by its creator Christian Martin
|
|
*/
|
|
|
|
/**
|
|
* @abstract
|
|
* Class adds function and style storing properties to the context (PageBuilder).
|
|
*/
|
|
class ScriptAndStyleContext {
|
|
/**
|
|
* @property {Map<string, Map<string, string>>} #css
|
|
* @type {Map<string, Map<string, string>>} #css
|
|
*/
|
|
#css;
|
|
/**
|
|
* @property {Map<string, FunctionStoreBuffer>} #functions
|
|
* @type {Map<string, FunctionStoreBuffer>} #functions
|
|
*/
|
|
#functions;
|
|
|
|
constructor() {
|
|
this.#functions = new Map();
|
|
this.#css = new Map();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} nameAddition text that will be added to the end of the generated name
|
|
* @returns a name for a function (e.g. for storing)
|
|
*/
|
|
getFunctionName(nameAddition = "") {
|
|
return `func${this.#functions.size}${nameAddition}`;
|
|
}
|
|
|
|
/**
|
|
* Registers a function to be added later in a script tag in the head of the document.
|
|
* @ATTENTION Be careful with intended empty strings (e.g. in variable values),
|
|
* empty strings within the function code will be shrunk.
|
|
*
|
|
* @param {Function} fun The function that will be registered
|
|
* @param {string} underTheName (alternative) name for the registration of the function,
|
|
* if none the name of the function will be used, if that is missing a name will be generated.
|
|
* @param {OverwriteBehaviour} overwriteBehaviour defines what to do,
|
|
* if the registration name already exists (default: OverwriteBehaviour.RENAME - adds a nr to the name)
|
|
* @returns {string} the name under witch the function is registered (and therefore can be called from)
|
|
*/
|
|
registerPageFunction(fun, underTheName = '', overwriteBehaviour = OverwriteBehaviour.RENAME) {
|
|
|
|
/* Find name-root */
|
|
let registrationName = [
|
|
underTheName.trim(),
|
|
fun.name.trim(),
|
|
this.getFunctionName()
|
|
].find(e => e !== '');
|
|
|
|
/* deal with name already present */
|
|
let functionNames = this.#functions.keys;
|
|
if (functionNames.includes(registrationName)) {
|
|
registrationName = resolveOverwrite(registrationName, this.#functions, overwriteBehaviour);
|
|
}
|
|
|
|
/* clear function text */
|
|
let clearedFuncText = clearFunctionDeclarationText(fun);
|
|
|
|
this.#functions.set(registrationName, new FunctionStoreBuffer(clearedFuncText));
|
|
|
|
return registrationName;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* @experimental Attention is adviced, registration mechanism doesn't work yet
|
|
* @param {Function} fun The function that is supposed to be executed repeatedly
|
|
* @param {number} interval the time in ms between executions
|
|
* @param {string} underTheName the name the interval will be tied to
|
|
* @param {OverwriteBehaviour} overwriteBehaviour defines what to do,
|
|
* if the registration name already exists (default: OverwriteBehaviour.RENAME - adds a nr to the name)
|
|
*/
|
|
registerRepeatingFunction(fun, interval, underTheName = '', overwriteBehaviour = OverwriteBehaviour.RENAME, args = []) {
|
|
let registrationName = this.registerPageFunction(fun, underTheName, overwriteBehaviour);
|
|
let fsb = this.#functions.get(registrationName);
|
|
fsb.repeats = true;
|
|
fsb.interval = interval;
|
|
fsb.args = args;
|
|
return registrationName;
|
|
}
|
|
|
|
|
|
/**
|
|
* Registeres a function to be executed after page-load
|
|
* @param {Function} func the function that will be executed
|
|
* @param {number} delay the time in ms the execution is delayed after load
|
|
* @param {string} name if provided the function will be registered as well
|
|
* @param {Array<any>} args arguments for the function
|
|
* @param {boolean} repeat defines if the function is supposed to be repeated as well
|
|
* @param {number} interval if the function is supposed to repeat, this defines the interval of repetition
|
|
*/
|
|
executeAfterLoad(fun, delay = 1000, underTheName = '', overwriteBehaviour = OverwriteBehaviour.RENAME, interval = -1, args = []) {
|
|
let registrationName = this.registerPageFunction(fun, underTheName, overwriteBehaviour);
|
|
let fsb = this.#functions.get(registrationName);
|
|
|
|
fsb.execAfterStart = true;
|
|
fsb.delay = delay;
|
|
fsb.args = args;
|
|
|
|
if (interval > 0) {
|
|
fsb.repeats = true;
|
|
fsb.interval = interval;
|
|
}
|
|
|
|
return registrationName;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} nameAddition text that will be added to the end of the generated name
|
|
* @returns a name for a styling (e.g. for storing)
|
|
*/
|
|
getStyleName(nameAddition = "") {
|
|
return `styling${this.#css.size}${nameAddition}`;
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds the styling rules to the element identifiers into the style tag.
|
|
* An element definition can only be used once, repeated use will be ignored.
|
|
*
|
|
* @todo implement extStore logic
|
|
*
|
|
* @param {string} elementIdentifier The element identifier
|
|
* @param {map<string, string>|Modifier} styleRuleMap The Styling rules/values
|
|
*/
|
|
registerStyling(elementIdentifier, styleRuleMap) {
|
|
if (styleRuleMap instanceof Modifier) {
|
|
styleRuleMap = styleRuleMap._modifications;
|
|
}
|
|
|
|
if (!this.#css.has(elementIdentifier)) {
|
|
this.#css.set(elementIdentifier, styleRuleMap);
|
|
}
|
|
return elementIdentifier;
|
|
}
|
|
|
|
/**
|
|
* Adds into the (head) document.
|
|
* - script tag
|
|
* - function tag(s)
|
|
* - sets and registers repeatedly executed functions
|
|
* - sets (timeout and) functions that are supposed to be executed after load
|
|
* @class ScriptAndStyleContext
|
|
*/
|
|
generate() {
|
|
let head = document.querySelector('head');
|
|
|
|
/* generate style tag and fill it with stored stylings */
|
|
let styleTag = document.createElement('style');
|
|
|
|
for (const tuple of this.#css.entries()) {
|
|
styleTag.innerText += `${tuple[0]} {${Object.entries(tuple[1])
|
|
.map(style => style[0] + ": " + style[1] + "; ")
|
|
.join(" ")
|
|
}} `;
|
|
}
|
|
|
|
head.appendChild(styleTag);
|
|
|
|
/*
|
|
generate script tag(s) and fill it with stored functions
|
|
for now there will be 3 script tags, so interval, execAfterStart and normal functions are sepperated.
|
|
*/
|
|
|
|
let containersTag = document.createElement('script');
|
|
containersTag.setAttribute("data-compel-mech-script", "main");
|
|
containersTag.innerText = 'const delayed = {}; ';
|
|
containersTag.innerText += 'const repeated = {}; ';
|
|
head.appendChild(containersTag);
|
|
|
|
if (this.#functions.size > 0) {
|
|
let funcTag = document.createElement('script');
|
|
for (const tuple of this.#functions.entries) {
|
|
let regName = tuple[0];
|
|
let fsb = tuple[1];
|
|
funcTag.innerText += getScriptTagInjectionText(fsb.func, regName);
|
|
|
|
if (fsb.repeats && !fsb.execAfterStart) {
|
|
repeated[regName] = setInterval(regName, fsb.interval, fsb.args);
|
|
}
|
|
|
|
if (!fsb.repeats && fsb.execAfterStart) {
|
|
delayed[regName] = setTimeout(regName, fsb.interval, fsb.args);
|
|
}
|
|
|
|
if (fsb.repeats && fsb.execAfterStart) {
|
|
repeated[regName] = setInterval(regName, fsb.interval, fsb.args);
|
|
delayed[regName] = setTimeout(repeated[regName], fsb.delay, fsb.args);
|
|
}
|
|
}
|
|
head.appendChild(funcTag);
|
|
}
|
|
}
|
|
}
|
|
|