@xuda.io/runtime-bundle 1.0.1247 → 1.0.1249

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2675,11 +2675,6 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
2675
2675
  };
2676
2676
 
2677
2677
  func.common.sha256 = async function (inputString) {
2678
- // const enc = new TextEncoder();
2679
- // const buf = await crypto.subtle.digest('SHA-256', enc.encode(str));
2680
- // const bytes = new Uint8Array(buf);
2681
- // return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');
2682
-
2683
2678
  // 1. Create a hash buffer from the input string using SHA-256.
2684
2679
  // This part remains the same as it provides a strong, unique cryptographic starting point.
2685
2680
  const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputString));
@@ -12169,469 +12164,1357 @@ const get_params_obj_new = async function (SESSION_ID, prog_id, nodeP, dsSession
12169
12164
  return { params_res, params_raw };
12170
12165
  };
12171
12166
 
12172
- func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, xu_func, $elm, val, is_init, refreshed_ds) {
12173
- if (is_skeleton) return;
12167
+ // func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, xu_func, $elm, val, is_init, refreshed_ds) {
12168
+ // if (is_skeleton) return;
12169
+
12170
+ // // console.log(nodeP.id, xu_func, val);
12171
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12172
+ // const tag_fx = {
12173
+ // [`xu-panel`]: {
12174
+ // program: async function ($elm, val) {
12175
+ // var ret = {};
12176
+ // var _session = SESSION_OBJ[SESSION_ID];
12177
+ // var _ds = _session.DS_GLB[paramsP.dsSessionP];
12178
+ // const init_program = async function () {
12179
+ // async function render_panel() {
12180
+ // const prog_id = val.value?.prog || val.value;
12181
+ // const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
12182
+ // let ret_panel = await func.UI.screen.init(SESSION_ID, prog_id, paramsP.screenId, _ds, $elm, null, _ds.currentRecordId, null, true, params_obj.params_res, 'initXu_panel', undefined, prog_id !== _ds.prog_id ? null : refreshed_ds, params_obj.params_raw);
12183
+ // ret = { $new_div: ret_panel };
12184
+ // if ($container.data().xuData) {
12185
+ // $container.data().xuData.xuPanelProps = $elm.data().xuAttributes;
12186
+ // $container.data().xuData.xuPanelData = ret_panel.data();
12187
+ // }
12188
+ // return ret;
12189
+ // }
12174
12190
 
12175
- // console.log(nodeP.id, xu_func, val);
12176
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12177
- const tag_fx = {
12178
- [`xu-panel`]: {
12179
- program: async function ($elm, val) {
12180
- var ret = {};
12181
- var _session = SESSION_OBJ[SESSION_ID];
12182
- var _ds = _session.DS_GLB[paramsP.dsSessionP];
12183
- const init_program = async function () {
12184
- async function render_panel() {
12185
- const prog_id = val.value?.prog || val.value;
12186
- const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
12187
- let ret_panel = await func.UI.screen.init(SESSION_ID, prog_id, paramsP.screenId, _ds, $elm, null, _ds.currentRecordId, null, true, params_obj.params_res, 'initXu_panel', undefined, prog_id !== _ds.prog_id ? null : refreshed_ds, params_obj.params_raw);
12188
- ret = { $new_div: ret_panel };
12189
- if ($container.data().xuData) {
12190
- $container.data().xuData.xuPanelProps = $elm.data().xuAttributes;
12191
- $container.data().xuData.xuPanelData = ret_panel.data();
12192
- }
12193
- return ret;
12194
- }
12191
+ // if (!val.value) {
12192
+ // val.value = '_empty_panel_program';
12193
+ // }
12195
12194
 
12196
- if (!val.value) {
12197
- val.value = '_empty_panel_program';
12198
- }
12195
+ // ret = await render_panel();
12199
12196
 
12200
- ret = await render_panel();
12197
+ // return ret;
12198
+ // };
12199
+ // const alter_program = async function () {
12200
+ // var _session = SESSION_OBJ[SESSION_ID];
12201
+ // var _ds = _session.DS_GLB[paramsP.dsSessionP];
12202
+
12203
+ // /////////////////
12204
+ // async function render_panel() {
12205
+ // // // if (!cache_str) {
12206
+ // // // await update_container(screen_ready_function);
12207
+ // // // }
12208
+ // // // if (cache_str && !CACHE_PROG_UI[cache_str]) {
12209
+ // // // await update_container(screen_ready_function);
12210
+ // // // save_cache();
12211
+ // // // }
12212
+ // // // if (callback) callback($div);
12213
+ // // // $container.data().xuData.node.children =
12214
+ // // // $div.data().xuData.node.children;
12215
+ // // // //swiper-wrapper
12216
+ // // // var restore_slides_elements = async function () {
12217
+ // // // if ($tmp_div.children().length) {
12218
+ // // // $tmp_div
12219
+ // // // .find(".swiper-wrapper")
12220
+ // // // .empty()
12221
+ // // // .append($new_div.children());
12222
+ // // // $new_div.append($tmp_div.children());
12223
+ // // // }
12224
+ // // // };
12225
+ // // // // console.log($tmp_div);
12226
+ // // // await restore_slides_elements();
12227
+ // // // // CHANGE_PANEL_BUSY = false;
12228
+ // // // func.events.delete_job(SESSION_ID, jobNo);
12229
+ // // };
12230
+ // const program = val.value?.prog || val.value;
12231
+ // var $wrapper = $('<div>');
12232
+ // var $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, nodeP.attributes, null, null, null, $wrapper, '');
12233
+ // const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
12234
+ // let ret_init = await func.UI.screen.init(SESSION_ID, program, paramsP.screenId, _ds, $div, null, _ds.currentRecordId, jobNoP, true, params_obj.params_res, 'alterXu_panel', undefined, undefined, params_obj.params_raw);
12235
+ // ret = {
12236
+ // $new_div: ret_init,
12237
+ // abort: true,
12238
+ // };
12239
+ // await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, $new_div, nodeP, $div.clone(true), jobNoP);
12240
+
12241
+ // return ret;
12242
+ // }
12243
+ // if (!val.value) {
12244
+ // return { abort: true };
12245
+ // }
12246
+ // await render_panel();
12247
+ // return ret;
12248
+ // };
12201
12249
 
12202
- return ret;
12203
- };
12204
- const alter_program = async function () {
12205
- var _session = SESSION_OBJ[SESSION_ID];
12206
- var _ds = _session.DS_GLB[paramsP.dsSessionP];
12250
+ // if (is_init) {
12251
+ // let ret = await init_program();
12252
+ // return ret;
12253
+ // }
12254
+ // return alter_program();
12255
+ // },
12207
12256
 
12208
- /////////////////
12209
- async function render_panel() {
12210
- // // if (!cache_str) {
12211
- // // await update_container(screen_ready_function);
12212
- // // }
12213
- // // if (cache_str && !CACHE_PROG_UI[cache_str]) {
12214
- // // await update_container(screen_ready_function);
12215
- // // save_cache();
12216
- // // }
12217
- // // if (callback) callback($div);
12218
- // // $container.data().xuData.node.children =
12219
- // // $div.data().xuData.node.children;
12220
- // // //swiper-wrapper
12221
- // // var restore_slides_elements = async function () {
12222
- // // if ($tmp_div.children().length) {
12223
- // // $tmp_div
12224
- // // .find(".swiper-wrapper")
12225
- // // .empty()
12226
- // // .append($new_div.children());
12227
- // // $new_div.append($tmp_div.children());
12228
- // // }
12229
- // // };
12230
- // // // console.log($tmp_div);
12231
- // // await restore_slides_elements();
12232
- // // // CHANGE_PANEL_BUSY = false;
12233
- // // func.events.delete_job(SESSION_ID, jobNo);
12234
- // };
12235
- const program = val.value?.prog || val.value;
12236
- var $wrapper = $('<div>');
12237
- var $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, nodeP.attributes, null, null, null, $wrapper, '');
12238
- const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
12239
- let ret_init = await func.UI.screen.init(SESSION_ID, program, paramsP.screenId, _ds, $div, null, _ds.currentRecordId, jobNoP, true, params_obj.params_res, 'alterXu_panel', undefined, undefined, params_obj.params_raw);
12240
- ret = {
12241
- $new_div: ret_init,
12242
- abort: true,
12243
- };
12244
- await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, $new_div, nodeP, $div.clone(true), jobNoP);
12257
+ // 'xu-render': async function ($elm, val) {
12258
+ // let ret = await common_fx['xu-render']($elm, val, true);
12259
+ // return ret;
12260
+ // },
12261
+ // 'xu-ref': async function ($elm, val) {
12262
+ // let ret = await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
12263
+ // return ret;
12264
+ // },
12265
+ // },
12266
+ // [`xu-teleport`]: {
12267
+ // to: async function ($elm, val) {
12268
+ // if (!glb.new_xu_render) {
12269
+ // if (val.value) {
12270
+ // // parent_infoP.is_xu_teleport;
12271
+ // if ($elm?.parent()?.data()?.xuData?.length) {
12272
+ // $elm.parent().data('xuTeleportData', []);
12273
+ // for (const [key, node] of Object.entries(nodeP.children)) {
12274
+ // const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $(val.value), node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12275
+
12276
+ // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12277
+ // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
12278
+ // }
12279
+ // $elm.remove();
12280
+ // } else {
12281
+ // $elm.data('xuTeleportData', []).attr('hidden', true);
12282
+ // for (const [key, node] of Object.entries(nodeP.children)) {
12283
+ // const $to_container = $(val.value);
12284
+ // if (!$to_container?.length) {
12285
+ // return console.error(`container ${val.value} for xuTeleportData not found`);
12286
+ // }
12287
+ // const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $to_container, node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12288
+
12289
+ // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12290
+ // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
12291
+ // }
12292
+ // }
12293
+ // }
12294
+ // return { abort: true };
12295
+ // }
12245
12296
 
12246
- return ret;
12247
- }
12248
- if (!val.value) {
12249
- return { abort: true };
12250
- }
12251
- await render_panel();
12252
- return ret;
12253
- };
12297
+ // if (val.value) {
12298
+ // // // parent_infoP.is_xu_teleport;
12299
+ // // if ($elm?.parent()?.data()?.xuData?.length) {
12300
+ // // $elm.parent().data('xuTeleportData', []);
12301
+ // // for (const [key, node] of Object.entries(nodeP.children)) {
12302
+ // // const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $(val.value), node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12303
+ // // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12304
+ // // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
12305
+ // // }
12306
+ // // $elm.remove();
12307
+ // // } else {
12308
+ // // $elm.data('xuTeleportData', []).attr('hidden', true);
12309
+ // // for (const [key, node] of Object.entries(nodeP.children)) {
12310
+ // // const $to_container = $(val.value);
12311
+ // // if (!$to_container?.length) {
12312
+ // // return console.error(`container ${val.value} for xuTeleportData not found`);
12313
+ // // }
12314
+ // // const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $to_container, node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12315
+ // // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12316
+ // // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
12317
+ // // }
12318
+ // // }
12319
+ // }
12320
+ // return {};
12321
+ // },
12322
+ // 'xu-render': async function ($elm, val) {
12323
+ // let ret = await common_fx['xu-render']($elm, val, true);
12324
+ // return ret;
12325
+ // },
12326
+ // 'xu-show': async function ($elm, val) {
12327
+ // let ret = await common_fx['xu-show']($elm, val, true);
12328
+ // return ret;
12329
+ // },
12330
+ // },
12331
+ // };
12254
12332
 
12255
- if (is_init) {
12256
- let ret = await init_program();
12257
- return ret;
12258
- }
12259
- return alter_program();
12260
- },
12333
+ // const load_cdn = async function (resource) {
12334
+ // // console.log("loading cdn", resource);
12335
+ // if (!_.isObject(resource) && _.isString(resource)) {
12336
+ // resource = { src: resource, type: 'js' };
12337
+ // }
12338
+ // if (!_.isObject(resource)) {
12339
+ // throw new Error('cdn resource in wrong format');
12340
+ // }
12341
+ // return new Promise(async (resolve) => {
12342
+ // try {
12343
+ // switch (resource.type) {
12344
+ // case 'js':
12345
+ // await func.utils.load_js_on_demand(resource.src);
12346
+ // break;
12347
+ // case 'css':
12348
+ // await func.utils.load_js_on_demand(resource.src);
12349
+ // break;
12350
+ // case 'module':
12351
+ // func.utils.load_js_on_demand(resource.src, 'module');
12352
+ // break;
12353
+
12354
+ // default:
12355
+ // await func.utils.load_js_on_demand(resource.src);
12356
+ // break;
12357
+ // }
12358
+ // resolve();
12359
+ // } catch (error) {
12360
+ // func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource, 'W');
12361
+ // resolve();
12362
+ // }
12261
12363
 
12262
- 'xu-render': async function ($elm, val) {
12263
- let ret = await common_fx['xu-render']($elm, val, true);
12264
- return ret;
12265
- },
12266
- 'xu-ref': async function ($elm, val) {
12267
- let ret = await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
12268
- return ret;
12269
- },
12270
- },
12271
- [`xu-teleport`]: {
12272
- to: async function ($elm, val) {
12273
- if (!glb.new_xu_render) {
12274
- if (val.value) {
12275
- // parent_infoP.is_xu_teleport;
12276
- if ($elm?.parent()?.data()?.xuData?.length) {
12277
- $elm.parent().data('xuTeleportData', []);
12278
- for (const [key, node] of Object.entries(nodeP.children)) {
12279
- const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $(val.value), node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12280
-
12281
- $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12282
- $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
12283
- }
12284
- $elm.remove();
12285
- } else {
12286
- $elm.data('xuTeleportData', []).attr('hidden', true);
12287
- for (const [key, node] of Object.entries(nodeP.children)) {
12288
- const $to_container = $(val.value);
12289
- if (!$to_container?.length) {
12290
- return console.error(`container ${val.value} for xuTeleportData not found`);
12291
- }
12292
- const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $to_container, node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12364
+ // // if (resource.type === "js" || !resource.type) {
12365
+ // // await func.utils.load_js_on_demand(resource.src);
12366
+ // // return resolve();
12367
+ // // }
12368
+ // // if (resource.type === "css") {
12369
+ // // func.utils.load_css_on_demand(resource.src);
12370
+ // // return resolve();
12371
+ // // }
12372
+ // // if (resource.type === "module") {
12373
+ // // func.utils.load_js_on_demand(resource.src, "module");
12374
+ // // return resolve();
12375
+ // // }
12376
+ // // func.utils.debug_report(
12377
+ // // SESSION_ID,
12378
+ // // "xu-cdn",
12379
+ // // "Fail to load: " + resource,
12380
+ // // "W"
12381
+ // // );
12382
+ // // return resolve();
12383
+ // });
12384
+ // };
12293
12385
 
12294
- $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12295
- $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
12296
- }
12297
- }
12298
- }
12299
- return { abort: true };
12300
- }
12386
+ // const common_fx = {
12387
+ // 'xu-attrs': async function ($elm, val) {
12388
+ // if (!val.value) return {};
12389
+ // if (!_.isObject(val.value)) throw 'xu-attrs value us not an object';
12390
+ // for (const [attr_key, attr_val] of Object.entries(val.value)) {
12391
+ // nodeP.attributes[attr_key] = attr_val;
12392
+ // }
12301
12393
 
12302
- if (val.value) {
12303
- // // parent_infoP.is_xu_teleport;
12304
- // if ($elm?.parent()?.data()?.xuData?.length) {
12305
- // $elm.parent().data('xuTeleportData', []);
12306
- // for (const [key, node] of Object.entries(nodeP.children)) {
12307
- // const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $(val.value), node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12308
- // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12309
- // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
12310
- // }
12311
- // $elm.remove();
12312
- // } else {
12313
- // $elm.data('xuTeleportData', []).attr('hidden', true);
12314
- // for (const [key, node] of Object.entries(nodeP.children)) {
12315
- // const $to_container = $(val.value);
12316
- // if (!$to_container?.length) {
12317
- // return console.error(`container ${val.value} for xuTeleportData not found`);
12318
- // }
12319
- // const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $to_container, node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
12320
- // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
12321
- // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
12322
- // }
12323
- // }
12324
- }
12325
- return {};
12326
- },
12327
- 'xu-render': async function ($elm, val) {
12328
- let ret = await common_fx['xu-render']($elm, val, true);
12329
- return ret;
12330
- },
12331
- 'xu-show': async function ($elm, val) {
12332
- let ret = await common_fx['xu-show']($elm, val, true);
12333
- return ret;
12334
- },
12335
- },
12336
- };
12394
+ // return {};
12395
+ // },
12396
+ // 'xu-ref': async function ($elm, val, dsSession) {
12397
+ // if (!val.value) return {};
12337
12398
 
