From ec298757c206394e78b86ebdddc78933e5de0ccf Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 18 Feb 2025 14:18:09 +0100 Subject: [PATCH] STEP,UNSTABLE,REFA: Restructured organization of Component and its ancestry --- src/component.js | 44 +- src/componentAncestry/addStyleAndFunctions.js | 432 ++++-------------- src/componentAncestry/modifiableComponent.js | 78 +--- src/componentAncestry/wrapperComponent.js | 75 ++- 4 files changed, 173 insertions(+), 456 deletions(-) diff --git a/src/component.js b/src/component.js index 640c677..fb080b7 100644 --- a/src/component.js +++ b/src/component.js @@ -4,19 +4,47 @@ * @copyright by its creator Christian Martin */ + /** - * A chainable HTMLElement builder. + * Represents the most basic and simple form of a Component. + * It is mainly a collection of wrapper methods + * around the HTMLElement methods to make them chainable. + * It serves as base for further functionallity extensions. + * @property {Map} _style */ -class Component extends ScriptStoringComponent { +class Component extends StyleAndScriptStoringComponent { + /** + * @type {boolean} + */ + #isCompel; + /** + * @type {WebTrinity} + */ + _wenity; + /** + * @type {Array} + */ + _toRegister; + /** + * @type {boolean} + */ + _isContextMenu; + + /** + * Initializes the component + * @param {HTMLElement} element the base element + * @param {Map} attr Specific already known attributes + */ constructor(element, attr = {}) { super(element, attr); - this._modifier = new Modifier().margin(new Sides().all(0)); - var akeys = Object.keys(attr); - for (let i = 0; i < akeys.length; i++) { - element.setAttribute(akeys[i], attr[akeys[i]]); - } - this._element = element; + this.#isCompel = false; + this._isContextMenu = false; + + this._modifier = new Modifier() + .margin(new Sides().all(0)); + this._modifier._modifications['display'] = "flex"; + this._toRegister = []; } diff --git a/src/componentAncestry/addStyleAndFunctions.js b/src/componentAncestry/addStyleAndFunctions.js index 537f4c7..38c3e06 100644 --- a/src/componentAncestry/addStyleAndFunctions.js +++ b/src/componentAncestry/addStyleAndFunctions.js @@ -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>} css - */ - #css; - + * @type {ExtStore} + */ + _stylesExtStore; /** - * @property {ExtStorageType} cssExtStore + * @type {Array} */ - _cssExtStore; - + _styles; /** - * @property {HTMLStyleElement} styleTag - */ - #styleTag; + * @type {ExtStore} + */ + _functionsExtStore; + /** + * @type {Array} + */ + _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} 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; } } diff --git a/src/componentAncestry/modifiableComponent.js b/src/componentAncestry/modifiableComponent.js index d0c50fd..7bd8922 100644 --- a/src/componentAncestry/modifiableComponent.js +++ b/src/componentAncestry/modifiableComponent.js @@ -4,41 +4,45 @@ * @copyright by its creator Christian Martin */ -/** - * - * @param {map} attrs - * @param {Object} intoContainer - * @param {Function} cb - * @returns {Object} the filled container - */ -function fillAttrsInContainerByCb(attrs, intoContainer, cb) { - let keys = Object.keys(attrs); - for (let i = 0; i < keys.length; i++) { - cb(keys[i], attrs[keys[i]], intoContainer); - } - return intoContainer; -} - /** * @extends ChildbearerComponent * @abstract */ class ModifiableComponent extends ChildbearerComponent { + /** + * @type {Modifier} modifier + */ _modifier; constructor(element, attr = {}) { super(element, attr); + this._modifier = new Modifier(); } /** * Sets, updates or overwrites the Modifier-Object for this component * @param {Modifier} modifier - * @returns {Componant} this component object + * @param {boolean|ExtStorage|ExtStoreType|OverwriteBehaviour} [extStore=null] + * @returns {Component} this component object */ - modifier(modifier) { - this._modifier = this._modifier - .join(modifier.ensureModifier()); + modifier(modifier, underTheName = "", extStore = false) { + if (underTheName === "") { + underTheName = `${this._compName}-style-${this._styles.length}`; + } + + if (!extStore) { + this._modifier = this._modifier + .join(modifier.ensureModifier()); + } else { + this._styles.push( + new SStoreDefinition( + underTheName, + modifier.ensureModifier() + ) + ); + } + return this; } @@ -51,40 +55,4 @@ class ModifiableComponent extends ChildbearerComponent { return new ChainableModifier(this); } - /** - * @inheritdoc - * @override - * @param {Component|ChainableModifier|} component - */ - _appendChildComponent(component) { - this._element.append( - (component instanceof Component - ? component - : component.toComponent() - ) - .generate() - ); - } - - /** - * @inheritdoc - * @override - * @returns {HTMLElement} - * @class ModifiableComponent - */ - generate() { - this._modifier._modifications["justify-content"] = this._arrangement; - this._modifier._modifications['display'] = "flex"; - this._modifier._modifications["align-content"] = this._alignment; - this._modifier._modifications["align-items"] = this._alignment; - this._modifier._modifications["text-align"] = this._alignment; - - fillAttrsInContainerByCb( - this._modifier._modifications, - this._element, - (key, val, el) => { el.style[key] = val; } - ); - - return this._element; - } } diff --git a/src/componentAncestry/wrapperComponent.js b/src/componentAncestry/wrapperComponent.js index bde3784..248f1cb 100644 --- a/src/componentAncestry/wrapperComponent.js +++ b/src/componentAncestry/wrapperComponent.js @@ -35,16 +35,21 @@ class ElementWrapper { * @param {map} attr Specific already known attributes */ constructor(element, attr = {}) { - let akeys = Object.keys(attr); - for (let i = 0; i < akeys.length; i++) { - element.setAttribute(akeys[i], attr[akeys[i]]); - } - this._element = element; + fillAttrsInContainerByCb( + attr, + element, + function cb(k, v, con) { + con.setAttribute(k, v); + } + ); + this._compName = Page.autoRegisterComponent(); - this.setAttribute('data-autocompel', this._compName); + element.setAttribute('data-autocompel', this._compName); + this._element = element; + this.addStyleClass(this._compName); } - setComponentName(name){ + setComponentName(name) { this._givenName = name; this.setAttribute('data-compel', name); Page.registerComponent(name); @@ -57,7 +62,11 @@ class ElementWrapper { * @returns {Component} this component object */ text(text) { - this._element.innerText = text; + if (this._element instanceof HTMLInputElement && this._element.type === "text") { + this._element.value = text; + } else { + this._element.innerText = text; + } return this; } @@ -103,18 +112,6 @@ class ElementWrapper { this._element.addEventListener(theEvent, theListener, options) return this; } - - /** - * Ends chain. - * Applies all modifications on the element. - * Returns the constructed HTMLElement of this Component. - * @class ElementWrapper - * @returns {HTMLElement} - * @class ElementWrapper - */ - generate() { - return this._element; - } } @@ -124,15 +121,23 @@ class ElementWrapper { */ class ChildbearerComponent extends ElementWrapper { /** - * @property {Alignment} alignment + * @type {Array} children + */ + _children; + /** + * @type {Alignment} alignment */ _alignment; /** - * @property {Arrangement} arrangement + * @type {Arrangement} arrangement */ _arrangement; + constructor(element, attr = {}) { + super(element, attr); + this._children = []; + } /** * @todo: Unify logic extract modifications into responsible construct @@ -171,30 +176,6 @@ class ChildbearerComponent extends ElementWrapper { return this; } - /** - * Defines how a child Component is to be appended. - * @param {Component} component the child component to add it. - */ - _appendChildComponent(component) { - this._element.append( - component.generate() - ); - } - - /** - * @override - * @inheritdoc - * @class ChildbearerComponent - */ - generate() { - this._element.style.justifyContent = this._arrangement; - this._element.style.display = "flex"; - this._element.style.alignContent = this._alignment; - this._element.style.alignItems = this._alignment; - this._element.style.textAlign = this._alignment; - return super.generate(); - } - /** * Opens a context to create children elements. * Either as one component or a list/array of components. @@ -211,7 +192,7 @@ class ChildbearerComponent extends ElementWrapper { this.childContext(component[i]); } } else { - this._appendChildComponent(component); + this._children.push(component); } return this; }