From 67e4b5268bd46c0c08a295e3dad84dd2a5be98f1 Mon Sep 17 00:00:00 2001 From: ahmed Date: Wed, 26 Nov 2025 18:47:05 +0300 Subject: [PATCH] radio --- css/iui.css | 30 +++++++ src/Core/IUI.js | 6 +- src/Core/IUIElement.js | 1 + src/Data/Include.js | 5 +- src/Router/Router.js | 4 +- src/UI/Input.js | 1 + src/UI/Radio.js | 191 +++++++++++++++++++++++++++++++++++++++++ src/UI/Select.js | 4 +- src/iui.js | 3 + 9 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 src/UI/Radio.js diff --git a/css/iui.css b/css/iui.css index 4d7d8b6..d4fa756 100644 --- a/css/iui.css +++ b/css/iui.css @@ -2611,10 +2611,16 @@ html[dir='rtl'] .multiselect-list-remove { } +.app { + display: block; + width: 100vw; + height: 100vh; +} .router, i-router { display: block; position: relative; + height: 100%; } .route { @@ -2627,6 +2633,7 @@ html[dir='rtl'] .multiselect-list-remove { left: 10px; top: 10px; width: calc(100% - 20px); + min-height: 20px; } .route:not([selected]) { @@ -3145,3 +3152,26 @@ html[dir='rtl'] .navbar-item[level='3'] > .link { color: white; padding: 4px; } + + +.radio-repeat{ + display: flex; + gap: 10px; + border: 1px solid #dadada; + border-radius: 10px; + padding: 4px; +} + + +.radio-repeat > * +{ + border-radius: 10px; + padding: 4px; + cursor: pointer; + background: #e0e0e0; +} + +.radio-repeat > .radio-selected{ + background: #487aba; + color: white; +} diff --git a/src/Core/IUI.js b/src/Core/IUI.js index 4299023..faddf68 100644 --- a/src/Core/IUI.js +++ b/src/Core/IUI.js @@ -368,7 +368,11 @@ export class IUI { // render children for (var i = 0; i < element.children.length; i++) { let el = element.children[i]; - if (el instanceof IUIElement) { + + if (el.hasAttribute("i-skip-data")) + continue; + + 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 diff --git a/src/Core/IUIElement.js b/src/Core/IUIElement.js index a70b9c2..46b4d3f 100644 --- a/src/Core/IUIElement.js +++ b/src/Core/IUIElement.js @@ -56,6 +56,7 @@ export default class IUIElement extends HTMLElement { async setData(value, radix) { this._data = value; + this._radix = radix; this._emit("data", {data: value}); await IUI.render(this, value, false, radix); diff --git a/src/Data/Include.js b/src/Data/Include.js index 8fee5ab..910ec2f 100644 --- a/src/Data/Include.js +++ b/src/Data/Include.js @@ -49,8 +49,11 @@ export default IUI.module(class Include extends IUIElement await IUI.create(this); IUI.bind(this, true, "include:" + src, this.scope); this.refs._build(); + await IUI.created(this); - await IUI.render(this, this._data, true); + await super.setData(this._data, this._radix); + + //await IUI.render(this, this._data, true); } // // call create for the new elements diff --git a/src/Router/Router.js b/src/Router/Router.js index 0cebf18..b473825 100644 --- a/src/Router/Router.js +++ b/src/Router/Router.js @@ -285,7 +285,7 @@ export default IUI.module( } } - this._emit("created"); + this._emit("load"); // this.navigate(this.origin); //console.log("Router created", this); } @@ -328,7 +328,7 @@ export default IUI.module( this._register("navigate"); this._register("route"); - this._register("created"); + this._register("load"); } } ); diff --git a/src/UI/Input.js b/src/UI/Input.js index 68a1222..8abf99a 100644 --- a/src/UI/Input.js +++ b/src/UI/Input.js @@ -61,6 +61,7 @@ export default IUI.module( this._input = document.createElement(type == "multiline" ? "textarea" : "input"); this._input.placeholder = this.getAttribute("placeholder") || ""; + this._input.type = type; let self = this; diff --git a/src/UI/Radio.js b/src/UI/Radio.js new file mode 100644 index 0000000..7445e3f --- /dev/null +++ b/src/UI/Radio.js @@ -0,0 +1,191 @@ +import { IUI, iui } from '../Core/IUI.js'; +import IUIElement from '../Core/IUIElement.js'; +import Menu from '../UI/Menu.js'; +import Layout from '../Data/Layout.js'; +import Repeat from '../Data/Repeat.js'; + +export default IUI.module(class Radio extends IUIElement { + constructor() { + super({ + query: (x) => null, + }); + + this._register("select"); + this._register("input"); + this._register("add"); + } + + _checkValidity() { + + if (this.validate != null) { + try { + let valid = this.validate.apply(this); + if (!valid) { + this.setAttribute("invalid", ""); + this.classList.add(this.cssClass + "-invalid"); + return false; + } + else { + this.removeAttribute("invalid"); + this.classList.remove(this.cssClass + "-invalid"); + return true; + } + } + catch (ex) { + console.log("Validation Error", ex); + return false; + } + } + + return true; + } + + set hasAdd(value) { + if (value) + this.setAttribute("add", "add"); + else + this.removeAttribute("add"); + } + + get hasAdd() { + return this.hasAttribute("add"); + } + + async create() { + + this.isAuto = this.hasAttribute("auto"); + this.field = this.getAttribute("field"); + + + if (this.field != null) + { + this.setAttribute(":data", `d['${this.field}']`) + this.setAttribute(":revert", `d['${this.field}'] = this.data`); + } + + + let self = this; + + this.repeat = new Repeat(); + this.repeat.cssClass = this.cssClass + "-repeat"; + + this.repeat.on("click", async (e) => { + + if (e.target !== self.repeat) + return; + + for(let i = 0; i < self.repeat.children.length; i++) + { + let el = self.repeat.children[i]; + + if (el.contains(e.target)) + { + el.classList.add(self.cssClass + "-selected"); + await self.setData(el.data); + self._emit("input", { value: el.data }); + + } + else { + el.classList.remove(self.cssClass + "-selected"); + } + } + }); + + // get repeated item + this.repeat.innerHTML = this.innerHTML; + + this.appendChild(this.repeat); + + if (this.hasAdd) { + this._add_button = document.createElement("div"); + this._add_button.className = this.cssClass + "-add"; + this.appendChild(this._add_button); + + this._add_button.addEventListener("click", function (e) { + self._emit("add", { value: self.data }) + }); + } + + + + if (app.loaded) + { + await IUI.create(this.repeat); + + IUI.bind(this.repeat, false, "radio", this.__i_bindings?.scope, false); + // update referencing + this.__i_bindings?.scope?.refs?._build(); + + await IUI.created(this.repeat); + } + + await this._query(); + } + + get disabled() { + return this.hasAttribute("disabled"); + } + + set disabled(value) { + if (value) { + this.setAttribute("disabled", value); + } + else { + this.removeAttribute("disabled"); + } + } + + clear() { + this.response.start = 0; + this.selected = null; + } + + async _query() { + + let self = this; + let res; + + if (this.query instanceof Array) { + res = this.query; + } + else if (this.query instanceof Function) { + res = this.query(0) + if (res instanceof Promise) + res = await res; + } + + await this.repeat.setData(res); + + if (this.repeat.data.length == 0) + await self.setData(null); + } + + + async setData(value, radix) { + + // this.label.innerHTML = ""; + + await super.setData(value, radix); + + try { + //let text = this.formatter(value); + // this.label.innerHTML = text == null ? "" : text; + + this._emit("select", { value }); + } + catch (ex) { + //console.log(ex); + this._emit("select", { value }); + } + + //this._checkValidity(); + + + if (this._checkValidity() && this.isAuto) + this.revert(); + + } + + + +}); \ No newline at end of file diff --git a/src/UI/Select.js b/src/UI/Select.js index 98d1e2b..cad97db 100644 --- a/src/UI/Select.js +++ b/src/UI/Select.js @@ -108,7 +108,7 @@ export default IUI.module(class Select extends IUIElement { this.repeat = new Repeat(); - this.repeat.cssClass = "select-menu-repeat"; + this.repeat.cssClass = this.cssClass + "-menu-repeat"; //this.repeat.innerHTML = this.innerHTML; if (this.hasAttribute("menu")) { @@ -127,7 +127,7 @@ export default IUI.module(class Select extends IUIElement { this.menu.on("click", async (e) => { - if (e.target != self.textbox && e.target != self.footer && e.target !== self.menu) { + if (e.target != self.textbox && e.target != self.footer && e.target !== self.menu && e.target != self.repeat) { await self.setData(e.target.data); self._emit("input", { value: e.target.data }); diff --git a/src/iui.js b/src/iui.js index a764b1d..711d344 100644 --- a/src/iui.js +++ b/src/iui.js @@ -40,6 +40,9 @@ import "./UI/Grid.js"; import "./UI/Location.js"; import "./UI/CodePreview.js"; + +import './UI/Radio.js'; + import Modifiable from "./Data/Modifiable.js"; window.addEventListener("beforeprint", e => {