@xuda.io/runtime-bundle 1.0.1249 → 1.0.1251

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2675,27 +2675,40 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
2675
2675
  });
2676
2676
  };
2677
2677
 
2678
- func.common.sha256 = async function (inputString) {
2679
- // 1. Create a hash buffer from the input string using SHA-256.
2680
- // This part remains the same as it provides a strong, unique cryptographic starting point.
2681
- const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputString));
2682
-
2683
- // 2. Interpret the first 8 bytes (64 bits) of the hash as one big number.
2684
- const view = new DataView(buffer);
2685
- const bigInt = view.getBigUint64(0, false); // `false` for big-endian
2686
-
2687
- // 3. Convert the BigInt to a Base36 string.
2688
- // The .toString(36) method handles the conversion to an alphanumeric representation (0-9, a-z).
2689
- const base36Hash = bigInt.toString(36);
2690
-
2691
- // 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
2692
- // For a 64-bit integer, the Base36 representation will be about 13 characters long,
2693
- // so slicing is a reliable way to get a fixed length.
2694
- const shortHash = base36Hash.slice(0, 10);
2695
-
2696
- // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
2697
- // This ensures the output is always exactly 10 characters long.
2698
- return shortHash.padStart(10, '0');
2678
+ // func.common.sha256 = async function (inputString) {
2679
+ // // 1. Create a hash buffer from the input string using SHA-256.
2680
+ // // This part remains the same as it provides a strong, unique cryptographic starting point.
2681
+ // const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputString));
2682
+
2683
+ // // 2. Interpret the first 8 bytes (64 bits) of the hash as one big number.
2684
+ // const view = new DataView(buffer);
2685
+ // const bigInt = view.getBigUint64(0, false); // `false` for big-endian
2686
+
2687
+ // // 3. Convert the BigInt to a Base36 string.
2688
+ // // The .toString(36) method handles the conversion to an alphanumeric representation (0-9, a-z).
2689
+ // const base36Hash = bigInt.toString(36);
2690
+
2691
+ // // 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
2692
+ // // For a 64-bit integer, the Base36 representation will be about 13 characters long,
2693
+ // // so slicing is a reliable way to get a fixed length.
2694
+ // const shortHash = base36Hash.slice(0, 10);
2695
+
2696
+ // // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
2697
+ // // This ensures the output is always exactly 10 characters long.
2698
+ // return shortHash.padStart(10, '0');
2699
+ // };
2700
+
2701
+ func.common.fastHash = function (inputString) {
2702
+ let hash = 0x811c9dc5; // FNV offset basis
2703
+
2704
+ for (let i = 0; i < inputString.length; i++) {
2705
+ hash ^= inputString.charCodeAt(i);
2706
+ // FNV prime multiplication with 32-bit overflow
2707
+ hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
2708
+ }
2709
+
2710
+ // Convert to base36 and pad to 10 characters
2711
+ return ((hash >>> 0).toString(36) + '0000000000').slice(0, 10);
2699
2712
  };
2700
2713
 
2701
2714
  glb.new_xu_render = false;
@@ -12481,162 +12494,312 @@ func.UI.screen.panel_post_render_handler = async function (
12481
12494
  return jobNoP;
12482
12495
  };
12483
12496
 
