2
0
mirror of https://github.com/esiur/iui.git synced 2025-05-06 06:42:58 +00:00
This commit is contained in:
Ahmed Zamil 2021-11-06 14:53:52 +03:00
parent 1bac10e60d
commit 589c4f3227
31 changed files with 12721 additions and 315 deletions

7
.babelrc Normal file
View File

@ -0,0 +1,7 @@
{
"presets": [
[
"@babel/preset-env"
]
]
}

9072
build/iui.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,20 +7,19 @@
<meta charset="UTF-8" content="">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
<link rel="manifest" href="site.webmanifest">
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5">
<link rel="apple-touch-icon" sizes="180x180" href="site/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="site/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="site/favicon-16x16.png">
<link rel="manifest" href="site/site.webmanifest">
<link rel="mask-icon" href="site/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#ffc40d">
<meta name="theme-color" content="#ffffff">
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
<!--IUI 2.0 -->
<link href="../css/iui.css" rel="stylesheet" />
@ -86,6 +85,10 @@
<i-route name="declarative" caption="Declarative Rendering" :content="load(this)">
</i-route>
<i-route name="scope" caption="Scope" :content="load(this)">
</i-route>
<i-route name="data-flow" caption="Data Flow" :content="load(this)">
</i-route>
@ -96,13 +99,14 @@
<i-route name="IUI Widgets" caption="IUI Widgets">
<i-route name="IUIElement" caption="IUIElement">
<i-route name="components" caption="Components">
<i-route name="iui-element" caption="IUIElement" :content="load(this)">
</i-route>
<i-route name="repeat" caption="Repeat" :content="load(this)">
</i-route>
<i-index></i-index>
</i-route>

View File

@ -11,6 +11,6 @@ async function load(route, skip=false) {
let content = await fetch(link);
if (content.status != 200)
return "Not found " + content.url;
var md = marked(await content.text());
var md = marked.parse(await content.text());
return skip ? "<div skip>" + md + "</div>" : md;
}

View File

@ -0,0 +1,24 @@
# IUI Element
*IUIElement* is the base class for all IUI components, it extends the HTMLElement, adds more functionality and define itself as a customElement in the browser.
IuI Widgets tags start with `<i-...>` to differentiate them from the built in html tags.
# Initialization Process
When the document is loaded or new HTML is inserted in the document, IUI process of initialization start which consists of
1- IUI.create(rootElement)
create is called on every IUI element in the tree, asking these elements to create themselves, in this phase an element can add more children to itself. (**IUIElement**)
1- IUI.bind(rootElement)
IUI.bind ensures that all executable attributes starting with : are compiled and tested for data binding.
Any property that is used by the `d` variable will be a candidate for binding, which means IUI will handle any modification on that property. (**IUIElement** and **HTMLElement**)
3- IUI.created(rootElement)
Notify every IUI element that the create and bind process has ended. (**IUIElement**)
4- IUI.render(element)
Render invokes the data binding functions and sets the element text nodes and attributes to the value returned by the binding functions. The process is recursive to all children in the element tree (**IUIElement** and **HTMLElement**)
The rootElement is the first `<i-app>` in the document when its loaded.

View File

@ -0,0 +1,14 @@
# I-Repeat
`<i-repeat>` performs a an iteration on an array and builds elements according to the given list
<i-codepreview>
<i-repeat :data="['Apple', 'Orange', 'Grape']">
<div>${d}</div>
</i-repeat>
</i-codepreview>
if the iteration on a specific element is needed, *repeat* attribute must be added to the element.
*Note* each element in the iteration has an index property

View File

@ -0,0 +1,13 @@
# Scope Variables
Scope variables are provided during the rendering process to the scripts and declarative rendering functions.
These variables propagate from an element to its children and could be altered or overwritten by any element in the tree so the children of that element receive a new value for these variables.
<i-codepreview>
<div :scope="{now: new Date()}">
<div>Date: ${now.toDateString()}</div>
<div>Time: ${now.toTimeString()}</div>
</div>
</i-codepreview>

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 546 B

After

Width:  |  Height:  |  Size: 546 B

View File

Before

Width:  |  Height:  |  Size: 871 B

After

Width:  |  Height:  |  Size: 871 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

