@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.
@@ -2676,11 +2676,6 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
2676
2676
  };
2677
2677
 
2678
2678
  func.common.sha256 = async function (inputString) {
2679
- // const enc = new TextEncoder();
2680
- // const buf = await crypto.subtle.digest('SHA-256', enc.encode(str));
2681
- // const bytes = new Uint8Array(buf);
2682
- // return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');
2683
-
2684
2679
  // 1. Create a hash buffer from the input string using SHA-256.
2685
2680
  // This part remains the same as it provides a strong, unique cryptographic starting point.
2686
2681
  const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputString));
@@ -9894,469 +9889,1357 @@ const get_params_obj_new = async function (SESSION_ID, prog_id, nodeP, dsSession
9894
9889
  return { params_res, params_raw };
9895
9890
  };
9896
9891
 
9897
- 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) {
9898
- if (is_skeleton) return;
9892
+ // 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) {
9893
+ // if (is_skeleton) return;
9894
+
9895
+ // // console.log(nodeP.id, xu_func, val);
9896
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
9897
+ // const tag_fx = {
9898
+ // [`xu-panel`]: {
9899
+ // program: async function ($elm, val) {
9900
+ // var ret = {};
9901
+ // var _session = SESSION_OBJ[SESSION_ID];
9902
+ // var _ds = _session.DS_GLB[paramsP.dsSessionP];
9903
+ // const init_program = async function () {
9904
+ // async function render_panel() {
9905
+ // const prog_id = val.value?.prog || val.value;
9906
+ // const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
9907
+ // 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);
9908
+ // ret = { $new_div: ret_panel };
9909
+ // if ($container.data().xuData) {
9910
+ // $container.data().xuData.xuPanelProps = $elm.data().xuAttributes;
9911
+ // $container.data().xuData.xuPanelData = ret_panel.data();
9912
+ // }
9913
+ // return ret;
9914
+ // }
9899
9915
 
9900
- // console.log(nodeP.id, xu_func, val);
9901
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
9902
- const tag_fx = {
9903
- [`xu-panel`]: {
9904
- program: async function ($elm, val) {
9905
- var ret = {};
9906
- var _session = SESSION_OBJ[SESSION_ID];
9907
- var _ds = _session.DS_GLB[paramsP.dsSessionP];
9908
- const init_program = async function () {
9909
- async function render_panel() {
9910
- const prog_id = val.value?.prog || val.value;
9911
- const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
9912
- 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);
9913
- ret = { $new_div: ret_panel };
9914
- if ($container.data().xuData) {
9915
- $container.data().xuData.xuPanelProps = $elm.data().xuAttributes;
9916
- $container.data().xuData.xuPanelData = ret_panel.data();
9917
- }
9918
- return ret;
9919
- }
9916
+ // if (!val.value) {
9917
+ // val.value = '_empty_panel_program';
9918
+ // }
9920
9919
 
9921
- if (!val.value) {
9922
- val.value = '_empty_panel_program';
9923
- }
9920
+ // ret = await render_panel();
9924
9921
 
9925
- ret = await render_panel();
9922
+ // return ret;
9923
+ // };
9924
+ // const alter_program = async function () {
9925
+ // var _session = SESSION_OBJ[SESSION_ID];
9926
+ // var _ds = _session.DS_GLB[paramsP.dsSessionP];
9927
+
9928
+ // /////////////////
9929
+ // async function render_panel() {
9930
+ // // // if (!cache_str) {
9931
+ // // // await update_container(screen_ready_function);
9932
+ // // // }
9933
+ // // // if (cache_str && !CACHE_PROG_UI[cache_str]) {
9934
+ // // // await update_container(screen_ready_function);
9935
+ // // // save_cache();
9936
+ // // // }
9937
+ // // // if (callback) callback($div);
9938
+ // // // $container.data().xuData.node.children =
9939
+ // // // $div.data().xuData.node.children;
9940
+ // // // //swiper-wrapper
9941
+ // // // var restore_slides_elements = async function () {
9942
+ // // // if ($tmp_div.children().length) {
9943
+ // // // $tmp_div
9944
+ // // // .find(".swiper-wrapper")
9945
+ // // // .empty()
9946
+ // // // .append($new_div.children());
9947
+ // // // $new_div.append($tmp_div.children());
9948
+ // // // }
9949
+ // // // };
9950
+ // // // // console.log($tmp_div);
9951
+ // // // await restore_slides_elements();
9952
+ // // // // CHANGE_PANEL_BUSY = false;
9953
+ // // // func.events.delete_job(SESSION_ID, jobNo);
9954
+ // // };
9955
+ // const program = val.value?.prog || val.value;
9956
+ // var $wrapper = $('<div>');
9957
+ // 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, '');
9958
+ // const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
9959
+ // 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);
9960
+ // ret = {
9961
+ // $new_div: ret_init,
9962
+ // abort: true,
9963
+ // };
9964
+ // await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, $new_div, nodeP, $div.clone(true), jobNoP);
9965
+
9966
+ // return ret;
9967
+ // }
9968
+ // if (!val.value) {
9969
+ // return { abort: true };
9970
+ // }
9971
+ // await render_panel();
9972
+ // return ret;
9973
+ // };
9926
9974
 
9927
- return ret;
9928
- };
9929
- const alter_program = async function () {
9930
- var _session = SESSION_OBJ[SESSION_ID];
9931
- var _ds = _session.DS_GLB[paramsP.dsSessionP];
9975
+ // if (is_init) {
9976
+ // let ret = await init_program();
9977
+ // return ret;
9978
+ // }
9979
+ // return alter_program();
9980
+ // },
9932
9981
 
9933
- /////////////////
9934
- async function render_panel() {
9935
- // // if (!cache_str) {
9936
- // // await update_container(screen_ready_function);
9937
- // // }
9938
- // // if (cache_str && !CACHE_PROG_UI[cache_str]) {
9939
- // // await update_container(screen_ready_function);
9940
- // // save_cache();
9941
- // // }
9942
- // // if (callback) callback($div);
9943
- // // $container.data().xuData.node.children =
9944
- // // $div.data().xuData.node.children;
9945
- // // //swiper-wrapper
9946
- // // var restore_slides_elements = async function () {
9947
- // // if ($tmp_div.children().length) {
9948
- // // $tmp_div
9949
- // // .find(".swiper-wrapper")
9950
- // // .empty()
9951
- // // .append($new_div.children());
9952
- // // $new_div.append($tmp_div.children());
9953
- // // }
9954
- // // };
9955
- // // // console.log($tmp_div);
9956
- // // await restore_slides_elements();
9957
- // // // CHANGE_PANEL_BUSY = false;
9958
- // // func.events.delete_job(SESSION_ID, jobNo);
9959
- // };
9960
- const program = val.value?.prog || val.value;
9961
- var $wrapper = $('<div>');
9962
- 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, '');
9963
- const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
9964
- 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);
9965
- ret = {
9966
- $new_div: ret_init,
9967
- abort: true,
9968
- };
9969
- await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, $new_div, nodeP, $div.clone(true), jobNoP);
9982
+ // 'xu-render': async function ($elm, val) {
9983
+ // let ret = await common_fx['xu-render']($elm, val, true);
9984
+ // return ret;
9985
+ // },
9986
+ // 'xu-ref': async function ($elm, val) {
9987
+ // let ret = await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
9988
+ // return ret;
9989
+ // },
9990
+ // },
9991
+ // [`xu-teleport`]: {
9992
+ // to: async function ($elm, val) {
9993
+ // if (!glb.new_xu_render) {
9994
+ // if (val.value) {
9995
+ // // parent_infoP.is_xu_teleport;
9996
+ // if ($elm?.parent()?.data()?.xuData?.length) {
9997
+ // $elm.parent().data('xuTeleportData', []);
9998
+ // for (const [key, node] of Object.entries(nodeP.children)) {
9999
+ // 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);
10000
+
10001
+ // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10002
+ // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
10003
+ // }
10004
+ // $elm.remove();
10005
+ // } else {
10006
+ // $elm.data('xuTeleportData', []).attr('hidden', true);
10007
+ // for (const [key, node] of Object.entries(nodeP.children)) {
10008
+ // const $to_container = $(val.value);
10009
+ // if (!$to_container?.length) {
10010
+ // return console.error(`container ${val.value} for xuTeleportData not found`);
10011
+ // }
10012
+ // 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);
10013
+
10014
+ // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10015
+ // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
10016
+ // }
10017
+ // }
10018
+ // }
10019
+ // return { abort: true };
10020
+ // }
9970
10021
 
9971
- return ret;
9972
- }
9973
- if (!val.value) {
9974
- return { abort: true };
9975
- }
9976
- await render_panel();
9977
- return ret;
9978
- };
10022
+ // if (val.value) {
10023
+ // // // parent_infoP.is_xu_teleport;
10024
+ // // if ($elm?.parent()?.data()?.xuData?.length) {
10025
+ // // $elm.parent().data('xuTeleportData', []);
10026
+ // // for (const [key, node] of Object.entries(nodeP.children)) {
10027
+ // // 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);
10028
+ // // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10029
+ // // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
10030
+ // // }
10031
+ // // $elm.remove();
10032
+ // // } else {
10033
+ // // $elm.data('xuTeleportData', []).attr('hidden', true);
10034
+ // // for (const [key, node] of Object.entries(nodeP.children)) {
10035
+ // // const $to_container = $(val.value);
10036
+ // // if (!$to_container?.length) {
10037
+ // // return console.error(`container ${val.value} for xuTeleportData not found`);
10038
+ // // }
10039
+ // // 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);
10040
+ // // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10041
+ // // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
10042
+ // // }
10043
+ // // }
10044
+ // }
10045
+ // return {};
10046
+ // },
10047
+ // 'xu-render': async function ($elm, val) {
10048
+ // let ret = await common_fx['xu-render']($elm, val, true);
10049
+ // return ret;
10050
+ // },
10051
+ // 'xu-show': async function ($elm, val) {
10052
+ // let ret = await common_fx['xu-show']($elm, val, true);
10053
+ // return ret;
10054
+ // },
10055
+ // },
10056
+ // };
9979
10057
 
9980
- if (is_init) {
9981
- let ret = await init_program();
9982
- return ret;
9983
- }
9984
- return alter_program();
9985
- },
10058
+ // const load_cdn = async function (resource) {
10059
+ // // console.log("loading cdn", resource);
10060
+ // if (!_.isObject(resource) && _.isString(resource)) {
10061
+ // resource = { src: resource, type: 'js' };
10062
+ // }
10063
+ // if (!_.isObject(resource)) {
10064
+ // throw new Error('cdn resource in wrong format');
10065
+ // }
10066
+ // return new Promise(async (resolve) => {
10067
+ // try {
10068
+ // switch (resource.type) {
10069
+ // case 'js':
10070
+ // await func.utils.load_js_on_demand(resource.src);
10071
+ // break;
10072
+ // case 'css':
10073
+ // await func.utils.load_js_on_demand(resource.src);
10074
+ // break;
10075
+ // case 'module':
10076
+ // func.utils.load_js_on_demand(resource.src, 'module');
10077
+ // break;
10078
+
10079
+ // default:
10080
+ // await func.utils.load_js_on_demand(resource.src);
10081
+ // break;
10082
+ // }
10083
+ // resolve();
10084
+ // } catch (error) {
10085
+ // func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource, 'W');
10086
+ // resolve();
10087
+ // }
9986
10088
 
9987
- 'xu-render': async function ($elm, val) {
9988
- let ret = await common_fx['xu-render']($elm, val, true);
9989
- return ret;
9990
- },
9991
- 'xu-ref': async function ($elm, val) {
9992
- let ret = await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
9993
- return ret;
9994
- },
9995
- },
9996
- [`xu-teleport`]: {
9997
- to: async function ($elm, val) {
9998
- if (!glb.new_xu_render) {
9999
- if (val.value) {
10000
- // parent_infoP.is_xu_teleport;
10001
- if ($elm?.parent()?.data()?.xuData?.length) {
10002
- $elm.parent().data('xuTeleportData', []);
10003
- for (const [key, node] of Object.entries(nodeP.children)) {
10004
- 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);
10005
-
10006
- $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10007
- $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
10008
- }
10009
- $elm.remove();
10010
- } else {
10011
- $elm.data('xuTeleportData', []).attr('hidden', true);
10012
- for (const [key, node] of Object.entries(nodeP.children)) {
10013
- const $to_container = $(val.value);
10014
- if (!$to_container?.length) {
10015
- return console.error(`container ${val.value} for xuTeleportData not found`);
10016
- }
10017
- 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);
10089
+ // // if (resource.type === "js" || !resource.type) {
10090
+ // // await func.utils.load_js_on_demand(resource.src);
10091
+ // // return resolve();
10092
+ // // }
10093
+ // // if (resource.type === "css") {
10094
+ // // func.utils.load_css_on_demand(resource.src);
10095
+ // // return resolve();
10096
+ // // }
10097
+ // // if (resource.type === "module") {
10098
+ // // func.utils.load_js_on_demand(resource.src, "module");
10099
+ // // return resolve();
10100
+ // // }
10101
+ // // func.utils.debug_report(
10102
+ // // SESSION_ID,
10103
+ // // "xu-cdn",
10104
+ // // "Fail to load: " + resource,
10105
+ // // "W"
10106
+ // // );
10107
+ // // return resolve();
10108
+ // });
10109
+ // };
10018
10110
 
10019
- $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10020
- $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
10021
- }
10022
- }
10023
- }
10024
- return { abort: true };
10025
- }
10111
+ // const common_fx = {
10112
+ // 'xu-attrs': async function ($elm, val) {
10113
+ // if (!val.value) return {};
10114
+ // if (!_.isObject(val.value)) throw 'xu-attrs value us not an object';
10115
+ // for (const [attr_key, attr_val] of Object.entries(val.value)) {
10116
+ // nodeP.attributes[attr_key] = attr_val;
10117
+ // }
10026
10118
 
10027
- if (val.value) {
10028
- // // parent_infoP.is_xu_teleport;
10029
- // if ($elm?.parent()?.data()?.xuData?.length) {
10030
- // $elm.parent().data('xuTeleportData', []);
10031
- // for (const [key, node] of Object.entries(nodeP.children)) {
10032
- // 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);
10033
- // $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10034
- // $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
10035
- // }
10036
- // $elm.remove();
10037
- // } else {
10038
- // $elm.data('xuTeleportData', []).attr('hidden', true);
10039
- // for (const [key, node] of Object.entries(nodeP.children)) {
10040
- // const $to_container = $(val.value);
10041
- // if (!$to_container?.length) {
10042
- // return console.error(`container ${val.value} for xuTeleportData not found`);
10043
- // }
10044
- // 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);
10045
- // $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
10046
- // $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
10047
- // }
10048
- // }
10049
- }
10050
- return {};
10051
- },
10052
- 'xu-render': async function ($elm, val) {
10053
- let ret = await common_fx['xu-render']($elm, val, true);
10054
- return ret;
10055
- },
10056
- 'xu-show': async function ($elm, val) {
10057
- let ret = await common_fx['xu-show']($elm, val, true);
10058
- return ret;
10059
- },
10060
- },
10061
- };
10119
+ // return {};
10120
+ // },
10121
+ // 'xu-ref': async function ($elm, val, dsSession) {
10122
+ // if (!val.value) return {};
10062
10123
 
10063
- const load_cdn = async function (resource) {
10064
- // console.log("loading cdn", resource);
10065
- if (!_.isObject(resource) && _.isString(resource)) {
10066
- resource = { src: resource, type: 'js' };
10067
- }
10068
- if (!_.isObject(resource)) {
10069
- throw new Error('cdn resource in wrong format');
10070
- }
10071
- return new Promise(async (resolve) => {
10072
- try {
10073
- switch (resource.type) {
10074
- case 'js':
10075
- await func.utils.load_js_on_demand(resource.src);
10076
- break;
10077
- case 'css':
10078
- await func.utils.load_js_on_demand(resource.src);
10079
- break;
10080
- case 'module':
10081
- func.utils.load_js_on_demand(resource.src, 'module');
10082
- break;
10124
+ // func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
10083
10125
 
10084
- default:
10085
- await func.utils.load_js_on_demand(resource.src);
10086
- break;
10087
- }
10088
- resolve();
10089
- } catch (error) {
10090
- func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource, 'W');
10091
- resolve();
10092
- }
10126
+ // // Select the node that will be observed for mutations
10127
+ // const targetNode = $elm[0];
10093
10128
 
10094
- // if (resource.type === "js" || !resource.type) {
10095
- // await func.utils.load_js_on_demand(resource.src);
10096
- // return resolve();
10097
- // }
10098
- // if (resource.type === "css") {
10099
- // func.utils.load_css_on_demand(resource.src);
10100
- // return resolve();
10101
- // }
10102
- // if (resource.type === "module") {
10103
- // func.utils.load_js_on_demand(resource.src, "module");
10104
- // return resolve();
10105
- // }
10106
- // func.utils.debug_report(
10107
- // SESSION_ID,
10108
- // "xu-cdn",
10109
- // "Fail to load: " + resource,
10110
- // "W"
10111
- // );
10112
- // return resolve();
10113
- });
10114
- };
10129
+ // if (!targetNode) return;
10115
10130
 