12497
+ // const generate_xu_ui_id = async function (SESSION_ID, nodeP, $container, paramsP, keyP) {
12498
+ // // const _paramsP = _.cloneDeep(paramsP);
12499
+ // const _paramsP = klona.klona(paramsP);
12500
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
12501
+
12502
+ // const currentRecordId = $container?.data?.()?.xuData?.recordid || (_ds ? _ds.currentRecordId : '');
12503
+ // const key_path = `${$container?.data()?.xuData?.key_path || '0'}-${keyP || '0'}`;
12504
+ // const elem_key = `${nodeP.xu_tree_id || nodeP.id}-${key_path}-${currentRecordId}`;
12505
+ // let ui_id = `${nodeP.id}-${elem_key}-${_paramsP?.dsSessionP?.toString() || ''}`; //nodeP.xu_tree_id ||
12506
+
12507
+ // const new_ui_id = await func.common.sha256(ui_id);
12508
+ // return new_ui_id;
12509
+ // };
12510
+
12484
12511
  const generate_xu_ui_id = async function (SESSION_ID, nodeP, $container, paramsP, keyP) {
12485
- // const _paramsP = _.cloneDeep(paramsP);
12486
- const _paramsP = klona.klona(paramsP);
12487
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
12512
+ // Avoid cloning if we only need dsSessionP
12513
+ const dsSessionP = paramsP.dsSessionP;
12514
+ const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];
12515
+
12516
+ // Cache container data access
12517
+ const containerXuData = $container?.data?.()?.xuData;
12518
+ const currentRecordId = containerXuData?.recordid || _ds?.currentRecordId || '';
12488
12519
 
12489
- const currentRecordId = $container?.data?.()?.xuData?.recordid || (_ds ? _ds.currentRecordId : '');
12490
- const key_path = `${$container?.data()?.xuData?.key_path || '0'}-${keyP || '0'}`;
12491
- const elem_key = `${nodeP.xu_tree_id || nodeP.id}-${key_path}-${currentRecordId}`;
12492
- let ui_id = `${nodeP.id}-${elem_key}-${_paramsP?.dsSessionP?.toString() || ''}`; //nodeP.xu_tree_id ||
12520
+ // Build strings efficiently
12521
+ const key_path = `${containerXuData?.key_path || '0'}-${keyP || '0'}`;
12522
+ const nodeId = nodeP.xu_tree_id || nodeP.id;
12523
+ const elem_key = `${nodeId}-${key_path}-${currentRecordId}`;
12524
+ const ui_id = `${nodeP.id}-${elem_key}-${dsSessionP?.toString() || ''}`;
12493
12525
 
12494
- const new_ui_id = await func.common.sha256(ui_id);
12495
- return new_ui_id;
12526
+ return await func.common.fastHash(ui_id);
12496
12527
  };
12497
12528
 
