@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.
@@ -24677,11 +24677,6 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
24677
24677
  };
24678
24678
 
24679
24679
  func.common.sha256 = async function (inputString) {
24680
- // const enc = new TextEncoder();
24681
- // const buf = await crypto.subtle.digest('SHA-256', enc.encode(str));
24682
- // const bytes = new Uint8Array(buf);
24683
- // return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');
24684
-
24685
24680
  // 1. Create a hash buffer from the input string using SHA-256.
24686
24681
  // This part remains the same as it provides a strong, unique cryptographic starting point.
24687
24682
  const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputString));
@@ -31895,469 +31890,1357 @@ const get_params_obj_new = async function (SESSION_ID, prog_id, nodeP, dsSession
31895
31890
  return { params_res, params_raw };
31896
31891
  };
31897
31892
 
31898
- 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) {
31899
- if (is_skeleton) return;
31893
+ // 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) {
31894
+ // if (is_skeleton) return;
31895
+
31896
+ // // console.log(nodeP.id, xu_func, val);
31897
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
31898
+ // const tag_fx = {
31899
+ // [`xu-panel`]: {
31900
+ // program: async function ($elm, val) {
31901
+ // var ret = {};
31902
+ // var _session = SESSION_OBJ[SESSION_ID];
31903
+ // var _ds = _session.DS_GLB[paramsP.dsSessionP];
31904
+ // const init_program = async function () {
31905
+ // async function render_panel() {
31906
+ // const prog_id = val.value?.prog || val.value;
31907
+ // const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
31908
+ // 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);
31909
+ // ret = { $new_div: ret_panel };
31910
+ // if ($container.data().xuData) {
31911
+ // $container.data().xuData.xuPanelProps = $elm.data().xuAttributes;
31912
+ // $container.data().xuData.xuPanelData = ret_panel.data();
31913
+ // }
31914
+ // return ret;
31915
+ // }
31900
31916
 
31901
- // console.log(nodeP.id, xu_func, val);
31902
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
31903
- const tag_fx = {
31904
- [`xu-panel`]: {
31905
- program: async function ($elm, val) {
31906
- var ret = {};
31907
- var _session = SESSION_OBJ[SESSION_ID];
31908
- var _ds = _session.DS_GLB[paramsP.dsSessionP];
31909
- const init_program = async function () {
31910
- async function render_panel() {
31911
- const prog_id = val.value?.prog || val.value;
31912
- const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
31913
- 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);
31914
- ret = { $new_div: ret_panel };
31915
- if ($container.data().xuData) {
31916
- $container.data().xuData.xuPanelProps = $elm.data().xuAttributes;
31917
- $container.data().xuData.xuPanelData = ret_panel.data();
31918
- }
31919
- return ret;
31920
- }
31917
+ // if (!val.value) {
31918
+ // val.value = '_empty_panel_program';
31919
+ // }
31921
31920
 
31922
- if (!val.value) {
31923
- val.value = '_empty_panel_program';
31924
- }
31921
+ // ret = await render_panel();
31925
31922
 
31926
- ret = await render_panel();
31923
+ // return ret;
31924
+ // };
31925
+ // const alter_program = async function () {
31926
+ // var _session = SESSION_OBJ[SESSION_ID];
31927
+ // var _ds = _session.DS_GLB[paramsP.dsSessionP];
31928
+
31929
+ // /////////////////
31930
+ // async function render_panel() {
31931
+ // // // if (!cache_str) {
31932
+ // // // await update_container(screen_ready_function);
31933
+ // // // }
31934
+ // // // if (cache_str && !CACHE_PROG_UI[cache_str]) {
31935
+ // // // await update_container(screen_ready_function);
31936
+ // // // save_cache();
31937
+ // // // }
31938
+ // // // if (callback) callback($div);
31939
+ // // // $container.data().xuData.node.children =
31940
+ // // // $div.data().xuData.node.children;
31941
+ // // // //swiper-wrapper
31942
+ // // // var restore_slides_elements = async function () {
31943
+ // // // if ($tmp_div.children().length) {
31944
+ // // // $tmp_div
31945
+ // // // .find(".swiper-wrapper")
31946
+ // // // .empty()
31947
+ // // // .append($new_div.children());
31948
+ // // // $new_div.append($tmp_div.children());
31949
+ // // // }
31950
+ // // // };
31951
+ // // // // console.log($tmp_div);
31952
+ // // // await restore_slides_elements();
31953
+ // // // // CHANGE_PANEL_BUSY = false;
31954
+ // // // func.events.delete_job(SESSION_ID, jobNo);
31955
+ // // };
31956
+ // const program = val.value?.prog || val.value;
31957
+ // var $wrapper = $('<div>');
31958
+ // 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, '');
31959
+ // const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
31960
+ // 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);
31961
+ // ret = {
31962
+ // $new_div: ret_init,
31963
+ // abort: true,
31964
+ // };
31965
+ // await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, $new_div, nodeP, $div.clone(true), jobNoP);
31966
+
31967
+ // return ret;
31968
+ // }
31969
+ // if (!val.value) {
31970
+ // return { abort: true };
31971
+ // }
31972
+ // await render_panel();
31973
+ // return ret;
31974
+ // };
31927
31975
 
31928
- return ret;
31929
- };
31930
- const alter_program = async function () {
31931
- var _session = SESSION_OBJ[SESSION_ID];
31932
- var _ds = _session.DS_GLB[paramsP.dsSessionP];
31976
+ // if (is_init) {
31977
+ // let ret = await init_program();
31978
+ // return ret;
31979
+ // }
31980
+ // return alter_program();
31981
+ // },
31933
31982
 
31934
- /////////////////
31935
- async function render_panel() {
31936
- // // if (!cache_str) {
31937
- // // await update_container(screen_ready_function);
31938
- // // }
31939
- // // if (cache_str && !CACHE_PROG_UI[cache_str]) {
31940
- // // await update_container(screen_ready_function);
31941
- // // save_cache();
31942
- // // }
31943
- // // if (callback) callback($div);
31944
- // // $container.data().xuData.node.children =
31945
- // // $div.data().xuData.node.children;
31946
- // // //swiper-wrapper
31947
- // // var restore_slides_elements = async function () {
31948
- // // if ($tmp_div.children().length) {
31949
- // // $tmp_div
31950
- // // .find(".swiper-wrapper")
31951
- // // .empty()
31952
- // // .append($new_div.children());
31953
- // // $new_div.append($tmp_div.children());
31954
- // // }
31955
- // // };
31956
- // // // console.log($tmp_div);
31957
- // // await restore_slides_elements();
31958
- // // // CHANGE_PANEL_BUSY = false;
31959
- // // func.events.delete_job(SESSION_ID, jobNo);
31960
- // };
31961
- const program = val.value?.prog || val.value;
31962
- var $wrapper = $('<div>');
31963
- 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, '');
31964
- const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
31965
- 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);
31966
- ret = {
31967
- $new_div: ret_init,
31968
- abort: true,
31969
- };
31970
- await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, $new_div, nodeP, $div.clone(true), jobNoP);
31983
+ // 'xu-render': async function ($elm, val) {
31984
+ // let ret = await common_fx['xu-render']($elm, val, true);
31985
+ // return ret;
31986
+ // },
31987
+ // 'xu-ref': async function ($elm, val) {
31988
+ // let ret = await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
31989
+ // return ret;
31990
+ // },
31991
+ // },
31992
+ // [`xu-teleport`]: {
31993
+ // to: async function ($elm, val) {
31994
+ // if (!glb.new_xu_render) {
31995
+ // if (val.value) {
31996
+ // // parent_infoP.is_xu_teleport;
31997
+ // if ($elm?.parent()?.data()?.xuData?.length) {
31998
+ // $elm.parent().data('xuTeleportData', []);
31999
+ // for (const [key, node] of Object.entries(nodeP.children)) {
32000
+ // 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);
32001
+
32002
+ // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32003
+ // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
32004
+ // }
32005
+ // $elm.remove();
32006
+ // } else {
32007
+ // $elm.data('xuTeleportData', []).attr('hidden', true);
32008
+ // for (const [key, node] of Object.entries(nodeP.children)) {
32009
+ // const $to_container = $(val.value);
32010
+ // if (!$to_container?.length) {
32011
+ // return console.error(`container ${val.value} for xuTeleportData not found`);
32012
+ // }
32013
+ // 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);
31971
32014
 
31972
- return ret;
31973
- }
31974
- if (!val.value) {
31975
- return { abort: true };
31976
- }
31977
- await render_panel();
31978
- return ret;
31979
- };
32015
+ // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32016
+ // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
32017
+ // }
32018
+ // }
32019
+ // }
32020
+ // return { abort: true };
32021
+ // }
31980
32022
 
31981
- if (is_init) {
31982
- let ret = await init_program();
31983
- return ret;
31984
- }
31985
- return alter_program();
31986
- },
32023
+ // if (val.value) {
32024
+ // // // parent_infoP.is_xu_teleport;
32025
+ // // if ($elm?.parent()?.data()?.xuData?.length) {
32026
+ // // $elm.parent().data('xuTeleportData', []);
32027
+ // // for (const [key, node] of Object.entries(nodeP.children)) {
32028
+ // // 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);
32029
+ // // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32030
+ // // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
32031
+ // // }
32032
+ // // $elm.remove();
32033
+ // // } else {
32034
+ // // $elm.data('xuTeleportData', []).attr('hidden', true);
32035
+ // // for (const [key, node] of Object.entries(nodeP.children)) {
32036
+ // // const $to_container = $(val.value);
32037
+ // // if (!$to_container?.length) {
32038
+ // // return console.error(`container ${val.value} for xuTeleportData not found`);
32039
+ // // }
32040
+ // // 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);
32041
+ // // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32042
+ // // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
32043
+ // // }
32044
+ // // }
32045
+ // }
32046
+ // return {};
32047
+ // },
32048
+ // 'xu-render': async function ($elm, val) {
32049
+ // let ret = await common_fx['xu-render']($elm, val, true);
32050
+ // return ret;
32051
+ // },
32052
+ // 'xu-show': async function ($elm, val) {
32053
+ // let ret = await common_fx['xu-show']($elm, val, true);
32054
+ // return ret;
32055
+ // },
32056
+ // },
32057
+ // };
31987
32058
 
31988
- 'xu-render': async function ($elm, val) {
31989
- let ret = await common_fx['xu-render']($elm, val, true);
31990
- return ret;
31991
- },
31992
- 'xu-ref': async function ($elm, val) {
31993
- let ret = await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
31994
- return ret;
31995
- },
31996
- },
31997
- [`xu-teleport`]: {
31998
- to: async function ($elm, val) {
31999
- if (!glb.new_xu_render) {
32000
- if (val.value) {
32001
- // parent_infoP.is_xu_teleport;
32002
- if ($elm?.parent()?.data()?.xuData?.length) {
32003
- $elm.parent().data('xuTeleportData', []);
32004
- for (const [key, node] of Object.entries(nodeP.children)) {
32005
- 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);
32006
-
32007
- $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32008
- $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
32009
- }
32010
- $elm.remove();
32011
- } else {
32012
- $elm.data('xuTeleportData', []).attr('hidden', true);
32013
- for (const [key, node] of Object.entries(nodeP.children)) {
32014
- const $to_container = $(val.value);
32015
- if (!$to_container?.length) {
32016
- return console.error(`container ${val.value} for xuTeleportData not found`);
32017
- }
32018
- 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);
32059
+ // const load_cdn = async function (resource) {
32060
+ // // console.log("loading cdn", resource);
32061
+ // if (!_.isObject(resource) && _.isString(resource)) {
32062
+ // resource = { src: resource, type: 'js' };
32063
+ // }
32064
+ // if (!_.isObject(resource)) {
32065
+ // throw new Error('cdn resource in wrong format');
32066
+ // }
32067
+ // return new Promise(async (resolve) => {
32068
+ // try {
32069
+ // switch (resource.type) {
32070
+ // case 'js':
32071
+ // await func.utils.load_js_on_demand(resource.src);
32072
+ // break;
32073
+ // case 'css':
32074
+ // await func.utils.load_js_on_demand(resource.src);
32075
+ // break;
32076
+ // case 'module':
32077
+ // func.utils.load_js_on_demand(resource.src, 'module');
32078
+ // break;
32079
+
32080
+ // default:
32081
+ // await func.utils.load_js_on_demand(resource.src);
32082
+ // break;
32083
+ // }
32084
+ // resolve();
32085
+ // } catch (error) {
32086
+ // func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource, 'W');
32087
+ // resolve();
32088
+ // }
32019
32089
 
32020
- $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32021
- $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
32022
- }
32023
- }
32024
- }
32025
- return { abort: true };
32026
- }
32090
+ // // if (resource.type === "js" || !resource.type) {
32091
+ // // await func.utils.load_js_on_demand(resource.src);
32092
+ // // return resolve();
32093
+ // // }
32094
+ // // if (resource.type === "css") {
32095
+ // // func.utils.load_css_on_demand(resource.src);
32096
+ // // return resolve();
32097
+ // // }
32098
+ // // if (resource.type === "module") {
32099
+ // // func.utils.load_js_on_demand(resource.src, "module");
32100
+ // // return resolve();
32101
+ // // }
32102
+ // // func.utils.debug_report(
32103
+ // // SESSION_ID,
32104
+ // // "xu-cdn",
32105
+ // // "Fail to load: " + resource,
32106
+ // // "W"
32107
+ // // );
32108
+ // // return resolve();
32109
+ // });
32110
+ // };
32027
32111
 
32028
- if (val.value) {
32029
- // // parent_infoP.is_xu_teleport;
32030
- // if ($elm?.parent()?.data()?.xuData?.length) {
32031
- // $elm.parent().data('xuTeleportData', []);
32032
- // for (const [key, node] of Object.entries(nodeP.children)) {
32033
- // 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);
32034
- // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32035
- // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
32036
- // }
32037
- // $elm.remove();
32038
- // } else {
32039
- // $elm.data('xuTeleportData', []).attr('hidden', true);
32040
- // for (const [key, node] of Object.entries(nodeP.children)) {
32041
- // const $to_container = $(val.value);
32042
- // if (!$to_container?.length) {
32043
- // return console.error(`container ${val.value} for xuTeleportData not found`);
32044
- // }
32045
- // 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);
32046
- // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
32047
- // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
32048
- // }
32049
- // }
32050
- }
32051
- return {};
32052
- },
32053
- 'xu-render': async function ($elm, val) {
32054
- let ret = await common_fx['xu-render']($elm, val, true);
32055
- return ret;
32056
- },
32057
- 'xu-show': async function ($elm, val) {
32058
- let ret = await common_fx['xu-show']($elm, val, true);
32059
- return ret;
32060
- },
32061
- },
32062
- };
32112
+ // const common_fx = {
32113
+ // 'xu-attrs': async function ($elm, val) {
32114
+ // if (!val.value) return {};
32115
+ // if (!_.isObject(val.value)) throw 'xu-attrs value us not an object';
32116
+ // for (const [attr_key, attr_val] of Object.entries(val.value)) {
32117
+ // nodeP.attributes[attr_key] = attr_val;
32118
+ // }
32063
32119
 
32064
- const load_cdn = async function (resource) {
32065
- // console.log("loading cdn", resource);
32066
- if (!_.isObject(resource) && _.isString(resource)) {
32067
- resource = { src: resource, type: 'js' };
32068
- }
32069
- if (!_.isObject(resource)) {
32070
- throw new Error('cdn resource in wrong format');
32071
- }
32072
- return new Promise(async (resolve) => {
32073
- try {
32074
- switch (resource.type) {
32075
- case 'js':
32076
- await func.utils.load_js_on_demand(resource.src);
32077
- break;
32078
- case 'css':
32079
- await func.utils.load_js_on_demand(resource.src);
32080
- break;
32081
- case 'module':
32082
- func.utils.load_js_on_demand(resource.src, 'module');
32083
- break;
32120
+ // return {};
32121
+ // },
32122
+ // 'xu-ref': async function ($elm, val, dsSession) {
32123
+ // if (!val.value) return {};
32084
32124
 
32085
- default:
32086
- await func.utils.load_js_on_demand(resource.src);
32087
- break;
32088
- }
32089
- resolve();
32090
- } catch (error) {
32091
- func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource, 'W');
32092
- resolve();
32093
- }
32125
+ // func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
32094
32126
 
32095
- // if (resource.type === "js" || !resource.type) {
32096
- // await func.utils.load_js_on_demand(resource.src);
32097
- // return resolve();
32098
- // }
32099
- // if (resource.type === "css") {
32100
- // func.utils.load_css_on_demand(resource.src);
32101
- // return resolve();
32102
- // }
32103
- // if (resource.type === "module") {
32104
- // func.utils.load_js_on_demand(resource.src, "module");
32105
- // return resolve();
32106
- // }
32107
- // func.utils.debug_report(
32108
- // SESSION_ID,
32109
- // "xu-cdn",
32110
- // "Fail to load: " + resource,
32111
- // "W"
32112
- // );
32113
- // return resolve();
32114
- });
32115
- };
32127
+ // // Select the node that will be observed for mutations
32128
+ // const targetNode = $elm[0];
32116
32129
 