12338
- const load_cdn = async function (resource) {
12339
- // console.log("loading cdn", resource);
12340
- if (!_.isObject(resource) && _.isString(resource)) {
12341
- resource = { src: resource, type: 'js' };
12342
- }
12343
- if (!_.isObject(resource)) {
12344
- throw new Error('cdn resource in wrong format');
12345
- }
12346
- return new Promise(async (resolve) => {
12347
- try {
12348
- switch (resource.type) {
12349
- case 'js':
12350
- await func.utils.load_js_on_demand(resource.src);
12351
- break;
12352
- case 'css':
12353
- await func.utils.load_js_on_demand(resource.src);
12354
- break;
12355
- case 'module':
12356
- func.utils.load_js_on_demand(resource.src, 'module');
12357
- break;
12399
+ // func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
12358
12400
 
12359
- default:
12360
- await func.utils.load_js_on_demand(resource.src);
12361
- break;
12362
- }
12363
- resolve();
12364
- } catch (error) {
12365
- func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource, 'W');
12366
- resolve();
12367
- }
12401
+ // // Select the node that will be observed for mutations
12402
+ // const targetNode = $elm[0];
12368
12403
 
12369
- // if (resource.type === "js" || !resource.type) {
12370
- // await func.utils.load_js_on_demand(resource.src);
12371
- // return resolve();
12372
- // }
12373
- // if (resource.type === "css") {
12374
- // func.utils.load_css_on_demand(resource.src);
12375
- // return resolve();
12376
- // }
12377
- // if (resource.type === "module") {
12378
- // func.utils.load_js_on_demand(resource.src, "module");
12379
- // return resolve();
12380
- // }
12381
- // func.utils.debug_report(
12382
- // SESSION_ID,
12383
- // "xu-cdn",
12384
- // "Fail to load: " + resource,
12385
- // "W"
12386
- // );
12387
- // return resolve();
12388
- });
12389
- };
12404
+ // if (!targetNode) return;
12390
12405
 
12391
- const common_fx = {
12392
- 'xu-attrs': async function ($elm, val) {
12393
- if (!val.value) return {};
12394
- if (!_.isObject(val.value)) throw 'xu-attrs value us not an object';
12395
- for (const [attr_key, attr_val] of Object.entries(val.value)) {
12396
- nodeP.attributes[attr_key] = attr_val;
12397
- }
12406
+ // // Options for the observer (which mutations to observe)
12407
+ // const config = { attributes: true, childList: true, subtree: true };
12398
12408
 
12399
- return {};
12400
- },
12401
- 'xu-ref': async function ($elm, val, dsSession) {
12402
- if (!val.value) return {};
12409
+ // // Callback function to execute when mutations are observed
12410
+ // const callback = (mutationList, observer) => {
12411
+ // func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
12412
+ // };
12403
12413
 
12404
- func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
12414
+ // // Create an observer instance linked to the callback function
12415
+ // const observer = new MutationObserver(callback);
12416
+
12417
+ // // Start observing the target node for configured mutations
12418
+ // observer.observe(targetNode, config);
12419
+
12420
+ // // Later, you can stop observing
12421
+ // // observer.disconnect();
12422
+
12423
+ // return {};
12424
+ // },
12425
+ // 'xu-bind': async function ($elm, val) {
12426
+ // if (is_skeleton) return;
12427
+
12428
+ // let val_is_reference_field = false;
12429
+
12430
+ // let _prog_id = $elm.data().xuData.paramsP.prog_id;
12431
+ // let _dsP = $elm.data().xuData.paramsP.dsSessionP;
12432
+ // const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
12433
+ // if (!view_ret) return {};
12434
+
12435
+ // let is_dynamic_field = false;
12436
+ // let field_prop;
12437
+ // let bind_field_id;
12438
+
12439
+ // const input_field_type = $elm.attr('type');
12440
+
12441
+ // const get_bind_field = async function (field_id) {
12442
+ // if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
12443
+ // is_dynamic_field = true;
12444
+ // field_prop = _ds.dynamic_fields[field_id];
12445
+ // } else {
12446
+ // field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
12447
+ // if (!field_prop) {
12448
+ // /// find the field everywhere in the chain Aug 30 2024
12449
+ // const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
12450
+
12451
+ // if (ret_get_value.found) {
12452
+ // _dsP = ret_get_value.dsSessionP;
12453
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
12454
+ // _prog_id = _ds.prog_id;
12455
+ // const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
12456
+ // if (!view_ret) return {};
12457
+ // field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
12458
+ // }
12459
+ // if (!field_prop) {
12460
+ // throw `field ${field_id} not found in the program scope`;
12461
+ // }
12462
+ // }
12463
+ // }
12464
+ // return field_id;
12465
+ // };
12405
12466
 
12406
- // Select the node that will be observed for mutations
12407
- const targetNode = $elm[0];
12467
+ // try {
12468
+ // bind_field_id = await get_bind_field(val.value.split('.')[0]);
12469
+ // val_is_reference_field = true;
12470
+ // } catch (err) {
12471
+ // console.error(err?.message || err);
12472
+ // return {};
12473
+ // }
12408
12474
 
12409
- if (!targetNode) return;
12475
+ // const field_changed = async function (e) {
12476
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
12410
12477
 
12411
- // Options for the observer (which mutations to observe)
12412
- const config = { attributes: true, childList: true, subtree: true };
12478
+ // // update array for checkbox that not in xu-for
12479
+ // if (field_prop.props.fieldType === 'array' && input_field_type === 'checkbox' && val_is_reference_field) {
12480
+ // let arr_value_before_cast = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, _ds.currentRecordId)).ret.value);
12481
+ // let value_from_getter = bind.getter($elm[0]);
12482
+ // let value;
12483
+ // if (arr_value_before_cast.includes(value_from_getter)) {
12484
+ // value = arr_value_before_cast.filter((item) => !_.isEqual(item, value_from_getter));
12485
+ // } else {
12486
+ // arr_value_before_cast.push(value_from_getter);
12487
+ // value = arr_value_before_cast;
12488
+ // }
12413
12489
 
12414
- // Callback function to execute when mutations are observed
12415
- const callback = (mutationList, observer) => {
12416
- func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
12417
- };
12490
+ // let datasource_changes = {
12491
+ // [_dsP]: {
12492
+ // [_ds.currentRecordId]: {
12493
+ // [bind_field_id]: value,
12494
+ // },
12495
+ // },
12496
+ // };
12418
12497
 
12419
- // Create an observer instance linked to the callback function
12420
- const observer = new MutationObserver(callback);
12498
+ // return await func.datasource.update(SESSION_ID, datasource_changes);
12499
+ // }
12421
12500
 
12422
- // Start observing the target node for configured mutations
12423
- observer.observe(targetNode, config);
12501
+ // // update array for radio that not in xu-for
12502
+ // if (field_prop.props.fieldType === 'array' && input_field_type === 'radio' && val_is_reference_field) {
12503
+ // let value_from_getter = bind.getter($elm[0]);
12424
12504
 
12425
- // Later, you can stop observing
12426
- // observer.disconnect();
12505
+ // let datasource_changes = {
12506
+ // [_dsP]: {
12507
+ // [_ds.currentRecordId]: {
12508
+ // [bind_field_id]: [value_from_getter],
12509
+ // },
12510
+ // },
12511
+ // };
12427
12512
 
12428
- return {};
12429
- },
12430
- 'xu-bind': async function ($elm, val) {
12431
- if (is_skeleton) return;
12513
+ // return await func.datasource.update(SESSION_ID, datasource_changes);
12514
+ // }
12432
12515
 
12433
- let val_is_reference_field = false;
12516
+ // var value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', field_prop.props.fieldType, bind.getter($elm[0]));
12434
12517
 
12435
- let _prog_id = $elm.data().xuData.paramsP.prog_id;
12436
- let _dsP = $elm.data().xuData.paramsP.dsSessionP;
12437
- const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
12438
- if (!view_ret) return {};
12518
+ // if (field_prop.props.fieldType === 'object') {
12519
+ // value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
12520
+ // }
12439
12521
 
12440
- let is_dynamic_field = false;
12441
- let field_prop;
12442
- let bind_field_id;
12522
+ // if (!_ds.currentRecordId) return;
12443
12523
 
12444
- const input_field_type = $elm.attr('type');
12524
+ // let datasource_changes = {
12525
+ // [_dsP]: {
12526
+ // [_ds.currentRecordId]: {
12527
+ // [bind_field_id]: value,
12528
+ // },
12529
+ // },
12530
+ // };
12445
12531
 
12446
- const get_bind_field = async function (field_id) {
12447
- if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
12448
- is_dynamic_field = true;
12449
- field_prop = _ds.dynamic_fields[field_id];
12450
- } else {
12451
- field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
12452
- if (!field_prop) {
12453
- /// find the field everywhere in the chain Aug 30 2024
12454
- const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
12532
+ // await func.datasource.update(SESSION_ID, datasource_changes);
12533
+ // const iterate_info = $elm?.data()?.xuData?.iterate_info;
12534
+ // const reference_source_obj = iterate_info?.reference_source_obj;
12535
+ // if (reference_source_obj) {
12536
+ // if (reference_source_obj.ret.type === 'array') {
12537
+ // if (iterate_info.iterator_val === bind_field_id) {
12538
+ // const arr_idx = Number($elm?.data()?.xuData?.iterate_info._key);
12455
12539
 
12456
- if (ret_get_value.found) {
12457
- _dsP = ret_get_value.dsSessionP;
12458
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
12459
- _prog_id = _ds.prog_id;
12460
- const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
12461
- if (!view_ret) return {};
12462
- field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
12463
- }
12464
- if (!field_prop) {
12465
- throw `field ${field_id} not found in the program scope`;
12466
- }
12467
- }
12468
- }
12469
- return field_id;
12470
- };
12540
+ // const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
12541
+ // let new_arr = _.cloneDeep(dataset_arr.ret.value);
12471
12542
 
12472
- try {
12473
- bind_field_id = await get_bind_field(val.value.split('.')[0]);
12474
- val_is_reference_field = true;
12475
- } catch (err) {
12476
- console.error(err?.message || err);
12477
- return {};
12478
- }
12543
+ // if (field_prop.props.fieldType === 'object' && val_is_reference_field) {
12544
+ // let obj_item = new_arr[arr_idx];
12479
12545
 
12480
- const field_changed = async function (e) {
12481
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
12546
+ // let e_exp = val.value.replace(bind_field_id, 'obj_item');
12482
12547
 
12483
- // update array for checkbox that not in xu-for
12484
- if (field_prop.props.fieldType === 'array' && input_field_type === 'checkbox' && val_is_reference_field) {
12485
- let arr_value_before_cast = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, _ds.currentRecordId)).ret.value);
12486
- let value_from_getter = bind.getter($elm[0]);
12487
- let value;
12488
- if (arr_value_before_cast.includes(value_from_getter)) {
12489
- value = arr_value_before_cast.filter((item) => !_.isEqual(item, value_from_getter));
12490
- } else {
12491
- arr_value_before_cast.push(value_from_getter);
12492
- value = arr_value_before_cast;
12493
- }
12548
+ // let new_val = eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
12494
12549
 
12495
- let datasource_changes = {
12496
- [_dsP]: {
12497
- [_ds.currentRecordId]: {
12498
- [bind_field_id]: value,
12499
- },
12500
- },
12501
- };
12550
+ // new_arr[arr_idx] = obj_item;
12551
+ // } else {
12552
+ // new_arr[arr_idx] = value;
12553
+ // }
12554
+ // // datasource_changes[_dsP][_ds.currentRecordId][reference_source_obj.fieldIdP] = new_arr;
12555
+
12556
+ // let datasource_changes = {
12557
+ // [_dsP]: {
12558
+ // [_ds.currentRecordId]: {
12559
+ // [reference_source_obj.fieldIdP]: new_arr,
12560
+ // },
12561
+ // },
12562
+ // };
12502
12563
 
12503
- return await func.datasource.update(SESSION_ID, datasource_changes);
12504
- }
12564
+ // await func.datasource.update(SESSION_ID, datasource_changes, null, true);
12565
+ // }
12566
+ // }
12567
+ // }
12505
12568
 
12506
- // update array for radio that not in xu-for
12507
- if (field_prop.props.fieldType === 'array' && input_field_type === 'radio' && val_is_reference_field) {
12508
- let value_from_getter = bind.getter($elm[0]);
12569
+ // await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, _ds.parentDataSourceNo);
12570
+ // };
12509
12571
 
12510
- let datasource_changes = {
12511
- [_dsP]: {
12512
- [_ds.currentRecordId]: {
12513
- [bind_field_id]: [value_from_getter],
12514
- },
12515
- },
12516
- };
12572
+ // const bind = new UI_FRAMEWORK_PLUGIN.bind();
12517
12573
 
12518
- return await func.datasource.update(SESSION_ID, datasource_changes);
12519
- }
12574
+ // bind.listener($elm[0], field_changed);
12520
12575
 
12521
- var value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', field_prop.props.fieldType, bind.getter($elm[0]));
12576
+ // const set_value = function () {
12577
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12578
+ // if (!_ds.currentRecordId) return;
12579
+ // let value;
12580
+ // try {
12581
+ // if (val_is_reference_field) {
12582
+ // if (is_dynamic_field) {
12583
+ // value = _ds.dynamic_fields[bind_field_id].value;
12584
+ // } else {
12585
+ // const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
12586
+ // value = _ds.data_feed.rows?.[row_idx]?.[bind_field_id];
12587
+ // }
12588
+ // if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'checkbox' && $elm.attr('value')) {
12589
+ // if (value.includes($elm.attr('value'))) {
12590
+ // value = true;
12591
+ // } else {
12592
+ // value = false;
12593
+ // }
12594
+ // } else if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'radio' && $elm.attr('value')) {
12595
+ // if (value.includes($elm.attr('value'))) {
12596
+ // value = $elm.attr('value');
12597
+ // } else {
12598
+ // value = false;
12599
+ // }
12600
+ // } else if (field_prop.props.fieldType === 'object' && val.value.split('.').length > 1) {
12601
+ // let str = val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')');
12602
+ // value = eval(str);
12603
+ // }
12604
+ // } else {
12605
+ // value = val.value;
12606
+ // }
12607
+ // if (typeof value === 'undefined') return;
12608
+ // bind.setter($elm[0], value);
12609
+ // } catch (err) {
12610
+ // console.error(err);
12611
+ // }
12612
+ // };
12613
+ // /// init value from ds
12614
+ // $('body').on('xu-bind-refresh.' + _ds.dsSession.toString(), () => {
12615
+ // set_value();
12616
+ // });
12522
12617
 
12523
- if (field_prop.props.fieldType === 'object') {
12524
- value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
12525
- }
12618
+ // set_value();
12619
+ // return {};
12620
+ // },
12621
+ // 'xu-render': async function ($elm, val, from_panel) {
12622
+ // const old_render = async function () {
12623
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
12624
+ // const init_render = function () {
12625
+ // if (!value) {
12626
+ // var cloned_$div = $elm.clone(true);
12627
+
12628
+ // let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container); //.hide();
12629
+ // let original_data_obj = {
12630
+ // $container: cloned_$div,
12631
+ // nodeP: _.cloneDeep(nodeP),
12632
+ // parent_infoP,
12633
+ // paramsP,
12634
+ // keyP,
12635
+ // parent_nodeP,
12636
+ // $root_container,
12637
+ // };
12638
+ // $xurender.data('xuData', cloned_$div.data().xuData);
12639
+ // $xurender.data().xuData.original_data_obj = original_data_obj;
12640
+ // $xurender.data().xuData.xurender_node = cloned_$div;
12641
+ // $xurender.data().xuAttributes = nodeP.attributes || {};
12642
+ // // $xurender.hide();
12643
+
12644
+ // $elm.remove();
12645
+ // return { abort: true };
12646
+ // }
12647
+ // return {};
12648
+ // };
12526
12649
 
12527
- if (!_ds.currentRecordId) return;
12650
+ // const post_render = async function () {
12651
+ // if (value) {
12652
+ // try {
12653
+ // // abort if already rended
12654
+ // if ($elm[0].tagName !== 'XURENDER' && $elm?.length) {
12655
+ // return func.events.delete_job(SESSION_ID, jobNoP);
12656
+ // }
12528
12657
 
12529
- let datasource_changes = {
12530
- [_dsP]: {
12531
- [_ds.currentRecordId]: {
12532
- [bind_field_id]: value,
12533
- },
12534
- },
12535
- };
12658
+ // let original_data_obj = $elm.data().xuData.original_data_obj;
12536
12659
 