10116
- const common_fx = {
10117
- 'xu-attrs': async function ($elm, val) {
10118
- if (!val.value) return {};
10119
- if (!_.isObject(val.value)) throw 'xu-attrs value us not an object';
10120
- for (const [attr_key, attr_val] of Object.entries(val.value)) {
10121
- nodeP.attributes[attr_key] = attr_val;
10122
- }
10131
+ // // Options for the observer (which mutations to observe)
10132
+ // const config = { attributes: true, childList: true, subtree: true };
10123
10133
 
10124
- return {};
10125
- },
10126
- 'xu-ref': async function ($elm, val, dsSession) {
10127
- if (!val.value) return {};
10134
+ // // Callback function to execute when mutations are observed
10135
+ // const callback = (mutationList, observer) => {
10136
+ // func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
10137
+ // };
10128
10138
 
10129
- func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
10139
+ // // Create an observer instance linked to the callback function
10140
+ // const observer = new MutationObserver(callback);
10141
+
10142
+ // // Start observing the target node for configured mutations
10143
+ // observer.observe(targetNode, config);
10144
+
10145
+ // // Later, you can stop observing
10146
+ // // observer.disconnect();
10147
+
10148
+ // return {};
10149
+ // },
10150
+ // 'xu-bind': async function ($elm, val) {
10151
+ // if (is_skeleton) return;
10152
+
10153
+ // let val_is_reference_field = false;
10154
+
10155
+ // let _prog_id = $elm.data().xuData.paramsP.prog_id;
10156
+ // let _dsP = $elm.data().xuData.paramsP.dsSessionP;
10157
+ // const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
10158
+ // if (!view_ret) return {};
10159
+
10160
+ // let is_dynamic_field = false;
10161
+ // let field_prop;
10162
+ // let bind_field_id;
10163
+
10164
+ // const input_field_type = $elm.attr('type');
10165
+
10166
+ // const get_bind_field = async function (field_id) {
10167
+ // if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
10168
+ // is_dynamic_field = true;
10169
+ // field_prop = _ds.dynamic_fields[field_id];
10170
+ // } else {
10171
+ // field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
10172
+ // if (!field_prop) {
10173
+ // /// find the field everywhere in the chain Aug 30 2024
10174
+ // const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
10175
+
10176
+ // if (ret_get_value.found) {
10177
+ // _dsP = ret_get_value.dsSessionP;
10178
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
10179
+ // _prog_id = _ds.prog_id;
10180
+ // const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
10181
+ // if (!view_ret) return {};
10182
+ // field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
10183
+ // }
10184
+ // if (!field_prop) {
10185
+ // throw `field ${field_id} not found in the program scope`;
10186
+ // }
10187
+ // }
10188
+ // }
10189
+ // return field_id;
10190
+ // };
10130
10191
 
10131
- // Select the node that will be observed for mutations
10132
- const targetNode = $elm[0];
10192
+ // try {
10193
+ // bind_field_id = await get_bind_field(val.value.split('.')[0]);
10194
+ // val_is_reference_field = true;
10195
+ // } catch (err) {
10196
+ // console.error(err?.message || err);
10197
+ // return {};
10198
+ // }
10133
10199
 
10134
- if (!targetNode) return;
10200
+ // const field_changed = async function (e) {
10201
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
10135
10202
 
10136
- // Options for the observer (which mutations to observe)
10137
- const config = { attributes: true, childList: true, subtree: true };
10203
+ // // update array for checkbox that not in xu-for
10204
+ // if (field_prop.props.fieldType === 'array' && input_field_type === 'checkbox' && val_is_reference_field) {
10205
+ // let arr_value_before_cast = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, _ds.currentRecordId)).ret.value);
10206
+ // let value_from_getter = bind.getter($elm[0]);
10207
+ // let value;
10208
+ // if (arr_value_before_cast.includes(value_from_getter)) {
10209
+ // value = arr_value_before_cast.filter((item) => !_.isEqual(item, value_from_getter));
10210
+ // } else {
10211
+ // arr_value_before_cast.push(value_from_getter);
10212
+ // value = arr_value_before_cast;
10213
+ // }
10138
10214
 
10139
- // Callback function to execute when mutations are observed
10140
- const callback = (mutationList, observer) => {
10141
- func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
10142
- };
10215
+ // let datasource_changes = {
10216
+ // [_dsP]: {
10217
+ // [_ds.currentRecordId]: {
10218
+ // [bind_field_id]: value,
10219
+ // },
10220
+ // },
10221
+ // };
10143
10222
 
10144
- // Create an observer instance linked to the callback function
10145
- const observer = new MutationObserver(callback);
10223
+ // return await func.datasource.update(SESSION_ID, datasource_changes);
10224
+ // }
10146
10225
 
10147
- // Start observing the target node for configured mutations
10148
- observer.observe(targetNode, config);
10226
+ // // update array for radio that not in xu-for
10227
+ // if (field_prop.props.fieldType === 'array' && input_field_type === 'radio' && val_is_reference_field) {
10228
+ // let value_from_getter = bind.getter($elm[0]);
10149
10229
 
10150
- // Later, you can stop observing
10151
- // observer.disconnect();
10230
+ // let datasource_changes = {
10231
+ // [_dsP]: {
10232
+ // [_ds.currentRecordId]: {
10233
+ // [bind_field_id]: [value_from_getter],
10234
+ // },
10235
+ // },
10236
+ // };
10152
10237
 
10153
- return {};
10154
- },
10155
- 'xu-bind': async function ($elm, val) {
10156
- if (is_skeleton) return;
10238
+ // return await func.datasource.update(SESSION_ID, datasource_changes);
10239
+ // }
10157
10240
 
10158
- let val_is_reference_field = false;
10241
+ // var value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', field_prop.props.fieldType, bind.getter($elm[0]));
10159
10242
 
10160
- let _prog_id = $elm.data().xuData.paramsP.prog_id;
10161
- let _dsP = $elm.data().xuData.paramsP.dsSessionP;
10162
- const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
10163
- if (!view_ret) return {};
10243
+ // if (field_prop.props.fieldType === 'object') {
10244
+ // value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
10245
+ // }
10164
10246
 
10165
- let is_dynamic_field = false;
10166
- let field_prop;
10167
- let bind_field_id;
10247
+ // if (!_ds.currentRecordId) return;
10168
10248
 
10169
- const input_field_type = $elm.attr('type');
10249
+ // let datasource_changes = {
10250
+ // [_dsP]: {
10251
+ // [_ds.currentRecordId]: {
10252
+ // [bind_field_id]: value,
10253
+ // },
10254
+ // },
10255
+ // };
10170
10256
 
10171
- const get_bind_field = async function (field_id) {
10172
- if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
10173
- is_dynamic_field = true;
10174
- field_prop = _ds.dynamic_fields[field_id];
10175
- } else {
10176
- field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
10177
- if (!field_prop) {
10178
- /// find the field everywhere in the chain Aug 30 2024
10179
- const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
10257
+ // await func.datasource.update(SESSION_ID, datasource_changes);
10258
+ // const iterate_info = $elm?.data()?.xuData?.iterate_info;
10259
+ // const reference_source_obj = iterate_info?.reference_source_obj;
10260
+ // if (reference_source_obj) {
10261
+ // if (reference_source_obj.ret.type === 'array') {
10262
+ // if (iterate_info.iterator_val === bind_field_id) {
10263
+ // const arr_idx = Number($elm?.data()?.xuData?.iterate_info._key);
10180
10264
 
10181
- if (ret_get_value.found) {
10182
- _dsP = ret_get_value.dsSessionP;
10183
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
10184
- _prog_id = _ds.prog_id;
10185
- const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
10186
- if (!view_ret) return {};
10187
- field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
10188
- }
10189
- if (!field_prop) {
10190
- throw `field ${field_id} not found in the program scope`;
10191
- }
10192
- }
10193
- }
10194
- return field_id;
10195
- };
10265
+ // const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
10266
+ // let new_arr = _.cloneDeep(dataset_arr.ret.value);
10196
10267
 
10197
- try {
10198
- bind_field_id = await get_bind_field(val.value.split('.')[0]);
10199
- val_is_reference_field = true;
10200
- } catch (err) {
10201
- console.error(err?.message || err);
10202
- return {};
10203
- }
10268
+ // if (field_prop.props.fieldType === 'object' && val_is_reference_field) {
10269
+ // let obj_item = new_arr[arr_idx];
10204
10270
 
10205
- const field_changed = async function (e) {
10206
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_dsP];
10271
+ // let e_exp = val.value.replace(bind_field_id, 'obj_item');
10207
10272
 
10208
- // update array for checkbox that not in xu-for
10209
- if (field_prop.props.fieldType === 'array' && input_field_type === 'checkbox' && val_is_reference_field) {
10210
- let arr_value_before_cast = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, _ds.currentRecordId)).ret.value);
10211
- let value_from_getter = bind.getter($elm[0]);
10212
- let value;
10213
- if (arr_value_before_cast.includes(value_from_getter)) {
10214
- value = arr_value_before_cast.filter((item) => !_.isEqual(item, value_from_getter));
10215
- } else {
10216
- arr_value_before_cast.push(value_from_getter);
10217
- value = arr_value_before_cast;
10218
- }
10273
+ // let new_val = eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
10219
10274
 
10220
- let datasource_changes = {
10221
- [_dsP]: {
10222
- [_ds.currentRecordId]: {
10223
- [bind_field_id]: value,
10224
- },
10225
- },
10226
- };
10275
+ // new_arr[arr_idx] = obj_item;
10276
+ // } else {
10277
+ // new_arr[arr_idx] = value;
10278
+ // }
10279
+ // // datasource_changes[_dsP][_ds.currentRecordId][reference_source_obj.fieldIdP] = new_arr;
10280
+
10281
+ // let datasource_changes = {
10282
+ // [_dsP]: {
10283
+ // [_ds.currentRecordId]: {
10284
+ // [reference_source_obj.fieldIdP]: new_arr,
10285
+ // },
10286
+ // },
10287
+ // };
10227
10288
 
10228
- return await func.datasource.update(SESSION_ID, datasource_changes);
10229
- }
10289
+ // await func.datasource.update(SESSION_ID, datasource_changes, null, true);
10290
+ // }
10291
+ // }
10292
+ // }
10230
10293
 
10231
- // update array for radio that not in xu-for
10232
- if (field_prop.props.fieldType === 'array' && input_field_type === 'radio' && val_is_reference_field) {
10233
- let value_from_getter = bind.getter($elm[0]);
10294
+ // await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, _ds.parentDataSourceNo);
10295
+ // };
10234
10296
 
10235
- let datasource_changes = {
10236
- [_dsP]: {
10237
- [_ds.currentRecordId]: {
10238
- [bind_field_id]: [value_from_getter],
10239
- },
10240
- },
10241
- };
10297
+ // const bind = new UI_FRAMEWORK_PLUGIN.bind();
10242
10298
 
10243
- return await func.datasource.update(SESSION_ID, datasource_changes);
10244
- }
10299
+ // bind.listener($elm[0], field_changed);
10245
10300
 
10246
- var value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', field_prop.props.fieldType, bind.getter($elm[0]));
10301
+ // const set_value = function () {
10302
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
10303
+ // if (!_ds.currentRecordId) return;
10304
+ // let value;
10305
+ // try {
10306
+ // if (val_is_reference_field) {
10307
+ // if (is_dynamic_field) {
10308
+ // value = _ds.dynamic_fields[bind_field_id].value;
10309
+ // } else {
10310
+ // const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
10311
+ // value = _ds.data_feed.rows?.[row_idx]?.[bind_field_id];
10312
+ // }
10313
+ // if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'checkbox' && $elm.attr('value')) {
10314
+ // if (value.includes($elm.attr('value'))) {
10315
+ // value = true;
10316
+ // } else {
10317
+ // value = false;
10318
+ // }
10319
+ // } else if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'radio' && $elm.attr('value')) {
10320
+ // if (value.includes($elm.attr('value'))) {
10321
+ // value = $elm.attr('value');
10322
+ // } else {
10323
+ // value = false;
10324
+ // }
10325
+ // } else if (field_prop.props.fieldType === 'object' && val.value.split('.').length > 1) {
10326
+ // let str = val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')');
10327
+ // value = eval(str);
10328
+ // }
10329
+ // } else {
10330
+ // value = val.value;
10331
+ // }
10332
+ // if (typeof value === 'undefined') return;
10333
+ // bind.setter($elm[0], value);
10334
+ // } catch (err) {
10335
+ // console.error(err);
10336
+ // }
10337
+ // };
10338
+ // /// init value from ds
10339
+ // $('body').on('xu-bind-refresh.' + _ds.dsSession.toString(), () => {
10340
+ // set_value();
10341
+ // });
10247
10342
 
10248
- if (field_prop.props.fieldType === 'object') {
10249
- value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
10250
- }
10343
+ // set_value();
10344
+ // return {};
10345
+ // },
10346
+ // 'xu-render': async function ($elm, val, from_panel) {
10347
+ // const old_render = async function () {
10348
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
10349
+ // const init_render = function () {
10350
+ // if (!value) {
10351
+ // var cloned_$div = $elm.clone(true);
10352
+
10353
+ // let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container); //.hide();
10354
+ // let original_data_obj = {
10355
+ // $container: cloned_$div,
10356
+ // nodeP: _.cloneDeep(nodeP),
10357
+ // parent_infoP,
10358
+ // paramsP,
10359
+ // keyP,
10360
+ // parent_nodeP,
10361
+ // $root_container,
10362
+ // };
10363
+ // $xurender.data('xuData', cloned_$div.data().xuData);
10364
+ // $xurender.data().xuData.original_data_obj = original_data_obj;
10365
+ // $xurender.data().xuData.xurender_node = cloned_$div;
10366
+ // $xurender.data().xuAttributes = nodeP.attributes || {};
10367
+ // // $xurender.hide();
10368
+
10369
+ // $elm.remove();
10370
+ // return { abort: true };
10371
+ // }
10372
+ // return {};
10373
+ // };
10251
10374
 
10252
- if (!_ds.currentRecordId) return;
10375
+ // const post_render = async function () {
10376
+ // if (value) {
10377
+ // try {
10378
+ // // abort if already rended
10379
+ // if ($elm[0].tagName !== 'XURENDER' && $elm?.length) {
10380
+ // return func.events.delete_job(SESSION_ID, jobNoP);
10381
+ // }
10253
10382
 
10254
- let datasource_changes = {
10255
- [_dsP]: {
10256
- [_ds.currentRecordId]: {
10257
- [bind_field_id]: value,
10258
- },
10259
- },
10260
- };
10383
+ // let original_data_obj = $elm.data().xuData.original_data_obj;
10261
10384
 