32117
- const common_fx = {
32118
- 'xu-attrs': async function ($elm, val) {
32119
- if (!val.value) return {};
32120
- if (!_.isObject(val.value)) throw 'xu-attrs value us not an object';
32121
- for (const [attr_key, attr_val] of Object.entries(val.value)) {
32122
- nodeP.attributes[attr_key] = attr_val;
32123
- }
32130
+ // if (!targetNode) return;
32124
32131
 
32125
- return {};
32126
- },
32127
- 'xu-ref': async function ($elm, val, dsSession) {
32128
- if (!val.value) return {};
32132
+ // // Options for the observer (which mutations to observe)
32133
+ // const config = { attributes: true, childList: true, subtree: true };
32129
32134
 
32130
- func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
32135
+ // // Callback function to execute when mutations are observed
32136
+ // const callback = (mutationList, observer) => {
32137
+ // func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
32138
+ // };
32131
32139
 
32132
- // Select the node that will be observed for mutations
32133
- const targetNode = $elm[0];
32140
+ // // Create an observer instance linked to the callback function
32141
+ // const observer = new MutationObserver(callback);
32142
+
32143
+ // // Start observing the target node for configured mutations
32144
+ // observer.observe(targetNode, config);
32145
+
32146
+ // // Later, you can stop observing
32147
+ // // observer.disconnect();
32148
+
32149
+ // return {};
32150
+ // },
32151
+ // 'xu-bind': async function ($elm, val) {
32152
+ // if (is_skeleton) return;
32153
+
32154
+ // let val_is_reference_field = false;
32155
+
32156
+ // let _prog_id = $elm.data().xuData.paramsP.prog_id;
32157
+ // let _dsP = $elm.data().xuData.paramsP.dsSessionP;
32158
+ // const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
32159
+ // if (!view_ret) return {};
32160
+
32161
+ // let is_dynamic_field = false;
32162
+ // let field_prop;
32163
+ // let bind_field_id;
32164
+
32165
+ // const input_field_type = $elm.attr('type');
32166
+
32167
+ // const get_bind_field = async function (field_id) {
32168
+ // if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
32169
+ // is_dynamic_field = true;
32170
+ // field_prop = _ds.dynamic_fields[field_id];
32171
+ // } else {
32172
+ // field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
32173
+ // if (!field_prop) {
32174
+ // /// find the field everywhere in the chain Aug 30 2024
32175
+ // const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
32176
+
32177
+ // if (ret_get_value.found) {
32178
+ // _dsP = ret_get_value.dsSessionP;
32179
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
32180
+ // _prog_id = _ds.prog_id;
32181
+ // const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
32182
+ // if (!view_ret) return {};
32183
+ // field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
32184
+ // }
32185
+ // if (!field_prop) {
32186
+ // throw `field ${field_id} not found in the program scope`;
32187
+ // }
32188
+ // }
32189
+ // }
32190
+ // return field_id;
32191
+ // };
32134
32192
 
32135
- if (!targetNode) return;
32193
+ // try {
32194
+ // bind_field_id = await get_bind_field(val.value.split('.')[0]);
32195
+ // val_is_reference_field = true;
32196
+ // } catch (err) {
32197
+ // console.error(err?.message || err);
32198
+ // return {};
32199
+ // }
32136
32200
 
32137
- // Options for the observer (which mutations to observe)
32138
- const config = { attributes: true, childList: true, subtree: true };
32201
+ // const field_changed = async function (e) {
32202
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
32139
32203
 
32140
- // Callback function to execute when mutations are observed
32141
- const callback = (mutationList, observer) => {
32142
- func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
32143
- };
32204
+ // // update array for checkbox that not in xu-for
32205
+ // if (field_prop.props.fieldType === 'array' && input_field_type === 'checkbox' && val_is_reference_field) {
32206
+ // let arr_value_before_cast = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, _ds.currentRecordId)).ret.value);
32207
+ // let value_from_getter = bind.getter($elm[0]);
32208
+ // let value;
32209
+ // if (arr_value_before_cast.includes(value_from_getter)) {
32210
+ // value = arr_value_before_cast.filter((item) => !_.isEqual(item, value_from_getter));
32211
+ // } else {
32212
+ // arr_value_before_cast.push(value_from_getter);
32213
+ // value = arr_value_before_cast;
32214
+ // }
32144
32215
 
32145
- // Create an observer instance linked to the callback function
32146
- const observer = new MutationObserver(callback);
32216
+ // let datasource_changes = {
32217
+ // [_dsP]: {
32218
+ // [_ds.currentRecordId]: {
32219
+ // [bind_field_id]: value,
32220
+ // },
32221
+ // },
32222
+ // };
32147
32223
 
32148
- // Start observing the target node for configured mutations
32149
- observer.observe(targetNode, config);
32224
+ // return await func.datasource.update(SESSION_ID, datasource_changes);
32225
+ // }
32150
32226
 
32151
- // Later, you can stop observing
32152
- // observer.disconnect();
32227
+ // // update array for radio that not in xu-for
32228
+ // if (field_prop.props.fieldType === 'array' && input_field_type === 'radio' && val_is_reference_field) {
32229
+ // let value_from_getter = bind.getter($elm[0]);
32153
32230
 
32154
- return {};
32155
- },
32156
- 'xu-bind': async function ($elm, val) {
32157
- if (is_skeleton) return;
32231
+ // let datasource_changes = {
32232
+ // [_dsP]: {
32233
+ // [_ds.currentRecordId]: {
32234
+ // [bind_field_id]: [value_from_getter],
32235
+ // },
32236
+ // },
32237
+ // };
32158
32238
 
32159
- let val_is_reference_field = false;
32239
+ // return await func.datasource.update(SESSION_ID, datasource_changes);
32240
+ // }
32160
32241
 
32161
- let _prog_id = $elm.data().xuData.paramsP.prog_id;
32162
- let _dsP = $elm.data().xuData.paramsP.dsSessionP;
32163
- const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
32164
- if (!view_ret) return {};
32242
+ // var value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', field_prop.props.fieldType, bind.getter($elm[0]));
32165
32243
 
32166
- let is_dynamic_field = false;
32167
- let field_prop;
32168
- let bind_field_id;
32244
+ // if (field_prop.props.fieldType === 'object') {
32245
+ // value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
32246
+ // }
32169
32247
 
32170
- const input_field_type = $elm.attr('type');
32248
+ // if (!_ds.currentRecordId) return;
32171
32249
 
32172
- const get_bind_field = async function (field_id) {
32173
- if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
32174
- is_dynamic_field = true;
32175
- field_prop = _ds.dynamic_fields[field_id];
32176
- } else {
32177
- field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
32178
- if (!field_prop) {
32179
- /// find the field everywhere in the chain Aug 30 2024
32180
- const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
32250
+ // let datasource_changes = {
32251
+ // [_dsP]: {
32252
+ // [_ds.currentRecordId]: {
32253
+ // [bind_field_id]: value,
32254
+ // },
32255
+ // },
32256
+ // };
32181
32257
 
32182
- if (ret_get_value.found) {
32183
- _dsP = ret_get_value.dsSessionP;
32184
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
32185
- _prog_id = _ds.prog_id;
32186
- const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
32187
- if (!view_ret) return {};
32188
- field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
32189
- }
32190
- if (!field_prop) {
32191
- throw `field ${field_id} not found in the program scope`;
32192
- }
32193
- }
32194
- }
32195
- return field_id;
32196
- };
32258
+ // await func.datasource.update(SESSION_ID, datasource_changes);
32259
+ // const iterate_info = $elm?.data()?.xuData?.iterate_info;
32260
+ // const reference_source_obj = iterate_info?.reference_source_obj;
32261
+ // if (reference_source_obj) {
32262
+ // if (reference_source_obj.ret.type === 'array') {
32263
+ // if (iterate_info.iterator_val === bind_field_id) {
32264
+ // const arr_idx = Number($elm?.data()?.xuData?.iterate_info._key);
32197
32265
 
32198
- try {
32199
- bind_field_id = await get_bind_field(val.value.split('.')[0]);
32200
- val_is_reference_field = true;
32201
- } catch (err) {
32202
- console.error(err?.message || err);
32203
- return {};
32204
- }
32266
+ // const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
32267
+ // let new_arr = _.cloneDeep(dataset_arr.ret.value);
32205
32268
 
32206
- const field_changed = async function (e) {
32207
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
32269
+ // if (field_prop.props.fieldType === 'object' && val_is_reference_field) {
32270
+ // let obj_item = new_arr[arr_idx];
32208
32271
 
32209
- // update array for checkbox that not in xu-for
32210
- if (field_prop.props.fieldType === 'array' && input_field_type === 'checkbox' && val_is_reference_field) {
32211
- let arr_value_before_cast = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, _ds.currentRecordId)).ret.value);
32212
- let value_from_getter = bind.getter($elm[0]);
32213
- let value;
32214
- if (arr_value_before_cast.includes(value_from_getter)) {
32215
- value = arr_value_before_cast.filter((item) => !_.isEqual(item, value_from_getter));
32216
- } else {
32217
- arr_value_before_cast.push(value_from_getter);
32218
- value = arr_value_before_cast;
32219
- }
32272
+ // let e_exp = val.value.replace(bind_field_id, 'obj_item');
32220
32273
 
32221
- let datasource_changes = {
32222
- [_dsP]: {
32223
- [_ds.currentRecordId]: {
32224
- [bind_field_id]: value,
32225
- },
32226
- },
32227
- };
32274
+ // let new_val = eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
32228
32275
 
32229
- return await func.datasource.update(SESSION_ID, datasource_changes);
32230
- }
32276
+ // new_arr[arr_idx] = obj_item;
32277
+ // } else {
32278
+ // new_arr[arr_idx] = value;
32279
+ // }
32280
+ // // datasource_changes[_dsP][_ds.currentRecordId][reference_source_obj.fieldIdP] = new_arr;
32281
+
32282
+ // let datasource_changes = {
32283
+ // [_dsP]: {
32284
+ // [_ds.currentRecordId]: {
32285
+ // [reference_source_obj.fieldIdP]: new_arr,
32286
+ // },
32287
+ // },
32288
+ // };
32231
32289
 
32232
- // update array for radio that not in xu-for
32233
- if (field_prop.props.fieldType === 'array' && input_field_type === 'radio' && val_is_reference_field) {
32234
- let value_from_getter = bind.getter($elm[0]);
32290
+ // await func.datasource.update(SESSION_ID, datasource_changes, null, true);
32291
+ // }
32292
+ // }
32293
+ // }
32235
32294
 
32236
- let datasource_changes = {
32237
- [_dsP]: {
32238
- [_ds.currentRecordId]: {
32239
- [bind_field_id]: [value_from_getter],
32240
- },
32241
- },
32242
- };
32295
+ // await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, _ds.parentDataSourceNo);
32296
+ // };
32243
32297
 
32244
- return await func.datasource.update(SESSION_ID, datasource_changes);
32245
- }
32298
+ // const bind = new UI_FRAMEWORK_PLUGIN.bind();
32246
32299
 
32247
- var value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', field_prop.props.fieldType, bind.getter($elm[0]));
32300
+ // bind.listener($elm[0], field_changed);
32248
32301
 
32249
- if (field_prop.props.fieldType === 'object') {
32250
- value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
32251
- }
32302
+ // const set_value = function () {
32303
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
32304
+ // if (!_ds.currentRecordId) return;
32305
+ // let value;
32306
+ // try {
32307
+ // if (val_is_reference_field) {
32308
+ // if (is_dynamic_field) {
32309
+ // value = _ds.dynamic_fields[bind_field_id].value;
32310
+ // } else {
32311
+ // const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
32312
+ // value = _ds.data_feed.rows?.[row_idx]?.[bind_field_id];
32313
+ // }
32314
+ // if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'checkbox' && $elm.attr('value')) {
32315
+ // if (value.includes($elm.attr('value'))) {
32316
+ // value = true;
32317
+ // } else {
32318
+ // value = false;
32319
+ // }
32320
+ // } else if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'radio' && $elm.attr('value')) {
32321
+ // if (value.includes($elm.attr('value'))) {
32322
+ // value = $elm.attr('value');
32323
+ // } else {
32324
+ // value = false;
32325
+ // }
32326
+ // } else if (field_prop.props.fieldType === 'object' && val.value.split('.').length > 1) {
32327
+ // let str = val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')');
32328
+ // value = eval(str);
32329
+ // }
32330
+ // } else {
32331
+ // value = val.value;
32332
+ // }
32333
+ // if (typeof value === 'undefined') return;
32334
+ // bind.setter($elm[0], value);
32335
+ // } catch (err) {
32336
+ // console.error(err);
32337
+ // }
32338
+ // };
32339
+ // /// init value from ds
32340
+ // $('body').on('xu-bind-refresh.' + _ds.dsSession.toString(), () => {
32341
+ // set_value();
32342
+ // });
32252
32343
 
32253
- if (!_ds.currentRecordId) return;
32344
+ // set_value();
32345
+ // return {};
32346
+ // },
32347
+ // 'xu-render': async function ($elm, val, from_panel) {
32348
+ // const old_render = async function () {
32349
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
32350
+ // const init_render = function () {
32351
+ // if (!value) {
32352
+ // var cloned_$div = $elm.clone(true);
32353
+
32354
+ // let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container); //.hide();
32355
+ // let original_data_obj = {
32356
+ // $container: cloned_$div,
32357
+ // nodeP: _.cloneDeep(nodeP),
32358
+ // parent_infoP,
32359
+ // paramsP,
32360
+ // keyP,
32361
+ // parent_nodeP,
32362
+ // $root_container,
32363
+ // };
32364
+ // $xurender.data('xuData', cloned_$div.data().xuData);
32365
+ // $xurender.data().xuData.original_data_obj = original_data_obj;
32366
+ // $xurender.data().xuData.xurender_node = cloned_$div;
32367
+ // $xurender.data().xuAttributes = nodeP.attributes || {};
32368
+ // // $xurender.hide();
32369
+
32370
+ // $elm.remove();
32371
+ // return { abort: true };
32372
+ // }
32373
+ // return {};
32374
+ // };
32254
32375
 
32255
- let datasource_changes = {
32256
- [_dsP]: {
32257
- [_ds.currentRecordId]: {
32258
- [bind_field_id]: value,
32259
- },
32260
- },
32261
- };
32376
+ // const post_render = async function () {
32377
+ // if (value) {
32378
+ // try {
32379
+ // // abort if already rended
32380
+ // if ($elm[0].tagName !== 'XURENDER' && $elm?.length) {
32381
+ // return func.events.delete_job(SESSION_ID, jobNoP);
32382
+ // }
32262
32383
 