12537
- await func.datasource.update(SESSION_ID, datasource_changes);
12538
- const iterate_info = $elm?.data()?.xuData?.iterate_info;
12539
- const reference_source_obj = iterate_info?.reference_source_obj;
12540
- if (reference_source_obj) {
12541
- if (reference_source_obj.ret.type === 'array') {
12542
- if (iterate_info.iterator_val === bind_field_id) {
12543
- const arr_idx = Number($elm?.data()?.xuData?.iterate_info._key);
12660
+ // if (!original_data_obj) {
12661
+ // func.events.delete_job(SESSION_ID, jobNoP);
12662
+ // return { delete_job: jobNoP };
12663
+ // }
12544
12664
 
12545
- const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
12546
- let new_arr = _.cloneDeep(dataset_arr.ret.value);
12665
+ // const new_$div = await func.UI.screen.render_ui_tree(
12666
+ // SESSION_ID,
12667
+ // $elm, //original_data_obj.$container,
12668
+ // _.cloneDeep(original_data_obj.nodeP),
12669
+ // original_data_obj.parent_infoP,
12670
+ // original_data_obj.paramsP,
12671
+ // jobNoP,
12672
+ // null,
12673
+ // original_data_obj.keyP,
12674
+ // null,
12675
+ // original_data_obj.parent_nodeP,
12676
+ // null,
12677
+ // original_data_obj.$root_container,
12678
+ // );
12679
+
12680
+ // new_$div.data().xuData.original_data_obj = original_data_obj;
12681
+ // new_$div.data().xuData.xurender_node = $elm.clone(true);
12682
+ // new_$div.data().xuAttributes = $elm.data().xuAttributes || {};
12683
+
12684
+ // const replace = async function () {
12685
+ // $elm.replaceWith(new_$div);
12686
+ // if (from_panel) {
12687
+ // const xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
12688
+ // $elm.parent().data().xuPanelWrapper = xuPanelWrapper;
12689
+ // $elm.replaceWith(new_$div.children());
12690
+ // }
12691
+
12692
+ // if (val.fields_arr) {
12693
+ // return await func.UI.screen.refresh_xu_attributes(SESSION_ID, val.fields_arr, val.jobNoP, new_$div);
12694
+ // }
12695
+ // func.events.delete_job(SESSION_ID, jobNoP);
12696
+ // };
12697
+ // // if ($elm && func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'xu_id', $elm.data().xuData.xu_id).length) {
12698
+ // if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length) {
12699
+ // if (new_$div.data().xuData.paramsP) {
12700
+ // return await replace();
12701
+ // }
12547
12702
 
12548
- if (field_prop.props.fieldType === 'object' && val_is_reference_field) {
12549
- let obj_item = new_arr[arr_idx];
12703
+ // func.events.delete_job(SESSION_ID, jobNoP);
12704
+ // }
12705
+ // } catch (error) {
12706
+ // func.events.delete_job(SESSION_ID, jobNoP);
12707
+ // }
12708
+ // return;
12709
+ // }
12710
+ // // if (!value) {
12711
+ // if ($elm.prop('tagName') === 'XURENDER') {
12712
+ // func.events.delete_job(SESSION_ID, jobNoP);
12713
+ // return;
12714
+ // }
12550
12715
 
12551
- let e_exp = val.value.replace(bind_field_id, 'obj_item');
12716
+ // let tmp_$div = $('<div>');
12552
12717
 
12553
- let new_val = eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
12718
+ // let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).appendTo(tmp_$div); //.hide();
12719
+ // // was true before
12720
+ // if ($elm.data().xuData.xurender_node) {
12721
+ // $xurender.data({
12722
+ // xuAttributes: $elm.data().xuData.xurender_node.data().xuAttributes || {},
12723
+ // xuData: $elm.data().xuData.xurender_node.data().xuData || {},
12724
+ // });
12725
+ // } else {
12726
+ // // default new state
12554
12727
 
12555
- new_arr[arr_idx] = obj_item;
12556
- } else {
12557
- new_arr[arr_idx] = value;
12558
- }
12559
- // datasource_changes[_dsP][_ds.currentRecordId][reference_source_obj.fieldIdP] = new_arr;
12560
-
12561
- let datasource_changes = {
12562
- [_dsP]: {
12563
- [_ds.currentRecordId]: {
12564
- [reference_source_obj.fieldIdP]: new_arr,
12565
- },
12566
- },
12567
- };
12728
+ // $xurender.data({
12729
+ // xuAttributes: $elm.data().xuAttributes || {},
12730
+ // xuData: $elm.data().xuData || {},
12731
+ // });
12732
+ // const original_data_obj = {
12733
+ // nodeP: _.cloneDeep($elm.data().xuData.node_org),
12734
+ // paramsP: $elm.data().xuData.paramsP,
12735
+ // $container: $elm.clone(true),
12736
+ // parent_infoP: parent_infoP,
12737
+ // };
12738
+
12739
+ // $xurender.data().xuData.original_data_obj = original_data_obj;
12740
+ // }
12568
12741
 
12569
- await func.datasource.update(SESSION_ID, datasource_changes, null, true);
12570
- }
12571
- }
12572
- }
12742
+ // //remove xu-teleport trace
12743
+ // $.each($elm.find('xu-teleport'), (key, val) => {
12744
+ // const xuTeleportData = $(val).data().xuTeleportData || [];
12745
+ // for (const teleported_elm_id of xuTeleportData) {
12746
+ // $(`[xu-ui-id="${teleported_elm_id}"]`).remove();
12747
+ // }
12748
+ // });
12573
12749
 
12574
- await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, _ds.parentDataSourceNo);
12575
- };
12750
+ // $elm.replaceWith(tmp_$div.children());
12751
+ // func.events.delete_job(SESSION_ID, jobNoP);
12752
+ // // }
12753
+ // };
12754
+ // if (is_init) {
12755
+ // return init_render();
12756
+ // }
12757
+ // return await post_render();
12758
+ // };
12576
12759
 
12577
- const bind = new UI_FRAMEWORK_PLUGIN.bind();
12760
+ // const new_render = async function () {
12761
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
12762
+ // const has_xu_render_attribute = true;
12763
+ // const has_xu_exp_render_attribute = $elm.data()?.xuData?.attr_exp_info?.['xu-render'] ? true : false;
12764
+ // const init_render = async function () {
12765
+ // nodeP.xu_render_made = value;
12766
+ // if (!value) {
12767
+ // if (has_xu_exp_render_attribute) {
12768
+ // return { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true };
12769
+ // }
12770
+ // return { has_xu_render_attribute, abort: true };
12771
+ // }
12772
+ // return { has_xu_exp_render_attribute, has_xu_render_attribute };
12773
+ // };
12578
12774
 
12579
- bind.listener($elm[0], field_changed);
12775
+ // const post_render = async function () {
12776
+ // // always come from refresh
12777
+ // let nodeP = $container.data().xuData.node.children[keyP];
12778
+ // nodeP.xu_render_made = value;
12779
+ // if (value) {
12780
+ // try {
12781
+ // const xu_render_cache_id = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
12782
+ // const xu_ui_id = $elm.attr('xu-ui-id');
12783
+ // let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[xu_ui_id + xu_render_cache_id]?.$div.clone(true);
12784
+ // let found_parent_vars = false;
12785
+ // if (new_$div) {
12786
+ // // validate if $div contains fields from parent ds
12787
+ // const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
12788
+ // const parent_fields = Object.keys(parent_data);
12789
+
12790
+ // $.each(new_$div.find('*'), (key, val) => {
12791
+ // const _xuAttributes = $(val)?.data()?.xuAttributes;
12792
+ // if (found_parent_vars || !_xuAttributes) return;
12793
+ // for (const [attr_key, attr_val] of Object.entries(_xuAttributes)) {
12794
+ // if (found_parent_vars) break;
12795
+ // for (const [key, val] of Object.entries(parent_fields)) {
12796
+ // if (attr_val.includes('@' + key)) {
12797
+ // found_parent_vars = true;
12798
+ // break;
12799
+ // }
12800
+ // }
12801
+ // }
12802
+ // });
12803
+ // }
12580
12804
 