10262
- await func.datasource.update(SESSION_ID, datasource_changes);
10263
- const iterate_info = $elm?.data()?.xuData?.iterate_info;
10264
- const reference_source_obj = iterate_info?.reference_source_obj;
10265
- if (reference_source_obj) {
10266
- if (reference_source_obj.ret.type === 'array') {
10267
- if (iterate_info.iterator_val === bind_field_id) {
10268
- const arr_idx = Number($elm?.data()?.xuData?.iterate_info._key);
10385
+ // if (!original_data_obj) {
10386
+ // func.events.delete_job(SESSION_ID, jobNoP);
10387
+ // return { delete_job: jobNoP };
10388
+ // }
10269
10389
 
10270
- const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
10271
- let new_arr = _.cloneDeep(dataset_arr.ret.value);
10390
+ // const new_$div = await func.UI.screen.render_ui_tree(
10391
+ // SESSION_ID,
10392
+ // $elm, //original_data_obj.$container,
10393
+ // _.cloneDeep(original_data_obj.nodeP),
10394
+ // original_data_obj.parent_infoP,
10395
+ // original_data_obj.paramsP,
10396
+ // jobNoP,
10397
+ // null,
10398
+ // original_data_obj.keyP,
10399
+ // null,
10400
+ // original_data_obj.parent_nodeP,
10401
+ // null,
10402
+ // original_data_obj.$root_container,
10403
+ // );
10404
+
10405
+ // new_$div.data().xuData.original_data_obj = original_data_obj;
10406
+ // new_$div.data().xuData.xurender_node = $elm.clone(true);
10407
+ // new_$div.data().xuAttributes = $elm.data().xuAttributes || {};
10408
+
10409
+ // const replace = async function () {
10410
+ // $elm.replaceWith(new_$div);
10411
+ // if (from_panel) {
10412
+ // const xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
10413
+ // $elm.parent().data().xuPanelWrapper = xuPanelWrapper;
10414
+ // $elm.replaceWith(new_$div.children());
10415
+ // }
10416
+
10417
+ // if (val.fields_arr) {
10418
+ // return await func.UI.screen.refresh_xu_attributes(SESSION_ID, val.fields_arr, val.jobNoP, new_$div);
10419
+ // }
10420
+ // func.events.delete_job(SESSION_ID, jobNoP);
10421
+ // };
10422
+ // // if ($elm && func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'xu_id', $elm.data().xuData.xu_id).length) {
10423
+ // if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length) {
10424
+ // if (new_$div.data().xuData.paramsP) {
10425
+ // return await replace();
10426
+ // }
10272
10427
 
10273
- if (field_prop.props.fieldType === 'object' && val_is_reference_field) {
10274
- let obj_item = new_arr[arr_idx];
10428
+ // func.events.delete_job(SESSION_ID, jobNoP);
10429
+ // }
10430
+ // } catch (error) {
10431
+ // func.events.delete_job(SESSION_ID, jobNoP);
10432
+ // }
10433
+ // return;
10434
+ // }
10435
+ // // if (!value) {
10436
+ // if ($elm.prop('tagName') === 'XURENDER') {
10437
+ // func.events.delete_job(SESSION_ID, jobNoP);
10438
+ // return;
10439
+ // }
10275
10440
 
10276
- let e_exp = val.value.replace(bind_field_id, 'obj_item');
10441
+ // let tmp_$div = $('<div>');
10277
10442
 
10278
- let new_val = eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
10443
+ // let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).appendTo(tmp_$div); //.hide();
10444
+ // // was true before
10445
+ // if ($elm.data().xuData.xurender_node) {
10446
+ // $xurender.data({
10447
+ // xuAttributes: $elm.data().xuData.xurender_node.data().xuAttributes || {},
10448
+ // xuData: $elm.data().xuData.xurender_node.data().xuData || {},
10449
+ // });
10450
+ // } else {
10451
+ // // default new state
10279
10452
 
10280
- new_arr[arr_idx] = obj_item;
10281
- } else {
10282
- new_arr[arr_idx] = value;
10283
- }
10284
- // datasource_changes[_dsP][_ds.currentRecordId][reference_source_obj.fieldIdP] = new_arr;
10285
-
10286
- let datasource_changes = {
10287
- [_dsP]: {
10288
- [_ds.currentRecordId]: {
10289
- [reference_source_obj.fieldIdP]: new_arr,
10290
- },
10291
- },
10292
- };
10453
+ // $xurender.data({
10454
+ // xuAttributes: $elm.data().xuAttributes || {},
10455
+ // xuData: $elm.data().xuData || {},
10456
+ // });
10457
+ // const original_data_obj = {
10458
+ // nodeP: _.cloneDeep($elm.data().xuData.node_org),
10459
+ // paramsP: $elm.data().xuData.paramsP,
10460
+ // $container: $elm.clone(true),
10461
+ // parent_infoP: parent_infoP,
10462
+ // };
10463
+
10464
+ // $xurender.data().xuData.original_data_obj = original_data_obj;
10465
+ // }
10293
10466
 
10294
- await func.datasource.update(SESSION_ID, datasource_changes, null, true);
10295
- }
10296
- }
10297
- }
10467
+ // //remove xu-teleport trace
10468
+ // $.each($elm.find('xu-teleport'), (key, val) => {
10469
+ // const xuTeleportData = $(val).data().xuTeleportData || [];
10470
+ // for (const teleported_elm_id of xuTeleportData) {
10471
+ // $(`[xu-ui-id="${teleported_elm_id}"]`).remove();
10472
+ // }
10473
+ // });
10298
10474
 
10299
- await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, _ds.parentDataSourceNo);
10300
- };
10475
+ // $elm.replaceWith(tmp_$div.children());
10476
+ // func.events.delete_job(SESSION_ID, jobNoP);
10477
+ // // }
10478
+ // };
10479
+ // if (is_init) {
10480
+ // return init_render();
10481
+ // }
10482
+ // return await post_render();
10483
+ // };
10301
10484
 
10302
- const bind = new UI_FRAMEWORK_PLUGIN.bind();
10485
+ // const new_render = async function () {
10486
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
10487
+ // const has_xu_render_attribute = true;
10488
+ // const has_xu_exp_render_attribute = $elm.data()?.xuData?.attr_exp_info?.['xu-render'] ? true : false;
10489
+ // const init_render = async function () {
10490
+ // nodeP.xu_render_made = value;
10491
+ // if (!value) {
10492
+ // if (has_xu_exp_render_attribute) {
10493
+ // return { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true };
10494
+ // }
10495
+ // return { has_xu_render_attribute, abort: true };
10496
+ // }
10497
+ // return { has_xu_exp_render_attribute, has_xu_render_attribute };
10498
+ // };
10303
10499
 
10304
- bind.listener($elm[0], field_changed);
10500
+ // const post_render = async function () {
10501
+ // // always come from refresh
10502
+ // let nodeP = $container.data().xuData.node.children[keyP];
10503
+ // nodeP.xu_render_made = value;
10504
+ // if (value) {
10505
+ // try {
10506
+ // 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 || {}));
10507
+ // const xu_ui_id = $elm.attr('xu-ui-id');
10508
+ // let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[xu_ui_id + xu_render_cache_id]?.$div.clone(true);
10509
+ // let found_parent_vars = false;
10510
+ // if (new_$div) {
10511
+ // // validate if $div contains fields from parent ds
10512
+ // const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
10513
+ // const parent_fields = Object.keys(parent_data);
10514
+
10515
+ // $.each(new_$div.find('*'), (key, val) => {
10516
+ // const _xuAttributes = $(val)?.data()?.xuAttributes;
10517
+ // if (found_parent_vars || !_xuAttributes) return;
10518
+ // for (const [attr_key, attr_val] of Object.entries(_xuAttributes)) {
10519
+ // if (found_parent_vars) break;
10520
+ // for (const [key, val] of Object.entries(parent_fields)) {
10521
+ // if (attr_val.includes('@' + key)) {
10522
+ // found_parent_vars = true;
10523
+ // break;
10524
+ // }
10525
+ // }
10526
+ // }
10527
+ // });
10528
+ // }
10305
10529
 
