Compare commits

...

2 commits

Author SHA1 Message Date
bf9908ded1 restructure and less wasted time while rendering 2022-12-07 21:08:53 +01:00
15a4048730 fixes 2022-12-07 20:27:57 +01:00

239
main.js
View file

@ -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;
}
}
@ -27,8 +27,10 @@ const pools = {
};
const stears = [];
/** Stear class */
export class Stear{
export class Stear {
elem;
#childs = {};
@ -39,9 +41,16 @@ 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() {
let i = stears.indexOf(this);
if (i == -1) return;
stears.splice(i, 1);
delete this;
}
/**
@ -49,7 +58,7 @@ export class Stear{
*
* @param {JSON} css
*/
style(css){
style(css) {
Object.entries(css).forEach(([k, d]) => {
this.elem.style[k] = d;
});
@ -61,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;
}
@ -72,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];
}
@ -88,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);
}
@ -101,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);
}
@ -111,17 +120,17 @@ 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();
});
}
});
@ -132,8 +141,8 @@ export class Stear{
*
* @param {string} text
*/
static addGlobalStyleText(text){
globalStyle.innerHTML+="\n"+text;
static addGlobalStyleText(text) {
globalStyle.innerHTML += "\n" + text;
}
/**
@ -143,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;
@ -162,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")}
@ -177,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];
@ -190,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;
});
this.globalRenderRequest();
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;
@ -334,7 +342,7 @@ ${Object.entries(json).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").jo
/**
* SFrame class
*/
export class SFrame{
export class SFrame {
#preRender;
#call;
@ -344,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);
@ -376,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);
}
}
@ -400,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 = {}) => {
@ -419,9 +427,9 @@ export class SFrame{
window.queueMicrotask(() => ppp.opts = options);
let firstRender = false;
renderElem = await this.#call(stear, options, args);
if(!renderElem) {
if (!renderElem) {
}else{
} else {
if (this.#preRender | firstRender) await render([]);
event.onloaded();
}
@ -432,7 +440,7 @@ export class SFrame{
}
/** Create a SWindow, a Fullscreen Frame. */
export class SWindow extends SFrame{
export class SWindow extends SFrame {
#Frame;
@ -442,7 +450,7 @@ export class SWindow extends SFrame{
* @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",
@ -457,7 +465,7 @@ export class SWindow extends SFrame{
find:"main"
}, []);*/
super({
call: async(...args) => _({
call: async (...args) => _({
style: {
top: "0px",
left: "0px",
@ -494,6 +502,8 @@ export class class_ {
#find;
#doBuild;
#dynamicState = 0;
/**
* Generate a new Stear render Node.
*
@ -501,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;
@ -531,15 +541,16 @@ export class class_ {
/**
* @param {Array} childs
*/
set childs(childs){
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];
@ -555,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;
}
}
}
/**
@ -585,40 +625,51 @@ export class class_ {
*
* @return {HTMLElement}
*/
get render (){
get render() {
if (!this.#doBuild) return this.#elem;
this.#elem.innerHTML = "";
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];
if (typeof elem == "string" || elem instanceof LanguagePoolString) {
this.#elem.appendChild(document.createTextNode(String(elem)));
out[i] = document.createTextNode(String(elem));
} else {
this.#elem.appendChild(elem.render);
out[i] = elem.render;
}
}
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 (){
get find() {
var out = {};
if (this.#doBuild){
this.#build.forEach(d=>{
Object.assign(out,d.find);
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;
}
}
@ -630,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;
/**
@ -648,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();
}
}
@ -681,7 +732,7 @@ class includeFrame{
* @param {*} settings
* @returns {HTMLElement}
*/
render(settings={}){
render(settings = {}) {
this.#elem.settings = settings;
this.#call.opts.event.onParentRender();
return this.#elem;