32263
- await func.datasource.update(SESSION_ID, datasource_changes);
32264
- const iterate_info = $elm?.data()?.xuData?.iterate_info;
32265
- const reference_source_obj = iterate_info?.reference_source_obj;
32266
- if (reference_source_obj) {
32267
- if (reference_source_obj.ret.type === 'array') {
32268
- if (iterate_info.iterator_val === bind_field_id) {
32269
- const arr_idx = Number($elm?.data()?.xuData?.iterate_info._key);
32384
+ // let original_data_obj = $elm.data().xuData.original_data_obj;
32270
32385
 
32271
- const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
32272
- let new_arr = _.cloneDeep(dataset_arr.ret.value);
32386
+ // if (!original_data_obj) {
32387
+ // func.events.delete_job(SESSION_ID, jobNoP);
32388
+ // return { delete_job: jobNoP };
32389
+ // }
32273
32390
 
32274
- if (field_prop.props.fieldType === 'object' && val_is_reference_field) {
32275
- let obj_item = new_arr[arr_idx];
32391
+ // const new_$div = await func.UI.screen.render_ui_tree(
32392
+ // SESSION_ID,
32393
+ // $elm, //original_data_obj.$container,
32394
+ // _.cloneDeep(original_data_obj.nodeP),
32395
+ // original_data_obj.parent_infoP,
32396
+ // original_data_obj.paramsP,
32397
+ // jobNoP,
32398
+ // null,
32399
+ // original_data_obj.keyP,
32400
+ // null,
32401
+ // original_data_obj.parent_nodeP,
32402
+ // null,
32403
+ // original_data_obj.$root_container,
32404
+ // );
32276
32405
 
32277
- let e_exp = val.value.replace(bind_field_id, 'obj_item');
32406
+ // new_$div.data().xuData.original_data_obj = original_data_obj;
32407
+ // new_$div.data().xuData.xurender_node = $elm.clone(true);
32408
+ // new_$div.data().xuAttributes = $elm.data().xuAttributes || {};
32278
32409
 
32279
- let new_val = eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
32410
+ // const replace = async function () {
32411
+ // $elm.replaceWith(new_$div);
32412
+ // if (from_panel) {
32413
+ // const xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
32414
+ // $elm.parent().data().xuPanelWrapper = xuPanelWrapper;
32415
+ // $elm.replaceWith(new_$div.children());
32416
+ // }
32280
32417
 
32281
- new_arr[arr_idx] = obj_item;
32282
- } else {
32283
- new_arr[arr_idx] = value;
32284
- }
32285
- // datasource_changes[_dsP][_ds.currentRecordId][reference_source_obj.fieldIdP] = new_arr;
32418
+ // if (val.fields_arr) {
32419
+ // return await func.UI.screen.refresh_xu_attributes(SESSION_ID, val.fields_arr, val.jobNoP, new_$div);
32420
+ // }
32421
+ // func.events.delete_job(SESSION_ID, jobNoP);
32422
+ // };
32423
+ // // if ($elm && func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'xu_id', $elm.data().xuData.xu_id).length) {
32424
+ // if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length) {
32425
+ // if (new_$div.data().xuData.paramsP) {
32426
+ // return await replace();
32427
+ // }
32286
32428
 
32287
- let datasource_changes = {
32288
- [_dsP]: {
32289
- [_ds.currentRecordId]: {
32290
- [reference_source_obj.fieldIdP]: new_arr,
32291
- },
32292
- },
32293
- };
32429
+ // func.events.delete_job(SESSION_ID, jobNoP);
32430
+ // }
32431
+ // } catch (error) {
32432
+ // func.events.delete_job(SESSION_ID, jobNoP);
32433
+ // }
32434
+ // return;
32435
+ // }
32436
+ // // if (!value) {
32437
+ // if ($elm.prop('tagName') === 'XURENDER') {
32438
+ // func.events.delete_job(SESSION_ID, jobNoP);
32439
+ // return;
32440
+ // }
32294
32441
 
32295
- await func.datasource.update(SESSION_ID, datasource_changes, null, true);
32296
- }
32297
- }
32298
- }
32442
+ // let tmp_$div = $('<div>');
32299
32443
 
32300
- await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, _ds.parentDataSourceNo);
32301
- };
32444
+ // let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).appendTo(tmp_$div); //.hide();
32445
+ // // was true before
32446
+ // if ($elm.data().xuData.xurender_node) {
32447
+ // $xurender.data({
32448
+ // xuAttributes: $elm.data().xuData.xurender_node.data().xuAttributes || {},
32449
+ // xuData: $elm.data().xuData.xurender_node.data().xuData || {},
32450
+ // });
32451
+ // } else {
32452
+ // // default new state
32302
32453
 
