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.
 
 

203 lines
5.9 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
*/
/**
* @todo Potentially class implementation could be removed entirely.
* Since it (at the time being) is only working as a singleton anyway.
* Further maybe rename to 'AppBuilder' instead of 'PageBuilder',
* page might later become part of a navigation setup.
*
*
* The class provides overreaching options for building the website.
* @extends ScriptAndStyleContext
*/
class PageBuilder extends ScriptAndStyleContext {
/**
* @type {Array<string>}
*/
#autoRegisteredComponents;
/**
* @type {Array<string>}
*/
#registeredComponents;
/**
* @type {boolean}
*/
#showFrameworkConsole;
/**
* @type {Array<CompelExtension>}
*/
_extensions;
/**
* @type {Map<string,*>}
*/
_groups;
constructor() {
super();
this.#showFrameworkConsole = false;
this.#autoRegisteredComponents = [];
this.#registeredComponents = [];
this._extensions = [];
this._groups = new Map();
}
/**
*
* @param {*|Array<*>} groups
* @param {Component} component
*/
subscribeComponentToGroup(groups, component) {
if (groups instanceof Array && !(groups instanceof String)) {
for (let i = 0; i < groups.length; i++) {
this.subscribeComponentToGroup(groups[i], component);
}
} else {
if (!this._groups.has(groups)) {
this._groups.set(groups, []);
}
this._groups.get(groups).push(component);
}
}
autoRegisterComponent() {
let compName = 'comp-el-' + this.#autoRegisteredComponents.length;
this.#autoRegisteredComponents.push(compName);
return compName;
}
registerComponent(compName) {
this.#registeredComponents.push(compName);
return compName;
}
/**
* Inserts the given element according to the extStore into the page/document.
* The refElement is a reference element for the case
* that extStore._position defines "before" or "segment_begin",
* which will then look for the refElement as the corresponding insert reference.
*
* @param {HTMLElement|Component} element
* @param {ExtStorage} extStore
* @param {HTMLElement|Component} refElement
*/
addElementToPage(element, extStore = ExtStoreType.CENTRALIZED_DOC_HEAD) {
let { insertCallEl, relativePositioning } = {};
relativePositioning = extStore.getRelativePositioning();
insertCallEl = extStore.getRefElement(element);
insertCallEl.insertAdjacentElement(
relativePositioning,
element
);
}
/**
* Determines that the jpc-like-websites libs shouldn't be part of the resulting page.
* Therefore the generate() methods will package/generate finalized js, css and html elements
* into the final html page in the end.
* Especially tricky are reusable elements and functions that use such.
*
* @todo This method/feature will have to have a logic implemented for state altering components
* that then can be "packaged" into a single page.
* @todo This method/feature will work only, if an automatic reuse logic for elements/components is implemented within the jpc lib.
* @ATTENTION DO NOT USE
*/
enableFrameworkConsole() {
this.#showFrameworkConsole = true;
return this;
}
/**
* Little helper function.
* If a single page application is in development.
* This method sets an autoreload interval for the page.
* Default is 20 (sec).
* @param {number} relaunchSeconds timeinterval for page to reload (changes)
*/
inDev(relaunchSeconds = 20) {
let head = document.querySelector("head");
let meta = document.createElement("meta");
meta.setAttribute("http-equiv", "refresh");
meta.setAttribute("content", `${relaunchSeconds}`);
let devScript = document.createElement('script');
devScript.setAttribute("data-label", "devScript");
devScript.innerText = `
let ts = new Date();
console.log("Page is in Dev-Mode (through 'inDev()' call of PageBuilder.");
console.log("Refreshed at: ", ts.getHours()+':'+ts.getMinutes()+':'+ts.getSeconds(), "Intervall ${relaunchSeconds}s");
`;
head.appendChild(devScript);
head.insertAdjacentElement("beforeend", meta);
}
/**
*
* @param {CompelExtension} extension
*/
addExtension(extension) {
if (extension instanceof CompelExtension) {
this._extensions.push(extension);
extension.install();
}
}
setPageTitle(title) {
this._apptitle = title;
}
generate() {
super.generate();
let docBody = document.querySelector('body');
if (this._apptitle) {
document.querySelector("title")
.innerText = this._apptitle;
}
if (this.#showFrameworkConsole) {
let pageContextControlPanel = frameworkControlPanel(this._extensions);
pageContextControlPanel = pageContextControlPanel.generate();
docBody.insertAdjacentElement(
"afterbegin",
pageContextControlPanel.html
);
}
}
compelgroups = this._groups;
}
}
const CommonCompelGroups = Object.freeze({
AUTO_REGISTRATED: "auto_registrated",
REUSABLE_COMPEL: "reusable",
HIGHER_COMPEL: "higher_compel",
OVERFLOWING: "overflowing",
HIDDEN_ON_START: "hidden_on_start",
IS_CONTEXT_MENU: "is_contextmenu",
HAS_CONTEXT_MENU: "has_contextmenu",
DRAGGABLE: "draggable",
HAS_DRAG_EVENT: "has_drag",
DROP_TARGET: "droptarget",
});
const Page = new PageBuilder();