12581
- const set_value = function () {
12582
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12583
- if (!_ds.currentRecordId) return;
12584
- let value;
12585
- try {
12586
- if (val_is_reference_field) {
12587
- if (is_dynamic_field) {
12588
- value = _ds.dynamic_fields[bind_field_id].value;
12589
- } else {
12590
- const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
12591
- value = _ds.data_feed.rows?.[row_idx]?.[bind_field_id];
12592
- }
12593
- if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'checkbox' && $elm.attr('value')) {
12594
- if (value.includes($elm.attr('value'))) {
12595
- value = true;
12596
- } else {
12597
- value = false;
12598
- }
12599
- } else if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'radio' && $elm.attr('value')) {
12600
- if (value.includes($elm.attr('value'))) {
12601
- value = $elm.attr('value');
12602
- } else {
12603
- value = false;
12604
- }
12605
- } else if (field_prop.props.fieldType === 'object' && val.value.split('.').length > 1) {
12606
- let str = val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')');
12607
- value = eval(str);
12608
- }
12805
+ // if (!new_$div || found_parent_vars) {
12806
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { paramsP };
12807
+ // nodeP.xu_render_xu_ui_id = xu_ui_id;
12808
+ // nodeP.xu_render_cache_id = xu_render_cache_id;
12809
+ // new_$div = await func.UI.screen.render_ui_tree(SESSION_ID, $container, nodeP, parent_infoP, paramsP, jobNoP, null, keyP, null, parent_nodeP, null, $root_container);
12810
+ // const _$div = new_$div.clone(true);
12811
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].$div = _$div;
12812
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].data = _$div.data();
12813
+ // }
12814
+ // // append order handling
12815
+
12816
+ // if (!$container.children().length) {
12817
+ // new_$div.appendTo($container);
12818
+ // } else {
12819
+ // // iterate the container node
12820
+ // let $last_elm_found = [];
12821
+ // $.each($container.data().xuData.node.children, (item_key, item_val) => {
12822
+ // // const $elm = $(`[xu-node-id="${item_val.id}"]`);
12823
+ // const $elm = func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'nodeid', item_val.id);
12824
+ // if ($elm.length) {
12825
+ // $last_elm_found = $elm;
12826
+ // }
12827
+ // if (keyP == item_key) {
12828
+ // if ($last_elm_found.length) {
12829
+ // new_$div.after($last_elm_found);
12830
+ // } else {
12831
+ // $container.prepend(new_$div);
12832
+ // }
12833
+ // }
12834
+ // });
12835
+ // }
12836
+ // } catch (error) {
12837
+ // func.events.delete_job(SESSION_ID, jobNoP);
12838
+ // }
12839
+ // return;
12840
+ // }
12841
+
12842
+ // /////////// !value ///////////
12843
+
12844
+ // const xu_ui_id = $elm.attr('xu-ui-id');
12845
+
12846
+ // const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
12847
+ // const _$div = $elm.clone(true);
12848
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
12849
+ // $elm.remove();
12850
+ // func.events.delete_job(SESSION_ID, jobNoP);
12851
+ // };
12852
+ // if (is_init) {
12853
+ // return await init_render();
12854
+ // }
12855
+ // return await post_render();
12856
+ // };
12857
+
12858
+ // if (glb.new_xu_render) {
12859
+ // return new_render();
12860
+ // }
12861
+ // return old_render();
12862
+ // },
12863
+ // 'xu-show': async function ($elm, val) {
12864
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
12865
+ // if (value) {
12866
+ // $elm.show();
12867
+ // }
12868
+ // if (!value) {
12869
+ // $elm.hide();
12870
+ // }
12871
+ // return {};
12872
+ // },
12873
+ // 'xu-content': async function ($elm, val) {
12874
+ // try {
12875
+ // $elm.html(val.value);
12876
+ // } catch (error) {
12877
+ // console.warn(e);
12878
+ // }
12879
+ // return;
12880
+ // },
12881
+ // 'xu-text': async function ($elm, val) {
12882
+ // try {
12883
+ // $elm.text(val.value);
12884
+ // } catch (error) {
12885
+ // console.warn(e);
12886
+ // }
12887
+ // return;
12888
+ // },
12889
+ // 'xu-html': async function ($elm, val) {
12890
+ // try {
12891
+ // $elm.html(val.value);
12892
+ // } catch (error) {
12893
+ // console.warn(e);
12894
+ // }
12895
+ // return;
12896
+ // },
12897
+ // 'xu-for': async function ($elm, data) {
12898
+ // // exit if call from rendered xu-for item to prevent infante loop (parent_infoP?.iterate_info indicate call from rendered item)
12899
+ // if (parent_infoP?.iterate_info) return {};
12900
+ // if (!data.value) return {};
12901
+ // try {
12902
+ // // data.value (xu-for) can store actual values such as an array, a CSV, or a field_id that references a specific field within the dataset, initialized with values for the iteration.
12903
+ // let arr = data.value;
12904
+
12905
+ // // find reference source field
12906
+ // let reference_source_obj;
12907
+
12908
+ // const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
12909
+
12910
+ // let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
12911
+ // // detect if data.value (xu-for) is reference field_id by checking if exist in the dataset
12912
+ // if (view_field_obj) {
12913
+ // // xu-for is reference field_id
12914
+ // reference_source_obj = await func.datasource.get_value(SESSION_ID, data.value, paramsP.dsSessionP);
12915
+ // arr = reference_source_obj?.ret?.value;
12916
+ // } else {
12917
+ // // xu-for is actual data
12918
+ // if (typeof data.value === 'string') {
12919
+ // arr = eval(data.value.replaceAll('\\', ''));
12920
+ // }
12921
+ // if (typeof arr === 'number') {
12922
+ // arr = Array.from(Array(arr).keys());
12923
+ // }
12924
+ // }
12925
+
12926
+ // const custom_iterator_key = $elm.data().xuData.iterator_key;
12927
+ // const custom_iterator_val = $elm.data().xuData.iterator_val;
12928
+
12929
+ // let iterator_key = custom_iterator_key;
12930
+ // let iterator_val = custom_iterator_val;
12931
+ // let is_key_dynamic_field, is_val_dynamic_field;
12932
+
12933
+ // // custom FOR_VAL name or namespaced default name
12934
+ // if (!custom_iterator_key) {
12935
+ // is_key_dynamic_field = true;
12936
+
12937
+ // iterator_key = '_FOR_KEY';
12938
+ // }
12939
+
12940
+ // if (!custom_iterator_val) {
12941
+ // is_val_dynamic_field = true;
12942
+
12943
+ // iterator_val = '_FOR_VAL';
12944
+ // }
12945
+
12946
+ // var i = 0;
12947
+ // for await (let [_key, _val] of Object.entries(arr)) {
12948
+ // if (_.isArray(arr)) {
12949
+ // _key = Number(_key);
12950
+ // }
12951
+
12952
+ // const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
12953
+ // if (is_dynamic_field) {
12954
+ // func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
12955
+ // } else {
12956
+ // const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
12957
+
12958
+ // let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
12959
+ // if (view_field_obj) {
12960
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12961
+ // try {
12962
+ // const row_idx = func.common.find_ROWID_idx(_ds, currentRecordId);
12963
+ // _ds.data_feed.rows[row_idx][field_id] = value;
12964
+ // } catch (err) {
12965
+ // console.error(err);
12966
+ // }
12967
+ // } else {
12968
+ // console.error('field not exist in dataset for xu-for method');
12969
+ // }
12970
+ // }
12971
+ // };
12972
+
12973
+ // var currentRecordId = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId.toString();
12974
+
12975
+ // await set_value(is_key_dynamic_field, currentRecordId, iterator_key, _key);
12976
+ // await set_value(is_val_dynamic_field, currentRecordId, iterator_val, _val);
12977
+
12978
+ // var iterate_info = {
12979
+ // _val,
12980
+ // _key,
12981
+ // iterator_key,
12982
+ // iterator_val,
12983
+ // is_key_dynamic_field,
12984
+ // is_val_dynamic_field,
12985
+ // reference_source_obj,
12986
+ // };
12987
+ // // let _parent_info = _.cloneDeep(parent_infoP) || {};
12988
+ // let _parent_info = klona.klona(parent_infoP) || {};
12989
+ // _parent_info.iterate_info = iterate_info;
12990
+
12991
+ // const $divP = await func.UI.screen.render_ui_tree(
12992
+ // SESSION_ID,
12993
+ // $container,
12994
+ // nodeP,
12995
+ // _parent_info, //parent_infoP ? _.cloneDeep(_parent_info) : null,
12996
+ // paramsP,
12997
+ // jobNoP,
12998
+ // null,
12999
+ // i,
13000
+ // null,
13001
+ // nodeP,
13002
+ // null,
13003
+ // $root_container,
13004
+ // );
13005
+
13006
+ // $.each($divP.children(), function (key, val) {
13007
+ // if ($(val)?.data()?.xuData) {
13008
+ // $(val).data().xuData.iterate_info = iterate_info;
13009
+ // }
13010
+ // });
13011
+
13012
+ // i++;
13013
+ // }
13014
+ // $elm.remove();
13015
+ // return { abort: true };
13016
+ // } catch (e) {
13017
+ // console.error(' Iterator Arr parse error');
13018
+ // return { abort: true };
13019
+ // }
13020
+ // },
13021
+ // 'xu-for-key': async function ($elm, val) {
13022
+ // $elm.data().xuData.iterator_key = val.value;
13023
+ // return {};
13024
+ // },
13025
+ // 'xu-for-val': async function ($elm, val) {
13026
+ // $elm.data().xuData.iterator_val = val.value;
13027
+ // return {};
13028
+ // },
13029
+ // 'xu-class': async function ($elm, val) {
13030
+ // try {
13031
+ // const classes_string = val.value;
13032
+ // // let obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
13033
+
13034
+ // const classes_obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
13035
+ // for await (const [cla, cond] of Object.entries(classes_obj)) {
13036
+ // let res = await func.expression.get(
13037
+ // SESSION_ID,
13038
+ // cond,
13039
+ // paramsP.dsSessionP,
13040
+ // 'UI Attr EXP',
13041
+ // $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
13042
+ // null,
13043
+ // null,
13044
+ // null,
13045
+ // null,
13046
+ // null,
13047
+ // $elm.data().xuData.iterate_info,
13048
+ // );
13049
+
13050
+ // if (res.result) {
13051
+ // $elm.addClass(cla);
13052
+ // } else {
13053
+ // $elm.removeClass(cla);
13054
+ // }
13055
+
13056
+ // $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
13057
+ // }
13058
+ // return {};
13059
+ // } catch (e) {
13060
+ // console.warn('parse error:' + val.value);
13061
+ // return { abort: true };
13062
+ // }
13063
+ // },
13064
+ // 'xu-exp': async function ($elm, val) {
13065
+ // let exp = val.value === null ? true : val.value;
13066
+
13067
+ // let exp_ret = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId, null, null, null, null, null, $elm.data().xuData.iterate_info);
13068
+
13069
+ // let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
13070
+
13071
+ // var new_val = {
13072
+ // key: val.key,
13073
+ // value,
13074
+ // };
13075
+
13076
+ // if (nodeP.tagName.substr(0, 3) === 'xu-') {
13077
+ // if (tag_fx[nodeP.tagName][new_val.key]) {
13078
+ // return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
13079
+ // }
13080
+ // console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
13081
+ // return {};
13082
+ // }
13083
+ // if (!$elm.data().xuData) return;
13084
+
13085
+ // $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
13086
+
13087
+ // // IGNORE UNDEFINED or NULL ATTRIBUTES
13088
+ // if (typeof new_val.value === 'undefined' || new_val.value === null) {
13089
+ // return {};
13090
+ // }
13091
+
13092
+ // // IGNORE ATTRIBUTES WITH EMPTY VALUES
13093
+ // if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
13094
+ // return {};
13095
+ // }
13096
+
13097
+ // if (new_val.key.substr(0, 2) === 'xu') {
13098
+ // return await common_fx[new_val.key]($elm, new_val);
13099
+ // }
13100
+
13101
+ // $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
13102
+ // return {};
13103
+ // },
13104
+ // 'xu-on': async function ($elm, val) {
13105
+ // CLIENT_ACTIVITY_TS = Date.now();
13106
+ // const trigger = val.key.split('xu-on:')[1].toLowerCase();
13107
+ // $elm.on(trigger, async function (evt) {
13108
+ // const _$elm = $(evt.currentTarget);
13109
+ // if (_.isEmpty(_$elm.data().xuAttributes)) return;
13110
+
13111
+ // for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
13112
+ // if (!_.isEmpty(val.props.condition)) {
13113
+ // const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
13114
+ // if (!expCond.result) continue;
13115
+ // }
13116
+
13117
+ // if (val.event_modifiers && evt[val.event_modifiers]) {
13118
+ // evt[val.event_modifiers]();
13119
+ // }
13120
+
13121
+ // // if (val.handler === 'custom') {
13122
+ // if (val.workflow) {
13123
+ // // do BL
13124
+ // for await (const [key2, val2] of Object.entries(val.workflow)) {
13125
+ // // var cond = val2.data.enabled;
13126
+ // // if (val2.data.enabled && val2.props.condition) {
13127
+ // // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
13128
+ // // cond = expCond.result;
13129
+ // // }
13130
+ // // if (!cond) continue;
13131
+
13132
+ // if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
13133
+
13134
+ // func.events.add_to_queue(SESSION_ID, 'element event', val2.id, evt.type, val2.data.action, val2.data.name, null, _$elm.attr('xu-ui-id'), null, evt, null, null, null, paramsP.dsSessionP, null, null, null, evt.type, val2.data.name, null, null, val2, null, null, null, null, null, null);
13135
+ // }
13136
+ // }
13137
+ // }
13138
+ // });
13139
+ // return {};
13140
+ // },
13141
+ // 'xu-script': async function ($elm, val) {
13142
+ // var checkExist = setInterval(async function () {
13143
+ // if ($elm.is(':visible')) {
13144
+ // try {
13145
+ // // var res = eval('(' + val.value + ')');
13146
+ // // const fn = `(function(el) {
13147
+ // // ${val.value}
13148
+ // // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
13149
+
13150
+ // const fn = `async (el)=>{${val.value} };`;
13151
+
13152
+ // var res = eval(fn);
13153
+ // await res($elm[0]);
13154
+ // // if (typeof res === 'function') {
13155
+ // // res($elm[0]);
13156
+ // // }
13157
+ // } catch (e) {
13158
+ // eval(val.value);
13159
+ // }
13160
+
13161
+ // clearInterval(checkExist);
13162
+ // }
13163
+ // }, 100); // check every 100ms
13164
+
13165
+ // return {};
13166
+ // },
13167
+ // 'xu-style-global': async function ($elm, val) {
13168
+ // $('head').append(`<style>${val.value}</style>`);
13169
+ // return {};
13170
+ // },
13171
+ // 'xu-style': async function ($elm, val) {
13172
+ // var cssString = val.value;
13173
+
13174
+ // var parser = new cssjs();
13175
+
13176
+ // var parsed = parser.parseCSS(cssString);
13177
+ // var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
13178
+
13179
+ // $.each(parsed, function (key, val) {
13180
+ // var selectors_arr = val.selector.split(',');
13181
+
13182
+ // $.each(selectors_arr, function (key2, val2) {
13183
+ // selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
13184
+ // // console.log(new_selector);
13185
+ // });
13186
+
13187
+ // val.selector = selectors_arr.join(',');
13188
+ // // console.log(parsed);
13189
+ // });
13190
+
13191
+ // var newCSSString = parser.getCSSForEditor(parsed);
13192
+
13193
+ // $('head').append(`<style>${newCSSString}</style>`);
13194
+ // return {};
13195
+ // },
13196
+ // 'xu-cdn': async function ($elm, val) {
13197
+ // for await (const [key, resource] of Object.entries(val.value)) {
13198
+ // await load_cdn(resource);
13199
+ // }
13200
+
13201
+ // return {};
13202
+ // },
13203
+ // 'xu-ui-plugin': async function ($elm, val) {
13204
+ // var _session = SESSION_OBJ[SESSION_ID];
13205
+
13206
+ // for await (const [plugin_name, value] of Object.entries(val.value)) {
13207
+ // const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
13208
+ // if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
13209
+ // if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
13210
+ // const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
13211
+ // func.utils.load_css_on_demand(plugin_runtime_css_url);
13212
+ // }
13213
+
13214
+ // const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
13215
+
13216
+ // const plugin_index_resources = await import(plugin_index_src);
13217
+
13218
+ // let properties = _.cloneDeep(plugin_index_resources.properties);
13219
+ // for await (let [prop_name, prop_val] of Object.entries(properties)) {
13220
+ // prop_val.value = value?.attributes?.[prop_name];
13221
+ // if (value?.attributes?.[`xu-exp:${prop_name}`]) {
13222
+ // const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
13223
+ // prop_val.value = res.result;
13224
+ // }
13225
+ // }
13226
+ // // $elm.data().xu_ui_plugin = { properties };
13227
+ // const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
13228
+
13229
+ // const plugin_runtime_resources = await import(plugin_runtime_src);
13230
+
13231
+ // if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
13232
+ // for await (const resource of plugin_runtime_resources.cdn) {
13233
+ // await load_cdn(resource);
13234
+ // }
13235
+ // }
13236
+
13237
+ // if (plugin_runtime_resources.fn) {
13238
+ // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
13239
+ // // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
13240
+ // }
13241
+ // }
13242
+ // }
13243
+
13244
+ // return {};
13245
+ // },
13246
+ // 'xu-store': async function ($elm, val) {
13247
+ // try {
13248
+ // const fields_obj = JSON5.parse(val.value);
13249
+ // for (const [field_id, value] of Object.entries(fields_obj)) {
13250
+ // func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
13251
+ // }
13252
+ // } catch (err) {
13253
+ // console.error(err);
13254
+ // }
13255
+ // return {};
13256
+ // },
13257
+ // 'xu-viewport': async function ($elm, val) {
13258
+ // // functionality in draw_html_element
13259
+ // return {};
13260
+ // },
13261
+ // };
13262
+
13263
+ // if (nodeP.tagName.substr(0, 3) === 'xu-') {
13264
+ // if (xu_func === 'xu-exp') {
13265
+ // return common_fx[xu_func]($elm, val);
13266
+ // }
13267
+
13268
+ // if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
13269
+ // let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
13270
+ // return ret;
13271
+ // }
13272
+ // // if (xu_func !== "tree_id")
13273
+ // console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
13274
+ // return {};
13275
+ // }
13276
+ // if (_.isEmpty($elm.data())) {
13277
+ // return {};
13278
+ // }
13279
+ // if (!$elm.data().xuData.debug_info.attribute_stat) {
13280
+ // $elm.data().xuData.debug_info.attribute_stat = {};
13281
+ // }
13282
+ // if (xu_func !== 'xu-exp') {
13283
+ // $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
13284
+ // }
13285
+ // try {
13286
+ // if (!common_fx[xu_func]) {
13287
+ // console.warn('invalid xu-tag', xu_func, error);
13288
+ // return {};
13289
+ // }
13290
+
13291
+ // return await common_fx[xu_func]($elm, val);
13292
+ // } catch (error) {
13293
+ // debugger;
13294
+ // }
13295
+ // };
13296
+
13297
+ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, xu_func, $elm, val, is_init, refreshed_ds) {
13298
+ if (is_skeleton) return;
13299
+
13300
+ // Cache frequently accessed values
13301
+ const _session = SESSION_OBJ[SESSION_ID];
13302
+ const _ds = _session.DS_GLB[paramsP.dsSessionP];
13303
+ const elmData = $elm.data();
13304
+ const xuData = elmData.xuData;
13305
+ const nodeTag = nodeP.tagName;
13306
+ const isXuTag = nodeTag && nodeTag.startsWith('xu-');
13307
+
13308
+ const load_cdn = async function (resource) {
13309
+ if (!_.isObject(resource)) {
13310
+ resource = _.isString(resource) ? { src: resource, type: 'js' } : null;
13311
+ }
13312
+ if (!resource) {
13313
+ throw new Error('cdn resource in wrong format');
13314
+ }
13315
+
13316
+ try {
13317
+ const loadFn = resource.type === 'css' ? func.utils.load_css_on_demand : func.utils.load_js_on_demand;
13318
+ const moduleArg = resource.type === 'module' ? 'module' : undefined;
13319
+ await loadFn(resource.src, moduleArg);
13320
+ } catch (error) {
13321
+ func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource.src, 'W');
13322
+ }
13323
+ };
13324
+
13325
+ const common_fx = {
13326
+ 'xu-attrs': async function ($elm, val) {
13327
+ if (!val.value || !_.isObject(val.value)) {
13328
+ if (val.value) throw 'xu-attrs value is not an object';
13329
+ return {};
13330
+ }
13331
+ Object.assign(nodeP.attributes, val.value);
13332
+ return {};
13333
+ },
13334
+
13335
+ 'xu-ref': async function ($elm, val, dsSession) {
13336
+ if (!val.value) return {};
13337
+
13338
+ func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
13339
+
13340
+ const targetNode = $elm[0];
13341
+ if (!targetNode) return {};
13342
+
13343
+ const observer = new MutationObserver(() => {
13344
+ func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
13345
+ });
13346
+
13347
+ observer.observe(targetNode, { attributes: true, childList: true, subtree: true });
13348
+ return {};
13349
+ },
13350
+
13351
+ 'xu-bind': async function ($elm, val) {
13352
+ if (is_skeleton) return {};
13353
+
13354
+ let val_is_reference_field = false;
13355
+ let _prog_id = xuData.paramsP.prog_id;
13356
+ let _dsP = xuData.paramsP.dsSessionP;
13357
+
13358
+ const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
13359
+ if (!view_ret) return {};
13360
+
13361
+ let is_dynamic_field = false;
13362
+ let field_prop;
13363
+ let bind_field_id;
13364
+ const input_field_type = $elm.attr('type');
13365
+
13366
+ const get_bind_field = async function (field_id) {
13367
+ if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
13368
+ is_dynamic_field = true;
13369
+ field_prop = _ds.dynamic_fields[field_id];
13370
+ } else {
13371
+ field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
13372
+ if (!field_prop) {
13373
+ const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
13374
+ if (ret_get_value.found) {
13375
+ _dsP = ret_get_value.dsSessionP;
13376
+ const ds = _session.DS_GLB[_dsP];
13377
+ _prog_id = ds.prog_id;
13378
+ const new_view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
13379
+ if (!new_view_ret) return {};
13380
+ field_prop = func.common.find_item_by_key(new_view_ret.progFields, 'field_id', field_id);
13381
+ }
13382
+ if (!field_prop) {
13383
+ throw `field ${field_id} not found in the program scope`;
13384
+ }
13385
+ }
13386
+ }
13387
+ return field_id;
13388
+ };
13389
+
13390
+ try {
13391
+ bind_field_id = await get_bind_field(val.value.split('.')[0]);
13392
+ val_is_reference_field = true;
13393
+ } catch (err) {
13394
+ console.error(err?.message || err);
13395
+ return {};
13396
+ }
13397
+
13398
+ const field_changed = async function (e) {
13399
+ const ds = _session.DS_GLB[_dsP];
13400
+ const fieldType = field_prop.props.fieldType;
13401
+ const isCheckbox = input_field_type === 'checkbox';
13402
+ const isRadio = input_field_type === 'radio';
13403
+
13404
+ // Handle array field with checkbox
13405
+ if (fieldType === 'array' && isCheckbox && val_is_reference_field) {
13406
+ const arr_value = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, ds.currentRecordId)).ret.value);
13407
+ const value_from_getter = bind.getter($elm[0]);
13408
+ const value = arr_value.includes(value_from_getter) ? arr_value.filter((item) => !_.isEqual(item, value_from_getter)) : [...arr_value, value_from_getter];
13409
+
13410
+ return await func.datasource.update(SESSION_ID, {
13411
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: value } },
13412
+ });
13413
+ }
13414
+
13415
+ // Handle array field with radio
13416
+ if (fieldType === 'array' && isRadio && val_is_reference_field) {
13417
+ return await func.datasource.update(SESSION_ID, {
13418
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: [bind.getter($elm[0])] } },
13419
+ });
13420
+ }
13421
+
13422
+ let value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', fieldType, bind.getter($elm[0]));
13423
+
13424
+ if (fieldType === 'object') {
13425
+ value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
13426
+ }
13427
+
13428
+ if (!ds.currentRecordId) return;
13429
+
13430
+ await func.datasource.update(SESSION_ID, {
13431
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: value } },
13432
+ });
13433
+
13434
+ const iterate_info = xuData?.iterate_info;
13435
+ const reference_source_obj = iterate_info?.reference_source_obj;
13436
+
13437
+ if (reference_source_obj?.ret?.type === 'array' && iterate_info.iterator_val === bind_field_id) {
13438
+ const arr_idx = Number(iterate_info._key);
13439
+ const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
13440
+ const new_arr = _.cloneDeep(dataset_arr.ret.value);
13441
+
13442
+ if (fieldType === 'object' && val_is_reference_field) {
13443
+ let obj_item = new_arr[arr_idx];
13444
+ const e_exp = val.value.replace(bind_field_id, 'obj_item');
13445
+ eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
13446
+ new_arr[arr_idx] = obj_item;
13447
+ } else {
13448
+ new_arr[arr_idx] = value;
13449
+ }
13450
+
13451
+ await func.datasource.update(
13452
+ SESSION_ID,
13453
+ {
13454
+ [_dsP]: { [ds.currentRecordId]: { [reference_source_obj.fieldIdP]: new_arr } },
13455
+ },
13456
+ null,
13457
+ true,
13458
+ );
13459
+ }
13460
+
13461
+ await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, ds.parentDataSourceNo);
13462
+ };
13463
+
13464
+ const bind = new UI_FRAMEWORK_PLUGIN.bind();
13465
+ bind.listener($elm[0], field_changed);
13466
+
13467
+ const set_value = function () {
13468
+ const ds = _session.DS_GLB[paramsP.dsSessionP];
13469
+ if (!ds.currentRecordId) return;
13470
+
13471
+ try {
13472
+ let value;
13473
+ if (val_is_reference_field) {
13474
+ if (is_dynamic_field) {
13475
+ value = ds.dynamic_fields[bind_field_id].value;
13476
+ } else {
13477
+ const row_idx = func.common.find_ROWID_idx(ds, ds.currentRecordId);
13478
+ value = ds.data_feed.rows?.[row_idx]?.[bind_field_id];
13479
+ }
13480
+
13481
+ const fieldType = field_prop.props.fieldType;
13482
+ const elmValue = $elm.attr('value');
13483
+
13484
+ if (fieldType === 'array' && input_field_type === 'checkbox' && elmValue) {
13485
+ value = value.includes(elmValue);
13486
+ } else if (fieldType === 'array' && input_field_type === 'radio' && elmValue) {
13487
+ value = value.includes(elmValue) ? elmValue : false;
13488
+ } else if (fieldType === 'object' && val.value.split('.').length > 1) {
13489
+ value = eval(val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')'));
13490
+ }
12609
13491
  } else {
12610
13492
  value = val.value;
12611
13493
  }
12612
- if (typeof value === 'undefined') return;
12613
- bind.setter($elm[0], value);
13494
+
13495
+ if (value !== undefined) {
13496
+ bind.setter($elm[0], value);
13497
+ }
12614
13498
  } catch (err) {
12615
13499
  console.error(err);
12616
13500
  }
12617
13501
  };
12618
- /// init value from ds
12619
- $('body').on('xu-bind-refresh.' + _ds.dsSession.toString(), () => {
12620
- set_value();
12621
- });
12622
13502
 
13503
+ $('body').on('xu-bind-refresh.' + _ds.dsSession, set_value);
12623
13504
  set_value();
12624
13505
  return {};
12625
13506
  },