32303
- const bind = new UI_FRAMEWORK_PLUGIN.bind();
32454
+ // $xurender.data({
32455
+ // xuAttributes: $elm.data().xuAttributes || {},
32456
+ // xuData: $elm.data().xuData || {},
32457
+ // });
32458
+ // const original_data_obj = {
32459
+ // nodeP: _.cloneDeep($elm.data().xuData.node_org),
32460
+ // paramsP: $elm.data().xuData.paramsP,
32461
+ // $container: $elm.clone(true),
32462
+ // parent_infoP: parent_infoP,
32463
+ // };
32464
+
32465
+ // $xurender.data().xuData.original_data_obj = original_data_obj;
32466
+ // }
32467
+
32468
+ // //remove xu-teleport trace
32469
+ // $.each($elm.find('xu-teleport'), (key, val) => {
32470
+ // const xuTeleportData = $(val).data().xuTeleportData || [];
32471
+ // for (const teleported_elm_id of xuTeleportData) {
32472
+ // $(`[xu-ui-id="${teleported_elm_id}"]`).remove();
32473
+ // }
32474
+ // });
32475
+
32476
+ // $elm.replaceWith(tmp_$div.children());
32477
+ // func.events.delete_job(SESSION_ID, jobNoP);
32478
+ // // }
32479
+ // };
32480
+ // if (is_init) {
32481
+ // return init_render();
32482
+ // }
32483
+ // return await post_render();
32484
+ // };
32485
+
32486
+ // const new_render = async function () {
32487
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
32488
+ // const has_xu_render_attribute = true;
32489
+ // const has_xu_exp_render_attribute = $elm.data()?.xuData?.attr_exp_info?.['xu-render'] ? true : false;
32490
+ // const init_render = async function () {
32491
+ // nodeP.xu_render_made = value;
32492
+ // if (!value) {
32493
+ // if (has_xu_exp_render_attribute) {
32494
+ // return { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true };
32495
+ // }
32496
+ // return { has_xu_render_attribute, abort: true };
32497
+ // }
32498
+ // return { has_xu_exp_render_attribute, has_xu_render_attribute };
32499
+ // };
32500
+
32501
+ // const post_render = async function () {
32502
+ // // always come from refresh
32503
+ // let nodeP = $container.data().xuData.node.children[keyP];
32504
+ // nodeP.xu_render_made = value;
32505
+ // if (value) {
32506
+ // try {
32507
+ // 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 || {}));
32508
+ // const xu_ui_id = $elm.attr('xu-ui-id');
32509
+ // let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[xu_ui_id + xu_render_cache_id]?.$div.clone(true);
32510
+ // let found_parent_vars = false;
32511
+ // if (new_$div) {
32512
+ // // validate if $div contains fields from parent ds
32513
+ // const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
32514
+ // const parent_fields = Object.keys(parent_data);
32515
+
32516
+ // $.each(new_$div.find('*'), (key, val) => {
32517
+ // const _xuAttributes = $(val)?.data()?.xuAttributes;
32518
+ // if (found_parent_vars || !_xuAttributes) return;
32519
+ // for (const [attr_key, attr_val] of Object.entries(_xuAttributes)) {
32520
+ // if (found_parent_vars) break;
32521
+ // for (const [key, val] of Object.entries(parent_fields)) {
32522
+ // if (attr_val.includes('@' + key)) {
32523
+ // found_parent_vars = true;
32524
+ // break;
32525
+ // }
32526
+ // }
32527
+ // }
32528
+ // });
32529
+ // }
32530
+
32531
+ // if (!new_$div || found_parent_vars) {
32532
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { paramsP };
32533
+ // nodeP.xu_render_xu_ui_id = xu_ui_id;
32534
+ // nodeP.xu_render_cache_id = xu_render_cache_id;
32535
+ // 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);
32536
+ // const _$div = new_$div.clone(true);
32537
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].$div = _$div;
32538
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].data = _$div.data();
32539
+ // }
32540
+ // // append order handling
32541
+
32542
+ // if (!$container.children().length) {
32543
+ // new_$div.appendTo($container);
32544
+ // } else {
32545
+ // // iterate the container node
32546
+ // let $last_elm_found = [];
32547
+ // $.each($container.data().xuData.node.children, (item_key, item_val) => {
32548
+ // // const $elm = $(`[xu-node-id="${item_val.id}"]`);
32549
+ // const $elm = func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'nodeid', item_val.id);
32550
+ // if ($elm.length) {
32551
+ // $last_elm_found = $elm;
32552
+ // }
32553
+ // if (keyP == item_key) {
32554
+ // if ($last_elm_found.length) {
32555
+ // new_$div.after($last_elm_found);
32556
+ // } else {
32557
+ // $container.prepend(new_$div);
32558
+ // }
32559
+ // }
32560
+ // });
32561
+ // }
32562
+ // } catch (error) {
32563
+ // func.events.delete_job(SESSION_ID, jobNoP);
32564
+ // }
32565
+ // return;
32566
+ // }
32567
+
32568
+ // /////////// !value ///////////
32569
+
32570
+ // const xu_ui_id = $elm.attr('xu-ui-id');
32571
+
32572
+ // const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
32573
+ // const _$div = $elm.clone(true);
32574
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
32575
+ // $elm.remove();
32576
+ // func.events.delete_job(SESSION_ID, jobNoP);
32577
+ // };
32578
+ // if (is_init) {
32579
+ // return await init_render();
32580
+ // }
32581
+ // return await post_render();
32582
+ // };
32583
+
32584
+ // if (glb.new_xu_render) {
32585
+ // return new_render();
32586
+ // }
32587
+ // return old_render();
32588
+ // },
32589
+ // 'xu-show': async function ($elm, val) {
32590
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
32591
+ // if (value) {
32592
+ // $elm.show();
32593
+ // }
32594
+ // if (!value) {
32595
+ // $elm.hide();
32596
+ // }
32597
+ // return {};
32598
+ // },
32599
+ // 'xu-content': async function ($elm, val) {
32600
+ // try {
32601
+ // $elm.html(val.value);
32602
+ // } catch (error) {
32603
+ // console.warn(e);
32604
+ // }
32605
+ // return;
32606
+ // },
32607
+ // 'xu-text': async function ($elm, val) {
32608
+ // try {
32609
+ // $elm.text(val.value);
32610
+ // } catch (error) {
32611
+ // console.warn(e);
32612
+ // }
32613
+ // return;
32614
+ // },
32615
+ // 'xu-html': async function ($elm, val) {
32616
+ // try {
32617
+ // $elm.html(val.value);
32618
+ // } catch (error) {
32619
+ // console.warn(e);
32620
+ // }
32621
+ // return;
32622
+ // },
32623
+ // 'xu-for': async function ($elm, data) {
32624
+ // // exit if call from rendered xu-for item to prevent infante loop (parent_infoP?.iterate_info indicate call from rendered item)
32625
+ // if (parent_infoP?.iterate_info) return {};
32626
+ // if (!data.value) return {};
32627
+ // try {
32628
+ // // 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.
32629
+ // let arr = data.value;
32630
+
32631
+ // // find reference source field
32632
+ // let reference_source_obj;
32633
+
32634
+ // const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
32635
+
32636
+ // let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
32637
+ // // detect if data.value (xu-for) is reference field_id by checking if exist in the dataset
32638
+ // if (view_field_obj) {
32639
+ // // xu-for is reference field_id
32640
+ // reference_source_obj = await func.datasource.get_value(SESSION_ID, data.value, paramsP.dsSessionP);
32641
+ // arr = reference_source_obj?.ret?.value;
32642
+ // } else {
32643
+ // // xu-for is actual data
32644
+ // if (typeof data.value === 'string') {
32645
+ // arr = eval(data.value.replaceAll('\\', ''));
32646
+ // }
32647
+ // if (typeof arr === 'number') {
32648
+ // arr = Array.from(Array(arr).keys());
32649
+ // }
32650
+ // }
32651
+
32652
+ // const custom_iterator_key = $elm.data().xuData.iterator_key;
32653
+ // const custom_iterator_val = $elm.data().xuData.iterator_val;
32654
+
32655
+ // let iterator_key = custom_iterator_key;
32656
+ // let iterator_val = custom_iterator_val;
32657
+ // let is_key_dynamic_field, is_val_dynamic_field;
32658
+
32659
+ // // custom FOR_VAL name or namespaced default name
32660
+ // if (!custom_iterator_key) {
32661
+ // is_key_dynamic_field = true;
32662
+
32663
+ // iterator_key = '_FOR_KEY';
32664
+ // }
32665
+
32666
+ // if (!custom_iterator_val) {
32667
+ // is_val_dynamic_field = true;
32668
+
32669
+ // iterator_val = '_FOR_VAL';
32670
+ // }
32671
+
32672
+ // var i = 0;
32673
+ // for await (let [_key, _val] of Object.entries(arr)) {
32674
+ // if (_.isArray(arr)) {
32675
+ // _key = Number(_key);
32676
+ // }
32677
+
32678
+ // const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
32679
+ // if (is_dynamic_field) {
32680
+ // func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
32681
+ // } else {
32682
+ // const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
32683
+
32684
+ // let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
32685
+ // if (view_field_obj) {
32686
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
32687
+ // try {
32688
+ // const row_idx = func.common.find_ROWID_idx(_ds, currentRecordId);
32689
+ // _ds.data_feed.rows[row_idx][field_id] = value;
32690
+ // } catch (err) {
32691
+ // console.error(err);
32692
+ // }
32693
+ // } else {
32694
+ // console.error('field not exist in dataset for xu-for method');
32695
+ // }
32696
+ // }
32697
+ // };
32698
+
32699
+ // var currentRecordId = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId.toString();
32700
+
32701
+ // await set_value(is_key_dynamic_field, currentRecordId, iterator_key, _key);
32702
+ // await set_value(is_val_dynamic_field, currentRecordId, iterator_val, _val);
32703
+
32704
+ // var iterate_info = {
32705
+ // _val,
32706
+ // _key,
32707
+ // iterator_key,
32708
+ // iterator_val,
32709
+ // is_key_dynamic_field,
32710
+ // is_val_dynamic_field,
32711
+ // reference_source_obj,
32712
+ // };
32713
+ // // let _parent_info = _.cloneDeep(parent_infoP) || {};
32714
+ // let _parent_info = klona.klona(parent_infoP) || {};
32715
+ // _parent_info.iterate_info = iterate_info;
32716
+
32717
+ // const $divP = await func.UI.screen.render_ui_tree(
32718
+ // SESSION_ID,
32719
+ // $container,
32720
+ // nodeP,
32721
+ // _parent_info, //parent_infoP ? _.cloneDeep(_parent_info) : null,
32722
+ // paramsP,
32723
+ // jobNoP,
32724
+ // null,
32725
+ // i,
32726
+ // null,
32727
+ // nodeP,
32728
+ // null,
32729
+ // $root_container,
32730
+ // );
32731
+
32732
+ // $.each($divP.children(), function (key, val) {
32733
+ // if ($(val)?.data()?.xuData) {
32734
+ // $(val).data().xuData.iterate_info = iterate_info;
32735
+ // }
32736
+ // });
32737
+
32738
+ // i++;
32739
+ // }
32740
+ // $elm.remove();
32741
+ // return { abort: true };
32742
+ // } catch (e) {
32743
+ // console.error(' Iterator Arr parse error');
32744
+ // return { abort: true };
32745
+ // }
32746
+ // },
32747
+ // 'xu-for-key': async function ($elm, val) {
32748
+ // $elm.data().xuData.iterator_key = val.value;
32749
+ // return {};
32750
+ // },
32751
+ // 'xu-for-val': async function ($elm, val) {
32752
+ // $elm.data().xuData.iterator_val = val.value;
32753
+ // return {};
32754
+ // },
32755
+ // 'xu-class': async function ($elm, val) {
32756
+ // try {
32757
+ // const classes_string = val.value;
32758
+ // // let obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
32759
+
32760
+ // const classes_obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
32761
+ // for await (const [cla, cond] of Object.entries(classes_obj)) {
32762
+ // let res = await func.expression.get(
32763
+ // SESSION_ID,
32764
+ // cond,
32765
+ // paramsP.dsSessionP,
32766
+ // 'UI Attr EXP',
32767
+ // $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
32768
+ // null,
32769
+ // null,
32770
+ // null,
32771
+ // null,
32772
+ // null,
32773
+ // $elm.data().xuData.iterate_info,
32774
+ // );
32775
+
32776
+ // if (res.result) {
32777
+ // $elm.addClass(cla);
32778
+ // } else {
32779
+ // $elm.removeClass(cla);
32780
+ // }
32781
+
32782
+ // $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
32783
+ // }
32784
+ // return {};
32785
+ // } catch (e) {
32786
+ // console.warn('parse error:' + val.value);
32787
+ // return { abort: true };
32788
+ // }
32789
+ // },
32790
+ // 'xu-exp': async function ($elm, val) {
32791
+ // let exp = val.value === null ? true : val.value;
32792
+
32793
+ // 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);
32794
+
32795
+ // let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
32796
+
32797
+ // var new_val = {
32798
+ // key: val.key,
32799
+ // value,
32800
+ // };
32801
+
32802
+ // if (nodeP.tagName.substr(0, 3) === 'xu-') {
32803
+ // if (tag_fx[nodeP.tagName][new_val.key]) {
32804
+ // return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
32805
+ // }
32806
+ // console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
32807
+ // return {};
32808
+ // }
32809
+ // if (!$elm.data().xuData) return;
32810
+
32811
+ // $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
32812
+
32813
+ // // IGNORE UNDEFINED or NULL ATTRIBUTES
32814
+ // if (typeof new_val.value === 'undefined' || new_val.value === null) {
32815
+ // return {};
32816
+ // }
32817
+
32818
+ // // IGNORE ATTRIBUTES WITH EMPTY VALUES
32819
+ // if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
32820
+ // return {};
32821
+ // }
32822
+
32823
+ // if (new_val.key.substr(0, 2) === 'xu') {
32824
+ // return await common_fx[new_val.key]($elm, new_val);
32825
+ // }
32826
+
32827
+ // $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
32828
+ // return {};
32829
+ // },
32830
+ // 'xu-on': async function ($elm, val) {
32831
+ // CLIENT_ACTIVITY_TS = Date.now();
32832
+ // const trigger = val.key.split('xu-on:')[1].toLowerCase();
32833
+ // $elm.on(trigger, async function (evt) {
32834
+ // const _$elm = $(evt.currentTarget);
32835
+ // if (_.isEmpty(_$elm.data().xuAttributes)) return;
32836
+
32837
+ // for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
32838
+ // if (!_.isEmpty(val.props.condition)) {
32839
+ // const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
32840
+ // if (!expCond.result) continue;
32841
+ // }
32842
+
32843
+ // if (val.event_modifiers && evt[val.event_modifiers]) {
32844
+ // evt[val.event_modifiers]();
32845
+ // }
32846
+
32847
+ // // if (val.handler === 'custom') {
32848
+ // if (val.workflow) {
32849
+ // // do BL
32850
+ // for await (const [key2, val2] of Object.entries(val.workflow)) {
32851
+ // // var cond = val2.data.enabled;
32852
+ // // if (val2.data.enabled && val2.props.condition) {
32853
+ // // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
32854
+ // // cond = expCond.result;
32855
+ // // }
32856
+ // // if (!cond) continue;
32857
+
32858
+ // if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
32859
+
32860
+ // 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);
32861
+ // }
32862
+ // }
32863
+ // }
32864
+ // });
32865
+ // return {};
32866
+ // },
32867
+ // 'xu-script': async function ($elm, val) {
32868
+ // var checkExist = setInterval(async function () {
32869
+ // if ($elm.is(':visible')) {
32870
+ // try {
32871
+ // // var res = eval('(' + val.value + ')');
32872
+ // // const fn = `(function(el) {
32873
+ // // ${val.value}
32874
+ // // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
32875
+
32876
+ // const fn = `async (el)=>{${val.value} };`;
32877
+
32878
+ // var res = eval(fn);
32879
+ // await res($elm[0]);
32880
+ // // if (typeof res === 'function') {
32881
+ // // res($elm[0]);
32882
+ // // }
32883
+ // } catch (e) {
32884
+ // eval(val.value);
32885
+ // }
32886
+
32887
+ // clearInterval(checkExist);
32888
+ // }
32889
+ // }, 100); // check every 100ms
32890
+
32891
+ // return {};
32892
+ // },
32893
+ // 'xu-style-global': async function ($elm, val) {
32894
+ // $('head').append(`<style>${val.value}</style>`);
32895
+ // return {};
32896
+ // },
32897
+ // 'xu-style': async function ($elm, val) {
32898
+ // var cssString = val.value;
32899
+
32900
+ // var parser = new cssjs();
32901
+
32902
+ // var parsed = parser.parseCSS(cssString);
32903
+ // var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
32904
+
32905
+ // $.each(parsed, function (key, val) {
32906
+ // var selectors_arr = val.selector.split(',');
32907
+
32908
+ // $.each(selectors_arr, function (key2, val2) {
32909
+ // selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
32910
+ // // console.log(new_selector);
32911
+ // });
32912
+
32913
+ // val.selector = selectors_arr.join(',');
32914
+ // // console.log(parsed);
32915
+ // });
32916
+
32917
+ // var newCSSString = parser.getCSSForEditor(parsed);
32918
+
32919
+ // $('head').append(`<style>${newCSSString}</style>`);
32920
+ // return {};
32921
+ // },
32922
+ // 'xu-cdn': async function ($elm, val) {
32923
+ // for await (const [key, resource] of Object.entries(val.value)) {
32924
+ // await load_cdn(resource);
32925
+ // }
32926
+
32927
+ // return {};
32928
+ // },
32929
+ // 'xu-ui-plugin': async function ($elm, val) {
32930
+ // var _session = SESSION_OBJ[SESSION_ID];
32931
+
32932
+ // for await (const [plugin_name, value] of Object.entries(val.value)) {
32933
+ // const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
32934
+ // if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
32935
+ // if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
32936
+ // const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
32937
+ // func.utils.load_css_on_demand(plugin_runtime_css_url);
32938
+ // }
32939
+
32940
+ // const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
32941
+
32942
+ // const plugin_index_resources = await import(plugin_index_src);
32943
+
32944
+ // let properties = _.cloneDeep(plugin_index_resources.properties);
32945
+ // for await (let [prop_name, prop_val] of Object.entries(properties)) {
32946
+ // prop_val.value = value?.attributes?.[prop_name];
32947
+ // if (value?.attributes?.[`xu-exp:${prop_name}`]) {
32948
+ // const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
32949
+ // prop_val.value = res.result;
32950
+ // }
32951
+ // }
32952
+ // // $elm.data().xu_ui_plugin = { properties };
32953
+ // const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
32954
+
32955
+ // const plugin_runtime_resources = await import(plugin_runtime_src);
32956
+
32957
+ // if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
32958
+ // for await (const resource of plugin_runtime_resources.cdn) {
32959
+ // await load_cdn(resource);
32960
+ // }
32961
+ // }
32962
+
32963
+ // if (plugin_runtime_resources.fn) {
32964
+ // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
32965
+ // // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
32966
+ // }
32967
+ // }
32968
+ // }
32969
+
32970
+ // return {};
32971
+ // },
32972
+ // 'xu-store': async function ($elm, val) {
32973
+ // try {
32974
+ // const fields_obj = JSON5.parse(val.value);
32975
+ // for (const [field_id, value] of Object.entries(fields_obj)) {
32976
+ // func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
32977
+ // }
32978
+ // } catch (err) {
32979
+ // console.error(err);
32980
+ // }
32981
+ // return {};
32982
+ // },
32983
+ // 'xu-viewport': async function ($elm, val) {
32984
+ // // functionality in draw_html_element
32985
+ // return {};
32986
+ // },
32987
+ // };
32988
+
32989
+ // if (nodeP.tagName.substr(0, 3) === 'xu-') {
32990
+ // if (xu_func === 'xu-exp') {
32991
+ // return common_fx[xu_func]($elm, val);
32992
+ // }
32993
+
32994
+ // if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
32995
+ // let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
32996
+ // return ret;
32997
+ // }
32998
+ // // if (xu_func !== "tree_id")
32999
+ // console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
33000
+ // return {};
33001
+ // }
33002
+ // if (_.isEmpty($elm.data())) {
33003
+ // return {};
33004
+ // }
33005
+ // if (!$elm.data().xuData.debug_info.attribute_stat) {
33006
+ // $elm.data().xuData.debug_info.attribute_stat = {};
33007
+ // }
33008
+ // if (xu_func !== 'xu-exp') {
33009
+ // $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
33010
+ // }
33011
+ // try {
33012
+ // if (!common_fx[xu_func]) {
33013
+ // console.warn('invalid xu-tag', xu_func, error);
33014
+ // return {};
33015
+ // }
33016
+
33017
+ // return await common_fx[xu_func]($elm, val);
33018
+ // } catch (error) {
33019
+ // debugger;
33020
+ // }
33021
+ // };
33022
+
33023
+ 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) {
33024
+ if (is_skeleton) return;
33025
+
33026
+ // Cache frequently accessed values
33027
+ const _session = SESSION_OBJ[SESSION_ID];
33028
+ const _ds = _session.DS_GLB[paramsP.dsSessionP];
33029
+ const elmData = $elm.data();
33030
+ const xuData = elmData.xuData;
33031
+ const nodeTag = nodeP.tagName;
33032
+ const isXuTag = nodeTag && nodeTag.startsWith('xu-');
32304
33033
 
33034
+ const load_cdn = async function (resource) {
33035
+ if (!_.isObject(resource)) {
33036
+ resource = _.isString(resource) ? { src: resource, type: 'js' } : null;
33037
+ }
33038
+ if (!resource) {
33039
+ throw new Error('cdn resource in wrong format');
33040
+ }
33041
+
33042
+ try {
33043
+ const loadFn = resource.type === 'css' ? func.utils.load_css_on_demand : func.utils.load_js_on_demand;
33044
+ const moduleArg = resource.type === 'module' ? 'module' : undefined;
33045
+ await loadFn(resource.src, moduleArg);
33046
+ } catch (error) {
33047
+ func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource.src, 'W');
33048
+ }
33049
+ };
33050
+
33051
+ const common_fx = {
33052
+ 'xu-attrs': async function ($elm, val) {
33053
+ if (!val.value || !_.isObject(val.value)) {
33054
+ if (val.value) throw 'xu-attrs value is not an object';
33055
+ return {};
33056
+ }
33057
+ Object.assign(nodeP.attributes, val.value);
33058
+ return {};
33059
+ },
33060
+
33061
+ 'xu-ref': async function ($elm, val, dsSession) {
33062
+ if (!val.value) return {};
33063
+
33064
+ func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
33065
+
33066
+ const targetNode = $elm[0];
33067
+ if (!targetNode) return {};
33068
+
33069
+ const observer = new MutationObserver(() => {
33070
+ func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
33071
+ });
33072
+
33073
+ observer.observe(targetNode, { attributes: true, childList: true, subtree: true });
33074
+ return {};
33075
+ },
33076
+
33077
+ 'xu-bind': async function ($elm, val) {
33078
+ if (is_skeleton) return {};
33079
+
33080
+ let val_is_reference_field = false;
33081
+ let _prog_id = xuData.paramsP.prog_id;
33082
+ let _dsP = xuData.paramsP.dsSessionP;
33083
+
33084
+ const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
33085
+ if (!view_ret) return {};
33086
+
33087
+ let is_dynamic_field = false;
33088
+ let field_prop;
33089
+ let bind_field_id;
33090
+ const input_field_type = $elm.attr('type');
33091
+
33092
+ const get_bind_field = async function (field_id) {
33093
+ if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
33094
+ is_dynamic_field = true;
33095
+ field_prop = _ds.dynamic_fields[field_id];
33096
+ } else {
33097
+ field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
33098
+ if (!field_prop) {
33099
+ const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
33100
+ if (ret_get_value.found) {
33101
+ _dsP = ret_get_value.dsSessionP;
33102
+ const ds = _session.DS_GLB[_dsP];
33103
+ _prog_id = ds.prog_id;
33104
+ const new_view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
33105
+ if (!new_view_ret) return {};
33106
+ field_prop = func.common.find_item_by_key(new_view_ret.progFields, 'field_id', field_id);
33107
+ }
33108
+ if (!field_prop) {
33109
+ throw `field ${field_id} not found in the program scope`;
33110
+ }
33111
+ }
33112
+ }
33113
+ return field_id;
33114
+ };
33115
+
33116
+ try {
33117
+ bind_field_id = await get_bind_field(val.value.split('.')[0]);
33118
+ val_is_reference_field = true;
33119
+ } catch (err) {
33120
+ console.error(err?.message || err);
33121
+ return {};
33122
+ }
33123
+
33124
+ const field_changed = async function (e) {
33125
+ const ds = _session.DS_GLB[_dsP];
33126
+ const fieldType = field_prop.props.fieldType;
33127
+ const isCheckbox = input_field_type === 'checkbox';
33128
+ const isRadio = input_field_type === 'radio';
33129
+
33130
+ // Handle array field with checkbox
33131
+ if (fieldType === 'array' && isCheckbox && val_is_reference_field) {
33132
+ const arr_value = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, ds.currentRecordId)).ret.value);
33133
+ const value_from_getter = bind.getter($elm[0]);
33134
+ const value = arr_value.includes(value_from_getter) ? arr_value.filter((item) => !_.isEqual(item, value_from_getter)) : [...arr_value, value_from_getter];
33135
+
33136
+ return await func.datasource.update(SESSION_ID, {
33137
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: value } },
33138
+ });
33139
+ }
33140
+
33141
+ // Handle array field with radio
33142
+ if (fieldType === 'array' && isRadio && val_is_reference_field) {
33143
+ return await func.datasource.update(SESSION_ID, {
33144
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: [bind.getter($elm[0])] } },
33145
+ });
33146
+ }
33147
+
33148
+ let value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', fieldType, bind.getter($elm[0]));
33149
+
33150
+ if (fieldType === 'object') {
33151
+ value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
33152
+ }
33153
+
33154
+ if (!ds.currentRecordId) return;
33155
+
33156
+ await func.datasource.update(SESSION_ID, {
33157
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: value } },
33158
+ });
33159
+
33160
+ const iterate_info = xuData?.iterate_info;
33161
+ const reference_source_obj = iterate_info?.reference_source_obj;
33162
+
33163
+ if (reference_source_obj?.ret?.type === 'array' && iterate_info.iterator_val === bind_field_id) {
33164
+ const arr_idx = Number(iterate_info._key);
33165
+ const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
33166
+ const new_arr = _.cloneDeep(dataset_arr.ret.value);
33167
+
33168
+ if (fieldType === 'object' && val_is_reference_field) {
33169
+ let obj_item = new_arr[arr_idx];
33170
+ const e_exp = val.value.replace(bind_field_id, 'obj_item');
33171
+ eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
33172
+ new_arr[arr_idx] = obj_item;
33173
+ } else {
33174
+ new_arr[arr_idx] = value;
33175
+ }
33176
+
33177
+ await func.datasource.update(
33178
+ SESSION_ID,
33179
+ {
33180
+ [_dsP]: { [ds.currentRecordId]: { [reference_source_obj.fieldIdP]: new_arr } },
33181
+ },
33182
+ null,
33183
+ true,
33184
+ );
33185
+ }
33186
+
33187
+ await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, ds.parentDataSourceNo);
33188
+ };
33189
+
33190
+ const bind = new UI_FRAMEWORK_PLUGIN.bind();
32305
33191
  bind.listener($elm[0], field_changed);
32306
33192
 
32307
33193
  const set_value = function () {
32308
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
32309
- if (!_ds.currentRecordId) return;
32310
- let value;
33194
+ const ds = _session.DS_GLB[paramsP.dsSessionP];
33195
+ if (!ds.currentRecordId) return;
33196
+
32311
33197
  try {
33198
+ let value;
32312
33199
  if (val_is_reference_field) {
32313
33200
  if (is_dynamic_field) {
32314
- value = _ds.dynamic_fields[bind_field_id].value;
33201
+ value = ds.dynamic_fields[bind_field_id].value;
32315
33202
  } else {
32316
- const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
32317
- value = _ds.data_feed.rows?.[row_idx]?.[bind_field_id];
33203
+ const row_idx = func.common.find_ROWID_idx(ds, ds.currentRecordId);
33204
+ value = ds.data_feed.rows?.[row_idx]?.[bind_field_id];
32318
33205
  }
32319
- if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'checkbox' && $elm.attr('value')) {
32320
- if (value.includes($elm.attr('value'))) {
32321
- value = true;
32322
- } else {
32323
- value = false;
32324
- }
32325
- } else if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'radio' && $elm.attr('value')) {
32326
- if (value.includes($elm.attr('value'))) {
32327
- value = $elm.attr('value');
32328
- } else {
32329
- value = false;
32330
- }
32331
- } else if (field_prop.props.fieldType === 'object' && val.value.split('.').length > 1) {
32332
- let str = val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')');
32333
- value = eval(str);
33206
+
33207
+ const fieldType = field_prop.props.fieldType;
33208
+ const elmValue = $elm.attr('value');
33209
+
33210
+ if (fieldType === 'array' && input_field_type === 'checkbox' && elmValue) {
33211
+ value = value.includes(elmValue);
33212
+ } else if (fieldType === 'array' && input_field_type === 'radio' && elmValue) {
33213
+ value = value.includes(elmValue) ? elmValue : false;
33214
+ } else if (fieldType === 'object' && val.value.split('.').length > 1) {
33215
+ value = eval(val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')'));
32334
33216
  }
32335
33217
  } else {
32336
33218
  value = val.value;
32337
33219
  }