12529
+ // func.UI.screen.create_container = async function (SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, classP, elem_propP, div_typeP, $appendToP, attr_str, is_placeholder) {
12530
+ // // const _paramsP = _.cloneDeep(paramsP);
12531
+ // const _paramsP = klona.klona(paramsP);
12532
+ // var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
12533
+ // var $appendTo = $container;
12534
+ // if ($appendToP) $appendTo = $appendToP;
12535
+ // if (!$appendTo || !$appendTo.length) return null; // screen closed or not exist abort build
12536
+ // var div = 'div';
12537
+ // if (div_typeP) div = div_typeP;
12538
+ // var items = [];
12539
+ // if (nodeP.children)
12540
+ // items = nodeP.children.map(function (val) {
12541
+ // return val.xu_tree_id || val.id;
12542
+ // });
12543
+ // var currentRecordId = $container?.data?.()?.xuData?.recordid || (_ds ? _ds.currentRecordId : '');
12544
+ // // var xu_id = (glb.screen_num++).toString();
12545
+ // // xu_id = xu_id += '_' + currentRecordId;
12546
+
12547
+ // try {
12548
+ // const key_path = `${$container?.data()?.xuData?.key_path || '0'}-${keyP || '0'}`;
12549
+ // const elem_key = `${nodeP.xu_tree_id || nodeP.id}-${key_path}-${currentRecordId}`;
12550
+ // // let ui_id = `${nodeP.id}-${elem_key}-${_paramsP?.dsSessionP?.toString() || ''}`; //nodeP.xu_tree_id ||
12551
+
12552
+ // /////////////////////////////////
12553
+
12554
+ // var $div;
12555
+
12556
+ // if (div === 'svg') {
12557
+ // const draw_svg = function (element) {
12558
+ // const get_tag_str = function (element, prop, val) {
12559
+ // let class_str = '';
12560
+ // let attr_str = '';
12561
+ // for (const [key, val] of Object.entries(prop)) {
12562
+ // if (key.substr(0, 2) !== 'xu') {
12563
+ // attr_str += ` ${key}="${val}" `;
12564
+ // }
12565
+ // }
12566
+ // if (element === 'svg') {
12567
+ // return `<${element} ${attr_str} > `;
12568
+ // }
12569
+ // let ret = '';
12570
+ // if (val?.children?.length) {
12571
+ // ret = iterate_svg(val);
12572
+ // }
12573
+
12574
+ // return `<${element} ${class_str} ${attr_str} > ${ret} </${element}>`;
12575
+ // };
12576
+ // let svg_str = get_tag_str(element, prop);
12577
+ // let inner_str = '';
12578
+ // const iterate_svg = function (node) {
12579
+ // let ret = '';
12580
+ // if (node.children) {
12581
+ // for (let val of node.children) {
12582
+ // let prop = val.attributes;
12583
+ // ret += get_tag_str(val.tagName, prop, val);
12584
+ // }
12585
+ // }
12586
+ // return ret;
12587
+ // };
12588
+ // inner_str = iterate_svg(nodeP);
12589
+
12590
+ // $div = $(svg_str + inner_str + '</svg>').appendTo($appendTo);
12591
+ // };
12592
+
12593
+ // draw_svg(div_typeP);
12594
+ // } else {
12595
+ // $div = $(`<${div} ${attr_str ? attr_str : ''}>`);
12596
+ // }
12597
+
12598
+ // // // Returns a 32-bit unsigned integer hash of a string (FNV-1a)
12599
+ // // function hash32(str) {
12600
+ // // let h = 0x811c9dc5; // FNV offset basis
12601
+ // // for (let i = 0; i < str.length; i++) {
12602
+ // // h ^= str.charCodeAt(i);
12603
+ // // // multiply by FNV prime (2^24 + 2^8 + 0x93) with 32-bit overflow
12604
+ // // h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
12605
+ // // }
12606
+ // // // Convert to unsigned 32-bit
12607
+ // // return h >>> 0;
12608
+ // // }
12609
+
12610
+ // // function hash32hex(str) {
12611
+ // // return (hash32(str) >>> 0).toString(16).padStart(8, '0');
12612
+ // // }
12613
+
12614
+ // // const new_ui_id = hash32hex(ui_id);
12615
+ // // const new_ui_id = await func.common.sha256(ui_id);
12616
+ // const new_ui_id = await generate_xu_ui_id(SESSION_ID, nodeP, $container, paramsP, keyP);
12617
+
12618
+ // $div
12619
+ // .attr('xu-ui-id', new_ui_id)
12620
+ // // .attr('xu-node-id', nodeP.id)
12621
+ // .data({
12622
+ // xuData: {
12623
+ // prog_id: _paramsP.prog_id,
12624
+ // nodeid: nodeP.id,
12625
+ // ui_type: nodeP.tagName,
12626
+ // // xu_id,
12627
+ // recordid: currentRecordId,
12628
+ // paramsP: _paramsP,
12629
+ // key: keyP,
12630
+ // key_path, //:($container?.data()?.xuData?.key || "0") + "-" + (keyP || "0"),
12631
+ // screenId: _paramsP.screenId,
12632
+ // parent_container: $container?.attr('id'),
12633
+ // elem_key,
12634
+ // properties: prop,
12635
+ // node: nodeP,
12636
+ // node_org: _.cloneDeep(nodeP),
12637
+ // is_panelP: _paramsP.is_panelP,
12638
+ // ui_id: new_ui_id,
12639
+ // elem_prop: elem_propP,
12640
+ // debug_info: {
12641
+ // id: nodeP.id,
12642
+ // parent_id: $container?.data()?.xuData?.ui_id,
12643
+ // items: items,
12644
+ // },
12645
+ // parent_node: parent_nodeP,
12646
+ // currentRecordId: currentRecordId,
12647
+ // $root_container: $root_container,
12648
+ // parent_element_ui_id: $container?.data()?.xuData?.ui_id,
12649
+ // },
12650
+ // xuAttributes: {},
12651
+ // });
12652
+ // if (is_placeholder) {
12653
+ // $div.addClass('display_none');
12654
+ // }
12655
+
12656
+ // if (div_typeP !== 'svg') {
12657
+ // $div.appendTo($appendTo);
12658
+ // }
12659
+ // } catch (e) {
12660
+ // console.error(e);
12661
+ // }
12662
+
12663
+ // if (parent_infoP?.iterate_info) {
12664
+ // $div.data().xuData.iterate_info = parent_infoP.iterate_info;
12665
+ // }
12666
+
12667
+ // if (classP) $div.addClass(classP);
12668
+
12669
+ // return $div;
12670
+ // };
12671
+
12498
12672
  func.UI.screen.create_container = async function (SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, classP, elem_propP, div_typeP, $appendToP, attr_str, is_placeholder) {
12499
- // const _paramsP = _.cloneDeep(paramsP);
12500
12673
  const _paramsP = klona.klona(paramsP);
12501
- var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
12502
- var $appendTo = $container;
12503
- if ($appendToP) $appendTo = $appendToP;
12504
- if (!$appendTo || !$appendTo.length) return null; // screen closed or not exist abort build
12505
- var div = 'div';
12506
- if (div_typeP) div = div_typeP;
12507
- var items = [];
12508
- if (nodeP.children)
12509
- items = nodeP.children.map(function (val) {
12510
- return val.xu_tree_id || val.id;
12511
- });
12512
- var currentRecordId = $container?.data?.()?.xuData?.recordid || (_ds ? _ds.currentRecordId : '');
12513
- // var xu_id = (glb.screen_num++).toString();
12514
- // xu_id = xu_id += '_' + currentRecordId;
12674
+ const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
12675
+ const $appendTo = $appendToP || $container;
12676
+
12677
+ // Early exit if container doesn't exist
12678
+ if (!$appendTo?.length) return null;
12679
+
12680
+ const div = div_typeP || 'div';
12681
+
12682
+ // Cache container data to avoid repeated access
12683
+ const containerData = $container?.data?.();
12684
+ const containerXuData = containerData?.xuData;
12685
+ const currentRecordId = containerXuData?.recordid || (_ds ? _ds.currentRecordId : '');
12686
+
12687
+ // Pre-compute items array
12688
+ const items = nodeP.children ? nodeP.children.map((val) => val.xu_tree_id || val.id) : [];
12515
12689
 
12516
12690
  try {
12517
- const key_path = `${$container?.data()?.xuData?.key_path || '0'}-${keyP || '0'}`;
12691
+ const key_path = `${containerXuData?.key_path || '0'}-${keyP || '0'}`;
12518
12692
  const elem_key = `${nodeP.xu_tree_id || nodeP.id}-${key_path}-${currentRecordId}`;
12519
- // let ui_id = `${nodeP.id}-${elem_key}-${_paramsP?.dsSessionP?.toString() || ''}`; //nodeP.xu_tree_id ||
12520
12693
 
12521
- /////////////////////////////////
12522
-
12523
- var $div;
12694
+ let $div;
12524
12695
 
12696
+ // Handle SVG creation
12525
12697
  if (div === 'svg') {
12526
12698
  const draw_svg = function (element) {
12527
12699
  const get_tag_str = function (element, prop, val) {
12528
- let class_str = '';
12529
- let attr_str = '';
12530
- for (const [key, val] of Object.entries(prop)) {
12531
- if (key.substr(0, 2) !== 'xu') {
12532
- attr_str += ` ${key}="${val}" `;
12700
+ const attrs = [];
12701
+
12702
+ for (const [key, value] of Object.entries(prop)) {
12703
+ if (!key.startsWith('xu')) {
12704
+ attrs.push(`${key}="${value}"`);
12533
12705
  }
12534
12706
  }
12707
+
12708
+ const attr_str = attrs.join(' ');
12709
+
12535
12710
  if (element === 'svg') {
12536
- return `<${element} ${attr_str} > `;
12537
- }
12538
- let ret = '';
12539
- if (val?.children?.length) {
12540
- ret = iterate_svg(val);
12711
+ return `<${element} ${attr_str}>`;
12541
12712
  }
12542
12713
 
12543
- return `<${element} ${class_str} ${attr_str} > ${ret} </${element}>`;
12714
+ const inner = val?.children?.length ? iterate_svg(val) : '';
12715
+ return `<${element} ${attr_str}>${inner}</${element}>`;
12544
12716
  };
12545
- let svg_str = get_tag_str(element, prop);
12546
- let inner_str = '';
12717
+
12547
12718
  const iterate_svg = function (node) {
12548
- let ret = '';
12549
- if (node.children) {
12550
- for (let val of node.children) {
12551
- let prop = val.attributes;
12552
- ret += get_tag_str(val.tagName, prop, val);
12553
- }
12554
- }
12555
- return ret;
12719
+ if (!node.children) return '';
12720
+
12721
+ return node.children.map((val) => get_tag_str(val.tagName, val.attributes, val)).join('');
12556
12722
  };
12557
- inner_str = iterate_svg(nodeP);
12723
+
12724
+ const svg_str = get_tag_str(element, prop);
12725
+ const inner_str = iterate_svg(nodeP);
12558
12726
 
12559
12727
  $div = $(svg_str + inner_str + '</svg>').appendTo($appendTo);
12560
12728
  };
12561
12729
 
12562
12730
  draw_svg(div_typeP);
12563
12731
  } else {
12564
- $div = $(`<${div} ${attr_str ? attr_str : ''}>`);
12732
+ $div = $(`<${div}${attr_str ? ' ' + attr_str : ''}>`);
12565
12733
  }
12566
12734
 
12567
- // // Returns a 32-bit unsigned integer hash of a string (FNV-1a)
12568
- // function hash32(str) {
12569
- // let h = 0x811c9dc5; // FNV offset basis
12570
- // for (let i = 0; i < str.length; i++) {
12571
- // h ^= str.charCodeAt(i);
12572
- // // multiply by FNV prime (2^24 + 2^8 + 0x93) with 32-bit overflow
12573
- // h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
12574
- // }
12575
- // // Convert to unsigned 32-bit
12576
- // return h >>> 0;
12577
- // }
12735
+ // Generate UI ID
12736
+ const new_ui_id = await generate_xu_ui_id(SESSION_ID, nodeP, $container, paramsP, keyP);
12578
12737
 
12579
- // function hash32hex(str) {
12580
- // return (hash32(str) >>> 0).toString(16).padStart(8, '0');
12581
- // }
12738
+ // Set attributes and data in one go
12739
+ $div.attr('xu-ui-id', new_ui_id);
12740
+
12741
+ // Build xuData object efficiently
12742
+ const xuData = {
12743
+ prog_id: _paramsP.prog_id,
12744
+ nodeid: nodeP.id,
12745
+ ui_type: nodeP.tagName,
12746
+ recordid: currentRecordId,
12747
+ paramsP: _paramsP,
12748
+ key: keyP,
12749
+ key_path,
12750
+ screenId: _paramsP.screenId,
12751
+ parent_container: containerData?.id,
12752
+ elem_key,
12753
+ properties: prop,
12754
+ node: nodeP,
12755
+ node_org: _.cloneDeep(nodeP),
12756
+ is_panelP: _paramsP.is_panelP,
12757
+ ui_id: new_ui_id,
12758
+ elem_prop: elem_propP,
12759
+ debug_info: {
12760
+ id: nodeP.id,
12761
+ parent_id: containerXuData?.ui_id,
12762
+ items: items,
12763
+ },
12764
+ parent_node: parent_nodeP,
12765
+ currentRecordId: currentRecordId,
12766
+ $root_container: $root_container,
12767
+ parent_element_ui_id: containerXuData?.ui_id,
12768
+ };
12582
12769
 
12583
- // const new_ui_id = hash32hex(ui_id);
12584
- // const new_ui_id = await func.common.sha256(ui_id);
12585
- const new_ui_id = await generate_xu_ui_id(SESSION_ID, nodeP, $container, paramsP, keyP);
12770
+ // Add iterate_info if present
12771
+ if (parent_infoP?.iterate_info) {
12772
+ xuData.iterate_info = parent_infoP.iterate_info;
12773
+ }
12586
12774
 
12587
- $div
12588
- .attr('xu-ui-id', new_ui_id)
12589
- // .attr('xu-node-id', nodeP.id)
12590
- .data({
12591
- xuData: {
12592
- prog_id: _paramsP.prog_id,
12593
- nodeid: nodeP.id,
12594
- ui_type: nodeP.tagName,
12595
- // xu_id,
12596
- recordid: currentRecordId,
12597
- paramsP: _paramsP,
12598
- key: keyP,
12599
- key_path, //:($container?.data()?.xuData?.key || "0") + "-" + (keyP || "0"),
12600
- screenId: _paramsP.screenId,
12601
- parent_container: $container?.attr('id'),
12602
- elem_key,
12603
- properties: prop,
12604
- node: nodeP,
12605
- node_org: _.cloneDeep(nodeP),
12606
- is_panelP: _paramsP.is_panelP,
12607
- ui_id: new_ui_id,
12608
- elem_prop: elem_propP,
12609
- debug_info: {
12610
- id: nodeP.id,
12611
- parent_id: $container?.data()?.xuData?.ui_id,
12612
- items: items,
12613
- },
12614
- parent_node: parent_nodeP,
12615
- currentRecordId: currentRecordId,
12616
- $root_container: $root_container,
12617
- parent_element_ui_id: $container?.data()?.xuData?.ui_id,
12618
- },
12619
- xuAttributes: {},
12620
- });
12775
+ // Set data once
12776
+ $div.data({
12777
+ xuData: xuData,
12778
+ xuAttributes: {},
12779
+ });
12780
+
12781
+ // Apply placeholder class if needed
12621
12782
  if (is_placeholder) {
12622
12783
  $div.addClass('display_none');
12623
12784
  }
12624
12785
 
12786
+ // Apply custom class if provided
12787
+ if (classP) {
12788
+ $div.addClass(classP);
12789
+ }
12790
+
12791
+ // Append to DOM (only for non-SVG elements)
12625
12792
  if (div_typeP !== 'svg') {
12626
12793
  $div.appendTo($appendTo);
12627
12794
  }
12628
- } catch (e) {
12629
- console.error(e);
12630
- }
12631
12795
 
12632
- if (parent_infoP?.iterate_info) {
12633
- $div.data().xuData.iterate_info = parent_infoP.iterate_info;
12796
+ return $div;
12797
+ } catch (e) {
12798
+ console.error('create_container error:', e);
12799
+ return null;
12634
12800
  }
12635
-
12636
- if (classP) $div.addClass(classP);
12637
-
12638
- return $div;
12639
12801
  };
12802
+
12640
12803
  func.UI.screen.execute_screen_ready_events = async function (SESSION_ID, paramsP, sourceP, $div, jobNoP, $div_objP) {
12641
12804
  var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
12642
12805
  if (!_ds) return;