|
|
@ -8,394 +8,134 @@ |
|
|
|
* @abstract |
|
|
|
* @extends ModifiableComponent |
|
|
|
*/ |
|
|
|
class StyleStoringComponent extends ModifiableComponent { |
|
|
|
class StyleAndScriptStoringComponent extends ModifiableComponent { |
|
|
|
/** |
|
|
|
* @property {boolean} _styleStoreInternal |
|
|
|
* @type {ExtStore} |
|
|
|
*/ |
|
|
|
_styleStoreInternal; |
|
|
|
_styleClassesExtStore |
|
|
|
/** |
|
|
|
* The style-rule collection of this component |
|
|
|
* @property {map<string,map<string,string>>} css |
|
|
|
*/ |
|
|
|
#css; |
|
|
|
|
|
|
|
* @type {ExtStore} |
|
|
|
*/ |
|
|
|
_stylesExtStore; |
|
|
|
/** |
|
|
|
* @property {ExtStorageType} cssExtStore |
|
|
|
* @type {Array<SStoreDefinition>} |
|
|
|
*/ |
|
|
|
_cssExtStore; |
|
|
|
|
|
|
|
_styles; |
|
|
|
/** |
|
|
|
* @property {HTMLStyleElement} styleTag |
|
|
|
*/ |
|
|
|
#styleTag; |
|
|
|
* @type {ExtStore} |
|
|
|
*/ |
|
|
|
_functionsExtStore; |
|
|
|
/** |
|
|
|
* @type {Array<SStoreDefinition>} |
|
|
|
*/ |
|
|
|
_functions; |
|
|
|
|
|
|
|
constructor(element, attr = {}) { |
|
|
|
super(element, attr); |
|
|
|
this.#css = {}; |
|
|
|
this._styleStoreInternal = true; |
|
|
|
this._cssExtStore = ExtStorageType.CENTRALIZED; |
|
|
|
this.#css = {}; |
|
|
|
this.addStyleClass(this._compName); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Ads class to classList via HTMLElement.classList.add() method. |
|
|
|
* Further collects rules in a property until generate is called. |
|
|
|
* @override |
|
|
|
* @param {string} styleClass |
|
|
|
* @param {Modifier} modifier |
|
|
|
* @param {OverwriteBehaviour} overwriteBehaviour |
|
|
|
* @returns {Componant} this component object |
|
|
|
*/ |
|
|
|
addStyleClass(styleClass, modifier = null, overwriteBehaviour = OverwriteBehaviour.REPLACE) { |
|
|
|
this._element.classList.add(styleClass); |
|
|
|
this._styleClassesExtStore = new ExtStorage( |
|
|
|
ExtStoreType.CENTRALIZED_DOC_HEAD, |
|
|
|
OverwriteBehaviour.REPLACE |
|
|
|
); |
|
|
|
|
|
|
|
let selector = '.' + styleClass; |
|
|
|
this._stylesExtStore = new ExtStorage( |
|
|
|
ExtStoreType.INTERNALIZED_WITHIN, |
|
|
|
OverwriteBehaviour.REPLACE |
|
|
|
); |
|
|
|
|
|
|
|
if (Object.keys(this.#css).includes(selector)) { |
|
|
|
selector = resolveOverwrite(selector, this.#css); |
|
|
|
} |
|
|
|
this._styles = []; |
|
|
|
|
|
|
|
this.#css[selector] = (modifier |
|
|
|
? (modifier instanceof Modifier |
|
|
|
? modifier._modifications |
|
|
|
: modifier |
|
|
|
) |
|
|
|
: {} |
|
|
|
this._functionsExtStore = new ExtStorage( |
|
|
|
ExtStoreType.CENTRALIZED_DOC_HEAD, |
|
|
|
OverwriteBehaviour.REPLACE |
|
|
|
); |
|
|
|
|
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param {boolean} storeInternal |
|
|
|
* @returns {Component} |
|
|
|
*/ |
|
|
|
setStylingsStorage(storeInternal) { |
|
|
|
if (storeInternal) { |
|
|
|
this._styleStoreInternal = storeInternal; |
|
|
|
} |
|
|
|
return this; |
|
|
|
this._functions = []; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Defines/Sets the general "storage-behaviour" for styling of this component. |
|
|
|
* Further for potential css definitions. |
|
|
|
* If a styling/modifier/class is passed via the corresponding methods/way, |
|
|
|
* an alternative behaviour can be passed as a parameter - which will only be applied on/for that single one. |
|
|
|
* |
|
|
|
* @param {ExtStorageType} storageType |
|
|
|
* @param {ExtStorage|ExtStoreType|OverwriteBehaviour} extStore |
|
|
|
* @returns {Component} |
|
|
|
*/ |
|
|
|
setCssStorage(storageType) { |
|
|
|
if (storageType) { |
|
|
|
this._cssExtStore = storageType; |
|
|
|
} |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Takes all "collected" styling rules associated to a selector (in #css) |
|
|
|
* and inserts them as innerText to a created HTMLStyleElement. |
|
|
|
* @returns {HTMLStyleElement} |
|
|
|
*/ |
|
|
|
_generateStyleTag() { |
|
|
|
return Object.keys(this.#css) |
|
|
|
.reduce((styleTag, selector) => { |
|
|
|
let styleRules = this.#css[selector]; |
|
|
|
let rulesText = Object.keys(styleRules) |
|
|
|
.map(key => `${key}:${styleRules[key]}; `) |
|
|
|
.join(' '); |
|
|
|
|
|
|
|
styleTag.innerText += `${selector} {${rulesText}} `; |
|
|
|
return styleTag; |
|
|
|
|
|
|
|
}, document.createElement('style')); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* @override |
|
|
|
* @param {StyleStoringComponent|Component|ChainableModifier} component |
|
|
|
*/ |
|
|
|
_appendChildComponent(component) { |
|
|
|
if (!(component instanceof Component)) { |
|
|
|
component = component.toComponent(); |
|
|
|
} |
|
|
|
let wenity = component.generate(); |
|
|
|
|
|
|
|
if (Object.hasOwn(wenity, "css") & wenity.css) { |
|
|
|
if (wenity.css instanceof HTMLStyleElement) { |
|
|
|
this.#styleTag = wenity.css; |
|
|
|
setStylingsStorage(extStore) { |
|
|
|
if (extStore) { |
|
|
|
if (extStore instanceof ExtStorage) { |
|
|
|
this._stylesExtStore = extStore; |
|
|
|
} else if (extStore instanceof ExtStoreType) { |
|
|
|
this._stylesExtStore.setExtStoreType(extStore); |
|
|
|
} else { |
|
|
|
Object.entries(wenity.css) |
|
|
|
.forEach(kv => { |
|
|
|
this.#css[kv[0]] = kv[1]; |
|
|
|
}); |
|
|
|
this._stylesExtStore.OverwriteBehaviour(extStore); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
this._element.append( |
|
|
|
(wenity instanceof WebTrinity |
|
|
|
? wenity.html |
|
|
|
: wenity |
|
|
|
) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @override |
|
|
|
* @param {boolean|null} styleStoreInternal |
|
|
|
* @param {ExtStorageType|null} cssStore |
|
|
|
* @returns {WebTrinity} |
|
|
|
* @class StyleStoringComponent |
|
|
|
*/ |
|
|
|
generate(styleStoreInternal = null, cssStore = null) { |
|
|
|
let wenity = new WebTrinity(); |
|
|
|
|
|
|
|
/* Sort Styling Storage Types */ |
|
|
|
this.setStylingsStorage(styleStoreInternal); |
|
|
|
this.setCssStorage(cssStore); |
|
|
|
|
|
|
|
/* invoke Storage Types/generate Element */ |
|
|
|
if (this._styleStoreInternal) { |
|
|
|
wenity.html = super.generate(); |
|
|
|
} else { |
|
|
|
this.addStyleClass(this._compName, this._modifier); |
|
|
|
wenity.html = this._element; |
|
|
|
} |
|
|
|
|
|
|
|
if (this._cssExtStore === ExtStorageType.CENTRALIZED) { |
|
|
|
Object.entries(this.#css) |
|
|
|
.forEach(kv => Page.registerStyling(kv[0], kv[1])); |
|
|
|
} else { |
|
|
|
switch (this._cssExtStore) { |
|
|
|
case ExtStorageType.INDIVIDUALLY: |
|
|
|
let tag = this._generateStyleTag(); |
|
|
|
tag.setAttribute('data-compel-for', this._compName); |
|
|
|
document.querySelector('head') |
|
|
|
.insertAdjacentElement( |
|
|
|
"beforeend", |
|
|
|
tag |
|
|
|
); |
|
|
|
break; |
|
|
|
case ExtStorageType.COLLECTED: |
|
|
|
wenity.css = this.#css; |
|
|
|
break; |
|
|
|
} |
|
|
|
console.log("(Style)ExtStore was empty, did nothing"); |
|
|
|
} |
|
|
|
|
|
|
|
return wenity; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
*/ |
|
|
|
class FunctionRegistration { |
|
|
|
/** |
|
|
|
* Defines/Sets the general "storage-behaviour" for functions of this component. |
|
|
|
* If a function is passed via "registerFunction", |
|
|
|
* an alternative behaviour can be passed as a parameter - which will only be applied on/for that single one. |
|
|
|
* |
|
|
|
* @param {Function} func |
|
|
|
* @param {OverwriteBehaviour} overwriteBehaviour |
|
|
|
*/ |
|
|
|
constructor(func, overwriteBehaviour = OverwriteBehaviour.RENAME) { |
|
|
|
this.fun = func; |
|
|
|
this.overwrite = overwriteBehaviour; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
*/ |
|
|
|
class ScriptStoringComponent extends StyleStoringComponent { |
|
|
|
/** |
|
|
|
* Collection of component associated/used functions |
|
|
|
* @property {map<string,FunctionRegistration>} functions |
|
|
|
*/ |
|
|
|
#functions; |
|
|
|
/** |
|
|
|
* @property {ExtStore} |
|
|
|
*/ |
|
|
|
_funcStore; |
|
|
|
/** |
|
|
|
* @property {HTMLScriptElement} scriptTag |
|
|
|
*/ |
|
|
|
#scriptTag; |
|
|
|
|
|
|
|
constructor(element, attr = {}) { |
|
|
|
super(element, attr); |
|
|
|
this.#functions = {}; |
|
|
|
this._funcStore = StoreExtAs.CENTRALIZED.positionedAt().BEGINNING(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @override |
|
|
|
* @param {ScriptStoringComponent|Component|ChainableModifier} component |
|
|
|
* @param {ExtStorage|ExtStoreType|OverwriteBehaviour} extStore |
|
|
|
* @returns {Component} |
|
|
|
*/ |
|
|
|
_appendChildComponent(component) { |
|
|
|
if (!(component instanceof Component)) { |
|
|
|
component = component.toComponent(); |
|
|
|
} |
|
|
|
let wenity = component.generate(); |
|
|
|
|
|
|
|
if (Object.hasOwn(wenity, "js") & wenity.js) { |
|
|
|
if (wenity.js instanceof HTMLScriptElement) { |
|
|
|
this.#scriptTag = wenity.js; |
|
|
|
setFunctionsStorage(extStore) { |
|
|
|
if (extStore) { |
|
|
|
if (extStore instanceof ExtStorage) { |
|
|
|
this._stylesExtStore = extStore; |
|
|
|
} else if (extStore instanceof ExtStoreType) { |
|
|
|
this._stylesExtStore.setExtStoreType(extStore); |
|
|
|
} else { |
|
|
|
Object.entries(wenity.js) |
|
|
|
.forEach(kv => { |
|
|
|
this.#functions[kv[0]] = kv[1]; |
|
|
|
}); |
|
|
|
this._stylesExtStore.OverwriteBehaviour(extStore); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (Object.hasOwn(wenity, "css") & wenity.css) { |
|
|
|
super._appendChildComponent(wenity); |
|
|
|
} else { |
|
|
|
this._element.append( |
|
|
|
(wenity instanceof WebTrinity |
|
|
|
? wenity.html |
|
|
|
: wenity |
|
|
|
) |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param {string} nameAddition |
|
|
|
* @returns |
|
|
|
*/ |
|
|
|
_getFunctionName(nameAddition = "") { |
|
|
|
return `func${this.#functions.length}${nameAddition}`; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @todo potential code duplication - and doc |
|
|
|
* @returns {HTMLScriptElement} |
|
|
|
*/ |
|
|
|
_generateScriptTag() { |
|
|
|
return Object.keys(this.#functions) |
|
|
|
.reduce((scriptTag, funName) => { |
|
|
|
let funReg = this.#functions[funName]; |
|
|
|
if (funReg.fun.startsWith('function')) { |
|
|
|
let funcNameDeclaration = `function ${funName}`; |
|
|
|
scriptTag.innerText += (funReg.fun.startsWith(funcNameDeclaration) |
|
|
|
? funReg.fun |
|
|
|
: funReg.fun.split('(') |
|
|
|
.replace((a, c, i) => (i === 0 ? [funcNameDeclaration] : [...a, c]),) |
|
|
|
.join('(') |
|
|
|
) |
|
|
|
} else { |
|
|
|
scriptTag.innerText += `const ${funName} = ${funReg.fun}; `; |
|
|
|
} |
|
|
|
return scriptTag; |
|
|
|
}, document.createElement('script')); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param {ExtStore} functionStore |
|
|
|
* @returns {Component} |
|
|
|
*/ |
|
|
|
setFunctionStorage(functionStore) { |
|
|
|
if (functionStore) { |
|
|
|
this._funcStore = functionStore; |
|
|
|
} |
|
|
|
if (this._funcStore === ExtStorageType.INTERNALIZED) { |
|
|
|
this._funcStore = ExtStorageType.INDIVIDUALLY; |
|
|
|
console.log("(Function)ExtStore was empty, did nothing"); |
|
|
|
} |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param {Function} func |
|
|
|
* @param {string} underTheName |
|
|
|
* @param {OverwriteBehaviour} overwriteBehaviour |
|
|
|
* @returns |
|
|
|
*/ |
|
|
|
registerFunction(func, underTheName = "", overwriteBehaviour = OverwriteBehaviour.RENAME) { |
|
|
|
let registrationName = [underTheName.trim(), func.name.trim(), this._getFunctionName()] |
|
|
|
.find(e !== ''); |
|
|
|
|
|
|
|
/* deal with name already present */ |
|
|
|
let functionNames = Object.keys(this.#functions); |
|
|
|
if (functionNames.some(key => key.includes(registrationName))) { |
|
|
|
registrationName = resolveOverwrite( |
|
|
|
registrationName, |
|
|
|
this.#functions |
|
|
|
); |
|
|
|
* |
|
|
|
* @param {Function} func |
|
|
|
* @param {string} underTheName |
|
|
|
* @param {ExtStorage|ExtStoreType|ExtStorePosition|OverwriteBehaviour|EXPosConfer|ESOverwriteConfer} extStore |
|
|
|
* if a unique definition is desired, all constants or configurator objects are allowed - they will be processed accordingly |
|
|
|
* @returns |
|
|
|
*/ |
|
|
|
registerFunction(func, underTheName = "", extStore = null) { |
|
|
|
|
|
|
|
let registrationName = [ |
|
|
|
underTheName.trim(), |
|
|
|
func.name.trim(), |
|
|
|
`func${this._compName}${Object.keys(this._functions).length}` |
|
|
|
] |
|
|
|
.find(e => e !== ''); |
|
|
|
|
|
|
|
/* |
|
|
|
if (!extStore) { |
|
|
|
extStore = this._functionsExtStore; |
|
|
|
} else if (extStore instanceof ExtStoreConfer) { |
|
|
|
extStore = extStore.ensureStore(); |
|
|
|
} else { |
|
|
|
extStore = new ExtStorage().setSingleValueToClone(extStore, this._functionsExtStore); |
|
|
|
} |
|
|
|
this.#functions[registrationName] = new FunctionRegistration(func, overwriteBehaviour); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* @param {boolean} styleStoreInternal |
|
|
|
* @param {ExtStorageType} cssStore |
|
|
|
* @param {ExtStore} funcStore |
|
|
|
* @class ScriptStoringComponent |
|
|
|
*/ |
|
|
|
generate(styleStoreInternal = null, cssStore = null, funcStore = null) { |
|
|
|
let wenity = super.generate(styleStoreInternal, cssStore); |
|
|
|
*/ |
|
|
|
|
|
|
|
/* Sort Styling Storage Types */ |
|
|
|
this.setFunctionStorage(funcStore); |
|
|
|
let entry = new SStoreDefinition(); |
|
|
|
entry._identifier = registrationName; |
|
|
|
entry._definition = func; |
|
|
|
entry._extStore = extStore; |
|
|
|
|
|
|
|
if (this._funcStore.type === ExtStorageType.INDIVIDUALLY) { |
|
|
|
let tag = this._generateScriptTag(); |
|
|
|
this._functions.push(entry); |
|
|
|
|
|
|
|
switch (this._funcStore.position) { |
|
|
|
case ExtStoragePos.WITHIN: |
|
|
|
wenity.html.insertAdjacentElement( |
|
|
|
"afterbegin", |
|
|
|
tag |
|
|
|
); |
|
|
|
break; |
|
|
|
//identifyAndResolveOverwrite(this._functions, registrationName, entry, extStore._overwriteBehaviour);
|
|
|
|
|
|
|
|
case ExtStoragePos.BEGINNING: |
|
|
|
document.querySelector('head') |
|
|
|
.insertAdjacentElement( |
|
|
|
"beforeend", |
|
|
|
tag |
|
|
|
); |
|
|
|
break; |
|
|
|
case ExtStoragePos.END: |
|
|
|
document.querySelector('body') |
|
|
|
.insertAdjacentElement( |
|
|
|
"beforeend", |
|
|
|
tag |
|
|
|
); |
|
|
|
break; |
|
|
|
case ExtStoragePos.BEFORE: |
|
|
|
case ExtStoragePos.SEGMENT_BEGIN: |
|
|
|
default: |
|
|
|
wenity.js = tag; |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
switch (this._funcStore.type) { |
|
|
|
case ExtStorageType.COLLECTED: |
|
|
|
case ExtStorageType.CENTRALIZED: |
|
|
|
default: |
|
|
|
/** |
|
|
|
* @todo implement difference between collected and centralized in |
|
|
|
* generate, appendChild and childContext function-chain |
|
|
|
*/ |
|
|
|
Object.entries(this.#functions) |
|
|
|
.forEach(tuple => { |
|
|
|
Page.registerPageFunction( |
|
|
|
fun = tuple[1].fun, |
|
|
|
underTheName = tuple[0], |
|
|
|
overwriteBehaviour = tuple[1].overwrite |
|
|
|
); |
|
|
|
}); |
|
|
|
//wenity.js = tag;
|
|
|
|
} |
|
|
|
} |
|
|
|
return wenity; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|