From b3479dbdbd93815f58b0c24ad5189191423177ae Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Fri, 29 Oct 2021 17:09:15 +0300 Subject: [PATCH] docs --- css/iui.css | 94 ++++++++++++- docs/android-chrome-192x192.png | Bin 0 -> 4406 bytes docs/android-chrome-512x512.png | Bin 0 -> 9686 bytes docs/apple-touch-icon.png | Bin 0 -> 3295 bytes docs/browserconfig.xml | 9 ++ docs/favicon-16x16.png | Bin 0 -> 546 bytes docs/favicon-32x32.png | Bin 0 -> 871 bytes docs/favicon.ico | Bin 0 -> 15086 bytes docs/img/logo.png | Bin 0 -> 3646 bytes docs/index.html | 112 +++++++++++++++ docs/js/docs.js | 16 +++ docs/md/getting-started.md | 17 +++ docs/md/getting-started/data-flow.md | 12 ++ docs/md/getting-started/declarative.md | 51 +++++++ docs/md/getting-started/first.md | 14 ++ docs/md/getting-started/install.md | 15 ++ docs/md/hello.md | 1 + docs/mstile-150x150.png | Bin 0 -> 3463 bytes docs/safari-pinned-tab.svg | 73 ++++++++++ docs/site.webmanifest | 19 +++ src/Core/App.js | 6 +- src/Core/Binding.js | 18 ++- src/Core/IUI.js | 188 ++++++++++++++++++++++--- src/Core/IUIElement.js | 55 ++++---- src/Data/Include.js | 77 +++++----- src/Data/Repeat.js | 7 +- src/Router/Route.js | 78 ++++++---- src/UI/CodePreview.js | 68 +++++++++ src/UI/Location.js | 39 +++++ src/UI/Select.js | 30 +--- src/UI/TabbedTarget.js | 8 +- src/UI/Table.js | 5 +- src/UI/Tabs.js | 8 +- src/UI/Window.js | 1 - src/iui.js | 2 + 35 files changed, 857 insertions(+), 166 deletions(-) create mode 100644 docs/android-chrome-192x192.png create mode 100644 docs/android-chrome-512x512.png create mode 100644 docs/apple-touch-icon.png create mode 100644 docs/browserconfig.xml create mode 100644 docs/favicon-16x16.png create mode 100644 docs/favicon-32x32.png create mode 100644 docs/favicon.ico create mode 100644 docs/img/logo.png create mode 100644 docs/index.html create mode 100644 docs/js/docs.js create mode 100644 docs/md/getting-started.md create mode 100644 docs/md/getting-started/data-flow.md create mode 100644 docs/md/getting-started/declarative.md create mode 100644 docs/md/getting-started/first.md create mode 100644 docs/md/getting-started/install.md create mode 100644 docs/md/hello.md create mode 100644 docs/mstile-150x150.png create mode 100644 docs/safari-pinned-tab.svg create mode 100644 docs/site.webmanifest create mode 100644 src/UI/CodePreview.js create mode 100644 src/UI/Location.js diff --git a/css/iui.css b/css/iui.css index 274a520..fae6bbd 100644 --- a/css/iui.css +++ b/css/iui.css @@ -2778,7 +2778,7 @@ html[dir='rtl'] .multiselect-list-remove { margin: 6px; background-image: var(--search); background-repeat: no-repeat; - background-size: 25px; + background-size: 19px; background-position: 2px 50%; padding-left: 30px; } @@ -2797,12 +2797,31 @@ html[dir='rtl'] .multiselect-list-remove { transition: max-height ease-in-out 0.3s; } +.navbar-item[level='1'] { + padding-left: 10px; +} + +html[dir='rtl'] .navbar-item[level='1'] { + padding-right: 10px; + padding-left: unset; +} + + .navbar-container { overflow: auto; visibility: hidden; } +.navbar-item > i-link +{ + display: flex; + padding: 3px 10px; +} + +.navbar-item > i-link > span { + flex: 1; +} .navbar i-link > span > span, .sitebar i-link > span > span @@ -2812,6 +2831,9 @@ html[dir='rtl'] .multiselect-list-remove { font-weight: bold; } + + + .navbar-container::-webkit-scrollbar { width: 6px; height: 6px; @@ -2879,7 +2901,14 @@ html[dir='rtl'] .multiselect-list-remove { .navbar-container i-check { - width: 42px; + width: 26px; + background-image: var(--arrow-left); + background-position: 0px 48%; + background-repeat: no-repeat; + border-radius: 10px; +} + + /* width: 42px; background-image: var(--arrow-left); background-position: 0px 48%; background-repeat: no-repeat; @@ -2888,8 +2917,8 @@ html[dir='rtl'] .multiselect-list-remove { align-self: stretch; background-color: #d6d6d6; border-top-left-radius: 10px; - border-bottom-left-radius: 10px; -} + border-bottom-left-radius: 10px; */ + .sitebar-container i-check { @@ -3009,3 +3038,60 @@ html[dir='rtl'] .multiselect-list-remove { transform-origin: right; } + + +.location +{ + display: flex; + gap: 10px; + align-items: center; +} + +.location > i-link +{ + text-decoration: underline; +} + +.location > span::after +{ + content: '/'; +} + +.codepreview +{ + display: flex; + flex-flow: column; + border: 1px solid #c2c2c2; + padding: 10px; + margin: 10px; + background: #f8f8f8; + border-left: 4px solid #4ebeec; +} + +.codepreview-content +{ + display: flex; +} + +.codepreview-editor +{ + background: #e8e8e8; + padding: 10px; + + border-top-left-radius: 10px; + border-bottom-left-radius: 10px; + flex: 1; +} + +.codepreview-preview{ + flex: 1; + background: white; + border-top-right-radius: 10px; + border-bottom-right-radius: 10px; + padding: 10px; +} + +.codepreview-bar +{ + +} \ No newline at end of file diff --git a/docs/android-chrome-192x192.png b/docs/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..42282762b9cb0d068f3cb7d21225b5c09e8b58a7 GIT binary patch literal 4406 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 Cfl7M- literal 0 HcmV?d00001 diff --git a/docs/android-chrome-512x512.png b/docs/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..4615796f6efcc556225e081a61e52ad7de0be796 GIT binary patch literal 9686 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 literal 0 HcmV?d00001 diff --git a/docs/apple-touch-icon.png b/docs/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6177efef3c23ceae413eb35abe46a84361a95aa7 GIT binary patch literal 3295 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 SQa + + + + + #ffc40d + + + diff --git a/docs/favicon-16x16.png b/docs/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..764867c486cb1443a897de7761026be997ac2d0f GIT binary patch literal 546 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

PZ&?##pmfmu+Fymw)m)^Nhs4?vm8fA9q&@{Xp znWDqQ)0C}?fk=b(J=K98IU#IB>R zH{5pb;nT@+$(oSj_0|KROCp2b5@)(TgCfnk`HM`nmIOIlgNcg3m{k(xZ4(9vaeL$s z#*cQ^fx%tz;nQnkv8K<8G%8UTEn!p_q zvhIIL}iNXFj(a*H^v*-7^kmv9NQ@+hTGW3%amd?Ivsb+_^S}cu68j!-7rwcdyY1=gMzpe+iN2D!w0}sm2#M%HZ-Xw>Zd3`oaaA;n+TjU zlD@pCa{o4@{@m+6d#QqDUp6Ipx%i znYHv{eGf@%S|>k#T)*FMmzP9U%G?T#lK92^j(RjF`m4I=dch`X5QlS_Qd>cGkICL7 z_2O_YNggjWn-8IL4ZdqJ+2E)O6q;cCmXI4I{{22?!QDSUI+xy_Jk(B`PdObSy47m^gU57f>aae*z$r_?kgoJwLpZyJ z51a;~b@k0MrAM{)S0Asmy`sC>IJBqWQ()8Wi!PBX>F$#cCmuQNed0`Xd6KL7aYM~2 zsUvO7FYOq=t5pJXEcdnBeVK`U`LoI9XIONiUH@_r@S>c?c8nSqObEam5pS$;4+{#b ziy3;bV`zIQD=xf}*XZ}nePOQNGRO4`7rEoC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+
+ +

Docs

+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + Getting started + + + + + + + + + + +
+ + + diff --git a/docs/js/docs.js b/docs/js/docs.js new file mode 100644 index 0000000..ff61c07 --- /dev/null +++ b/docs/js/docs.js @@ -0,0 +1,16 @@ + + +marked.setOptions({ + highlight: function(code, lang) { + return hljs.highlight(lang, code).value; + } +}); + +async function load(route) { + var link = "md/" + route.link + ".md"; + let content = await fetch(link); + if (content.status != 200) + return "Not found " + content.url; + var md = marked(await content.text()); + return md; +} \ No newline at end of file diff --git a/docs/md/getting-started.md b/docs/md/getting-started.md new file mode 100644 index 0000000..1a30f42 --- /dev/null +++ b/docs/md/getting-started.md @@ -0,0 +1,17 @@ +# Compatibility +IUI depends on Web Components (customElement) to render its widgets. + +*PC* + +| Chrome | Firefox | Edge | IE | Opera | Safari | +|:------:|:--------|:----:|:--:|:-----:|--------| +| 54 | 79 | 63 | No | 41 | 10.1 | + ------------------------------------------------ + +*Mobile* + +| Android WebView | Chrome Android | Firefox Android | Safari iOS | Samsung Internet | +| :--------------: | :-------------:| :--------------:|:----------:| :--------------: | +| 54 | 54 | 63 | 10.3 | 6.0 | + ------------------------------------------------------------------------------------- + diff --git a/docs/md/getting-started/data-flow.md b/docs/md/getting-started/data-flow.md new file mode 100644 index 0000000..64bc12c --- /dev/null +++ b/docs/md/getting-started/data-flow.md @@ -0,0 +1,12 @@ +# Data flow + +When the :data attribute is set to an element any other attribute and child will be able to access this field directly using the variable *data* or the shortended *d*. + + + +
+ My name is ${d.name} and I work as a ${d.job}. +
+
+ + \ No newline at end of file diff --git a/docs/md/getting-started/declarative.md b/docs/md/getting-started/declarative.md new file mode 100644 index 0000000..c6f0f49 --- /dev/null +++ b/docs/md/getting-started/declarative.md @@ -0,0 +1,51 @@ +# Declarative Rendering + +# Text nodes +Text nodes are enclosed with `${...}` + + ${ navigator.userAgent } + + +# Fields + starts with `:` + + + + +# Attributes + starts with `::` + + + + +# Asynchronous + +*Promise* +Promises are automatically resolved. + + + ${fetch("md/hello.md")} + + +*Await* +To use await in text nodes **async** attribute must be added to the parent element + + + +
+ ${await (await fetch("md/hello.md")).text()} +
+
+ +In attributes, the attribute name must be preceded with **async:** + + + + + +Attributes are similar they must start with *async::* + + + + + \ No newline at end of file diff --git a/docs/md/getting-started/first.md b/docs/md/getting-started/first.md new file mode 100644 index 0000000..6e8785d --- /dev/null +++ b/docs/md/getting-started/first.md @@ -0,0 +1,14 @@ + +```html + + + + + + + + Current time: ${new Date()} + + + +``` \ No newline at end of file diff --git a/docs/md/getting-started/install.md b/docs/md/getting-started/install.md new file mode 100644 index 0000000..0fa9515 --- /dev/null +++ b/docs/md/getting-started/install.md @@ -0,0 +1,15 @@ + +NPM + +```html +npm install @esiur/iui +``` + +Include in web page + +# +```html + + +``` + diff --git a/docs/md/hello.md b/docs/md/hello.md new file mode 100644 index 0000000..1c8a3a1 --- /dev/null +++ b/docs/md/hello.md @@ -0,0 +1 @@ +Hello World ! \ No newline at end of file diff --git a/docs/mstile-150x150.png b/docs/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..a5dfe497fa431778780ab98a7cbb2462db36104a GIT binary patch literal 3463 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 + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + + + diff --git a/docs/site.webmanifest b/docs/site.webmanifest new file mode 100644 index 0000000..b20abb7 --- /dev/null +++ b/docs/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/src/Core/App.js b/src/Core/App.js index 4718183..f927179 100644 --- a/src/Core/App.js +++ b/src/Core/App.js @@ -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; } - - }); \ No newline at end of file diff --git a/src/Core/Binding.js b/src/Core/Binding.js index 6ab76e5..f177c62 100644 --- a/src/Core/Binding.js +++ b/src/Core/Binding.js @@ -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) { diff --git a/src/Core/IUI.js b/src/Core/IUI.js index 4349302..9106143 100644 --- a/src/Core/IUI.js +++ b/src/Core/IUI.js @@ -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) diff --git a/src/Core/IUIElement.js b/src/Core/IUIElement.js index ed1aadb..16a16dc 100644 --- a/src/Core/IUIElement.js +++ b/src/Core/IUIElement.js @@ -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); }`; diff --git a/src/Data/Include.js b/src/Data/Include.js index 4299903..4708711 100644 --- a/src/Data/Include.js +++ b/src/Data/Include.js @@ -39,43 +39,56 @@ export default IUI.module(class Include extends IUIElement //let xeval = (code) => eval(code); - // call create for the new elements - var newElements = this.querySelectorAll("*"); - for (var i = 0; i < newElements.length; i++) { - var el = newElements[i]; - - // set route for all elements - //newElements[i].route = this.route; - el.route = this.route; - el.view = this; - if (el.hasAttribute("ref")) { - this.refs[el.getAttribute("ref")] = el; - } - - if (el instanceof HTMLScriptElement) { - // this because HTML parser don't evaluate script tag - let func = new Function("//# sourceURL=iui://" + src + "-" + Math.round(Math.random() * 10000) + "\r\n return " + el.text.trim());// "return " + el.text + ";"); - - let rt = func.call(el.parentElement); - - //let rt = xeval.call(el.parentElement, "//# sourceURL=iui://" + src + Math.round(Math.random() * 10000) + "\r\n (" + el.text + ")"); - if (typeof (rt) === "object") { - for (var k in rt) - el.parentElement[k] = rt[k]; - } - } + if (window?.app?.loaded) + { + await IUI.create(this); + await IUI.created(this); + IUI.bind(this, this, "include:" + src); + await IUI.render(this, this._data, true); } + + // // call create for the new elements + // var newElements = this.querySelectorAll("*"); + // for (var i = 0; i < newElements.length; i++) { + // var el = newElements[i]; + + // // set route for all elements + // //newElements[i].route = this.route; + // el.route = this.route; + // el.view = this; + // if (el.hasAttribute("ref")) { + // this.refs[el.getAttribute("ref")] = el; + // } + + // if (el instanceof HTMLScriptElement) { + // // this because HTML parser don't evaluate script tag + // let func = new Function("//# sourceURL=iui://" + src + "-" + Math.round(Math.random() * 10000) + "\r\n return " + el.text.trim());// "return " + el.text + ";"); + + // let rt = func.call(el.parentElement); + + // //let rt = xeval.call(el.parentElement, "//# sourceURL=iui://" + src + Math.round(Math.random() * 10000) + "\r\n (" + el.text + ")"); + // if (typeof (rt) === "object") { + // for (var k in rt) + // el.parentElement[k] = rt[k]; + // } + // } + // } } this.classList.remove(this.cssClass + "-loading"); - if (window?.app?.loaded) - { - await IUI.create(this); - await IUI.created(this); - this.updateBindings(); - await this.render(); - } + // if (window?.app?.loaded) + // { + // await IUI.create(this); + // await IUI.created(this); + + // for(let i = 0; i < this.children.length; i++) + // { + // let el = this.children[i]; + // IUIElement._make_bindings(el); + // await IUIElement._renderElement(el, el._data); + // } + // } this._loading = false; } diff --git a/src/Data/Repeat.js b/src/Data/Repeat.js index ae2112f..46fb194 100644 --- a/src/Data/Repeat.js +++ b/src/Data/Repeat.js @@ -190,7 +190,8 @@ export default IUI.module(class Repeat extends IUIElement //console.log("ST4"); - this._make_bindings(e) + //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 }); @@ -260,9 +261,7 @@ export default IUI.module(class Repeat extends IUIElement } - //super._uiBindings = null; - //super.updateBindings(); - + // @TODO: check if this works for event names starting with ":" this._emit(":data", { data: value }); // this._emit("modified", { data: value, property: "data" }); diff --git a/src/Router/Route.js b/src/Router/Route.js index 0317db1..4fb6825 100644 --- a/src/Router/Route.js +++ b/src/Router/Route.js @@ -80,6 +80,13 @@ export default IUI.module(class Route extends IUIElement { return null; } + // get route() { + // return this; + // } + + // get view() { + // return this; + // } async create() { @@ -100,41 +107,52 @@ export default IUI.module(class Route extends IUIElement { //let xeval = (code) => eval(code); } - // call create for the new elements - var newElements = this.querySelectorAll("*"); - for (var i = 0; i < newElements.length; i++) { - // set route for all elements - var el = newElements[i]; - // newElements[i].route = this; - el.view = this; - el.route = this; - if (el.hasAttribute("ref")) { - this.refs[el.getAttribute("ref")] = el; - } + if (window?.app?.loaded) + { + await IUI.create(this); + await IUI.created(this); + IUI.bind(this, this, "route:" + src); - if (el instanceof HTMLScriptElement) { - // this because HTML parsers don't evaluate script tag - // xeval.call(el.parentElement, "//# sourceURL=iui://" + src + "\r\n" + el.text); - - //let func = new Function("//# sourceURL=iui://" + - // src + "-" + Math.round(Math.random() * 10000) + "\r\n return " + el.text.trim()); - - let func = new Function("//# sourceURL=iui://" + this.link - + "\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]; - } - } + await IUI.render(this, this._data, true); } + + // // call create for the new elements + // var newElements = this.querySelectorAll("*"); + // for (var i = 0; i < newElements.length; i++) { + // // set route for all elements + // var el = newElements[i]; + // // newElements[i].route = this; + // el.view = this; + // el.route = this; + + // if (el.hasAttribute("ref")) { + // this.refs[el.getAttribute("ref")] = el; + // } + + // if (el instanceof HTMLScriptElement) { + // // this because HTML parsers don't evaluate script tag + // // xeval.call(el.parentElement, "//# sourceURL=iui://" + src + "\r\n" + el.text); + + // //let func = new Function("//# sourceURL=iui://" + + // // src + "-" + Math.round(Math.random() * 10000) + "\r\n return " + el.text.trim()); + + // let func = new Function("//# sourceURL=iui://" + this.link + // + "\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]; + // } + // } + // } } - created() { - //this.updateBindings(); + created() + { + } set(value) { diff --git a/src/UI/CodePreview.js b/src/UI/CodePreview.js new file mode 100644 index 0000000..e699b99 --- /dev/null +++ b/src/UI/CodePreview.js @@ -0,0 +1,68 @@ +import IUIElement from "../Core/IUIElement.js"; +import { IUI } from "../Core/IUI.js"; + +export default IUI.module(class CodePreview extends IUIElement { + constructor(properties) { + super(); + } + + async create() { + + + + if (this.hasAttribute("debug")) + debugger; + + this._code = this.innerHTML; + this.textContent = ''; + + // create elements + this.bar = document.createElement("div"); + this.bar.className = this.cssClass + "-bar"; + this.content = document.createElement("div"); + this.content.className = this.cssClass + "-content"; + this.editor = document.createElement("code"); + this.editor.className = this.cssClass + "-editor"; + + this.editor.innerText = this._code; + this.editor.contentEditable = true; + + this.editor.setAttribute("skip", true); + + let self = this; + this.editor.addEventListener("input", function() { + self._code = self.editor.innerText; + self.update(); + }, false); + + this.preview = document.createElement("div"); + this.preview.className = this.cssClass + "-preview"; + //this.preview.setAttribute(":content", ""); + + this.content.append(this.editor); + this.content.append(this.preview); + + this.append(this.bar); + this.append(this.content); + this.field = this.getAttribute("field"); + + await this.update(); + } + + + async update() { + + if (this._updating) + return; + + this._updating = true; + this.preview.innerHTML = this._code; + + await IUI.create(this.preview); + await IUI.created(this.preview); + IUI.bind(this.preview, this.preview, "preview"); + await IUI.render(this.preview, this._data, true); + + this._updating = false; + } +}); \ No newline at end of file diff --git a/src/UI/Location.js b/src/UI/Location.js new file mode 100644 index 0000000..5e79073 --- /dev/null +++ b/src/UI/Location.js @@ -0,0 +1,39 @@ + +import IUIElement from "../Core/IUIElement.js"; +import { IUI } from "../Core/IUI.js"; +import Link from '../Router/Link.js'; + +export default IUI.module(class Location extends IUIElement { + constructor() { + super(); + } + + create() { + let self = this; + window.router.on("route", (e) => { + + self.textContent = ''; // clear everything + + + let html = ""; + let route = e.route; + + var current = document.createElement("div"); + current.innerHTML = route.caption; + + self.append(current); + + while (route = route.parent) { + + var sep = document.createElement("span"); + self.prepend(sep); + + let link = new Link(); + link.link = route.link; + link.innerHTML = route.caption; + + self.prepend(link); + } + }); + } +}); \ No newline at end of file diff --git a/src/UI/Select.js b/src/UI/Select.js index ed235a2..21e01a8 100644 --- a/src/UI/Select.js +++ b/src/UI/Select.js @@ -220,10 +220,13 @@ export default IUI.module(class Select extends IUIElement { app.appendChild(this.menu); if (app.loaded) { + ///console.log("Append", this.menu); await this.menu.create(); + IUI.bind(this.menu, this, "menu"); await IUI.create(this.menu); - this._make_bindings(this.menu); + + //this._make_bindings(this.menu); } } @@ -313,30 +316,7 @@ export default IUI.module(class Select extends IUIElement { await this.menu.setData(res); - // show results - //self.menu.clear(); - - - - // for (var i = 0; i < res.length; i++) { - // let nodes = this.template.content.cloneNode(true).childNodes; - - // while (nodes.length > 0) { - // let n = nodes[0]; - // if (n instanceof HTMLElement) - // n.setAttribute(":data", `d[${i}]`); - // self.menu.appendChild(n); - // } - - // } - - // self.menu.updateBindings(); - //self.menu.setData(res); - - - //}).catch(x => { - - //}); + } diff --git a/src/UI/TabbedTarget.js b/src/UI/TabbedTarget.js index 33e01f2..b357ed1 100644 --- a/src/UI/TabbedTarget.js +++ b/src/UI/TabbedTarget.js @@ -131,9 +131,7 @@ export default IUI.module(class TabbedTarget extends Target { this._body.append(item); - //this._bar.appendChild(label); - //this._bar.insertAdjacentElement("afterBegin", label); - + this.list.push(item); var self = this; label.on("check", function (v) { @@ -141,9 +139,7 @@ export default IUI.module(class TabbedTarget extends Target { self.select(item); }); - //this._updateSize(); - //this.updateBindings(); - + if (item.selected) this.select(item); diff --git a/src/UI/Table.js b/src/UI/Table.js index 0a4c5b5..a139d99 100644 --- a/src/UI/Table.js +++ b/src/UI/Table.js @@ -907,7 +907,10 @@ export default IUI.module(class Table extends IUIElement { let cl = column.node.cloneNode(true);// tr.insertCell(); - this._make_bindings(cl) + //this._make_bindings(cl) + + IUI.bind(cl, this, "table"); + tr.appendChild(cl); if (cl.dataMap != null) diff --git a/src/UI/Tabs.js b/src/UI/Tabs.js index 0ddc5e6..9fe089a 100644 --- a/src/UI/Tabs.js +++ b/src/UI/Tabs.js @@ -132,9 +132,7 @@ export default IUI.module(class Tabs extends IUIElement { this._body.append(item); - //this._bar.appendChild(label); - //this._bar.insertAdjacentElement("afterBegin", label); - + this.list.push(item); var self = this; label.on("check", function (v) { @@ -142,9 +140,7 @@ export default IUI.module(class Tabs extends IUIElement { self.select(item); }); - //this._updateSize(); - //this.updateBindings(); - + if (item.selected) this.select(item); diff --git a/src/UI/Window.js b/src/UI/Window.js index 116eac2..d8aeefb 100644 --- a/src/UI/Window.js +++ b/src/UI/Window.js @@ -42,7 +42,6 @@ export default IUI.module(class IUIWindow extends IUIElement { this.insertAdjacentElement("afterBegin", this._body); - //super.updateBindings(); } else this._body = b[0]; diff --git a/src/iui.js b/src/iui.js index 8cc855e..a38f323 100644 --- a/src/iui.js +++ b/src/iui.js @@ -38,6 +38,8 @@ import './UI/Select.js'; import './UI/DropDown.js'; import './UI/Grid.js'; +import './UI/Location.js'; +import './UI/CodePreview.js'; window.addEventListener("beforeprint", (e)=>{ let viewRoute = router.current.viewRoute;