32338
- if (typeof value === 'undefined') return;
32339
- bind.setter($elm[0], value);
33220
+
33221
+ if (value !== undefined) {
33222
+ bind.setter($elm[0], value);
33223
+ }
32340
33224
  } catch (err) {
32341
33225
  console.error(err);
32342
33226
  }
32343
33227
  };
32344
- /// init value from ds
32345
- $('body').on('xu-bind-refresh.' + _ds.dsSession.toString(), () => {
32346
- set_value();
32347
- });
32348
33228
 
33229
+ $('body').on('xu-bind-refresh.' + _ds.dsSession, set_value);
32349
33230
  set_value();
32350
33231
  return {};
32351
33232
  },
33233
+
32352
33234
  'xu-render': async function ($elm, val, from_panel) {
32353
- const old_render = async function () {
32354
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
33235
+ const value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
33236
+
33237
+ if (!glb.new_xu_render) {
33238
+ // Old render logic (kept as is for compatibility)
32355
33239
  const init_render = function () {
32356
33240
  if (!value) {
32357
- var cloned_$div = $elm.clone(true);
32358
-
32359
- let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container); //.hide();
32360
- let original_data_obj = {
33241
+ const cloned_$div = $elm.clone(true);
33242
+ const $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container);
33243
+ const original_data_obj = {
32361
33244
  $container: cloned_$div,
32362
33245
  nodeP: _.cloneDeep(nodeP),
32363
33246
  parent_infoP,
@@ -32370,8 +33253,6 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32370
33253
  $xurender.data().xuData.original_data_obj = original_data_obj;
32371
33254
  $xurender.data().xuData.xurender_node = cloned_$div;
32372
33255
  $xurender.data().xuAttributes = nodeP.attributes || {};
32373
- // $xurender.hide();
32374
-
32375
33256
  $elm.remove();
32376
33257
  return { abort: true };
32377
33258
  }
@@ -32381,271 +33262,207 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32381
33262
  const post_render = async function () {
32382
33263
  if (value) {
32383
33264
  try {
32384
- // abort if already rended
32385
- if ($elm[0].tagName !== 'XURENDER' && $elm?.length) {
33265
+ if ($elm[0].tagName !== 'XURENDER' || !$elm?.length) {
32386
33266
  return func.events.delete_job(SESSION_ID, jobNoP);
32387
33267
  }
32388
33268
 
32389
- let original_data_obj = $elm.data().xuData.original_data_obj;
32390
-
33269
+ const original_data_obj = $elm.data().xuData.original_data_obj;
32391
33270
  if (!original_data_obj) {
32392
33271
  func.events.delete_job(SESSION_ID, jobNoP);
32393
33272
  return { delete_job: jobNoP };
32394
33273
  }
32395
33274
 
32396
- const new_$div = await func.UI.screen.render_ui_tree(
32397
- SESSION_ID,
32398
- $elm, //original_data_obj.$container,
32399
- _.cloneDeep(original_data_obj.nodeP),
32400
- original_data_obj.parent_infoP,
32401
- original_data_obj.paramsP,
32402
- jobNoP,
32403
- null,
32404
- original_data_obj.keyP,
32405
- null,
32406
- original_data_obj.parent_nodeP,
32407
- null,
32408
- original_data_obj.$root_container,
32409
- );
33275
+ 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);
32410
33276
 
32411
33277
  new_$div.data().xuData.original_data_obj = original_data_obj;
32412
33278
  new_$div.data().xuData.xurender_node = $elm.clone(true);
32413
33279
  new_$div.data().xuAttributes = $elm.data().xuAttributes || {};
32414
33280
 
32415
33281
  const replace = async function () {
32416
- $elm.replaceWith(new_$div);
33282
+ $elm.replaceWith(from_panel ? new_$div.children() : new_$div);
32417
33283
  if (from_panel) {
32418
- const xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
32419
- $elm.parent().data().xuPanelWrapper = xuPanelWrapper;
32420
- $elm.replaceWith(new_$div.children());
33284
+ $elm.parent().data().xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
32421
33285
  }
32422
-
32423
33286
  if (val.fields_arr) {
32424
33287
  return await func.UI.screen.refresh_xu_attributes(SESSION_ID, val.fields_arr, val.jobNoP, new_$div);
32425
33288
  }
32426
33289
  func.events.delete_job(SESSION_ID, jobNoP);
32427
33290
  };
32428
- // if ($elm && func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'xu_id', $elm.data().xuData.xu_id).length) {
32429
- if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length) {
32430
- if (new_$div.data().xuData.paramsP) {
32431
- return await replace();
32432
- }
32433
33291
 
32434
- func.events.delete_job(SESSION_ID, jobNoP);
33292
+ if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length && new_$div.data().xuData.paramsP) {
33293
+ return await replace();
32435
33294
  }
33295
+ func.events.delete_job(SESSION_ID, jobNoP);
32436
33296
  } catch (error) {
32437
33297
  func.events.delete_job(SESSION_ID, jobNoP);
32438
33298
  }
32439
33299
  return;
32440
33300
  }
32441
- // if (!value) {
33301
+
32442
33302
  if ($elm.prop('tagName') === 'XURENDER') {
32443
33303
  func.events.delete_job(SESSION_ID, jobNoP);
32444
33304
  return;
32445
33305
  }
32446
33306
 
32447
- let tmp_$div = $('<div>');
33307
+ const $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id'));
32448
33308
 
32449
- let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).appendTo(tmp_$div); //.hide();
32450
- // was true before
32451
33309
  if ($elm.data().xuData.xurender_node) {
32452
33310
  $xurender.data({
32453
33311
  xuAttributes: $elm.data().xuData.xurender_node.data().xuAttributes || {},
32454
33312
  xuData: $elm.data().xuData.xurender_node.data().xuData || {},
32455
33313
  });
32456
33314
  } else {
32457
- // default new state
32458
-
32459
33315
  $xurender.data({
32460
33316
  xuAttributes: $elm.data().xuAttributes || {},
32461
33317
  xuData: $elm.data().xuData || {},
32462
33318
  });
32463
- const original_data_obj = {
33319
+ $xurender.data().xuData.original_data_obj = {
32464
33320
  nodeP: _.cloneDeep($elm.data().xuData.node_org),
32465
33321
  paramsP: $elm.data().xuData.paramsP,
32466
33322
  $container: $elm.clone(true),
32467
33323
  parent_infoP: parent_infoP,
32468
33324
  };
32469
-
32470
- $xurender.data().xuData.original_data_obj = original_data_obj;
32471
33325
  }
32472
33326
 
32473
- //remove xu-teleport trace
32474
33327
  $.each($elm.find('xu-teleport'), (key, val) => {
32475
33328
  const xuTeleportData = $(val).data().xuTeleportData || [];
32476
- for (const teleported_elm_id of xuTeleportData) {
32477
- $(`[xu-ui-id="${teleported_elm_id}"]`).remove();
32478
- }
33329
+ xuTeleportData.forEach((id) => $(`[xu-ui-id="${id}"]`).remove());
32479
33330
  });
32480
33331
 
32481
- $elm.replaceWith(tmp_$div.children());
33332
+ $elm.replaceWith($xurender);
32482
33333
  func.events.delete_job(SESSION_ID, jobNoP);
32483
- // }
32484
33334
  };
32485
- if (is_init) {
32486
- return init_render();
32487
- }
32488
- return await post_render();
32489
- };
32490
33335
 
32491
- const new_render = async function () {
32492
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
32493
- const has_xu_render_attribute = true;
32494
- const has_xu_exp_render_attribute = $elm.data()?.xuData?.attr_exp_info?.['xu-render'] ? true : false;
32495
- const init_render = async function () {
32496
- nodeP.xu_render_made = value;
32497
- if (!value) {
32498
- if (has_xu_exp_render_attribute) {
32499
- return { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true };
32500
- }
32501
- return { has_xu_render_attribute, abort: true };
32502
- }
32503
- return { has_xu_exp_render_attribute, has_xu_render_attribute };
32504
- };
33336
+ return is_init ? init_render() : await post_render();
33337
+ }
32505
33338
 
32506
- const post_render = async function () {
32507
- // always come from refresh
32508
- let nodeP = $container.data().xuData.node.children[keyP];
32509
- nodeP.xu_render_made = value;
32510
- if (value) {
32511
- try {
32512
- 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 || {}));
32513
- const xu_ui_id = $elm.attr('xu-ui-id');
32514
- let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[xu_ui_id + xu_render_cache_id]?.$div.clone(true);
32515
- let found_parent_vars = false;
32516
- if (new_$div) {
32517
- // validate if $div contains fields from parent ds
32518
- const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
32519
- const parent_fields = Object.keys(parent_data);
32520
-
32521
- $.each(new_$div.find('*'), (key, val) => {
32522
- const _xuAttributes = $(val)?.data()?.xuAttributes;
32523
- if (found_parent_vars || !_xuAttributes) return;
32524
- for (const [attr_key, attr_val] of Object.entries(_xuAttributes)) {
32525
- if (found_parent_vars) break;
32526
- for (const [key, val] of Object.entries(parent_fields)) {
32527
- if (attr_val.includes('@' + key)) {
32528
- found_parent_vars = true;
32529
- break;
32530
- }
32531
- }
32532
- }
32533
- });
32534
- }
33339
+ // New render logic
33340
+ const has_xu_render_attribute = true;
33341
+ const has_xu_exp_render_attribute = !!xuData?.attr_exp_info?.['xu-render'];
32535
33342
 
32536
- if (!new_$div || found_parent_vars) {
32537
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { paramsP };
32538
- nodeP.xu_render_xu_ui_id = xu_ui_id;
32539
- nodeP.xu_render_cache_id = xu_render_cache_id;
32540
- 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);
32541
- const _$div = new_$div.clone(true);
32542
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].$div = _$div;
32543
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].data = _$div.data();
32544
- }
32545
- // append order handling
33343
+ const init_render = async function () {
33344
+ nodeP.xu_render_made = value;
33345
+ if (!value) {
33346
+ 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 };
33347
+ }
33348
+ return { has_xu_exp_render_attribute, has_xu_render_attribute };
33349
+ };
32546
33350
 
32547
- if (!$container.children().length) {
32548
- new_$div.appendTo($container);
32549
- } else {
32550
- // iterate the container node
32551
- let $last_elm_found = [];
32552
- $.each($container.data().xuData.node.children, (item_key, item_val) => {
32553
- // const $elm = $(`[xu-node-id="${item_val.id}"]`);
32554
- const $elm = func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'nodeid', item_val.id);
32555
- if ($elm.length) {
32556
- $last_elm_found = $elm;
32557
- }
32558
- if (keyP == item_key) {
32559
- if ($last_elm_found.length) {
32560
- new_$div.after($last_elm_found);
32561
- } else {
32562
- $container.prepend(new_$div);
32563
- }
33351
+ const post_render = async function () {
33352
+ const containerNodeP = $container.data().xuData.node.children[keyP];
33353
+ containerNodeP.xu_render_made = value;
33354
+
33355
+ if (value) {
33356
+ try {
33357
+ const xu_render_cache_id = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys(xuData?.attr_exp_info?.['xu-render']?.fields || {}));
33358
+ const xu_ui_id = $elm.attr('xu-ui-id');
33359
+ const cache_key = xu_ui_id + xu_render_cache_id;
33360
+ let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[cache_key]?.$div?.clone(true);
33361
+ let found_parent_vars = false;
33362
+
33363
+ if (new_$div) {
33364
+ const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
33365
+ const parent_fields = Object.keys(parent_data);
33366
+
33367
+ $.each(new_$div.find('*'), (key, val) => {
33368
+ if (found_parent_vars) return;
33369
+ const _xuAttributes = $(val)?.data()?.xuAttributes;
33370
+ if (!_xuAttributes) return;
33371
+
33372
+ for (const attr_val of Object.values(_xuAttributes)) {
33373
+ if (parent_fields.some((field) => attr_val.includes('@' + field))) {
33374
+ found_parent_vars = true;
33375
+ break;
32564
33376
  }
32565
- });
32566
- }
32567
- } catch (error) {
32568
- func.events.delete_job(SESSION_ID, jobNoP);
33377
+ }
33378
+ });
32569
33379
  }
32570
- return;
32571
- }
32572
33380
 
32573
- /////////// !value ///////////
33381
+ if (!new_$div || found_parent_vars) {
33382
+ UI_WORKER_OBJ.xu_render_cache[cache_key] = { paramsP };
33383
+ containerNodeP.xu_render_xu_ui_id = xu_ui_id;
33384
+ containerNodeP.xu_render_cache_id = xu_render_cache_id;
32574
33385
 
32575
- const xu_ui_id = $elm.attr('xu-ui-id');
33386
+ 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);
32576
33387
 
32577
- const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
32578
- const _$div = $elm.clone(true);
32579
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
32580
- $elm.remove();
32581
- func.events.delete_job(SESSION_ID, jobNoP);
32582
- };
32583
- if (is_init) {
32584
- return await init_render();
33388
+ const _$div = new_$div.clone(true);
33389
+ UI_WORKER_OBJ.xu_render_cache[cache_key] = { $div: _$div, data: _$div.data(), paramsP };
33390
+ }
33391
+
33392
+ // Append order handling
33393
+ if (!$container.children().length) {
33394
+ new_$div.appendTo($container);
33395
+ } else {
33396
+ let $last_elm_found = [];
33397
+ $.each($container.data().xuData.node.children, (item_key, item_val) => {
33398
+ const $elm = func.UI.utils.find_in_element_data('xuData', $(_session.root_element), 'nodeid', item_val.id);
33399
+ if ($elm.length) $last_elm_found = $elm;
33400
+ if (keyP == item_key) {
33401
+ $last_elm_found.length ? new_$div.after($last_elm_found) : $container.prepend(new_$div);
33402
+ }
33403
+ });
33404
+ }
33405
+ } catch (error) {
33406
+ func.events.delete_job(SESSION_ID, jobNoP);
33407
+ }
33408
+ return;
32585
33409
  }
32586
- return await post_render();
33410
+
33411
+ // !value
33412
+ const xu_ui_id = $elm.attr('xu-ui-id');
33413
+ const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys(xuData?.attr_exp_info?.['xu-render']?.fields || {}));
33414
+ const _$div = $elm.clone(true);
33415
+ UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
33416
+ $elm.remove();
33417
+ func.events.delete_job(SESSION_ID, jobNoP);
32587
33418
  };
32588
33419
 
32589
- if (glb.new_xu_render) {
32590
- return new_render();
32591
- }
32592
- return old_render();
33420
+ return is_init ? await init_render() : await post_render();
32593
33421
  },
33422
+
32594
33423
  'xu-show': async function ($elm, val) {
32595
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
32596
- if (value) {
32597
- $elm.show();
32598
- }
32599
- if (!value) {
32600
- $elm.hide();
32601
- }
33424
+ const value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
33425
+ $elm.toggle(value);
32602
33426
  return {};
32603
33427
  },
33428
+
32604
33429
  'xu-content': async function ($elm, val) {
32605
33430
  try {
32606
33431
  $elm.html(val.value);
32607
33432
  } catch (error) {
32608
- console.warn(e);
33433
+ console.warn(error);
32609
33434
  }
32610
- return;
32611
33435
  },
33436
+
32612
33437
  'xu-text': async function ($elm, val) {
32613
33438
  try {
32614
33439
  $elm.text(val.value);
32615
33440
  } catch (error) {
32616
- console.warn(e);
33441
+ console.warn(error);
32617
33442
  }
32618
- return;
32619
33443
  },
33444
+
32620
33445
  'xu-html': async function ($elm, val) {
32621
33446
  try {
32622
33447
  $elm.html(val.value);
32623
33448
  } catch (error) {
32624
- console.warn(e);
33449
+ console.warn(error);
32625
33450
  }
32626
- return;
32627
33451
  },
