woodpecker-test/stear/main.js

378 lines
10 KiB
JavaScript
Raw Normal View History

2022-11-06 20:39:28 +01:00
import { LanguagePool, LanguagePoolString } from "./language.js"
var counter = 0;
var globalStyle = document.createElement("style");
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("");
};
class callPromise extends Promise{
#opts = {};
constructor(cb){
super(cb);
};
set opts(opts){
this.#opts = opts;
}
get opts(){
return this.#opts;
}
}
const pools = {
};
export class Stear{
elem;
#childs = {};
constructor(elem){
this.elem = elem;
elem.style.position="relative";
}
style(css){
Object.entries(css).forEach(([k, d]) => {
this.elem.style[k] = d;
});
}
addElement (id,elem){
if(!(elem instanceof SFrame))throw new TypeError("Cannot add Element not extending from SFrame");
this.#childs[id] = elem;
}
getElement (id) {
return this.g(id);
}
g(id){
return this.#childs[id];
}
async call (elem, args, layer = 1){
return await elem.call(this, args, layer);
}
include(elem, args, renderParent, layer = 1){
return elem.call(this, args, layer, renderParent);
}
static addGlobalStyleText(text){
globalStyle.innerHTML+="\n"+text;
}
static addAnimation(steps, name = "stearAnimation_" + counter++){
Stear.addGlobalStyleText(`@keyframes ${name} {
${
Object.entries(steps).map(([k,d])=>
` ${k} {
${Object.entries(d).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").join("\n")}
}`).join("\n")
}
}`);
return name;
}
static addGlobalStyleJSON(json, name = ".stearClass_" + counter++){
Stear.addGlobalStyleText(`
${name} {
${Object.entries(json).map(d => " " + toCssAttr(d[0]) + ": " + d[1] + ";").join("\n")}
}
`)
return name;
}
static addLanguagePool(name){
if(typeof pools[name] == "undefined"){
pools[name] = new LanguagePool();
}
return pools[name];
}
static addLanguageFile(data,lang){
Object.entries(data).forEach(([k,d]) => {
if (typeof pools[k] == "undefined") pools[k] = new LanguagePool();
pools[k].addFile(d,lang);
});
}
static set lang (lang){
Object.entries(pools).forEach(([k, d]) => {
d.lang = lang;
});
}
static get getLanguageFile(){
var out = {};
Object.entries(pools).forEach(([k, d]) => {
out[k] = d.getFile;
});
return out;
}
}
export class SFrame{
#preRender;
#call;
constructor({ call, preRender = true }){
this.#preRender = preRender;
this.#call = call;
}
call(stear, args, layer = 1, renderParent = stear.elem){
let lastRender;
let renderElem;
let event = { onloaded: () => { }, onclose: ()=>{}, onresolve: () => { }, onBeforRerender: () => { }, onAfterRerender: () => { }, onParentRender:()=>{} };
let find = {};
let resolved = false;
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_");
await now.build(args);
renderParent.appendChild(now.render);
lastRender = now;
now._.style.zIndex = layer;
for (var member in find) delete find[member];
Object.assign(find, now.find);
return lastRender;
}
const ppp = new callPromise(async (res,rej)=>{
const options = {
find,
render: async (...args) => {
await event.onBeforRerender(...args);
if (renderElem) await render(args);
firstRender = true;
await event.onAfterRerender(...args);
return find;
},
resolve: async (r, close = true) => {
if (resolved) return;
resolved = true;
await event.onresolve();
if (close && lastRender && [...(renderParent.children)].includes(lastRender._)) renderParent.removeChild(lastRender._);
res(r);
},
call: (elem, args = {}) => {
return stear.call(elem, args, layer + 1);
},
close: async () => {
await event.onclose();
if (close && lastRender && [...(renderParent.children)].includes(lastRender._)) renderParent.removeChild(lastRender._);
},
include: (frame, args = {}) => {
let iFrame = new includeFrame(stear, frame, layer + 1, args);
return iFrame;
},
event,
};
window.queueMicrotask(() => ppp.opts = options);
let firstRender = false;
renderElem = await this.#call(stear, options, args);
if(!renderElem) {
}else{
if (this.#preRender | firstRender) await render([]);
event.onloaded();
}
});
return ppp;
}
}
export class SWindow extends SFrame{
#Frame;
constructor({ call, preRender = true, backgroundColor = "transparent"}){
var Frame = _({
style: {
top: "0px",
left: "0px",
position: "absolute",
height: "100%",
width: "100%",
display: "block",
backgroundColor,
//overflow:"scroll"
},
find:"main"
}, []);
super({
call: async(...args) => _({
style: {
top: "0px",
left: "0px",
position: "absolute",
height: "100%",
width: "100%",
display: "block",
backgroundColor,
//overflow:"scroll"
},
find: "main"
}, await call(...args)),
preRender
});
this.#Frame = Frame;
}
}
export class class_ {
#elem;
#childs;
#build;
#find;
#doBuild;
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])=>{
this.#elem.style[k] = d;
});
} else if (key == "find"){
this.#find = settings[key];
} else if (key == "event"){
Object.entries(settings[key]).forEach(([k, d]) => {
this.#elem.addEventListener(k,d);
});
} else if (key == "attr"){
Object.entries(settings[key]).forEach(([k, d]) => {
this.#elem.setAttribute(k, d);
});
} else {
this.#elem.setAttribute(key,settings[key]);
}
}
this.#doBuild = doBuild;
}
set childs(childs){
if (!this.#doBuild) return;
this.#childs = Array.isArray(childs) ? childs : [childs];
}
set settings(settings){
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]) => {
this.#elem.style[k] = d;
});
} else if (key == "find") {
this.#find = settings[key];
} else {
this.#elem.setAttribute(key, settings[key]);
}
}
}
async build (args) {
if(!this.#doBuild)return;
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(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);
this.#build.push(elem);
}
}
}
get render (){
if (!this.#doBuild) return this.#elem;
this.#elem.innerHTML = "";
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)));
} else {
this.#elem.appendChild(elem.render);
}
}
return this.#elem;
}
get _ (){
return this.#elem;
}
get find (){
var out = {};
if (this.#doBuild){
this.#build.forEach(d=>{
Object.assign(out,d.find);
});
}
if (this.#find) out[this.#find]=this;
return out;
}
}
export const _ = (settings = {}, childs = []) => new class_(settings, Array.isArray(childs) ? childs : [childs]);
export const s = (type,settings,...childs)=>new class_(Object.assign(settings,{type}),childs);
class includeFrame{
#elem;
#call;
constructor(stear,frame,layer, args = {}){
this.#elem = new class_({},[],false);
this.#call = stear.include(frame, args, this.#elem._, layer);
this.#call.then(()=>{
})
.catch(()=>{
});
}
get opts(){
return this.#call.opts;
}
close(){
if(this.#call){
this.#call.opts.close();
}
}
render(settings={}){
this.#elem.settings = settings;
this.#call.opts.event.onParentRender();
return this.#elem;
}
};