@yuneta/gobj-ui 7.26.34 → 7.26.36
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/README.md +223 -53
- package/dist/gobj-ui.cjs.js +1109 -143
- package/dist/gobj-ui.es.js +1109 -143
- package/package.json +2 -2
- package/scripts/validate-locales.mjs +672 -96
- package/src/c_yui_form.js +186 -9
- package/src/c_yui_gclass.js +2 -0
- package/src/c_yui_gobj_tree_js.js +2 -0
- package/src/c_yui_json.js +2 -0
- package/src/c_yui_json_graph.js +2 -0
- package/src/c_yui_nav.js +23 -5
- package/src/c_yui_shell.css +16 -0
- package/src/c_yui_shell.js +282 -26
- package/src/c_yui_treedb_graph.js +26 -8
- package/src/c_yui_treedb_topic_with_form.js +40 -18
- package/src/c_yui_treedb_topics.js +34 -11
- package/src/c_yui_window.js +132 -32
- package/src/c_yui_window_manager.js +250 -46
- package/src/form_json_editor_names.js +448 -0
- package/src/form_json_editor_names.wiring.test.js +595 -0
- package/src/form_label_i18n.wiring.test.js +169 -0
- package/src/i18n_key_functions.js +14 -6
- package/src/i18n_key_functions.test.js +124 -2
- package/src/lib_maplibre.js +26 -2
- package/src/lib_maplibre_relocalize.test.js +78 -0
- package/src/named_controls.wiring.test.js +468 -0
- package/src/nav_cards_helpers.js +9 -1
- package/src/nav_item_badge.wiring.test.js +182 -1
- package/src/shell_route_map.js +25 -8
- package/src/table_editor_name.wiring.test.js +201 -0
- package/src/treedb_column_title.wiring.test.js +151 -0
- package/src/treedb_json_drill.wiring.test.js +41 -1
- package/src/window_layer.wiring.test.js +348 -43
- package/src/window_show.wiring.test.js +6 -2
- package/src/window_stacking.wiring.test.js +334 -0
- package/src/yui_badge.js +58 -13
- package/src/yui_badge.test.js +40 -3
- package/src/yui_dev.js +2 -1
- package/src/yui_file_field.js +2 -0
- package/src/yui_frontend_view.js +2 -1
- package/src/yui_gclass_view.js +9 -6
- package/src/yui_tabulator_i18n.js +42 -0
- package/src/yui_tabulator_i18n.test.js +48 -1
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -545,14 +545,26 @@ function text_list_item_formatter(label) {
|
|
|
545
545
|
* ALWAYS RENDERED, hidden when empty, so the runtime setters have a
|
|
546
546
|
* node to write into and never rebuild the control that holds it.
|
|
547
547
|
*
|
|
548
|
-
*
|
|
549
|
-
* carries an explicit aria-label, and an explicit label
|
|
550
|
-
* the element's content for a screen reader -- so a badge
|
|
551
|
-
* it
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
548
|
+
* PART OF THE CONTROL'S NAME (name_control_with_badge()). The
|
|
549
|
+
* control carries an explicit aria-label, and an explicit label
|
|
550
|
+
* REPLACES the element's content for a screen reader -- so a badge
|
|
551
|
+
* inside it is silent, and inside a <button> (the toolbar, an
|
|
552
|
+
* accordion head) its children are not even in the tree. The
|
|
553
|
+
* control is labelled by ITSELF (its aria-label, which
|
|
554
|
+
* refresh_language() re-translates) and by the badge: the name is
|
|
555
|
+
* "Alarms 3" while there is a count, "Alarms" while there is none,
|
|
556
|
+
* with nothing composed in javascript that a language switch would
|
|
557
|
+
* leave behind.
|
|
558
|
+
*
|
|
559
|
+
* NOT a live region any more. Up to 7.26.34 the badge was its own
|
|
560
|
+
* role="status", and that said "3" with no word of what has three;
|
|
561
|
+
* hidden while empty, it was not in the tree when the first count
|
|
562
|
+
* arrived, so 0 -> 1 was most likely never said; and inside a
|
|
563
|
+
* <button> it was not there at all. The change is said by the
|
|
564
|
+
* shell, in one live region of its own that is always there, with
|
|
565
|
+
* the name of the item: "Alarms, 3" (yui_shell_set_nav_item_badge,
|
|
566
|
+
* yui_shell_set_toolbar_item_badge). A write that changes nothing
|
|
567
|
+
* still touches no DOM.
|
|
556
568
|
*
|
|
557
569
|
* A TONE, optional: one of BADGE_TONES, drawn as Bulma's
|
|
558
570
|
* `is-<tone>` on the badge. It says HOW BAD the count is -- the
|
|
@@ -578,6 +590,7 @@ var BADGE_TONES = Object.freeze([
|
|
|
578
590
|
"primary",
|
|
579
591
|
"link"
|
|
580
592
|
]);
|
|
593
|
+
var __badge_seq__ = 0;
|
|
581
594
|
/************************************************************
|
|
582
595
|
* The text a badge shows for `value`, "" when it shows none.
|
|
583
596
|
************************************************************/
|
|
@@ -611,10 +624,7 @@ function badge_tone(tone, who) {
|
|
|
611
624
|
function badge_node(value, tone, classes, who) {
|
|
612
625
|
let text = badge_text(value);
|
|
613
626
|
let known = badge_tone(tone, who);
|
|
614
|
-
let attrs = {
|
|
615
|
-
class: known ? `${classes} is-${known}` : classes,
|
|
616
|
-
role: "status"
|
|
617
|
-
};
|
|
627
|
+
let attrs = { class: known ? `${classes} is-${known}` : classes };
|
|
618
628
|
if (!text) attrs.hidden = "hidden";
|
|
619
629
|
return [
|
|
620
630
|
"span",
|
|
@@ -623,6 +633,31 @@ function badge_node(value, tone, classes, who) {
|
|
|
623
633
|
];
|
|
624
634
|
}
|
|
625
635
|
/************************************************************
|
|
636
|
+
* Make the count part of the NAME of the control that carries
|
|
637
|
+
* the badge: its `aria-labelledby` points at the control itself
|
|
638
|
+
* and at the badge.
|
|
639
|
+
*
|
|
640
|
+
* The control keeps its `aria-label` and its
|
|
641
|
+
* data-i18n-aria-label: a self-reference reads the aria-label,
|
|
642
|
+
* so the name is the translated label followed by the badge's
|
|
643
|
+
* text -- "Alarms 3" -- or the label alone while the badge is
|
|
644
|
+
* empty. A painted count is in the name at once, and a language
|
|
645
|
+
* switch re-translates the label as it always did.
|
|
646
|
+
*
|
|
647
|
+
* Both are createElement2() descriptions, before anything is
|
|
648
|
+
* built: `control_attrs` (the attrs of the <a> or <button>, which
|
|
649
|
+
* must carry its aria-label) gets an `id` when it has none, and
|
|
650
|
+
* the `aria-labelledby`; `badge` (what badge_node() answered)
|
|
651
|
+
* gets its `id`.
|
|
652
|
+
************************************************************/
|
|
653
|
+
function name_control_with_badge(control_attrs, badge) {
|
|
654
|
+
let seq = ++__badge_seq__;
|
|
655
|
+
if (!control_attrs.id) control_attrs.id = `yui-badged-${seq}`;
|
|
656
|
+
let badge_attrs = badge[1];
|
|
657
|
+
badge_attrs.id = `yui-badge-${seq}`;
|
|
658
|
+
control_attrs["aria-labelledby"] = `${control_attrs.id} ${badge_attrs.id}`;
|
|
659
|
+
}
|
|
660
|
+
/************************************************************
|
|
626
661
|
* Write a badge that is already in the DOM, as badge_node()
|
|
627
662
|
* draws it. `tone` is one badge_tone() answered: the setter
|
|
628
663
|
* checks it once for all the badges it paints.
|
|
@@ -1019,6 +1054,8 @@ function secondary_nav_renders(item, layout) {
|
|
|
1019
1054
|
*
|
|
1020
1055
|
* Parses a JSON config to build:
|
|
1021
1056
|
* - Layers (z-stacked): base, overlay, popup, modal, notification, loading
|
|
1057
|
+
* (the overlay holds the WINDOW layer, where the windows live,
|
|
1058
|
+
* under the drawer: yui_shell_window_layer())
|
|
1022
1059
|
* - Zones (inside base layer): top, top-sub, left, center, right,
|
|
1023
1060
|
* bottom-sub, bottom
|
|
1024
1061
|
* - Menus (primary + submenus) rendered via C_YUI_NAV — one nav
|
|
@@ -1046,6 +1083,8 @@ function secondary_nav_renders(item, layout) {
|
|
|
1046
1083
|
***************************************************************/
|
|
1047
1084
|
var GCLASS_NAME$22 = "C_YUI_SHELL";
|
|
1048
1085
|
var __last_shell__ = null;
|
|
1086
|
+
var __shell_watchers__ = [];
|
|
1087
|
+
var __window_z__ = 10;
|
|
1049
1088
|
var ZONE_IDS = [
|
|
1050
1089
|
"top",
|
|
1051
1090
|
"top-sub",
|
|
@@ -1080,10 +1119,12 @@ var attrs_table$22 = [
|
|
|
1080
1119
|
var PRIVATE_DATA$22 = {
|
|
1081
1120
|
zones: {},
|
|
1082
1121
|
layers: {},
|
|
1122
|
+
window_layer: null,
|
|
1083
1123
|
stages: {},
|
|
1084
1124
|
navs: [],
|
|
1085
1125
|
item_index: {},
|
|
1086
1126
|
nav_badges: {},
|
|
1127
|
+
badge_status: null,
|
|
1087
1128
|
dynamic_items: {},
|
|
1088
1129
|
section_pos: {},
|
|
1089
1130
|
route_mru: [],
|
|
@@ -1124,6 +1165,7 @@ function mt_create$22(gobj) {
|
|
|
1124
1165
|
if (subscriber) (0, _yuneta_gobj_js.gobj_subscribe_event)(gobj, null, {}, subscriber);
|
|
1125
1166
|
__last_shell__ = gobj;
|
|
1126
1167
|
build_ui$19(gobj);
|
|
1168
|
+
tell_shell_watchers(gobj);
|
|
1127
1169
|
}
|
|
1128
1170
|
/***************************************************************
|
|
1129
1171
|
* Framework Method: Start
|
|
@@ -1307,10 +1349,11 @@ function mt_stop$20(gobj) {
|
|
|
1307
1349
|
***************************************************************/
|
|
1308
1350
|
function mt_destroy$22(gobj) {
|
|
1309
1351
|
close_toolbar_dropdown(gobj);
|
|
1352
|
+
if (__last_shell__ === gobj) __last_shell__ = null;
|
|
1310
1353
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
1311
1354
|
if ($container && $container.parentNode) $container.parentNode.removeChild($container);
|
|
1355
|
+
tell_shell_watchers(gobj);
|
|
1312
1356
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "$container", null);
|
|
1313
|
-
if (__last_shell__ === gobj) __last_shell__ = null;
|
|
1314
1357
|
}
|
|
1315
1358
|
/***************************
|
|
1316
1359
|
* Local Methods
|
|
@@ -1433,6 +1476,17 @@ function build_ui$19(gobj) {
|
|
|
1433
1476
|
$container.appendChild($layer);
|
|
1434
1477
|
priv.layers[id] = $layer;
|
|
1435
1478
|
}
|
|
1479
|
+
let $windows = (0, _yuneta_gobj_js.createElement2)(["div", { class: "SHELL_WINDOW_LAYER yui-window-layer" }]);
|
|
1480
|
+
priv.layers.overlay.appendChild($windows);
|
|
1481
|
+
priv.window_layer = $windows;
|
|
1482
|
+
let $status = (0, _yuneta_gobj_js.createElement2)(["div", {
|
|
1483
|
+
class: "SHELL_BADGE_STATUS is-sr-only",
|
|
1484
|
+
role: "status",
|
|
1485
|
+
"aria-live": "polite",
|
|
1486
|
+
"aria-atomic": "true"
|
|
1487
|
+
}]);
|
|
1488
|
+
$container.appendChild($status);
|
|
1489
|
+
priv.badge_status = $status;
|
|
1436
1490
|
let $base = priv.layers.base;
|
|
1437
1491
|
$base.classList.add("yui-base-grid");
|
|
1438
1492
|
let zones_cfg = shell_cfg.zones || {};
|
|
@@ -2026,14 +2080,18 @@ function toolbar_link_attrs(it) {
|
|
|
2026
2080
|
************************************************************/
|
|
2027
2081
|
function build_toolbar_action_item(gobj, it) {
|
|
2028
2082
|
let children = [];
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
[
|
|
2033
|
-
|
|
2034
|
-
"
|
|
2035
|
-
|
|
2036
|
-
|
|
2083
|
+
let badge = null;
|
|
2084
|
+
if (!(0, _yuneta_gobj_js.empty_string)(it.icon)) {
|
|
2085
|
+
badge = badge_node(it.badge, it.badge_tone, "TOOLBAR_ITEM_BADGE yui-badge yui-toolbar-badge", `C_YUI_SHELL: toolbar item '${it.id || "?"}'`);
|
|
2086
|
+
children.push([
|
|
2087
|
+
"span",
|
|
2088
|
+
{ class: "icon yui-toolbar-icon" },
|
|
2089
|
+
[["i", {
|
|
2090
|
+
class: it.icon,
|
|
2091
|
+
"aria-hidden": "true"
|
|
2092
|
+
}], badge]
|
|
2093
|
+
]);
|
|
2094
|
+
}
|
|
2037
2095
|
if (!(0, _yuneta_gobj_js.empty_string)(it.name)) children.push([
|
|
2038
2096
|
"span",
|
|
2039
2097
|
{
|
|
@@ -2060,6 +2118,7 @@ function build_toolbar_action_item(gobj, it) {
|
|
|
2060
2118
|
btn_attrs.title = tip;
|
|
2061
2119
|
btn_attrs["data-i18n-title"] = tip;
|
|
2062
2120
|
}
|
|
2121
|
+
if (badge && !(0, _yuneta_gobj_js.empty_string)(aria_key)) name_control_with_badge(btn_attrs, badge);
|
|
2063
2122
|
let link = toolbar_link_attrs(it);
|
|
2064
2123
|
if (link) {
|
|
2065
2124
|
delete btn_attrs.type;
|
|
@@ -2844,23 +2903,32 @@ function update_secondary_nav_visibility(gobj, entry) {
|
|
|
2844
2903
|
}
|
|
2845
2904
|
}
|
|
2846
2905
|
/************************************************************
|
|
2847
|
-
*
|
|
2848
|
-
* of a menu of app_config.json, of one of
|
|
2849
|
-
* one given to yui_shell_set_submenu() since
|
|
2906
|
+
* The item `item_id` a menu of this shell declares, null when
|
|
2907
|
+
* none does: an item of a menu of app_config.json, of one of
|
|
2908
|
+
* their submenus, or one given to yui_shell_set_submenu() since
|
|
2909
|
+
* -- which comes first, because it replaced what the submenu
|
|
2910
|
+
* declared and is what the navs draw.
|
|
2850
2911
|
************************************************************/
|
|
2851
|
-
function
|
|
2912
|
+
function nav_item_of(gobj, item_id) {
|
|
2852
2913
|
let priv = gobj.priv;
|
|
2853
2914
|
let config = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "config") || {};
|
|
2854
2915
|
let menus = (0, _yuneta_gobj_js.is_object)(config.menu) ? config.menu : {};
|
|
2855
|
-
let
|
|
2916
|
+
let find = (items) => (0, _yuneta_gobj_js.is_array)(items) && items.find((it) => it && it.id === item_id) || null;
|
|
2917
|
+
for (let parent_item_id in priv.dynamic_items) {
|
|
2918
|
+
let it = find(priv.dynamic_items[parent_item_id]);
|
|
2919
|
+
if (it) return it;
|
|
2920
|
+
}
|
|
2856
2921
|
for (let menu_id in menus) {
|
|
2857
2922
|
let items = menus[menu_id] && menus[menu_id].items;
|
|
2858
2923
|
if (!(0, _yuneta_gobj_js.is_array)(items)) continue;
|
|
2859
|
-
|
|
2860
|
-
|
|
2924
|
+
let it = find(items);
|
|
2925
|
+
if (it) return it;
|
|
2926
|
+
for (let parent of items) {
|
|
2927
|
+
let sub = parent && parent.submenu && find(parent.submenu.items);
|
|
2928
|
+
if (sub) return sub;
|
|
2929
|
+
}
|
|
2861
2930
|
}
|
|
2862
|
-
|
|
2863
|
-
return false;
|
|
2931
|
+
return null;
|
|
2864
2932
|
}
|
|
2865
2933
|
/************************************************************
|
|
2866
2934
|
* Every C_YUI_NAV of this shell: the navs of its menus, and the
|
|
@@ -2878,6 +2946,61 @@ function shell_navs(gobj) {
|
|
|
2878
2946
|
}
|
|
2879
2947
|
return navs;
|
|
2880
2948
|
}
|
|
2949
|
+
/************************************************************
|
|
2950
|
+
* Say a badge that changed, with the name of what it counts:
|
|
2951
|
+
* "Alarms, 3", in the shell's live region (build_ui()).
|
|
2952
|
+
*
|
|
2953
|
+
* The badge itself is no live region (yui_badge.js): its number
|
|
2954
|
+
* alone said nothing, hidden while empty it missed the first
|
|
2955
|
+
* count, and inside a <button> it was not there at all. The
|
|
2956
|
+
* setters call this only when the text a reader would see
|
|
2957
|
+
* changes and is not empty: a count going away is not news, and
|
|
2958
|
+
* the same count again is not either.
|
|
2959
|
+
*
|
|
2960
|
+
* `name_key` is the key of the control's name; the phrase is a
|
|
2961
|
+
* key of its own, so a language orders and punctuates it its
|
|
2962
|
+
* way. Said once: a live region needs no re-translation.
|
|
2963
|
+
************************************************************/
|
|
2964
|
+
function announce_badge(gobj, name_key, text) {
|
|
2965
|
+
let priv = gobj.priv;
|
|
2966
|
+
let $status = priv.badge_status;
|
|
2967
|
+
if (!$status) {
|
|
2968
|
+
(0, _yuneta_gobj_js.log_error)(`C_YUI_SHELL: no live region to say badge '${name_key}': ${text}`);
|
|
2969
|
+
return;
|
|
2970
|
+
}
|
|
2971
|
+
let message;
|
|
2972
|
+
if (typeof priv.translator === "function") {
|
|
2973
|
+
const tr = priv.translator;
|
|
2974
|
+
message = tr("{{name}}, {{n}}", {
|
|
2975
|
+
name: tr(name_key),
|
|
2976
|
+
n: text
|
|
2977
|
+
});
|
|
2978
|
+
} else message = `${name_key}, ${text}`;
|
|
2979
|
+
$status.textContent = message;
|
|
2980
|
+
}
|
|
2981
|
+
/************************************************************
|
|
2982
|
+
* A shell was built (mt_create) or is being destroyed
|
|
2983
|
+
* (mt_destroy): tell every gobj that keeps DOM in a shell's
|
|
2984
|
+
* layers without being its child (yui_shell_watch_changes()).
|
|
2985
|
+
* Each one decides in its own action what it means for it --
|
|
2986
|
+
* the trace shows EV_SHELL_CHANGED arriving, from a `!!` shell
|
|
2987
|
+
* when it is the one going.
|
|
2988
|
+
*
|
|
2989
|
+
* An event, not a call into the window's module: the shell does
|
|
2990
|
+
* not import its watchers, and the move is work, so it crosses
|
|
2991
|
+
* their FSM. A watcher that is being destroyed is one whose
|
|
2992
|
+
* mt_destroy did not unwatch: it is dropped, and said.
|
|
2993
|
+
************************************************************/
|
|
2994
|
+
function tell_shell_watchers(gobj) {
|
|
2995
|
+
for (let watcher of __shell_watchers__.slice()) {
|
|
2996
|
+
if ((0, _yuneta_gobj_js.gobj_is_destroying)(watcher)) {
|
|
2997
|
+
(0, _yuneta_gobj_js.log_error)(`C_YUI_SHELL: a destroyed gobj still watches the shell (${(0, _yuneta_gobj_js.gobj_short_name)(watcher)}): it must call yui_shell_unwatch_changes() in its mt_destroy`);
|
|
2998
|
+
yui_shell_unwatch_changes(watcher);
|
|
2999
|
+
continue;
|
|
3000
|
+
}
|
|
3001
|
+
(0, _yuneta_gobj_js.gobj_send_event)(watcher, "EV_SHELL_CHANGED", {}, gobj);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
2881
3004
|
/***************************
|
|
2882
3005
|
* Actions
|
|
2883
3006
|
***************************/
|
|
@@ -3147,6 +3270,81 @@ function yui_shell_of(gobj) {
|
|
|
3147
3270
|
return __last_shell__;
|
|
3148
3271
|
}
|
|
3149
3272
|
/************************************************************
|
|
3273
|
+
* The DOM where a C_YUI_WINDOW lives when its host names no
|
|
3274
|
+
* `$parent`: the WINDOW layer, a stacking context of its own
|
|
3275
|
+
* inside the overlay layer -- above the content, below the
|
|
3276
|
+
* drawer, the toolbar's dropdowns, the dialogs and the toasts,
|
|
3277
|
+
* whatever z-index a window takes there. Null with no shell (the
|
|
3278
|
+
* window then lives in document.body).
|
|
3279
|
+
************************************************************/
|
|
3280
|
+
function yui_shell_window_layer(shell_gobj) {
|
|
3281
|
+
if (!shell_gobj || !shell_gobj.priv) return null;
|
|
3282
|
+
let priv = shell_gobj.priv;
|
|
3283
|
+
return priv.window_layer || priv.layers && priv.layers.overlay || null;
|
|
3284
|
+
}
|
|
3285
|
+
/************************************************************
|
|
3286
|
+
* Put a window on top of the others: the next number of ONE
|
|
3287
|
+
* counter, the same for a window of the dock and for a floating
|
|
3288
|
+
* one.
|
|
3289
|
+
*
|
|
3290
|
+
* Up to 7.26.34 there were two orders: the dock raised its windows
|
|
3291
|
+
* to a counter of its own (11, 12, ...), and a window without a
|
|
3292
|
+
* dock sat at 3 and was raised by being moved to the end of its
|
|
3293
|
+
* parent -- so a window opened LATER without a dock (a treedb's
|
|
3294
|
+
* raw json) opened UNDER any docked one, and no click could bring
|
|
3295
|
+
* it up. They share the window layer, and this one number orders
|
|
3296
|
+
* them all. It grows for ever, and it can: nothing else lives in
|
|
3297
|
+
* the window layer's stacking context.
|
|
3298
|
+
*
|
|
3299
|
+
* A number, not a move in the DOM: moving an element takes its
|
|
3300
|
+
* focus, its scroll positions and the pointer press that started
|
|
3301
|
+
* on it.
|
|
3302
|
+
************************************************************/
|
|
3303
|
+
function yui_shell_raise_window($el) {
|
|
3304
|
+
if (!$el || !$el.style) {
|
|
3305
|
+
(0, _yuneta_gobj_js.log_error)("C_YUI_SHELL: yui_shell_raise_window() needs an element");
|
|
3306
|
+
return;
|
|
3307
|
+
}
|
|
3308
|
+
__window_z__ += 1;
|
|
3309
|
+
$el.style.zIndex = String(__window_z__);
|
|
3310
|
+
}
|
|
3311
|
+
/************************************************************
|
|
3312
|
+
* Ask to be told (EV_SHELL_CHANGED, an INPUT event the gclass of
|
|
3313
|
+
* `gobj` must take in its FSM) when a shell is built or
|
|
3314
|
+
* destroyed.
|
|
3315
|
+
*
|
|
3316
|
+
* For a gobj that keeps DOM in a shell's layers without being
|
|
3317
|
+
* its child -- a window parented to the app, the dock. A shell's
|
|
3318
|
+
* children are destroyed with it; such a gobj is not, and its
|
|
3319
|
+
* place goes with the shell: a logout destroys the shell, the
|
|
3320
|
+
* login builds another. Told, it takes its place again in the
|
|
3321
|
+
* action.
|
|
3322
|
+
*
|
|
3323
|
+
* Idempotent. Pair it with yui_shell_unwatch_changes() in
|
|
3324
|
+
* mt_destroy, or the next shell sends the event to a destroyed
|
|
3325
|
+
* gobj.
|
|
3326
|
+
*
|
|
3327
|
+
* function mt_create(gobj) {
|
|
3328
|
+
* ...
|
|
3329
|
+
* yui_shell_watch_changes(gobj);
|
|
3330
|
+
* }
|
|
3331
|
+
* function mt_destroy(gobj) {
|
|
3332
|
+
* yui_shell_unwatch_changes(gobj);
|
|
3333
|
+
* ...
|
|
3334
|
+
* }
|
|
3335
|
+
************************************************************/
|
|
3336
|
+
function yui_shell_watch_changes(gobj) {
|
|
3337
|
+
if (!(0, _yuneta_gobj_js.is_gobj)(gobj)) {
|
|
3338
|
+
(0, _yuneta_gobj_js.log_error)("C_YUI_SHELL: yui_shell_watch_changes() needs a gobj");
|
|
3339
|
+
return;
|
|
3340
|
+
}
|
|
3341
|
+
if (__shell_watchers__.indexOf(gobj) < 0) __shell_watchers__.push(gobj);
|
|
3342
|
+
}
|
|
3343
|
+
function yui_shell_unwatch_changes(gobj) {
|
|
3344
|
+
let idx = __shell_watchers__.indexOf(gobj);
|
|
3345
|
+
if (idx >= 0) __shell_watchers__.splice(idx, 1);
|
|
3346
|
+
}
|
|
3347
|
+
/************************************************************
|
|
3150
3348
|
* Programmatic navigation.
|
|
3151
3349
|
*
|
|
3152
3350
|
* Default — PUSH: the user MOVED somewhere new, so change the URL via
|
|
@@ -3402,7 +3600,13 @@ function yui_shell_set_toolbar_item_badge(shell_gobj, item_id, value, tone) {
|
|
|
3402
3600
|
if (!$container) return;
|
|
3403
3601
|
let $badge = $container.querySelector(`[data-toolbar-item-id="${item_id}"] .yui-toolbar-badge`);
|
|
3404
3602
|
if (!$badge) return;
|
|
3603
|
+
let before = $badge.hasAttribute("hidden") ? "" : $badge.textContent;
|
|
3405
3604
|
paint_badge($badge, value, tone);
|
|
3605
|
+
let now = badge_text(value);
|
|
3606
|
+
if (now && now !== before) {
|
|
3607
|
+
let $item = $badge.closest("[data-toolbar-item-id]");
|
|
3608
|
+
announce_badge(shell_gobj, $item && $item.getAttribute("data-i18n-aria-label") || item_id, now);
|
|
3609
|
+
}
|
|
3406
3610
|
}
|
|
3407
3611
|
/************************************************************
|
|
3408
3612
|
* Set (or clear) the badge of a MENU item — the twin of
|
|
@@ -3436,8 +3640,11 @@ function yui_shell_set_nav_item_badge(shell_gobj, item_id, value, tone) {
|
|
|
3436
3640
|
tone = badge_tone(tone, `C_YUI_SHELL: yui_shell_set_nav_item_badge('${item_id}')`);
|
|
3437
3641
|
if (!shell_gobj || !(0, _yuneta_gobj_js.is_gobj)(shell_gobj) || (0, _yuneta_gobj_js.gobj_is_destroying)(shell_gobj) || (0, _yuneta_gobj_js.empty_string)(item_id)) return;
|
|
3438
3642
|
let priv = shell_gobj.priv;
|
|
3439
|
-
|
|
3643
|
+
let item = priv ? nav_item_of(shell_gobj, item_id) : null;
|
|
3644
|
+
if (!item) return;
|
|
3440
3645
|
let badge = value === void 0 ? null : value;
|
|
3646
|
+
let was = priv.nav_badges[item_id];
|
|
3647
|
+
let before = badge_text(was ? was.badge : item.badge);
|
|
3441
3648
|
priv.nav_badges[item_id] = {
|
|
3442
3649
|
badge,
|
|
3443
3650
|
badge_tone: tone
|
|
@@ -3447,6 +3654,8 @@ function yui_shell_set_nav_item_badge(shell_gobj, item_id, value, tone) {
|
|
|
3447
3654
|
badge,
|
|
3448
3655
|
badge_tone: tone
|
|
3449
3656
|
}, shell_gobj);
|
|
3657
|
+
let now = badge_text(badge);
|
|
3658
|
+
if (now && now !== before) announce_badge(shell_gobj, item.name || item_id, now);
|
|
3450
3659
|
}
|
|
3451
3660
|
/************************************************************
|
|
3452
3661
|
* Programmatic close of any open toolbar dropdown. Useful for
|
|
@@ -4050,7 +4259,7 @@ var MOBILE_MAX = 768;
|
|
|
4050
4259
|
***************************************************************/
|
|
4051
4260
|
var attrs_table$21 = [
|
|
4052
4261
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "subscriber", 0, null, "Subscriber of output events"),
|
|
4053
|
-
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$parent", 0, null, "$container will be appended to $parent if not null, else to the
|
|
4262
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$parent", 0, null, "$container will be appended to $parent if not null, else to the window layer of the shell (document.body while there is none), following the shell when it is destroyed or another is built"),
|
|
4054
4263
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "x", 0, "300", "X position"),
|
|
4055
4264
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "y", 0, "100", "Y position"),
|
|
4056
4265
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "width", 0, "700", "Width of the window"),
|
|
@@ -4086,7 +4295,11 @@ var attrs_table$21 = [
|
|
|
4086
4295
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "win_resize_handler", 0, null, "Internal: native window 'resize' listener"),
|
|
4087
4296
|
(0, _yuneta_gobj_js.SDATA_END)()
|
|
4088
4297
|
];
|
|
4089
|
-
var PRIVATE_DATA$21 = {
|
|
4298
|
+
var PRIVATE_DATA$21 = {
|
|
4299
|
+
prevSize: 0,
|
|
4300
|
+
placed_by_shell: false,
|
|
4301
|
+
back_shell: null
|
|
4302
|
+
};
|
|
4090
4303
|
var __gclass__$21 = null;
|
|
4091
4304
|
/******************************
|
|
4092
4305
|
* Framework Methods
|
|
@@ -4101,6 +4314,7 @@ function mt_create$21(gobj) {
|
|
|
4101
4314
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "window_id", window_id);
|
|
4102
4315
|
let manager = resolve_manager(gobj);
|
|
4103
4316
|
build_ui$18(gobj);
|
|
4317
|
+
yui_shell_watch_changes(gobj);
|
|
4104
4318
|
if (manager) {
|
|
4105
4319
|
let $c = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
4106
4320
|
if ($c) $c.addEventListener("pointerdown", function() {
|
|
@@ -4116,7 +4330,16 @@ function mt_create$21(gobj) {
|
|
|
4116
4330
|
title_prefix: (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "title_prefix") || "",
|
|
4117
4331
|
icon: (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "icon") || ""
|
|
4118
4332
|
}, gobj);
|
|
4119
|
-
} else
|
|
4333
|
+
} else {
|
|
4334
|
+
let $c = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
4335
|
+
if ($c) {
|
|
4336
|
+
yui_shell_raise_window($c);
|
|
4337
|
+
$c.addEventListener("pointerdown", function() {
|
|
4338
|
+
if (!(0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SHOW", {}, gobj);
|
|
4339
|
+
}, true);
|
|
4340
|
+
}
|
|
4341
|
+
if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "back_dismissable")) register_back_overlay(gobj);
|
|
4342
|
+
}
|
|
4120
4343
|
let on_win_resize = function() {
|
|
4121
4344
|
handleResize(gobj);
|
|
4122
4345
|
};
|
|
@@ -4127,13 +4350,15 @@ function mt_create$21(gobj) {
|
|
|
4127
4350
|
* Framework Method: Destroy
|
|
4128
4351
|
***************************************************************/
|
|
4129
4352
|
function mt_destroy$21(gobj) {
|
|
4353
|
+
let priv = gobj.priv;
|
|
4354
|
+
yui_shell_unwatch_changes(gobj);
|
|
4130
4355
|
let manager = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(gobj, "manager");
|
|
4131
4356
|
if (manager) (0, _yuneta_gobj_js.gobj_send_event)(manager, "EV_UNREGISTER_WINDOW", { window: (0, _yuneta_gobj_js.gobj_full_name)(gobj) }, gobj);
|
|
4132
4357
|
let back_overlay = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "back_overlay");
|
|
4133
4358
|
if (back_overlay) {
|
|
4134
|
-
|
|
4135
|
-
if (shell) yui_shell_overlay_dismissed(shell, back_overlay);
|
|
4359
|
+
if (priv.back_shell) yui_shell_overlay_dismissed(priv.back_shell, back_overlay);
|
|
4136
4360
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "back_overlay", null);
|
|
4361
|
+
priv.back_shell = null;
|
|
4137
4362
|
}
|
|
4138
4363
|
let on_win_resize = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "win_resize_handler");
|
|
4139
4364
|
if (on_win_resize) {
|
|
@@ -4545,7 +4770,8 @@ function build_ui$18(gobj) {
|
|
|
4545
4770
|
}
|
|
4546
4771
|
(0, _yuneta_gobj_js.refresh_language)($container, i18next.t);
|
|
4547
4772
|
let $parent = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$parent");
|
|
4548
|
-
|
|
4773
|
+
gobj.priv.placed_by_shell = !$parent;
|
|
4774
|
+
if (!$parent) $parent = window_place(gobj);
|
|
4549
4775
|
$parent.appendChild($container);
|
|
4550
4776
|
if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "openMaximized")) max$2(gobj);
|
|
4551
4777
|
else if (!mobile) {
|
|
@@ -4587,11 +4813,13 @@ function register_back_overlay(gobj) {
|
|
|
4587
4813
|
};
|
|
4588
4814
|
let overlay = yui_shell_register_overlay(shell, function() {
|
|
4589
4815
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "back_overlay", null);
|
|
4816
|
+
gobj.priv.back_shell = null;
|
|
4590
4817
|
const closing = close_window(gobj);
|
|
4591
4818
|
if (closing.state === "vetoed") rearm();
|
|
4592
4819
|
else if (closing.state === "asking") closing.answer.then(rearm);
|
|
4593
4820
|
}, { keep_on_navigate: (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "keep_on_navigate") });
|
|
4594
4821
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "back_overlay", overlay);
|
|
4822
|
+
gobj.priv.back_shell = overlay ? shell : null;
|
|
4595
4823
|
}
|
|
4596
4824
|
/************************************************************
|
|
4597
4825
|
* Ask to close the window. Answers what happened:
|
|
@@ -4633,7 +4861,8 @@ function close_window(gobj) {
|
|
|
4633
4861
|
}
|
|
4634
4862
|
/************************************************************
|
|
4635
4863
|
* Where a window lives when its host names no `$parent`: the
|
|
4636
|
-
*
|
|
4864
|
+
* WINDOW layer of its shell (yui_shell_window_layer()), inside
|
|
4865
|
+
* the overlay layer -- above the content, below the drawer, the
|
|
4637
4866
|
* toolbar's dropdowns, the dialogs and the toasts.
|
|
4638
4867
|
*
|
|
4639
4868
|
* It used to be document.body, and that put every window above
|
|
@@ -4646,14 +4875,17 @@ function close_window(gobj) {
|
|
|
4646
4875
|
* toolbar, any dialog opened with a window on screen, the same.
|
|
4647
4876
|
*
|
|
4648
4877
|
* Inside the layer the dock's z-index still orders the windows
|
|
4649
|
-
* among themselves
|
|
4650
|
-
* the
|
|
4878
|
+
* among themselves, and no number it gives them reaches the
|
|
4879
|
+
* drawer (7.26.31 put them in the overlay layer itself, beside
|
|
4880
|
+
* it). No shell (a page with windows and no shell, or the time
|
|
4881
|
+
* between a logout and the next login): the body.
|
|
4882
|
+
*
|
|
4883
|
+
* The place is the shell's, and a window parented to the app
|
|
4884
|
+
* outlives it: ac_shell_changed() moves it when a shell goes or
|
|
4885
|
+
* comes.
|
|
4651
4886
|
************************************************************/
|
|
4652
|
-
function
|
|
4653
|
-
|
|
4654
|
-
let layers = shell && shell.priv && shell.priv.layers;
|
|
4655
|
-
if (layers && layers.overlay) return layers.overlay;
|
|
4656
|
-
return document.body;
|
|
4887
|
+
function window_place(gobj) {
|
|
4888
|
+
return yui_shell_window_layer(yui_shell_of(gobj)) || document.body;
|
|
4657
4889
|
}
|
|
4658
4890
|
/************************************************************
|
|
4659
4891
|
*
|
|
@@ -4925,8 +5157,7 @@ function ac_show$15(gobj, event, kw, src) {
|
|
|
4925
5157
|
return -1;
|
|
4926
5158
|
}
|
|
4927
5159
|
$container.style.removeProperty("display");
|
|
4928
|
-
|
|
4929
|
-
if ($parent && $parent.lastChild !== $container) $parent.appendChild($container);
|
|
5160
|
+
yui_shell_raise_window($container);
|
|
4930
5161
|
return 0;
|
|
4931
5162
|
}
|
|
4932
5163
|
/************************************************************
|
|
@@ -4943,6 +5174,49 @@ function ac_close(gobj, event, kw, src) {
|
|
|
4943
5174
|
close_window(gobj);
|
|
4944
5175
|
return 0;
|
|
4945
5176
|
}
|
|
5177
|
+
/************************************************************
|
|
5178
|
+
* EV_SHELL_CHANGED -- a shell was built, or is being destroyed
|
|
5179
|
+
* (`src`, then destroying): the place this window lives in may
|
|
5180
|
+
* have gone with it, or be in the new one
|
|
5181
|
+
* (yui_shell_watch_changes()).
|
|
5182
|
+
*
|
|
5183
|
+
* - A window whose host named no `$parent` takes the window place
|
|
5184
|
+
* again: the window layer of the shell that governs it NOW,
|
|
5185
|
+
* document.body while there is none. So the developer window
|
|
5186
|
+
* outlives a logout in the body, and the login's shell takes it
|
|
5187
|
+
* in -- above its content, under its dialogs. From 7.26.31 to
|
|
5188
|
+
* 7.26.34 it stayed in the destroyed shell's layer: alive,
|
|
5189
|
+
* detached, invisible.
|
|
5190
|
+
* - A window its host placed stays where it was put, unless that
|
|
5191
|
+
* element was inside the shell being destroyed: then no place
|
|
5192
|
+
* is left, and it takes the window place from now on.
|
|
5193
|
+
* - Its Back entry, when the shell being destroyed held it, went
|
|
5194
|
+
* with that shell's history and is forgotten. The next shell
|
|
5195
|
+
* does not get one: a history entry pushed while a shell is
|
|
5196
|
+
* still being built would sit under its first route. Back no
|
|
5197
|
+
* longer closes such a window; its ✕ does, as before 7.26.31.
|
|
5198
|
+
************************************************************/
|
|
5199
|
+
function ac_shell_changed$1(gobj, event, kw, src) {
|
|
5200
|
+
let priv = gobj.priv;
|
|
5201
|
+
let going = (0, _yuneta_gobj_js.gobj_is_destroying)(src);
|
|
5202
|
+
if (going && priv.back_shell === src) {
|
|
5203
|
+
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "back_overlay", null);
|
|
5204
|
+
priv.back_shell = null;
|
|
5205
|
+
}
|
|
5206
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
5207
|
+
if (!$container) {
|
|
5208
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: EV_SHELL_CHANGED without a container`);
|
|
5209
|
+
return -1;
|
|
5210
|
+
}
|
|
5211
|
+
if (!priv.placed_by_shell) {
|
|
5212
|
+
let $shell = going ? (0, _yuneta_gobj_js.gobj_read_attr)(src, "$container") : null;
|
|
5213
|
+
if (!$shell || !$shell.contains($container)) return 0;
|
|
5214
|
+
priv.placed_by_shell = true;
|
|
5215
|
+
}
|
|
5216
|
+
let $place = window_place(gobj);
|
|
5217
|
+
if ($container.parentNode !== $place) $place.appendChild($container);
|
|
5218
|
+
return 0;
|
|
5219
|
+
}
|
|
4946
5220
|
/***************************
|
|
4947
5221
|
* FSM
|
|
4948
5222
|
***************************/
|
|
@@ -4978,6 +5252,11 @@ function create_gclass$21(gclass_name) {
|
|
|
4978
5252
|
"EV_CLOSE_WINDOW",
|
|
4979
5253
|
ac_close,
|
|
4980
5254
|
null
|
|
5255
|
+
],
|
|
5256
|
+
[
|
|
5257
|
+
"EV_SHELL_CHANGED",
|
|
5258
|
+
ac_shell_changed$1,
|
|
5259
|
+
null
|
|
4981
5260
|
]
|
|
4982
5261
|
]]];
|
|
4983
5262
|
const event_types = [
|
|
@@ -4987,7 +5266,8 @@ function create_gclass$21(gclass_name) {
|
|
|
4987
5266
|
["EV_REFRESH", 0],
|
|
4988
5267
|
["EV_SHOW", 0],
|
|
4989
5268
|
["EV_HIDE", 0],
|
|
4990
|
-
["EV_CLOSE_WINDOW", 0]
|
|
5269
|
+
["EV_CLOSE_WINDOW", 0],
|
|
5270
|
+
["EV_SHELL_CHANGED", 0]
|
|
4991
5271
|
];
|
|
4992
5272
|
__gclass__$21 = (0, _yuneta_gobj_js.gclass_create)(gclass_name, event_types, states, gmt$21, 0, attrs_table$21, PRIVATE_DATA$21, 0, 0, 0, 0);
|
|
4993
5273
|
if (!__gclass__$21) return -1;
|
|
@@ -5038,6 +5318,7 @@ function register_c_yui_window() {
|
|
|
5038
5318
|
var GCLASS_NAME$20 = "C_YUI_WINDOW_MANAGER";
|
|
5039
5319
|
var DOCK_Z = 1e6;
|
|
5040
5320
|
var WC_X = "<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M4.5 4.5 L11.5 11.5 M11.5 4.5 L4.5 11.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>";
|
|
5321
|
+
var __chip_seq__ = 0;
|
|
5041
5322
|
/***************************************************************
|
|
5042
5323
|
* Data
|
|
5043
5324
|
***************************************************************/
|
|
@@ -5047,15 +5328,15 @@ var attrs_table$20 = [
|
|
|
5047
5328
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "dock_corner", 0, "bottom-left", "Floating placement: top-left | top-right | bottom-left | bottom-right"),
|
|
5048
5329
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "inline_selector", 0, "", "CSS selector of the container the dock mounts into when inline (e.g. a shell zone)"),
|
|
5049
5330
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "responsive_query", 0, "(max-width: 768px)", "Media query that selects inline placement when dock_mode is 'responsive'"),
|
|
5050
|
-
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$parent", 0, null, "Where the floating dock mounts (default document.body)"),
|
|
5331
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$parent", 0, null, "Where the floating dock mounts (default: the popup layer of the shell, document.body while there is none)"),
|
|
5051
5332
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$container", 0, null, "Internal: the dock element"),
|
|
5052
5333
|
(0, _yuneta_gobj_js.SDATA_END)()
|
|
5053
5334
|
];
|
|
5054
5335
|
var PRIVATE_DATA$20 = {
|
|
5055
5336
|
windows: null,
|
|
5056
|
-
z: 0,
|
|
5057
5337
|
mql: null,
|
|
5058
|
-
mql_handler: null
|
|
5338
|
+
mql_handler: null,
|
|
5339
|
+
lang_shell: null
|
|
5059
5340
|
};
|
|
5060
5341
|
var __gclass__$20 = null;
|
|
5061
5342
|
/******************************
|
|
@@ -5067,7 +5348,6 @@ var __gclass__$20 = null;
|
|
|
5067
5348
|
function mt_create$20(gobj) {
|
|
5068
5349
|
let priv = gobj.priv;
|
|
5069
5350
|
priv.windows = [];
|
|
5070
|
-
priv.z = 10;
|
|
5071
5351
|
if (((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "dock_mode") || "floating") === "responsive") {
|
|
5072
5352
|
let q = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "responsive_query") || "(max-width: 768px)";
|
|
5073
5353
|
priv.mql = window.matchMedia(q);
|
|
@@ -5077,6 +5357,8 @@ function mt_create$20(gobj) {
|
|
|
5077
5357
|
priv.mql.addEventListener("change", priv.mql_handler);
|
|
5078
5358
|
}
|
|
5079
5359
|
build_dock(gobj);
|
|
5360
|
+
yui_shell_watch_changes(gobj);
|
|
5361
|
+
follow_language(gobj);
|
|
5080
5362
|
const subscriber = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(gobj, "subscriber");
|
|
5081
5363
|
if (subscriber) (0, _yuneta_gobj_js.gobj_subscribe_event)(gobj, null, {}, subscriber);
|
|
5082
5364
|
}
|
|
@@ -5085,6 +5367,11 @@ function mt_create$20(gobj) {
|
|
|
5085
5367
|
***************************************************************/
|
|
5086
5368
|
function mt_destroy$20(gobj) {
|
|
5087
5369
|
let priv = gobj.priv;
|
|
5370
|
+
yui_shell_unwatch_changes(gobj);
|
|
5371
|
+
if (priv.lang_shell) {
|
|
5372
|
+
if (!(0, _yuneta_gobj_js.gobj_is_destroying)(priv.lang_shell)) (0, _yuneta_gobj_js.gobj_unsubscribe_event)(priv.lang_shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
5373
|
+
priv.lang_shell = null;
|
|
5374
|
+
}
|
|
5088
5375
|
if (priv.mql && priv.mql_handler) {
|
|
5089
5376
|
priv.mql.removeEventListener("change", priv.mql_handler);
|
|
5090
5377
|
priv.mql = null;
|
|
@@ -5096,6 +5383,37 @@ function mt_destroy$20(gobj) {
|
|
|
5096
5383
|
* Local Methods
|
|
5097
5384
|
***************************/
|
|
5098
5385
|
/************************************************************
|
|
5386
|
+
* Hear the language of the shell that holds the dock -- the
|
|
5387
|
+
* dock outlives a shell, so it follows them: the dying one's
|
|
5388
|
+
* subscription goes with it, the next one is heard. The
|
|
5389
|
+
* toggle of a chip whose window's title has a DATA half has a
|
|
5390
|
+
* composed title, which no key carries: it is written again in
|
|
5391
|
+
* the new language (ac_language_changed).
|
|
5392
|
+
************************************************************/
|
|
5393
|
+
function follow_language(gobj) {
|
|
5394
|
+
let priv = gobj.priv;
|
|
5395
|
+
let shell = yui_shell_of(gobj);
|
|
5396
|
+
if (shell && (0, _yuneta_gobj_js.gobj_is_destroying)(shell)) shell = null;
|
|
5397
|
+
if (shell === priv.lang_shell) return;
|
|
5398
|
+
if (priv.lang_shell && !(0, _yuneta_gobj_js.gobj_is_destroying)(priv.lang_shell)) (0, _yuneta_gobj_js.gobj_unsubscribe_event)(priv.lang_shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
5399
|
+
priv.lang_shell = null;
|
|
5400
|
+
if (shell) {
|
|
5401
|
+
(0, _yuneta_gobj_js.gobj_subscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
5402
|
+
priv.lang_shell = shell;
|
|
5403
|
+
}
|
|
5404
|
+
}
|
|
5405
|
+
/************************************************************
|
|
5406
|
+
* The toggle's title and aria-label, in the current language:
|
|
5407
|
+
* the same join as C_YUI_WINDOW's composed_title(), DATA half
|
|
5408
|
+
* first. The title the window registered with when it gave no
|
|
5409
|
+
* halves (a legacy caller).
|
|
5410
|
+
************************************************************/
|
|
5411
|
+
function chip_title(entry) {
|
|
5412
|
+
let kind = entry.title_key ? (0, i18next.t)(entry.title_key) : "";
|
|
5413
|
+
if (entry.title_prefix && kind) return `${entry.title_prefix} · ${kind}`;
|
|
5414
|
+
return entry.title_prefix || kind || entry.title;
|
|
5415
|
+
}
|
|
5416
|
+
/************************************************************
|
|
5099
5417
|
* Inject the dock stylesheet once (theme-aware).
|
|
5100
5418
|
************************************************************/
|
|
5101
5419
|
function ensure_dock_style() {
|
|
@@ -5134,10 +5452,18 @@ function ensure_dock_style() {
|
|
|
5134
5452
|
}
|
|
5135
5453
|
.yui-dock-chip {
|
|
5136
5454
|
display: inline-flex; align-items: center; gap: 7px; font: inherit; font-size: 12px;
|
|
5137
|
-
padding:
|
|
5138
|
-
background: var(--bulma-scheme-main); color: var(--bulma-text);
|
|
5455
|
+
padding: 0 5px 0 0; border: 1px solid var(--bulma-border); border-radius: 7px;
|
|
5456
|
+
background: var(--bulma-scheme-main); color: var(--bulma-text); white-space: nowrap;
|
|
5139
5457
|
}
|
|
5140
5458
|
.yui-dock-chip:hover { border-color: var(--bulma-text-weak); }
|
|
5459
|
+
/* The chip is the look; its toggle a button that adds none, and
|
|
5460
|
+
* takes the pill's padding, so the whole label is what a press lands
|
|
5461
|
+
* on and the chip reads as one pill with its ✕ at the end. */
|
|
5462
|
+
.yui-dock-chip-toggle {
|
|
5463
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
5464
|
+
padding: 4px 0 4px 11px; margin: 0; border: 0; border-radius: 7px 0 0 7px;
|
|
5465
|
+
background: transparent; font: inherit; color: inherit; cursor: pointer; white-space: nowrap;
|
|
5466
|
+
}
|
|
5141
5467
|
/* The BORDER says active, not the text: blue ink on a blue tint is
|
|
5142
5468
|
* the same hue on itself -- 4.49:1 on the light chip, under the 4.5
|
|
5143
5469
|
* its 12px label needs. The label takes the text colour (11:1). */
|
|
@@ -5227,10 +5553,33 @@ function apply_placement(gobj) {
|
|
|
5227
5553
|
"bottom-left",
|
|
5228
5554
|
"bottom-right"
|
|
5229
5555
|
]) $dock.classList.toggle(`yui-dock--${c}`, !inline && c === corner);
|
|
5230
|
-
let target = inline ? $inline : (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$parent") ||
|
|
5556
|
+
let target = inline ? $inline : (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$parent") || dock_place(gobj);
|
|
5231
5557
|
if ($dock.parentNode !== target) target.appendChild($dock);
|
|
5232
5558
|
}
|
|
5233
5559
|
/************************************************************
|
|
5560
|
+
* Where the FLOATING dock lives when the app names no
|
|
5561
|
+
* `$parent`: the popup layer of the shell, at the top of it.
|
|
5562
|
+
*
|
|
5563
|
+
* It was document.body at z-index 1000000, and that put it
|
|
5564
|
+
* above the WHOLE shell -- `.yui-shell` is a stacking context
|
|
5565
|
+
* of its own, so its dialogs (modal layer, 99) and toasts (120)
|
|
5566
|
+
* counted only inside it: the dock stayed clickable over a
|
|
5567
|
+
* dialog's backdrop (a window could be closed from its chip
|
|
5568
|
+
* while its own "all changes will be lost" question was open),
|
|
5569
|
+
* and it covered a toast where they met.
|
|
5570
|
+
*
|
|
5571
|
+
* The popup layer, not the window layer: the dock has to stay
|
|
5572
|
+
* above EVERY window, and windows live in two layers -- the
|
|
5573
|
+
* window layer (no `$parent`) and the popup layer, where the
|
|
5574
|
+
* site map and the JSON windows of the treedb views put theirs.
|
|
5575
|
+
* Above both; below the dialogs, the toasts and the loading
|
|
5576
|
+
* cover. No shell (before the first, between a logout and the
|
|
5577
|
+
* next login): the body.
|
|
5578
|
+
************************************************************/
|
|
5579
|
+
function dock_place(gobj) {
|
|
5580
|
+
return yui_shell_popup_layer(yui_shell_of(gobj)) || document.body;
|
|
5581
|
+
}
|
|
5582
|
+
/************************************************************
|
|
5234
5583
|
* Destroy the dock element.
|
|
5235
5584
|
************************************************************/
|
|
5236
5585
|
function destroy_dock(gobj) {
|
|
@@ -5307,7 +5656,6 @@ function set_active(gobj, entry) {
|
|
|
5307
5656
|
* Bring a window to front and mark it active/visible.
|
|
5308
5657
|
************************************************************/
|
|
5309
5658
|
function focus_entry(gobj, entry) {
|
|
5310
|
-
let priv = gobj.priv;
|
|
5311
5659
|
let $win = (0, _yuneta_gobj_js.gobj_read_attr)(entry.gobj, "$container");
|
|
5312
5660
|
if ($win) {
|
|
5313
5661
|
if (entry.minimized) {
|
|
@@ -5315,8 +5663,7 @@ function focus_entry(gobj, entry) {
|
|
|
5315
5663
|
entry.minimized = false;
|
|
5316
5664
|
if (entry.$chip) entry.$chip.classList.remove("is-min");
|
|
5317
5665
|
}
|
|
5318
|
-
|
|
5319
|
-
$win.style.zIndex = priv.z;
|
|
5666
|
+
yui_shell_raise_window($win);
|
|
5320
5667
|
}
|
|
5321
5668
|
set_active(gobj, entry);
|
|
5322
5669
|
}
|
|
@@ -5383,57 +5730,60 @@ function ac_register_window(gobj, event, kw, src) {
|
|
|
5383
5730
|
{ class: "yui-dock-label-kind" },
|
|
5384
5731
|
text_node(title)
|
|
5385
5732
|
]);
|
|
5733
|
+
let chip_seq = ++__chip_seq__;
|
|
5734
|
+
let label_ids = label_items.map(function(item, i) {
|
|
5735
|
+
item[1].id = `yui-dock-chip-${chip_seq}-${i}`;
|
|
5736
|
+
return item[1].id;
|
|
5737
|
+
});
|
|
5386
5738
|
let entry = {
|
|
5387
5739
|
gobj: win,
|
|
5388
5740
|
$chip: null,
|
|
5389
|
-
minimized: false
|
|
5741
|
+
minimized: false,
|
|
5742
|
+
title,
|
|
5743
|
+
title_key,
|
|
5744
|
+
title_prefix: prefix
|
|
5390
5745
|
};
|
|
5746
|
+
let window_name = (0, _yuneta_gobj_js.gobj_full_name)(win);
|
|
5391
5747
|
let $chip = (0, _yuneta_gobj_js.createElement2)([
|
|
5392
5748
|
"div",
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5749
|
+
{ class: "DOCK_CHIP yui-dock-chip" },
|
|
5750
|
+
[[
|
|
5751
|
+
"button",
|
|
5752
|
+
Object.assign({
|
|
5753
|
+
class: "DOCK_CHIP_TOGGLE yui-dock-chip-toggle",
|
|
5754
|
+
type: "button",
|
|
5755
|
+
title,
|
|
5756
|
+
"aria-label": title,
|
|
5757
|
+
"aria-labelledby": label_ids.join(" ")
|
|
5758
|
+
}, !prefix && title_key ? {
|
|
5759
|
+
"data-i18n-title": title_key,
|
|
5760
|
+
"data-i18n-aria-label": title_key
|
|
5761
|
+
} : {}),
|
|
5762
|
+
[chip_lead(kw.icon), [
|
|
5402
5763
|
"span",
|
|
5403
5764
|
{ class: "yui-dock-label" },
|
|
5404
5765
|
label_items
|
|
5405
|
-
],
|
|
5406
|
-
|
|
5407
|
-
"button",
|
|
5408
|
-
{
|
|
5409
|
-
class: "yui-dock-close",
|
|
5410
|
-
type: "button",
|
|
5411
|
-
title: (0, i18next.t)("close"),
|
|
5412
|
-
"data-i18n-title": "close",
|
|
5413
|
-
"aria-label": (0, i18next.t)("close"),
|
|
5414
|
-
"data-i18n-aria-label": "close"
|
|
5415
|
-
},
|
|
5416
|
-
(0, _yuneta_gobj_js.html_markup)(WC_X),
|
|
5417
|
-
{ click: (evt) => {
|
|
5418
|
-
evt.stopPropagation();
|
|
5419
|
-
(0, _yuneta_gobj_js.gobj_send_event)(entry.gobj, "EV_CLOSE_WINDOW", {}, gobj);
|
|
5420
|
-
} }
|
|
5421
|
-
]
|
|
5422
|
-
],
|
|
5423
|
-
{
|
|
5424
|
-
click: (evt) => {
|
|
5766
|
+
]],
|
|
5767
|
+
{ click: (evt) => {
|
|
5425
5768
|
evt.stopPropagation();
|
|
5426
|
-
|
|
5769
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_WINDOW", { window: window_name }, gobj);
|
|
5770
|
+
} }
|
|
5771
|
+
], [
|
|
5772
|
+
"button",
|
|
5773
|
+
{
|
|
5774
|
+
class: "DOCK_CHIP_CLOSE yui-dock-close",
|
|
5775
|
+
type: "button",
|
|
5776
|
+
title: (0, i18next.t)("close"),
|
|
5777
|
+
"data-i18n-title": "close",
|
|
5778
|
+
"aria-label": (0, i18next.t)("close"),
|
|
5779
|
+
"data-i18n-aria-label": "close"
|
|
5427
5780
|
},
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
}
|
|
5435
|
-
}
|
|
5436
|
-
}
|
|
5781
|
+
(0, _yuneta_gobj_js.html_markup)(WC_X),
|
|
5782
|
+
{ click: (evt) => {
|
|
5783
|
+
evt.stopPropagation();
|
|
5784
|
+
(0, _yuneta_gobj_js.gobj_send_event)(entry.gobj, "EV_CLOSE_WINDOW", {}, gobj);
|
|
5785
|
+
} }
|
|
5786
|
+
]]
|
|
5437
5787
|
]);
|
|
5438
5788
|
entry.$chip = $chip;
|
|
5439
5789
|
priv.windows.push(entry);
|
|
@@ -5477,6 +5827,67 @@ function ac_focus_window(gobj, event, kw, src) {
|
|
|
5477
5827
|
if (entry) focus_entry(gobj, entry);
|
|
5478
5828
|
return 0;
|
|
5479
5829
|
}
|
|
5830
|
+
/************************************************************
|
|
5831
|
+
* EV_TOGGLE_WINDOW { window } -- the toggle of a chip of THIS
|
|
5832
|
+
* dock was pressed: bring a minimized or covered window to the
|
|
5833
|
+
* front, send the one in front to the dock. Only the dock's own
|
|
5834
|
+
* chip sends it (src is the dock): the events a window sends
|
|
5835
|
+
* about itself come from the window, and this one from the chip
|
|
5836
|
+
* that names it.
|
|
5837
|
+
************************************************************/
|
|
5838
|
+
function ac_toggle_window(gobj, event, kw, src) {
|
|
5839
|
+
let priv = gobj.priv;
|
|
5840
|
+
if (src !== gobj) {
|
|
5841
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} comes from the dock's own chip, not from ${(0, _yuneta_gobj_js.is_gobj)(src) ? (0, _yuneta_gobj_js.gobj_full_name)(src) : String(src)}`);
|
|
5842
|
+
return -1;
|
|
5843
|
+
}
|
|
5844
|
+
let name = kw && kw.window;
|
|
5845
|
+
let entry = priv.windows.find((e) => (0, _yuneta_gobj_js.gobj_full_name)(e.gobj) === name);
|
|
5846
|
+
if (!entry) {
|
|
5847
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event}: no window '${name}' in the dock`);
|
|
5848
|
+
return -1;
|
|
5849
|
+
}
|
|
5850
|
+
on_chip_click(gobj, entry);
|
|
5851
|
+
return 0;
|
|
5852
|
+
}
|
|
5853
|
+
/************************************************************
|
|
5854
|
+
* EV_SHELL_CHANGED -- a shell was built, or is being destroyed
|
|
5855
|
+
* (yui_shell_watch_changes()). The dock's place -- the shell's
|
|
5856
|
+
* popup layer, or its zone when inline -- may have gone with
|
|
5857
|
+
* it, or be in the new one: place it again. Up to 7.26.34 an
|
|
5858
|
+
* inline dock stayed in the destroyed shell's zone after a
|
|
5859
|
+
* logout, detached, until a window registered. Its language
|
|
5860
|
+
* is the new shell's too.
|
|
5861
|
+
************************************************************/
|
|
5862
|
+
function ac_shell_changed(gobj, event, kw, src) {
|
|
5863
|
+
apply_placement(gobj);
|
|
5864
|
+
follow_language(gobj);
|
|
5865
|
+
return 0;
|
|
5866
|
+
}
|
|
5867
|
+
/************************************************************
|
|
5868
|
+
* EV_LANGUAGE_CHANGED -- from the shell that holds the dock.
|
|
5869
|
+
* A chip's label re-translates by its key (refresh_language()
|
|
5870
|
+
* reaches its kind half); the toggle's title and aria-label
|
|
5871
|
+
* of a window with a DATA half are COMPOSED, so no key carries
|
|
5872
|
+
* them: written again here. Up to 7.26.35 they stayed in the
|
|
5873
|
+
* language the window was opened in (a reader took the
|
|
5874
|
+
* aria-labelledby, which changed; the tooltip did not).
|
|
5875
|
+
************************************************************/
|
|
5876
|
+
function ac_language_changed$11(gobj, event, kw, src) {
|
|
5877
|
+
let priv = gobj.priv;
|
|
5878
|
+
for (let entry of priv.windows) {
|
|
5879
|
+
if (!entry.title_prefix || !entry.$chip) continue;
|
|
5880
|
+
let $toggle = entry.$chip.querySelector(".DOCK_CHIP_TOGGLE");
|
|
5881
|
+
if (!$toggle) {
|
|
5882
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: a chip without its toggle`);
|
|
5883
|
+
continue;
|
|
5884
|
+
}
|
|
5885
|
+
let title = chip_title(entry);
|
|
5886
|
+
$toggle.setAttribute("title", title);
|
|
5887
|
+
$toggle.setAttribute("aria-label", title);
|
|
5888
|
+
}
|
|
5889
|
+
return 0;
|
|
5890
|
+
}
|
|
5480
5891
|
/***************************
|
|
5481
5892
|
* FSM
|
|
5482
5893
|
***************************/
|
|
@@ -5496,7 +5907,10 @@ function create_gclass$20(gclass_name) {
|
|
|
5496
5907
|
["EV_REGISTER_WINDOW", 0],
|
|
5497
5908
|
["EV_UNREGISTER_WINDOW", 0],
|
|
5498
5909
|
["EV_MINIMIZE_WINDOW", 0],
|
|
5499
|
-
["EV_FOCUS_WINDOW", 0]
|
|
5910
|
+
["EV_FOCUS_WINDOW", 0],
|
|
5911
|
+
["EV_TOGGLE_WINDOW", 0],
|
|
5912
|
+
["EV_SHELL_CHANGED", 0],
|
|
5913
|
+
["EV_LANGUAGE_CHANGED", 0]
|
|
5500
5914
|
], [["ST_IDLE", [
|
|
5501
5915
|
[
|
|
5502
5916
|
"EV_REGISTER_WINDOW",
|
|
@@ -5517,6 +5931,21 @@ function create_gclass$20(gclass_name) {
|
|
|
5517
5931
|
"EV_FOCUS_WINDOW",
|
|
5518
5932
|
ac_focus_window,
|
|
5519
5933
|
null
|
|
5934
|
+
],
|
|
5935
|
+
[
|
|
5936
|
+
"EV_TOGGLE_WINDOW",
|
|
5937
|
+
ac_toggle_window,
|
|
5938
|
+
null
|
|
5939
|
+
],
|
|
5940
|
+
[
|
|
5941
|
+
"EV_SHELL_CHANGED",
|
|
5942
|
+
ac_shell_changed,
|
|
5943
|
+
null
|
|
5944
|
+
],
|
|
5945
|
+
[
|
|
5946
|
+
"EV_LANGUAGE_CHANGED",
|
|
5947
|
+
ac_language_changed$11,
|
|
5948
|
+
null
|
|
5520
5949
|
]
|
|
5521
5950
|
]]], gmt$20, 0, attrs_table$20, PRIVATE_DATA$20, 0, 0, 0, 0);
|
|
5522
5951
|
if (!__gclass__$20) return -1;
|
|
@@ -6796,6 +7225,41 @@ function yui_tabulator_name_row_selects(table, t) {
|
|
|
6796
7225
|
}
|
|
6797
7226
|
} catch (e) {}
|
|
6798
7227
|
}
|
|
7228
|
+
/***************************************************************
|
|
7229
|
+
* Name the EDITOR of an editable column: the box Tabulator draws
|
|
7230
|
+
* in a cell while it is edited (input, number, textarea, list,
|
|
7231
|
+
* tickCross, date...).
|
|
7232
|
+
*
|
|
7233
|
+
* Tabulator gives it nothing -- no label, no aria-label, no title
|
|
7234
|
+
* -- so a reader lands in an anonymous edit box. Its name is the
|
|
7235
|
+
* column's: a cell is edited under its column's title. Asked at
|
|
7236
|
+
* the MOMENT of editing: Tabulator takes `editorParams` as a
|
|
7237
|
+
* function of the cell, and every built-in editor writes the
|
|
7238
|
+
* `elementAttributes` it answers onto the element it draws. So
|
|
7239
|
+
* the name is in the language of that moment, with nothing to
|
|
7240
|
+
* re-apply after a language change or a rebuild of the columns
|
|
7241
|
+
* -- the twin of the header filters above, which have to be
|
|
7242
|
+
* renamed after every render.
|
|
7243
|
+
*
|
|
7244
|
+
* `name_of(cell)` answers the column's title, TRANSLATED (the
|
|
7245
|
+
* view's own label: a cascade, a schema header); "" names
|
|
7246
|
+
* nothing. What `editorParams` the column had is kept, its own
|
|
7247
|
+
* `elementAttributes` too; a name it set itself wins.
|
|
7248
|
+
***************************************************************/
|
|
7249
|
+
function yui_tabulator_name_editor(column_def, name_of) {
|
|
7250
|
+
if (!column_def || !column_def.editor || typeof name_of !== "function") return;
|
|
7251
|
+
let base = column_def.editorParams;
|
|
7252
|
+
column_def.editorParams = function(cell) {
|
|
7253
|
+
let params = typeof base === "function" ? base(cell) : base || {};
|
|
7254
|
+
let name = name_of(cell);
|
|
7255
|
+
if (!name) return params;
|
|
7256
|
+
let attrs = Object.assign({
|
|
7257
|
+
"aria-label": name,
|
|
7258
|
+
title: name
|
|
7259
|
+
}, params.elementAttributes || {});
|
|
7260
|
+
return Object.assign({}, params, { elementAttributes: attrs });
|
|
7261
|
+
};
|
|
7262
|
+
}
|
|
6799
7263
|
function yui_tabulator_relocalize(table, t) {
|
|
6800
7264
|
if (!table) return;
|
|
6801
7265
|
try {
|
|
@@ -7316,6 +7780,7 @@ function yui_file_control(gobj, { name, value, readonly, accept, on_pick }) {
|
|
|
7316
7780
|
{
|
|
7317
7781
|
type: "button",
|
|
7318
7782
|
class: "FILE_PICK button is-small",
|
|
7783
|
+
title: (0, i18next.t)("choose a file"),
|
|
7319
7784
|
"data-i18n-title": "choose a file",
|
|
7320
7785
|
"aria-label": (0, i18next.t)("choose a file"),
|
|
7321
7786
|
"data-i18n-aria-label": "choose a file"
|
|
@@ -7334,6 +7799,7 @@ function yui_file_control(gobj, { name, value, readonly, accept, on_pick }) {
|
|
|
7334
7799
|
{
|
|
7335
7800
|
type: "button",
|
|
7336
7801
|
class: "FILE_CLEAR button is-small",
|
|
7802
|
+
title: (0, i18next.t)("remove the file"),
|
|
7337
7803
|
"data-i18n-title": "remove the file",
|
|
7338
7804
|
"aria-label": (0, i18next.t)("remove the file"),
|
|
7339
7805
|
"data-i18n-aria-label": "remove the file"
|
|
@@ -8682,6 +9148,293 @@ function json_editor_value(content) {
|
|
|
8682
9148
|
return JSON.stringify(content.json);
|
|
8683
9149
|
}
|
|
8684
9150
|
//#endregion
|
|
9151
|
+
//#region src/form_json_editor_names.js
|
|
9152
|
+
/***********************************************************************
|
|
9153
|
+
* form_json_editor_names.js
|
|
9154
|
+
*
|
|
9155
|
+
* The NAMES of the buttons vanilla-jsoneditor draws in its menu
|
|
9156
|
+
* (a json field of C_YUI_FORM): in the app's language, and with an
|
|
9157
|
+
* aria-label.
|
|
9158
|
+
*
|
|
9159
|
+
* The editor draws them itself, in English, with a `title` and
|
|
9160
|
+
* nothing else: "Format JSON: add proper indentation and new lines
|
|
9161
|
+
* (Ctrl+I)", "Undo (Ctrl+Z)", and three mode buttons whose text is
|
|
9162
|
+
* "text", "tree" and "table" (REV-CLOUD V23.5.6). Two hooks reach
|
|
9163
|
+
* them, and both are needed:
|
|
9164
|
+
*
|
|
9165
|
+
* - json_editor_menu_items(), the editor's `onRenderMenu`: the
|
|
9166
|
+
* items it is about to draw, with each title translated (its
|
|
9167
|
+
* shortcut kept) and the mode buttons' text too. Svelte draws
|
|
9168
|
+
* from these, so a button born in a re-render is born named.
|
|
9169
|
+
* - name_json_editor_menu(), after the render, from the form's
|
|
9170
|
+
* FSM: the aria-label of each button, with its key, so
|
|
9171
|
+
* refresh_language() re-translates it, and the state of the
|
|
9172
|
+
* mode buttons (aria-pressed). A menu item has no field for
|
|
9173
|
+
* either.
|
|
9174
|
+
*
|
|
9175
|
+
* A button is known by the CLASS the editor gives it (`jse-format`,
|
|
9176
|
+
* `jse-undo`...), never by its English title: a class is what the
|
|
9177
|
+
* editor's own stylesheet relies on. A button not listed here keeps
|
|
9178
|
+
* the editor's words.
|
|
9179
|
+
*
|
|
9180
|
+
* Its CONTEXT MENU (`onRenderContextMenu`,
|
|
9181
|
+
* json_editor_context_menu_items()) has no class on its items, so
|
|
9182
|
+
* an item is known by what it IS and where it IS: the icon the
|
|
9183
|
+
* editor draws it with (a FontAwesome name: `paste`, `scissors`),
|
|
9184
|
+
* the column of the menu it stands in, its place in a dropdown
|
|
9185
|
+
* (the main button, the first or the second of its list), the
|
|
9186
|
+
* mode of the editor (tree or table) -- never by its words. Its
|
|
9187
|
+
* text and title go back translated; after the render the same
|
|
9188
|
+
* pass names its buttons, and the arrow of each dropdown, which
|
|
9189
|
+
* the editor draws with no name at all.
|
|
9190
|
+
*
|
|
9191
|
+
* Not reached, because the editor gives them no hook: its search
|
|
9192
|
+
* box, its repair messages, the tip at the foot of the context
|
|
9193
|
+
* menu, and its modals (sort, transform). They stay in its
|
|
9194
|
+
* English.
|
|
9195
|
+
*
|
|
9196
|
+
* Copyright (c) 2026, ArtGins.
|
|
9197
|
+
* All Rights Reserved.
|
|
9198
|
+
***********************************************************************/
|
|
9199
|
+
/***************************************************************
|
|
9200
|
+
* Constants
|
|
9201
|
+
***************************************************************/
|
|
9202
|
+
var JSON_EDITOR_BUTTON_KEYS = {
|
|
9203
|
+
"jse-expand-all": "expand all",
|
|
9204
|
+
"jse-collapse-all": "collapse all",
|
|
9205
|
+
"jse-search": "search",
|
|
9206
|
+
"jse-copy": "copy",
|
|
9207
|
+
"jse-undo": "undo",
|
|
9208
|
+
"jse-redo": "redo",
|
|
9209
|
+
"jse-cancel": "cancel",
|
|
9210
|
+
"jse-format": "format json",
|
|
9211
|
+
"jse-compact": "compact json",
|
|
9212
|
+
"jse-sort": "sort",
|
|
9213
|
+
"jse-transform": "transform",
|
|
9214
|
+
"jse-contextmenu": "open context menu"
|
|
9215
|
+
};
|
|
9216
|
+
var JSON_EDITOR_MODE_NAME_KEYS = {
|
|
9217
|
+
text: "text view",
|
|
9218
|
+
tree: "tree view",
|
|
9219
|
+
table: "table view"
|
|
9220
|
+
};
|
|
9221
|
+
var JSON_EDITOR_MODE_TEXT_KEYS = {
|
|
9222
|
+
text: "text mode",
|
|
9223
|
+
tree: "tree mode",
|
|
9224
|
+
table: "table mode"
|
|
9225
|
+
};
|
|
9226
|
+
var MODE_CLASS = "yui-jse-mode-";
|
|
9227
|
+
var SHORTCUT = /\((?:Ctrl|Cmd|⌘)[^()]*\)\s*$/;
|
|
9228
|
+
var CONTEXT_BUTTON_KEYS = {
|
|
9229
|
+
"pen": "edit key",
|
|
9230
|
+
"paste": "paste",
|
|
9231
|
+
"clone": "duplicate",
|
|
9232
|
+
"crop-simple": "extract",
|
|
9233
|
+
"arrow-down-short-wide": "sort",
|
|
9234
|
+
"filter": "transform",
|
|
9235
|
+
"trash-can": "remove",
|
|
9236
|
+
"square-caret-up": "insert before",
|
|
9237
|
+
"square-caret-down": "insert after"
|
|
9238
|
+
};
|
|
9239
|
+
var CONTEXT_ROW_BUTTON_KEYS = {
|
|
9240
|
+
"pen": "edit row",
|
|
9241
|
+
"clone": "duplicate row",
|
|
9242
|
+
"trash-can": "remove row"
|
|
9243
|
+
};
|
|
9244
|
+
var CONTEXT_DROPDOWN_MAIN_KEYS = {
|
|
9245
|
+
"pen": "edit value",
|
|
9246
|
+
"scissors": "cut",
|
|
9247
|
+
"copy": "copy"
|
|
9248
|
+
};
|
|
9249
|
+
var CONTEXT_DROPDOWN_FIRST_KEYS = {
|
|
9250
|
+
"pen": "edit value",
|
|
9251
|
+
"scissors": "cut formatted",
|
|
9252
|
+
"copy": "copy formatted"
|
|
9253
|
+
};
|
|
9254
|
+
var CONTEXT_DROPDOWN_SECOND_KEYS = {
|
|
9255
|
+
"pen": "enforce string",
|
|
9256
|
+
"scissors": "cut compacted",
|
|
9257
|
+
"copy": "copy compacted"
|
|
9258
|
+
};
|
|
9259
|
+
var CONTEXT_TARGET_KEYS = {
|
|
9260
|
+
"0": "structure",
|
|
9261
|
+
"1": "object",
|
|
9262
|
+
"2": "array",
|
|
9263
|
+
"3": "value"
|
|
9264
|
+
};
|
|
9265
|
+
var TARGET_ICONS = ["arrow-right-arrow-left", "plus"];
|
|
9266
|
+
var CONTEXT_LABEL_KEYS = {
|
|
9267
|
+
convert: "convert to",
|
|
9268
|
+
insert: "insert",
|
|
9269
|
+
cell: "table cell",
|
|
9270
|
+
row: "table row"
|
|
9271
|
+
};
|
|
9272
|
+
/***************************
|
|
9273
|
+
* Local Methods
|
|
9274
|
+
***************************/
|
|
9275
|
+
function has_key(table, name) {
|
|
9276
|
+
return Object.prototype.hasOwnProperty.call(table, name);
|
|
9277
|
+
}
|
|
9278
|
+
function button_class(classes) {
|
|
9279
|
+
return (Array.isArray(classes) ? classes : String(classes || "").split(/\s+/)).find((c) => has_key(JSON_EDITOR_BUTTON_KEYS, c)) || "";
|
|
9280
|
+
}
|
|
9281
|
+
function mode_of_item(item) {
|
|
9282
|
+
if (String(item.className || "").split(/\s+/).indexOf("jse-group-button") < 0) return "";
|
|
9283
|
+
return has_key(JSON_EDITOR_MODE_NAME_KEYS, item.text) ? item.text : "";
|
|
9284
|
+
}
|
|
9285
|
+
function icon_of(item) {
|
|
9286
|
+
return item && item.icon && typeof item.icon.iconName === "string" ? item.icon.iconName : "";
|
|
9287
|
+
}
|
|
9288
|
+
function named_item(item, name) {
|
|
9289
|
+
let m = SHORTCUT.exec(String(item.title || ""));
|
|
9290
|
+
return Object.assign({}, item, {
|
|
9291
|
+
text: name,
|
|
9292
|
+
title: m ? `${name} ${m[0].trim()}` : name
|
|
9293
|
+
});
|
|
9294
|
+
}
|
|
9295
|
+
function context_dropdown(item) {
|
|
9296
|
+
let icon = icon_of(item.main);
|
|
9297
|
+
if (!has_key(CONTEXT_DROPDOWN_MAIN_KEYS, icon)) return item;
|
|
9298
|
+
let list = Array.isArray(item.items) ? item.items : [];
|
|
9299
|
+
return Object.assign({}, item, {
|
|
9300
|
+
main: named_item(item.main, (0, i18next.t)(CONTEXT_DROPDOWN_MAIN_KEYS[icon])),
|
|
9301
|
+
items: list.map(function(it, i) {
|
|
9302
|
+
if (!it || it.type !== "button") return it;
|
|
9303
|
+
if (i === 0) return named_item(it, (0, i18next.t)(CONTEXT_DROPDOWN_FIRST_KEYS[icon]));
|
|
9304
|
+
if (i === 1) return named_item(it, (0, i18next.t)(CONTEXT_DROPDOWN_SECOND_KEYS[icon]));
|
|
9305
|
+
return it;
|
|
9306
|
+
})
|
|
9307
|
+
});
|
|
9308
|
+
}
|
|
9309
|
+
function context_button(item, row_column) {
|
|
9310
|
+
let icon = icon_of(item);
|
|
9311
|
+
if (row_column && has_key(CONTEXT_ROW_BUTTON_KEYS, icon)) return named_item(item, (0, i18next.t)(CONTEXT_ROW_BUTTON_KEYS[icon]));
|
|
9312
|
+
if (has_key(CONTEXT_BUTTON_KEYS, icon)) return named_item(item, (0, i18next.t)(CONTEXT_BUTTON_KEYS[icon]));
|
|
9313
|
+
return item;
|
|
9314
|
+
}
|
|
9315
|
+
function context_column(item, table, index) {
|
|
9316
|
+
let list = Array.isArray(item.items) ? item.items : [];
|
|
9317
|
+
let buttons = list.filter((it) => it && it.type === "button");
|
|
9318
|
+
let targets = !table && buttons.length > 0 && buttons.every((it) => TARGET_ICONS.indexOf(icon_of(it)) >= 0);
|
|
9319
|
+
let row_column = table && index === 1;
|
|
9320
|
+
let label_kind = "";
|
|
9321
|
+
if (table) label_kind = index === 0 ? "cell" : index === 1 ? "row" : "";
|
|
9322
|
+
else if (targets) label_kind = icon_of(buttons[0]) === "plus" ? "insert" : "convert";
|
|
9323
|
+
let target = 0;
|
|
9324
|
+
let insert_row = 0;
|
|
9325
|
+
return Object.assign({}, item, { items: list.map(function(it) {
|
|
9326
|
+
if (!it || typeof it !== "object") return it;
|
|
9327
|
+
if (it.type === "label") return label_kind ? Object.assign({}, it, { text: (0, i18next.t)(CONTEXT_LABEL_KEYS[label_kind]) }) : it;
|
|
9328
|
+
if (it.type === "dropdown-button") return context_dropdown(it);
|
|
9329
|
+
if (it.type !== "button") return it;
|
|
9330
|
+
if (targets) return named_item(it, (0, i18next.t)(CONTEXT_TARGET_KEYS[String(target++)]));
|
|
9331
|
+
if (row_column && icon_of(it) === "plus") return named_item(it, (0, i18next.t)(insert_row++ === 0 ? CONTEXT_BUTTON_KEYS["square-caret-up"] : CONTEXT_BUTTON_KEYS["square-caret-down"]));
|
|
9332
|
+
return context_button(it, row_column);
|
|
9333
|
+
}) });
|
|
9334
|
+
}
|
|
9335
|
+
function context_item(item, table) {
|
|
9336
|
+
if (!item || typeof item !== "object") return item;
|
|
9337
|
+
if (item.type === "row") {
|
|
9338
|
+
let column = 0;
|
|
9339
|
+
let list = Array.isArray(item.items) ? item.items : [];
|
|
9340
|
+
return Object.assign({}, item, { items: list.map(function(it) {
|
|
9341
|
+
if (it && it.type === "column") return context_column(it, table, column++);
|
|
9342
|
+
return context_item(it, table);
|
|
9343
|
+
}) });
|
|
9344
|
+
}
|
|
9345
|
+
if (item.type === "dropdown-button") return context_dropdown(item);
|
|
9346
|
+
if (item.type === "button") return context_button(item, false);
|
|
9347
|
+
return item;
|
|
9348
|
+
}
|
|
9349
|
+
function mode_of_button($b) {
|
|
9350
|
+
for (let c of $b.classList) if (c.indexOf(MODE_CLASS) === 0) {
|
|
9351
|
+
let mode = c.slice(13);
|
|
9352
|
+
if (has_key(JSON_EDITOR_MODE_NAME_KEYS, mode)) return mode;
|
|
9353
|
+
}
|
|
9354
|
+
return "";
|
|
9355
|
+
}
|
|
9356
|
+
/***************************
|
|
9357
|
+
* Public
|
|
9358
|
+
***************************/
|
|
9359
|
+
/************************************************************
|
|
9360
|
+
* The editor's `onRenderMenu`: the items it is about to draw,
|
|
9361
|
+
* translated. A title keeps the editor's shortcut after the
|
|
9362
|
+
* translated name ("Deshacer (Ctrl+Z)"); a mode button gets its
|
|
9363
|
+
* mode's name as title and its short text translated, and a class
|
|
9364
|
+
* that says its mode. Anything else is returned as it came.
|
|
9365
|
+
*
|
|
9366
|
+
* Pure: what it answers is data for the editor to draw.
|
|
9367
|
+
************************************************************/
|
|
9368
|
+
function json_editor_menu_items(items) {
|
|
9369
|
+
if (!Array.isArray(items)) return items;
|
|
9370
|
+
return items.map(function(item) {
|
|
9371
|
+
if (!item || item.type !== "button") return item;
|
|
9372
|
+
let mode = mode_of_item(item);
|
|
9373
|
+
if (mode) return Object.assign({}, item, {
|
|
9374
|
+
className: `${item.className} ${MODE_CLASS}${mode}`,
|
|
9375
|
+
title: (0, i18next.t)(JSON_EDITOR_MODE_NAME_KEYS[mode]),
|
|
9376
|
+
text: (0, i18next.t)(JSON_EDITOR_MODE_TEXT_KEYS[mode])
|
|
9377
|
+
});
|
|
9378
|
+
let cls = button_class(item.className);
|
|
9379
|
+
if (!cls) return item;
|
|
9380
|
+
let m = SHORTCUT.exec(String(item.title || ""));
|
|
9381
|
+
let name = (0, i18next.t)(JSON_EDITOR_BUTTON_KEYS[cls]);
|
|
9382
|
+
return Object.assign({}, item, { title: m ? `${name} ${m[0].trim()}` : name });
|
|
9383
|
+
});
|
|
9384
|
+
}
|
|
9385
|
+
/************************************************************
|
|
9386
|
+
* The editor's `onRenderContextMenu`: the items it is about to
|
|
9387
|
+
* draw, translated -- each known by its icon and its place, never
|
|
9388
|
+
* by its words (context_item()). Anything the module does not
|
|
9389
|
+
* know comes back as it came: a newer editor that moves an item
|
|
9390
|
+
* leaves it in English, it does not mislabel it.
|
|
9391
|
+
*
|
|
9392
|
+
* Pure: what it answers is data for the editor to draw.
|
|
9393
|
+
************************************************************/
|
|
9394
|
+
function json_editor_context_menu_items(items, context) {
|
|
9395
|
+
if (!Array.isArray(items)) return items;
|
|
9396
|
+
let table = !!(context && context.mode === "table");
|
|
9397
|
+
return items.map((item) => context_item(item, table));
|
|
9398
|
+
}
|
|
9399
|
+
/************************************************************
|
|
9400
|
+
* Name the buttons of a rendered editor's menu: an aria-label
|
|
9401
|
+
* with its key (data-i18n-aria-label, so a language change
|
|
9402
|
+
* reaches it), and aria-pressed on the mode buttons -- the
|
|
9403
|
+
* selected one is the mode on screen (`jse-selected`). Run
|
|
9404
|
+
* after every render of the menu: a re-render may draw new
|
|
9405
|
+
* buttons, which carry none of it.
|
|
9406
|
+
************************************************************/
|
|
9407
|
+
function name_json_editor_menu($editor) {
|
|
9408
|
+
if (!$editor || typeof $editor.querySelectorAll !== "function") return 0;
|
|
9409
|
+
let named = 0;
|
|
9410
|
+
for (let $b of $editor.querySelectorAll(".jse-menu button")) {
|
|
9411
|
+
let mode = mode_of_button($b);
|
|
9412
|
+
const key = mode ? JSON_EDITOR_MODE_NAME_KEYS[mode] : JSON_EDITOR_BUTTON_KEYS[button_class([...$b.classList])];
|
|
9413
|
+
if (!key) continue;
|
|
9414
|
+
$b.setAttribute("aria-label", (0, i18next.t)(key));
|
|
9415
|
+
$b.setAttribute("data-i18n-aria-label", key);
|
|
9416
|
+
if (mode) $b.setAttribute("aria-pressed", $b.classList.contains("jse-selected") ? "true" : "false");
|
|
9417
|
+
named++;
|
|
9418
|
+
}
|
|
9419
|
+
const MORE = "more options";
|
|
9420
|
+
for (let $b of $editor.querySelectorAll("div.jse-contextmenu button")) {
|
|
9421
|
+
if ($b.getAttribute("data-type") === "jse-open-dropdown") {
|
|
9422
|
+
$b.setAttribute("title", (0, i18next.t)(MORE));
|
|
9423
|
+
$b.setAttribute("data-i18n-title", MORE);
|
|
9424
|
+
$b.setAttribute("aria-label", (0, i18next.t)(MORE));
|
|
9425
|
+
$b.setAttribute("data-i18n-aria-label", MORE);
|
|
9426
|
+
named++;
|
|
9427
|
+
continue;
|
|
9428
|
+
}
|
|
9429
|
+
let text = ($b.textContent || "").trim();
|
|
9430
|
+
if (text) {
|
|
9431
|
+
$b.setAttribute("aria-label", text);
|
|
9432
|
+
named++;
|
|
9433
|
+
}
|
|
9434
|
+
}
|
|
9435
|
+
return named;
|
|
9436
|
+
}
|
|
9437
|
+
//#endregion
|
|
8685
9438
|
//#region src/c_yui_form.js
|
|
8686
9439
|
/***********************************************************************
|
|
8687
9440
|
* c_yui_form.js
|
|
@@ -8731,7 +9484,9 @@ var attrs_table$17 = [
|
|
|
8731
9484
|
var PRIVATE_DATA$17 = {
|
|
8732
9485
|
rearm_timer: null,
|
|
8733
9486
|
tables: null,
|
|
8734
|
-
table_seq: 0
|
|
9487
|
+
table_seq: 0,
|
|
9488
|
+
json_names_posted: false,
|
|
9489
|
+
lang_shell: null
|
|
8735
9490
|
};
|
|
8736
9491
|
var __gclass__$17 = null;
|
|
8737
9492
|
/***************************
|
|
@@ -8762,13 +9517,23 @@ function mt_destroy$17(gobj) {
|
|
|
8762
9517
|
* Framework Method start
|
|
8763
9518
|
************************************************************/
|
|
8764
9519
|
function mt_start$17(gobj) {
|
|
9520
|
+
let priv = gobj.priv;
|
|
9521
|
+
let shell = yui_shell_of(gobj);
|
|
9522
|
+
if (shell) {
|
|
9523
|
+
(0, _yuneta_gobj_js.gobj_subscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
9524
|
+
priv.lang_shell = shell;
|
|
9525
|
+
}
|
|
8765
9526
|
let record = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "record");
|
|
8766
9527
|
if (record) (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_LOAD_RECORD", record, gobj);
|
|
8767
9528
|
}
|
|
8768
9529
|
/************************************************************
|
|
8769
9530
|
* Framework Method stop
|
|
8770
9531
|
************************************************************/
|
|
8771
|
-
function mt_stop$17(gobj) {
|
|
9532
|
+
function mt_stop$17(gobj) {
|
|
9533
|
+
let priv = gobj.priv;
|
|
9534
|
+
if (priv.lang_shell && !(0, _yuneta_gobj_js.gobj_is_destroying)(priv.lang_shell)) (0, _yuneta_gobj_js.gobj_unsubscribe_event)(priv.lang_shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
9535
|
+
priv.lang_shell = null;
|
|
9536
|
+
}
|
|
8772
9537
|
/***************************
|
|
8773
9538
|
* Local Methods
|
|
8774
9539
|
***************************/
|
|
@@ -9224,6 +9989,80 @@ function name_form_control$1($field, conf) {
|
|
|
9224
9989
|
$clear.setAttribute("data-i18n-aria-label", CLEAR_KEY);
|
|
9225
9990
|
}
|
|
9226
9991
|
}
|
|
9992
|
+
/************************************************************
|
|
9993
|
+
* The ✕ of ONE selected option of a Tom Select: its
|
|
9994
|
+
* remove_button plugin calls this for every option it draws.
|
|
9995
|
+
*
|
|
9996
|
+
* The plugin's own was a div titled "Remove" in English -- never
|
|
9997
|
+
* translated, no aria-label -- with tabindex -1, and the form
|
|
9998
|
+
* turns Backspace deletion off (no_backspace_delete): a keyboard
|
|
9999
|
+
* could not take one option out at all. Named here through t()
|
|
10000
|
+
* with its key (so a language change reaches it), and pressed by
|
|
10001
|
+
* Enter or Space as the clear button is: the key clicks it, which
|
|
10002
|
+
* runs the plugin's own handler.
|
|
10003
|
+
************************************************************/
|
|
10004
|
+
function remove_option_button() {
|
|
10005
|
+
const KEY = "remove this option";
|
|
10006
|
+
let $b = (0, _yuneta_gobj_js.createElement2)([
|
|
10007
|
+
"div",
|
|
10008
|
+
{
|
|
10009
|
+
class: "remove",
|
|
10010
|
+
role: "button",
|
|
10011
|
+
tabindex: "0",
|
|
10012
|
+
title: (0, i18next.t)(KEY),
|
|
10013
|
+
"data-i18n-title": KEY,
|
|
10014
|
+
"aria-label": (0, i18next.t)(KEY),
|
|
10015
|
+
"data-i18n-aria-label": KEY
|
|
10016
|
+
},
|
|
10017
|
+
"×"
|
|
10018
|
+
]);
|
|
10019
|
+
$b.addEventListener("keydown", function(evt) {
|
|
10020
|
+
if (evt.key === "Enter" || evt.key === " ") {
|
|
10021
|
+
evt.preventDefault();
|
|
10022
|
+
evt.stopPropagation();
|
|
10023
|
+
$b.click();
|
|
10024
|
+
}
|
|
10025
|
+
});
|
|
10026
|
+
return $b;
|
|
10027
|
+
}
|
|
10028
|
+
/************************************************************
|
|
10029
|
+
* The `onRenderMenu` of a json editor of this form.
|
|
10030
|
+
*
|
|
10031
|
+
* The editor calls it with the items it is about to draw: they go
|
|
10032
|
+
* back translated (json_editor_menu_items(), data for the editor
|
|
10033
|
+
* to draw). What no item can carry -- an aria-label, the state of
|
|
10034
|
+
* the mode buttons -- is written on the drawn buttons, after the
|
|
10035
|
+
* render, by the form's FSM (EV_NAME_JSON_EDITORS): the callback
|
|
10036
|
+
* only posts the event, once until it is handled. Posted, not
|
|
10037
|
+
* sent: when it runs the editor has not drawn the menu yet.
|
|
10038
|
+
*
|
|
10039
|
+
* A new function each call: handing an editor a new one is what
|
|
10040
|
+
* makes it draw its menu again (ac_language_changed).
|
|
10041
|
+
************************************************************/
|
|
10042
|
+
function json_editor_render_menu(gobj) {
|
|
10043
|
+
return function(items) {
|
|
10044
|
+
ask_json_editor_names(gobj);
|
|
10045
|
+
return json_editor_menu_items(items);
|
|
10046
|
+
};
|
|
10047
|
+
}
|
|
10048
|
+
/************************************************************
|
|
10049
|
+
* The `onRenderContextMenu` of a json editor of this form: the
|
|
10050
|
+
* same, for the menu it opens on a right click or Ctrl+Q. It is
|
|
10051
|
+
* built each time it opens, in the language of that moment.
|
|
10052
|
+
************************************************************/
|
|
10053
|
+
function json_editor_render_context_menu(gobj) {
|
|
10054
|
+
return function(items, context) {
|
|
10055
|
+
ask_json_editor_names(gobj);
|
|
10056
|
+
return json_editor_context_menu_items(items, context);
|
|
10057
|
+
};
|
|
10058
|
+
}
|
|
10059
|
+
function ask_json_editor_names(gobj) {
|
|
10060
|
+
let priv = gobj.priv;
|
|
10061
|
+
if (!priv.json_names_posted && !(0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) {
|
|
10062
|
+
priv.json_names_posted = true;
|
|
10063
|
+
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_NAME_JSON_EDITORS", {}, gobj);
|
|
10064
|
+
}
|
|
10065
|
+
}
|
|
9227
10066
|
function build_form(gobj) {
|
|
9228
10067
|
let form_id = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "form_id");
|
|
9229
10068
|
let $form = (0, _yuneta_gobj_js.createElement2)(["form", {
|
|
@@ -9255,7 +10094,7 @@ function build_html_form(gobj, $form, prefix, template) {
|
|
|
9255
10094
|
let label_keys = topic_name ? [topic_name + "." + field_desc.name, field_desc.name] : [field_desc.name];
|
|
9256
10095
|
const NO_I18N = "\0";
|
|
9257
10096
|
html_field_conf.label = (0, i18next.t)(label_keys, { defaultValue: field_desc.header });
|
|
9258
|
-
html_field_conf.label_i18n = (0, i18next.t)(
|
|
10097
|
+
html_field_conf.label_i18n = label_keys.find((k) => (0, i18next.t)(k, { defaultValue: NO_I18N }) !== NO_I18N) || null;
|
|
9259
10098
|
html_field_conf.placeholder = field_desc.placeholder ? (0, i18next.t)(field_desc.placeholder) : "";
|
|
9260
10099
|
let placeholders = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "placeholders");
|
|
9261
10100
|
if (placeholders[key]) html_field_conf.placeholder = placeholders[key];
|
|
@@ -9961,7 +10800,7 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
9961
10800
|
"clear_button": { "title": (0, i18next.t)("remove all selected options") },
|
|
9962
10801
|
"no_active_items": {},
|
|
9963
10802
|
"no_backspace_delete": {},
|
|
9964
|
-
"remove_button": {}
|
|
10803
|
+
"remove_button": { html: remove_option_button }
|
|
9965
10804
|
}
|
|
9966
10805
|
});
|
|
9967
10806
|
$extend.tom_select.on("change", function() {
|
|
@@ -10030,7 +10869,9 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
10030
10869
|
},
|
|
10031
10870
|
timestampTag: function({ field, value, path }) {
|
|
10032
10871
|
return is_time_field(field);
|
|
10033
|
-
}
|
|
10872
|
+
},
|
|
10873
|
+
onRenderMenu: json_editor_render_menu(gobj),
|
|
10874
|
+
onRenderContextMenu: json_editor_render_context_menu(gobj)
|
|
10034
10875
|
}
|
|
10035
10876
|
});
|
|
10036
10877
|
break;
|
|
@@ -10562,6 +11403,9 @@ function template2columns(gobj, columns, template, sub_elements) {
|
|
|
10562
11403
|
}
|
|
10563
11404
|
if (column) {
|
|
10564
11405
|
if (readonly) delete column.editor;
|
|
11406
|
+
yui_tabulator_name_editor(column, function() {
|
|
11407
|
+
return (0, i18next.t)(field_desc.header || field_desc.name);
|
|
11408
|
+
});
|
|
10565
11409
|
columns.push(column);
|
|
10566
11410
|
}
|
|
10567
11411
|
});
|
|
@@ -11322,6 +12166,39 @@ function ac_hide$11(gobj, event, kw, src) {
|
|
|
11322
12166
|
function ac_timeout(gobj, event, kw, src) {
|
|
11323
12167
|
return 0;
|
|
11324
12168
|
}
|
|
12169
|
+
/************************************************************
|
|
12170
|
+
* EV_NAME_JSON_EDITORS {} -- a menu of a json editor of this
|
|
12171
|
+
* form was drawn, its menu or its context menu (posted by
|
|
12172
|
+
* ask_json_editor_names): name its buttons. Every editor of the
|
|
12173
|
+
* form: naming is idempotent, and a kw is plain json, which an
|
|
12174
|
+
* editor is not.
|
|
12175
|
+
************************************************************/
|
|
12176
|
+
function ac_name_json_editors(gobj, event, kw, src) {
|
|
12177
|
+
let priv = gobj.priv;
|
|
12178
|
+
priv.json_names_posted = false;
|
|
12179
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
12180
|
+
if (!$container) {
|
|
12181
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} without a container`);
|
|
12182
|
+
return -1;
|
|
12183
|
+
}
|
|
12184
|
+
for (let $editor of $container.querySelectorAll(".jsoneditor")) name_json_editor_menu($editor);
|
|
12185
|
+
return 0;
|
|
12186
|
+
}
|
|
12187
|
+
/************************************************************
|
|
12188
|
+
* EV_LANGUAGE_CHANGED {} -- from the shell. A json editor draws
|
|
12189
|
+
* its menu once: its titles and the text of its mode buttons stay
|
|
12190
|
+
* in the old language until it draws it again, so each is told to
|
|
12191
|
+
* (a new onRenderMenu), and the render names it again.
|
|
12192
|
+
************************************************************/
|
|
12193
|
+
function ac_language_changed$10(gobj, event, kw, src) {
|
|
12194
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
12195
|
+
if (!$container) return 0;
|
|
12196
|
+
for (let $editor of $container.querySelectorAll(".jsoneditor")) {
|
|
12197
|
+
let editor = $editor.jsoneditor;
|
|
12198
|
+
if (editor && typeof editor.updateProps === "function") editor.updateProps({ onRenderMenu: json_editor_render_menu(gobj) });
|
|
12199
|
+
}
|
|
12200
|
+
return 0;
|
|
12201
|
+
}
|
|
11325
12202
|
/***************************
|
|
11326
12203
|
* FSM
|
|
11327
12204
|
***************************/
|
|
@@ -11471,6 +12348,16 @@ function create_gclass$17(gclass_name) {
|
|
|
11471
12348
|
"EV_TIMEOUT",
|
|
11472
12349
|
ac_timeout,
|
|
11473
12350
|
null
|
|
12351
|
+
],
|
|
12352
|
+
[
|
|
12353
|
+
"EV_NAME_JSON_EDITORS",
|
|
12354
|
+
ac_name_json_editors,
|
|
12355
|
+
null
|
|
12356
|
+
],
|
|
12357
|
+
[
|
|
12358
|
+
"EV_LANGUAGE_CHANGED",
|
|
12359
|
+
ac_language_changed$10,
|
|
12360
|
+
null
|
|
11474
12361
|
]
|
|
11475
12362
|
]]];
|
|
11476
12363
|
const event_types = [
|
|
@@ -11489,7 +12376,9 @@ function create_gclass$17(gclass_name) {
|
|
|
11489
12376
|
["EV_REFRESH", 0],
|
|
11490
12377
|
["EV_SHOW", 0],
|
|
11491
12378
|
["EV_HIDE", 0],
|
|
11492
|
-
["EV_TIMEOUT", 0]
|
|
12379
|
+
["EV_TIMEOUT", 0],
|
|
12380
|
+
["EV_NAME_JSON_EDITORS", 0],
|
|
12381
|
+
["EV_LANGUAGE_CHANGED", 0]
|
|
11493
12382
|
];
|
|
11494
12383
|
__gclass__$17 = (0, _yuneta_gobj_js.gclass_create)(gclass_name, event_types, states, gmt$17, 0, attrs_table$17, PRIVATE_DATA$17, 0, 0, 0, 0);
|
|
11495
12384
|
if (!__gclass__$17) return -1;
|
|
@@ -11509,7 +12398,7 @@ function register_c_yui_form() {
|
|
|
11509
12398
|
*
|
|
11510
12399
|
* Utilities for maplibre
|
|
11511
12400
|
*
|
|
11512
|
-
* Copyright (c) 2025, ArtGins.
|
|
12401
|
+
* Copyright (c) 2025-2026, ArtGins.
|
|
11513
12402
|
* All Rights Reserved.
|
|
11514
12403
|
***********************************************************************/
|
|
11515
12404
|
var EditControl = class {
|
|
@@ -11705,9 +12594,14 @@ function label_ctrl($root, selector, text) {
|
|
|
11705
12594
|
$el.setAttribute("aria-label", text);
|
|
11706
12595
|
}
|
|
11707
12596
|
}
|
|
12597
|
+
function relabel_written($root, selector, was, now) {
|
|
12598
|
+
if (!$root || !now) return;
|
|
12599
|
+
for (const $el of $root.querySelectorAll(selector)) if ($el.getAttribute("aria-label") === was) $el.setAttribute("aria-label", now);
|
|
12600
|
+
}
|
|
11708
12601
|
function yui_maplibre_relocalize(map, t) {
|
|
11709
12602
|
if (!map || typeof map.getContainer !== "function") return;
|
|
11710
12603
|
const strings = yui_maplibre_locale(t);
|
|
12604
|
+
const was = Object.assign({}, map._locale);
|
|
11711
12605
|
try {
|
|
11712
12606
|
map._locale = Object.assign({}, map._locale, strings);
|
|
11713
12607
|
} catch (e) {}
|
|
@@ -11719,6 +12613,8 @@ function yui_maplibre_relocalize(map, t) {
|
|
|
11719
12613
|
label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
|
|
11720
12614
|
label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
|
|
11721
12615
|
label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
|
|
12616
|
+
relabel_written($c, ".maplibregl-canvas", was["Map.Title"], strings["Map.Title"]);
|
|
12617
|
+
relabel_written($c, ".maplibregl-marker", was["Marker.Title"], strings["Marker.Title"]);
|
|
11722
12618
|
const mac = typeof navigator !== "undefined" && (navigator.userAgent || "").includes("Mac");
|
|
11723
12619
|
const $desktop = $c.querySelector(".maplibregl-desktop-message");
|
|
11724
12620
|
if ($desktop) $desktop.textContent = mac ? strings["CooperativeGesturesHandler.MacHelpText"] : strings["CooperativeGesturesHandler.WindowsHelpText"];
|
|
@@ -14467,6 +15363,8 @@ function make_toolbar$5(gobj) {
|
|
|
14467
15363
|
type: "text",
|
|
14468
15364
|
placeholder: (0, i18next.t)("search"),
|
|
14469
15365
|
"data-i18n-placeholder": "search",
|
|
15366
|
+
title: (0, i18next.t)("search"),
|
|
15367
|
+
"data-i18n-title": "search",
|
|
14470
15368
|
"aria-label": (0, i18next.t)("search"),
|
|
14471
15369
|
"data-i18n-aria-label": "search"
|
|
14472
15370
|
},
|
|
@@ -16007,6 +16905,8 @@ function make_toolbar$4(gobj) {
|
|
|
16007
16905
|
type: "text",
|
|
16008
16906
|
placeholder: (0, i18next.t)("search"),
|
|
16009
16907
|
"data-i18n-placeholder": "search",
|
|
16908
|
+
title: (0, i18next.t)("search"),
|
|
16909
|
+
"data-i18n-title": "search",
|
|
16010
16910
|
"aria-label": (0, i18next.t)("search"),
|
|
16011
16911
|
"data-i18n-aria-label": "search"
|
|
16012
16912
|
},
|
|
@@ -19280,6 +20180,8 @@ function make_toolbar$2(gobj) {
|
|
|
19280
20180
|
type: "text",
|
|
19281
20181
|
placeholder: (0, i18next.t)("search"),
|
|
19282
20182
|
"data-i18n-placeholder": "search",
|
|
20183
|
+
title: (0, i18next.t)("search"),
|
|
20184
|
+
"data-i18n-title": "search",
|
|
19283
20185
|
"aria-label": (0, i18next.t)("search"),
|
|
19284
20186
|
"data-i18n-aria-label": "search"
|
|
19285
20187
|
},
|
|
@@ -21100,7 +22002,7 @@ function open_gclass_view(host, gclass_name, opts) {
|
|
|
21100
22002
|
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
21101
22003
|
return handle;
|
|
21102
22004
|
}
|
|
21103
|
-
let $win_parent = window_layer_of(host
|
|
22005
|
+
let $win_parent = window_layer_of(host);
|
|
21104
22006
|
handle.win = (0, _yuneta_gobj_js.gobj_create_service)(`gclass-win-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(host))}`, "C_YUI_WINDOW", {
|
|
21105
22007
|
$parent: $win_parent,
|
|
21106
22008
|
subscriber: null,
|
|
@@ -21168,14 +22070,19 @@ function close_gclass_view(handle) {
|
|
|
21168
22070
|
* window on `body` and mounted in the shell's popup layer
|
|
21169
22071
|
* lands BEHIND its opener whatever number it is given, and
|
|
21170
22072
|
* the button reads as one that did nothing.
|
|
22073
|
+
*
|
|
22074
|
+
* Opened from no window: null -- the window layer of the
|
|
22075
|
+
* shell, where every window lives (the legacy '#top-layer'
|
|
22076
|
+
* when a page has one). It was the shell's popup layer: above
|
|
22077
|
+
* the drawer, in the way of the toolbar's dropdowns.
|
|
21171
22078
|
************************************************************/
|
|
21172
|
-
function window_layer_of(host
|
|
22079
|
+
function window_layer_of(host) {
|
|
21173
22080
|
let $c = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(host, "$container");
|
|
21174
22081
|
if ($c && typeof $c.closest === "function") {
|
|
21175
22082
|
let $win = $c.closest(".C_YUI_WINDOW");
|
|
21176
22083
|
if ($win && $win.parentNode) return $win.parentNode;
|
|
21177
22084
|
}
|
|
21178
|
-
return typeof document !== "undefined" && document.getElementById("top-layer") ||
|
|
22085
|
+
return typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
21179
22086
|
}
|
|
21180
22087
|
/************************************************************
|
|
21181
22088
|
* A window is not a sheet: below this width there is no room
|
|
@@ -21844,6 +22751,8 @@ function make_find_items(gobj) {
|
|
|
21844
22751
|
type: "text",
|
|
21845
22752
|
placeholder: (0, i18next.t)("search"),
|
|
21846
22753
|
"data-i18n-placeholder": "search",
|
|
22754
|
+
title: (0, i18next.t)("search"),
|
|
22755
|
+
"data-i18n-title": "search",
|
|
21847
22756
|
"aria-label": (0, i18next.t)("search"),
|
|
21848
22757
|
"data-i18n-aria-label": "search"
|
|
21849
22758
|
},
|
|
@@ -23629,7 +24538,7 @@ function card_descriptor(it, show_label, badge_of) {
|
|
|
23629
24538
|
"aria-label": label || it.id
|
|
23630
24539
|
};
|
|
23631
24540
|
if (label) a_attrs["data-i18n-aria-label"] = label;
|
|
23632
|
-
let tip = it.tooltip || it.aria_label;
|
|
24541
|
+
let tip = it.tooltip || it.aria_label || label;
|
|
23633
24542
|
if (tip) {
|
|
23634
24543
|
a_attrs.title = tip;
|
|
23635
24544
|
a_attrs["data-i18n-title"] = tip;
|
|
@@ -23638,6 +24547,7 @@ function card_descriptor(it, show_label, badge_of) {
|
|
|
23638
24547
|
a_attrs["aria-disabled"] = "true";
|
|
23639
24548
|
a_attrs["tabindex"] = "-1";
|
|
23640
24549
|
}
|
|
24550
|
+
if (badge) name_control_with_badge(a_attrs, badge);
|
|
23641
24551
|
return [
|
|
23642
24552
|
"a",
|
|
23643
24553
|
a_attrs,
|
|
@@ -24040,6 +24950,7 @@ function render_tabs(gobj, items) {
|
|
|
24040
24950
|
a_attrs.title = tip;
|
|
24041
24951
|
a_attrs["data-i18n-title"] = tip;
|
|
24042
24952
|
}
|
|
24953
|
+
name_control_with_badge(a_attrs, badge_el);
|
|
24043
24954
|
let li_class = (0, _yuneta_gobj_js.empty_string)(it.class) ? "" : String(it.class);
|
|
24044
24955
|
lis.push([
|
|
24045
24956
|
"li",
|
|
@@ -24119,11 +25030,14 @@ function render_breadcrumb(gobj, items) {
|
|
|
24119
25030
|
href: it.route ? "#" + it.route : "#",
|
|
24120
25031
|
"data-item-id": it.id,
|
|
24121
25032
|
"data-route": it.route || "",
|
|
24122
|
-
"data-disabled": it.disabled ? "1" : "0"
|
|
25033
|
+
"data-disabled": it.disabled ? "1" : "0",
|
|
25034
|
+
"aria-label": it.name || it.id
|
|
24123
25035
|
};
|
|
24124
|
-
if (it.name)
|
|
24125
|
-
|
|
24126
|
-
|
|
25036
|
+
if (it.name) a_attrs["data-i18n-aria-label"] = it.name;
|
|
25037
|
+
let tip = it.tooltip || it.aria_label || it.name;
|
|
25038
|
+
if (tip) {
|
|
25039
|
+
a_attrs.title = tip;
|
|
25040
|
+
a_attrs["data-i18n-title"] = tip;
|
|
24127
25041
|
}
|
|
24128
25042
|
lis.push([
|
|
24129
25043
|
"li",
|
|
@@ -24256,17 +25170,19 @@ function render_accordion(gobj, items) {
|
|
|
24256
25170
|
"aria-expanded": "false",
|
|
24257
25171
|
"aria-controls": body_id
|
|
24258
25172
|
};
|
|
25173
|
+
let head_badge = item_badge_node(gobj, it, false);
|
|
24259
25174
|
if (!(0, _yuneta_gobj_js.empty_string)(head_text)) {
|
|
24260
25175
|
head_attrs.i18n = head_text;
|
|
24261
25176
|
head_attrs.title = head_text;
|
|
24262
25177
|
head_attrs["data-i18n-title"] = head_text;
|
|
24263
25178
|
head_attrs["aria-label"] = head_text;
|
|
24264
25179
|
head_attrs["data-i18n-aria-label"] = head_text;
|
|
25180
|
+
name_control_with_badge(head_attrs, head_badge);
|
|
24265
25181
|
}
|
|
24266
25182
|
let $hdr = (0, _yuneta_gobj_js.createElement2)([
|
|
24267
25183
|
"button",
|
|
24268
25184
|
head_attrs,
|
|
24269
|
-
[text_node(head_text),
|
|
25185
|
+
[text_node(head_text), head_badge]
|
|
24270
25186
|
]);
|
|
24271
25187
|
$container.appendChild($hdr);
|
|
24272
25188
|
let $ul = (0, _yuneta_gobj_js.createElement2)(["ul", {
|
|
@@ -24355,6 +25271,7 @@ function item_li(gobj, it, opts) {
|
|
|
24355
25271
|
a_attrs["aria-disabled"] = "true";
|
|
24356
25272
|
a_attrs["tabindex"] = "-1";
|
|
24357
25273
|
}
|
|
25274
|
+
name_control_with_badge(a_attrs, badge_el);
|
|
24358
25275
|
return [
|
|
24359
25276
|
"li",
|
|
24360
25277
|
{},
|
|
@@ -24401,6 +25318,7 @@ function item_iconbar(gobj, it, opts) {
|
|
|
24401
25318
|
a_attrs.title = tip;
|
|
24402
25319
|
a_attrs["data-i18n-title"] = tip;
|
|
24403
25320
|
}
|
|
25321
|
+
name_control_with_badge(a_attrs, badge_el);
|
|
24404
25322
|
return [
|
|
24405
25323
|
"div",
|
|
24406
25324
|
{ class: "level-item" },
|
|
@@ -24658,7 +25576,10 @@ function render_node(node) {
|
|
|
24658
25576
|
if (node.icon && /^yi-[a-z0-9-]+$/.test(node.icon)) row.push([
|
|
24659
25577
|
"span",
|
|
24660
25578
|
{ class: "icon ROUTEMAP_ICON" },
|
|
24661
|
-
[["i", {
|
|
25579
|
+
[["i", {
|
|
25580
|
+
class: node.icon,
|
|
25581
|
+
"aria-hidden": "true"
|
|
25582
|
+
}]]
|
|
24662
25583
|
]);
|
|
24663
25584
|
row.push([
|
|
24664
25585
|
"span",
|
|
@@ -24707,16 +25628,23 @@ function render_node(node) {
|
|
|
24707
25628
|
]);
|
|
24708
25629
|
let row_class = (node.current ? " ROUTEMAP_CURRENT" : "") + (node.ref ? " ROUTEMAP_IS_REF" : "");
|
|
24709
25630
|
let $row;
|
|
24710
|
-
if (node.route)
|
|
24711
|
-
|
|
24712
|
-
{
|
|
25631
|
+
if (node.route) {
|
|
25632
|
+
let a_attrs = {
|
|
24713
25633
|
class: "ROUTEMAP_LINK ROUTEMAP_ROW" + row_class,
|
|
24714
25634
|
href: "#" + node.route,
|
|
24715
25635
|
title: node.route
|
|
24716
|
-
}
|
|
24717
|
-
|
|
24718
|
-
|
|
24719
|
-
|
|
25636
|
+
};
|
|
25637
|
+
if (node.label) {
|
|
25638
|
+
a_attrs["aria-label"] = node.label;
|
|
25639
|
+
a_attrs["data-i18n-aria-label"] = node.label;
|
|
25640
|
+
}
|
|
25641
|
+
if (node.current) a_attrs["aria-current"] = "page";
|
|
25642
|
+
$row = (0, _yuneta_gobj_js.createElement2)([
|
|
25643
|
+
"a",
|
|
25644
|
+
a_attrs,
|
|
25645
|
+
row
|
|
25646
|
+
]);
|
|
25647
|
+
} else $row = (0, _yuneta_gobj_js.createElement2)([
|
|
24720
25648
|
"span",
|
|
24721
25649
|
{ class: "ROUTEMAP_ROW ROUTEMAP_STRUCT" + row_class },
|
|
24722
25650
|
row
|
|
@@ -25000,7 +25928,7 @@ function yui_shell_show_route_map(shell, opts) {
|
|
|
25000
25928
|
if ((0, _yuneta_gobj_js.gclass_find_by_name)("C_YUI_WINDOW")) {
|
|
25001
25929
|
let win_ref = { gobj: null };
|
|
25002
25930
|
let $body = build_body(shell, t);
|
|
25003
|
-
let $parent =
|
|
25931
|
+
let $parent = typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
25004
25932
|
let win = (0, _yuneta_gobj_js.gobj_create_service)(WIN_NAME$2, "C_YUI_WINDOW", {
|
|
25005
25933
|
$parent,
|
|
25006
25934
|
subscriber: null,
|
|
@@ -26074,7 +27002,13 @@ function add_tab(gobj, gobj2, id, text, icon) {
|
|
|
26074
27002
|
let $item = (0, _yuneta_gobj_js.createElement2)([
|
|
26075
27003
|
"li",
|
|
26076
27004
|
{ class: "" },
|
|
26077
|
-
[["a", {
|
|
27005
|
+
[["a", {
|
|
27006
|
+
href: id,
|
|
27007
|
+
title: (0, i18next.t)(text),
|
|
27008
|
+
"data-i18n-title": text,
|
|
27009
|
+
"aria-label": (0, i18next.t)(text),
|
|
27010
|
+
"data-i18n-aria-label": text
|
|
27011
|
+
}]]
|
|
26078
27012
|
]);
|
|
26079
27013
|
$tabs.appendChild($item);
|
|
26080
27014
|
$item.gobj = gobj2;
|
|
@@ -26082,7 +27016,10 @@ function add_tab(gobj, gobj2, id, text, icon) {
|
|
|
26082
27016
|
if (icon) $a.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
26083
27017
|
"span",
|
|
26084
27018
|
{ class: "icon is-small is-hidden-mobile" },
|
|
26085
|
-
["i", {
|
|
27019
|
+
["i", {
|
|
27020
|
+
class: `${icon}`,
|
|
27021
|
+
"aria-hidden": "true"
|
|
27022
|
+
}]
|
|
26086
27023
|
]));
|
|
26087
27024
|
$a.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
26088
27025
|
"span",
|
|
@@ -26271,7 +27208,9 @@ function add_topic_card(gobj, id, text, icon, desc) {
|
|
|
26271
27208
|
class: "yui-nav-item yui-nav-card TREEDB_TOPIC_CARD",
|
|
26272
27209
|
href: "#",
|
|
26273
27210
|
"data-topic-href": id,
|
|
26274
|
-
|
|
27211
|
+
title: (0, i18next.t)(text),
|
|
27212
|
+
"data-i18n-title": text,
|
|
27213
|
+
"aria-label": (0, i18next.t)(text),
|
|
26275
27214
|
"data-i18n-aria-label": text
|
|
26276
27215
|
},
|
|
26277
27216
|
[[
|
|
@@ -27115,7 +28054,7 @@ function open_json_viewer$1(gobj, opts) {
|
|
|
27115
28054
|
}
|
|
27116
28055
|
});
|
|
27117
28056
|
} else {
|
|
27118
|
-
let $win_parent =
|
|
28057
|
+
let $win_parent = typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
27119
28058
|
priv.json_win = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-topics-jsonwin-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_WINDOW", {
|
|
27120
28059
|
$parent: $win_parent,
|
|
27121
28060
|
subscriber: null,
|
|
@@ -27242,7 +28181,9 @@ function request_print_tranger$1(gobj, path) {
|
|
|
27242
28181
|
}, gobj);
|
|
27243
28182
|
if (ret) {
|
|
27244
28183
|
(0, _yuneta_gobj_js.log_error)(ret);
|
|
27245
|
-
|
|
28184
|
+
const refusal = refusal_text$1(ret);
|
|
28185
|
+
if (refusal) answer_print_tranger_refused$1(gobj, path, { error: refusal });
|
|
28186
|
+
else answer_print_tranger_refused$1(gobj, path, { i18n: "print-tranger failed" });
|
|
27246
28187
|
return;
|
|
27247
28188
|
}
|
|
27248
28189
|
if (path) priv.drills_in_flight.add(path);
|
|
@@ -27310,9 +28251,13 @@ function ac_mt_command_answer$2(gobj, event, kw, src) {
|
|
|
27310
28251
|
}
|
|
27311
28252
|
} else gobj.priv.drills_in_flight.clear();
|
|
27312
28253
|
if (result < 0) {
|
|
27313
|
-
if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
28254
|
+
if (path && comment) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
28255
|
+
path,
|
|
28256
|
+
error: comment
|
|
28257
|
+
}, gobj);
|
|
28258
|
+
else if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
27314
28259
|
path,
|
|
27315
|
-
|
|
28260
|
+
i18n: "print-tranger failed"
|
|
27316
28261
|
}, gobj);
|
|
27317
28262
|
else yui_shell_show_error(yui_shell_of(gobj), comment || "print-tranger failed", { t: i18next.t });
|
|
27318
28263
|
return 0;
|
|
@@ -29097,7 +30042,7 @@ function present_json_popup(gobj, $box, opts) {
|
|
|
29097
30042
|
win: null
|
|
29098
30043
|
};
|
|
29099
30044
|
let win = (0, _yuneta_gobj_js.gobj_create_service)(opts.name, "C_YUI_WINDOW", {
|
|
29100
|
-
$parent: popup_mount_layer(
|
|
30045
|
+
$parent: popup_mount_layer(),
|
|
29101
30046
|
subscriber: null,
|
|
29102
30047
|
modal: false,
|
|
29103
30048
|
showMax: true,
|
|
@@ -29151,10 +30096,17 @@ function retire_popup_window(win) {
|
|
|
29151
30096
|
(0, _yuneta_gobj_js.log_warning)(`${GCLASS_NAME$5}: json window already gone: ${e}`);
|
|
29152
30097
|
}
|
|
29153
30098
|
}
|
|
29154
|
-
|
|
29155
|
-
|
|
29156
|
-
|
|
29157
|
-
|
|
30099
|
+
/************************************************************
|
|
30100
|
+
* Where a json window of this view lives: null, the WINDOW
|
|
30101
|
+
* layer of the shell, where every window lives -- below the
|
|
30102
|
+
* shell's dialogs, so a confirm asked over it paints above it
|
|
30103
|
+
* (the legacy C_YUI_MAIN '#popup-layer' when a page has one).
|
|
30104
|
+
* It was the shell's popup layer: above the drawer, in the way
|
|
30105
|
+
* of the toolbar's dropdowns, and in an order of its own no
|
|
30106
|
+
* other window could rise above.
|
|
30107
|
+
************************************************************/
|
|
30108
|
+
function popup_mount_layer() {
|
|
30109
|
+
return document.getElementById("popup-layer") || null;
|
|
29158
30110
|
}
|
|
29159
30111
|
/******************************
|
|
29160
30112
|
* Framework Methods
|
|
@@ -29769,7 +30721,10 @@ function col_title_formatter(gobj, col) {
|
|
|
29769
30721
|
let text = col_label(col, topic_name);
|
|
29770
30722
|
let attrs = {};
|
|
29771
30723
|
const NO_I18N = "\0";
|
|
29772
|
-
|
|
30724
|
+
let key = null;
|
|
30725
|
+
if (topic_name && (0, i18next.t)(topic_name + "." + col.id, { defaultValue: NO_I18N }) !== NO_I18N) key = topic_name + "." + col.id;
|
|
30726
|
+
else if ((0, i18next.t)(col.id, { defaultValue: NO_I18N }) !== NO_I18N) key = col.id;
|
|
30727
|
+
if (key) attrs.i18n = key;
|
|
29773
30728
|
return (0, _yuneta_gobj_js.createElement2)([
|
|
29774
30729
|
"span",
|
|
29775
30730
|
attrs,
|
|
@@ -29863,6 +30818,9 @@ function create_tabulator(gobj) {
|
|
|
29863
30818
|
colDef.editable = function() {
|
|
29864
30819
|
return (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "editable") && !(0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "readonly");
|
|
29865
30820
|
};
|
|
30821
|
+
yui_tabulator_name_editor(colDef, function() {
|
|
30822
|
+
return col_label(col, (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "topic_name"));
|
|
30823
|
+
});
|
|
29866
30824
|
}
|
|
29867
30825
|
const FILTERABLE = [
|
|
29868
30826
|
"string",
|
|
@@ -71221,7 +72179,7 @@ function open_json_viewer(gobj) {
|
|
|
71221
72179
|
});
|
|
71222
72180
|
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
71223
72181
|
} else {
|
|
71224
|
-
let $win_parent =
|
|
72182
|
+
let $win_parent = typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
71225
72183
|
priv.json_win = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-jsonwin-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_WINDOW", {
|
|
71226
72184
|
$parent: $win_parent,
|
|
71227
72185
|
subscriber: null,
|
|
@@ -71335,7 +72293,9 @@ function request_print_tranger(gobj, path) {
|
|
|
71335
72293
|
}, gobj);
|
|
71336
72294
|
if (ret) {
|
|
71337
72295
|
(0, _yuneta_gobj_js.log_error)(ret);
|
|
71338
|
-
|
|
72296
|
+
const refusal = refusal_text(ret);
|
|
72297
|
+
if (refusal) answer_print_tranger_refused(gobj, path, { error: refusal });
|
|
72298
|
+
else answer_print_tranger_refused(gobj, path, { i18n: "print-tranger failed" });
|
|
71339
72299
|
return;
|
|
71340
72300
|
}
|
|
71341
72301
|
if (path) priv.drills_in_flight.add(path);
|
|
@@ -71740,9 +72700,13 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
|
|
|
71740
72700
|
}
|
|
71741
72701
|
} else priv.drills_in_flight.clear();
|
|
71742
72702
|
if (result < 0) {
|
|
71743
|
-
if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
72703
|
+
if (path && comment) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
72704
|
+
path,
|
|
72705
|
+
error: comment
|
|
72706
|
+
}, gobj);
|
|
72707
|
+
else if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
71744
72708
|
path,
|
|
71745
|
-
|
|
72709
|
+
i18n: "print-tranger failed"
|
|
71746
72710
|
}, gobj);
|
|
71747
72711
|
else yui_shell_show_error(yui_shell_of(gobj), comment || "print-tranger failed", { t: i18next.t });
|
|
71748
72712
|
return 0;
|
|
@@ -83334,7 +84298,8 @@ function apply_dev_traces() {
|
|
|
83334
84298
|
* Shell-agnostic: the legacy C_YUI_MAIN shell has a
|
|
83335
84299
|
* '#top-layer' stacking element; the new C_YUI_SHELL does not.
|
|
83336
84300
|
* We pass that element when present, otherwise null — C_YUI_WINDOW
|
|
83337
|
-
*
|
|
84301
|
+
* then takes the window layer of the shell (document.body while
|
|
84302
|
+
* there is none), and follows the shell across a logout.
|
|
83338
84303
|
************************************************************/
|
|
83339
84304
|
function setup_dev(self, show) {
|
|
83340
84305
|
if (show) {
|
|
@@ -83424,7 +84389,8 @@ var WIN_NAME$1 = "Frontend-View-Window";
|
|
|
83424
84389
|
* Shell-agnostic: the legacy C_YUI_MAIN shell has a
|
|
83425
84390
|
* '#top-layer' stacking element; the new C_YUI_SHELL does not.
|
|
83426
84391
|
* We pass that element when present, otherwise null — C_YUI_WINDOW
|
|
83427
|
-
*
|
|
84392
|
+
* then takes the window layer of the shell (document.body while
|
|
84393
|
+
* there is none), and follows the shell across a logout.
|
|
83428
84394
|
*
|
|
83429
84395
|
* Returns the window gobj, or null.
|
|
83430
84396
|
************************************************************/
|