10306
- const set_value = function () {
10307
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
10308
- if (!_ds.currentRecordId) return;
10309
- let value;
10310
- try {
10311
- if (val_is_reference_field) {
10312
- if (is_dynamic_field) {
10313
- value = _ds.dynamic_fields[bind_field_id].value;
10314
- } else {
10315
- const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
10316
- value = _ds.data_feed.rows?.[row_idx]?.[bind_field_id];
10317
- }
10318
- if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'checkbox' && $elm.attr('value')) {
10319
- if (value.includes($elm.attr('value'))) {
10320
- value = true;
10321
- } else {
10322
- value = false;
10323
- }
10324
- } else if (field_prop.props.fieldType === 'array' && $elm.attr('type') === 'radio' && $elm.attr('value')) {
10325
- if (value.includes($elm.attr('value'))) {
10326
- value = $elm.attr('value');
10327
- } else {
10328
- value = false;
10329
- }
10330
- } else if (field_prop.props.fieldType === 'object' && val.value.split('.').length > 1) {
10331
- let str = val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')');
10332
- value = eval(str);
10333
- }
10530
+ // if (!new_$div || found_parent_vars) {
10531
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { paramsP };
10532
+ // nodeP.xu_render_xu_ui_id = xu_ui_id;
10533
+ // nodeP.xu_render_cache_id = xu_render_cache_id;
10534
+ // 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);
10535
+ // const _$div = new_$div.clone(true);
10536
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].$div = _$div;
10537
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].data = _$div.data();
10538
+ // }
10539
+ // // append order handling
10540
+
10541
+ // if (!$container.children().length) {
10542
+ // new_$div.appendTo($container);
10543
+ // } else {
10544
+ // // iterate the container node
10545
+ // let $last_elm_found = [];
10546
+ // $.each($container.data().xuData.node.children, (item_key, item_val) => {
10547
+ // // const $elm = $(`[xu-node-id="${item_val.id}"]`);
10548
+ // const $elm = func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'nodeid', item_val.id);
10549
+ // if ($elm.length) {
10550
+ // $last_elm_found = $elm;
10551
+ // }
10552
+ // if (keyP == item_key) {
10553
+ // if ($last_elm_found.length) {
10554
+ // new_$div.after($last_elm_found);
10555
+ // } else {
10556
+ // $container.prepend(new_$div);
10557
+ // }
10558
+ // }
10559
+ // });
10560
+ // }
10561
+ // } catch (error) {
10562
+ // func.events.delete_job(SESSION_ID, jobNoP);
10563
+ // }
10564
+ // return;
10565
+ // }
10566
+
10567
+ // /////////// !value ///////////
10568
+
10569
+ // const xu_ui_id = $elm.attr('xu-ui-id');
10570
+
10571
+ // const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
10572
+ // const _$div = $elm.clone(true);
10573
+ // UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
10574
+ // $elm.remove();
10575
+ // func.events.delete_job(SESSION_ID, jobNoP);
10576
+ // };
10577
+ // if (is_init) {
10578
+ // return await init_render();
10579
+ // }
10580
+ // return await post_render();
10581
+ // };
10582
+
10583
+ // if (glb.new_xu_render) {
10584
+ // return new_render();
10585
+ // }
10586
+ // return old_render();
10587
+ // },
10588
+ // 'xu-show': async function ($elm, val) {
10589
+ // var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
10590
+ // if (value) {
10591
+ // $elm.show();
10592
+ // }
10593
+ // if (!value) {
10594
+ // $elm.hide();
10595
+ // }
10596
+ // return {};
10597
+ // },
10598
+ // 'xu-content': async function ($elm, val) {
10599
+ // try {
10600
+ // $elm.html(val.value);
10601
+ // } catch (error) {
10602
+ // console.warn(e);
10603
+ // }
10604
+ // return;
10605
+ // },
10606
+ // 'xu-text': async function ($elm, val) {
10607
+ // try {
10608
+ // $elm.text(val.value);
10609
+ // } catch (error) {
10610
+ // console.warn(e);
10611
+ // }
10612
+ // return;
10613
+ // },
10614
+ // 'xu-html': async function ($elm, val) {
10615
+ // try {
10616
+ // $elm.html(val.value);
10617
+ // } catch (error) {
10618
+ // console.warn(e);
10619
+ // }
10620
+ // return;
10621
+ // },
10622
+ // 'xu-for': async function ($elm, data) {
10623
+ // // exit if call from rendered xu-for item to prevent infante loop (parent_infoP?.iterate_info indicate call from rendered item)
10624
+ // if (parent_infoP?.iterate_info) return {};
10625
+ // if (!data.value) return {};
10626
+ // try {
10627
+ // // 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.
10628
+ // let arr = data.value;
10629
+
10630
+ // // find reference source field
10631
+ // let reference_source_obj;
10632
+
10633
+ // const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
10634
+
10635
+ // let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
10636
+ // // detect if data.value (xu-for) is reference field_id by checking if exist in the dataset
10637
+ // if (view_field_obj) {
10638
+ // // xu-for is reference field_id
10639
+ // reference_source_obj = await func.datasource.get_value(SESSION_ID, data.value, paramsP.dsSessionP);
10640
+ // arr = reference_source_obj?.ret?.value;
10641
+ // } else {
10642
+ // // xu-for is actual data
10643
+ // if (typeof data.value === 'string') {
10644
+ // arr = eval(data.value.replaceAll('\\', ''));
10645
+ // }
10646
+ // if (typeof arr === 'number') {
10647
+ // arr = Array.from(Array(arr).keys());
10648
+ // }
10649
+ // }
10650
+
10651
+ // const custom_iterator_key = $elm.data().xuData.iterator_key;
10652
+ // const custom_iterator_val = $elm.data().xuData.iterator_val;
10653
+
10654
+ // let iterator_key = custom_iterator_key;
10655
+ // let iterator_val = custom_iterator_val;
10656
+ // let is_key_dynamic_field, is_val_dynamic_field;
10657
+
10658
+ // // custom FOR_VAL name or namespaced default name
10659
+ // if (!custom_iterator_key) {
10660
+ // is_key_dynamic_field = true;
10661
+
10662
+ // iterator_key = '_FOR_KEY';
10663
+ // }
10664
+
10665
+ // if (!custom_iterator_val) {
10666
+ // is_val_dynamic_field = true;
10667
+
10668
+ // iterator_val = '_FOR_VAL';
10669
+ // }
10670
+
10671
+ // var i = 0;
10672
+ // for await (let [_key, _val] of Object.entries(arr)) {
10673
+ // if (_.isArray(arr)) {
10674
+ // _key = Number(_key);
10675
+ // }
10676
+
10677
+ // const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
10678
+ // if (is_dynamic_field) {
10679
+ // func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
10680
+ // } else {
10681
+ // const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
10682
+
10683
+ // let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
10684
+ // if (view_field_obj) {
10685
+ // let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
10686
+ // try {
10687
+ // const row_idx = func.common.find_ROWID_idx(_ds, currentRecordId);
10688
+ // _ds.data_feed.rows[row_idx][field_id] = value;
10689
+ // } catch (err) {
10690
+ // console.error(err);
10691
+ // }
10692
+ // } else {
10693
+ // console.error('field not exist in dataset for xu-for method');
10694
+ // }
10695
+ // }
10696
+ // };
10697
+
10698
+ // var currentRecordId = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId.toString();
10699
+
10700
+ // await set_value(is_key_dynamic_field, currentRecordId, iterator_key, _key);
10701
+ // await set_value(is_val_dynamic_field, currentRecordId, iterator_val, _val);
10702
+
10703
+ // var iterate_info = {
10704
+ // _val,
10705
+ // _key,
10706
+ // iterator_key,
10707
+ // iterator_val,
10708
+ // is_key_dynamic_field,
10709
+ // is_val_dynamic_field,
10710
+ // reference_source_obj,
10711
+ // };
10712
+ // // let _parent_info = _.cloneDeep(parent_infoP) || {};
10713
+ // let _parent_info = klona.klona(parent_infoP) || {};
10714
+ // _parent_info.iterate_info = iterate_info;
10715
+
10716
+ // const $divP = await func.UI.screen.render_ui_tree(
10717
+ // SESSION_ID,
10718
+ // $container,
10719
+ // nodeP,
10720
+ // _parent_info, //parent_infoP ? _.cloneDeep(_parent_info) : null,
10721
+ // paramsP,
10722
+ // jobNoP,
10723
+ // null,
10724
+ // i,
10725
+ // null,
10726
+ // nodeP,
10727
+ // null,
10728
+ // $root_container,
10729
+ // );
10730
+
10731
+ // $.each($divP.children(), function (key, val) {
10732
+ // if ($(val)?.data()?.xuData) {
10733
+ // $(val).data().xuData.iterate_info = iterate_info;
10734
+ // }
10735
+ // });
10736
+
10737
+ // i++;
10738
+ // }
10739
+ // $elm.remove();
10740
+ // return { abort: true };
10741
+ // } catch (e) {
10742
+ // console.error(' Iterator Arr parse error');
10743
+ // return { abort: true };
10744
+ // }
10745
+ // },
10746
+ // 'xu-for-key': async function ($elm, val) {
10747
+ // $elm.data().xuData.iterator_key = val.value;
10748
+ // return {};
10749
+ // },
10750
+ // 'xu-for-val': async function ($elm, val) {
10751
+ // $elm.data().xuData.iterator_val = val.value;
10752
+ // return {};
10753
+ // },
10754
+ // 'xu-class': async function ($elm, val) {
10755
+ // try {
10756
+ // const classes_string = val.value;
10757
+ // // let obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
10758
+
10759
+ // const classes_obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
10760
+ // for await (const [cla, cond] of Object.entries(classes_obj)) {
10761
+ // let res = await func.expression.get(
10762
+ // SESSION_ID,
10763
+ // cond,
10764
+ // paramsP.dsSessionP,
10765
+ // 'UI Attr EXP',
10766
+ // $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
10767
+ // null,
10768
+ // null,
10769
+ // null,
10770
+ // null,
10771
+ // null,
10772
+ // $elm.data().xuData.iterate_info,
10773
+ // );
10774
+
10775
+ // if (res.result) {
10776
+ // $elm.addClass(cla);
10777
+ // } else {
10778
+ // $elm.removeClass(cla);
10779
+ // }
10780
+
10781
+ // $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
10782
+ // }
10783
+ // return {};
10784
+ // } catch (e) {
10785
+ // console.warn('parse error:' + val.value);
10786
+ // return { abort: true };
10787
+ // }
10788
+ // },
10789
+ // 'xu-exp': async function ($elm, val) {
10790
+ // let exp = val.value === null ? true : val.value;
10791
+
10792
+ // 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);
10793
+
10794
+ // let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
10795
+
10796
+ // var new_val = {
10797
+ // key: val.key,
10798
+ // value,
10799
+ // };
10800
+
10801
+ // if (nodeP.tagName.substr(0, 3) === 'xu-') {
10802
+ // if (tag_fx[nodeP.tagName][new_val.key]) {
10803
+ // return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
10804
+ // }
10805
+ // console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
10806
+ // return {};
10807
+ // }
10808
+ // if (!$elm.data().xuData) return;
10809
+
10810
+ // $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
10811
+
10812
+ // // IGNORE UNDEFINED or NULL ATTRIBUTES
10813
+ // if (typeof new_val.value === 'undefined' || new_val.value === null) {
10814
+ // return {};
10815
+ // }
10816
+
10817
+ // // IGNORE ATTRIBUTES WITH EMPTY VALUES
10818
+ // if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
10819
+ // return {};
10820
+ // }
10821
+
10822
+ // if (new_val.key.substr(0, 2) === 'xu') {
10823
+ // return await common_fx[new_val.key]($elm, new_val);
10824
+ // }
10825
+
10826
+ // $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
10827
+ // return {};
10828
+ // },
10829
+ // 'xu-on': async function ($elm, val) {
10830
+ // CLIENT_ACTIVITY_TS = Date.now();
10831
+ // const trigger = val.key.split('xu-on:')[1].toLowerCase();
10832
+ // $elm.on(trigger, async function (evt) {
10833
+ // const _$elm = $(evt.currentTarget);
10834
+ // if (_.isEmpty(_$elm.data().xuAttributes)) return;
10835
+
10836
+ // for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
10837
+ // if (!_.isEmpty(val.props.condition)) {
10838
+ // const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
10839
+ // if (!expCond.result) continue;
10840
+ // }
10841
+
10842
+ // if (val.event_modifiers && evt[val.event_modifiers]) {
10843
+ // evt[val.event_modifiers]();
10844
+ // }
10845
+
10846
+ // // if (val.handler === 'custom') {
10847
+ // if (val.workflow) {
10848
+ // // do BL
10849
+ // for await (const [key2, val2] of Object.entries(val.workflow)) {
10850
+ // // var cond = val2.data.enabled;
10851
+ // // if (val2.data.enabled && val2.props.condition) {
10852
+ // // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
10853
+ // // cond = expCond.result;
10854
+ // // }
10855
+ // // if (!cond) continue;
10856
+
10857
+ // if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
10858
+
10859
+ // 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);
10860
+ // }
10861
+ // }
10862
+ // }
10863
+ // });
10864
+ // return {};
10865
+ // },
10866
+ // 'xu-script': async function ($elm, val) {
10867
+ // var checkExist = setInterval(async function () {
10868
+ // if ($elm.is(':visible')) {
10869
+ // try {
10870
+ // // var res = eval('(' + val.value + ')');
10871
+ // // const fn = `(function(el) {
10872
+ // // ${val.value}
10873
+ // // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
10874
+
10875
+ // const fn = `async (el)=>{${val.value} };`;
10876
+
10877
+ // var res = eval(fn);
10878
+ // await res($elm[0]);
10879
+ // // if (typeof res === 'function') {
10880
+ // // res($elm[0]);
10881
+ // // }
10882
+ // } catch (e) {
10883
+ // eval(val.value);
10884
+ // }
10885
+
10886
+ // clearInterval(checkExist);
10887
+ // }
10888
+ // }, 100); // check every 100ms
10889
+
10890
+ // return {};
10891
+ // },
10892
+ // 'xu-style-global': async function ($elm, val) {
10893
+ // $('head').append(`<style>${val.value}</style>`);
10894
+ // return {};
10895
+ // },
10896
+ // 'xu-style': async function ($elm, val) {
10897
+ // var cssString = val.value;
10898
+
10899
+ // var parser = new cssjs();
10900
+
10901
+ // var parsed = parser.parseCSS(cssString);
10902
+ // var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
10903
+
10904
+ // $.each(parsed, function (key, val) {
10905
+ // var selectors_arr = val.selector.split(',');
10906
+
10907
+ // $.each(selectors_arr, function (key2, val2) {
10908
+ // selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
10909
+ // // console.log(new_selector);
10910
+ // });
10911
+
10912
+ // val.selector = selectors_arr.join(',');
10913
+ // // console.log(parsed);
10914
+ // });
10915
+
10916
+ // var newCSSString = parser.getCSSForEditor(parsed);
10917
+
10918
+ // $('head').append(`<style>${newCSSString}</style>`);
10919
+ // return {};
10920
+ // },
10921
+ // 'xu-cdn': async function ($elm, val) {
10922
+ // for await (const [key, resource] of Object.entries(val.value)) {
10923
+ // await load_cdn(resource);
10924
+ // }
10925
+
10926
+ // return {};
10927
+ // },
10928
+ // 'xu-ui-plugin': async function ($elm, val) {
10929
+ // var _session = SESSION_OBJ[SESSION_ID];
10930
+
10931
+ // for await (const [plugin_name, value] of Object.entries(val.value)) {
10932
+ // const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
10933
+ // if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
10934
+ // if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
10935
+ // const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
10936
+ // func.utils.load_css_on_demand(plugin_runtime_css_url);
10937
+ // }
10938
+
10939
+ // const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
10940
+
10941
+ // const plugin_index_resources = await import(plugin_index_src);
10942
+
10943
+ // let properties = _.cloneDeep(plugin_index_resources.properties);
10944
+ // for await (let [prop_name, prop_val] of Object.entries(properties)) {
10945
+ // prop_val.value = value?.attributes?.[prop_name];
10946
+ // if (value?.attributes?.[`xu-exp:${prop_name}`]) {
10947
+ // const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
10948
+ // prop_val.value = res.result;
10949
+ // }
10950
+ // }
10951
+ // // $elm.data().xu_ui_plugin = { properties };
10952
+ // const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
10953
+
10954
+ // const plugin_runtime_resources = await import(plugin_runtime_src);
10955
+
10956
+ // if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
10957
+ // for await (const resource of plugin_runtime_resources.cdn) {
10958
+ // await load_cdn(resource);
10959
+ // }
10960
+ // }
10961
+
10962
+ // if (plugin_runtime_resources.fn) {
10963
+ // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
10964
+ // // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
10965
+ // }
10966
+ // }
10967
+ // }
10968
+
10969
+ // return {};
10970
+ // },
10971
+ // 'xu-store': async function ($elm, val) {
10972
+ // try {
10973
+ // const fields_obj = JSON5.parse(val.value);
10974
+ // for (const [field_id, value] of Object.entries(fields_obj)) {
10975
+ // func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
10976
+ // }
10977
+ // } catch (err) {
10978
+ // console.error(err);
10979
+ // }
10980
+ // return {};
10981
+ // },
10982
+ // 'xu-viewport': async function ($elm, val) {
10983
+ // // functionality in draw_html_element
10984
+ // return {};
10985
+ // },
10986
+ // };
10987
+
10988
+ // if (nodeP.tagName.substr(0, 3) === 'xu-') {
10989
+ // if (xu_func === 'xu-exp') {
10990
+ // return common_fx[xu_func]($elm, val);
10991
+ // }
10992
+
10993
+ // if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
10994
+ // let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
10995
+ // return ret;
10996
+ // }
10997
+ // // if (xu_func !== "tree_id")
10998
+ // console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
10999
+ // return {};
11000
+ // }
11001
+ // if (_.isEmpty($elm.data())) {
11002
+ // return {};
11003
+ // }
11004
+ // if (!$elm.data().xuData.debug_info.attribute_stat) {
11005
+ // $elm.data().xuData.debug_info.attribute_stat = {};
11006
+ // }
11007
+ // if (xu_func !== 'xu-exp') {
11008
+ // $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
11009
+ // }
11010
+ // try {
11011
+ // if (!common_fx[xu_func]) {
11012
+ // console.warn('invalid xu-tag', xu_func, error);
11013
+ // return {};
11014
+ // }
11015
+
11016
+ // return await common_fx[xu_func]($elm, val);
11017
+ // } catch (error) {
11018
+ // debugger;
11019
+ // }
11020
+ // };
11021
+
11022
+ 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) {
11023
+ if (is_skeleton) return;
11024
+
11025
+ // Cache frequently accessed values
11026
+ const _session = SESSION_OBJ[SESSION_ID];
11027
+ const _ds = _session.DS_GLB[paramsP.dsSessionP];
11028
+ const elmData = $elm.data();
11029
+ const xuData = elmData.xuData;
11030
+ const nodeTag = nodeP.tagName;
11031
+ const isXuTag = nodeTag && nodeTag.startsWith('xu-');
11032
+
11033
+ const load_cdn = async function (resource) {
11034
+ if (!_.isObject(resource)) {
11035
+ resource = _.isString(resource) ? { src: resource, type: 'js' } : null;
11036
+ }
11037
+ if (!resource) {
11038
+ throw new Error('cdn resource in wrong format');
11039
+ }
11040
+
11041
+ try {
11042
+ const loadFn = resource.type === 'css' ? func.utils.load_css_on_demand : func.utils.load_js_on_demand;
11043
+ const moduleArg = resource.type === 'module' ? 'module' : undefined;
11044
+ await loadFn(resource.src, moduleArg);
11045
+ } catch (error) {
11046
+ func.utils.debug_report(SESSION_ID, 'xu-cdn', 'Fail to load: ' + resource.src, 'W');
11047
+ }
11048
+ };
11049
+
11050
+ const common_fx = {
11051
+ 'xu-attrs': async function ($elm, val) {
11052
+ if (!val.value || !_.isObject(val.value)) {
11053
+ if (val.value) throw 'xu-attrs value is not an object';
11054
+ return {};
11055
+ }
11056
+ Object.assign(nodeP.attributes, val.value);
11057
+ return {};
11058
+ },
11059
+
11060
+ 'xu-ref': async function ($elm, val, dsSession) {
11061
+ if (!val.value) return {};
11062
+
11063
+ func.UI.update_xu_ref(SESSION_ID, dsSession || paramsP.dsSessionP, val.value, $elm);
11064
+
11065
+ const targetNode = $elm[0];
11066
+ if (!targetNode) return {};
11067
+
11068
+ const observer = new MutationObserver(() => {
11069
+ func.UI.screen.refresh_xu_attributes(SESSION_ID, [val.value]);
11070
+ });
11071
+
11072
+ observer.observe(targetNode, { attributes: true, childList: true, subtree: true });
11073
+ return {};
11074
+ },
11075
+
11076
+ 'xu-bind': async function ($elm, val) {
11077
+ if (is_skeleton) return {};
11078
+
11079
+ let val_is_reference_field = false;
11080
+ let _prog_id = xuData.paramsP.prog_id;
11081
+ let _dsP = xuData.paramsP.dsSessionP;
11082
+
11083
+ const view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
11084
+ if (!view_ret) return {};
11085
+
11086
+ let is_dynamic_field = false;
11087
+ let field_prop;
11088
+ let bind_field_id;
11089
+ const input_field_type = $elm.attr('type');
11090
+
11091
+ const get_bind_field = async function (field_id) {
11092
+ if (['_FOR_VAL', '_FOR_KEY'].includes(field_id)) {
11093
+ is_dynamic_field = true;
11094
+ field_prop = _ds.dynamic_fields[field_id];
11095
+ } else {
11096
+ field_prop = func.common.find_item_by_key(view_ret.progFields, 'field_id', field_id);
11097
+ if (!field_prop) {
11098
+ const ret_get_value = await func.datasource.get_value(SESSION_ID, field_id, _dsP);
11099
+ if (ret_get_value.found) {
11100
+ _dsP = ret_get_value.dsSessionP;
11101
+ const ds = _session.DS_GLB[_dsP];
11102
+ _prog_id = ds.prog_id;
11103
+ const new_view_ret = await func.utils.VIEWS_OBJ.get(SESSION_ID, _prog_id);
11104
+ if (!new_view_ret) return {};
11105
+ field_prop = func.common.find_item_by_key(new_view_ret.progFields, 'field_id', field_id);
11106
+ }
11107
+ if (!field_prop) {
11108
+ throw `field ${field_id} not found in the program scope`;
11109
+ }
11110
+ }
11111
+ }
11112
+ return field_id;
11113
+ };
11114
+
11115
+ try {
11116
+ bind_field_id = await get_bind_field(val.value.split('.')[0]);
11117
+ val_is_reference_field = true;
11118
+ } catch (err) {
11119
+ console.error(err?.message || err);
11120
+ return {};
11121
+ }
11122
+
11123
+ const field_changed = async function (e) {
11124
+ const ds = _session.DS_GLB[_dsP];
11125
+ const fieldType = field_prop.props.fieldType;
11126
+ const isCheckbox = input_field_type === 'checkbox';
11127
+ const isRadio = input_field_type === 'radio';
11128
+
11129
+ // Handle array field with checkbox
11130
+ if (fieldType === 'array' && isCheckbox && val_is_reference_field) {
11131
+ const arr_value = _.clone((await func.datasource.get_value(SESSION_ID, bind_field_id, _dsP, ds.currentRecordId)).ret.value);
11132
+ const value_from_getter = bind.getter($elm[0]);
11133
+ const value = arr_value.includes(value_from_getter) ? arr_value.filter((item) => !_.isEqual(item, value_from_getter)) : [...arr_value, value_from_getter];
11134
+
11135
+ return await func.datasource.update(SESSION_ID, {
11136
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: value } },
11137
+ });
11138
+ }
11139
+
11140
+ // Handle array field with radio
11141
+ if (fieldType === 'array' && isRadio && val_is_reference_field) {
11142
+ return await func.datasource.update(SESSION_ID, {
11143
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: [bind.getter($elm[0])] } },
11144
+ });
11145
+ }
11146
+
11147
+ let value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', fieldType, bind.getter($elm[0]));
11148
+
11149
+ if (fieldType === 'object') {
11150
+ value = await func.common.get_cast_val(SESSION_ID, 'xu-bind', 'value', input_field_type, bind.getter($elm[0]));
11151
+ }
11152
+
11153
+ if (!ds.currentRecordId) return;
11154
+
11155
+ await func.datasource.update(SESSION_ID, {
11156
+ [_dsP]: { [ds.currentRecordId]: { [bind_field_id]: value } },
11157
+ });
11158
+
11159
+ const iterate_info = xuData?.iterate_info;
11160
+ const reference_source_obj = iterate_info?.reference_source_obj;
11161
+
11162
+ if (reference_source_obj?.ret?.type === 'array' && iterate_info.iterator_val === bind_field_id) {
11163
+ const arr_idx = Number(iterate_info._key);
11164
+ const dataset_arr = await func.datasource.get_value(SESSION_ID, reference_source_obj.fieldIdP, _dsP, reference_source_obj.currentRecordId);
11165
+ const new_arr = _.cloneDeep(dataset_arr.ret.value);
11166
+
11167
+ if (fieldType === 'object' && val_is_reference_field) {
11168
+ let obj_item = new_arr[arr_idx];
11169
+ const e_exp = val.value.replace(bind_field_id, 'obj_item');
11170
+ eval(e_exp + (input_field_type === 'string' ? `="${value}"` : `=${value}`));
11171
+ new_arr[arr_idx] = obj_item;
11172
+ } else {
11173
+ new_arr[arr_idx] = value;
11174
+ }
11175
+
11176
+ await func.datasource.update(
11177
+ SESSION_ID,
11178
+ {
11179
+ [_dsP]: { [ds.currentRecordId]: { [reference_source_obj.fieldIdP]: new_arr } },
11180
+ },
11181
+ null,
11182
+ true,
11183
+ );
11184
+ }
11185
+
11186
+ await func.datasource.update_changes_for_out_parameter(SESSION_ID, _dsP, ds.parentDataSourceNo);
11187
+ };
11188
+
11189
+ const bind = new UI_FRAMEWORK_PLUGIN.bind();
11190
+ bind.listener($elm[0], field_changed);
11191
+
11192
+ const set_value = function () {
11193
+ const ds = _session.DS_GLB[paramsP.dsSessionP];
11194
+ if (!ds.currentRecordId) return;
11195
+
11196
+ try {
11197
+ let value;
11198
+ if (val_is_reference_field) {
11199
+ if (is_dynamic_field) {
11200
+ value = ds.dynamic_fields[bind_field_id].value;
11201
+ } else {
11202
+ const row_idx = func.common.find_ROWID_idx(ds, ds.currentRecordId);
11203
+ value = ds.data_feed.rows?.[row_idx]?.[bind_field_id];
11204
+ }
11205
+
11206
+ const fieldType = field_prop.props.fieldType;
11207
+ const elmValue = $elm.attr('value');
11208
+
11209
+ if (fieldType === 'array' && input_field_type === 'checkbox' && elmValue) {
11210
+ value = value.includes(elmValue);
11211
+ } else if (fieldType === 'array' && input_field_type === 'radio' && elmValue) {
11212
+ value = value.includes(elmValue) ? elmValue : false;
11213
+ } else if (fieldType === 'object' && val.value.split('.').length > 1) {
11214
+ value = eval(val.value.replace(bind_field_id, '(' + JSON.stringify(value) + ')'));
11215
+ }
10334
11216
  } else {
10335
11217
  value = val.value;
10336
11218
  }
10337
- if (typeof value === 'undefined') return;
10338
- bind.setter($elm[0], value);
11219
+
11220
+ if (value !== undefined) {
11221
+ bind.setter($elm[0], value);
11222
+ }
10339
11223
  } catch (err) {
10340
11224
  console.error(err);
10341
11225
  }
10342
11226
  };
10343
- /// init value from ds
10344
- $('body').on('xu-bind-refresh.' + _ds.dsSession.toString(), () => {
10345
- set_value();
10346
- });
10347
11227
 