3322
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,16 @@
"test": "test"
},
"dependencies": {},
"devDependencies": {},
"devDependencies": {
"@babel/cli": "^7.16.0",
"@babel/core": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"babelify": "^10.0.0",
"browserify": "^17.0.0"
},
"scripts": {
"build": "browserify src/iui.js -t babelify --outfile build/iui.js",
"prepublish": "browserify src/iui.js -t babelify --outfile build/iui.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {

View File

@ -1,9 +1,11 @@
import IUIElement from "../Core/IUIElement.js";
import { IUI } from "../Core/IUI.js";
import RefsCollection from "./RefsCollection.js";
export default IUI.module(class App extends IUIElement {
constructor() {
super();
this.refs = new RefsCollection(this);
}
create() {
@ -11,8 +13,14 @@ export default IUI.module(class App extends IUIElement {
window.app = this;
}
created() {
IUI.bind(this, this, "/");
IUI.bind(this, this, "/", {app: this, refs: this.refs});
// update referencing
this.refs._build();
//IUIElement._make_bindings(this);
this.render();
this._emit("load", { app: this });

View File

@ -20,7 +20,7 @@ export const AttributeBindingDestination = {
const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
export class Binding {
static create(nodeOrAttributeOrIUIElement) {
static create(nodeOrAttributeOrIUIElement, scope) {
var code, isAsync, type, attrType, attrKey, func, script;
//if (nodeOrAttributeOrIUIElement.created)
@ -100,11 +100,17 @@ export class Binding {
// test the function
let scopeKeys = Object.keys(scope);
let scopeValues = Object.values(scope);
try {
let args = ["data", "d", "context", "_test",
...scopeKeys]
if (isAsync)
func = new AsyncFunction("data", "d", "context", "_test", code);
func = new AsyncFunction(...args, code);
else
func = new Function("data", "d", "context", "_test", code);
func = new Function(...args, code);
}
catch (ex) {
console.log("Test failed: " + ex, code);
@ -113,7 +119,7 @@ export class Binding {
let rt = new Binding();
Object.assign(rt, { isAsync, type, attrType, attrKey, func, target: nodeOrAttributeOrIUIElement, checked: false, script });
Object.assign(rt, { isAsync, type, attrType, attrKey, func, target: nodeOrAttributeOrIUIElement, checked: false, script, scopeKeys, scopeValues });
return rt;
}
@ -144,7 +150,9 @@ export class Binding {
let proxy = new Proxy(map, detector);
try {
let d = this.func.apply(thisArg, [proxy, proxy, {}, true]);
let d = this.func.apply(thisArg, [proxy, proxy, {}, true
, ...this.scopeKeys]);
this.map = map;
return d;
}
@ -158,9 +166,9 @@ export class Binding {
if (!this.checked)
this._findMap(thisArg);
let context = {};
var rt = this.func.apply(thisArg, [data, data, context, false]);
var rt = this.func.apply(thisArg, [data, data, context, false,
...this.scopeValues]);
//console.log(rt);
if (rt instanceof Promise)
@ -231,9 +239,12 @@ export class Binding {
try {
if (this.type === BindingType.IUIElement) {
let d = this.func.apply(this.target, [data, data]);
if (d instanceof Promise)
d = await d;
//let d = this.func.apply(this.target, [data, data]);
//if (d instanceof Promise)
// d = await d;
let d = await this._execute(this.target, data);
await this.target.setData(d);
}
else if (this.type === BindingType.TextNode) {
@ -277,8 +288,10 @@ export class Binding {
if (window?.app?.loaded)
{
await IUI.create(targetElement);
IUI.bind(targetElement, true, "content", targetElement.__i_bindings?.scope);
// update references
targetElement.__i_bindings?.scope?.refs?._build();
await IUI.created(targetElement);
IUI.bind(targetElement, targetElement, "content");
await IUI.render(targetElement, targetElement._data, true);
}
//await IUI.updateTree(targetElement);

21
src/Core/BindingList.js Normal file
View File

@ -0,0 +1,21 @@
export default class BindingList extends Array {
constructor(target, scope) {
super();
this.target = target;
this.scope = scope;
}
getArgumentsNames(){
if (this.scope == null)
return [];
let rt;
for (var i in this.scope.length)
rt.push(i);
return rt;
}
}

View File

@ -1,6 +1,7 @@
import IUIElement from "./IUIElement.js";
import { Binding, BindingType } from "./Binding.js";
//import Route from '../Router/Route.js';
import BindingList from "./BindingList.js";
export class IUI {
@ -124,13 +125,13 @@ export class IUI {
return objectClass;
}
static extend(properties, defaults, force)
static extend(properties, defaults, overwrite)
{
if (properties == null)
properties = defaults;
else
for(var i in defaults)
if (force)
if (overwrite)
properties[i] = defaults[i];
else if (properties[i] === undefined)
properties[i] = defaults[i];
@ -138,7 +139,7 @@ export class IUI {
}
static bind(element, rootElement, sourcePath){
static bind(element, skipAttributes, sourcePath, scope) {
// ::Attribute
// : Field
@ -148,6 +149,7 @@ export class IUI {
// skip element ?
if (element.hasAttribute("skip")
|| element.hasAttribute("i-skip")
|| element instanceof HTMLTemplateElement)
return;
@ -155,21 +157,37 @@ export class IUI {
//if (element instanceof HTMLScriptElement )
//return;
if (rootElement == null)
rootElement = element;
let bindings;
if (element != rootElement)
{
element.view = rootElement.view;
element.route = rootElement.route;
bindings = [];
if (scope == null)
scope = {};
// get refs before they get overwritten
//let refs = scope?.refs;
// some element extended or overwritten the binding arguments
if (element.scope != null)
IUI.extend(scope, element.scope, true);
bindings = new BindingList(element, scope);
if (skipAttributes)
{
// copy attributes bindings
if (element.__i_bindings != null)
for(var i = 0; i < element.__i_bindings.length; i++)
if (element.__i_bindings[i].type != BindingType.TextNode)
bindings.push(element.__i_bindings[i]);
}
else
{
// 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],
bindings.scope);
if (b != null) {
if (b.type == BindingType.HTMLElementDataAttribute
@ -182,37 +200,50 @@ export class IUI {
}
}
// 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 = {};
// if (element.hasAttribute("ref")) {
// let ref = element.getAttribute("ref");
// if (refs[ref] == null)
// refs[ref] = element;
// else if (refs[ref] == element){
// // do nothing
// }
// else if (refs[ref] instanceof Array){
// refs[ref].push(element);
// } else {
// var firstRef = refs[ref];
// refs[ref] =[firstRef, element];
// }
// }
}
// get new refs (scope might been overwritten)
//refs = scope?.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);
IUI.bind(el, false, sourcePath, scope);
}
else if (el instanceof HTMLElement) {
IUI.bind(el, rootElement, sourcePath);
IUI.bind(el, false, sourcePath, scope);
}
else if (el instanceof Text) {
let b = Binding.create(el);
let b = Binding.create(el, bindings.scope);
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 func = new Function("//# sourceURL=iui://" + sourcePath + "-" + Math.round(Math.random() * 10000) + "\r\n return " + el.text.trim());
let func = new Function("//# sourceURL=iui://" + sourcePath + "-" + Math.round(Math.random() * 10000) + "\r\n" + el.text.trim());
let rt = func.call(el.parentElement);
if (typeof (rt) === "object") {
@ -222,24 +253,25 @@ export class IUI {
}
}
element.bindings = bindings;
element.__i_bindings = bindings;
}
static async render(element, data, textNodesOnly = false) {
if (!element.bindings) {
if (!element.__i_bindings) {
return;
}
let bindings = element.__i_bindings;
if (textNodesOnly) {
for (var i = 0; i < element.bindings.length; i++)
if (element.bindings[i].type == BindingType.TextNode)
await element.bindings[i].render(data);
for (var i = 0; i < bindings.length; i++)
if (bindings[i].type == BindingType.TextNode)
await bindings[i].render(data);
} else {
// render attributes & text nodes
for (var i = 0; i < element.bindings.length; i++)
await element.bindings[i].render(data);
for (var i = 0; i < bindings.length; i++)
await bindings[i].render(data);
}
// render children

View File

@ -41,7 +41,6 @@ export default class IUIElement extends HTMLElement {
async render() {
await IUI.render(this, this._data);
//await IUIElement._renderElement(this, this._data);
}
_getParentData() {
@ -57,22 +56,15 @@ export default class IUIElement extends HTMLElement {
async setData(value) {
this._data = value;
this._emit("data", {data: value});
await IUIElement._renderElement(this, value);
await IUI.render(this, value);
}
get data() {
return this._data;
}
async revert(){
//if (this.revertMap != null)
//{
//if (data == undefined)
// await this.revertMap.render(this._getParentData());
//else
// await this.revertMap.render(data);
// revert parents
let e = this;
do {
@ -81,7 +73,6 @@ export default class IUIElement extends HTMLElement {
if (e.revertMap != null)
await e.revertMap.render(p?.data);
} while (e = p);
//}
}
async update(data) {
@ -101,51 +92,17 @@ export default class IUIElement extends HTMLElement {
}
}
static async _renderElement(element, data) {
if (!element.bindings) {
return;
// bindings arguments
get scope(){
return null;
}
// 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 e = element.children[i];
if (e instanceof IUIElement)
// @TODO should check if the element depends on parent or not
if (e.dataMap != null) {
// if map function failed to call setData, we will render without it
if (!(await e.dataMap.render(data)))
await e.render();
}
else
await e.setData(data);
else {
if (e.dataMap != null)
await e.dataMap.render(data);
else
e.data = data;
//let data = e.mapData(data);
await IUIElement._renderElement(e, e.data);
}
}
}
// this meant to be inherited
modified() {
}
get data() {
return this._data;
}
connectedCallback() {
if (this.hasAttribute("css-class"))
{
this.classList.add(this.getAttribute("css-class"));
@ -182,8 +139,6 @@ export default class IUIElement extends HTMLElement {
}
destroy() {
console.log("Destroy", this);
IUI.registry.splice(IUI.registry.indexOf(this), 1);
if (this.parentNode)
this.parentNode.removeChild(this);
@ -191,67 +146,6 @@ export default class IUIElement extends HTMLElement {
static _make_bindings(element, isRoot = false) {
// ::Attribute
// : Field
// async:: Async Attribute
// async: Async Field
// @ Event
// skip element ?
if (element.hasAttribute("skip"))
return;
// tags to skip
if (element instanceof HTMLScriptElement
|| element instanceof HTMLTemplateElement)
return;
let bindings = [];
if (!isRoot)
{
// 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);
}
}
}
// compile nodes
for (var i = 0; i < element.childNodes.length; i++) {
let e = element.childNodes[i];
if (e instanceof IUIElement) {
// @TODO: check if the IUI element handles the binding
IUIElement._make_bindings(e);
}
else if (e instanceof HTMLElement) {
IUIElement._make_bindings(e);
}
else if (e instanceof Text) {
let b = Binding.create(e);
if (b != null)
bindings.push(b);
}
}
element.bindings = bindings;
}
_emit(event, values) {
//var args = Array.prototype.slice.call(arguments, 1);
var e = new CustomEvent(event, values);
@ -304,13 +198,13 @@ export default class IUIElement extends HTMLElement {
}
}
off(event, fn) {
this.removeEventListener(event, fn);
off(event, func) {
this.removeEventListener(event, func);
return this;
}
on(event, fn) {
this.addEventListener(event, fn, false);
on(event, func) {
this.addEventListener(event, func, false);
return this;
}
}

View File

@ -0,0 +1,46 @@
export default class RefsCollection
{
constructor(rootElement){
this._rootElement = rootElement;
}
_build(element) {
if (element == undefined)
element = this._rootElement;
for(var i in this)
if (i != "_rootElement" && i != "_build")
delete this[i];
for(var i = 0; i < element.children.length; i++)
{
let child = element.children[i];
if (child.hasAttribute("ref"))
{
let ref = child.getAttribute("ref");
if (this[ref] == null)
this[ref] = child;
else if (this[ref] == child){
// do nothing
}
else if (this[ref] instanceof Array){
this[ref].push(child);
} else {
var firstRef = this[ref];
this[ref] =[firstRef, child];
}
}
if (child.refs != undefined)
// opt out if the element handles referencing
break;
else
this._build(child);
}
}
}

View File

@ -1,12 +1,13 @@
import IUIElement from "../Core/IUIElement.js";
import { IUI } from "../Core/IUI.js";
import RefsCollection from "../Core/RefsCollection.js";
export default IUI.module(class Include extends IUIElement
{
constructor()
{
super();
this.refs = {};
this.refs = new RefsCollection();
}
get src(){
@ -18,6 +19,11 @@ export default IUI.module(class Include extends IUIElement
this._load(value);
}
get scope() {
return {view: this, refs: this.refs};
}
async _load(url)
{
if (this._loading)
@ -42,8 +48,11 @@ export default IUI.module(class Include extends IUIElement
if (window?.app?.loaded)
{
await IUI.create(this);
IUI.bind(this, true, "include:" + src,
IUI.extend(this._i__bindings.scope, this.scope, true));
this.refs._build();
await IUI.created(this);
IUI.bind(this, this, "include:" + src);
await IUI.render(this, this._data, true);
}
@ -99,4 +108,8 @@ export default IUI.module(class Include extends IUIElement
await this._load(this.getAttribute("src"));
}
async created() {
this.refs._build();
}
});

View File

@ -53,11 +53,11 @@ export default IUI.module(class Repeat extends IUIElement
}
var newElements = this.querySelectorAll("*");
for (var i = 0; i < newElements.length; i++)
newElements[i].repeat = this;
// var newElements = this.querySelectorAll("*");
// for (var i = 0; i < newElements.length; i++)
// newElements[i].repeat = this;
var self = this;
// var self = this;
/*
this._repeatModified = function(propertyName, value)
@ -104,31 +104,6 @@ export default IUI.module(class Repeat extends IUIElement
return this._data.length;
}
_assign(node, index) {
// update fields
// this so we won't mess with i-include view
if (node.view == undefined)
node.view = this.view;
node.rotue = this.route;
node.index = index;
// update references
if (node.hasAttribute("ref"))
{
let ref = node.getAttribute("ref");
// create new array
if (!(this.view.refs[ref] instanceof Array))
this.view.refs[ref] = [];
this.view.refs[ref][index] = node;
}
//Object.assign(node, customFields);
for (var i = 0; i < node.children.length; i++)
this._assign(node.children[i], index);
}
async setData(value)
{
@ -141,18 +116,14 @@ export default IUI.module(class Repeat extends IUIElement
return false;
}
//console.log("RPT: SetData", value);
this._busy = true;
// var id = Math.random();
//console.log("SetData " + this.getAttribute("ref") + " " + id, value);
//console.trace();
// clear
this.clear();
if (value instanceof Structure)
value = value.toPairs();
if (value?.toArray instanceof Function)
value = value.toArray();
else if (value == null || !(value instanceof Array || value instanceof Int32Array))
value = [];
@ -163,100 +134,24 @@ export default IUI.module(class Repeat extends IUIElement
for (let i = 0; i < value.length; i++) {
///console.log("ST1");
//let content = this.template.content.cloneNode(true);
//let nodes = content.childNodes;
let e = this._repeatNode.cloneNode(true);
this.list.push(e);
//console.log("ST2");
// Create node
if (e instanceof IUIElement)
await e.create();
// console.log("ST3");
// Create children
//console.log("Create repeat " + i, this, e);
await IUI.create(e);
//console.log("Created repeat " + i, this, e);
IUI.bind(e, false, "repeat",
IUI.extend(this.__i_bindings?.scope,
{index: i, repeat: this}, true));
//console.log("ST4");
//this._make_bindings(e)
IUI.bind(e, this, "repeat");
this._container.insertBefore(e, this._beforeNode);
this._assign(e, i);// { view: this.view, route: this.route, index: i });
// update referencing
this.__i_bindings?.scope?.refs?._build();
await IUI.created(e);
//console.log("ST5");
if (e instanceof IUIElement) {
// @TODO should check if the element depends on parent or not
if (e.dataMap != null) {
// if map function failed to call setData, we will render without it
if (!(await e.dataMap.render(value[i])))
await e.render();
}
else{
await e.setData(value[i]);
// console.log("ST6.1");
}
}
else {
if (e.dataMap != null)
await e.dataMap.render(value[i]);
else
e.data = value[i];
// console.log("ST6.2", e);
await this._renderElement(e, e.data);
// console.log("ST6.3");
}
// if (node.dataMap != null) {
// await node.dataMap.render(value[i]);
// this._renderElement(node, node.data);
// }
// else {
// node.data = value[i];
// this._renderElement(node, node.data);
// }
/*
var newElements = content.querySelectorAll("*");
while (nodes.length > 0) {
let n = nodes[0];
//n.index = i;
if (n instanceof HTMLElement)
n.setAttribute(":data", `d[${i}]`);
this._container.appendChild(n);
}
// this has to be called after appending the child otherwise node will be HTMLElement and not IUIElement , bug maybe in webkit ?
for (var j = 0; j < newElements.length; j++) {
let el = newElements[j];
// set route for all elements
el.index = i;
el.view = this;
el.route = this.route;
//newElements[j].route = this.route;
if (el instanceof IUIElement)
el.create();
}
*/
await IUI.render(e, value[i], false);
}

View File

@ -1,6 +1,7 @@
import IUIElement from "../Core/IUIElement.js";
import { IUI } from "../Core/IUI.js";
import Router from "./Router.js";
import RefsCollection from "../Core/RefsCollection.js";
export default IUI.module(class Route extends IUIElement {
@ -8,7 +9,7 @@ export default IUI.module(class Route extends IUIElement {
super();
this.routes = [];
this.refs = {};
this.refs = new RefsCollection(this);
this._register("show");
this._register("hide");
@ -21,6 +22,10 @@ export default IUI.module(class Route extends IUIElement {
return await super.setData(value);
}
get scope(){
return {route: this, view: this};
}
_updateLinks() {
for (var i = 0; i < this.children.length; i++) {
if (this.children[i] instanceof Route) {
@ -111,9 +116,9 @@ export default IUI.module(class Route extends IUIElement {
if (window?.app?.loaded)
{
await IUI.create(this);
IUI.bind(this, true, "route:" + src, this.scope);
this.refs._build();
await IUI.created(this);
IUI.bind(this, this, "route:" + src);
await IUI.render(this, this._data, true);
}
@ -152,7 +157,7 @@ export default IUI.module(class Route extends IUIElement {
created()
{
this.refs._build();
}
set(value) {

View File

@ -1,9 +1,11 @@
import IUIElement from "../Core/IUIElement.js";
import { IUI } from "../Core/IUI.js";
import RefsCollection from "../Core/RefsCollection.js";
export default IUI.module(class CodePreview extends IUIElement {
constructor(properties) {
constructor() {
super();
this.refs = new RefsCollection(this);
}
async create() {
@ -30,7 +32,7 @@ export default IUI.module(class CodePreview extends IUIElement {
let self = this;
this.editor.addEventListener("input", function() {
self._code = self.editor.innerText.trim();
self.update();
self.updatePreview();
}, false);
this.preview = document.createElement("div");
@ -44,11 +46,18 @@ export default IUI.module(class CodePreview extends IUIElement {
this.append(this.content);
this.field = this.getAttribute("field");
await this.update();
//await this.updatePreview();
}
async created(){
await this.updatePreview();
}
async update() {
get scope(){
return {view: this, refs: this.refs};
}
async updatePreview() {
if (this._updating)
return;
@ -56,10 +65,15 @@ export default IUI.module(class CodePreview extends IUIElement {
this._updating = true;
this.preview.innerHTML = this._code;
if (window.app?.loaded)
{
await IUI.create(this.preview);
await IUI.created(this.preview);
IUI.bind(this.preview, this.preview, "preview");
IUI.bind(this.preview, true, "preview", this.scope);
this.refs._build();
await IUI.render(this.preview, this._data, true);
}
this._updating = false;
}

View File

@ -223,7 +223,7 @@ export default IUI.module(class Select extends IUIElement {
///console.log("Append", this.menu);
await this.menu.create();
IUI.bind(this.menu, this, "menu");
IUI.bind(this.menu, false, "menu");
await IUI.create(this.menu);
//this._make_bindings(this.menu);

View File

@ -909,7 +909,8 @@ export default IUI.module(class Table extends IUIElement {
//this._make_bindings(cl)
IUI.bind(cl, this, "table");
IUI.bind(cl, false, "table",
IUI.extend(this.__i_bindings, {index: i}, true));
tr.appendChild(cl);