2
0
mirror of https://github.com/esiur/iui.git synced 2025-06-27 17:33:12 +00:00
This commit is contained in:
2021-10-29 17:09:15 +03:00
parent 1e8ae99d39
commit b3479dbdbd
35 changed files with 857 additions and 166 deletions

View File

@ -12,13 +12,11 @@ export default IUI.module(class App extends IUIElement {
}
created() {
this.updateBindings();
IUI.bind(this, this, "/");
//IUIElement._make_bindings(this);
this.render();
this._emit("load", { app: this });
this.loaded = true;
}
});

View File

@ -1,4 +1,5 @@
import IUIElement from "./IUIElement.js";
import { IUI } from "./IUI.js";
export const BindingType = {
IUIElement: 0, // this will never happen !
@ -260,7 +261,10 @@ export class Binding {
}
// Content Attribute
else if (this.type == BindingType.ContentAttribute) {
let d = await this._execute(this.target.ownerElement, data);
let targetElement = this.target.ownerElement;
let d = await this._execute(targetElement, data);
if (d === undefined)
return false;
@ -268,7 +272,17 @@ export class Binding {
//if (d instanceof Promise)
// d = await d;
this.target.ownerElement.innerHTML = d;
targetElement.innerHTML = d;
if (window?.app?.loaded)
{
await IUI.create(targetElement);
await IUI.created(targetElement);
IUI.bind(targetElement, targetElement, "content");
await IUI.render(targetElement, targetElement._data, true);
}
//await IUI.updateTree(targetElement);
}
else if (this.type == BindingType.IfAttribute)
{

View File

@ -1,7 +1,16 @@
import IUIElement from "./IUIElement.js";
import { Binding, BindingType } from "./Binding.js";
//import Route from '../Router/Route.js';
export const IUI = {
format: function (input) {
export class IUI {
static _menus = [];
static views = [];
static modules = {};
static registry = [];
static format(input) {
if (typeof input == "string" || input instanceof String) {
let template = document.createElement("template");
template.innerHTML = input;
@ -14,12 +23,9 @@ export const IUI = {
return [input];
else
return [];
},
_menus: [],
views: [],
modules: {},
registry : [],
observer: new IntersectionObserver(function(entries) {
}
static observer = new IntersectionObserver(function(entries) {
// isIntersecting is true when element and viewport are overlapping
// isIntersecting is false when element and viewport don't overlap
for(var i = 0; i < entries.length; i++)
@ -31,8 +37,10 @@ export const IUI = {
}
}
}, { threshold: [0] }),
created: async function (element) {
}, { threshold: [0] });
static async created (element) {
for (var i = 0; i < element.children.length; i++) {
let e = element.children[i];
@ -40,15 +48,15 @@ export const IUI = {
await e.created();
await IUI.created(e);
}
},
create: async function(element)
}
static async create(element)
{
for (let i = 0; i < element.children.length; i++) {
let e = element.children[i];
if (e instanceof IUIElement) {
await e.create();
// e.updateBindings();
}
await IUI.create(e);
@ -73,8 +81,9 @@ export const IUI = {
// //await IUI.registry[i].updateAttributes();
//}
//return;
},
get : function(o)
}
static get(o)
{
return document.getElementById(o);
@ -82,12 +91,14 @@ export const IUI = {
// if (IUI.registry[i].id == o)
// return IUI.registry[i];
//return null;
},
put: function(o)
}
static put(o)
{
IUI.registry.push(o);
},
remove: function(id)
}
static remove(id)
{
for(var i = 0; i < IUI.registry.length; i++)
if (IUI.registry[i].el.id == id)
@ -95,8 +106,9 @@ export const IUI = {
IUI.registry.splice(i, 1);
break;
}
},
module: function(objectClass)
}
static module(objectClass)
{
let moduleName = objectClass.moduleName;
@ -110,8 +122,9 @@ export const IUI = {
}
return objectClass;
},
extend: function(properties, defaults, force)
}
static extend(properties, defaults, force)
{
if (properties == null)
properties = defaults;
@ -123,6 +136,135 @@ export const IUI = {
properties[i] = defaults[i];
return properties;
}
static bind(element, rootElement, sourcePath){
// ::Attribute
// : Field
// async:: Async Attribute
// async: Async Field
// @ Event
// skip element ?
if (element.hasAttribute("skip")
|| element instanceof HTMLTemplateElement)
return;
// tags to skip
//if (element instanceof HTMLScriptElement )
//return;
if (rootElement == null)
rootElement = element;
let bindings;
if (element != rootElement)
{
element.view = rootElement.view;
element.route = rootElement.route;
bindings = [];
// compile attributes
for (var i = 0; i < element.attributes.length; i++) {
let b = Binding.create(element.attributes[i]);
if (b != null) {
if (b.type == BindingType.HTMLElementDataAttribute
|| b.type == BindingType.IUIElementDataAttribute)
element.dataMap = b;
else if (b.type == BindingType.RevertAttribute)
element.revertMap = b;
else
bindings.push(b);
}
}
// add reference
if (element.hasAttribute("ref")) {
rootElement.refs[el.getAttribute("ref")] = element;
}
}
else
{
// remove previous text node bindings
bindings = element.bindings == null ? [] : element.bindings.filter(x=> x.type != BindingType.TextNode);
element.refs = {};
}
// compile nodes
for (var i = 0; i < element.childNodes.length; i++) {
let el = element.childNodes[i];
if (el instanceof IUIElement) {
// @TODO: check if the IUI element handles the binding
IUI.bind(el, rootElement, sourcePath);
}
else if (el instanceof HTMLElement) {
IUI.bind(el, rootElement, sourcePath);
}
else if (el instanceof Text) {
let b = Binding.create(el);
if (b != null)
bindings.push(b);
}
else if (el instanceof HTMLScriptElement)
{
// this because HTML parser don't evaluate script tag
let func = new Function("//# sourceURL=iui://" + sourcePath + "-" + Math.round(Math.random() * 10000) + "\r\n return " + el.text.trim());
let rt = func.call(el.parentElement);
if (typeof (rt) === "object") {
for (var k in rt)
el.parentElement[k] = rt[k];
}
}
}
element.bindings = bindings;
}
static async render(element, data, textNodesOnly = false) {
if (!element.bindings) {
return;
}
if (textNodesOnly) {
for (var i = 0; i < element.bindings.length; i++)
if (element.bindings[i].type == BindingType.TextNode)
await element.bindings[i].render(data);
} else {
// render attributes & text nodes
for (var i = 0; i < element.bindings.length; i++)
await element.bindings[i].render(data);
}
// render children
for (var i = 0; i < element.children.length; i++) {
let el = element.children[i];
if (el instanceof IUIElement)
// @TODO should check if the element depends on parent or not
if (el.dataMap != null) {
// if map function failed to call setData, we will render without it
if (!(await el.dataMap.render(data)))
await el.render();
}
else
await el.setData(data);
else {
if (el.dataMap != null)
await el.dataMap.render(data);
else
el.data = data;
//let data = e.mapData(data);
await IUI.render(el, el.data);
}
}
}
};
export function iui(selector)

View File

@ -40,7 +40,8 @@ export default class IUIElement extends HTMLElement {
}
async render() {
await this._renderElement(this, this._data);
await IUI.render(this, this._data);
//await IUIElement._renderElement(this, this._data);
}
_getParentData() {
@ -54,15 +55,9 @@ export default class IUIElement extends HTMLElement {
}
async setData(value) {
//if (this.bindings === undefined)
// this.updateBindings();
this._data = value;
this._emit("data", {data: value});
await this._renderElement(this, value);
//console.log("IUI: SetData", value, this.tagName);
await IUIElement._renderElement(this, value);
}
get data() {
@ -106,7 +101,7 @@ export default class IUIElement extends HTMLElement {
}
}
async _renderElement(element, data) {
static async _renderElement(element, data) {
if (!element.bindings) {
return;
}
@ -134,7 +129,7 @@ export default class IUIElement extends HTMLElement {
e.data = data;
//let data = e.mapData(data);
await this._renderElement(e, e.data);
await IUIElement._renderElement(e, e.data);
}
}
}
@ -183,7 +178,7 @@ export default class IUIElement extends HTMLElement {
}
create() {
//this.updateBindings();
}
destroy() {
@ -196,7 +191,7 @@ export default class IUIElement extends HTMLElement {
_make_bindings(element) {
static _make_bindings(element, isRoot = false) {
// ::Attribute
// : Field
@ -205,6 +200,10 @@ export default class IUIElement extends HTMLElement {
// @ Event
// skip element ?
if (element.hasAttribute("skip"))
return;
// tags to skip
if (element instanceof HTMLScriptElement
|| element instanceof HTMLTemplateElement)
@ -213,19 +212,22 @@ export default class IUIElement extends HTMLElement {
let bindings = [];
// compile attributes
for (var i = 0; i < element.attributes.length; i++) {
if (!isRoot)
{
// compile attributes
for (var i = 0; i < element.attributes.length; i++) {
let b = Binding.create(element.attributes[i]);
let b = Binding.create(element.attributes[i]);
if (b != null) {
if (b.type == BindingType.HTMLElementDataAttribute
|| b.type == BindingType.IUIElementDataAttribute)
element.dataMap = b;
else if (b.type == BindingType.RevertAttribute)
element.revertMap = b;
else
bindings.push(b);
if (b != null) {
if (b.type == BindingType.HTMLElementDataAttribute
|| b.type == BindingType.IUIElementDataAttribute)
element.dataMap = b;
else if (b.type == BindingType.RevertAttribute)
element.revertMap = b;
else
bindings.push(b);
}
}
}
@ -234,10 +236,10 @@ export default class IUIElement extends HTMLElement {
let e = element.childNodes[i];
if (e instanceof IUIElement) {
// @TODO: check if the IUI element handles the binding
this._make_bindings(e);
IUIElement._make_bindings(e);
}
else if (e instanceof HTMLElement) {
this._make_bindings(e);
IUIElement._make_bindings(e);
}
else if (e instanceof Text) {
let b = Binding.create(e);
@ -268,9 +270,6 @@ export default class IUIElement extends HTMLElement {
}
}
updateBindings() {
this._make_bindings(this);
}
_encapsulateEvent(code){
return `try {\r\n ${code} \r\n}\r\n catch(ex) { console.log(ex.name + ":" + ex.message, this); }`;