11228
+ $('body').on('xu-bind-refresh.' + _ds.dsSession, set_value);
10348
11229
  set_value();
10349
11230
  return {};
10350
11231
  },
11232
+
10351
11233
  'xu-render': async function ($elm, val, from_panel) {
10352
- const old_render = async function () {
10353
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
11234
+ const value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
11235
+
11236
+ if (!glb.new_xu_render) {
11237
+ // Old render logic (kept as is for compatibility)
10354
11238
  const init_render = function () {
10355
11239
  if (!value) {
10356
- var cloned_$div = $elm.clone(true);
10357
-
10358
- let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container); //.hide();
10359
- let original_data_obj = {
11240
+ const cloned_$div = $elm.clone(true);
11241
+ const $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).attr('hidden', true).appendTo($container);
11242
+ const original_data_obj = {
10360
11243
  $container: cloned_$div,
10361
11244
  nodeP: _.cloneDeep(nodeP),
10362
11245
  parent_infoP,
@@ -10369,8 +11252,6 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10369
11252
  $xurender.data().xuData.original_data_obj = original_data_obj;
10370
11253
  $xurender.data().xuData.xurender_node = cloned_$div;
10371
11254
  $xurender.data().xuAttributes = nodeP.attributes || {};
10372
- // $xurender.hide();
10373
-
10374
11255
  $elm.remove();
10375
11256
  return { abort: true };
10376
11257
  }
@@ -10380,271 +11261,207 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10380
11261
  const post_render = async function () {
10381
11262
  if (value) {
10382
11263
  try {
10383
- // abort if already rended
10384
- if ($elm[0].tagName !== 'XURENDER' && $elm?.length) {
11264
+ if ($elm[0].tagName !== 'XURENDER' || !$elm?.length) {
10385
11265
  return func.events.delete_job(SESSION_ID, jobNoP);
10386
11266
  }
10387
11267
 
10388
- let original_data_obj = $elm.data().xuData.original_data_obj;
10389
-
11268
+ const original_data_obj = $elm.data().xuData.original_data_obj;
10390
11269
  if (!original_data_obj) {
10391
11270
  func.events.delete_job(SESSION_ID, jobNoP);
10392
11271
  return { delete_job: jobNoP };
10393
11272
  }
10394
11273
 
10395
- const new_$div = await func.UI.screen.render_ui_tree(
10396
- SESSION_ID,
10397
- $elm, //original_data_obj.$container,
10398
- _.cloneDeep(original_data_obj.nodeP),
10399
- original_data_obj.parent_infoP,
10400
- original_data_obj.paramsP,
10401
- jobNoP,
10402
- null,
10403
- original_data_obj.keyP,
10404
- null,
10405
- original_data_obj.parent_nodeP,
10406
- null,
10407
- original_data_obj.$root_container,
10408
- );
11274
+ 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);
10409
11275
 
10410
11276
  new_$div.data().xuData.original_data_obj = original_data_obj;
10411
11277
  new_$div.data().xuData.xurender_node = $elm.clone(true);
10412
11278
  new_$div.data().xuAttributes = $elm.data().xuAttributes || {};
10413
11279
 
10414
11280
  const replace = async function () {
10415
- $elm.replaceWith(new_$div);
11281
+ $elm.replaceWith(from_panel ? new_$div.children() : new_$div);
10416
11282
  if (from_panel) {
10417
- const xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
10418
- $elm.parent().data().xuPanelWrapper = xuPanelWrapper;
10419
- $elm.replaceWith(new_$div.children());
11283
+ $elm.parent().data().xuPanelWrapper = _.clone(new_$div.data().xuPanelWrapper);
10420
11284
  }
10421
-
10422
11285
  if (val.fields_arr) {
10423
11286
  return await func.UI.screen.refresh_xu_attributes(SESSION_ID, val.fields_arr, val.jobNoP, new_$div);
10424
11287
  }
10425
11288
  func.events.delete_job(SESSION_ID, jobNoP);
10426
11289
  };
10427
- // if ($elm && func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'xu_id', $elm.data().xuData.xu_id).length) {
10428
- if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length) {
10429
- if (new_$div.data().xuData.paramsP) {
10430
- return await replace();
10431
- }
10432
11290
 
10433
- func.events.delete_job(SESSION_ID, jobNoP);
11291
+ if ($elm && $(`[xu-ui-id="${$elm.attr('xu-ui-id')}"]`).length && new_$div.data().xuData.paramsP) {
11292
+ return await replace();
10434
11293
  }
11294
+ func.events.delete_job(SESSION_ID, jobNoP);
10435
11295
  } catch (error) {
10436
11296
  func.events.delete_job(SESSION_ID, jobNoP);
10437
11297
  }
10438
11298
  return;
10439
11299
  }
10440
- // if (!value) {
11300
+
10441
11301
  if ($elm.prop('tagName') === 'XURENDER') {
10442
11302
  func.events.delete_job(SESSION_ID, jobNoP);
10443
11303
  return;
10444
11304
  }
10445
11305
 
10446
- let tmp_$div = $('<div>');
11306
+ const $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id'));
10447
11307
 
10448
- let $xurender = $('<xurender>').attr('xu-ui-id', $elm.attr('xu-ui-id')).appendTo(tmp_$div); //.hide();
10449
- // was true before
10450
11308
  if ($elm.data().xuData.xurender_node) {
10451
11309
  $xurender.data({
10452
11310
  xuAttributes: $elm.data().xuData.xurender_node.data().xuAttributes || {},
10453
11311
  xuData: $elm.data().xuData.xurender_node.data().xuData || {},
10454
11312
  });
10455
11313
  } else {
10456
- // default new state
10457
-
10458
11314
  $xurender.data({
10459
11315
  xuAttributes: $elm.data().xuAttributes || {},
10460
11316
  xuData: $elm.data().xuData || {},
10461
11317
  });
10462
- const original_data_obj = {
11318
+ $xurender.data().xuData.original_data_obj = {
10463
11319
  nodeP: _.cloneDeep($elm.data().xuData.node_org),
10464
11320
  paramsP: $elm.data().xuData.paramsP,
10465
11321
  $container: $elm.clone(true),
10466
11322
  parent_infoP: parent_infoP,
10467
11323
  };
10468
-
10469
- $xurender.data().xuData.original_data_obj = original_data_obj;
10470
11324
  }
10471
11325
 
10472
- //remove xu-teleport trace
10473
11326
  $.each($elm.find('xu-teleport'), (key, val) => {
10474
11327
  const xuTeleportData = $(val).data().xuTeleportData || [];
10475
- for (const teleported_elm_id of xuTeleportData) {
10476
- $(`[xu-ui-id="${teleported_elm_id}"]`).remove();
10477
- }
11328
+ xuTeleportData.forEach((id) => $(`[xu-ui-id="${id}"]`).remove());
10478
11329
  });
10479
11330
 
10480
- $elm.replaceWith(tmp_$div.children());
11331
+ $elm.replaceWith($xurender);
10481
11332
  func.events.delete_job(SESSION_ID, jobNoP);
10482
- // }
10483
11333
  };
10484
- if (is_init) {
10485
- return init_render();
10486
- }
10487
- return await post_render();
10488
- };
10489
11334
 
10490
- const new_render = async function () {
10491
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-render', 'bool', val.value);
10492
- const has_xu_render_attribute = true;
10493
- const has_xu_exp_render_attribute = $elm.data()?.xuData?.attr_exp_info?.['xu-render'] ? true : false;
10494
- const init_render = async function () {
10495
- nodeP.xu_render_made = value;
10496
- if (!value) {
10497
- if (has_xu_exp_render_attribute) {
10498
- return { has_xu_exp_render_attribute, has_xu_render_attribute, xu_render_background_processing: true };
10499
- }
10500
- return { has_xu_render_attribute, abort: true };
10501
- }
10502
- return { has_xu_exp_render_attribute, has_xu_render_attribute };
10503
- };
11335
+ return is_init ? init_render() : await post_render();
11336
+ }
10504
11337
 
10505
- const post_render = async function () {
10506
- // always come from refresh
10507
- let nodeP = $container.data().xuData.node.children[keyP];
10508
- nodeP.xu_render_made = value;
10509
- if (value) {
10510
- try {
10511
- 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 || {}));
10512
- const xu_ui_id = $elm.attr('xu-ui-id');
10513
- let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[xu_ui_id + xu_render_cache_id]?.$div.clone(true);
10514
- let found_parent_vars = false;
10515
- if (new_$div) {
10516
- // validate if $div contains fields from parent ds
10517
- const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
10518
- const parent_fields = Object.keys(parent_data);
10519
-
10520
- $.each(new_$div.find('*'), (key, val) => {
10521
- const _xuAttributes = $(val)?.data()?.xuAttributes;
10522
- if (found_parent_vars || !_xuAttributes) return;
10523
- for (const [attr_key, attr_val] of Object.entries(_xuAttributes)) {
10524
- if (found_parent_vars) break;
10525
- for (const [key, val] of Object.entries(parent_fields)) {
10526
- if (attr_val.includes('@' + key)) {
10527
- found_parent_vars = true;
10528
- break;
10529
- }
10530
- }
10531
- }
10532
- });
10533
- }
11338
+ // New render logic
11339
+ const has_xu_render_attribute = true;
11340
+ const has_xu_exp_render_attribute = !!xuData?.attr_exp_info?.['xu-render'];
10534
11341
 
10535
- if (!new_$div || found_parent_vars) {
10536
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { paramsP };
10537
- nodeP.xu_render_xu_ui_id = xu_ui_id;
10538
- nodeP.xu_render_cache_id = xu_render_cache_id;
10539
- 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);
10540
- const _$div = new_$div.clone(true);
10541
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].$div = _$div;
10542
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id].data = _$div.data();
10543
- }
10544
- // append order handling
11342
+ const init_render = async function () {
11343
+ nodeP.xu_render_made = value;
11344
+ if (!value) {
11345
+ 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 };
11346
+ }
11347
+ return { has_xu_exp_render_attribute, has_xu_render_attribute };
11348
+ };
10545
11349
 
10546
- if (!$container.children().length) {
10547
- new_$div.appendTo($container);
10548
- } else {
10549
- // iterate the container node
10550
- let $last_elm_found = [];
10551
- $.each($container.data().xuData.node.children, (item_key, item_val) => {
10552
- // const $elm = $(`[xu-node-id="${item_val.id}"]`);
10553
- const $elm = func.UI.utils.find_in_element_data('xuData', $(SESSION_OBJ[SESSION_ID].root_element), 'nodeid', item_val.id);
10554
- if ($elm.length) {
10555
- $last_elm_found = $elm;
10556
- }
10557
- if (keyP == item_key) {
10558
- if ($last_elm_found.length) {
10559
- new_$div.after($last_elm_found);
10560
- } else {
10561
- $container.prepend(new_$div);
10562
- }
11350
+ const post_render = async function () {
11351
+ const containerNodeP = $container.data().xuData.node.children[keyP];
11352
+ containerNodeP.xu_render_made = value;
11353
+
11354
+ if (value) {
11355
+ try {
11356
+ const xu_render_cache_id = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys(xuData?.attr_exp_info?.['xu-render']?.fields || {}));
11357
+ const xu_ui_id = $elm.attr('xu-ui-id');
11358
+ const cache_key = xu_ui_id + xu_render_cache_id;
11359
+ let new_$div = UI_WORKER_OBJ?.xu_render_cache?.[cache_key]?.$div?.clone(true);
11360
+ let found_parent_vars = false;
11361
+
11362
+ if (new_$div) {
11363
+ const parent_data = get_parent_ds_fields(SESSION_ID, paramsP.dsSessionP);
11364
+ const parent_fields = Object.keys(parent_data);
11365
+
11366
+ $.each(new_$div.find('*'), (key, val) => {
11367
+ if (found_parent_vars) return;
11368
+ const _xuAttributes = $(val)?.data()?.xuAttributes;
11369
+ if (!_xuAttributes) return;
11370
+
11371
+ for (const attr_val of Object.values(_xuAttributes)) {
11372
+ if (parent_fields.some((field) => attr_val.includes('@' + field))) {
11373
+ found_parent_vars = true;
11374
+ break;
10563
11375
  }
10564
- });
10565
- }
10566
- } catch (error) {
10567
- func.events.delete_job(SESSION_ID, jobNoP);
11376
+ }
11377
+ });
10568
11378
  }
10569
- return;
10570
- }
10571
11379
 
10572
- /////////// !value ///////////
11380
+ if (!new_$div || found_parent_vars) {
11381
+ UI_WORKER_OBJ.xu_render_cache[cache_key] = { paramsP };
11382
+ containerNodeP.xu_render_xu_ui_id = xu_ui_id;
11383
+ containerNodeP.xu_render_cache_id = xu_render_cache_id;
10573
11384
 
10574
- const xu_ui_id = $elm.attr('xu-ui-id');
11385
+ 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);
10575
11386
 
10576
- const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($elm.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
10577
- const _$div = $elm.clone(true);
10578
- UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
10579
- $elm.remove();
10580
- func.events.delete_job(SESSION_ID, jobNoP);
10581
- };
10582
- if (is_init) {
10583
- return await init_render();
11387
+ const _$div = new_$div.clone(true);
11388
+ UI_WORKER_OBJ.xu_render_cache[cache_key] = { $div: _$div, data: _$div.data(), paramsP };
11389
+ }
11390
+
11391
+ // Append order handling
11392
+ if (!$container.children().length) {
11393
+ new_$div.appendTo($container);
11394
+ } else {
11395
+ let $last_elm_found = [];
11396
+ $.each($container.data().xuData.node.children, (item_key, item_val) => {
11397
+ const $elm = func.UI.utils.find_in_element_data('xuData', $(_session.root_element), 'nodeid', item_val.id);
11398
+ if ($elm.length) $last_elm_found = $elm;
11399
+ if (keyP == item_key) {
11400
+ $last_elm_found.length ? new_$div.after($last_elm_found) : $container.prepend(new_$div);
11401
+ }
11402
+ });
11403
+ }
11404
+ } catch (error) {
11405
+ func.events.delete_job(SESSION_ID, jobNoP);
11406
+ }
11407
+ return;
10584
11408
  }
10585
- return await post_render();
11409
+
11410
+ // !value
11411
+ const xu_ui_id = $elm.attr('xu-ui-id');
11412
+ const cache_str = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys(xuData?.attr_exp_info?.['xu-render']?.fields || {}));
11413
+ const _$div = $elm.clone(true);
11414
+ UI_WORKER_OBJ.xu_render_cache[xu_ui_id + cache_str] = { $div: _$div, data: _$div.data(), paramsP };
11415
+ $elm.remove();
11416
+ func.events.delete_job(SESSION_ID, jobNoP);
10586
11417
  };
10587
11418
 
10588
- if (glb.new_xu_render) {
10589
- return new_render();
10590
- }
10591
- return old_render();
11419
+ return is_init ? await init_render() : await post_render();
10592
11420
  },
11421
+
10593
11422
  'xu-show': async function ($elm, val) {
10594
- var value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
10595
- if (value) {
10596
- $elm.show();
10597
- }
10598
- if (!value) {
10599
- $elm.hide();
10600
- }
11423
+ const value = await func.common.get_cast_val(SESSION_ID, 'common fx', 'xu-show', 'bool', val.value);
11424
+ $elm.toggle(value);
10601
11425
  return {};
10602
11426
  },
11427
+
10603
11428
  'xu-content': async function ($elm, val) {
10604
11429
  try {
10605
11430
  $elm.html(val.value);
10606
11431
  } catch (error) {
10607
- console.warn(e);
11432
+ console.warn(error);
10608
11433
  }
10609
- return;
10610
11434
  },
11435
+
10611
11436
  'xu-text': async function ($elm, val) {
10612
11437
  try {
10613
11438
  $elm.text(val.value);
10614
11439
  } catch (error) {
10615
- console.warn(e);
11440
+ console.warn(error);
10616
11441
  }
10617
- return;
10618
11442
  },
11443
+
10619
11444
  'xu-html': async function ($elm, val) {
10620
11445
  try {
10621
11446
  $elm.html(val.value);
10622
11447
  } catch (error) {
10623
- console.warn(e);
11448
+ console.warn(error);
10624
11449
  }
10625
- return;
10626
11450
  },
