diff --git a/main.js b/main.js index ee615ac..de2cdc5 100644 --- a/main.js +++ b/main.js @@ -6,19 +6,19 @@ document.head.appendChild(globalStyle); String.prototype.map = Array.prototype.map; -function toCssAttr(txt){ - return txt.map(d => (d.toUpperCase() === d && d !== d.toLowerCase()) ? "-" + d.toLowerCase(): d ).join(""); +function toCssAttr(txt) { + return txt.map(d => (d.toUpperCase() === d && d !== d.toLowerCase()) ? "-" + d.toLowerCase() : d).join(""); }; -class callPromise extends Promise{ +class callPromise extends Promise { #opts = {}; - constructor(cb){ + constructor(cb) { super(cb); }; - set opts(opts){ + set opts(opts) { this.#opts = opts; } - get opts(){ + get opts() { return this.#opts; } } @@ -30,7 +30,7 @@ const pools = { const stears = []; /** Stear class */ -export class Stear{ +export class Stear { elem; #childs = {}; @@ -41,15 +41,15 @@ export class Stear{ * * @param {HTMLElement} elem */ - constructor(elem){ + constructor(elem) { this.elem = elem; - elem.style.position="relative"; + elem.style.position = "relative"; stears.push(this); } - destroy(){ + destroy() { let i = stears.indexOf(this); - if(i==-1) return; - stears.splice(i,1); + if (i == -1) return; + stears.splice(i, 1); delete this; } @@ -58,7 +58,7 @@ export class Stear{ * * @param {JSON} css */ - style(css){ + style(css) { Object.entries(css).forEach(([k, d]) => { this.elem.style[k] = d; }); @@ -70,8 +70,8 @@ export class Stear{ * @param {string} id * @param {SFrame} elem */ - addElement (id,elem){ - if(!(elem instanceof SFrame))throw new TypeError("Cannot add Element not extending from SFrame"); + addElement(id, elem) { + if (!(elem instanceof SFrame)) throw new TypeError("Cannot add Element not extending from SFrame"); this.#childs[id] = elem; } @@ -81,11 +81,11 @@ export class Stear{ * @param {string} id * @returns {SFrame} */ - getElement (id) { + getElement(id) { return this.g(id); } - - g(id){ + + g(id) { return this.#childs[id]; } @@ -97,7 +97,7 @@ export class Stear{ * @param {number} layer * @returns {callPromise} */ - async call (elem, args, layer = 1){ + async call(elem, args, layer = 1) { return await elem.call(this, args, this.#frames, layer); } @@ -110,7 +110,7 @@ export class Stear{ * @param {number} layer * @returns {callPromise} */ - include(elem, args, renderParent, layer = 1){ + include(elem, args, renderParent, layer = 1) { return elem.call(this, args, this.#frames, layer, renderParent); } @@ -120,20 +120,20 @@ export class Stear{ * @param {*} arg * @returns {Promise} */ - rerenderGlobal(arg){ - return new Promise((res,rej)=>{ - if(this.#frames.length == 0)return void res(); + rerenderGlobal(arg) { + return new Promise((res, rej) => { + if (this.#frames.length == 0) return void res(); let running = this.#frames.length; for (let i = 0; i < this.#frames.length; i++) { const element = this.#frames[i]; element.globalRenderRequest(arg) - .then(()=>{ - running--; - if(running==0)res(); - }); + .then(() => { + running--; + if (running == 0) res(); + }); } }); - + } /** @@ -141,8 +141,8 @@ export class Stear{ * * @param {string} text */ - static addGlobalStyleText(text){ - globalStyle.innerHTML+="\n"+text; + static addGlobalStyleText(text) { + globalStyle.innerHTML += "\n" + text; } /** @@ -152,14 +152,13 @@ export class Stear{ * @param {string} name * @returns {string} name */ - static addAnimation(steps, name = "stearAnimation_" + counter++){ + static addAnimation(steps, name = "stearAnimation_" + counter++) { Stear.addGlobalStyleText(`@keyframes ${name} { -${ -Object.entries(steps).map(([k,d])=> -` ${k} { +${Object.entries(steps).map(([k, d]) => + ` ${k} { ${Object.entries(d).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").join("\n")} }`).join("\n") -} + } }`); return name; @@ -171,7 +170,7 @@ ${Object.entries(d).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").joi * @param {string} name - e.g. .classname * @returns {string} name */ - static addGlobalStyleJSON(json, name = ".stearClass_" + counter++){ + static addGlobalStyleJSON(json, name = ".stearClass_" + counter++) { Stear.addGlobalStyleText(` ${name} { ${Object.entries(json).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").join("\n")} @@ -186,8 +185,8 @@ ${Object.entries(json).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").jo * @param {string} name * @returns {LanguagePool} */ - static addLanguagePool(name){ - if(typeof pools[name] == "undefined"){ + static addLanguagePool(name) { + if (typeof pools[name] == "undefined") { pools[name] = new LanguagePool(); } return pools[name]; @@ -199,27 +198,27 @@ ${Object.entries(json).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").jo * @param {JSON} data * @param {string} lang */ - static addLanguageFile(data,lang){ - Object.entries(data).forEach(([k,d]) => { + static addLanguageFile(data, lang) { + Object.entries(data).forEach(([k, d]) => { if (typeof pools[k] == "undefined") pools[k] = new LanguagePool(); - pools[k].addFile(d,lang); + pools[k].addFile(d, lang); }); - } + } /** * Used Language */ - static set lang (lang){ + static set lang(lang) { Object.entries(pools).forEach(([k, d]) => { d.lang = lang; }); - stears.forEach(s=>s.rerenderGlobal()); + stears.forEach(s => s.rerenderGlobal()); } /** * Generate Language File with defaults */ - static get getLanguageFile(){ + static get getLanguageFile() { var out = {}; Object.entries(pools).forEach(([k, d]) => { out[k] = d.getFile; @@ -343,7 +342,7 @@ ${Object.entries(json).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").jo /** * SFrame class */ -export class SFrame{ +export class SFrame { #preRender; #call; @@ -353,26 +352,26 @@ export class SFrame{ * @param {callCallback} args.call * @param {boolean} [args.preRender] */ - constructor({ call, preRender = true }){ + constructor({ call, preRender = true }) { this.#preRender = preRender; this.#call = call; } - call(stear, args, frames, layer = 1, renderParent = stear.elem){ + call(stear, args, frames, layer = 1, renderParent = stear.elem) { let lastRender; let renderElem; - - let event = { onloaded: () => { }, onclose: ()=>{}, onresolve: () => { }, onBeforRerender: () => { }, onAfterRerender: () => { }, onParentRender:()=>{}, onGlobalRenderRequest:()=>true }; + + let event = { onloaded: () => { }, onclose: () => { }, onresolve: () => { }, onBeforRerender: () => { }, onAfterRerender: () => { }, onParentRender: () => { }, onGlobalRenderRequest: () => true }; let find = {}; let resolved = false; - async function render(args){ - if(!renderElem) return; + async function render(args) { + if (!renderElem) return; if (lastRender) if ([...(renderParent.children)].includes(lastRender._)) renderParent.removeChild(lastRender._); let now = renderElem; - if(typeof now == "function")now = await now(); - if(!(now instanceof class_)) throw new Error("The Element to render is not an instance of class_"); + if (typeof now == "function") now = await now(); + if (!(now instanceof class_)) throw new Error("The Element to render is not an instance of class_"); await now.build(args); renderParent.appendChild(now.render); @@ -385,11 +384,11 @@ export class SFrame{ return lastRender; } - const ppp = new callPromise(async (res,rej)=>{ + const ppp = new callPromise(async (res, rej) => { const globalRegister = { - globalRenderRequest: async (...args)=>{ + globalRenderRequest: async (...args) => { const arg = await event.onGlobalRenderRequest(...args); - if(arg===false) return; + if (arg === false) return; await options.render(arg); } } @@ -409,7 +408,7 @@ export class SFrame{ await event.onresolve(); if (close && lastRender && [...(renderParent.children)].includes(lastRender._)) renderParent.removeChild(lastRender._); let i = frames.indexOf(globalRegister); - if(i>-1)frames.splice(i,1); + if (i > -1) frames.splice(i, 1); res(r); }, call: (elem, args = {}) => { @@ -425,15 +424,15 @@ export class SFrame{ }, event, }; - window.queueMicrotask(() => ppp.opts = options); + window.queueMicrotask(() => ppp.opts = options); let firstRender = false; renderElem = await this.#call(stear, options, args); - if(!renderElem) { - - }else{ + if (!renderElem) { + + } else { if (this.#preRender | firstRender) await render([]); event.onloaded(); - } + } }); return ppp; } @@ -441,17 +440,17 @@ export class SFrame{ } /** Create a SWindow, a Fullscreen Frame. */ -export class SWindow extends SFrame{ +export class SWindow extends SFrame { #Frame; - + /** * * @param {Object} args * @param {callCallback} args.call * @param {boolean} [args.preRender] */ - constructor({ call, preRender = true, backgroundColor = "transparent"}){ + constructor({ call, preRender = true, backgroundColor = "transparent" }) { /*var Frame = _({ style: { top: "0px", @@ -466,7 +465,7 @@ export class SWindow extends SFrame{ find:"main" }, []);*/ super({ - call: async(...args) => _({ + call: async (...args) => _({ style: { top: "0px", left: "0px", @@ -478,12 +477,12 @@ export class SWindow extends SFrame{ //overflow:"scroll" }, find: "main" - }, await call(...args)), + }, await call(...args)), preRender }); //this.#Frame = Frame; } - + } /** @@ -503,6 +502,8 @@ export class class_ { #find; #doBuild; + #dynamicState = 0; + /** * Generate a new Stear render Node. * @@ -510,28 +511,28 @@ export class class_ { * @param {Array} childs * @param {boolean} doBuild */ - constructor(settings,childs,doBuild = true){ + constructor(settings, childs, doBuild = true) { this.#elem = document.createElement(settings.type ?? "div"); this.#childs = childs; var keys = Object.keys(settings); for (let i = 0; i < keys.length; i++) { const key = keys[i]; - if(key == "type"){} else if (key == "style"){ - Object.entries(settings[key]).forEach(([k,d])=>{ + if (key == "type") { } else if (key == "style") { + Object.entries(settings[key]).forEach(([k, d]) => { this.#elem.style[k] = d; }); - } else if (key == "find"){ + } else if (key == "find") { this.#find = settings[key]; - } else if (key == "event"){ + } else if (key == "event") { Object.entries(settings[key]).forEach(([k, d]) => { - this.#elem.addEventListener(k,d); + this.#elem.addEventListener(k, d); }); - } else if (key == "attr"){ + } else if (key == "attr") { Object.entries(settings[key]).forEach(([k, d]) => { this.#elem.setAttribute(k, d); }); } else { - this.#elem.setAttribute(key,settings[key]); + this.#elem.setAttribute(key, settings[key]); } } this.#doBuild = doBuild; @@ -540,15 +541,16 @@ export class class_ { /** * @param {Array} childs */ - set childs(childs){ - if (!this.#doBuild) return; + set childs(childs) { + if (!this.#doBuild) return; this.#childs = Array.isArray(childs) ? childs : [childs]; + this.#dynamicState = 0; } /** * @param {renderNodeSettings} settings */ - set settings(settings){ + set settings(settings) { var keys = Object.keys(settings); for (let i = 0; i < keys.length; i++) { const key = keys[i]; @@ -564,29 +566,58 @@ export class class_ { } } + async #syncBuild(args) { + for (let i = 0; i < this.#childs.length; i++) { + let elem = this.#childs[i]; + + if (Array.isArray(elem)) { + for (let j = 0; j < elem.length; j++) { + if (elem[j] instanceof class_) await elem[j].build(args); + } + } else { + if (elem instanceof class_) await elem.build(args); + } + } + } + /** * Build Stear Structure * * @param {*} args */ - async build (args) { - if(!this.#doBuild)return; + async build(args) { + if (!this.#doBuild) return; + if (this.#dynamicState < 0) return void await this.#syncBuild(args); this.#build = []; for (let i = 0; i < this.#childs.length; i++) { let elem = this.#childs[i]; - if (typeof elem == "function") elem = (await elem(...args))??[]; + if (typeof elem == "function") { + elem = (await elem(...args)) ?? []; + this.#dynamicState = 2; + } - if(Array.isArray(elem)){ + if (Array.isArray(elem)) { for (let j = 0; j < elem.length; j++) { if (elem[j] instanceof class_) await elem[j].build(args); } this.#build.push(...elem); - }else{ - if(elem instanceof class_)await elem.build(args); + } else { + if (elem instanceof class_) await elem.build(args); this.#build.push(elem); } } + if (this.#dynamicState <= 0) this.#dynamicState = -1; + } + + #syncRender() { + let out = []; + for (let i = 0; i < this.#build.length; i++) { + const elem = this.#build[i]; + if (typeof elem != "string" && !(elem instanceof LanguagePoolString)) { + out[i] = elem.render; + } + } } /** @@ -594,8 +625,12 @@ export class class_ { * * @return {HTMLElement} */ - get render (){ + get render() { if (!this.#doBuild) return this.#elem; + if (this.#dynamicState < -1) { + this.#syncRender(); + return this.#elem; + } let out = []; for (let i = 0; i < this.#build.length; i++) { const elem = this.#build[i]; @@ -606,29 +641,35 @@ export class class_ { } } this.#elem.replaceChildren(...out); + if (this.#dynamicState < 0) this.#dynamicState = -2; return this.#elem; } /** * @return {HTMLElement} */ - get _ (){ + get _() { return this.#elem; } + async rerender(args = []) { + await this.build(args); + this.render; + } + /** * Returns find Object * * @return {Object} find */ - get find (){ - var out = {}; - if (this.#doBuild){ - this.#build.forEach(d=>{ - Object.assign(out,d.find); + get find() { + var out = {}; + if (this.#doBuild) { + this.#build.forEach(d => { + Object.assign(out, d.find); }); } - if (this.#find) out[this.#find]=this; + if (this.#find) out[this.#find] = this; return out; } } @@ -640,14 +681,14 @@ export class class_ { * @returns {class_} */ export const _ = (settings = {}, childs = []) => new class_(settings, Array.isArray(childs) ? childs : [childs]); -export const s = (type,settings,...childs)=>{ +export const s = (type, settings, ...childs) => { settings = settings ?? {}; settings.type = type; - return new class_(settings,childs); + return new class_(settings, childs); } /** includeFrame */ -class includeFrame{ +class includeFrame { #elem; #call; /** @@ -658,29 +699,29 @@ class includeFrame{ * @param {number} layer * @param {*} args */ - constructor(stear,frame,layer, args = {}){ - this.#elem = new class_({},[],false); + constructor(stear, frame, layer, args = {}) { + this.#elem = new class_({}, [], false); this.#call = stear.include(frame, args, this.#elem._, layer); - this.#call.then(()=>{ + this.#call.then(() => { }) - .catch(()=>{ + .catch(() => { - }); + }); } - + /** * @return {callUtils} utils from included Frame */ - get opts(){ + get opts() { return this.#call.opts; } /** * Close the included Frame. */ - close(){ - if(this.#call){ + close() { + if (this.#call) { this.#call.opts.close(); } } @@ -691,10 +732,10 @@ class includeFrame{ * @param {*} settings * @returns {HTMLElement} */ - render(settings={}){ + render(settings = {}) { this.#elem.settings = settings; this.#call.opts.event.onParentRender(); return this.#elem; } - + }; \ No newline at end of file