13507
+
12626
13508
  'xu-render': async function ($elm, val, from_panel) {
12627
- const old_render = async function () {
12628
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
13509
+ const value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
13510
+
13511
+ if (!glb.new_xu_render) {
13512
+ // Old render logic (kept as is for compatibility)
12629
13513
  const init_render = function () {
12630
13514
  if (!value) {
12631
- var cloned_$div = $elm.clone(true);
12632
-
12633
- let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container); //.hide();
12634
- let original_data_obj = {
13515
+ const cloned_$div = $elm.clone(true);
13516
+ const $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container);
13517
+ const original_data_obj = {
12635
13518
  $container: cloned_$div,
12636
13519
  nodeP: _.cloneDeep(nodeP),
12637
13520
  parent_infoP,
@@ -12644,8 +13527,6 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
12644
13527
  $xurender.data().xuData.original_data_obj = original_data_obj;
12645
13528
  $xurender.data().xuData.xurender_node = cloned_$div;
12646
13529
  $xurender.data().xuAttributes = nodeP.attributes || {};
12647
- // $xurender.hide();
12648
-
12649
13530
  $elm.remove();
12650
13531
  return { abort: true };
12651
13532
  }
@@ -12655,271 +13536,207 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
12655
13536
  const post_render = async function () {
12656
13537
  if (value) {
12657
13538
  try {
12658
- // abort if already rended
12659
- if ($elm[0].tagName !== 'XURENDER' && $elm?.length) {
13539
+ if ($elm[0].tagName !== 'XURENDER' || !$elm?.length) {
12660
13540
  return func.events.delete_job(SESSION_ID, jobNoP);
12661
13541
  }
12662
13542
 
12663
- let original_data_obj = $elm.data().xuData.original_data_obj;
12664
-
13543
+ const original_data_obj = $elm.data().xuData.original_data_obj;
12665
13544
  if (!original_data_obj) {
12666
13545
  func.events.delete_job(SESSION_ID, jobNoP);
12667
13546
  return { delete_job: jobNoP };
12668
13547
  }
12669
13548
 
12670
- const new_$div = await func.UI.screen.render_ui_tree(
12671
- SESSION_ID,
12672
- $elm, //original_data_obj.$container,
12673
- _.cloneDeep(original_data_obj.nodeP),
12674
- original_data_obj.parent_infoP,
12675
- original_data_obj.paramsP,
12676
- jobNoP,
12677
- null,
12678
- original_data_obj.keyP,
12679
- null,
12680
- original_data_obj.parent_nodeP,
12681
- null,
12682
- original_data_obj.$root_container,
12683
- );
13549
+ const new_$div = await func.UI.screen.render_ui_tree(SESSION_ID, $elm, _.cloneDeep(original_data_obj.nodeP), original_data_obj.parent_infoP, original_data_obj.paramsP, jobNoP, null, original_data_obj.keyP, null, original_data_obj.parent_nodeP, null, original_data_obj.$root_container);
12684
13550
 
12685
13551
  new_$div.data().xuData.original_data_obj = original_data_obj;
12686
13552
  new_$div.data().xuData.xurender_node = $elm.clone(true);
12687
13553
  new_$div.data().xuAttributes = $elm.data().xuAttributes || {};
12688
13554
 
12689
13555
  const replace = async function () {
12690
- $elm.replaceWith(new_$div);
13556
+ $elm.replaceWith(from_panel ? new_$div.children() : new_$div);
12691
13557
  if (from_panel) {
12692
- const xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
12693
- $elm.parent().data().xuPanelWrapper = xuPanelWrapper;
12694
- $elm.replaceWith(new_$div.children());
13558
+ $elm.parent().data().xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
12695
13559
  }
12696
-
12697
13560
  if (val.fields_arr) {
12698
13561
  return await func.UI.screen.refresh_xu_attributes(SESSION_ID, val.fields_arr, val.jobNoP, new_$div);
12699
13562
  }
12700
13563
  func.events.delete_job(SESSION_ID, jobNoP);
12701
13564
  };
12702
- // if ($elm && func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'xu_id', $elm.data().xuData.xu_id).length) {
12703
- if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length) {
12704
- if (new_$div.data().xuData.paramsP) {
12705
- return await replace();
12706
- }
12707
13565
 
12708
- func.events.delete_job(SESSION_ID, jobNoP);
13566
+ if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length && new_$div.data().xuData.paramsP) {
13567
+ return await replace();
12709
13568
  }
13569
+ func.events.delete_job(SESSION_ID, jobNoP);
12710
13570
  } catch (error) {
12711
13571
  func.events.delete_job(SESSION_ID, jobNoP);
12712
13572
  }
12713
13573
  return;
12714
13574
  }
12715
- // if (!value) {
13575
+
12716
13576
  if ($elm.prop('tagName') === 'XURENDER') {
12717
13577
  func.events.delete_job(SESSION_ID, jobNoP);
12718
13578
  return;
12719
13579
  }
12720
13580
 
12721
- let tmp_$div = $('<div>');
13581
+ const $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id'));
12722
13582
 
12723
- let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).appendTo(tmp_$div); //.hide();
12724
- // was true before
12725
13583
  if ($elm.data().xuData.xurender_node) {
12726
13584
  $xurender.data({
12727
13585
  xuAttributes: $elm.data().xuData.xurender_node.data().xuAttributes || {},
12728
13586
  xuData: $elm.data().xuData.xurender_node.data().xuData || {},
12729
13587
  });
12730
13588
  } else {
12731
- // default new state
12732
-
12733
13589
  $xurender.data({
12734
13590
  xuAttributes: $elm.data().xuAttributes || {},
12735
13591
  xuData: $elm.data().xuData || {},
12736
13592
  });
12737
- const original_data_obj = {
13593
+ $xurender.data().xuData.original_data_obj = {
12738
13594
  nodeP: _.cloneDeep($elm.data().xuData.node_org),
12739
13595
  paramsP: $elm.data().xuData.paramsP,
12740
13596
  $container: $elm.clone(true),
12741
13597
  parent_infoP: parent_infoP,
12742
13598
  };
12743
-
12744
- $xurender.data().xuData.original_data_obj = original_data_obj;
12745
13599
  }
12746
13600
 
12747
- //remove xu-teleport trace
12748
13601
  $.each($elm.find('xu-teleport'), (key, val) => {
12749
13602
  const xuTeleportData = $(val).data().xuTeleportData || [];
12750
- for (const teleported_elm_id of xuTeleportData) {
12751
- $(`[xu-ui-id="${teleported_elm_id}"]`).remove();
12752
- }
13603
+ xuTeleportData.forEach((id) => $(`[xu-ui-id="${id}"]`).remove());
12753
13604
  });
12754
13605
 
12755
- $elm.replaceWith(tmp_$div.children());
13606
+ $elm.replaceWith($xurender);
12756
13607
  func.events.delete_job(SESSION_ID, jobNoP);
12757
- // }
12758
13608
  };
12759
- if (is_init) {
12760
- return init_render();
12761
- }
12762
- return await post_render();
12763
- };
12764
13609
 
12765
- const new_render = async function () {
12766
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
12767
- const has_xu_render_attribute = true;
12768
- const has_xu_exp_render_attribute = $elm.data()?.xuData?.attr_exp_info?.['xu-render'] ? true : false;
12769
- const init_render = async function () {
12770
- nodeP.xu_render_made = value;
12771
- if (!value) {
12772
- if (has_xu_exp_render_attribute) {
12773
- return { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true };
12774
- }
12775
- return { has_xu_render_attribute, abort: true };
12776
- }
12777
- return { has_xu_exp_render_attribute, has_xu_render_attribute };
12778
- };
13610
+ return is_init ? init_render() : await post_render();
13611
+ }
12779
13612
 
12780
- const post_render = async function () {
12781
- // always come from refresh
12782
- let nodeP = $container.data().xuData.node.children[keyP];
12783
- nodeP.xu_render_made = value;
12784
- if (value) {
12785
- try {
12786
- const xu_render_cache_id = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
12787
- const xu_ui_id = $elm.attr('xu-ui-id');
12788
- let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[xu_ui_id + xu_render_cache_id]?.$div.clone(true);
12789
- let found_parent_vars = false;
12790
- if (new_$div) {
12791
- // validate if $div contains fields from parent ds
12792
- const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
12793
- const parent_fields = Object.keys(parent_data);
12794
-
12795
- $.each(new_$div.find('*'), (key, val) => {
12796
- const _xuAttributes = $(val)?.data()?.xuAttributes;
12797
- if (found_parent_vars || !_xuAttributes) return;
12798
- for (const [attr_key, attr_val] of Object.entries(_xuAttributes)) {
12799
- if (found_parent_vars) break;
12800
- for (const [key, val] of Object.entries(parent_fields)) {
12801
- if (attr_val.includes('@' + key)) {
12802
- found_parent_vars = true;
12803
- break;
12804
- }
12805
- }
12806
- }
12807
- });
12808
- }
13613
+ // New render logic
13614
+ const has_xu_render_attribute = true;
13615
+ const has_xu_exp_render_attribute = !!xuData?.attr_exp_info?.['xu-render'];
12809
13616
 
12810
- if (!new_$div || found_parent_vars) {
12811
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { paramsP };
12812
- nodeP.xu_render_xu_ui_id = xu_ui_id;
12813
- nodeP.xu_render_cache_id = xu_render_cache_id;
12814
- new_$div = await func.UI.screen.render_ui_tree(SESSION_ID, $container, nodeP, parent_infoP, paramsP, jobNoP, null, keyP, null, parent_nodeP, null, $root_container);
12815
- const _$div = new_$div.clone(true);
12816
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].$div = _$div;
12817
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].data = _$div.data();
12818
- }
12819
- // append order handling
13617
+ const init_render = async function () {
13618
+ nodeP.xu_render_made = value;
13619
+ if (!value) {
13620
+ return has_xu_exp_render_attribute ? { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true } : { has_xu_render_attribute, abort: true };
13621
+ }
13622
+ return { has_xu_exp_render_attribute, has_xu_render_attribute };
13623
+ };
12820
13624
 
12821
- if (!$container.children().length) {
12822
- new_$div.appendTo($container);
12823
- } else {
12824
- // iterate the container node
12825
- let $last_elm_found = [];
12826
- $.each($container.data().xuData.node.children, (item_key, item_val) => {
12827
- // const $elm = $(`[xu-node-id="${item_val.id}"]`);
12828
- const $elm = func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'nodeid', item_val.id);
12829
- if ($elm.length) {
12830
- $last_elm_found = $elm;
12831
- }
12832
- if (keyP == item_key) {
12833
- if ($last_elm_found.length) {
12834
- new_$div.after($last_elm_found);
12835
- } else {
12836
- $container.prepend(new_$div);
12837
- }
13625
+ const post_render = async function () {
13626
+ const containerNodeP = $container.data().xuData.node.children[keyP];
13627
+ containerNodeP.xu_render_made = value;
13628
+
13629
+ if (value) {
13630
+ try {
13631
+ const xu_render_cache_id = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys(xuData?.attr_exp_info?.['xu-render']?.fields || {}));
13632
+ const xu_ui_id = $elm.attr('xu-ui-id');
13633
+ const cache_key = xu_ui_id + xu_render_cache_id;
13634
+ let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[cache_key]?.$div?.clone(true);
13635
+ let found_parent_vars = false;
13636
+
13637
+ if (new_$div) {
13638
+ const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
13639
+ const parent_fields = Object.keys(parent_data);
13640
+
13641
+ $.each(new_$div.find('*'), (key, val) => {
13642
+ if (found_parent_vars) return;
13643
+ const _xuAttributes = $(val)?.data()?.xuAttributes;
13644
+ if (!_xuAttributes) return;
13645
+
13646
+ for (const attr_val of Object.values(_xuAttributes)) {
13647
+ if (parent_fields.some((field) => attr_val.includes('@' + field))) {
13648
+ found_parent_vars = true;
13649
+ break;
12838
13650
  }
12839
- });
12840
- }
12841
- } catch (error) {
12842
- func.events.delete_job(SESSION_ID, jobNoP);
13651
+ }
13652
+ });
12843
13653
  }
12844
- return;
12845
- }
12846
13654
 
12847
- /////////// !value ///////////
13655
+ if (!new_$div || found_parent_vars) {
13656
+ UI_WORKER_OBJ.xu_render_cache[cache_key] = { paramsP };
13657
+ containerNodeP.xu_render_xu_ui_id = xu_ui_id;
13658
+ containerNodeP.xu_render_cache_id = xu_render_cache_id;
12848
13659
 
12849
- const xu_ui_id = $elm.attr('xu-ui-id');
13660
+ new_$div = await func.UI.screen.render_ui_tree(SESSION_ID, $container, containerNodeP, parent_infoP, paramsP, jobNoP, null, keyP, null, parent_nodeP, null, $root_container);
12850
13661
 
12851
- const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
12852
- const _$div = $elm.clone(true);
12853
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
12854
- $elm.remove();
12855
- func.events.delete_job(SESSION_ID, jobNoP);
12856
- };
12857
- if (is_init) {
12858
- return await init_render();
13662
+ const _$div = new_$div.clone(true);
13663
+ UI_WORKER_OBJ.xu_render_cache[cache_key] = { $div: _$div, data: _$div.data(), paramsP };
13664
+ }
13665
+
13666
+ // Append order handling
13667
+ if (!$container.children().length) {
13668
+ new_$div.appendTo($container);
13669
+ } else {
13670
+ let $last_elm_found = [];
13671
+ $.each($container.data().xuData.node.children, (item_key, item_val) => {
13672
+ const $elm = func.UI.utils.find_in_element_data('xuData', $(_session.root_element), 'nodeid', item_val.id);
13673
+ if ($elm.length) $last_elm_found = $elm;
13674
+ if (keyP == item_key) {
13675
+ $last_elm_found.length ? new_$div.after($last_elm_found) : $container.prepend(new_$div);
13676
+ }
13677
+ });
13678
+ }
13679
+ } catch (error) {
13680
+ func.events.delete_job(SESSION_ID, jobNoP);
13681
+ }
13682
+ return;
12859
13683
  }
12860
- return await post_render();
13684
+
13685
+ // !value
13686
+ const xu_ui_id = $elm.attr('xu-ui-id');
13687
+ const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys(xuData?.attr_exp_info?.['xu-render']?.fields || {}));
13688
+ const _$div = $elm.clone(true);
13689
+ UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
13690
+ $elm.remove();
13691
+ func.events.delete_job(SESSION_ID, jobNoP);
12861
13692
  };
12862
13693
 
12863
- if (glb.new_xu_render) {
12864
- return new_render();
12865
- }
12866
- return old_render();
13694
+ return is_init ? await init_render() : await post_render();
12867
13695
  },
13696
+
12868
13697
  'xu-show': async function ($elm, val) {
12869
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
12870
- if (value) {
12871
- $elm.show();
12872
- }
12873
- if (!value) {
12874
- $elm.hide();
12875
- }
13698
+ const value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
13699
+ $elm.toggle(value);
12876
13700
  return {};
12877
13701
  },
13702
+
12878
13703
  'xu-content': async function ($elm, val) {
12879
13704
  try {
12880
13705
  $elm.html(val.value);
12881
13706
  } catch (error) {
12882
- console.warn(e);
13707
+ console.warn(error);
12883
13708
  }
12884
- return;
12885
13709
  },
13710
+
12886
13711
  'xu-text': async function ($elm, val) {
12887
13712
  try {
12888
13713
  $elm.text(val.value);
12889
13714
  } catch (error) {
12890
- console.warn(e);
13715
+ console.warn(error);
12891
13716
  }
12892
- return;
12893
13717
  },
13718
+
12894
13719
  'xu-html': async function ($elm, val) {
12895
13720
  try {
12896
13721
  $elm.html(val.value);
12897
13722
  } catch (error) {
12898
- console.warn(e);
13723
+ console.warn(error);
12899
13724
  }
12900
- return;
12901
13725
  },
