/** * 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 */ /** * 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 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.#isCompel = false; this._isContextMenu = false; this._modifier = new Modifier() .margin(new Sides().all(0)); this._modifier._modifications['display'] = "flex"; this._toRegister = []; } /** * Adds a class to classList via HTMLElement.classList.add() method. * Further collects rules in a property until generate is called. * * @CAUGHTION implementation is not safe to use, ignoring extStore is recommended; * * @todo difference between stylings and classes, extStore logic in combination with the Page.register... logic * * @override * * @param {string} styleClass (without the '.' in the front) * @param {string|Modifier|map} styling * @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 {Component} this component object */ addStyleClass(styleClass, styling = null, extStore = null) { if (!extStore) { extStore = this._styleClassesExtStore; } else if (extStore.isMissing()) { extStore = extStore.fillBy(this._styleClassesExtStore); } if (styling) { if (styling instanceof Modifier) { styling = styling._modifications; } Page.registerStyling('.' + styleClass, styling); } this._element.classList.add(styleClass); return this; } /** * * @returns {Component} */ isHigherComponent() { this.#isCompel = true; return this.setAttribute("data-compel-isHCompel", "true") } /** * Collects the given List in the _toRegister attribute. * When generate() is called, * the created Element will be registered (added) in every list * within the list. * @param {Array} listName */ subscribeOnGenerate(listName) { this._toRegister.push(listName); return this; } /** * Defines how a child Component is to be appended. * @param {Component} component the child component to add it. * @returns {HTMLElement} */ _appendChildComponent(component) { let child = new WebTrinity(); if (component instanceof Component) { child = component.generate(); } if (component instanceof WebTrinity) { child = component; } if (component instanceof HTMLElement) { console.log("No wenity set - htmlEl was given"); child.html = component; } this._element.append(child.html); return child; } _processStyles(extStore = null) { if (!extStore) { extStore = this._stylesExtStore.updateForGeneralStyling(); } else { extStore.updateForGeneralStyling(); } /** * @todo very likely code dupplication - but kept for the time being * for error tracking. */ if (extStore._type === ExtStoreType.INTERNALIZED_WITHIN) { fillAttrsInContainerByCb( this._modifier._modifications, this._element, (key, val, el) => { el.style[key] = val; } ); } else { /* ADDS ELEMENT MODIFIER TO this._styles list for styles processing */ let modifierSSD = new SStoreDefinition(); modifierSSD._identifier = this._compName; modifierSSD._definition = this._modifier._modifications; modifierSSD._extStore = extStore; this._styles.unshift(modifierSSD); } let forCollection = []; let counter = 0; for (let i = 0; i < this._styles.length; i++) { const ssd = this._styles[i]; /* Make sure that the type is unified for later processing */ if (ssd._definition instanceof Modifier) { ssd._definition = ssd._definition._modifications; } /* Check/Ensure proper ExtStorageType for following comparison */ let refESType = ( ssd._extStore && ssd._extStore._type ? ssd._extStore.updateForGeneralStyling()._type : extStore._type ); switch (refESType) { case ExtStoreType.INTERNALIZED_WITHIN: fillAttrsInContainerByCb( ssd._definition, this._element, (key, val, el) => { el.style[key] = val; } ) break; case ExtStoreType.INDIVIDUALLY_DOC_HEAD: let container = document.createElement("style"); container.setAttribute("data-compel-individually-nr", counter++); let styleRules = Object.keys(ssd._definition); for (let j = 0; j < styleRules.length; j++) { let rule = styleRules[j]; container.innerText += `${rule} {${ssd._definition[rule]} } `; } Page.addElementToPage(container, refESType); break; case ExtStoreType.COLLECTED_DOC_HEAD: forCollection.push(ssd); break; case ExtStoreType.CENTRALIZED_DOC_HEAD: Page.registerStyling(ssd._identifier, ssd._definition); break; } } return forCollection; } _processFunctions(extStore = null) { if (!extStore) { extStore = this._functionsExtStore.updateForFunctions(); } else { extStore.updateForFunctions(); } const forCollection = new Map(); const collectForBefore = []; let counter = 0; for (let i = 0; i < this._functions.length; i++) { const ssd = this._functions[i]; /* Make sure that the type is unified for later processing */ let refESType = ( ssd._extStore && ssd._extStore._type ? ssd._extStore.updateForFunctions()._type : extStore._type ); switch (refESType) { case ExtStoreType.CENTRALIZED_DOC_HEAD: case ExtStoreType.CENTRALIZED_SEGMENT_BEGIN: case ExtStoreType.CENTRALIZED_DOC_FOOTER: Page.registerPageFunction(ssd._identifier, ssd._definition); break; case ExtStoreType.INDIVIDUALLY_WITHIN: case ExtStoreType.INDIVIDUALLY_BEFORE: case ExtStoreType.INDIVIDUALLY_SEGMENT_BEGIN: case ExtStoreType.INDIVIDUALLY_DOC_FOOTER: case ExtStoreType.INDIVIDUALLY_DOC_HEAD: let container = document.createElement("script"); container.setAttribute("data-compel-individually-nr", counter++); container.innerText += getScriptTagInjectionText( clearFunctionDeclarationText(ssd._definition), ssd._identifier ); Page.addElementToPage(container, refESType, this._element); break; case ExtStoreType.COLLECTED_BEFORE: collectForBefore.push(ssd); break; case ExtStoreType.COLLECTED_SEGMENT_BEGIN: case ExtStoreType.COLLECTED_DOC_FOOTER: case ExtStoreType.COLLECTED_DOC_HEAD: if (!forCollection.has(refESType)) { forCollection.set(refESType, []); } forCollection.get(refESType).push(ssd); break; } } return forCollection; } /** * Ends chain. * Applies all modifications on the element. * Processes alls stored additions. * Returns the constructed HTMLElement of this Component. * * * * @param {ExtStorage} * @returns {WebTrinity} the constructed HTMLElement of this Component. */ generate(styleStore = null, functionStore = null) { this._wenity = new WebTrinity(); /* DEAL WITH COMPONENT MODIFICATION FIRST */ this._modifier._modifications["justify-content"] = this._arrangement; this._modifier._modifications["align-content"] = this._alignment; this._modifier._modifications["align-items"] = this._alignment; this._modifier._modifications["text-align"] = this._alignment; let collectedWenities = []; for (let i = 0; i < this._children.length; i++) { /** * @type {Component} */ let child = this._children[i]; if (child instanceof ChainableModifier) { child = child.toComponent(); } child._modifier._updateDimensionsBy(this._modifier._paddingValues); child = child.generate(); let wenity = this._appendChildComponent(child); if (!wenity.isSSEmpty()) { collectedWenities.push(wenity); } } let styleCollection = this._processStyles(styleStore); /* dealing with being the "collecting" one or not if (this.#isCompel) { let collectedContainer = document.createElement("style"); collectedContainer.setAttribute("data-compel-collected", counter); Page.addElementToPage(collectedContainer, extStore, this._element); }else{ this._wenity.css = stylesForCollection; } */ /** * @type {Map>} */ const funcCollections = this._processFunctions(functionStore); if (this.#isCompel) { funcCollections.get(ExtStoreType.COLLECTED_DOC_FOOTER) funcCollections.get(ExtStoreType.COLLECTED_DOC_HEAD) funcCollections.get(ExtStoreType.COLLECTED_SEGMENT_BEGIN) } else { this._wenity.js = funcCollections; this._wenity.css = styleCollection; } this._wenity.html = this._element; return this._wenity; } }