@xuda.io/runtime-bundle 1.0.1412 → 1.0.1413
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.
- package/js/xuda-runtime-bundle.js +12443 -7109
- package/js/xuda-runtime-bundle.min.js +1 -1
- package/js/xuda-runtime-slim.js +9645 -4311
- package/js/xuda-runtime-slim.min.es.js +411 -94
- package/js/xuda-runtime-slim.min.js +2 -2
- package/js/xuda-server-bundle.min.mjs +1 -1
- package/js/xuda-server-bundle.mjs +24 -3
- package/js/xuda-worker-bundle.js +24 -3
- package/js/xuda-worker-bundle.min.js +1 -1
- package/package.json +1 -1
|
@@ -4282,6 +4282,23 @@ func.datasource.execute = async function (SESSION_ID, dataSourceSession, IS_DATA
|
|
|
4282
4282
|
let prog_obj = await func.utils.VIEWS_OBJ.get(SESSION_ID, _ds.prog_id);
|
|
4283
4283
|
|
|
4284
4284
|
const callback_datasource = async function () {
|
|
4285
|
+
const run_on_load_events = async function () {
|
|
4286
|
+
if (!(await func.datasource.get_view_events_count(SESSION_ID, dataSourceSession, 'on_load'))) {
|
|
4287
|
+
return false;
|
|
4288
|
+
}
|
|
4289
|
+
await func.datasource.execute_view_events(SESSION_ID, dataSourceSession, 'on_load');
|
|
4290
|
+
return true;
|
|
4291
|
+
};
|
|
4292
|
+
const schedule_panel_on_load_events = function () {
|
|
4293
|
+
setTimeout(async function () {
|
|
4294
|
+
try {
|
|
4295
|
+
await run_on_load_events();
|
|
4296
|
+
} catch (error) {
|
|
4297
|
+
console.error(error);
|
|
4298
|
+
}
|
|
4299
|
+
}, 0);
|
|
4300
|
+
};
|
|
4301
|
+
|
|
4285
4302
|
if (typeof IS_WORKER === 'undefined' && typeof IS_DOCKER === 'undefined' && typeof IS_PROCESS_SERVER === 'undefined' && _ds.viewSourceProp === 'globals') {
|
|
4286
4303
|
if (!['main'].includes(_session.opt.app_computing_mode)) {
|
|
4287
4304
|
await func.index.call_worker(SESSION_ID, {
|
|
@@ -4291,10 +4308,13 @@ func.datasource.execute = async function (SESSION_ID, dataSourceSession, IS_DATA
|
|
|
4291
4308
|
}
|
|
4292
4309
|
}
|
|
4293
4310
|
|
|
4294
|
-
if (
|
|
4295
|
-
await func.datasource.
|
|
4311
|
+
if (args.is_panelP) {
|
|
4312
|
+
const callback_ret = await func.datasource.callback(SESSION_ID, dataSourceSession, args.rowIdP, args.jobNoP, _ds.prog_id);
|
|
4313
|
+
schedule_panel_on_load_events();
|
|
4314
|
+
return callback_ret;
|
|
4296
4315
|
}
|
|
4297
|
-
|
|
4316
|
+
|
|
4317
|
+
await run_on_load_events();
|
|
4298
4318
|
return await func.datasource.callback(SESSION_ID, dataSourceSession, args.rowIdP, args.jobNoP, _ds.prog_id);
|
|
4299
4319
|
};
|
|
4300
4320
|
|
|
@@ -5832,6 +5852,7 @@ func.datasource.update = async function (SESSION_ID, datasource_changes, update_
|
|
|
5832
5852
|
dsSession_changed: findMin(datasource_changed),
|
|
5833
5853
|
avoid_xu_for_refresh,
|
|
5834
5854
|
trigger,
|
|
5855
|
+
ignore_screen_blocker: true,
|
|
5835
5856
|
});
|
|
5836
5857
|
// await removed from the below function cause to dead lock Mar 3 25
|
|
5837
5858
|
await func.runtime.ui.refresh_screen({
|
|
@@ -10131,7 +10152,7 @@ func.UI.utils.get_panels_wrapper_from_dom = async function (SESSION_ID, $xu_embe
|
|
|
10131
10152
|
const panel_keys = Object.keys(refresh_state?.panel_wrappers_cache || {});
|
|
10132
10153
|
for (let index = 0; index < panel_keys.length; index++) {
|
|
10133
10154
|
const panel_entry = refresh_state.panel_wrappers_cache[panel_keys[index]];
|
|
10134
|
-
if (
|
|
10155
|
+
if (!panel_entry?.$panel_div?.length || !panel_entry.$panel_div[0]?.isConnected) {
|
|
10135
10156
|
requires_rebuild = true;
|
|
10136
10157
|
break;
|
|
10137
10158
|
}
|
|
@@ -10584,15 +10605,52 @@ func.UI.worker.init = async function (SESSION_ID) {
|
|
|
10584
10605
|
return elementBottom > viewportTop && elementTop < viewportBottom;
|
|
10585
10606
|
};
|
|
10586
10607
|
|
|
10587
|
-
|
|
10588
|
-
|
|
10589
|
-
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10608
|
+
if (!UI_WORKER_OBJ.in_flight_job_elements) {
|
|
10609
|
+
UI_WORKER_OBJ.in_flight_job_elements = [];
|
|
10610
|
+
}
|
|
10611
|
+
|
|
10612
|
+
const contains_job_element = function ($parent, $child) {
|
|
10613
|
+
const parent_node = $parent?.[0];
|
|
10614
|
+
const child_node = $child?.[0];
|
|
10615
|
+
if (!parent_node || !child_node) {
|
|
10616
|
+
return false;
|
|
10617
|
+
}
|
|
10618
|
+
return parent_node.contains(child_node);
|
|
10619
|
+
};
|
|
10620
|
+
|
|
10621
|
+
// Cancel in-flight child jobs when a parent element is being removed/hidden.
|
|
10622
|
+
// This prevents orphaned jobs whose DOM elements no longer exist.
|
|
10623
|
+
func.UI.worker.cancel_child_in_flight_jobs = function ($parent_element) {
|
|
10624
|
+
if (!$parent_element?.length || !UI_WORKER_OBJ.in_flight_job_elements.length) return;
|
|
10625
|
+
const parent_node = $parent_element[0];
|
|
10626
|
+
if (!parent_node) return;
|
|
10627
|
+
for (let i = UI_WORKER_OBJ.in_flight_job_elements.length - 1; i >= 0; i--) {
|
|
10628
|
+
const child_el = UI_WORKER_OBJ.in_flight_job_elements[i];
|
|
10629
|
+
const child_node = child_el?.[0];
|
|
10630
|
+
if (child_node && parent_node.contains(child_node)) {
|
|
10631
|
+
UI_WORKER_OBJ.in_flight_job_elements.splice(i, 1);
|
|
10593
10632
|
}
|
|
10594
|
-
|
|
10595
|
-
|
|
10633
|
+
}
|
|
10634
|
+
};
|
|
10635
|
+
|
|
10636
|
+
const overlaps_any_in_flight = function (job) {
|
|
10637
|
+
if (!job?.elementP) {
|
|
10638
|
+
return false;
|
|
10639
|
+
}
|
|
10640
|
+
for (let index = 0; index < UI_WORKER_OBJ.in_flight_job_elements.length; index++) {
|
|
10641
|
+
const active_el = UI_WORKER_OBJ.in_flight_job_elements[index];
|
|
10642
|
+
if (!active_el) continue;
|
|
10643
|
+
// Block only when the new job is a CHILD of an in-flight element.
|
|
10644
|
+
// If the new job is a PARENT of an in-flight element, allow it to run
|
|
10645
|
+
// (e.g. xu-render hiding a container while a child panel's on_load is still running).
|
|
10646
|
+
if (contains_job_element(active_el, job.elementP)) {
|
|
10647
|
+
return true;
|
|
10648
|
+
}
|
|
10649
|
+
}
|
|
10650
|
+
return false;
|
|
10651
|
+
};
|
|
10652
|
+
|
|
10653
|
+
const job_iterator = async function (run_mode = 'data') {
|
|
10596
10654
|
const mark_pending_delete_on_descendants = function ($element) {
|
|
10597
10655
|
if (!$element?.length) {
|
|
10598
10656
|
return;
|
|
@@ -10611,6 +10669,7 @@ func.UI.worker.init = async function (SESSION_ID) {
|
|
|
10611
10669
|
};
|
|
10612
10670
|
const dom_job_budget = run_mode === 'dom' ? UI_WORKER_OBJ.dom_jobs_per_frame : Number.POSITIVE_INFINITY;
|
|
10613
10671
|
let dom_jobs_processed = 0;
|
|
10672
|
+
const dispatched_jobs = [];
|
|
10614
10673
|
|
|
10615
10674
|
if (UI_WORKER_OBJ.active_jobs_count) {
|
|
10616
10675
|
func.UI.worker.idle = 0;
|
|
@@ -10624,9 +10683,15 @@ func.UI.worker.init = async function (SESSION_ID) {
|
|
|
10624
10683
|
|
|
10625
10684
|
if (run_mode === 'data' && job_lane !== 'data') continue;
|
|
10626
10685
|
if (job_lane === 'dom' && dom_jobs_processed >= dom_job_budget) continue;
|
|
10686
|
+
// skip jobs whose element overlaps with any currently in-flight job (parent/child)
|
|
10687
|
+
// sibling containers can run in parallel
|
|
10688
|
+
if (overlaps_any_in_flight(val)) continue;
|
|
10627
10689
|
|
|
10628
10690
|
if (!val.elementP) {
|
|
10629
|
-
|
|
10691
|
+
const job_promise = func.UI.worker.execute(val.SESSION_ID, val).catch(function (err) {
|
|
10692
|
+
console.error(err);
|
|
10693
|
+
});
|
|
10694
|
+
dispatched_jobs.push(job_promise);
|
|
10630
10695
|
if (job_lane === 'dom') {
|
|
10631
10696
|
dom_jobs_processed++;
|
|
10632
10697
|
}
|
|
@@ -10646,67 +10711,48 @@ func.UI.worker.init = async function (SESSION_ID) {
|
|
|
10646
10711
|
continue;
|
|
10647
10712
|
}
|
|
10648
10713
|
|
|
10649
|
-
//
|
|
10714
|
+
// keep overlapping parent/child jobs serialized; siblings can run in-flight together
|
|
10650
10715
|
if (contains_job_element(val.elementP, running_job_obj.elementP)) {
|
|
10651
|
-
|
|
10652
|
-
mark_pending_delete_on_descendants(val.elementP);
|
|
10653
|
-
func.UI.worker.mark_pending_delete_session(SESSION_ID);
|
|
10654
|
-
await func.UI.worker.delete_job(SESSION_ID, running_job_obj.job_num);
|
|
10655
|
-
break;
|
|
10656
|
-
}
|
|
10716
|
+
continue;
|
|
10657
10717
|
}
|
|
10658
10718
|
}
|
|
10659
10719
|
|
|
10660
|
-
//
|
|
10661
|
-
|
|
10720
|
+
// Track this element as in-flight so future schedule_run passes skip overlapping jobs
|
|
10721
|
+
const in_flight_entry = val.elementP;
|
|
10722
|
+
UI_WORKER_OBJ.in_flight_job_elements.push(in_flight_entry);
|
|
10723
|
+
|
|
10724
|
+
// execute siblings/non-overlapping jobs — fire and forget, re-trigger scheduler on completion
|
|
10725
|
+
const job_promise = func.UI.worker.execute(val.SESSION_ID, val).catch(function (err) {
|
|
10726
|
+
console.error(err);
|
|
10727
|
+
}).finally(function () {
|
|
10728
|
+
// remove this element from in-flight tracking
|
|
10729
|
+
const idx = UI_WORKER_OBJ.in_flight_job_elements.indexOf(in_flight_entry);
|
|
10730
|
+
if (idx !== -1) {
|
|
10731
|
+
UI_WORKER_OBJ.in_flight_job_elements.splice(idx, 1);
|
|
10732
|
+
}
|
|
10733
|
+
// re-trigger scheduler so blocked sibling jobs can now run
|
|
10734
|
+
func.UI.worker.schedule_run(0);
|
|
10735
|
+
});
|
|
10736
|
+
dispatched_jobs.push(job_promise);
|
|
10662
10737
|
if (job_lane === 'dom') {
|
|
10663
10738
|
dom_jobs_processed++;
|
|
10664
10739
|
}
|
|
10665
10740
|
continue;
|
|
10666
|
-
|
|
10667
|
-
// active_job_children_elements = [];
|
|
10668
|
-
// if (val.elementP) {
|
|
10669
|
-
// // get active_job children elements only if job handle ui job (not update)
|
|
10670
|
-
// $.each(val.elementP.find('*'), function (key, val) {
|
|
10671
|
-
// const xu_ui_id = val.elementP.attr('xu-ui-id');
|
|
10672
|
-
// if (!xu_ui_id) return true;
|
|
10673
|
-
// active_job_children_elements.push(xu_ui_id);
|
|
10674
|
-
// });
|
|
10675
|
-
// func.UI.worker.execute(val.SESSION_ID, val);
|
|
10676
|
-
// continue;
|
|
10677
|
-
// } else {
|
|
10678
|
-
// // non ui job
|
|
10679
|
-
// await func.UI.worker.execute(val.SESSION_ID, val);
|
|
10680
|
-
// break;
|
|
10681
|
-
// }
|
|
10682
|
-
|
|
10683
|
-
// if (UI_WORKER_OBJ.jobs.length > 1 && val.elementP) {
|
|
10684
|
-
// const xu_ui_id = val.elementP.attr('xu-ui-id');
|
|
10685
|
-
// if (!xu_ui_id) continue;
|
|
10686
|
-
// // skip - if job element exist in the active job ui as child element
|
|
10687
|
-
// if (active_job_children_elements.includes(xu_ui_id)) {
|
|
10688
|
-
// continue;
|
|
10689
|
-
// }
|
|
10690
|
-
// // abort - if active job element exist in the current job ui (parent element changed)
|
|
10691
|
-
// $.each(val.elementP.find('*'), function (key, val) {
|
|
10692
|
-
// const xu_ui_id = val.elementP.attr('xu-ui-id');
|
|
10693
|
-
// if (!xu_ui_id) return true;
|
|
10694
|
-
// active_job_children_elements.push(xu_ui_id);
|
|
10695
|
-
// });
|
|
10696
|
-
// // execute - if active job element not exist the current job ui and not detected as parent element
|
|
10697
|
-
// const active_job = UI_WORKER_OBJ.jobs[0];
|
|
10698
|
-
// }
|
|
10699
|
-
|
|
10700
|
-
// break;
|
|
10701
10741
|
} catch (err) {
|
|
10702
10742
|
console.error(err);
|
|
10703
10743
|
}
|
|
10704
10744
|
}
|
|
10745
|
+
|
|
10746
|
+
// Only await jobs that have no element (data jobs) — don't block on long-running UI jobs
|
|
10747
|
+
// UI jobs with elements will re-trigger schedule_run when they complete
|
|
10705
10748
|
}
|
|
10706
10749
|
};
|
|
10707
10750
|
func.UI.worker.schedule_run = function (delay = 0, preferred_mode) {
|
|
10708
10751
|
func.UI.worker.ensure_runtime_indexes();
|
|
10709
10752
|
if (UI_WORKER_OBJ.run_in_progress) {
|
|
10753
|
+
// Allow re-entry: even though a scan is in progress, mark run_again
|
|
10754
|
+
// so the scheduler re-scans after the current pass. This lets sibling
|
|
10755
|
+
// jobs that were queued after the scan started get picked up quickly.
|
|
10710
10756
|
UI_WORKER_OBJ.run_again = true;
|
|
10711
10757
|
return;
|
|
10712
10758
|
}
|
|
@@ -10952,8 +10998,69 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
10952
10998
|
}
|
|
10953
10999
|
return $root.find(`[xu-ui-id="${xu_ui_id}"]`);
|
|
10954
11000
|
},
|
|
10955
|
-
get_live_element_context: function (elem_key, fallback_$elm) {
|
|
10956
|
-
|
|
11001
|
+
get_live_element_context: function (elem_key, fallback_$elm, context = {}) {
|
|
11002
|
+
let raw_$elm = elem_key ? fx.get_element_by_ui_id(elem_key) : fallback_$elm;
|
|
11003
|
+
let $elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(raw_$elm) : raw_$elm;
|
|
11004
|
+
|
|
11005
|
+
if (context.node_id) {
|
|
11006
|
+
const $root = func.UI.worker.get_session_root(SESSION_ID);
|
|
11007
|
+
const runtime_nodes = func.runtime?.ui?.get_refresh_index_elements
|
|
11008
|
+
? func.runtime.ui.get_refresh_index_elements(SESSION_ID, $root).toArray()
|
|
11009
|
+
: $root.find('[xu-ui-id]').toArray();
|
|
11010
|
+
let matching_nodes = [];
|
|
11011
|
+
|
|
11012
|
+
for (let index = 0; index < runtime_nodes.length; index++) {
|
|
11013
|
+
const node = runtime_nodes[index];
|
|
11014
|
+
const node_data = func.runtime.ui.get_data(node);
|
|
11015
|
+
const node_xu_data = node_data?.xuData;
|
|
11016
|
+
if (!node_xu_data) {
|
|
11017
|
+
continue;
|
|
11018
|
+
}
|
|
11019
|
+
if (node_xu_data.nodeid !== context.node_id) {
|
|
11020
|
+
continue;
|
|
11021
|
+
}
|
|
11022
|
+
if (context.recordid && node_xu_data.recordid !== context.recordid) {
|
|
11023
|
+
continue;
|
|
11024
|
+
}
|
|
11025
|
+
if (context.prog_id && node_xu_data.paramsP?.prog_id !== context.prog_id) {
|
|
11026
|
+
continue;
|
|
11027
|
+
}
|
|
11028
|
+
if (context.parent_element_ui_id && node_xu_data.parent_element_ui_id !== context.parent_element_ui_id) {
|
|
11029
|
+
continue;
|
|
11030
|
+
}
|
|
11031
|
+
if (node_xu_data.pending_to_delete) {
|
|
11032
|
+
continue;
|
|
11033
|
+
}
|
|
11034
|
+
matching_nodes.push(node);
|
|
11035
|
+
}
|
|
11036
|
+
|
|
11037
|
+
if (!matching_nodes.length) {
|
|
11038
|
+
for (let index = 0; index < runtime_nodes.length; index++) {
|
|
11039
|
+
const node = runtime_nodes[index];
|
|
11040
|
+
const node_data = func.runtime.ui.get_data(node);
|
|
11041
|
+
const node_xu_data = node_data?.xuData;
|
|
11042
|
+
if (!node_xu_data) {
|
|
11043
|
+
continue;
|
|
11044
|
+
}
|
|
11045
|
+
if (node_xu_data.nodeid !== context.node_id) {
|
|
11046
|
+
continue;
|
|
11047
|
+
}
|
|
11048
|
+
if (context.recordid && node_xu_data.recordid !== context.recordid) {
|
|
11049
|
+
continue;
|
|
11050
|
+
}
|
|
11051
|
+
if (node_xu_data.pending_to_delete) {
|
|
11052
|
+
continue;
|
|
11053
|
+
}
|
|
11054
|
+
matching_nodes.push(node);
|
|
11055
|
+
}
|
|
11056
|
+
}
|
|
11057
|
+
|
|
11058
|
+
if (matching_nodes.length) {
|
|
11059
|
+
raw_$elm = $(matching_nodes);
|
|
11060
|
+
$elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(raw_$elm) : raw_$elm;
|
|
11061
|
+
}
|
|
11062
|
+
}
|
|
11063
|
+
|
|
10957
11064
|
if (!$elm?.length) {
|
|
10958
11065
|
return {
|
|
10959
11066
|
$elm: $(),
|
|
@@ -11008,6 +11115,13 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11008
11115
|
'xu-for': true,
|
|
11009
11116
|
'xu-exp:xu-bind': true,
|
|
11010
11117
|
};
|
|
11118
|
+
const raw_value_attributes = {
|
|
11119
|
+
'xu-bind': true,
|
|
11120
|
+
'xu-ref': true,
|
|
11121
|
+
'xu-on': true,
|
|
11122
|
+
'xu-for-key': true,
|
|
11123
|
+
'xu-for-val': true,
|
|
11124
|
+
};
|
|
11011
11125
|
|
|
11012
11126
|
const execution_plan = [];
|
|
11013
11127
|
for (let index = 0; index < (refresh_attributes || []).length; index++) {
|
|
@@ -11023,7 +11137,7 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11023
11137
|
attr_new,
|
|
11024
11138
|
xu_func,
|
|
11025
11139
|
is_regular_attribute: !!(attr_new && attr_new.substr(0, 2) !== 'xu'),
|
|
11026
|
-
requires_expression: attr !== 'xu-class' && attr !== 'xu-ui-plugin',
|
|
11140
|
+
requires_expression: !raw_value_attributes[attr] && attr !== 'xu-class' && attr !== 'xu-ui-plugin',
|
|
11027
11141
|
regular_attr_name: attr_new ? (attr_new !== 'viewBox' ? attr_new.toLowerCase() : attr_new) : null,
|
|
11028
11142
|
});
|
|
11029
11143
|
}
|
|
@@ -11099,23 +11213,26 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11099
11213
|
},
|
|
11100
11214
|
execute_xu_render_attributes: async function () {
|
|
11101
11215
|
const perf_end = func.runtime?.perf?.start?.(SESSION_ID, 'execute_xu_render_attributes');
|
|
11102
|
-
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj.paramsP?.elem_val?.$elm);
|
|
11216
|
+
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj.paramsP?.elem_val?.$elm, queue_obj.paramsP);
|
|
11103
11217
|
const _data = live_context.data;
|
|
11218
|
+
console.log('[xu-render EXEC]', { attr_value: queue_obj.paramsP.attr_value, has_data: !!_data?.xuData?.paramsP, elem_key: queue_obj.paramsP?.elem_key, tagName: live_context.$elm?.[0]?.tagName, elm_length: live_context.$elm?.length });
|
|
11104
11219
|
try {
|
|
11105
11220
|
if (_data?.xuData?.paramsP) {
|
|
11221
|
+
const live_xu_data = _data.xuData;
|
|
11106
11222
|
await func.runtime.render.execute_xu_function({
|
|
11107
11223
|
SESSION_ID,
|
|
11108
11224
|
is_skeleton: null,
|
|
11109
|
-
$root_container:
|
|
11110
|
-
nodeP:
|
|
11111
|
-
$container: fx.get_element_by_ui_id(
|
|
11112
|
-
paramsP:
|
|
11113
|
-
parent_infoP: {},
|
|
11225
|
+
$root_container: live_xu_data.$root_container,
|
|
11226
|
+
nodeP: live_xu_data.node,
|
|
11227
|
+
$container: fx.get_element_by_ui_id(live_xu_data.parent_element_ui_id) || live_xu_data.$container,
|
|
11228
|
+
paramsP: live_xu_data.paramsP,
|
|
11229
|
+
parent_infoP: live_xu_data.iterate_info ? { iterate_info: live_xu_data.iterate_info } : {},
|
|
11114
11230
|
jobNoP: queue_obj.jobNoP,
|
|
11115
|
-
keyP:
|
|
11116
|
-
parent_nodeP:
|
|
11231
|
+
keyP: live_xu_data.key,
|
|
11232
|
+
parent_nodeP: live_xu_data.parent_node,
|
|
11117
11233
|
xu_func: 'xu-render',
|
|
11118
11234
|
$elm: live_context.$elm,
|
|
11235
|
+
$live_elm: live_context.$elm,
|
|
11119
11236
|
val: {
|
|
11120
11237
|
key: 'xu-render',
|
|
11121
11238
|
value: queue_obj.paramsP.attr_value,
|
|
@@ -11138,7 +11255,7 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11138
11255
|
};
|
|
11139
11256
|
|
|
11140
11257
|
try {
|
|
11141
|
-
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj.paramsP?.elem_val?.$elm);
|
|
11258
|
+
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj.paramsP?.elem_val?.$elm, queue_obj.paramsP);
|
|
11142
11259
|
const $elm = live_context.$elm;
|
|
11143
11260
|
const live_data = live_context.data;
|
|
11144
11261
|
const elm_node = $elm?.[0];
|
|
@@ -11151,18 +11268,20 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11151
11268
|
const refresh_attributes = queue_obj.paramsP?.elem_val?.attributes || [];
|
|
11152
11269
|
const execution_plan = fx.get_refresh_execution_plan(live_data, refresh_attributes);
|
|
11153
11270
|
const expression_results_cache = {};
|
|
11271
|
+
const live_parent_container = fx.get_element_by_ui_id(live_xu_data.parent_element_ui_id);
|
|
11154
11272
|
const xu_execution_context = {
|
|
11155
11273
|
SESSION_ID,
|
|
11156
11274
|
is_skeleton: null,
|
|
11157
11275
|
$root_container: live_xu_data.$root_container,
|
|
11158
11276
|
nodeP: live_xu_data.node,
|
|
11159
|
-
$container: live_xu_data.$container,
|
|
11277
|
+
$container: live_parent_container?.length ? live_parent_container : live_xu_data.$container,
|
|
11160
11278
|
paramsP: live_xu_data.paramsP,
|
|
11161
|
-
parent_infoP: {},
|
|
11279
|
+
parent_infoP: live_xu_data.iterate_info ? { iterate_info: live_xu_data.iterate_info } : {},
|
|
11162
11280
|
jobNoP: queue_obj.jobNoP,
|
|
11163
|
-
keyP:
|
|
11164
|
-
parent_nodeP:
|
|
11281
|
+
keyP: live_xu_data.key,
|
|
11282
|
+
parent_nodeP: live_xu_data.parent_node,
|
|
11165
11283
|
$elm,
|
|
11284
|
+
$live_elm: $elm,
|
|
11166
11285
|
get_params_obj_new: func.runtime.program.get_params_obj,
|
|
11167
11286
|
};
|
|
11168
11287
|
const handler_bundle = func.runtime.render.build_xu_handlers(xu_execution_context, SESSION_OBJ[SESSION_ID].DS_GLB[live_xu_data.paramsP.dsSessionP]);
|
|
@@ -11217,7 +11336,7 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11217
11336
|
execute_xu_for: async function () {
|
|
11218
11337
|
const perf_end = func.runtime?.perf?.start?.(SESSION_ID, 'execute_xu_for');
|
|
11219
11338
|
try {
|
|
11220
|
-
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj?.paramsP?.elem_val?.$elm);
|
|
11339
|
+
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj?.paramsP?.elem_val?.$elm, queue_obj.paramsP);
|
|
11221
11340
|
var $elm = live_context.$elm; // $(SESSION_OBJ[SESSION_ID].root_element).find(`[xu-ui-id=${queue_obj.paramsP.elem_key}]`)
|
|
11222
11341
|
|
|
11223
11342
|
if (!$elm?.length) {
|
|
@@ -11294,7 +11413,7 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11294
11413
|
},
|
|
11295
11414
|
execute_xu_widget: async function () {
|
|
11296
11415
|
try {
|
|
11297
|
-
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj?.paramsP?.elem_val?.$elm);
|
|
11416
|
+
const live_context = fx.get_live_element_context(queue_obj.paramsP?.elem_key, queue_obj.elementP || queue_obj?.paramsP?.elem_val?.$elm, queue_obj.paramsP);
|
|
11298
11417
|
var $elm = live_context.$elm; // $(SESSION_OBJ[SESSION_ID].root_element).find(`[xu-ui-id=${queue_obj.paramsP.elem_key}]`)
|
|
11299
11418
|
|
|
11300
11419
|
if (!$elm?.length) {
|
|
@@ -11323,7 +11442,16 @@ func.UI.worker.execute = async function (SESSION_ID, queue_obj) {
|
|
|
11323
11442
|
},
|
|
11324
11443
|
};
|
|
11325
11444
|
|
|
11326
|
-
|
|
11445
|
+
try {
|
|
11446
|
+
return await fx[queue_obj.functionP]();
|
|
11447
|
+
} catch (error) {
|
|
11448
|
+
console.error(error);
|
|
11449
|
+
const failed_job_index = func.UI.worker.find_job_index(SESSION_ID, queue_obj.job_num);
|
|
11450
|
+
if (failed_job_index !== null && typeof failed_job_index !== 'undefined' && UI_WORKER_OBJ.jobs[failed_job_index]) {
|
|
11451
|
+
await func.UI.worker.delete_job(SESSION_ID, queue_obj.job_num);
|
|
11452
|
+
}
|
|
11453
|
+
return null;
|
|
11454
|
+
}
|
|
11327
11455
|
};
|
|
11328
11456
|
func.UI.worker.find_job_index = function (SESSION_ID, jobNoP) {
|
|
11329
11457
|
var ret = null;
|
|
@@ -13509,6 +13637,41 @@ func.runtime.ui.find_refresh_elements_by_attr = function ($root, attr_name, attr
|
|
|
13509
13637
|
|
|
13510
13638
|
return $(elements);
|
|
13511
13639
|
};
|
|
13640
|
+
func.runtime.ui.get_preferred_live_element = function (target) {
|
|
13641
|
+
const elements = func.runtime.ui.as_jquery(target).toArray();
|
|
13642
|
+
if (!elements.length) {
|
|
13643
|
+
return $();
|
|
13644
|
+
}
|
|
13645
|
+
|
|
13646
|
+
let best_node = null;
|
|
13647
|
+
let best_score = -Infinity;
|
|
13648
|
+
for (let index = 0; index < elements.length; index++) {
|
|
13649
|
+
const node = elements[index];
|
|
13650
|
+
if (!node) {
|
|
13651
|
+
continue;
|
|
13652
|
+
}
|
|
13653
|
+
const node_data = func.runtime.ui.get_data(node);
|
|
13654
|
+
let score = 0;
|
|
13655
|
+
if (node.isConnected) {
|
|
13656
|
+
score += 100;
|
|
13657
|
+
}
|
|
13658
|
+
if (!node_data?.xuData?.pending_to_delete) {
|
|
13659
|
+
score += 50;
|
|
13660
|
+
}
|
|
13661
|
+
if (node.getClientRects?.().length) {
|
|
13662
|
+
score += 25;
|
|
13663
|
+
}
|
|
13664
|
+
if (!node.hidden) {
|
|
13665
|
+
score += 10;
|
|
13666
|
+
}
|
|
13667
|
+
if (score >= best_score) {
|
|
13668
|
+
best_score = score;
|
|
13669
|
+
best_node = node;
|
|
13670
|
+
}
|
|
13671
|
+
}
|
|
13672
|
+
|
|
13673
|
+
return best_node ? $(best_node) : $(elements[elements.length - 1]);
|
|
13674
|
+
};
|
|
13512
13675
|
func.runtime.ui.get_refresh_indexed_element_by_ui_id = function (SESSION_ID, selector_id) {
|
|
13513
13676
|
const state = func.runtime.ui.ensure_refresh_dependency_state(SESSION_ID);
|
|
13514
13677
|
if (!state) {
|
|
@@ -13519,12 +13682,14 @@ func.runtime.ui.get_refresh_indexed_element_by_ui_id = function (SESSION_ID, sel
|
|
|
13519
13682
|
}
|
|
13520
13683
|
|
|
13521
13684
|
let $elm = state.elements_by_ui_id?.[selector_id];
|
|
13685
|
+
$elm = func.runtime.ui.get_preferred_live_element($elm);
|
|
13522
13686
|
if ($elm?.length && $elm[0]?.isConnected) {
|
|
13687
|
+
state.elements_by_ui_id[selector_id] = $elm;
|
|
13523
13688
|
return $elm;
|
|
13524
13689
|
}
|
|
13525
13690
|
|
|
13526
13691
|
const $root = func.runtime.ui.get_refresh_index_root(SESSION_ID);
|
|
13527
|
-
$elm = func.runtime.ui.find_refresh_elements_by_attr($root, 'xu-ui-id', selector_id
|
|
13692
|
+
$elm = func.runtime.ui.get_preferred_live_element(func.runtime.ui.find_refresh_elements_by_attr($root, 'xu-ui-id', selector_id));
|
|
13528
13693
|
if ($elm?.length) {
|
|
13529
13694
|
state.elements_by_ui_id[selector_id] = $elm;
|
|
13530
13695
|
state.runtime_elements_cache = null;
|
|
@@ -13628,12 +13793,14 @@ func.runtime.ui.get_refresh_indexed_panel_wrapper_by_id = function (SESSION_ID,
|
|
|
13628
13793
|
}
|
|
13629
13794
|
|
|
13630
13795
|
let $elm = state.panel_wrappers_by_id?.[wrapper_id];
|
|
13796
|
+
$elm = func.runtime.ui.get_preferred_live_element($elm);
|
|
13631
13797
|
if ($elm?.length && $elm[0]?.isConnected) {
|
|
13798
|
+
state.panel_wrappers_by_id[wrapper_id] = $elm;
|
|
13632
13799
|
return $elm;
|
|
13633
13800
|
}
|
|
13634
13801
|
|
|
13635
13802
|
const $root = func.runtime.ui.get_refresh_index_root(SESSION_ID);
|
|
13636
|
-
$elm = func.runtime.ui.find_refresh_elements_by_attr($root, 'xu-panel-wrapper-id', wrapper_id
|
|
13803
|
+
$elm = func.runtime.ui.get_preferred_live_element(func.runtime.ui.find_refresh_elements_by_attr($root, 'xu-panel-wrapper-id', wrapper_id));
|
|
13637
13804
|
if ($elm?.length) {
|
|
13638
13805
|
state.panel_wrappers_by_id[wrapper_id] = $elm;
|
|
13639
13806
|
state.panel_wrapper_elements_cache = null;
|
|
@@ -13865,6 +14032,10 @@ func.runtime.ui.build_refresh_job_obj = function (options, elem_key, elem_val, e
|
|
|
13865
14032
|
SESSION_ID: options.SESSION_ID,
|
|
13866
14033
|
fields_arr: options.fields_arr,
|
|
13867
14034
|
elem_key,
|
|
14035
|
+
node_id: elm_data?.xuData?.nodeid,
|
|
14036
|
+
recordid: elm_data?.xuData?.recordid,
|
|
14037
|
+
parent_element_ui_id: elm_data?.xuData?.parent_element_ui_id,
|
|
14038
|
+
prog_id: elm_data?.xuData?.paramsP?.prog_id,
|
|
13868
14039
|
elem_val: {
|
|
13869
14040
|
attributes: [...(elem_val.attributes || [])],
|
|
13870
14041
|
},
|
|
@@ -14189,7 +14360,7 @@ func.runtime.render = func.runtime.render || {};
|
|
|
14189
14360
|
// Browser-only xu-attribute refresh helpers live here so screen refresh orchestration can stay focused.
|
|
14190
14361
|
|
|
14191
14362
|
func.runtime.ui.refresh_xu_attributes = async function (options) {
|
|
14192
|
-
if (options.trigger !== 'click' && !_.isEmpty(SCREEN_BLOCKER_OBJ)) {
|
|
14363
|
+
if (!options.ignore_screen_blocker && options.trigger !== 'click' && !_.isEmpty(SCREEN_BLOCKER_OBJ)) {
|
|
14193
14364
|
setTimeout(() => {
|
|
14194
14365
|
func.runtime.ui.refresh_xu_attributes(options);
|
|
14195
14366
|
}, 100);
|
|
@@ -16710,11 +16881,19 @@ func.runtime.render.handle_xu_ref = async function (options) {
|
|
|
16710
16881
|
func.runtime.render.handle_xu_bind = async function (options) {
|
|
16711
16882
|
if (options.is_skeleton) return {};
|
|
16712
16883
|
|
|
16713
|
-
const
|
|
16884
|
+
const $elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(options.$elm) : func.runtime.ui.as_jquery(options.$elm);
|
|
16885
|
+
const elm_data = func.runtime.ui.get_data($elm);
|
|
16714
16886
|
const xuData = elm_data?.xuData;
|
|
16887
|
+
const bind_expression =
|
|
16888
|
+
typeof options?.val?.value === 'string'
|
|
16889
|
+
? options.val.value
|
|
16890
|
+
: elm_data?.xuAttributes?.['xu-bind'] || func.runtime.ui.get_attr($elm, 'xu-bind');
|
|
16715
16891
|
if (!xuData?.paramsP) {
|
|
16716
16892
|
return {};
|
|
16717
16893
|
}
|
|
16894
|
+
if (!bind_expression) {
|
|
16895
|
+
return {};
|
|
16896
|
+
}
|
|
16718
16897
|
|
|
16719
16898
|
let val_is_reference_field = false;
|
|
16720
16899
|
let _prog_id = xuData.paramsP.prog_id;
|
|
@@ -16722,10 +16901,94 @@ func.runtime.render.handle_xu_bind = async function (options) {
|
|
|
16722
16901
|
let is_dynamic_field = false;
|
|
16723
16902
|
let field_prop;
|
|
16724
16903
|
let bind_field_id;
|
|
16725
|
-
const input_field_type =
|
|
16904
|
+
const input_field_type = $elm?.[0]?.type || func.runtime.ui.get_attr($elm, 'type');
|
|
16905
|
+
const bind_ui_id = xuData.ui_id || func.runtime.ui.get_attr($elm, 'xu-ui-id');
|
|
16906
|
+
const get_bind_targets = function () {
|
|
16907
|
+
const $root = func.runtime.ui.get_refresh_index_root?.(options.SESSION_ID) || func.runtime.ui.get_root_element?.(options.SESSION_ID) || $('body');
|
|
16908
|
+
const live_targets = [];
|
|
16909
|
+
const seen_nodes = new Set();
|
|
16910
|
+
const add_candidate = function (node) {
|
|
16911
|
+
if (!node || seen_nodes.has(node)) {
|
|
16912
|
+
return;
|
|
16913
|
+
}
|
|
16914
|
+
const target_data = func.runtime.ui.get_data(node);
|
|
16915
|
+
if (!node.isConnected || target_data?.xuData?.pending_to_delete) {
|
|
16916
|
+
return;
|
|
16917
|
+
}
|
|
16918
|
+
seen_nodes.add(node);
|
|
16919
|
+
live_targets.push(node);
|
|
16920
|
+
};
|
|
16921
|
+
|
|
16922
|
+
if (bind_ui_id && options.SESSION_ID && func.runtime?.ui?.find_refresh_elements_by_attr) {
|
|
16923
|
+
const ui_id_targets = func.runtime.ui.find_refresh_elements_by_attr($root, 'xu-ui-id', bind_ui_id).toArray();
|
|
16924
|
+
for (let index = 0; index < ui_id_targets.length; index++) {
|
|
16925
|
+
add_candidate(ui_id_targets[index]);
|
|
16926
|
+
}
|
|
16927
|
+
}
|
|
16928
|
+
|
|
16929
|
+
const runtime_nodes = func.runtime?.ui?.get_refresh_index_elements
|
|
16930
|
+
? func.runtime.ui.get_refresh_index_elements(options.SESSION_ID, $root).toArray()
|
|
16931
|
+
: $root.find('[xu-ui-id]').toArray();
|
|
16932
|
+
const target_parent_ui_id = xuData.parent_element_ui_id;
|
|
16933
|
+
const target_node_id = xuData.nodeid;
|
|
16934
|
+
const target_recordid = xuData.recordid;
|
|
16935
|
+
const target_prog_id = xuData.paramsP?.prog_id;
|
|
16936
|
+
for (let index = 0; index < runtime_nodes.length; index++) {
|
|
16937
|
+
const node = runtime_nodes[index];
|
|
16938
|
+
const node_data = func.runtime.ui.get_data(node);
|
|
16939
|
+
const node_xu_data = node_data?.xuData;
|
|
16940
|
+
if (!node_xu_data) {
|
|
16941
|
+
continue;
|
|
16942
|
+
}
|
|
16943
|
+
if (target_node_id && node_xu_data.nodeid !== target_node_id) {
|
|
16944
|
+
continue;
|
|
16945
|
+
}
|
|
16946
|
+
if (target_parent_ui_id && node_xu_data.parent_element_ui_id !== target_parent_ui_id) {
|
|
16947
|
+
continue;
|
|
16948
|
+
}
|
|
16949
|
+
if (target_prog_id && node_xu_data.paramsP?.prog_id !== target_prog_id) {
|
|
16950
|
+
continue;
|
|
16951
|
+
}
|
|
16952
|
+
if (typeof target_recordid !== 'undefined' && target_recordid !== null && node_xu_data.recordid !== target_recordid) {
|
|
16953
|
+
continue;
|
|
16954
|
+
}
|
|
16955
|
+
const node_bind_expression = node_data?.xuAttributes?.['xu-bind'] || func.runtime.ui.get_attr(node, 'xu-bind');
|
|
16956
|
+
if (node_bind_expression !== bind_expression) {
|
|
16957
|
+
continue;
|
|
16958
|
+
}
|
|
16959
|
+
add_candidate(node);
|
|
16960
|
+
}
|
|
16961
|
+
|
|
16962
|
+
if (!live_targets.length) {
|
|
16963
|
+
return $elm;
|
|
16964
|
+
}
|
|
16965
|
+
|
|
16966
|
+
for (let index = 0; index < live_targets.length; index++) {
|
|
16967
|
+
const node = live_targets[index];
|
|
16968
|
+
const target_data = func.runtime.ui.get_data(node);
|
|
16969
|
+
if (!node?.isConnected || target_data?.xuData?.pending_to_delete) {
|
|
16970
|
+
continue;
|
|
16971
|
+
}
|
|
16972
|
+
add_candidate(node);
|
|
16973
|
+
}
|
|
16974
|
+
|
|
16975
|
+
if (!live_targets.length) {
|
|
16976
|
+
return $elm;
|
|
16977
|
+
}
|
|
16978
|
+
|
|
16979
|
+
const target_nodes = live_targets;
|
|
16980
|
+
const visible_targets = [];
|
|
16981
|
+
for (let index = 0; index < target_nodes.length; index++) {
|
|
16982
|
+
const node = target_nodes[index];
|
|
16983
|
+
if (node.getClientRects?.().length && !node.hidden) {
|
|
16984
|
+
visible_targets.push(node);
|
|
16985
|
+
}
|
|
16986
|
+
}
|
|
16987
|
+
return $(visible_targets.length ? visible_targets : live_targets);
|
|
16988
|
+
};
|
|
16726
16989
|
|
|
16727
16990
|
try {
|
|
16728
|
-
const bind_field = await func.runtime.bind.resolve_field(options.SESSION_ID, _prog_id, _dsP,
|
|
16991
|
+
const bind_field = await func.runtime.bind.resolve_field(options.SESSION_ID, _prog_id, _dsP, bind_expression.split('.')[0]);
|
|
16729
16992
|
bind_field_id = bind_field.bind_field_id;
|
|
16730
16993
|
field_prop = bind_field.field_prop;
|
|
16731
16994
|
is_dynamic_field = bind_field.is_dynamic_field;
|
|
@@ -16774,38 +17037,80 @@ func.runtime.render.handle_xu_bind = async function (options) {
|
|
|
16774
17037
|
field_prop,
|
|
16775
17038
|
val_is_reference_field,
|
|
16776
17039
|
input_field_type,
|
|
16777
|
-
expression_value:
|
|
17040
|
+
expression_value: bind_expression,
|
|
16778
17041
|
value,
|
|
16779
17042
|
});
|
|
16780
17043
|
|
|
16781
17044
|
await func.datasource.update_changes_for_out_parameter(options.SESSION_ID, _dsP, _ds.parentDataSourceNo);
|
|
16782
17045
|
};
|
|
16783
17046
|
|
|
16784
|
-
|
|
17047
|
+
const bind_targets = get_bind_targets();
|
|
17048
|
+
const target_nodes = bind_targets.toArray();
|
|
17049
|
+
for (let index = 0; index < target_nodes.length; index++) {
|
|
17050
|
+
const target = target_nodes[index];
|
|
17051
|
+
const target_data = func.runtime.ui.get_data(target);
|
|
17052
|
+
if (!target_data?.xuData || target_data.xuData.bind_listener_attached) {
|
|
17053
|
+
continue;
|
|
17054
|
+
}
|
|
17055
|
+
bind.listener(target, field_changed);
|
|
17056
|
+
target_data.xuData.bind_listener_attached = true;
|
|
17057
|
+
}
|
|
16785
17058
|
|
|
16786
|
-
const set_value = function () {
|
|
16787
|
-
const _ds = SESSION_OBJ[options.SESSION_ID].DS_GLB[
|
|
16788
|
-
if (!_ds
|
|
17059
|
+
const set_value = async function () {
|
|
17060
|
+
const _ds = SESSION_OBJ[options.SESSION_ID].DS_GLB[_dsP];
|
|
17061
|
+
if (!_ds) return;
|
|
17062
|
+
const target_record_id = xuData.recordid || _ds.currentRecordId;
|
|
17063
|
+
if (!target_record_id) return;
|
|
16789
17064
|
let value;
|
|
16790
17065
|
try {
|
|
16791
17066
|
if (val_is_reference_field) {
|
|
16792
|
-
|
|
16793
|
-
|
|
17067
|
+
const resolved_value = await func.datasource.get_value(options.SESSION_ID, bind_field_id, _dsP, target_record_id);
|
|
17068
|
+
if (resolved_value?.found) {
|
|
17069
|
+
value = resolved_value.ret.value;
|
|
17070
|
+
} else {
|
|
17071
|
+
value = func.runtime.bind.get_source_value(_ds, bind_field_id, is_dynamic_field);
|
|
17072
|
+
}
|
|
17073
|
+
value = func.runtime.bind.format_display_value($elm, field_prop, bind_field_id, bind_expression, value, input_field_type);
|
|
16794
17074
|
} else {
|
|
16795
|
-
value =
|
|
17075
|
+
value = bind_expression;
|
|
16796
17076
|
}
|
|
16797
17077
|
if (typeof value === 'undefined') return;
|
|
16798
|
-
|
|
17078
|
+
|
|
17079
|
+
const live_bind_targets = get_bind_targets().toArray();
|
|
17080
|
+
for (let index = 0; index < live_bind_targets.length; index++) {
|
|
17081
|
+
const elm = live_bind_targets[index];
|
|
17082
|
+
if (!elm) {
|
|
17083
|
+
continue;
|
|
17084
|
+
}
|
|
17085
|
+
|
|
17086
|
+
bind.setter(elm, value);
|
|
17087
|
+
const target_input_type = elm.type || input_field_type;
|
|
17088
|
+
switch (target_input_type) {
|
|
17089
|
+
case 'radio':
|
|
17090
|
+
elm.checked = elm.value === _.toString(value);
|
|
17091
|
+
break;
|
|
17092
|
+
case 'checkbox':
|
|
17093
|
+
elm.checked = !!value;
|
|
17094
|
+
break;
|
|
17095
|
+
default:
|
|
17096
|
+
if (typeof elm.value !== 'undefined') {
|
|
17097
|
+
elm.value = value === null ? '' : _.toString(value);
|
|
17098
|
+
}
|
|
17099
|
+
break;
|
|
17100
|
+
}
|
|
17101
|
+
}
|
|
16799
17102
|
} catch (err) {
|
|
16800
17103
|
console.error(err);
|
|
16801
17104
|
}
|
|
16802
17105
|
};
|
|
16803
17106
|
|
|
16804
|
-
|
|
16805
|
-
|
|
17107
|
+
const bind_refresh_event = 'xu-bind-refresh.' + _dsP.toString();
|
|
17108
|
+
const bind_refresh_namespace = `.ui${bind_ui_id || bind_field_id || 'bind'}`;
|
|
17109
|
+
$('body').off(bind_refresh_namespace).on(bind_refresh_event + bind_refresh_namespace, async () => {
|
|
17110
|
+
await set_value();
|
|
16806
17111
|
});
|
|
16807
17112
|
|
|
16808
|
-
set_value();
|
|
17113
|
+
await set_value();
|
|
16809
17114
|
return {};
|
|
16810
17115
|
};
|
|
16811
17116
|
func.runtime.render.apply_xu_class = async function (options) {
|
|
@@ -17163,12 +17468,24 @@ func.runtime.render.handle_modern_xu_render = async function (options) {
|
|
|
17163
17468
|
}
|
|
17164
17469
|
|
|
17165
17470
|
func.runtime.render.insert_ordered_child(options.$container, new_$div, options.keyP);
|
|
17471
|
+
// Remove the XURENDER placeholder now that the real content has been inserted.
|
|
17472
|
+
if (options.$elm?.[0]?.tagName === 'XURENDER') {
|
|
17473
|
+
func.runtime.ui.remove(options.$elm);
|
|
17474
|
+
}
|
|
17166
17475
|
} catch (error) {
|
|
17476
|
+
console.error('[xu-render post_render ERROR]', error, { keyP: options.keyP, container_tag: options.$container?.[0]?.tagName, has_node: !!nodeP, xu_ui_id: func.runtime.ui.get_attr(options.$elm, 'xu-ui-id') });
|
|
17167
17477
|
func.events.delete_job(options.SESSION_ID, options.jobNoP);
|
|
17168
17478
|
}
|
|
17169
17479
|
return;
|
|
17170
17480
|
}
|
|
17171
17481
|
|
|
17482
|
+
// Cancel any in-flight child jobs before removing the element.
|
|
17483
|
+
// This prevents orphaned jobs (e.g. a child panel's long-running on_load delay)
|
|
17484
|
+
// from blocking future scheduler passes after the parent element is gone.
|
|
17485
|
+
if (func.UI?.worker?.cancel_child_in_flight_jobs) {
|
|
17486
|
+
func.UI.worker.cancel_child_in_flight_jobs(options.$elm);
|
|
17487
|
+
}
|
|
17488
|
+
|
|
17172
17489
|
const xu_ui_id = func.runtime.ui.get_attr(options.$elm, 'xu-ui-id');
|
|
17173
17490
|
const exclude_fields = func.runtime.render.get_xu_render_exclude_fields(options.$elm);
|
|
17174
17491
|
const cache_str = await func.runtime.render.get_xu_render_cache_str(
|