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
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();
|
|
|