13726
+
12902
13727
  'xu-for': async function ($elm, data) {
12903
- // exit if call from rendered xu-for item to prevent infante loop (parent_infoP?.iterate_info indicate call from rendered item)
12904
- if (parent_infoP?.iterate_info) return {};
12905
- if (!data.value) return {};
13728
+ if (parent_infoP?.iterate_info || !data.value) return {};
13729
+
12906
13730
  try {
12907
- // data.value (xu-for) can store actual values such as an array, a CSV, or a field_id that references a specific field within the dataset, initialized with values for the iteration.
12908
13731
  let arr = data.value;
12909
-
12910
- // find reference source field
12911
13732
  let reference_source_obj;
12912
-
12913
13733
  const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
13734
+ const view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
12914
13735
 
12915
- let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
12916
- // detect if data.value (xu-for) is reference field_id by checking if exist in the dataset
12917
13736
  if (view_field_obj) {
12918
- // xu-for is reference field_id
12919
13737
  reference_source_obj = await func.datasource.get_value(SESSION_ID, data.value, paramsP.dsSessionP);
12920
13738
  arr = reference_source_obj?.ret?.value;
12921
13739
  } else {
12922
- // xu-for is actual data
12923
13740
  if (typeof data.value === 'string') {
12924
13741
  arr = eval(data.value.replaceAll('\\', ''));
12925
13742
  }
@@ -12928,59 +13745,44 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
12928
13745
  }
12929
13746
  }
12930
13747
 
12931
- const custom_iterator_key = $elm.data().xuData.iterator_key;
12932
- const custom_iterator_val = $elm.data().xuData.iterator_val;
12933
-
12934
- let iterator_key = custom_iterator_key;
12935
- let iterator_val = custom_iterator_val;
12936
- let is_key_dynamic_field, is_val_dynamic_field;
12937
-
12938
- // custom FOR_VAL name or namespaced default name
12939
- if (!custom_iterator_key) {
12940
- is_key_dynamic_field = true;
12941
-
12942
- iterator_key = '_FOR_KEY';
12943
- }
13748
+ const custom_iterator_key = xuData.iterator_key;
13749
+ const custom_iterator_val = xuData.iterator_val;
13750
+ const iterator_key = custom_iterator_key || '_FOR_KEY';
13751
+ const iterator_val = custom_iterator_val || '_FOR_VAL';
13752
+ const is_key_dynamic_field = !custom_iterator_key;
13753
+ const is_val_dynamic_field = !custom_iterator_val;
12944
13754
 
12945
- if (!custom_iterator_val) {
12946
- is_val_dynamic_field = true;
12947
-
12948
- iterator_val = '_FOR_VAL';
12949
- }
12950
-
12951
- var i = 0;
12952
- for await (let [_key, _val] of Object.entries(arr)) {
12953
- if (_.isArray(arr)) {
12954
- _key = Number(_key);
12955
- }
13755
+ const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
13756
+ if (is_dynamic_field) {
13757
+ func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
13758
+ } else {
13759
+ const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
13760
+ const view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
12956
13761
 
12957
- const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
12958
- if (is_dynamic_field) {
12959
- func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
12960
- } else {
12961
- const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
12962
-
12963
- let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
12964
- if (view_field_obj) {
12965
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12966
- try {
12967
- const row_idx = func.common.find_ROWID_idx(_ds, currentRecordId);
12968
- _ds.data_feed.rows[row_idx][field_id] = value;
12969
- } catch (err) {
12970
- console.error(err);
12971
- }
12972
- } else {
12973
- console.error('field not exist in dataset for xu-for method');
13762
+ if (view_field_obj) {
13763
+ const ds = _session.DS_GLB[paramsP.dsSessionP];
13764
+ try {
13765
+ const row_idx = func.common.find_ROWID_idx(ds, currentRecordId);
13766
+ ds.data_feed.rows[row_idx][field_id] = value;
13767
+ } catch (err) {
13768
+ console.error(err);
12974
13769
  }
13770
+ } else {
13771
+ console.error('field not exist in dataset for xu-for method');
12975
13772
  }
12976
- };
13773
+ }
13774
+ };
13775
+
13776
+ const currentRecordId = _ds.currentRecordId.toString();
13777
+ let i = 0;
12977
13778
 
12978
- var currentRecordId = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId.toString();
13779
+ for (let [_key, _val] of Object.entries(arr)) {
13780
+ if (_.isArray(arr)) _key = Number(_key);
12979
13781
 
12980
13782
  await set_value(is_key_dynamic_field, currentRecordId, iterator_key, _key);
12981
13783
  await set_value(is_val_dynamic_field, currentRecordId, iterator_val, _val);
12982
13784
 
12983
- var iterate_info = {
13785
+ const iterate_info = {
12984
13786
  _val,
12985
13787
  _key,
12986
13788
  iterator_key,
@@ -12989,26 +13791,13 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
12989
13791
  is_val_dynamic_field,
12990
13792
  reference_source_obj,
12991
13793
  };
12992
- // let _parent_info = _.cloneDeep(parent_infoP) || {};
12993
- let _parent_info = klona.klona(parent_infoP) || {};
13794
+
13795
+ const _parent_info = klona.klona(parent_infoP) || {};
12994
13796
  _parent_info.iterate_info = iterate_info;
12995
13797
 
12996
- const $divP = await func.UI.screen.render_ui_tree(
12997
- SESSION_ID,
12998
- $container,
12999
- nodeP,
13000
- _parent_info, //parent_infoP ? _.cloneDeep(_parent_info) : null,
13001
- paramsP,
13002
- jobNoP,
13003
- null,
13004
- i,
13005
- null,
13006
- nodeP,
13007
- null,
13008
- $root_container,
13009
- );
13798
+ const $divP = await func.UI.screen.render_ui_tree(SESSION_ID, $container, nodeP, _parent_info, paramsP, jobNoP, null, i, null, nodeP, null, $root_container);
13010
13799
 
13011
- $.each($divP.children(), function (key, val) {
13800
+ $.each($divP.children(), (key, val) => {
13012
13801
  if ($(val)?.data()?.xuData) {
13013
13802
  $(val).data().xuData.iterate_info = iterate_info;
13014
13803
  }
@@ -13016,106 +13805,87 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
13016
13805
 
13017
13806
  i++;
13018
13807
  }
13808
+
13019
13809
  $elm.remove();
13020
13810
  return { abort: true };
13021
13811
  } catch (e) {
13022
- console.error(' Iterator Arr parse error');
13812
+ console.error('Iterator Arr parse error', e);
13023
13813
  return { abort: true };
13024
13814
  }
13025
13815
  },
13816
+
13026
13817
  'xu-for-key': async function ($elm, val) {
13027
- $elm.data().xuData.iterator_key = val.value;
13818
+ xuData.iterator_key = val.value;
13028
13819
  return {};
13029
13820
  },
13821
+
13030
13822
  'xu-for-val': async function ($elm, val) {
13031
- $elm.data().xuData.iterator_val = val.value;
13823
+ xuData.iterator_val = val.value;
13032
13824
  return {};
13033
13825
  },
13826
+
13034
13827
  'xu-class': async function ($elm, val) {
13035
13828
  try {
13036
- const classes_string = val.value;
13037
- // let obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
13829
+ const classes_obj = _.isString(val.value) ? JSON.parse(val.value) : _.defaults(val.value, {});
13038
13830
 
13039
- const classes_obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
13040
- for await (const [cla, cond] of Object.entries(classes_obj)) {
13041
- let res = await func.expression.get(
13042
- SESSION_ID,
13043
- cond,
13044
- paramsP.dsSessionP,
13045
- 'UI Attr EXP',
13046
- $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
13047
- null,
13048
- null,
13049
- null,
13050
- null,
13051
- null,
13052
- $elm.data().xuData.iterate_info,
13053
- );
13054
-
13055
- if (res.result) {
13056
- $elm.addClass(cla);
13057
- } else {
13058
- $elm.removeClass(cla);
13059
- }
13831
+ for (const [cla, cond] of Object.entries(classes_obj)) {
13832
+ const res = await func.expression.get(SESSION_ID, cond, paramsP.dsSessionP, 'UI Attr EXP', xuData.currentRecordId, null, null, null, null, null, xuData.iterate_info);
13060
13833
 
13061
- $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
13834
+ $elm.toggleClass(cla, res.result);
13062
13835
  }
13836
+
13837
+ xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
13063
13838
  return {};
13064
13839
  } catch (e) {
13065
13840
  console.warn('parse error:' + val.value);
13066
13841
  return { abort: true };
13067
13842
  }
13068
13843
  },
13069
- 'xu-exp': async function ($elm, val) {
13070
- let exp = val.value === null ? true : val.value;
13071
-
13072
- let exp_ret = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId, null, null, null, null, null, $elm.data().xuData.iterate_info);
13073
13844
 
13074
- let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
13845
+ 'xu-exp': async function ($elm, val) {
13846
+ const exp = val.value === null ? true : val.value;
13847
+ const exp_ret = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId, null, null, null, null, null, xuData.iterate_info);
13075
13848
 
13076
- var new_val = {
13077
- key: val.key,
13078
- value,
13079
- };
13849
+ const value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
13850
+ const new_val = { key: val.key, value };
13080
13851
 
13081
- if (nodeP.tagName.substr(0, 3) === 'xu-') {
13082
- if (tag_fx[nodeP.tagName][new_val.key]) {
13083
- return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
13852
+ if (isXuTag) {
13853
+ if (tag_fx[nodeTag]?.[new_val.key]) {
13854
+ return await tag_fx[nodeTag][new_val.key]($elm, new_val);
13084
13855
  }
13085
- console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
13856
+ console.warn(`attribute ${new_val.key} not found for ${nodeTag}`);
13086
13857
  return {};
13087
13858
  }
13088
- if (!$elm.data().xuData) return;
13089
-
13090
- $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
13091
13859
 
13092
- // IGNORE UNDEFINED or NULL ATTRIBUTES
13093
- if (typeof new_val.value === 'undefined' || new_val.value === null) {
13094
- return {};
13095
- }
13860
+ if (!xuData) return {};
13861
+ xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
13096
13862
 
13097
- // IGNORE ATTRIBUTES WITH EMPTY VALUES
13098
- if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
13099
- return {};
13100
- }
13863
+ if (new_val.value === undefined || new_val.value === null) return {};
13864
+ if (glb.solid_attributes.includes(new_val.key) && !new_val.value) return {};
13101
13865
 
13102
- if (new_val.key.substr(0, 2) === 'xu') {
13866
+ if (new_val.key.startsWith('xu')) {
13103
13867
  return await common_fx[new_val.key]($elm, new_val);
13104
13868
  }
13105
13869
 
13106
13870
  $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
13107
13871
  return {};
13108
13872
  },
13873
+
13109
13874
  'xu-on': async function ($elm, val) {
13110
13875
  CLIENT_ACTIVITY_TS = Date.now();
13111
13876
  const trigger = val.key.split('xu-on:')[1].toLowerCase();
13877
+
13112
13878
  $elm.on(trigger, async function (evt) {
13113
13879
  const _$elm = $(evt.currentTarget);
13114
- if (_.isEmpty(_$elm.data().xuAttributes)) return;
13880
+ const xuAttributes = _$elm.data().xuAttributes;
13881
+ if (_.isEmpty(xuAttributes)) return;
13882
+
13883
+ const handlers = xuAttributes['xu-on:' + evt.type];
13884
+ if (!handlers) return;
13115
13885
 
13116
- for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
13886
+ for (const [key, val] of Object.entries(handlers)) {
13117
13887
  if (!_.isEmpty(val.props.condition)) {
13118
- const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
13888
+ const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid);
13119
13889
  if (!expCond.result) continue;
13120
13890
  }
13121
13891
 
@@ -13123,18 +13893,9 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
13123
13893
  evt[val.event_modifiers]();
13124
13894
  }
13125
13895
 
13126
- // if (val.handler === 'custom') {
13127
13896
  if (val.workflow) {
13128
- // do BL
13129
- for await (const [key2, val2] of Object.entries(val.workflow)) {
13130
- // var cond = val2.data.enabled;
13131
- // if (val2.data.enabled && val2.props.condition) {
13132
- // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
13133
- // cond = expCond.result;
13134
- // }
13135
- // if (!cond) continue;
13136
-
13137
- if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
13897
+ for (const [key2, val2] of Object.entries(val.workflow)) {
13898
+ if (!val2.data.enabled) continue;
13138
13899
 
13139
13900
  func.events.add_to_queue(SESSION_ID, 'element event', val2.id, evt.type, val2.data.action, val2.data.name, null, _$elm.attr('xu-ui-id'), null, evt, null, null, null, paramsP.dsSessionP, null, null, null, evt.type, val2.data.name, null, null, val2, null, null, null, null, null, null);
13140
13901
  }
@@ -13143,111 +13904,91 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
13143
13904
  });
13144
13905
  return {};
13145
13906
  },
13907
+
13146
13908
  'xu-script': async function ($elm, val) {
13147
- var checkExist = setInterval(async function () {
13909
+ const checkExist = setInterval(async function () {
13148
13910
  if ($elm.is(':visible')) {
13149
13911
  try {
13150
- // var res = eval('(' + val.value + ')');
13151
- // const fn = `(function(el) {
13152
- // ${val.value}
13153
- // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
13154
-
13155
- const fn = `async (el)=>{${val.value} };`;
13156
-
13157
- var res = eval(fn);
13158
- await res($elm[0]);
13159
- // if (typeof res === 'function') {
13160
- // res($elm[0]);
13161
- // }
13912
+ const fn = eval(`async (el)=>{${val.value}}`);
13913
+ await fn($elm[0]);
13162
13914
  } catch (e) {
13163
13915
  eval(val.value);
13164
13916
  }
13165
-
13166
13917
  clearInterval(checkExist);
13167
13918
  }
13168
- }, 100); // check every 100ms
13169
-
13170
- return {};
13171
- },
13172
- 'xu-style-global': async function ($elm, val) {
13173
- $('head').append(`<style>${val.value}</style>`);
13919
+ }, 100);
13174
13920
  return {};
13175
13921
  },
13176
- 'xu-style': async function ($elm, val) {
13177
- var cssString = val.value;
13178
-
13179
- var parser = new cssjs();
13180
13922
 
13181
- var parsed = parser.parseCSS(cssString);
13182
- var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
13183
-
13184
- $.each(parsed, function (key, val) {
13185
- var selectors_arr = val.selector.split(',');
13186
-
13187
- $.each(selectors_arr, function (key2, val2) {
13188
- selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
13189
- // console.log(new_selector);
13190
- });
13923
+ 'xu-style-global': async function ($elm, val) {
13924
+ $('head').append(`<style>${val.value}</style>`);
13925
+ return {};
13926
+ },
13191
13927
 
13192
- val.selector = selectors_arr.join(',');
13193
- // console.log(parsed);
13928
+ 'xu-style': async function ($elm, val) {
13929
+ const parser = new cssjs();
13930
+ const parsed = parser.parseCSS(val.value);
13931
+ const xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
13932
+
13933
+ parsed.forEach((rule) => {
13934
+ rule.selector = rule.selector
13935
+ .split(',')
13936
+ .map((sel) => `${xuUiId} ${sel}, ${xuUiId}${sel}`)
13937
+ .join(',');
13194
13938
  });
13195
13939
 
13196
- var newCSSString = parser.getCSSForEditor(parsed);
13197
-
13198
- $('head').append(`<style>${newCSSString}</style>`);
13940
+ $('head').append(`<style>${parser.getCSSForEditor(parsed)}</style>`);
13199
13941
  return {};
13200
13942
  },
13943
+
13201
13944
  'xu-cdn': async function ($elm, val) {
13202
- for await (const [key, resource] of Object.entries(val.value)) {
13945
+ for (const resource of Object.values(val.value)) {
13203
13946
  await load_cdn(resource);
13204
13947
  }
13205
-
13206
13948
  return {};
13207
13949
  },
13208
- 'xu-ui-plugin': async function ($elm, val) {
13209
- var _session = SESSION_OBJ[SESSION_ID];
13210
13950
 
13211
- for await (const [plugin_name, value] of Object.entries(val.value)) {
13951
+ 'xu-ui-plugin': async function ($elm, val) {
13952
+ for (const [plugin_name, value] of Object.entries(val.value)) {
13212
13953
  const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
13213
- if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
13214
- if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
13215
- const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
13216
- func.utils.load_css_on_demand(plugin_runtime_css_url);
13217
- }
13218
13954
 
13219
- const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
13955
+ if (!_plugin?.installed || !_plugin?.manifest?.['runtime.mjs']?.exist || !_plugin?.manifest?.['index.mjs']?.exist || !value.enabled) continue;
13220
13956
 
13221
- const plugin_index_resources = await import(plugin_index_src);
13957
+ if (_plugin.manifest['runtime.mjs'].dist && _plugin.manifest['runtime.mjs'].css) {
13958
+ const css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
13959
+ func.utils.load_css_on_demand(css_url);
13960
+ }
13222
13961
 
13223
- let properties = _.cloneDeep(plugin_index_resources.properties);
13224
- for await (let [prop_name, prop_val] of Object.entries(properties)) {
13225
- prop_val.value = value?.attributes?.[prop_name];
13226
- if (value?.attributes?.[`xu-exp:${prop_name}`]) {
13227
- const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
13228
- prop_val.value = res.result;
13229
- }
13230
- }
13231
- // $elm.data().xu_ui_plugin = { properties };
13232
- const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
13962
+ const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
13233
13963
 
13234
- const plugin_runtime_resources = await import(plugin_runtime_src);
13964
+ const plugin_index_resources = await import(plugin_index_src);
13965
+ const properties = _.cloneDeep(plugin_index_resources.properties);
13235
13966
 
13236
- if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
13237
- for await (const resource of plugin_runtime_resources.cdn) {
13238
- await load_cdn(resource);
13239
- }
13967
+ for (const [prop_name, prop_val] of Object.entries(properties)) {
13968
+ prop_val.value = value?.attributes?.[prop_name];
13969
+ if (value?.attributes?.[`xu-exp:${prop_name}`]) {
13970
+ const res = await func.expression.get(SESSION_ID, value.attributes[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
13971
+ prop_val.value = res.result;
13240
13972
  }
13973
+ }
13974
+
13975
+ const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
13241
13976
 
13242
- if (plugin_runtime_resources.fn) {
13243
- await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
13244
- // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
13977
+ const plugin_runtime_resources = await import(plugin_runtime_src);
13978
+
13979
+ if (plugin_runtime_resources.cdn && _.isArray(plugin_runtime_resources.cdn)) {
13980
+ for (const resource of plugin_runtime_resources.cdn) {
13981
+ await load_cdn(resource);
13245
13982
  }
13246
13983
  }
13247
- }
13248
13984
 
13985
+ if (plugin_runtime_resources.fn) {
13986
+ await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
13987
+ }
13988
+ }
13249
13989
  return {};
13250
13990
  },
13991
+
13251
13992
  'xu-store': async function ($elm, val) {
13252
13993
  try {
13253
13994
  const fields_obj = JSON5.parse(val.value);
@@ -13259,43 +14000,135 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
13259
14000
  }
13260
14001
  return {};
13261
14002
  },
14003
+
13262
14004
  'xu-viewport': async function ($elm, val) {
13263
- // functionality in draw_html_element
13264
14005
  return {};
13265
14006
  },
13266
14007
  };
13267
14008
 
13268
- if (nodeP.tagName.substr(0, 3) === 'xu-') {
14009
+ const tag_fx = {
14010
+ 'xu-panel': {
14011
+ program: async function ($elm, val) {
14012
+ const init_program = async function () {
14013
+ async function render_panel() {
14014
+ const prog_id = val.value?.prog || val.value;
14015
+ const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
14016
+ const ret_panel = await func.UI.screen.init(SESSION_ID, prog_id, paramsP.screenId, _ds, $elm, null, _ds.currentRecordId, null, true, params_obj.params_res, 'initXu_panel', undefined, prog_id !== _ds.prog_id ? null : refreshed_ds, params_obj.params_raw);
14017
+
14018
+ const containerData = $container.data();
14019
+ if (containerData.xuData) {
14020
+ containerData.xuData.xuPanelProps = elmData.xuAttributes;
14021
+ containerData.xuData.xuPanelData = ret_panel.data();
14022
+ }
14023
+ return { $new_div: ret_panel };
14024
+ }
14025
+
14026
+ if (!val.value) val.value = '_empty_panel_program';
14027
+ return await render_panel();
14028
+ };
14029
+
14030
+ const alter_program = async function () {
14031
+ async function render_panel() {
14032
+ const program = val.value?.prog || val.value;
14033
+ const $wrapper = $('<div>');
14034
+ const $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, nodeP.attributes, null, null, null, $wrapper, '');
14035
+
14036
+ const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
14037
+ const ret_init = await func.UI.screen.init(SESSION_ID, program, paramsP.screenId, _ds, $div, null, _ds.currentRecordId, jobNoP, true, params_obj.params_res, 'alterXu_panel', undefined, undefined, params_obj.params_raw);
14038
+
14039
+ await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, ret_init, nodeP, $div.clone(true), jobNoP);
14040
+
14041
+ return { $new_div: ret_init, abort: true };
14042
+ }
14043
+
14044
+ if (!val.value) return { abort: true };
14045
+ await render_panel();
14046
+ return { abort: true };
14047
+ };
14048
+
14049
+ return is_init ? await init_program() : await alter_program();
14050
+ },
14051
+
14052
+ 'xu-render': async function ($elm, val) {
14053
+ return await common_fx['xu-render']($elm, val, true);
14054
+ },
14055
+
14056
+ 'xu-ref': async function ($elm, val) {
14057
+ return await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
14058
+ },
14059
+ },
14060
+
14061
+ 'xu-teleport': {
14062
+ to: async function ($elm, val) {
14063
+ if (!glb.new_xu_render && val.value) {
14064
+ if ($elm?.parent()?.data()?.xuData?.length) {
14065
+ $elm.parent().data('xuTeleportData', []);
14066
+ for (const [key, node] of Object.entries(nodeP.children)) {
14067
+ const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $(val.value), node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
14068
+ $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
14069
+ $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
14070
+ }
14071
+ $elm.remove();
14072
+ } else {
14073
+ $elm.data('xuTeleportData', []).attr('hidden', true);
14074
+ for (const [key, node] of Object.entries(nodeP.children)) {
14075
+ const $to_container = $(val.value);
14076
+ if (!$to_container?.length) {
14077
+ return console.error(`container ${val.value} for xuTeleportData not found`);
14078
+ }
14079
+ const $teleport_elm = await func.UI.screen.render_ui_tree(SESSION_ID, $to_container, node, parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, node, null, $root_container);
14080
+ $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
14081
+ $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
14082
+ }
14083
+ }
14084
+ return { abort: true };
14085
+ }
14086
+ return {};
14087
+ },
14088
+
14089
+ 'xu-render': async function ($elm, val) {
14090
+ return await common_fx['xu-render']($elm, val, true);
14091
+ },
14092
+
14093
+ 'xu-show': async function ($elm, val) {
14094
+ return await common_fx['xu-show']($elm, val, true);
14095
+ },
14096
+ },
14097
+ };
14098
+
14099
+ // Main execution logic
14100
+ if (isXuTag) {
13269
14101
  if (xu_func === 'xu-exp') {
13270
14102
  return common_fx[xu_func]($elm, val);
13271
14103
  }
13272
14104
 
13273
- if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
13274
- let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
13275
- return ret;
14105
+ if (tag_fx?.[nodeTag]?.[xu_func]) {
14106
+ return await tag_fx[nodeTag][xu_func]($elm, val);
13276
14107
  }
13277
- // if (xu_func !== "tree_id")
13278
- console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
13279
- return {};
13280
- }
13281
- if (_.isEmpty($elm.data())) {
14108
+
14109
+ console.warn(`attribute ${xu_func} not found for ${nodeTag}`);
13282
14110
  return {};
13283
14111
  }
13284
- if (!$elm.data().xuData.debug_info.attribute_stat) {
13285
- $elm.data().xuData.debug_info.attribute_stat = {};
14112
+
14113
+ if (_.isEmpty(elmData)) return {};
14114
+
14115
+ if (!xuData.debug_info.attribute_stat) {
14116
+ xuData.debug_info.attribute_stat = {};
13286
14117
  }
14118
+
13287
14119
  if (xu_func !== 'xu-exp') {
13288
- $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
14120
+ xuData.debug_info.attribute_stat[xu_func] = val.value;
13289
14121
  }
14122
+
13290
14123
  try {
13291
14124
  if (!common_fx[xu_func]) {
13292
- console.warn('invalid xu-tag', xu_func, error);
14125
+ console.warn('invalid xu-tag', xu_func);
13293
14126
  return {};
13294
14127
  }
13295
-
13296
14128
  return await common_fx[xu_func]($elm, val);
13297
14129
  } catch (error) {
13298
- debugger;
14130
+ console.error('execute_xu_functions error:', error);
14131
+ return {};
13299
14132
  }
13300
14133
  };
13301
14134
 
@@ -13318,62 +14151,408 @@ func.UI.screen.fix_val_defaults = function (key, val) {
13318
14151
  return ret;
13319
14152
  };
13320
14153
 
14154
+ // func.UI.screen.set_attributes_new = async function (SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $elm, is_init, execute_attributes = [], refreshed_ds) {
14155
+ // var done_exp = [];
14156
+
14157
+ // const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
14158
+ // if (!_ds) return { abort: true };
14159
+
14160
+ // const get_attr_value = async function (key) {
14161
+ // let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
14162
+ // if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
14163
+ // ret = await get_xuExp(key);
14164
+ // }
14165
+ // return ret;
14166
+ // };
14167
+
14168
+ // const get_xuExp = async function (attrib) {
14169
+ // if (is_skeleton) return;
14170
+ // if (glb.new_xu_render) {
14171
+ // let _xuData = $elm.data().xuData;
14172
+ // if (!_xuData.attr_exp_info) {
14173
+ // _xuData.attr_exp_info = {};
14174
+ // }
14175
+ // }
14176
+ // const attr = `xu-exp:${attrib}`;
14177
+
14178
+ // if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
14179
+ // // const attr = `xu-exp-${attrib}`;
14180
+ // var exp = nodeP.attributes[attr];
14181
+ // // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
14182
+
14183
+ // var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
14184
+ // if (glb.new_xu_render) {
14185
+ // _xuData.attr_exp_info[attrib] = res;
14186
+ // }
14187
+ // // nodeP.attributes[attr] = value; //{ value: value, res: res };
14188
+ // done_exp.push(attr);
14189
+ // return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
14190
+ // };
14191
+
14192
+ // var _ret = {};
14193
+ // if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
14194
+
14195
+ // for (let [key, val] of Object.entries(nodeP.attributes)) {
14196
+ // // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
14197
+ // if (key.substring(0, 6) === 'xu-exp') {
14198
+ // if (_.isEmpty(val)) {
14199
+ // delete nodeP.attributes[key];
14200
+ // continue;
14201
+ // }
14202
+ // const clean_key = key.split(':')[1];
14203
+ // if (typeof nodeP.attributes[clean_key] !== 'undefined') {
14204
+ // delete nodeP.attributes[clean_key];
14205
+ // }
14206
+ // }
14207
+ // // FIX abbreviations
14208
+ // if (glb.attr_abbreviations_arr.includes(key)) {
14209
+ // nodeP.attributes[`xu-on:${key.substring(3)}`] = [
14210
+ // {
14211
+ // handler: 'custom',
14212
+ // props: {},
14213
+ // event: [
14214
+ // {
14215
+ // id: Date.now(),
14216
+ // data: {
14217
+ // action: 'update',
14218
+ // name: { value: val },
14219
+ // enabled: true,
14220
+ // },
14221
+ // props: {},
14222
+ // },
14223
+ // ],
14224
+ // },
14225
+ // ];
14226
+ // delete nodeP.attributes[key];
14227
+ // }
14228
+ // }
14229
+
14230
+ // for (let [key, val] of Object.entries(nodeP.attributes)) {
14231
+ // // FIX STATIC DEFAULTS
14232
+ // val = func.UI.screen.fix_val_defaults(key, val);
14233
+
14234
+ // // REMOVE UNDEFINED or NULL ATTRIBUTES
14235
+ // if (typeof val === 'undefined' || val === null) {
14236
+ // delete nodeP.attributes[key];
14237
+ // }
14238
+
14239
+ // // REMOVE ATTRIBUTES WITH EMPTY VALUES
14240
+ // if (glb.solid_attributes.includes(key) && !val) {
14241
+ // delete nodeP.attributes[key];
14242
+ // }
14243
+ // }
14244
+
14245
+ // // XU-ATTRS
14246
+ // if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
14247
+ // const attr = 'xu-attrs';
14248
+ // let ret = await func.UI.screen.execute_xu_functions(
14249
+ // SESSION_ID,
14250
+ // is_skeleton,
14251
+ // $root_container,
14252
+ // nodeP,
14253
+ // $container,
14254
+ // paramsP,
14255
+ // parent_infoP,
14256
+ // jobNoP,
14257
+ // keyP,
14258
+ // parent_nodeP,
14259
+ // attr,
14260
+ // $elm,
14261
+ // {
14262
+ // key: attr,
14263
+ // value: await get_attr_value(attr),
14264
+ // },
14265
+ // is_init,
14266
+ // );
14267
+ // }
14268
+
14269
+ // // BEFORE
14270
+ // if (!_.isEmpty(nodeP.attributes)) {
14271
+ // for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
14272
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
14273
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
14274
+ // continue;
14275
+ // }
14276
+
14277
+ // if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
14278
+ // continue;
14279
+ // }
14280
+
14281
+ // if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
14282
+ // continue;
14283
+ // }
14284
+
14285
+ // let ret = await func.UI.screen.execute_xu_functions(
14286
+ // SESSION_ID,
14287
+ // is_skeleton,
14288
+ // $root_container,
14289
+ // nodeP,
14290
+ // $container,
14291
+ // paramsP,
14292
+ // parent_infoP,
14293
+ // jobNoP,
14294
+ // keyP,
14295
+ // parent_nodeP,
14296
+ // attr,
14297
+ // $elm,
14298
+ // {
14299
+ // key: attr,
14300
+
14301
+ // value: await get_attr_value(attr),
14302
+ // },
14303
+ // is_init,
14304
+ // );
14305
+ // _ret = _.assignIn(_ret, ret);
14306
+ // }
14307
+ // }
14308
+
14309
+ // // ALL
14310
+
14311
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
14312
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
14313
+ // if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
14314
+ // continue;
14315
+ // }
14316
+
14317
+ // const new_key = key.split(':')[0]; // break expression
14318
+ // if (
14319
+ // nodeP.tagName !== 'xu-panel' &&
14320
+ // nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
14321
+ // (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
14322
+ // ) {
14323
+ // // handle common html attributes
14324
+ // try {
14325
+ // $elm.get(0).setAttribute(key, val);
14326
+ // } catch (err) {
14327
+ // console.error(err.message);
14328
+ // }
14329
+
14330
+ // continue;
14331
+ // }
14332
+ // // handle xu attributes
14333
+ // try {
14334
+ // if ($elm?.data()?.xuAttributes) {
14335
+ // // in some cases xu data delete in purpose when refreshing the screen
14336
+ // $elm.data().xuAttributes[key] = val;
14337
+ // }
14338
+ // } catch (error) {
14339
+ // debugger;
14340
+ // console.error(error);
14341
+ // }
14342
+
14343
+ // if (new_key === 'xu-exp' || nodeP.attributes['xu-exp:' + new_key] || glb.run_xu_before.includes(new_key) || glb.run_xu_after.includes(new_key)) {
14344
+ // continue;
14345
+ // }
14346
+
14347
+ // if (new_key === 'xu-on') {
14348
+ // let ret = await func.UI.screen.execute_xu_functions(
14349
+ // SESSION_ID,
14350
+ // is_skeleton,
14351
+ // $root_container,
14352
+ // nodeP,
14353
+ // $container,
14354
+ // paramsP,
14355
+ // parent_infoP,
14356
+ // jobNoP,
14357
+ // keyP,
14358
+ // parent_nodeP,
14359
+ // 'xu-on',
14360
+ // $elm,
14361
+ // {
14362
+ // key: key,
14363
+ // // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
14364
+ // value: await get_attr_value(key),
14365
+ // },
14366
+ // is_init,
14367
+ // refreshed_ds,
14368
+ // );
14369
+ // _ret = _.assignIn(_ret, ret);
14370
+ // continue;
14371
+ // }
14372
+
14373
+ // let ret = await func.UI.screen.execute_xu_functions(
14374
+ // SESSION_ID,
14375
+ // is_skeleton,
14376
+ // $root_container,
14377
+ // nodeP,
14378
+ // $container,
14379
+ // paramsP,
14380
+ // parent_infoP,
14381
+ // jobNoP,
14382
+ // keyP,
14383
+ // parent_nodeP,
14384
+ // new_key,
14385
+ // $elm,
14386
+ // {
14387
+ // key: key,
14388
+ // // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
14389
+ // value: await get_attr_value(key),
14390
+ // },
14391
+ // is_init,
14392
+ // refreshed_ds,
14393
+ // );
14394
+
14395
+ // _ret = _.assignIn(_ret, ret);
14396
+ // }
14397
+
14398
+ // // EXP for
14399
+
14400
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
14401
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
14402
+
14403
+ // const attr = key.split('xu-exp:')[1];
14404
+
14405
+ // if (!attr) {
14406
+ // continue;
14407
+ // }
14408
+
14409
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
14410
+
14411
+ // if (done_exp.includes(key)) {
14412
+ // continue;
14413
+ // }
14414
+ // let ret = await func.UI.screen.execute_xu_functions(
14415
+ // SESSION_ID,
14416
+ // is_skeleton,
14417
+ // $root_container,
14418
+ // nodeP,
14419
+ // $container,
14420
+ // paramsP,
14421
+ // parent_infoP,
14422
+ // jobNoP,
14423
+ // keyP,
14424
+ // parent_nodeP,
14425
+ // 'xu-exp',
14426
+ // $elm,
14427
+ // {
14428
+ // key: attr,
14429
+ // value: val,
14430
+ // },
14431
+ // true,
14432
+ // refreshed_ds,
14433
+ // );
14434
+ // _ret = _.assignIn(_ret, ret);
14435
+ // }
14436
+
14437
+ // // AFTER
14438
+
14439
+ // for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
14440
+ // if ($container?.data()?.xuData?.pending_to_delete) break;
14441
+
14442
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
14443
+
14444
+ // if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
14445
+
14446
+ // let ret = await func.UI.screen.execute_xu_functions(
14447
+ // SESSION_ID,
14448
+ // is_skeleton,
14449
+ // $root_container,
14450
+ // nodeP,
14451
+ // $container,
14452
+ // paramsP,
14453
+ // parent_infoP,
14454
+ // jobNoP,
14455
+ // keyP,
14456
+ // parent_nodeP,
14457
+ // attr,
14458
+ // $elm,
14459
+ // {
14460
+ // key: attr,
14461
+ // // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
14462
+ // value: await get_attr_value(attr),
14463
+ // },
14464
+ // is_init,
14465
+ // refreshed_ds,
14466
+ // );
14467
+ // _ret = _.assignIn(_ret, ret);
14468
+ // }
14469
+
14470
+ // // REGISTER EVENTS ATTRIBUTES
14471
+
14472
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
14473
+ // if ($container?.data()?.xuData?.pending_to_delete) break;
14474
+ // if (!glb.html5_events_handler.includes(key)) break;
14475
+ // // $elm.attr(key, await get_xuExp(key)) || val;
14476
+ // $elm.attr(key, await get_xuExp(key)) || val;
14477
+ // }
14478
+
14479
+ // return _ret;
14480
+ // };
14481
+
13321
14482
  func.UI.screen.set_attributes_new = async function (SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $elm, is_init, execute_attributes = [], refreshed_ds) {
13322
- var done_exp = [];
14483
+ const done_exp = new Set(); // Use Set for O(1) lookups instead of array
13323
14484
 
13324
14485
  const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
13325
14486
  if (!_ds) return { abort: true };
13326
14487
 
14488
+ // Early return if not an element or no attributes
14489
+ if (nodeP.type !== 'element' || !nodeP.attributes) return {};
14490
+
14491
+ // Cache frequently accessed values
14492
+ const nodeAttrs = nodeP.attributes;
14493
+ const elmData = $elm.data();
14494
+ const xuData = elmData.xuData;
14495
+ const containerData = $container?.data();
14496
+ const containerXuData = containerData?.xuData;
14497
+
13327
14498
  const get_attr_value = async function (key) {
13328
- let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
13329
- if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
13330
- ret = await get_xuExp(key);
14499
+ const expKey = `xu-exp:${key}`;
14500
+ if (nodeAttrs.hasOwnProperty(expKey)) {
14501
+ return await get_xuExp(key);
13331
14502
  }
13332
- return ret;
14503
+ return func.UI.screen.fix_val_defaults(key, nodeAttrs[key]);
13333
14504
  };
13334
14505
 
13335
14506
  const get_xuExp = async function (attrib) {
13336
14507
  if (is_skeleton) return;
14508
+
14509
+ const attr = `xu-exp:${attrib}`;
14510
+ if (!nodeAttrs.hasOwnProperty(attr)) return;
14511
+
13337
14512
  if (glb.new_xu_render) {
13338
- let _xuData = $elm.data().xuData;
13339
- if (!_xuData.attr_exp_info) {
13340
- _xuData.attr_exp_info = {};
14513
+ if (!xuData.attr_exp_info) {
14514
+ xuData.attr_exp_info = {};
13341
14515
  }
13342
14516
  }
13343
- const attr = `xu-exp:${attrib}`;
13344
14517
 
13345
- if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
13346
- // const attr = `xu-exp-${attrib}`;
13347
- var exp = nodeP.attributes[attr];
13348
- // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
14518
+ const exp = nodeAttrs[attr];
14519
+ const res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
13349
14520
 
13350
- var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
13351
14521
  if (glb.new_xu_render) {
13352
- _xuData.attr_exp_info[attrib] = res;
14522
+ xuData.attr_exp_info[attrib] = res;
13353
14523
  }
13354
- // nodeP.attributes[attr] = value; //{ value: value, res: res };
13355
- done_exp.push(attr);
13356
- return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
13357
- };
13358
14524
 
13359
- var _ret = {};
13360
- if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
14525
+ done_exp.add(attr);
14526
+ return res.result;
14527
+ };
13361
14528
 
13362
- for (let [key, val] of Object.entries(nodeP.attributes)) {
13363
- // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
13364
- if (key.substring(0, 6) === 'xu-exp') {
14529
+ // Create Sets for O(1) lookups
14530
+ const html5EventsSet = new Set(glb.html5_events_handler);
14531
+ const executeAttrsSet = new Set(execute_attributes);
14532
+ const solidAttrsSet = new Set(glb.solid_attributes);
14533
+ const abbreviationsSet = new Set(glb.attr_abbreviations_arr);
14534
+ const runXuBeforeSet = new Set(Object.values(glb.run_xu_before));
14535
+ const runXuAfterSet = new Set(Object.values(glb.run_xu_after));
14536
+
14537
+ // Process attributes in a single pass where possible
14538
+ const attrsToDelete = [];
14539
+ const xuOnAttrs = {};
14540
+
14541
+ for (const [key, val] of Object.entries(nodeAttrs)) {
14542
+ // Handle xu-exp attributes
14543
+ if (key.startsWith('xu-exp:')) {
13365
14544
  if (_.isEmpty(val)) {
13366
- delete nodeP.attributes[key];
14545
+ attrsToDelete.push(key);
13367
14546
  continue;
13368
14547
  }
13369
- const clean_key = key.split(':')[1];
13370
- if (typeof nodeP.attributes[clean_key] !== 'undefined') {
13371
- delete nodeP.attributes[clean_key];
14548
+ const clean_key = key.slice(7); // 'xu-exp:'.length = 7
14549
+ if (nodeAttrs[clean_key] !== undefined) {
14550
+ attrsToDelete.push(clean_key);
13372
14551
  }
13373
14552
  }
13374
- // FIX abbreviations
13375
- if (glb.attr_abbreviations_arr.includes(key)) {
13376
- nodeP.attributes[`xu-on:${key.substring(3)}`] = [
14553
+ // Handle abbreviations
14554
+ else if (abbreviationsSet.has(key)) {
14555
+ xuOnAttrs[`xu-on:${key.slice(3)}`] = [
13377
14556
  {
13378
14557
  handler: 'custom',
13379
14558
  props: {},
@@ -13390,257 +14569,131 @@ func.UI.screen.set_attributes_new = async function (SESSION_ID, is_skeleton, $ro
13390
14569
  ],
13391
14570
  },
13392
14571
  ];
13393
- delete nodeP.attributes[key];
14572
+ attrsToDelete.push(key);
13394
14573
  }
13395
14574
  }
13396
14575
 
13397
- for (let [key, val] of Object.entries(nodeP.attributes)) {
13398
- // FIX STATIC DEFAULTS
13399
- val = func.UI.screen.fix_val_defaults(key, val);
14576
+ // Delete marked attributes
14577
+ for (const key of attrsToDelete) {
14578
+ delete nodeAttrs[key];
14579
+ }
13400
14580
 
13401
- // REMOVE UNDEFINED or NULL ATTRIBUTES
13402
- if (typeof val === 'undefined' || val === null) {
13403
- delete nodeP.attributes[key];
13404
- }
14581
+ // Add xu-on attributes
14582
+ Object.assign(nodeAttrs, xuOnAttrs);
13405
14583
 
13406
- // REMOVE ATTRIBUTES WITH EMPTY VALUES
13407
- if (glb.solid_attributes.includes(key) && !val) {
13408
- delete nodeP.attributes[key];
14584
+ // Clean up attributes
14585
+ for (const [key, val] of Object.entries(nodeAttrs)) {
14586
+ const fixedVal = func.UI.screen.fix_val_defaults(key, val);
14587
+
14588
+ if (fixedVal === undefined || fixedVal === null) {
14589
+ delete nodeAttrs[key];
14590
+ } else if (solidAttrsSet.has(key) && !fixedVal) {
14591
+ delete nodeAttrs[key];
14592
+ } else {
14593
+ nodeAttrs[key] = fixedVal;
13409
14594
  }
13410
14595
  }
13411
14596
 
14597
+ const _ret = {};
14598
+
14599
+ // Helper to check abort condition
14600
+ const shouldAbort = () => _ret.abort || containerXuData?.pending_to_delete;
14601
+
13412
14602
  // XU-ATTRS
13413
- if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
14603
+ if (nodeAttrs['xu-attrs'] || nodeAttrs['xu-exp:xu-attrs']) {
13414
14604
  const attr = 'xu-attrs';
13415
- let ret = await func.UI.screen.execute_xu_functions(
13416
- SESSION_ID,
13417
- is_skeleton,
13418
- $root_container,
13419
- nodeP,
13420
- $container,
13421
- paramsP,
13422
- parent_infoP,
13423
- jobNoP,
13424
- keyP,
13425
- parent_nodeP,
13426
- attr,
13427
- $elm,
13428
- {
13429
- key: attr,
13430
- value: await get_attr_value(attr),
13431
- },
13432
- is_init,
13433
- );
14605
+ await func.UI.screen.execute_xu_functions(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, attr, $elm, { key: attr, value: await get_attr_value(attr) }, is_init);
13434
14606
  }
13435
14607
 
13436
14608
  // BEFORE
13437
- if (!_.isEmpty(nodeP.attributes)) {
13438
- for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
13439
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
13440
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
13441
- continue;
13442
- }
13443
-
13444
- if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
13445
- continue;
13446
- }
14609
+ if (!_.isEmpty(nodeAttrs)) {
14610
+ for (const [key, attr] of Object.entries(glb.run_xu_before)) {
14611
+ if (shouldAbort()) break;
14612
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
13447
14613
 
13448
- if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
13449
- continue;
13450
- }
13451
-
13452
- let ret = await func.UI.screen.execute_xu_functions(
13453
- SESSION_ID,
13454
- is_skeleton,
13455
- $root_container,
13456
- nodeP,
13457
- $container,
13458
- paramsP,
13459
- parent_infoP,
13460
- jobNoP,
13461
- keyP,
13462
- parent_nodeP,
13463
- attr,
13464
- $elm,
13465
- {
13466
- key: attr,
14614
+ const expKey = `xu-exp:${attr}`;
14615
+ if (!nodeAttrs.hasOwnProperty(attr) && !nodeAttrs.hasOwnProperty(expKey)) continue;
14616
+ if (!nodeAttrs[expKey] && nodeAttrs.hasOwnProperty(attr) && func.UI.screen.fix_val_defaults(attr, nodeAttrs[attr]) === undefined) continue;
13467
14617
 
13468
- value: await get_attr_value(attr),
13469
- },
13470
- is_init,
13471
- );
13472
- _ret = _.assignIn(_ret, ret);
14618
+ const ret = await func.UI.screen.execute_xu_functions(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, attr, $elm, { key: attr, value: await get_attr_value(attr) }, is_init);
14619
+ Object.assign(_ret, ret);
13473
14620
  }
13474
14621
  }
13475
14622
 
13476
- // ALL
14623
+ // ALL - Process attributes
14624
+ const isXuPanel = nodeP.tagName === 'xu-panel';
14625
+ const isXuTeleport = nodeP.tagName === 'xu-teleport';
14626
+ const elmElement = $elm.get(0);
13477
14627
 
13478
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
13479
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
13480
- if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
13481
- continue;
13482
- }
14628
+ for (const [key, val] of Object.entries(nodeAttrs)) {
14629
+ if (shouldAbort()) break;
14630
+ if (html5EventsSet.has(key) || executeAttrsSet.has(key)) continue;
13483
14631
 
13484
- const new_key = key.split(':')[0]; // break expression
13485
- if (
13486
- nodeP.tagName !== 'xu-panel' &&
13487
- nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
13488
- (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
13489
- ) {
13490
- // handle common html attributes
14632
+ const colonIndex = key.indexOf(':');
14633
+ const new_key = colonIndex > -1 ? key.slice(0, colonIndex) : key;
14634
+
14635
+ if (!isXuPanel && !isXuTeleport && (!new_key.startsWith('xu-') || new_key.length < 3 || new_key[2] !== '-')) {
13491
14636
  try {
13492
- $elm.get(0).setAttribute(key, val);
14637
+ elmElement.setAttribute(key, val);
13493
14638
  } catch (err) {
13494
14639
  console.error(err.message);
13495
14640
  }
13496
-
13497
14641
  continue;
13498
14642
  }
13499
- // handle xu attributes
13500
- try {
13501
- if ($elm?.data()?.xuAttributes) {
13502
- // in some cases xu data delete in purpose when refreshing the screen
13503
- $elm.data().xuAttributes[key] = val;
13504
- }
13505
- } catch (error) {
13506
- debugger;
13507
- console.error(error);
14643
+
14644
+ // Store xu attributes
14645
+ if (elmData.xuAttributes) {
14646
+ elmData.xuAttributes[key] = val;
13508
14647
  }
13509
14648
 
13510
- if (new_key === 'xu-exp' || nodeP.attributes['xu-exp:' + new_key] || glb.run_xu_before.includes(new_key) || glb.run_xu_after.includes(new_key)) {
14649
+ const expKey = `xu-exp:${new_key}`;
14650
+ if (new_key === 'xu-exp' || nodeAttrs[expKey] || runXuBeforeSet.has(new_key) || runXuAfterSet.has(new_key)) {
13511
14651
  continue;
13512
14652
  }
13513
14653
 
13514
14654
  if (new_key === 'xu-on') {
13515
- let ret = await func.UI.screen.execute_xu_functions(
13516
- SESSION_ID,
13517
- is_skeleton,
13518
- $root_container,
13519
- nodeP,
13520
- $container,
13521
- paramsP,
13522
- parent_infoP,
13523
- jobNoP,
13524
- keyP,
13525
- parent_nodeP,
13526
- 'xu-on',
13527
- $elm,
13528
- {
13529
- key: key,
13530
- // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
13531
- value: await get_attr_value(key),
13532
- },
13533
- is_init,
13534
- refreshed_ds,
13535
- );
13536
- _ret = _.assignIn(_ret, ret);
14655
+ const ret = await func.UI.screen.execute_xu_functions(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, 'xu-on', $elm, { key: key, value: await get_attr_value(key) }, is_init, refreshed_ds);
14656
+ Object.assign(_ret, ret);
13537
14657
  continue;
13538
14658
  }
13539
14659
 
13540
- let ret = await func.UI.screen.execute_xu_functions(
13541
- SESSION_ID,
13542
- is_skeleton,
13543
- $root_container,
13544
- nodeP,
13545
- $container,
13546
- paramsP,
13547
- parent_infoP,
13548
- jobNoP,
13549
- keyP,
13550
- parent_nodeP,
13551
- new_key,
13552
- $elm,
13553
- {
13554
- key: key,
13555
- // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
13556
- value: await get_attr_value(key),
13557
- },
13558
- is_init,
13559
- refreshed_ds,
13560
- );
13561
-
13562
- _ret = _.assignIn(_ret, ret);
14660
+ const ret = await func.UI.screen.execute_xu_functions(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, new_key, $elm, { key: key, value: await get_attr_value(key) }, is_init, refreshed_ds);
14661
+ Object.assign(_ret, ret);
13563
14662
  }
13564
14663
 
13565
- // EXP for
13566
-
13567
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
13568
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
13569
-
13570
- const attr = key.split('xu-exp:')[1];
14664
+ // EXP - Process expressions
14665
+ for (const [key, val] of Object.entries(nodeAttrs)) {
14666
+ if (shouldAbort()) break;
13571
14667
 
13572
- if (!attr) {
13573
- continue;
13574
- }
14668
+ if (!key.startsWith('xu-exp:')) continue;
14669
+ const attr = key.slice(7);
13575
14670
 
13576
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
14671
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
14672
+ if (done_exp.has(key)) continue;
13577
14673
 
13578
- if (done_exp.includes(key)) {
13579
- continue;
13580
- }
13581
- let ret = await func.UI.screen.execute_xu_functions(
13582
- SESSION_ID,
13583
- is_skeleton,
13584
- $root_container,
13585
- nodeP,
13586
- $container,
13587
- paramsP,
13588
- parent_infoP,
13589
- jobNoP,
13590
- keyP,
13591
- parent_nodeP,
13592
- 'xu-exp',
13593
- $elm,
13594
- {
13595
- key: attr,
13596
- value: val,
13597
- },
13598
- true,
13599
- refreshed_ds,
13600
- );
13601
- _ret = _.assignIn(_ret, ret);
14674
+ const ret = await func.UI.screen.execute_xu_functions(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, 'xu-exp', $elm, { key: attr, value: val }, true, refreshed_ds);
14675
+ Object.assign(_ret, ret);
13602
14676
  }
13603
14677
 
13604
14678
  // AFTER
14679
+ for (const [key, attr] of Object.entries(glb.run_xu_after)) {
14680
+ if (containerXuData?.pending_to_delete) break;
14681
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
13605
14682
 
13606
- for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
13607
- if ($container?.data()?.xuData?.pending_to_delete) break;
13608
-
13609
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
14683
+ const expKey = `xu-exp:${attr}`;
14684
+ if (!nodeAttrs || (!nodeAttrs[attr] && !nodeAttrs[expKey])) continue;
13610
14685
 
13611
- if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
13612
-
13613
- let ret = await func.UI.screen.execute_xu_functions(
13614
- SESSION_ID,
13615
- is_skeleton,
13616
- $root_container,
13617
- nodeP,
13618
- $container,
13619
- paramsP,
13620
- parent_infoP,
13621
- jobNoP,
13622
- keyP,
13623
- parent_nodeP,
13624
- attr,
13625
- $elm,
13626
- {
13627
- key: attr,
13628
- // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
13629
- value: await get_attr_value(attr),
13630
- },
13631
- is_init,
13632
- refreshed_ds,
13633
- );
13634
- _ret = _.assignIn(_ret, ret);
14686
+ const ret = await func.UI.screen.execute_xu_functions(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, attr, $elm, { key: attr, value: await get_attr_value(attr) }, is_init, refreshed_ds);
14687
+ Object.assign(_ret, ret);
13635
14688
  }
13636
14689
 
13637
14690
  // REGISTER EVENTS ATTRIBUTES
14691
+ for (const [key, val] of Object.entries(nodeAttrs)) {
14692
+ if (containerXuData?.pending_to_delete) break;
14693
+ if (!html5EventsSet.has(key)) break;
13638
14694
 
13639
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
13640
- if ($container?.data()?.xuData?.pending_to_delete) break;
13641
- if (!glb.html5_events_handler.includes(key)) break;
13642
- // $elm.attr(key, await get_xuExp(key)) || val;
13643
- $elm.attr(key, await get_xuExp(key)) || val;
14695
+ const expVal = await get_xuExp(key);
14696
+ $elm.attr(key, expVal || val);
13644
14697
  }
13645
14698
 
13646
14699
  return _ret;