11451
+
10627
11452
  'xu-for': async function ($elm, data) {
10628
- // exit if call from rendered xu-for item to prevent infante loop (parent_infoP?.iterate_info indicate call from rendered item)
10629
- if (parent_infoP?.iterate_info) return {};
10630
- if (!data.value) return {};
11453
+ if (parent_infoP?.iterate_info || !data.value) return {};
11454
+
10631
11455
  try {
10632
- // 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.
10633
11456
  let arr = data.value;
10634
-
10635
- // find reference source field
10636
11457
  let reference_source_obj;
10637
-
10638
11458
  const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
11459
+ const view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
10639
11460
 
10640
- let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', data.value);
10641
- // detect if data.value (xu-for) is reference field_id by checking if exist in the dataset
10642
11461
  if (view_field_obj) {
10643
- // xu-for is reference field_id
10644
11462
  reference_source_obj = await func.datasource.get_value(SESSION_ID, data.value, paramsP.dsSessionP);
10645
11463
  arr = reference_source_obj?.ret?.value;
10646
11464
  } else {
10647
- // xu-for is actual data
10648
11465
  if (typeof data.value === 'string') {
10649
11466
  arr = eval(data.value.replaceAll('\\', ''));
10650
11467
  }
@@ -10653,59 +11470,44 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10653
11470
  }
10654
11471
  }
10655
11472
 
10656
- const custom_iterator_key = $elm.data().xuData.iterator_key;
10657
- const custom_iterator_val = $elm.data().xuData.iterator_val;
10658
-
10659
- let iterator_key = custom_iterator_key;
10660
- let iterator_val = custom_iterator_val;
10661
- let is_key_dynamic_field, is_val_dynamic_field;
10662
-
10663
- // custom FOR_VAL name or namespaced default name
10664
- if (!custom_iterator_key) {
10665
- is_key_dynamic_field = true;
10666
-
10667
- iterator_key = '_FOR_KEY';
10668
- }
11473
+ const custom_iterator_key = xuData.iterator_key;
11474
+ const custom_iterator_val = xuData.iterator_val;
11475
+ const iterator_key = custom_iterator_key || '_FOR_KEY';
11476
+ const iterator_val = custom_iterator_val || '_FOR_VAL';
11477
+ const is_key_dynamic_field = !custom_iterator_key;
11478
+ const is_val_dynamic_field = !custom_iterator_val;
10669
11479
 
10670
- if (!custom_iterator_val) {
10671
- is_val_dynamic_field = true;
10672
-
10673
- iterator_val = '_FOR_VAL';
10674
- }
10675
-
10676
- var i = 0;
10677
- for await (let [_key, _val] of Object.entries(arr)) {
10678
- if (_.isArray(arr)) {
10679
- _key = Number(_key);
10680
- }
11480
+ const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
11481
+ if (is_dynamic_field) {
11482
+ func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
11483
+ } else {
11484
+ const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
11485
+ const view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
10681
11486
 
10682
- const set_value = async function (is_dynamic_field, currentRecordId, field_id, value) {
10683
- if (is_dynamic_field) {
10684
- func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
10685
- } else {
10686
- const _progFields = await func.datasource.get_progFields(SESSION_ID, paramsP.dsSessionP);
10687
-
10688
- let view_field_obj = func.common.find_item_by_key(_progFields, 'field_id', field_id);
10689
- if (view_field_obj) {
10690
- let _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
10691
- try {
10692
- const row_idx = func.common.find_ROWID_idx(_ds, currentRecordId);
10693
- _ds.data_feed.rows[row_idx][field_id] = value;
10694
- } catch (err) {
10695
- console.error(err);
10696
- }
10697
- } else {
10698
- console.error('field not exist in dataset for xu-for method');
11487
+ if (view_field_obj) {
11488
+ const ds = _session.DS_GLB[paramsP.dsSessionP];
11489
+ try {
11490
+ const row_idx = func.common.find_ROWID_idx(ds, currentRecordId);
11491
+ ds.data_feed.rows[row_idx][field_id] = value;
11492
+ } catch (err) {
11493
+ console.error(err);
10699
11494
  }
11495
+ } else {
11496
+ console.error('field not exist in dataset for xu-for method');
10700
11497
  }
10701
- };
11498
+ }
11499
+ };
11500
+
11501
+ const currentRecordId = _ds.currentRecordId.toString();
11502
+ let i = 0;
10702
11503
 
10703
- var currentRecordId = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId.toString();
11504
+ for (let [_key, _val] of Object.entries(arr)) {
11505
+ if (_.isArray(arr)) _key = Number(_key);
10704
11506
 
10705
11507
  await set_value(is_key_dynamic_field, currentRecordId, iterator_key, _key);
10706
11508
  await set_value(is_val_dynamic_field, currentRecordId, iterator_val, _val);
10707
11509
 
10708
- var iterate_info = {
11510
+ const iterate_info = {
10709
11511
  _val,
10710
11512
  _key,
10711
11513
  iterator_key,
@@ -10714,26 +11516,13 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10714
11516
  is_val_dynamic_field,
10715
11517
  reference_source_obj,
10716
11518
  };
10717
- // let _parent_info = _.cloneDeep(parent_infoP) || {};
10718
- let _parent_info = klona.klona(parent_infoP) || {};
11519
+
11520
+ const _parent_info = klona.klona(parent_infoP) || {};
10719
11521
  _parent_info.iterate_info = iterate_info;
10720
11522
 
10721
- const $divP = await func.UI.screen.render_ui_tree(
10722
- SESSION_ID,
10723
- $container,
10724
- nodeP,
10725
- _parent_info, //parent_infoP ? _.cloneDeep(_parent_info) : null,
10726
- paramsP,
10727
- jobNoP,
10728
- null,
10729
- i,
10730
- null,
10731
- nodeP,
10732
- null,
10733
- $root_container,
10734
- );
11523
+ const $divP = await func.UI.screen.render_ui_tree(SESSION_ID, $container, nodeP, _parent_info, paramsP, jobNoP, null, i, null, nodeP, null, $root_container);
10735
11524
 
10736
- $.each($divP.children(), function (key, val) {
11525
+ $.each($divP.children(), (key, val) => {
10737
11526
  if ($(val)?.data()?.xuData) {
10738
11527
  $(val).data().xuData.iterate_info = iterate_info;
10739
11528
  }
@@ -10741,106 +11530,87 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10741
11530
 
10742
11531
  i++;
10743
11532
  }
11533
+
10744
11534
  $elm.remove();
10745
11535
  return { abort: true };
10746
11536
  } catch (e) {
10747
- console.error(' Iterator Arr parse error');
11537
+ console.error('Iterator Arr parse error', e);
10748
11538
  return { abort: true };
10749
11539
  }
10750
11540
  },
11541
+
10751
11542
  'xu-for-key': async function ($elm, val) {
10752
- $elm.data().xuData.iterator_key = val.value;
11543
+ xuData.iterator_key = val.value;
10753
11544
  return {};
10754
11545
  },
11546
+
10755
11547
  'xu-for-val': async function ($elm, val) {
10756
- $elm.data().xuData.iterator_val = val.value;
11548
+ xuData.iterator_val = val.value;
10757
11549
  return {};
10758
11550
  },
11551
+
10759
11552
  'xu-class': async function ($elm, val) {
10760
11553
  try {
10761
- const classes_string = val.value;
10762
- // let obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
11554
+ const classes_obj = _.isString(val.value) ? JSON.parse(val.value) : _.defaults(val.value, {});
10763
11555
 
10764
- const classes_obj = _.isString(classes_string) ? JSON.parse(classes_string) : _.defaults(classes_string, {});
10765
- for await (const [cla, cond] of Object.entries(classes_obj)) {
10766
- let res = await func.expression.get(
10767
- SESSION_ID,
10768
- cond,
10769
- paramsP.dsSessionP,
10770
- 'UI Attr EXP',
10771
- $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
10772
- null,
10773
- null,
10774
- null,
10775
- null,
10776
- null,
10777
- $elm.data().xuData.iterate_info,
10778
- );
10779
-
10780
- if (res.result) {
10781
- $elm.addClass(cla);
10782
- } else {
10783
- $elm.removeClass(cla);
10784
- }
11556
+ for (const [cla, cond] of Object.entries(classes_obj)) {
11557
+ const res = await func.expression.get(SESSION_ID, cond, paramsP.dsSessionP, 'UI Attr EXP', xuData.currentRecordId, null, null, null, null, null, xuData.iterate_info);
10785
11558
 
10786
- $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
11559
+ $elm.toggleClass(cla, res.result);
10787
11560
  }
11561
+
11562
+ xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
10788
11563
  return {};
10789
11564
  } catch (e) {
10790
11565
  console.warn('parse error:' + val.value);
10791
11566
  return { abort: true };
10792
11567
  }
10793
11568
  },
10794
- 'xu-exp': async function ($elm, val) {
10795
- let exp = val.value === null ? true : val.value;
10796
-
10797
- 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);
10798
11569
 
10799
- let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
11570
+ 'xu-exp': async function ($elm, val) {
11571
+ const exp = val.value === null ? true : val.value;
11572
+ 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);
10800
11573
 
10801
- var new_val = {
10802
- key: val.key,
10803
- value,
10804
- };
11574
+ const value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
11575
+ const new_val = { key: val.key, value };
10805
11576
 
10806
- if (nodeP.tagName.substr(0, 3) === 'xu-') {
10807
- if (tag_fx[nodeP.tagName][new_val.key]) {
10808
- return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
11577
+ if (isXuTag) {
11578
+ if (tag_fx[nodeTag]?.[new_val.key]) {
11579
+ return await tag_fx[nodeTag][new_val.key]($elm, new_val);
10809
11580
  }
10810
- console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
11581
+ console.warn(`attribute ${new_val.key} not found for ${nodeTag}`);
10811
11582
  return {};
10812
11583
  }
10813
- if (!$elm.data().xuData) return;
10814
-
10815
- $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
10816
11584
 
10817
- // IGNORE UNDEFINED or NULL ATTRIBUTES
10818
- if (typeof new_val.value === 'undefined' || new_val.value === null) {
10819
- return {};
10820
- }
11585
+ if (!xuData) return {};
11586
+ xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
10821
11587
 
10822
- // IGNORE ATTRIBUTES WITH EMPTY VALUES
10823
- if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
10824
- return {};
10825
- }
11588
+ if (new_val.value === undefined || new_val.value === null) return {};
11589
+ if (glb.solid_attributes.includes(new_val.key) && !new_val.value) return {};
10826
11590
 
10827
- if (new_val.key.substr(0, 2) === 'xu') {
11591
+ if (new_val.key.startsWith('xu')) {
10828
11592
  return await common_fx[new_val.key]($elm, new_val);
10829
11593
  }
10830
11594
 
10831
11595
  $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
10832
11596
  return {};
10833
11597
  },
11598
+
10834
11599
  'xu-on': async function ($elm, val) {
10835
11600
  CLIENT_ACTIVITY_TS = Date.now();
10836
11601
  const trigger = val.key.split('xu-on:')[1].toLowerCase();
11602
+
10837
11603
  $elm.on(trigger, async function (evt) {
10838
11604
  const _$elm = $(evt.currentTarget);
10839
- if (_.isEmpty(_$elm.data().xuAttributes)) return;
11605
+ const xuAttributes = _$elm.data().xuAttributes;
11606
+ if (_.isEmpty(xuAttributes)) return;
11607
+
11608
+ const handlers = xuAttributes['xu-on:' + evt.type];
11609
+ if (!handlers) return;
10840
11610
 
10841
- for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
11611
+ for (const [key, val] of Object.entries(handlers)) {
10842
11612
  if (!_.isEmpty(val.props.condition)) {
10843
- const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
11613
+ const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid);
10844
11614
  if (!expCond.result) continue;
10845
11615
  }
10846
11616
 
@@ -10848,18 +11618,9 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10848
11618
  evt[val.event_modifiers]();
10849
11619
  }
10850
11620
 
10851
- // if (val.handler === 'custom') {
10852
11621
  if (val.workflow) {
10853
- // do BL
10854
- for await (const [key2, val2] of Object.entries(val.workflow)) {
10855
- // var cond = val2.data.enabled;
10856
- // if (val2.data.enabled && val2.props.condition) {
10857
- // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
10858
- // cond = expCond.result;
10859
- // }
10860
- // if (!cond) continue;
10861
-
10862
- if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
11622
+ for (const [key2, val2] of Object.entries(val.workflow)) {
11623
+ if (!val2.data.enabled) continue;
10863
11624
 
10864
11625
  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);
10865
11626
  }
@@ -10868,111 +11629,91 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10868
11629
  });
10869
11630
  return {};
10870
11631
  },
11632
+
10871
11633
  'xu-script': async function ($elm, val) {
10872
- var checkExist = setInterval(async function () {
11634
+ const checkExist = setInterval(async function () {
10873
11635
  if ($elm.is(':visible')) {
10874
11636
  try {
10875
- // var res = eval('(' + val.value + ')');
10876
- // const fn = `(function(el) {
10877
- // ${val.value}
10878
- // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
10879
-
10880
- const fn = `async (el)=>{${val.value} };`;
10881
-
10882
- var res = eval(fn);
10883
- await res($elm[0]);
10884
- // if (typeof res === 'function') {
10885
- // res($elm[0]);
10886
- // }
11637
+ const fn = eval(`async (el)=>{${val.value}}`);
11638
+ await fn($elm[0]);
10887
11639
  } catch (e) {
10888
11640
  eval(val.value);
10889
11641
  }
10890
-
10891
11642
  clearInterval(checkExist);
10892
11643
  }
10893
- }, 100); // check every 100ms
10894
-
10895
- return {};
10896
- },
10897
- 'xu-style-global': async function ($elm, val) {
10898
- $('head').append(`<style>${val.value}</style>`);
11644
+ }, 100);
10899
11645
  return {};
10900
11646
  },
10901
- 'xu-style': async function ($elm, val) {
10902
- var cssString = val.value;
10903
-
10904
- var parser = new cssjs();
10905
11647
 
10906
- var parsed = parser.parseCSS(cssString);
10907
- var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
10908
-
10909
- $.each(parsed, function (key, val) {
10910
- var selectors_arr = val.selector.split(',');
10911
-
10912
- $.each(selectors_arr, function (key2, val2) {
10913
- selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
10914
- // console.log(new_selector);
10915
- });
11648
+ 'xu-style-global': async function ($elm, val) {
11649
+ $('head').append(`<style>${val.value}</style>`);
11650
+ return {};
11651
+ },
10916
11652
 
10917
- val.selector = selectors_arr.join(',');
10918
- // console.log(parsed);
11653
+ 'xu-style': async function ($elm, val) {
11654
+ const parser = new cssjs();
11655
+ const parsed = parser.parseCSS(val.value);
11656
+ const xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
11657
+
11658
+ parsed.forEach((rule) => {
11659
+ rule.selector = rule.selector
11660
+ .split(',')
11661
+ .map((sel) => `${xuUiId} ${sel}, ${xuUiId}${sel}`)
11662
+ .join(',');
10919
11663
  });
10920
11664
 
10921
- var newCSSString = parser.getCSSForEditor(parsed);
10922
-
10923
- $('head').append(`<style>${newCSSString}</style>`);
11665
+ $('head').append(`<style>${parser.getCSSForEditor(parsed)}</style>`);
10924
11666
  return {};
10925
11667
  },
11668
+
10926
11669
  'xu-cdn': async function ($elm, val) {
10927
- for await (const [key, resource] of Object.entries(val.value)) {
11670
+ for (const resource of Object.values(val.value)) {
10928
11671
  await load_cdn(resource);
10929
11672
  }
10930
-
10931
11673
  return {};
10932
11674
  },
10933
- 'xu-ui-plugin': async function ($elm, val) {
10934
- var _session = SESSION_OBJ[SESSION_ID];
10935
11675
 
10936
- for await (const [plugin_name, value] of Object.entries(val.value)) {
11676
+ 'xu-ui-plugin': async function ($elm, val) {
11677
+ for (const [plugin_name, value] of Object.entries(val.value)) {
10937
11678
  const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
10938
- if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
10939
- if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
10940
- const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
10941
- func.utils.load_css_on_demand(plugin_runtime_css_url);
10942
- }
10943
11679
 
10944
- const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
11680
+ if (!_plugin?.installed || !_plugin?.manifest?.['runtime.mjs']?.exist || !_plugin?.manifest?.['index.mjs']?.exist || !value.enabled) continue;
10945
11681
 
10946
- const plugin_index_resources = await import(plugin_index_src);
11682
+ if (_plugin.manifest['runtime.mjs'].dist && _plugin.manifest['runtime.mjs'].css) {
11683
+ const css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
11684
+ func.utils.load_css_on_demand(css_url);
11685
+ }
10947
11686
 
10948
- let properties = _.cloneDeep(plugin_index_resources.properties);
10949
- for await (let [prop_name, prop_val] of Object.entries(properties)) {
10950
- prop_val.value = value?.attributes?.[prop_name];
10951
- if (value?.attributes?.[`xu-exp:${prop_name}`]) {
10952
- const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
10953
- prop_val.value = res.result;
10954
- }
10955
- }
10956
- // $elm.data().xu_ui_plugin = { properties };
10957
- const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
11687
+ const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
10958
11688
 
10959
- const plugin_runtime_resources = await import(plugin_runtime_src);
11689
+ const plugin_index_resources = await import(plugin_index_src);
11690
+ const properties = _.cloneDeep(plugin_index_resources.properties);
10960
11691
 
10961
- if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
10962
- for await (const resource of plugin_runtime_resources.cdn) {
10963
- await load_cdn(resource);
10964
- }
11692
+ for (const [prop_name, prop_val] of Object.entries(properties)) {
11693
+ prop_val.value = value?.attributes?.[prop_name];
11694
+ if (value?.attributes?.[`xu-exp:${prop_name}`]) {
11695
+ const res = await func.expression.get(SESSION_ID, value.attributes[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
11696
+ prop_val.value = res.result;
10965
11697
  }
11698
+ }
11699
+
11700
+ const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
10966
11701
 
10967
- if (plugin_runtime_resources.fn) {
10968
- await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
10969
- // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
11702
+ const plugin_runtime_resources = await import(plugin_runtime_src);
11703
+
11704
+ if (plugin_runtime_resources.cdn && _.isArray(plugin_runtime_resources.cdn)) {
11705
+ for (const resource of plugin_runtime_resources.cdn) {
11706
+ await load_cdn(resource);
10970
11707
  }
10971
11708
  }
10972
- }
10973
11709
 
11710
+ if (plugin_runtime_resources.fn) {
11711
+ await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
11712
+ }
11713
+ }
10974
11714
  return {};
10975
11715
  },
11716
+
10976
11717
  'xu-store': async function ($elm, val) {
10977
11718
  try {
10978
11719
  const fields_obj = JSON5.parse(val.value);
@@ -10984,43 +11725,135 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
10984
11725
  }
10985
11726
  return {};
10986
11727
  },
11728
+
10987
11729
  'xu-viewport': async function ($elm, val) {
10988
- // functionality in draw_html_element
10989
11730
  return {};
10990
11731
  },
10991
11732
  };
10992
11733
 
10993
- if (nodeP.tagName.substr(0, 3) === 'xu-') {
11734
+ const tag_fx = {
11735
+ 'xu-panel': {
11736
+ program: async function ($elm, val) {
11737
+ const init_program = async function () {
11738
+ async function render_panel() {
11739
+ const prog_id = val.value?.prog || val.value;
11740
+ const params_obj = await get_params_obj_new(SESSION_ID, prog_id, nodeP, paramsP.dsSessionP);
11741
+ 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);
11742
+
11743
+ const containerData = $container.data();
11744
+ if (containerData.xuData) {
11745
+ containerData.xuData.xuPanelProps = elmData.xuAttributes;
11746
+ containerData.xuData.xuPanelData = ret_panel.data();
11747
+ }
11748
+ return { $new_div: ret_panel };
11749
+ }
11750
+
11751
+ if (!val.value) val.value = '_empty_panel_program';
11752
+ return await render_panel();
11753
+ };
11754
+
11755
+ const alter_program = async function () {
11756
+ async function render_panel() {
11757
+ const program = val.value?.prog || val.value;
11758
+ const $wrapper = $('<div>');
11759
+ 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, '');
11760
+
11761
+ const params_obj = await get_params_obj_new(SESSION_ID, program, nodeP, paramsP.dsSessionP);
11762
+ 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);
11763
+
11764
+ await func.UI.screen.panel_post_render_handler(SESSION_ID, $elm, ret_init, nodeP, $div.clone(true), jobNoP);
11765
+
11766
+ return { $new_div: ret_init, abort: true };
11767
+ }
11768
+
11769
+ if (!val.value) return { abort: true };
11770
+ await render_panel();
11771
+ return { abort: true };
11772
+ };
11773
+
11774
+ return is_init ? await init_program() : await alter_program();
11775
+ },
11776
+
11777
+ 'xu-render': async function ($elm, val) {
11778
+ return await common_fx['xu-render']($elm, val, true);
11779
+ },
11780
+
11781
+ 'xu-ref': async function ($elm, val) {
11782
+ return await common_fx['xu-ref']($container, val, $container.data().xuData.xuPanelData.xuData.paramsP.dsSessionP);
11783
+ },
11784
+ },
11785
+
11786
+ 'xu-teleport': {
11787
+ to: async function ($elm, val) {
11788
+ if (!glb.new_xu_render && val.value) {
11789
+ if ($elm?.parent()?.data()?.xuData?.length) {
11790
+ $elm.parent().data('xuTeleportData', []);
11791
+ for (const [key, node] of Object.entries(nodeP.children)) {
11792
+ 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);
11793
+ $elm.parent().data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
11794
+ $teleport_elm.attr('xu-teleport-parent-id', $elm.parent().attr('xu-ui-id'));
11795
+ }
11796
+ $elm.remove();
11797
+ } else {
11798
+ $elm.data('xuTeleportData', []).attr('hidden', true);
11799
+ for (const [key, node] of Object.entries(nodeP.children)) {
11800
+ const $to_container = $(val.value);
11801
+ if (!$to_container?.length) {
11802
+ return console.error(`container ${val.value} for xuTeleportData not found`);
11803
+ }
11804
+ 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);
11805
+ $elm.data().xuTeleportData.push($teleport_elm.attr('xu-ui-id'));
11806
+ $teleport_elm.attr('xu-teleport-parent-id', $elm.attr('xu-ui-id'));
11807
+ }
11808
+ }
11809
+ return { abort: true };
11810
+ }
11811
+ return {};
11812
+ },
11813
+
11814
+ 'xu-render': async function ($elm, val) {
11815
+ return await common_fx['xu-render']($elm, val, true);
11816
+ },
11817
+
11818
+ 'xu-show': async function ($elm, val) {
11819
+ return await common_fx['xu-show']($elm, val, true);
11820
+ },
11821
+ },
11822
+ };
11823
+
11824
+ // Main execution logic
11825
+ if (isXuTag) {
10994
11826
  if (xu_func === 'xu-exp') {
10995
11827
  return common_fx[xu_func]($elm, val);
10996
11828
  }
10997
11829
 
10998
- if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
10999
- let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
11000
- return ret;
11830
+ if (tag_fx?.[nodeTag]?.[xu_func]) {
11831
+ return await tag_fx[nodeTag][xu_func]($elm, val);
11001
11832
  }
11002
- // if (xu_func !== "tree_id")
11003
- console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
11004
- return {};
11005
- }
11006
- if (_.isEmpty($elm.data())) {
11833
+
11834
+ console.warn(`attribute ${xu_func} not found for ${nodeTag}`);
11007
11835
  return {};
11008
11836
  }
11009
- if (!$elm.data().xuData.debug_info.attribute_stat) {
11010
- $elm.data().xuData.debug_info.attribute_stat = {};
11837
+
11838
+ if (_.isEmpty(elmData)) return {};
11839
+
11840
+ if (!xuData.debug_info.attribute_stat) {
11841
+ xuData.debug_info.attribute_stat = {};
11011
11842
  }
11843
+
11012
11844
  if (xu_func !== 'xu-exp') {
11013
- $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
11845
+ xuData.debug_info.attribute_stat[xu_func] = val.value;
11014
11846
  }
11847
+
11015
11848
  try {
11016
11849
  if (!common_fx[xu_func]) {
11017
- console.warn('invalid xu-tag', xu_func, error);
11850
+ console.warn('invalid xu-tag', xu_func);
11018
11851
  return {};
11019
11852
  }
11020
-
11021
11853
  return await common_fx[xu_func]($elm, val);
11022
11854
  } catch (error) {
11023
- debugger;
11855
+ console.error('execute_xu_functions error:', error);
11856
+ return {};
11024
11857
  }
11025
11858
  };
11026
11859
 
@@ -11043,62 +11876,408 @@ func.UI.screen.fix_val_defaults = function (key, val) {
11043
11876
  return ret;
11044
11877
  };
11045
11878
 
11879
+ // 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) {
11880
+ // var done_exp = [];
11881
+
11882
+ // const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
11883
+ // if (!_ds) return { abort: true };
11884
+
11885
+ // const get_attr_value = async function (key) {
11886
+ // let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
11887
+ // if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
11888
+ // ret = await get_xuExp(key);
11889
+ // }
11890
+ // return ret;
11891
+ // };
11892
+
11893
+ // const get_xuExp = async function (attrib) {
11894
+ // if (is_skeleton) return;
11895
+ // if (glb.new_xu_render) {
11896
+ // let _xuData = $elm.data().xuData;
11897
+ // if (!_xuData.attr_exp_info) {
11898
+ // _xuData.attr_exp_info = {};
11899
+ // }
11900
+ // }
11901
+ // const attr = `xu-exp:${attrib}`;
11902
+
11903
+ // if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
11904
+ // // const attr = `xu-exp-${attrib}`;
11905
+ // var exp = nodeP.attributes[attr];
11906
+ // // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
11907
+
11908
+ // var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
11909
+ // if (glb.new_xu_render) {
11910
+ // _xuData.attr_exp_info[attrib] = res;
11911
+ // }
11912
+ // // nodeP.attributes[attr] = value; //{ value: value, res: res };
11913
+ // done_exp.push(attr);
11914
+ // return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
11915
+ // };
11916
+
11917
+ // var _ret = {};
11918
+ // if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
11919
+
11920
+ // for (let [key, val] of Object.entries(nodeP.attributes)) {
11921
+ // // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
11922
+ // if (key.substring(0, 6) === 'xu-exp') {
11923
+ // if (_.isEmpty(val)) {
11924
+ // delete nodeP.attributes[key];
11925
+ // continue;
11926
+ // }
11927
+ // const clean_key = key.split(':')[1];
11928
+ // if (typeof nodeP.attributes[clean_key] !== 'undefined') {
11929
+ // delete nodeP.attributes[clean_key];
11930
+ // }
11931
+ // }
11932
+ // // FIX abbreviations
11933
+ // if (glb.attr_abbreviations_arr.includes(key)) {
11934
+ // nodeP.attributes[`xu-on:${key.substring(3)}`] = [
11935
+ // {
11936
+ // handler: 'custom',
11937
+ // props: {},
11938
+ // event: [
11939
+ // {
11940
+ // id: Date.now(),
11941
+ // data: {
11942
+ // action: 'update',
11943
+ // name: { value: val },
11944
+ // enabled: true,
11945
+ // },
11946
+ // props: {},
11947
+ // },
11948
+ // ],
11949
+ // },
11950
+ // ];
11951
+ // delete nodeP.attributes[key];
11952
+ // }
11953
+ // }
11954
+
11955
+ // for (let [key, val] of Object.entries(nodeP.attributes)) {
11956
+ // // FIX STATIC DEFAULTS
11957
+ // val = func.UI.screen.fix_val_defaults(key, val);
11958
+
11959
+ // // REMOVE UNDEFINED or NULL ATTRIBUTES
11960
+ // if (typeof val === 'undefined' || val === null) {
11961
+ // delete nodeP.attributes[key];
11962
+ // }
11963
+
11964
+ // // REMOVE ATTRIBUTES WITH EMPTY VALUES
11965
+ // if (glb.solid_attributes.includes(key) && !val) {
11966
+ // delete nodeP.attributes[key];
11967
+ // }
11968
+ // }
11969
+
11970
+ // // XU-ATTRS
11971
+ // if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
11972
+ // const attr = 'xu-attrs';
11973
+ // let ret = await func.UI.screen.execute_xu_functions(
11974
+ // SESSION_ID,
11975
+ // is_skeleton,
11976
+ // $root_container,
11977
+ // nodeP,
11978
+ // $container,
11979
+ // paramsP,
11980
+ // parent_infoP,
11981
+ // jobNoP,
11982
+ // keyP,
11983
+ // parent_nodeP,
11984
+ // attr,
11985
+ // $elm,
11986
+ // {
11987
+ // key: attr,
11988
+ // value: await get_attr_value(attr),
11989
+ // },
11990
+ // is_init,
11991
+ // );
11992
+ // }
11993
+
11994
+ // // BEFORE
11995
+ // if (!_.isEmpty(nodeP.attributes)) {
11996
+ // for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
11997
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
11998
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
11999
+ // continue;
12000
+ // }
12001
+
12002
+ // if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
12003
+ // continue;
12004
+ // }
12005
+
12006
+ // if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
12007
+ // continue;
12008
+ // }
12009
+
12010
+ // let ret = await func.UI.screen.execute_xu_functions(
12011
+ // SESSION_ID,
12012
+ // is_skeleton,
12013
+ // $root_container,
12014
+ // nodeP,
12015
+ // $container,
12016
+ // paramsP,
12017
+ // parent_infoP,
12018
+ // jobNoP,
12019
+ // keyP,
12020
+ // parent_nodeP,
12021
+ // attr,
12022
+ // $elm,
12023
+ // {
12024
+ // key: attr,
12025
+
12026
+ // value: await get_attr_value(attr),
12027
+ // },
12028
+ // is_init,
12029
+ // );
12030
+ // _ret = _.assignIn(_ret, ret);
12031
+ // }
12032
+ // }
12033
+
12034
+ // // ALL
12035
+
12036
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
12037
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
12038
+ // if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
12039
+ // continue;
12040
+ // }
12041
+
12042
+ // const new_key = key.split(':')[0]; // break expression
12043
+ // if (
12044
+ // nodeP.tagName !== 'xu-panel' &&
12045
+ // nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
12046
+ // (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
12047
+ // ) {
12048
+ // // handle common html attributes
12049
+ // try {
12050
+ // $elm.get(0).setAttribute(key, val);
12051
+ // } catch (err) {
12052
+ // console.error(err.message);
12053
+ // }
12054
+
12055
+ // continue;
12056
+ // }
12057
+ // // handle xu attributes
12058
+ // try {
12059
+ // if ($elm?.data()?.xuAttributes) {
12060
+ // // in some cases xu data delete in purpose when refreshing the screen
12061
+ // $elm.data().xuAttributes[key] = val;
12062
+ // }
12063
+ // } catch (error) {
12064
+ // debugger;
12065
+ // console.error(error);
12066
+ // }
12067
+
12068
+ // 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)) {
12069
+ // continue;
12070
+ // }
12071
+
12072
+ // if (new_key === 'xu-on') {
12073
+ // let ret = await func.UI.screen.execute_xu_functions(
12074
+ // SESSION_ID,
12075
+ // is_skeleton,
12076
+ // $root_container,
12077
+ // nodeP,
12078
+ // $container,
12079
+ // paramsP,
12080
+ // parent_infoP,
12081
+ // jobNoP,
12082
+ // keyP,
12083
+ // parent_nodeP,
12084
+ // 'xu-on',
12085
+ // $elm,
12086
+ // {
12087
+ // key: key,
12088
+ // // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
12089
+ // value: await get_attr_value(key),
12090
+ // },
12091
+ // is_init,
12092
+ // refreshed_ds,
12093
+ // );
12094
+ // _ret = _.assignIn(_ret, ret);
12095
+ // continue;
12096
+ // }
12097
+
12098
+ // let ret = await func.UI.screen.execute_xu_functions(
12099
+ // SESSION_ID,
12100
+ // is_skeleton,
12101
+ // $root_container,
12102
+ // nodeP,
12103
+ // $container,
12104
+ // paramsP,
12105
+ // parent_infoP,
12106
+ // jobNoP,
12107
+ // keyP,
12108
+ // parent_nodeP,
12109
+ // new_key,
12110
+ // $elm,
12111
+ // {
12112
+ // key: key,
12113
+ // // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
12114
+ // value: await get_attr_value(key),
12115
+ // },
12116
+ // is_init,
12117
+ // refreshed_ds,
12118
+ // );
12119
+
12120
+ // _ret = _.assignIn(_ret, ret);
12121
+ // }
12122
+
12123
+ // // EXP for
12124
+
12125
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
12126
+ // if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
12127
+
12128
+ // const attr = key.split('xu-exp:')[1];
12129
+
12130
+ // if (!attr) {
12131
+ // continue;
12132
+ // }
12133
+
12134
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
12135
+
12136
+ // if (done_exp.includes(key)) {
12137
+ // continue;
12138
+ // }
12139
+ // let ret = await func.UI.screen.execute_xu_functions(
12140
+ // SESSION_ID,
12141
+ // is_skeleton,
12142
+ // $root_container,
12143
+ // nodeP,
12144
+ // $container,
12145
+ // paramsP,
12146
+ // parent_infoP,
12147
+ // jobNoP,
12148
+ // keyP,
12149
+ // parent_nodeP,
12150
+ // 'xu-exp',
12151
+ // $elm,
12152
+ // {
12153
+ // key: attr,
12154
+ // value: val,
12155
+ // },
12156
+ // true,
12157
+ // refreshed_ds,
12158
+ // );
12159
+ // _ret = _.assignIn(_ret, ret);
12160
+ // }
12161
+
12162
+ // // AFTER
12163
+
12164
+ // for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
12165
+ // if ($container?.data()?.xuData?.pending_to_delete) break;
12166
+
12167
+ // if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
12168
+
12169
+ // if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
12170
+
12171
+ // let ret = await func.UI.screen.execute_xu_functions(
12172
+ // SESSION_ID,
12173
+ // is_skeleton,
12174
+ // $root_container,
12175
+ // nodeP,
12176
+ // $container,
12177
+ // paramsP,
12178
+ // parent_infoP,
12179
+ // jobNoP,
12180
+ // keyP,
12181
+ // parent_nodeP,
12182
+ // attr,
12183
+ // $elm,
12184
+ // {
12185
+ // key: attr,
12186
+ // // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
12187
+ // value: await get_attr_value(attr),
12188
+ // },
12189
+ // is_init,
12190
+ // refreshed_ds,
12191
+ // );
12192
+ // _ret = _.assignIn(_ret, ret);
12193
+ // }
12194
+
12195
+ // // REGISTER EVENTS ATTRIBUTES
12196
+
12197
+ // for await (const [key, val] of Object.entries(nodeP.attributes)) {
12198
+ // if ($container?.data()?.xuData?.pending_to_delete) break;
12199
+ // if (!glb.html5_events_handler.includes(key)) break;
12200
+ // // $elm.attr(key, await get_xuExp(key)) || val;
12201
+ // $elm.attr(key, await get_xuExp(key)) || val;
12202
+ // }
12203
+
12204
+ // return _ret;
12205
+ // };
12206
+
11046
12207
  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) {
11047
- var done_exp = [];
12208
+ const done_exp = new Set(); // Use Set for O(1) lookups instead of array
11048
12209
 
11049
12210
  const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
11050
12211
  if (!_ds) return { abort: true };
11051
12212
 
12213
+ // Early return if not an element or no attributes
12214
+ if (nodeP.type !== 'element' || !nodeP.attributes) return {};
12215
+
12216
+ // Cache frequently accessed values
12217
+ const nodeAttrs = nodeP.attributes;
12218
+ const elmData = $elm.data();
12219
+ const xuData = elmData.xuData;
12220
+ const containerData = $container?.data();
12221
+ const containerXuData = containerData?.xuData;
12222
+
11052
12223
  const get_attr_value = async function (key) {
11053
- let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
11054
- if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
11055
- ret = await get_xuExp(key);
12224
+ const expKey = `xu-exp:${key}`;
12225
+ if (nodeAttrs.hasOwnProperty(expKey)) {
12226
+ return await get_xuExp(key);
11056
12227
  }
11057
- return ret;
12228
+ return func.UI.screen.fix_val_defaults(key, nodeAttrs[key]);
11058
12229
  };
11059
12230
 
11060
12231
  const get_xuExp = async function (attrib) {
11061
12232
  if (is_skeleton) return;
12233
+
12234
+ const attr = `xu-exp:${attrib}`;
12235
+ if (!nodeAttrs.hasOwnProperty(attr)) return;
12236
+
11062
12237
  if (glb.new_xu_render) {
11063
- let _xuData = $elm.data().xuData;
11064
- if (!_xuData.attr_exp_info) {
11065
- _xuData.attr_exp_info = {};
12238
+ if (!xuData.attr_exp_info) {
12239
+ xuData.attr_exp_info = {};
11066
12240
  }
11067
12241
  }
11068
- const attr = `xu-exp:${attrib}`;
11069
12242
 
11070
- if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
11071
- // const attr = `xu-exp-${attrib}`;
11072
- var exp = nodeP.attributes[attr];
11073
- // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
12243
+ const exp = nodeAttrs[attr];
12244
+ const res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
11074
12245
 
11075
- var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
11076
12246
  if (glb.new_xu_render) {
11077
- _xuData.attr_exp_info[attrib] = res;
12247
+ xuData.attr_exp_info[attrib] = res;
11078
12248
  }
11079
- // nodeP.attributes[attr] = value; //{ value: value, res: res };
11080
- done_exp.push(attr);
11081
- return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
11082
- };
11083
12249
 
11084
- var _ret = {};
11085
- if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
12250
+ done_exp.add(attr);
12251
+ return res.result;
12252
+ };
11086
12253
 
11087
- for (let [key, val] of Object.entries(nodeP.attributes)) {
11088
- // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
11089
- if (key.substring(0, 6) === 'xu-exp') {
12254
+ // Create Sets for O(1) lookups
12255
+ const html5EventsSet = new Set(glb.html5_events_handler);
12256
+ const executeAttrsSet = new Set(execute_attributes);
12257
+ const solidAttrsSet = new Set(glb.solid_attributes);
12258
+ const abbreviationsSet = new Set(glb.attr_abbreviations_arr);
12259
+ const runXuBeforeSet = new Set(Object.values(glb.run_xu_before));
12260
+ const runXuAfterSet = new Set(Object.values(glb.run_xu_after));
12261
+
12262
+ // Process attributes in a single pass where possible
12263
+ const attrsToDelete = [];
12264
+ const xuOnAttrs = {};
12265
+
12266
+ for (const [key, val] of Object.entries(nodeAttrs)) {
12267
+ // Handle xu-exp attributes
12268
+ if (key.startsWith('xu-exp:')) {
11090
12269
  if (_.isEmpty(val)) {
11091
- delete nodeP.attributes[key];
12270
+ attrsToDelete.push(key);
11092
12271
  continue;
11093
12272
  }
11094
- const clean_key = key.split(':')[1];
11095
- if (typeof nodeP.attributes[clean_key] !== 'undefined') {
11096
- delete nodeP.attributes[clean_key];
12273
+ const clean_key = key.slice(7); // 'xu-exp:'.length = 7
12274
+ if (nodeAttrs[clean_key] !== undefined) {
12275
+ attrsToDelete.push(clean_key);
11097
12276
  }
11098
12277
  }
11099
- // FIX abbreviations
11100
- if (glb.attr_abbreviations_arr.includes(key)) {
11101
- nodeP.attributes[`xu-on:${key.substring(3)}`] = [
12278
+ // Handle abbreviations
12279
+ else if (abbreviationsSet.has(key)) {
12280
+ xuOnAttrs[`xu-on:${key.slice(3)}`] = [
11102
12281
  {
11103
12282
  handler: 'custom',
11104
12283
  props: {},
@@ -11115,257 +12294,131 @@ func.UI.screen.set_attributes_new = async function (SESSION_ID, is_skeleton, $ro
11115
12294
  ],
11116
12295
  },
11117
12296
  ];
11118
- delete nodeP.attributes[key];
12297
+ attrsToDelete.push(key);
11119
12298
  }
11120
12299
  }
11121
12300
 
11122
- for (let [key, val] of Object.entries(nodeP.attributes)) {
11123
- // FIX STATIC DEFAULTS
11124
- val = func.UI.screen.fix_val_defaults(key, val);
12301
+ // Delete marked attributes
12302
+ for (const key of attrsToDelete) {
12303
+ delete nodeAttrs[key];
12304
+ }
11125
12305
 
11126
- // REMOVE UNDEFINED or NULL ATTRIBUTES
11127
- if (typeof val === 'undefined' || val === null) {
11128
- delete nodeP.attributes[key];
11129
- }
12306
+ // Add xu-on attributes
12307
+ Object.assign(nodeAttrs, xuOnAttrs);
11130
12308
 
11131
- // REMOVE ATTRIBUTES WITH EMPTY VALUES
11132
- if (glb.solid_attributes.includes(key) && !val) {
11133
- delete nodeP.attributes[key];
12309
+ // Clean up attributes
12310
+ for (const [key, val] of Object.entries(nodeAttrs)) {
12311
+ const fixedVal = func.UI.screen.fix_val_defaults(key, val);
12312
+
12313
+ if (fixedVal === undefined || fixedVal === null) {
12314
+ delete nodeAttrs[key];
12315
+ } else if (solidAttrsSet.has(key) && !fixedVal) {
12316
+ delete nodeAttrs[key];
12317
+ } else {
12318
+ nodeAttrs[key] = fixedVal;
11134
12319
  }
11135
12320
  }
11136
12321
 
12322
+ const _ret = {};
12323
+
12324
+ // Helper to check abort condition
12325
+ const shouldAbort = () => _ret.abort || containerXuData?.pending_to_delete;
12326
+
11137
12327
  // XU-ATTRS
11138
- if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
12328
+ if (nodeAttrs['xu-attrs'] || nodeAttrs['xu-exp:xu-attrs']) {
11139
12329
  const attr = 'xu-attrs';
11140
- let ret = await func.UI.screen.execute_xu_functions(
11141
- SESSION_ID,
11142
- is_skeleton,
11143
- $root_container,
11144
- nodeP,
11145
- $container,
11146
- paramsP,
11147
- parent_infoP,
11148
- jobNoP,
11149
- keyP,
11150
- parent_nodeP,
11151
- attr,
11152
- $elm,
11153
- {
11154
- key: attr,
11155
- value: await get_attr_value(attr),
11156
- },
11157
- is_init,
11158
- );
12330
+ 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);
11159
12331
  }
11160
12332
 
11161
12333
  // BEFORE
11162
- if (!_.isEmpty(nodeP.attributes)) {
11163
- for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
11164
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
11165
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
11166
- continue;
11167
- }
11168
-
11169
- if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
11170
- continue;
11171
- }
12334
+ if (!_.isEmpty(nodeAttrs)) {
12335
+ for (const [key, attr] of Object.entries(glb.run_xu_before)) {
12336
+ if (shouldAbort()) break;
12337
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
11172
12338
 
11173
- if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
11174
- continue;
11175
- }
11176
-
11177
- let ret = await func.UI.screen.execute_xu_functions(
11178
- SESSION_ID,
11179
- is_skeleton,
11180
- $root_container,
11181
- nodeP,
11182
- $container,
11183
- paramsP,
11184
- parent_infoP,
11185
- jobNoP,
11186
- keyP,
11187
- parent_nodeP,
11188
- attr,
11189
- $elm,
11190
- {
11191
- key: attr,
12339
+ const expKey = `xu-exp:${attr}`;
12340
+ if (!nodeAttrs.hasOwnProperty(attr) && !nodeAttrs.hasOwnProperty(expKey)) continue;
12341
+ if (!nodeAttrs[expKey] && nodeAttrs.hasOwnProperty(attr) && func.UI.screen.fix_val_defaults(attr, nodeAttrs[attr]) === undefined) continue;
11192
12342
 
11193
- value: await get_attr_value(attr),
11194
- },
11195
- is_init,
11196
- );
11197
- _ret = _.assignIn(_ret, ret);
12343
+ 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);
12344
+ Object.assign(_ret, ret);
11198
12345
  }
11199
12346
  }
11200
12347
 
11201
- // ALL
12348
+ // ALL - Process attributes
12349
+ const isXuPanel = nodeP.tagName === 'xu-panel';
12350
+ const isXuTeleport = nodeP.tagName === 'xu-teleport';
12351
+ const elmElement = $elm.get(0);
11202
12352
 
11203
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
11204
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
11205
- if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
11206
- continue;
11207
- }
12353
+ for (const [key, val] of Object.entries(nodeAttrs)) {
12354
+ if (shouldAbort()) break;
12355
+ if (html5EventsSet.has(key) || executeAttrsSet.has(key)) continue;
11208
12356
 
11209
- const new_key = key.split(':')[0]; // break expression
11210
- if (
11211
- nodeP.tagName !== 'xu-panel' &&
11212
- nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
11213
- (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
11214
- ) {
11215
- // handle common html attributes
12357
+ const colonIndex = key.indexOf(':');
12358
+ const new_key = colonIndex > -1 ? key.slice(0, colonIndex) : key;
12359
+
12360
+ if (!isXuPanel && !isXuTeleport && (!new_key.startsWith('xu-') || new_key.length < 3 || new_key[2] !== '-')) {
11216
12361
  try {
11217
- $elm.get(0).setAttribute(key, val);
12362
+ elmElement.setAttribute(key, val);
11218
12363
  } catch (err) {
11219
12364
  console.error(err.message);
11220
12365
  }
11221
-
11222
12366
  continue;
11223
12367
  }
11224
- // handle xu attributes
11225
- try {
11226
- if ($elm?.data()?.xuAttributes) {
11227
- // in some cases xu data delete in purpose when refreshing the screen
11228
- $elm.data().xuAttributes[key] = val;
11229
- }
11230
- } catch (error) {
11231
- debugger;
11232
- console.error(error);
12368
+
12369
+ // Store xu attributes
12370
+ if (elmData.xuAttributes) {
12371
+ elmData.xuAttributes[key] = val;
11233
12372
  }
11234
12373
 
11235
- 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)) {
12374
+ const expKey = `xu-exp:${new_key}`;
12375
+ if (new_key === 'xu-exp' || nodeAttrs[expKey] || runXuBeforeSet.has(new_key) || runXuAfterSet.has(new_key)) {
11236
12376
  continue;
11237
12377
  }
11238
12378
 
11239
12379
  if (new_key === 'xu-on') {
11240
- let ret = await func.UI.screen.execute_xu_functions(
11241
- SESSION_ID,
11242
- is_skeleton,
11243
- $root_container,
11244
- nodeP,
11245
- $container,
11246
- paramsP,
11247
- parent_infoP,
11248
- jobNoP,
11249
- keyP,
11250
- parent_nodeP,
11251
- 'xu-on',
11252
- $elm,
11253
- {
11254
- key: key,
11255
- // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
11256
- value: await get_attr_value(key),
11257
- },
11258
- is_init,
11259
- refreshed_ds,
11260
- );
11261
- _ret = _.assignIn(_ret, ret);
12380
+ 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);
12381
+ Object.assign(_ret, ret);
11262
12382
  continue;
11263
12383
  }
11264
12384
 
11265
- let ret = await func.UI.screen.execute_xu_functions(
11266
- SESSION_ID,
11267
- is_skeleton,
11268
- $root_container,
11269
- nodeP,
11270
- $container,
11271
- paramsP,
11272
- parent_infoP,
11273
- jobNoP,
11274
- keyP,
11275
- parent_nodeP,
11276
- new_key,
11277
- $elm,
11278
- {
11279
- key: key,
11280
- // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
11281
- value: await get_attr_value(key),
11282
- },
11283
- is_init,
11284
- refreshed_ds,
11285
- );
11286
-
11287
- _ret = _.assignIn(_ret, ret);
12385
+ 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);
12386
+ Object.assign(_ret, ret);
11288
12387
  }
11289
12388
 
11290
- // EXP for
11291
-
11292
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
11293
- if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
11294
-
11295
- const attr = key.split('xu-exp:')[1];
12389
+ // EXP - Process expressions
12390
+ for (const [key, val] of Object.entries(nodeAttrs)) {
12391
+ if (shouldAbort()) break;
11296
12392
 
11297
- if (!attr) {
11298
- continue;
11299
- }
12393
+ if (!key.startsWith('xu-exp:')) continue;
12394
+ const attr = key.slice(7);
11300
12395
 
11301
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
12396
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
12397
+ if (done_exp.has(key)) continue;
11302
12398
 
11303
- if (done_exp.includes(key)) {
11304
- continue;
11305
- }
11306
- let ret = await func.UI.screen.execute_xu_functions(
11307
- SESSION_ID,
11308
- is_skeleton,
11309
- $root_container,
11310
- nodeP,
11311
- $container,
11312
- paramsP,
11313
- parent_infoP,
11314
- jobNoP,
11315
- keyP,
11316
- parent_nodeP,
11317
- 'xu-exp',
11318
- $elm,
11319
- {
11320
- key: attr,
11321
- value: val,
11322
- },
11323
- true,
11324
- refreshed_ds,
11325
- );
11326
- _ret = _.assignIn(_ret, ret);
12399
+ 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);
12400
+ Object.assign(_ret, ret);
11327
12401
  }
11328
12402
 
11329
12403
  // AFTER
12404
+ for (const [key, attr] of Object.entries(glb.run_xu_after)) {
12405
+ if (containerXuData?.pending_to_delete) break;
12406
+ if (html5EventsSet.has(attr) || executeAttrsSet.has(attr)) continue;
11330
12407
 
11331
- for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
11332
- if ($container?.data()?.xuData?.pending_to_delete) break;
11333
-
11334
- if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
12408
+ const expKey = `xu-exp:${attr}`;
12409
+ if (!nodeAttrs || (!nodeAttrs[attr] && !nodeAttrs[expKey])) continue;
11335
12410
 
11336
- if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
11337
-
11338
- let ret = await func.UI.screen.execute_xu_functions(
11339
- SESSION_ID,
11340
- is_skeleton,
11341
- $root_container,
11342
- nodeP,
11343
- $container,
11344
- paramsP,
11345
- parent_infoP,
11346
- jobNoP,
11347
- keyP,
11348
- parent_nodeP,
11349
- attr,
11350
- $elm,
11351
- {
11352
- key: attr,
11353
- // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
11354
- value: await get_attr_value(attr),
11355
- },
11356
- is_init,
11357
- refreshed_ds,
11358
- );
11359
- _ret = _.assignIn(_ret, ret);
12411
+ 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);
12412
+ Object.assign(_ret, ret);
11360
12413
  }
11361
12414
 
11362
12415
  // REGISTER EVENTS ATTRIBUTES
12416
+ for (const [key, val] of Object.entries(nodeAttrs)) {
12417
+ if (containerXuData?.pending_to_delete) break;
12418
+ if (!html5EventsSet.has(key)) break;
11363
12419
 
11364
- for await (const [key, val] of Object.entries(nodeP.attributes)) {
11365
- if ($container?.data()?.xuData?.pending_to_delete) break;
11366
- if (!glb.html5_events_handler.includes(key)) break;
11367
- // $elm.attr(key, await get_xuExp(key)) || val;
11368
- $elm.attr(key, await get_xuExp(key)) || val;
12420
+ const expVal = await get_xuExp(key);
12421
+ $elm.attr(key, expVal || val);
11369
12422
  }
11370
12423
 
11371
12424
  return _ret;