33452
+
32628
33453
  'xu-for': async function ($elm, data) {
32629
- // exit if call from rendered xu-for item to prevent infante loop (parent_infoP?.iterate_info indicate call from rendered item)
32630
- if (parent_infoP?.iterate_info) return {};
32631
- if (!data.value) return {};
33454
+ if (parent_infoP?.iterate_info || !data.value) return {};
33455
+
32632
33456
  try {
32633
- // 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.
32634
33457
  let arr = data.value;
32635
-
32636
- // find reference source field
32637
33458
  let reference_source_obj;
32638
-
32639
33459
  const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
33460
+ const view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
32640
33461
 
32641
- let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
32642
- // detect if data.value (xu-for) is reference field_id by checking if exist in the dataset
32643
33462
  if (view_field_obj) {
32644
- // xu-for is reference field_id
32645
33463
  reference_source_obj = await func.datasource.get_value(SESSION_ID, data.value, paramsP.dsSessionP);
32646
33464
  arr = reference_source_obj?.ret?.value;
32647
33465
  } else {
32648
- // xu-for is actual data
32649
33466
  if (typeof data.value === 'string') {
32650
33467
  arr = eval(data.value.replaceAll('\\', ''));
32651
33468
  }
@@ -32654,59 +33471,44 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32654
33471
  }
32655
33472
  }
32656
33473
 
32657
- const custom_iterator_key = $elm.data().xuData.iterator_key;
32658
- const custom_iterator_val = $elm.data().xuData.iterator_val;
32659
-
32660
- let iterator_key = custom_iterator_key;
32661
- let iterator_val = custom_iterator_val;
32662
- let is_key_dynamic_field, is_val_dynamic_field;
33474
+ const custom_iterator_key = xuData.iterator_key;
33475
+ const custom_iterator_val = xuData.iterator_val;
33476
+ const iterator_key = custom_iterator_key || '_FOR_KEY';
33477
+ const iterator_val = custom_iterator_val || '_FOR_VAL';
33478
+ const is_key_dynamic_field = !custom_iterator_key;
33479
+ const is_val_dynamic_field = !custom_iterator_val;
32663
33480
 
32664
- // custom FOR_VAL name or namespaced default name
32665
- if (!custom_iterator_key) {
32666
- is_key_dynamic_field = true;
32667
-
32668
- iterator_key = '_FOR_KEY';
32669
- }
32670
-
32671
- if (!custom_iterator_val) {
32672
- is_val_dynamic_field = true;
32673
-
32674
- iterator_val = '_FOR_VAL';
32675
- }
32676
-
32677
- var i = 0;
32678
- for await (let [_key, _val] of Object.entries(arr)) {
32679
- if (_.isArray(arr)) {
32680
- _key = Number(_key);
32681
- }
32682
-
32683
- const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
32684
- if (is_dynamic_field) {
32685
- func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
32686
- } else {
32687
- const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
33481
+ const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
33482
+ if (is_dynamic_field) {
33483
+ func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
33484
+ } else {
33485
+ const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
33486
+ const view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
32688
33487
 
32689
- let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
32690
- if (view_field_obj) {
32691
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
32692
- try {
32693
- const row_idx = func.common.find_ROWID_idx(_ds, currentRecordId);
32694
- _ds.data_feed.rows[row_idx][field_id] = value;
32695
- } catch (err) {
32696
- console.error(err);
32697
- }
32698
- } else {
32699
- console.error('field not exist in dataset for xu-for method');
33488
+ if (view_field_obj) {
33489
+ const ds = _session.DS_GLB[paramsP.dsSessionP];
33490
+ try {
33491
+ const row_idx = func.common.find_ROWID_idx(ds, currentRecordId);
33492
+ ds.data_feed.rows[row_idx][field_id] = value;
33493
+ } catch (err) {
33494
+ console.error(err);
32700
33495
  }
33496
+ } else {
33497
+ console.error('field not exist in dataset for xu-for method');
32701
33498
  }
32702
- };
33499
+ }
33500
+ };
32703
33501
 
32704
- var currentRecordId = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId.toString();
33502
+ const currentRecordId = _ds.currentRecordId.toString();
33503
+ let i = 0;
33504
+
33505
+ for (let [_key, _val] of Object.entries(arr)) {
33506
+ if (_.isArray(arr)) _key = Number(_key);
32705
33507
 
32706
33508
  await set_value(is_key_dynamic_field, currentRecordId, iterator_key, _key);
32707
33509
  await set_value(is_val_dynamic_field, currentRecordId, iterator_val, _val);
32708
33510
 
32709
- var iterate_info = {
33511
+ const iterate_info = {
32710
33512
  _val,
32711
33513
  _key,
32712
33514
  iterator_key,
@@ -32715,26 +33517,13 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32715
33517
  is_val_dynamic_field,
32716
33518
  reference_source_obj,
32717
33519
  };
32718
- // let _parent_info = _.cloneDeep(parent_infoP) || {};
32719
- let _parent_info = klona.klona(parent_infoP) || {};
33520
+
33521
+ const _parent_info = klona.klona(parent_infoP) || {};
32720
33522
  _parent_info.iterate_info = iterate_info;
32721
33523
 
32722
- const $divP = await func.UI.screen.render_ui_tree(
32723
- SESSION_ID,
32724
- $container,
32725
- nodeP,
32726
- _parent_info, //parent_infoP ? _.cloneDeep(_parent_info) : null,
32727
- paramsP,
32728
- jobNoP,
32729
- null,
32730
- i,
32731
- null,
32732
- nodeP,
32733
- null,
32734
- $root_container,
32735
- );
33524
+ const $divP = await func.UI.screen.render_ui_tree(SESSION_ID, $container, nodeP, _parent_info, paramsP, jobNoP, null, i, null, nodeP, null, $root_container);
32736
33525
 
32737
- $.each($divP.children(), function (key, val) {
33526
+ $.each($divP.children(), (key, val) => {
32738
33527
  if ($(val)?.data()?.xuData) {
32739
33528
  $(val).data().xuData.iterate_info = iterate_info;
32740
33529
  }
@@ -32742,106 +33531,87 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32742
33531
 
32743
33532
  i++;
32744
33533
  }
33534
+
32745
33535
  $elm.remove();
32746
33536
  return { abort: true };
32747
33537
  } catch (e) {
32748
- console.error(' Iterator Arr parse error');
33538
+ console.error('Iterator Arr parse error', e);
32749
33539
  return { abort: true };
32750
33540
  }
32751
33541
  },
33542
+
32752
33543
  'xu-for-key': async function ($elm, val) {
32753
- $elm.data().xuData.iterator_key = val.value;
33544
+ xuData.iterator_key = val.value;
32754
33545
  return {};
32755
33546
  },
33547
+
32756
33548
  'xu-for-val': async function ($elm, val) {
32757
- $elm.data().xuData.iterator_val = val.value;
33549
+ xuData.iterator_val = val.value;
32758
33550
  return {};
32759
33551
  },
33552
+
32760
33553
  'xu-class': async function ($elm, val) {
32761
33554
  try {
32762
- const classes_string = val.value;
32763
- // let obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
32764
-
32765
- const classes_obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
32766
- for await (const [cla, cond] of Object.entries(classes_obj)) {
32767
- let res = await func.expression.get(
32768
- SESSION_ID,
32769
- cond,
32770
- paramsP.dsSessionP,
32771
- 'UI Attr EXP',
32772
- $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
32773
- null,
32774
- null,
32775
- null,
32776
- null,
32777
- null,
32778
- $elm.data().xuData.iterate_info,
32779
- );
33555
+ const classes_obj = _.isString(val.value) ? JSON.parse(val.value) : _.defaults(val.value, {});
32780
33556
 
32781
- if (res.result) {
32782
- $elm.addClass(cla);
32783
- } else {
32784
- $elm.removeClass(cla);
32785
- }
33557
+ for (const [cla, cond] of Object.entries(classes_obj)) {
33558
+ const res = await func.expression.get(SESSION_ID, cond, paramsP.dsSessionP, 'UI Attr EXP', xuData.currentRecordId, null, null, null, null, null, xuData.iterate_info);
32786
33559
 
32787
- $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
33560
+ $elm.toggleClass(cla, res.result);
32788
33561
  }
33562
+
33563
+ xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
32789
33564
  return {};
32790
33565
  } catch (e) {
32791
33566
  console.warn('parse error:' + val.value);
32792
33567
  return { abort: true };
32793
33568
  }
32794
33569
  },
32795
- 'xu-exp': async function ($elm, val) {
32796
- let exp = val.value === null ? true : val.value;
32797
33570
 
32798
- 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);
32799
-
32800
- let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
33571
+ 'xu-exp': async function ($elm, val) {
33572
+ const exp = val.value === null ? true : val.value;
33573
+ 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);
32801
33574
 
32802
- var new_val = {
32803
- key: val.key,
32804
- value,
32805
- };
33575
+ const value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
33576
+ const new_val = { key: val.key, value };
32806
33577
 
32807
- if (nodeP.tagName.substr(0, 3) === 'xu-') {
32808
- if (tag_fx[nodeP.tagName][new_val.key]) {
32809
- return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
33578
+ if (isXuTag) {
33579
+ if (tag_fx[nodeTag]?.[new_val.key]) {
33580
+ return await tag_fx[nodeTag][new_val.key]($elm, new_val);
32810
33581
  }
32811
- console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
33582
+ console.warn(`attribute ${new_val.key} not found for ${nodeTag}`);
32812
33583
  return {};
32813
33584
  }
32814
- if (!$elm.data().xuData) return;
32815
33585
 
32816
- $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
33586
+ if (!xuData) return {};
33587
+ xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
32817
33588
 
32818
- // IGNORE UNDEFINED or NULL ATTRIBUTES
32819
- if (typeof new_val.value === 'undefined' || new_val.value === null) {
32820
- return {};
32821
- }
33589
+ if (new_val.value === undefined || new_val.value === null) return {};
33590
+ if (glb.solid_attributes.includes(new_val.key) && !new_val.value) return {};
32822
33591
 
32823
- // IGNORE ATTRIBUTES WITH EMPTY VALUES
32824
- if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
32825
- return {};
32826
- }
32827
-
32828
- if (new_val.key.substr(0, 2) === 'xu') {
33592
+ if (new_val.key.startsWith('xu')) {
32829
33593
  return await common_fx[new_val.key]($elm, new_val);
32830
33594
  }
32831
33595
 
32832
33596
  $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
32833
33597
  return {};
32834
33598
  },
33599
+
32835
33600
  'xu-on': async function ($elm, val) {
32836
33601
  CLIENT_ACTIVITY_TS = Date.now();
32837
33602
  const trigger = val.key.split('xu-on:')[1].toLowerCase();
33603
+
32838
33604
  $elm.on(trigger, async function (evt) {
32839
33605
  const _$elm = $(evt.currentTarget);
32840
- if (_.isEmpty(_$elm.data().xuAttributes)) return;
33606
+ const xuAttributes = _$elm.data().xuAttributes;
33607
+ if (_.isEmpty(xuAttributes)) return;
32841
33608
 
32842
- for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
33609
+ const handlers = xuAttributes['xu-on:' + evt.type];
33610
+ if (!handlers) return;
33611
+
33612
+ for (const [key, val] of Object.entries(handlers)) {
32843
33613
  if (!_.isEmpty(val.props.condition)) {
32844
- const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
33614
+ const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid);
32845
33615
  if (!expCond.result) continue;
32846
33616
  }
32847
33617
 
@@ -32849,18 +33619,9 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32849
33619
  evt[val.event_modifiers]();
32850
33620
  }
32851
33621
 
32852
- // if (val.handler === 'custom') {
32853
33622
  if (val.workflow) {
32854
- // do BL
32855
- for await (const [key2, val2] of Object.entries(val.workflow)) {
32856
- // var cond = val2.data.enabled;
32857
- // if (val2.data.enabled && val2.props.condition) {
32858
- // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
32859
- // cond = expCond.result;
32860
- // }
32861
- // if (!cond) continue;
32862
-
32863
- if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
33623
+ for (const [key2, val2] of Object.entries(val.workflow)) {
33624
+ if (!val2.data.enabled) continue;
32864
33625
 
32865
33626
  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);
32866
33627
  }
@@ -32869,111 +33630,91 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32869
33630
  });
32870
33631
  return {};
32871
33632
  },
33633
+
32872
33634
  'xu-script': async function ($elm, val) {
32873
- var checkExist = setInterval(async function () {
33635
+ const checkExist = setInterval(async function () {
32874
33636
  if ($elm.is(':visible')) {
32875
33637
  try {
32876
- // var res = eval('(' + val.value + ')');
32877
- // const fn = `(function(el) {
32878
- // ${val.value}
32879
- // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
32880
-
32881
- const fn = `async (el)=>{${val.value} };`;
32882
-
32883
- var res = eval(fn);
32884
- await res($elm[0]);
32885
- // if (typeof res === 'function') {
32886
- // res($elm[0]);
32887
- // }
33638
+ const fn = eval(`async (el)=>{${val.value}}`);
33639
+ await fn($elm[0]);
32888
33640
  } catch (e) {
32889
33641
  eval(val.value);
32890
33642
  }
32891
-
32892
33643
  clearInterval(checkExist);
32893
33644
  }
32894
- }, 100); // check every 100ms
32895
-
33645
+ }, 100);
32896
33646
  return {};
32897
33647
  },
33648
+
32898
33649
  'xu-style-global': async function ($elm, val) {
32899
33650
  $('head').append(`<style>${val.value}</style>`);
32900
33651
  return {};
32901
33652
  },
32902
- 'xu-style': async function ($elm, val) {
32903
- var cssString = val.value;
32904
-
32905
- var parser = new cssjs();
32906
-
32907
- var parsed = parser.parseCSS(cssString);
32908
- var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
32909
33653
 
32910
- $.each(parsed, function (key, val) {
32911
- var selectors_arr = val.selector.split(',');
32912
-
32913
- $.each(selectors_arr, function (key2, val2) {
32914
- selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
32915
- // console.log(new_selector);
32916
- });
32917
-
32918
- val.selector = selectors_arr.join(',');
32919
- // console.log(parsed);
33654
+ 'xu-style': async function ($elm, val) {
33655
+ const parser = new cssjs();
33656
+ const parsed = parser.parseCSS(val.value);
33657
+ const xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
33658
+
33659
+ parsed.forEach((rule) => {
33660
+ rule.selector = rule.selector
33661
+ .split(',')
33662
+ .map((sel) => `${xuUiId} ${sel}, ${xuUiId}${sel}`)
33663
+ .join(',');
32920
33664
  });
32921
33665
 
32922
- var newCSSString = parser.getCSSForEditor(parsed);
32923
-
32924
- $('head').append(`<style>${newCSSString}</style>`);
33666
+ $('head').append(`<style>${parser.getCSSForEditor(parsed)}</style>`);
32925
33667
  return {};
32926
33668
  },
33669
+
32927
33670
  'xu-cdn': async function ($elm, val) {
32928
- for await (const [key, resource] of Object.entries(val.value)) {
33671
+ for (const resource of Object.values(val.value)) {
32929
33672
  await load_cdn(resource);
32930
33673
  }
32931
-
32932
33674
  return {};
32933
33675
  },
32934
- 'xu-ui-plugin': async function ($elm, val) {
32935
- var _session = SESSION_OBJ[SESSION_ID];
32936
33676
 
32937
- for await (const [plugin_name, value] of Object.entries(val.value)) {
33677
+ 'xu-ui-plugin': async function ($elm, val) {
33678
+ for (const [plugin_name, value] of Object.entries(val.value)) {
32938
33679
  const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
32939
- if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
32940
- if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
32941
- const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
32942
- func.utils.load_css_on_demand(plugin_runtime_css_url);
32943
- }
32944
33680
 
32945
- const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
33681
+ if (!_plugin?.installed || !_plugin?.manifest?.['runtime.mjs']?.exist || !_plugin?.manifest?.['index.mjs']?.exist || !value.enabled) continue;
32946
33682
 
32947
- const plugin_index_resources = await import(plugin_index_src);
33683
+ if (_plugin.manifest['runtime.mjs'].dist && _plugin.manifest['runtime.mjs'].css) {
33684
+ const css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
33685
+ func.utils.load_css_on_demand(css_url);
33686
+ }
32948
33687
 
32949
- let properties = _.cloneDeep(plugin_index_resources.properties);
32950
- for await (let [prop_name, prop_val] of Object.entries(properties)) {
32951
- prop_val.value = value?.attributes?.[prop_name];
32952
- if (value?.attributes?.[`xu-exp:${prop_name}`]) {
32953
- const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
32954
- prop_val.value = res.result;
32955
- }
32956
- }
32957
- // $elm.data().xu_ui_plugin = { properties };
32958
- const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
33688
+ const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
32959
33689
 
32960
- const plugin_runtime_resources = await import(plugin_runtime_src);
33690
+ const plugin_index_resources = await import(plugin_index_src);
33691
+ const properties = _.cloneDeep(plugin_index_resources.properties);
32961
33692
 
32962
- if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
32963
- for await (const resource of plugin_runtime_resources.cdn) {
32964
- await load_cdn(resource);
32965
- }
33693
+ for (const [prop_name, prop_val] of Object.entries(properties)) {
33694
+ prop_val.value = value?.attributes?.[prop_name];
33695
+ if (value?.attributes?.[`xu-exp:${prop_name}`]) {
33696
+ const res = await func.expression.get(SESSION_ID, value.attributes[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
33697
+ prop_val.value = res.result;
32966
33698
  }
33699
+ }
33700
+
33701
+ const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
32967
33702
 
32968
- if (plugin_runtime_resources.fn) {
32969
- await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
32970
- // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
33703
+ const plugin_runtime_resources = await import(plugin_runtime_src);
33704
+
33705
+ if (plugin_runtime_resources.cdn && _.isArray(plugin_runtime_resources.cdn)) {
33706
+ for (const resource of plugin_runtime_resources.cdn) {
33707
+ await load_cdn(resource);
32971
33708
  }
32972
33709
  }
32973
- }
32974
33710
 
33711
+ if (plugin_runtime_resources.fn) {
33712
+ await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
33713
+ }
33714
+ }
32975
33715
  return {};
32976
33716
  },
33717
+
32977
33718
  'xu-store': async function ($elm, val) {
32978
33719
  try {
32979
33720
  const fields_obj = JSON5.parse(val.value);
@@ -32985,43 +33726,135 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32985
33726
  }
32986
33727
  return {};
32987
33728
  },
33729
+
32988
33730
  'xu-viewport': async function ($elm, val) {
32989
- // functionality in draw_html_element
32990
33731
  return {};
32991
33732
  },
32992
33733
  };
32993
33734
 
32994
- if (nodeP.tagName.substr(0, 3) === 'xu-') {
33735
+ const tag_fx = {
33736
+ 'xu-panel': {
33737
+ program: async function ($elm, val) {
33738
+ const init_program = async function () {
33739
+ async function render_panel() {
33740
+ const prog_id = val.value?.prog || val.value;
33741
+ const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
33742
+ 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);
33743
+
33744
+ const containerData = $container.data();
33745
+ if (containerData.xuData) {
33746
+ containerData.xuData.xuPanelProps = elmData.xuAttributes;
33747
+ containerData.xuData.xuPanelData = ret_panel.data();
33748
+ }
33749
+ return { $new_div: ret_panel };
33750
+ }
33751
+
33752
+ if (!val.value) val.value = '_empty_panel_program';
33753
+ return await render_panel();
33754
+ };
33755
+
33756
+ const alter_program = async function () {
33757
+ async function render_panel() {
33758
+ const program = val.value?.prog || val.value;
33759
+ const $wrapper = $('<div>');
33760
+ 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, '');
33761
+
33762
+ const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
33763
+ 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);
33764
+
33765
+ await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, ret_init, nodeP, $div.clone(true), jobNoP);
33766
+
33767
+ return { $new_div: ret_init, abort: true };
33768
+ }
33769
+
33770
+ if (!val.value) return { abort: true };
33771
+ await render_panel();
33772
+ return { abort: true };
33773
+ };
33774
+
33775
+ return is_init ? await init_program() : await alter_program();
33776
+ },
33777
+
33778
+ 'xu-render': async function ($elm, val) {
33779
+ return await common_fx['xu-render']($elm, val, true);
33780
+ },
33781
+
33782
+ 'xu-ref': async function ($elm, val) {
33783
+ return await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
33784
+ },
33785
+ },
33786
+
33787
+ 'xu-teleport': {
33788
+ to: async function ($elm, val) {
33789
+ if (!glb.new_xu_render && val.value) {
33790
+ if ($elm?.parent()?.data()?.xuData?.length) {
33791
+ $elm.parent().data('xuTeleportData', []);
33792
+ for (const [key, node] of Object.entries(nodeP.children)) {
33793
+ 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);
33794
+ $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
33795
+ $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
33796
+ }
33797
+ $elm.remove();
33798
+ } else {
33799
+ $elm.data('xuTeleportData', []).attr('hidden', true);
33800
+ for (const [key, node] of Object.entries(nodeP.children)) {
33801
+ const $to_container = $(val.value);
33802
+ if (!$to_container?.length) {
33803
+ return console.error(`container ${val.value} for xuTeleportData not found`);
33804
+ }
33805
+ 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);
33806
+ $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
33807
+ $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
33808
+ }
33809
+ }
33810
+ return { abort: true };
33811
+ }
33812
+ return {};
33813
+ },
33814
+
33815
+ 'xu-render': async function ($elm, val) {
33816
+ return await common_fx['xu-render']($elm, val, true);
33817
+ },
33818
+
33819
+ 'xu-show': async function ($elm, val) {
33820
+ return await common_fx['xu-show']($elm, val, true);
33821
+ },
33822
+ },
33823
+ };
33824
+
33825
+ // Main execution logic
33826
+ if (isXuTag) {
32995
33827
  if (xu_func === 'xu-exp') {
32996
33828
  return common_fx[xu_func]($elm, val);
32997
33829
  }
32998
33830
 
32999
- if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
33000
- let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
33001
- return ret;
33831
+ if (tag_fx?.[nodeTag]?.[xu_func]) {
33832
+ return await tag_fx[nodeTag][xu_func]($elm, val);
33002
33833
  }
33003
- // if (xu_func !== "tree_id")
33004
- console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
33005
- return {};
33006
- }
33007
- if (_.isEmpty($elm.data())) {
33834
+
33835
+ console.warn(`attribute ${xu_func} not found for ${nodeTag}`);
33008
33836
  return {};
33009
33837
  }
33010
- if (!$elm.data().xuData.debug_info.attribute_stat) {
33011
- $elm.data().xuData.debug_info.attribute_stat = {};
33838
+
33839
+ if (_.isEmpty(elmData)) return {};
33840
+
33841
+ if (!xuData.debug_info.attribute_stat) {
33842
+ xuData.debug_info.attribute_stat = {};
33012
33843
  }
33844
+
33013
33845
  if (xu_func !== 'xu-exp') {
33014
- $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
33846
+ xuData.debug_info.attribute_stat[xu_func] = val.value;
33015
33847
  }
33848
+
33016
33849
  try {
33017
33850
  if (!common_fx[xu_func]) {
33018
- console.warn('invalid xu-tag', xu_func, error);
33851
+ console.warn('invalid xu-tag', xu_func);
33019
33852
  return {};
33020
33853
  }
33021
-
33022
33854
  return await common_fx[xu_func]($elm, val);
33023
33855
  } catch (error) {
33024
- debugger;
33856
+ console.error('execute_xu_functions error:', error);
33857
+ return {};
33025
33858
  }
33026
33859
  };
33027
33860
 
@@ -33044,62 +33877,408 @@ func.UI.screen.fix_val_defaults = function (key, val) {
33044
33877
  return ret;
33045
33878
  };
33046
33879
 
33880
+ // 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) {
33881
+ // var done_exp = [];
33882
+
33883
+ // const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
33884
+ // if (!_ds) return { abort: true };
33885
+
33886
+ // const get_attr_value = async function (key) {
33887
+ // let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
33888
+ // if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
33889
+ // ret = await get_xuExp(key);
33890
+ // }
33891
+ // return ret;
33892
+ // };
33893
+
33894
+ // const get_xuExp = async function (attrib) {
33895
+ // if (is_skeleton) return;
33896
+ // if (glb.new_xu_render) {
33897
+ // let _xuData = $elm.data().xuData;
33898
+ // if (!_xuData.attr_exp_info) {
33899
+ // _xuData.attr_exp_info = {};
33900
+ // }
33901
+ // }
33902
+ // const attr = `xu-exp:${attrib}`;
33903
+
33904
+ // if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
33905
+ // // const attr = `xu-exp-${attrib}`;
33906
+ // var exp = nodeP.attributes[attr];
33907
+ // // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
33908
+
33909
+ // var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
33910
+ // if (glb.new_xu_render) {
33911
+ // _xuData.attr_exp_info[attrib] = res;
33912
+ // }
33913
+ // // nodeP.attributes[attr] = value; //{ value: value, res: res };
33914
+ // done_exp.push(attr);
33915
+ // return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
33916
+ // };
33917
+
33918
+ // var _ret = {};
33919
+ // if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
33920
+
33921
+ // for (let [key, val] of Object.entries(nodeP.attributes)) {
33922
+ // // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
33923
+ // if (key.substring(0, 6) === 'xu-exp') {
33924
+ // if (_.isEmpty(val)) {
33925
+ // delete nodeP.attributes[key];
33926
+ // continue;
33927
+ // }
33928
+ // const clean_key = key.split(':')[1];
33929
+ // if (typeof nodeP.attributes[clean_key] !== 'undefined') {
33930
+ // delete nodeP.attributes[clean_key];
33931
+ // }
33932
+ // }
33933
+ // // FIX abbreviations
33934
+ // if (glb.attr_abbreviations_arr.includes(key)) {
33935
+ // nodeP.attributes[`xu-on:${key.substring(3)}`] = [
33936
+ // {
33937
+ // handler: 'custom',
33938
+ // props: {},
33939
+ // event: [
33940
+ // {
33941
+ // id: Date.now(),
33942
+ // data: {
33943
+ // action: 'update',
33944
+ // name: { value: val },
33945
+ // enabled: true,
33946
+ // },
33947
+ // props: {},
33948
+ // },
33949
+ // ],
33950
+ // },
33951
+ // ];
33952
+ // delete nodeP.attributes[key];
33953
+ // }
33954
+ // }
33955
+
33956
+ // for (let [key, val] of Object.entries(nodeP.attributes)) {
33957
+ // // FIX STATIC DEFAULTS
33958
+ // val = func.UI.screen.fix_val_defaults(key, val);
33959
+
33960
+ // // REMOVE UNDEFINED or NULL ATTRIBUTES
33961
+ // if (typeof val === 'undefined' || val === null) {
33962
+ // delete nodeP.attributes[key];
33963
+ // }
33964
+
33965
+ // // REMOVE ATTRIBUTES WITH EMPTY VALUES
33966
+ // if (glb.solid_attributes.includes(key) && !val) {
33967
+ // delete nodeP.attributes[key];
33968
+ // }
33969
+ // }
33970
+
33971
+ // // XU-ATTRS
33972
+ // if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
33973
+ // const attr = 'xu-attrs';
33974
+ // let ret = await func.UI.screen.execute_xu_functions(
33975
+ // SESSION_ID,
33976
+ // is_skeleton,
33977
+ // $root_container,
33978
+ // nodeP,
33979
+ // $container,
33980
+ // paramsP,
33981
+ // parent_infoP,
33982
+ // jobNoP,
33983
+ // keyP,
33984
+ // parent_nodeP,
33985
+ // attr,
33986
+ // $elm,
33987
+ // {
33988
+ // key: attr,
33989
+ // value: await get_attr_value(attr),
33990
+ // },
33991
+ // is_init,
33992
+ // );
33993
+ // }
33994
+
33995
+ // // BEFORE
33996
+ // if (!_.isEmpty(nodeP.attributes)) {
33997
+ // for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
33998
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33999
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
34000
+ // continue;
34001
+ // }
34002
+
34003
+ // if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
34004
+ // continue;
34005
+ // }
34006
+
34007
+ // if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
34008
+ // continue;
34009
+ // }
34010
+
34011
+ // let ret = await func.UI.screen.execute_xu_functions(
34012
+ // SESSION_ID,
34013
+ // is_skeleton,
34014
+ // $root_container,
34015
+ // nodeP,
34016
+ // $container,
34017
+ // paramsP,
34018
+ // parent_infoP,
34019
+ // jobNoP,
34020
+ // keyP,
34021
+ // parent_nodeP,
34022
+ // attr,
34023
+ // $elm,
34024
+ // {
34025
+ // key: attr,
34026
+
34027
+ // value: await get_attr_value(attr),
34028
+ // },
34029
+ // is_init,
34030
+ // );
34031
+ // _ret = _.assignIn(_ret, ret);
34032
+ // }
34033
+ // }
34034
+
34035
+ // // ALL
34036
+
34037
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
34038
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
34039
+ // if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
34040
+ // continue;
34041
+ // }
34042
+
34043
+ // const new_key = key.split(':')[0]; // break expression
34044
+ // if (
34045
+ // nodeP.tagName !== 'xu-panel' &&
34046
+ // nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
34047
+ // (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
34048
+ // ) {
34049
+ // // handle common html attributes
34050
+ // try {
34051
+ // $elm.get(0).setAttribute(key, val);
34052
+ // } catch (err) {
34053
+ // console.error(err.message);
34054
+ // }
34055
+
34056
+ // continue;
34057
+ // }
34058
+ // // handle xu attributes
34059
+ // try {
34060
+ // if ($elm?.data()?.xuAttributes) {
34061
+ // // in some cases xu data delete in purpose when refreshing the screen
34062
+ // $elm.data().xuAttributes[key] = val;
34063
+ // }
34064
+ // } catch (error) {
34065
+ // debugger;
34066
+ // console.error(error);
34067
+ // }
34068
+
34069
+ // 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)) {
34070
+ // continue;
34071
+ // }
34072
+
34073
+ // if (new_key === 'xu-on') {
34074
+ // let ret = await func.UI.screen.execute_xu_functions(
34075
+ // SESSION_ID,
34076
+ // is_skeleton,
34077
+ // $root_container,
34078
+ // nodeP,
34079
+ // $container,
34080
+ // paramsP,
34081
+ // parent_infoP,
34082
+ // jobNoP,
34083
+ // keyP,
34084
+ // parent_nodeP,
34085
+ // 'xu-on',
34086
+ // $elm,
34087
+ // {
34088
+ // key: key,
34089
+ // // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
34090
+ // value: await get_attr_value(key),
34091
+ // },
34092
+ // is_init,
34093
+ // refreshed_ds,
34094
+ // );
34095
+ // _ret = _.assignIn(_ret, ret);
34096
+ // continue;
34097
+ // }
34098
+
34099
+ // let ret = await func.UI.screen.execute_xu_functions(
34100
+ // SESSION_ID,
34101
+ // is_skeleton,
34102
+ // $root_container,
34103
+ // nodeP,
34104
+ // $container,
34105
+ // paramsP,
34106
+ // parent_infoP,
34107
+ // jobNoP,
34108
+ // keyP,
34109
+ // parent_nodeP,
34110
+ // new_key,
34111
+ // $elm,
34112
+ // {
34113
+ // key: key,
34114
+ // // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
34115
+ // value: await get_attr_value(key),
34116
+ // },
34117
+ // is_init,
34118
+ // refreshed_ds,
34119
+ // );
34120
+
34121
+ // _ret = _.assignIn(_ret, ret);
34122
+ // }
34123
+
34124
+ // // EXP for
34125
+
34126
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
34127
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
34128
+
34129
+ // const attr = key.split('xu-exp:')[1];
34130
+
34131
+ // if (!attr) {
34132
+ // continue;
34133
+ // }
34134
+
34135
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
34136
+
34137
+ // if (done_exp.includes(key)) {
34138
+ // continue;
34139
+ // }
34140
+ // let ret = await func.UI.screen.execute_xu_functions(
34141
+ // SESSION_ID,
34142
+ // is_skeleton,
34143
+ // $root_container,
34144
+ // nodeP,
34145
+ // $container,
34146
+ // paramsP,
34147
+ // parent_infoP,
34148
+ // jobNoP,
34149
+ // keyP,
34150
+ // parent_nodeP,
34151
+ // 'xu-exp',
34152
+ // $elm,
34153
+ // {
34154
+ // key: attr,
34155
+ // value: val,
34156
+ // },
34157
+ // true,
34158
+ // refreshed_ds,
34159
+ // );
34160
+ // _ret = _.assignIn(_ret, ret);
34161
+ // }
34162
+
34163
+ // // AFTER
34164
+
34165
+ // for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
34166
+ // if ($container?.data()?.xuData?.pending_to_delete) break;
34167
+
34168
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
34169
+
34170
+ // if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
34171
+
34172
+ // let ret = await func.UI.screen.execute_xu_functions(
34173
+ // SESSION_ID,
34174
+ // is_skeleton,
34175
+ // $root_container,
34176
+ // nodeP,
34177
+ // $container,
34178
+ // paramsP,
34179
+ // parent_infoP,
34180
+ // jobNoP,
34181
+ // keyP,
34182
+ // parent_nodeP,
34183
+ // attr,
34184
+ // $elm,
34185
+ // {
34186
+ // key: attr,
34187
+ // // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
34188
+ // value: await get_attr_value(attr),
34189
+ // },
34190
+ // is_init,
34191
+ // refreshed_ds,
34192
+ // );
34193
+ // _ret = _.assignIn(_ret, ret);
34194
+ // }
34195
+
34196
+ // // REGISTER EVENTS ATTRIBUTES
34197
+
34198
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
34199
+ // if ($container?.data()?.xuData?.pending_to_delete) break;
34200
+ // if (!glb.html5_events_handler.includes(key)) break;
34201
+ // // $elm.attr(key, await get_xuExp(key)) || val;
34202
+ // $elm.attr(key, await get_xuExp(key)) || val;
34203
+ // }
34204
+
34205
+ // return _ret;
34206
+ // };
34207
+
33047
34208
  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) {
33048
- var done_exp = [];
34209
+ const done_exp = new Set(); // Use Set for O(1) lookups instead of array
33049
34210
 
33050
34211
  const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
33051
34212
  if (!_ds) return { abort: true };
33052
34213
 
34214
+ // Early return if not an element or no attributes
34215
+ if (nodeP.type !== 'element' || !nodeP.attributes) return {};
34216
+
34217
+ // Cache frequently accessed values
34218
+ const nodeAttrs = nodeP.attributes;
34219
+ const elmData = $elm.data();
34220
+ const xuData = elmData.xuData;
34221
+ const containerData = $container?.data();
34222
+ const containerXuData = containerData?.xuData;
34223
+
33053
34224
  const get_attr_value = async function (key) {
33054
- let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
33055
- if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
33056
- ret = await get_xuExp(key);
34225
+ const expKey = `xu-exp:${key}`;
34226
+ if (nodeAttrs.hasOwnProperty(expKey)) {
34227
+ return await get_xuExp(key);
33057
34228
  }
33058
- return ret;
34229
+ return func.UI.screen.fix_val_defaults(key, nodeAttrs[key]);
33059
34230
  };
33060
34231
 
33061
34232
  const get_xuExp = async function (attrib) {
33062
34233
  if (is_skeleton) return;
34234
+
34235
+ const attr = `xu-exp:${attrib}`;
34236
+ if (!nodeAttrs.hasOwnProperty(attr)) return;
34237
+
33063
34238
  if (glb.new_xu_render) {
33064
- let _xuData = $elm.data().xuData;
33065
- if (!_xuData.attr_exp_info) {
33066
- _xuData.attr_exp_info = {};
34239
+ if (!xuData.attr_exp_info) {
34240
+ xuData.attr_exp_info = {};
33067
34241
  }
33068
34242
  }
33069
- const attr = `xu-exp:${attrib}`;
33070
34243
 
33071
- if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
33072
- // const attr = `xu-exp-${attrib}`;
33073
- var exp = nodeP.attributes[attr];
33074
- // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
34244
+ const exp = nodeAttrs[attr];
34245
+ const res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
33075
34246
 
33076
- var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
33077
34247
  if (glb.new_xu_render) {
33078
- _xuData.attr_exp_info[attrib] = res;
34248
+ xuData.attr_exp_info[attrib] = res;
33079
34249
  }
33080
- // nodeP.attributes[attr] = value; //{ value: value, res: res };
33081
- done_exp.push(attr);
33082
- return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
33083
- };
33084
34250
 
33085
- var _ret = {};
33086
- if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
34251
+ done_exp.add(attr);
34252
+ return res.result;
34253
+ };
33087
34254
 
33088
- for (let [key, val] of Object.entries(nodeP.attributes)) {
33089
- // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
33090
- if (key.substring(0, 6) === 'xu-exp') {
34255
+ // Create Sets for O(1) lookups
34256
+ const html5EventsSet = new Set(glb.html5_events_handler);
34257
+ const executeAttrsSet = new Set(execute_attributes);
34258
+ const solidAttrsSet = new Set(glb.solid_attributes);
34259
+ const abbreviationsSet = new Set(glb.attr_abbreviations_arr);
34260
+ const runXuBeforeSet = new Set(Object.values(glb.run_xu_before));
34261
+ const runXuAfterSet = new Set(Object.values(glb.run_xu_after));
34262
+
34263
+ // Process attributes in a single pass where possible
34264
+ const attrsToDelete = [];
34265
+ const xuOnAttrs = {};
34266
+
34267
+ for (const [key, val] of Object.entries(nodeAttrs)) {
34268
+ // Handle xu-exp attributes
34269
+ if (key.startsWith('xu-exp:')) {
33091
34270
  if (_.isEmpty(val)) {
33092
- delete nodeP.attributes[key];
34271
+ attrsToDelete.push(key);
33093
34272
  continue;
33094
34273
  }
33095
- const clean_key = key.split(':')[1];
33096
- if (typeof nodeP.attributes[clean_key] !== 'undefined') {
33097
- delete nodeP.attributes[clean_key];
34274
+ const clean_key = key.slice(7); // 'xu-exp:'.length = 7
34275
+ if (nodeAttrs[clean_key] !== undefined) {
34276
+ attrsToDelete.push(clean_key);
33098
34277
  }
33099
34278
  }
33100
- // FIX abbreviations
33101
- if (glb.attr_abbreviations_arr.includes(key)) {
33102
- nodeP.attributes[`xu-on:${key.substring(3)}`] = [
34279
+ // Handle abbreviations
34280
+ else if (abbreviationsSet.has(key)) {
34281
+ xuOnAttrs[`xu-on:${key.slice(3)}`] = [
33103
34282
  {
33104
34283
  handler: 'custom',
33105
34284
  props: {},
@@ -33116,257 +34295,131 @@ func.UI.screen.set_attributes_new = async function (SESSION_ID, is_skeleton, $ro
33116
34295
  ],
33117
34296
  },
33118
34297
  ];
33119
- delete nodeP.attributes[key];
34298
+ attrsToDelete.push(key);
33120
34299
  }
33121
34300
  }
33122
34301
 
33123
- for (let [key, val] of Object.entries(nodeP.attributes)) {
33124
- // FIX STATIC DEFAULTS
33125
- val = func.UI.screen.fix_val_defaults(key, val);
34302
+ // Delete marked attributes
34303
+ for (const key of attrsToDelete) {
34304
+ delete nodeAttrs[key];
34305
+ }
33126
34306
 
33127
- // REMOVE UNDEFINED or NULL ATTRIBUTES
33128
- if (typeof val === 'undefined' || val === null) {
33129
- delete nodeP.attributes[key];
33130
- }
34307
+ // Add xu-on attributes
34308
+ Object.assign(nodeAttrs, xuOnAttrs);
33131
34309
 
33132
- // REMOVE ATTRIBUTES WITH EMPTY VALUES
33133
- if (glb.solid_attributes.includes(key) && !val) {
33134
- delete nodeP.attributes[key];
34310
+ // Clean up attributes
34311
+ for (const [key, val] of Object.entries(nodeAttrs)) {
34312
+ const fixedVal = func.UI.screen.fix_val_defaults(key, val);
34313
+
34314
+ if (fixedVal === undefined || fixedVal === null) {
34315
+ delete nodeAttrs[key];
34316
+ } else if (solidAttrsSet.has(key) && !fixedVal) {
34317
+ delete nodeAttrs[key];
34318
+ } else {
34319
+ nodeAttrs[key] = fixedVal;
33135
34320
  }
33136
34321
  }
33137
34322
 
34323
+ const _ret = {};
34324
+
34325
+ // Helper to check abort condition
34326
+ const shouldAbort = () => _ret.abort || containerXuData?.pending_to_delete;
34327
+
33138
34328
  // XU-ATTRS
33139
- if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
34329
+ if (nodeAttrs['xu-attrs'] || nodeAttrs['xu-exp:xu-attrs']) {
33140
34330
  const attr = 'xu-attrs';
33141
- let ret = await func.UI.screen.execute_xu_functions(
33142
- SESSION_ID,
33143
- is_skeleton,
33144
- $root_container,
33145
- nodeP,
33146
- $container,
33147
- paramsP,
33148
- parent_infoP,
33149
- jobNoP,
33150
- keyP,
33151
- parent_nodeP,
33152
- attr,
33153
- $elm,
33154
- {
33155
- key: attr,
33156
- value: await get_attr_value(attr),
33157
- },
33158
- is_init,
33159
- );
34331
+ 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);
33160
34332
  }
33161
34333
 
33162
34334
  // BEFORE
33163
- if (!_.isEmpty(nodeP.attributes)) {
33164
- for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
33165
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33166
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
33167
- continue;
33168
- }
33169
-
33170
- if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
33171
- continue;
33172
- }
34335
+ if (!_.isEmpty(nodeAttrs)) {
34336
+ for (const [key, attr] of Object.entries(glb.run_xu_before)) {
34337
+ if (shouldAbort()) break;
34338
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
33173
34339
 
33174
- if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
33175
- continue;
33176
- }
33177
-
33178
- let ret = await func.UI.screen.execute_xu_functions(
33179
- SESSION_ID,
33180
- is_skeleton,
33181
- $root_container,
33182
- nodeP,
33183
- $container,
33184
- paramsP,
33185
- parent_infoP,
33186
- jobNoP,
33187
- keyP,
33188
- parent_nodeP,
33189
- attr,
33190
- $elm,
33191
- {
33192
- key: attr,
34340
+ const expKey = `xu-exp:${attr}`;
34341
+ if (!nodeAttrs.hasOwnProperty(attr) && !nodeAttrs.hasOwnProperty(expKey)) continue;
34342
+ if (!nodeAttrs[expKey] && nodeAttrs.hasOwnProperty(attr) && func.UI.screen.fix_val_defaults(attr, nodeAttrs[attr]) === undefined) continue;
33193
34343
 
33194
- value: await get_attr_value(attr),
33195
- },
33196
- is_init,
33197
- );
33198
- _ret = _.assignIn(_ret, ret);
34344
+ 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);
34345
+ Object.assign(_ret, ret);
33199
34346
  }
33200
34347
  }
33201
34348
 
33202
- // ALL
34349
+ // ALL - Process attributes
34350
+ const isXuPanel = nodeP.tagName === 'xu-panel';
34351
+ const isXuTeleport = nodeP.tagName === 'xu-teleport';
34352
+ const elmElement = $elm.get(0);
33203
34353
 
33204
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
33205
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33206
- if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
33207
- continue;
33208
- }
34354
+ for (const [key, val] of Object.entries(nodeAttrs)) {
34355
+ if (shouldAbort()) break;
34356
+ if (html5EventsSet.has(key) || executeAttrsSet.has(key)) continue;
33209
34357
 
33210
- const new_key = key.split(':')[0]; // break expression
33211
- if (
33212
- nodeP.tagName !== 'xu-panel' &&
33213
- nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
33214
- (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
33215
- ) {
33216
- // handle common html attributes
34358
+ const colonIndex = key.indexOf(':');
34359
+ const new_key = colonIndex > -1 ? key.slice(0, colonIndex) : key;
34360
+
34361
+ if (!isXuPanel && !isXuTeleport && (!new_key.startsWith('xu-') || new_key.length < 3 || new_key[2] !== '-')) {
33217
34362
  try {
33218
- $elm.get(0).setAttribute(key, val);
34363
+ elmElement.setAttribute(key, val);
33219
34364
  } catch (err) {
33220
34365
  console.error(err.message);
33221
34366
  }
33222
-
33223
34367
  continue;
33224
34368
  }
33225
- // handle xu attributes
33226
- try {
33227
- if ($elm?.data()?.xuAttributes) {
33228
- // in some cases xu data delete in purpose when refreshing the screen
33229
- $elm.data().xuAttributes[key] = val;
33230
- }
33231
- } catch (error) {
33232
- debugger;
33233
- console.error(error);
34369
+
34370
+ // Store xu attributes
34371
+ if (elmData.xuAttributes) {
34372
+ elmData.xuAttributes[key] = val;
33234
34373
  }
33235
34374
 
33236
- 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)) {
34375
+ const expKey = `xu-exp:${new_key}`;
34376
+ if (new_key === 'xu-exp' || nodeAttrs[expKey] || runXuBeforeSet.has(new_key) || runXuAfterSet.has(new_key)) {
33237
34377
  continue;
33238
34378
  }
33239
34379
 
33240
34380
  if (new_key === 'xu-on') {
33241
- let ret = await func.UI.screen.execute_xu_functions(
33242
- SESSION_ID,
33243
- is_skeleton,
33244
- $root_container,
33245
- nodeP,
33246
- $container,
33247
- paramsP,
33248
- parent_infoP,
33249
- jobNoP,
33250
- keyP,
33251
- parent_nodeP,
33252
- 'xu-on',
33253
- $elm,
33254
- {
33255
- key: key,
33256
- // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
33257
- value: await get_attr_value(key),
33258
- },
33259
- is_init,
33260
- refreshed_ds,
33261
- );
33262
- _ret = _.assignIn(_ret, ret);
34381
+ 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);
34382
+ Object.assign(_ret, ret);
33263
34383
  continue;
33264
34384
  }
33265
34385
 
33266
- let ret = await func.UI.screen.execute_xu_functions(
33267
- SESSION_ID,
33268
- is_skeleton,
33269
- $root_container,
33270
- nodeP,
33271
- $container,
33272
- paramsP,
33273
- parent_infoP,
33274
- jobNoP,
33275
- keyP,
33276
- parent_nodeP,
33277
- new_key,
33278
- $elm,
33279
- {
33280
- key: key,
33281
- // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
33282
- value: await get_attr_value(key),
33283
- },
33284
- is_init,
33285
- refreshed_ds,
33286
- );
33287
-
33288
- _ret = _.assignIn(_ret, ret);
34386
+ 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);
34387
+ Object.assign(_ret, ret);
33289
34388
  }
33290
34389
 
33291
- // EXP for
33292
-
33293
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
33294
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33295
-
33296
- const attr = key.split('xu-exp:')[1];
34390
+ // EXP - Process expressions
34391
+ for (const [key, val] of Object.entries(nodeAttrs)) {
34392
+ if (shouldAbort()) break;
33297
34393
 
33298
- if (!attr) {
33299
- continue;
33300
- }
34394
+ if (!key.startsWith('xu-exp:')) continue;
34395
+ const attr = key.slice(7);
33301
34396
 
33302
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
34397
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
34398
+ if (done_exp.has(key)) continue;
33303
34399
 
33304
- if (done_exp.includes(key)) {
33305
- continue;
33306
- }
33307
- let ret = await func.UI.screen.execute_xu_functions(
33308
- SESSION_ID,
33309
- is_skeleton,
33310
- $root_container,
33311
- nodeP,
33312
- $container,
33313
- paramsP,
33314
- parent_infoP,
33315
- jobNoP,
33316
- keyP,
33317
- parent_nodeP,
33318
- 'xu-exp',
33319
- $elm,
33320
- {
33321
- key: attr,
33322
- value: val,
33323
- },
33324
- true,
33325
- refreshed_ds,
33326
- );
33327
- _ret = _.assignIn(_ret, ret);
34400
+ 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);
34401
+ Object.assign(_ret, ret);
33328
34402
  }
33329
34403
 
33330
34404
  // AFTER
34405
+ for (const [key, attr] of Object.entries(glb.run_xu_after)) {
34406
+ if (containerXuData?.pending_to_delete) break;
34407
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
33331
34408
 
33332
- for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
33333
- if ($container?.data()?.xuData?.pending_to_delete) break;
33334
-
33335
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
34409
+ const expKey = `xu-exp:${attr}`;
34410
+ if (!nodeAttrs || (!nodeAttrs[attr] && !nodeAttrs[expKey])) continue;
33336
34411
 
33337
- if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
33338
-
33339
- let ret = await func.UI.screen.execute_xu_functions(
33340
- SESSION_ID,
33341
- is_skeleton,
33342
- $root_container,
33343
- nodeP,
33344
- $container,
33345
- paramsP,
33346
- parent_infoP,
33347
- jobNoP,
33348
- keyP,
33349
- parent_nodeP,
33350
- attr,
33351
- $elm,
33352
- {
33353
- key: attr,
33354
- // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
33355
- value: await get_attr_value(attr),
33356
- },
33357
- is_init,
33358
- refreshed_ds,
33359
- );
33360
- _ret = _.assignIn(_ret, ret);
34412
+ 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);
34413
+ Object.assign(_ret, ret);
33361
34414
  }
33362
34415
 
33363
34416
  // REGISTER EVENTS ATTRIBUTES
34417
+ for (const [key, val] of Object.entries(nodeAttrs)) {
34418
+ if (containerXuData?.pending_to_delete) break;
34419
+ if (!html5EventsSet.has(key)) break;
33364
34420
 
33365
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
33366
- if ($container?.data()?.xuData?.pending_to_delete) break;
33367
- if (!glb.html5_events_handler.includes(key)) break;
33368
- // $elm.attr(key, await get_xuExp(key)) || val;
33369
- $elm.attr(key, await get_xuExp(key)) || val;
34421
+ const expVal = await get_xuExp(key);
34422
+ $elm.attr(key, expVal || val);
33370
34423
  }
33371
34424
 
33372
34425
  return _ret;