@yuneta/gobj-ui 7.26.33 → 7.26.35
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 +1053 -144
- package/dist/gobj-ui.es.js +1053 -144
- package/package.json +2 -2
- package/scripts/validate-locales.mjs +672 -96
- package/src/c_yui_form.js +229 -11
- 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 +156 -44
- 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/form_table_validator.wiring.test.js +192 -0
- package/src/form_template_field.wiring.test.js +21 -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 +308 -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,13 +5328,12 @@ 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
5338
|
mql_handler: null
|
|
5059
5339
|
};
|
|
@@ -5067,7 +5347,6 @@ var __gclass__$20 = null;
|
|
|
5067
5347
|
function mt_create$20(gobj) {
|
|
5068
5348
|
let priv = gobj.priv;
|
|
5069
5349
|
priv.windows = [];
|
|
5070
|
-
priv.z = 10;
|
|
5071
5350
|
if (((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "dock_mode") || "floating") === "responsive") {
|
|
5072
5351
|
let q = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "responsive_query") || "(max-width: 768px)";
|
|
5073
5352
|
priv.mql = window.matchMedia(q);
|
|
@@ -5077,6 +5356,7 @@ function mt_create$20(gobj) {
|
|
|
5077
5356
|
priv.mql.addEventListener("change", priv.mql_handler);
|
|
5078
5357
|
}
|
|
5079
5358
|
build_dock(gobj);
|
|
5359
|
+
yui_shell_watch_changes(gobj);
|
|
5080
5360
|
const subscriber = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(gobj, "subscriber");
|
|
5081
5361
|
if (subscriber) (0, _yuneta_gobj_js.gobj_subscribe_event)(gobj, null, {}, subscriber);
|
|
5082
5362
|
}
|
|
@@ -5085,6 +5365,7 @@ function mt_create$20(gobj) {
|
|
|
5085
5365
|
***************************************************************/
|
|
5086
5366
|
function mt_destroy$20(gobj) {
|
|
5087
5367
|
let priv = gobj.priv;
|
|
5368
|
+
yui_shell_unwatch_changes(gobj);
|
|
5088
5369
|
if (priv.mql && priv.mql_handler) {
|
|
5089
5370
|
priv.mql.removeEventListener("change", priv.mql_handler);
|
|
5090
5371
|
priv.mql = null;
|
|
@@ -5134,10 +5415,18 @@ function ensure_dock_style() {
|
|
|
5134
5415
|
}
|
|
5135
5416
|
.yui-dock-chip {
|
|
5136
5417
|
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);
|
|
5418
|
+
padding: 0 5px 0 0; border: 1px solid var(--bulma-border); border-radius: 7px;
|
|
5419
|
+
background: var(--bulma-scheme-main); color: var(--bulma-text); white-space: nowrap;
|
|
5139
5420
|
}
|
|
5140
5421
|
.yui-dock-chip:hover { border-color: var(--bulma-text-weak); }
|
|
5422
|
+
/* The chip is the look; its toggle a button that adds none, and
|
|
5423
|
+
* takes the pill's padding, so the whole label is what a press lands
|
|
5424
|
+
* on and the chip reads as one pill with its ✕ at the end. */
|
|
5425
|
+
.yui-dock-chip-toggle {
|
|
5426
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
5427
|
+
padding: 4px 0 4px 11px; margin: 0; border: 0; border-radius: 7px 0 0 7px;
|
|
5428
|
+
background: transparent; font: inherit; color: inherit; cursor: pointer; white-space: nowrap;
|
|
5429
|
+
}
|
|
5141
5430
|
/* The BORDER says active, not the text: blue ink on a blue tint is
|
|
5142
5431
|
* the same hue on itself -- 4.49:1 on the light chip, under the 4.5
|
|
5143
5432
|
* its 12px label needs. The label takes the text colour (11:1). */
|
|
@@ -5227,10 +5516,33 @@ function apply_placement(gobj) {
|
|
|
5227
5516
|
"bottom-left",
|
|
5228
5517
|
"bottom-right"
|
|
5229
5518
|
]) $dock.classList.toggle(`yui-dock--${c}`, !inline && c === corner);
|
|
5230
|
-
let target = inline ? $inline : (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$parent") ||
|
|
5519
|
+
let target = inline ? $inline : (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$parent") || dock_place(gobj);
|
|
5231
5520
|
if ($dock.parentNode !== target) target.appendChild($dock);
|
|
5232
5521
|
}
|
|
5233
5522
|
/************************************************************
|
|
5523
|
+
* Where the FLOATING dock lives when the app names no
|
|
5524
|
+
* `$parent`: the popup layer of the shell, at the top of it.
|
|
5525
|
+
*
|
|
5526
|
+
* It was document.body at z-index 1000000, and that put it
|
|
5527
|
+
* above the WHOLE shell -- `.yui-shell` is a stacking context
|
|
5528
|
+
* of its own, so its dialogs (modal layer, 99) and toasts (120)
|
|
5529
|
+
* counted only inside it: the dock stayed clickable over a
|
|
5530
|
+
* dialog's backdrop (a window could be closed from its chip
|
|
5531
|
+
* while its own "all changes will be lost" question was open),
|
|
5532
|
+
* and it covered a toast where they met.
|
|
5533
|
+
*
|
|
5534
|
+
* The popup layer, not the window layer: the dock has to stay
|
|
5535
|
+
* above EVERY window, and windows live in two layers -- the
|
|
5536
|
+
* window layer (no `$parent`) and the popup layer, where the
|
|
5537
|
+
* site map and the JSON windows of the treedb views put theirs.
|
|
5538
|
+
* Above both; below the dialogs, the toasts and the loading
|
|
5539
|
+
* cover. No shell (before the first, between a logout and the
|
|
5540
|
+
* next login): the body.
|
|
5541
|
+
************************************************************/
|
|
5542
|
+
function dock_place(gobj) {
|
|
5543
|
+
return yui_shell_popup_layer(yui_shell_of(gobj)) || document.body;
|
|
5544
|
+
}
|
|
5545
|
+
/************************************************************
|
|
5234
5546
|
* Destroy the dock element.
|
|
5235
5547
|
************************************************************/
|
|
5236
5548
|
function destroy_dock(gobj) {
|
|
@@ -5307,7 +5619,6 @@ function set_active(gobj, entry) {
|
|
|
5307
5619
|
* Bring a window to front and mark it active/visible.
|
|
5308
5620
|
************************************************************/
|
|
5309
5621
|
function focus_entry(gobj, entry) {
|
|
5310
|
-
let priv = gobj.priv;
|
|
5311
5622
|
let $win = (0, _yuneta_gobj_js.gobj_read_attr)(entry.gobj, "$container");
|
|
5312
5623
|
if ($win) {
|
|
5313
5624
|
if (entry.minimized) {
|
|
@@ -5315,8 +5626,7 @@ function focus_entry(gobj, entry) {
|
|
|
5315
5626
|
entry.minimized = false;
|
|
5316
5627
|
if (entry.$chip) entry.$chip.classList.remove("is-min");
|
|
5317
5628
|
}
|
|
5318
|
-
|
|
5319
|
-
$win.style.zIndex = priv.z;
|
|
5629
|
+
yui_shell_raise_window($win);
|
|
5320
5630
|
}
|
|
5321
5631
|
set_active(gobj, entry);
|
|
5322
5632
|
}
|
|
@@ -5383,57 +5693,57 @@ function ac_register_window(gobj, event, kw, src) {
|
|
|
5383
5693
|
{ class: "yui-dock-label-kind" },
|
|
5384
5694
|
text_node(title)
|
|
5385
5695
|
]);
|
|
5696
|
+
let chip_seq = ++__chip_seq__;
|
|
5697
|
+
let label_ids = label_items.map(function(item, i) {
|
|
5698
|
+
item[1].id = `yui-dock-chip-${chip_seq}-${i}`;
|
|
5699
|
+
return item[1].id;
|
|
5700
|
+
});
|
|
5386
5701
|
let entry = {
|
|
5387
5702
|
gobj: win,
|
|
5388
5703
|
$chip: null,
|
|
5389
5704
|
minimized: false
|
|
5390
5705
|
};
|
|
5706
|
+
let window_name = (0, _yuneta_gobj_js.gobj_full_name)(win);
|
|
5391
5707
|
let $chip = (0, _yuneta_gobj_js.createElement2)([
|
|
5392
5708
|
"div",
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5709
|
+
{ class: "DOCK_CHIP yui-dock-chip" },
|
|
5710
|
+
[[
|
|
5711
|
+
"button",
|
|
5712
|
+
Object.assign({
|
|
5713
|
+
class: "DOCK_CHIP_TOGGLE yui-dock-chip-toggle",
|
|
5714
|
+
type: "button",
|
|
5715
|
+
title,
|
|
5716
|
+
"aria-label": title,
|
|
5717
|
+
"aria-labelledby": label_ids.join(" ")
|
|
5718
|
+
}, !prefix && title_key ? {
|
|
5719
|
+
"data-i18n-title": title_key,
|
|
5720
|
+
"data-i18n-aria-label": title_key
|
|
5721
|
+
} : {}),
|
|
5722
|
+
[chip_lead(kw.icon), [
|
|
5402
5723
|
"span",
|
|
5403
5724
|
{ class: "yui-dock-label" },
|
|
5404
5725
|
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) => {
|
|
5726
|
+
]],
|
|
5727
|
+
{ click: (evt) => {
|
|
5425
5728
|
evt.stopPropagation();
|
|
5426
|
-
|
|
5729
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_WINDOW", { window: window_name }, gobj);
|
|
5730
|
+
} }
|
|
5731
|
+
], [
|
|
5732
|
+
"button",
|
|
5733
|
+
{
|
|
5734
|
+
class: "DOCK_CHIP_CLOSE yui-dock-close",
|
|
5735
|
+
type: "button",
|
|
5736
|
+
title: (0, i18next.t)("close"),
|
|
5737
|
+
"data-i18n-title": "close",
|
|
5738
|
+
"aria-label": (0, i18next.t)("close"),
|
|
5739
|
+
"data-i18n-aria-label": "close"
|
|
5427
5740
|
},
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
}
|
|
5435
|
-
}
|
|
5436
|
-
}
|
|
5741
|
+
(0, _yuneta_gobj_js.html_markup)(WC_X),
|
|
5742
|
+
{ click: (evt) => {
|
|
5743
|
+
evt.stopPropagation();
|
|
5744
|
+
(0, _yuneta_gobj_js.gobj_send_event)(entry.gobj, "EV_CLOSE_WINDOW", {}, gobj);
|
|
5745
|
+
} }
|
|
5746
|
+
]]
|
|
5437
5747
|
]);
|
|
5438
5748
|
entry.$chip = $chip;
|
|
5439
5749
|
priv.windows.push(entry);
|
|
@@ -5477,6 +5787,41 @@ function ac_focus_window(gobj, event, kw, src) {
|
|
|
5477
5787
|
if (entry) focus_entry(gobj, entry);
|
|
5478
5788
|
return 0;
|
|
5479
5789
|
}
|
|
5790
|
+
/************************************************************
|
|
5791
|
+
* EV_TOGGLE_WINDOW { window } -- the toggle of a chip of THIS
|
|
5792
|
+
* dock was pressed: bring a minimized or covered window to the
|
|
5793
|
+
* front, send the one in front to the dock. Only the dock's own
|
|
5794
|
+
* chip sends it (src is the dock): the events a window sends
|
|
5795
|
+
* about itself come from the window, and this one from the chip
|
|
5796
|
+
* that names it.
|
|
5797
|
+
************************************************************/
|
|
5798
|
+
function ac_toggle_window(gobj, event, kw, src) {
|
|
5799
|
+
let priv = gobj.priv;
|
|
5800
|
+
if (src !== gobj) {
|
|
5801
|
+
(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)}`);
|
|
5802
|
+
return -1;
|
|
5803
|
+
}
|
|
5804
|
+
let name = kw && kw.window;
|
|
5805
|
+
let entry = priv.windows.find((e) => (0, _yuneta_gobj_js.gobj_full_name)(e.gobj) === name);
|
|
5806
|
+
if (!entry) {
|
|
5807
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event}: no window '${name}' in the dock`);
|
|
5808
|
+
return -1;
|
|
5809
|
+
}
|
|
5810
|
+
on_chip_click(gobj, entry);
|
|
5811
|
+
return 0;
|
|
5812
|
+
}
|
|
5813
|
+
/************************************************************
|
|
5814
|
+
* EV_SHELL_CHANGED -- a shell was built, or is being destroyed
|
|
5815
|
+
* (yui_shell_watch_changes()). The dock's place -- the shell's
|
|
5816
|
+
* popup layer, or its zone when inline -- may have gone with
|
|
5817
|
+
* it, or be in the new one: place it again. Up to 7.26.34 an
|
|
5818
|
+
* inline dock stayed in the destroyed shell's zone after a
|
|
5819
|
+
* logout, detached, until a window registered.
|
|
5820
|
+
************************************************************/
|
|
5821
|
+
function ac_shell_changed(gobj, event, kw, src) {
|
|
5822
|
+
apply_placement(gobj);
|
|
5823
|
+
return 0;
|
|
5824
|
+
}
|
|
5480
5825
|
/***************************
|
|
5481
5826
|
* FSM
|
|
5482
5827
|
***************************/
|
|
@@ -5496,7 +5841,9 @@ function create_gclass$20(gclass_name) {
|
|
|
5496
5841
|
["EV_REGISTER_WINDOW", 0],
|
|
5497
5842
|
["EV_UNREGISTER_WINDOW", 0],
|
|
5498
5843
|
["EV_MINIMIZE_WINDOW", 0],
|
|
5499
|
-
["EV_FOCUS_WINDOW", 0]
|
|
5844
|
+
["EV_FOCUS_WINDOW", 0],
|
|
5845
|
+
["EV_TOGGLE_WINDOW", 0],
|
|
5846
|
+
["EV_SHELL_CHANGED", 0]
|
|
5500
5847
|
], [["ST_IDLE", [
|
|
5501
5848
|
[
|
|
5502
5849
|
"EV_REGISTER_WINDOW",
|
|
@@ -5517,6 +5864,16 @@ function create_gclass$20(gclass_name) {
|
|
|
5517
5864
|
"EV_FOCUS_WINDOW",
|
|
5518
5865
|
ac_focus_window,
|
|
5519
5866
|
null
|
|
5867
|
+
],
|
|
5868
|
+
[
|
|
5869
|
+
"EV_TOGGLE_WINDOW",
|
|
5870
|
+
ac_toggle_window,
|
|
5871
|
+
null
|
|
5872
|
+
],
|
|
5873
|
+
[
|
|
5874
|
+
"EV_SHELL_CHANGED",
|
|
5875
|
+
ac_shell_changed,
|
|
5876
|
+
null
|
|
5520
5877
|
]
|
|
5521
5878
|
]]], gmt$20, 0, attrs_table$20, PRIVATE_DATA$20, 0, 0, 0, 0);
|
|
5522
5879
|
if (!__gclass__$20) return -1;
|
|
@@ -6796,6 +7153,41 @@ function yui_tabulator_name_row_selects(table, t) {
|
|
|
6796
7153
|
}
|
|
6797
7154
|
} catch (e) {}
|
|
6798
7155
|
}
|
|
7156
|
+
/***************************************************************
|
|
7157
|
+
* Name the EDITOR of an editable column: the box Tabulator draws
|
|
7158
|
+
* in a cell while it is edited (input, number, textarea, list,
|
|
7159
|
+
* tickCross, date...).
|
|
7160
|
+
*
|
|
7161
|
+
* Tabulator gives it nothing -- no label, no aria-label, no title
|
|
7162
|
+
* -- so a reader lands in an anonymous edit box. Its name is the
|
|
7163
|
+
* column's: a cell is edited under its column's title. Asked at
|
|
7164
|
+
* the MOMENT of editing: Tabulator takes `editorParams` as a
|
|
7165
|
+
* function of the cell, and every built-in editor writes the
|
|
7166
|
+
* `elementAttributes` it answers onto the element it draws. So
|
|
7167
|
+
* the name is in the language of that moment, with nothing to
|
|
7168
|
+
* re-apply after a language change or a rebuild of the columns
|
|
7169
|
+
* -- the twin of the header filters above, which have to be
|
|
7170
|
+
* renamed after every render.
|
|
7171
|
+
*
|
|
7172
|
+
* `name_of(cell)` answers the column's title, TRANSLATED (the
|
|
7173
|
+
* view's own label: a cascade, a schema header); "" names
|
|
7174
|
+
* nothing. What `editorParams` the column had is kept, its own
|
|
7175
|
+
* `elementAttributes` too; a name it set itself wins.
|
|
7176
|
+
***************************************************************/
|
|
7177
|
+
function yui_tabulator_name_editor(column_def, name_of) {
|
|
7178
|
+
if (!column_def || !column_def.editor || typeof name_of !== "function") return;
|
|
7179
|
+
let base = column_def.editorParams;
|
|
7180
|
+
column_def.editorParams = function(cell) {
|
|
7181
|
+
let params = typeof base === "function" ? base(cell) : base || {};
|
|
7182
|
+
let name = name_of(cell);
|
|
7183
|
+
if (!name) return params;
|
|
7184
|
+
let attrs = Object.assign({
|
|
7185
|
+
"aria-label": name,
|
|
7186
|
+
title: name
|
|
7187
|
+
}, params.elementAttributes || {});
|
|
7188
|
+
return Object.assign({}, params, { elementAttributes: attrs });
|
|
7189
|
+
};
|
|
7190
|
+
}
|
|
6799
7191
|
function yui_tabulator_relocalize(table, t) {
|
|
6800
7192
|
if (!table) return;
|
|
6801
7193
|
try {
|
|
@@ -7316,6 +7708,7 @@ function yui_file_control(gobj, { name, value, readonly, accept, on_pick }) {
|
|
|
7316
7708
|
{
|
|
7317
7709
|
type: "button",
|
|
7318
7710
|
class: "FILE_PICK button is-small",
|
|
7711
|
+
title: (0, i18next.t)("choose a file"),
|
|
7319
7712
|
"data-i18n-title": "choose a file",
|
|
7320
7713
|
"aria-label": (0, i18next.t)("choose a file"),
|
|
7321
7714
|
"data-i18n-aria-label": "choose a file"
|
|
@@ -7334,6 +7727,7 @@ function yui_file_control(gobj, { name, value, readonly, accept, on_pick }) {
|
|
|
7334
7727
|
{
|
|
7335
7728
|
type: "button",
|
|
7336
7729
|
class: "FILE_CLEAR button is-small",
|
|
7730
|
+
title: (0, i18next.t)("remove the file"),
|
|
7337
7731
|
"data-i18n-title": "remove the file",
|
|
7338
7732
|
"aria-label": (0, i18next.t)("remove the file"),
|
|
7339
7733
|
"data-i18n-aria-label": "remove the file"
|
|
@@ -8682,6 +9076,293 @@ function json_editor_value(content) {
|
|
|
8682
9076
|
return JSON.stringify(content.json);
|
|
8683
9077
|
}
|
|
8684
9078
|
//#endregion
|
|
9079
|
+
//#region src/form_json_editor_names.js
|
|
9080
|
+
/***********************************************************************
|
|
9081
|
+
* form_json_editor_names.js
|
|
9082
|
+
*
|
|
9083
|
+
* The NAMES of the buttons vanilla-jsoneditor draws in its menu
|
|
9084
|
+
* (a json field of C_YUI_FORM): in the app's language, and with an
|
|
9085
|
+
* aria-label.
|
|
9086
|
+
*
|
|
9087
|
+
* The editor draws them itself, in English, with a `title` and
|
|
9088
|
+
* nothing else: "Format JSON: add proper indentation and new lines
|
|
9089
|
+
* (Ctrl+I)", "Undo (Ctrl+Z)", and three mode buttons whose text is
|
|
9090
|
+
* "text", "tree" and "table" (REV-CLOUD V23.5.6). Two hooks reach
|
|
9091
|
+
* them, and both are needed:
|
|
9092
|
+
*
|
|
9093
|
+
* - json_editor_menu_items(), the editor's `onRenderMenu`: the
|
|
9094
|
+
* items it is about to draw, with each title translated (its
|
|
9095
|
+
* shortcut kept) and the mode buttons' text too. Svelte draws
|
|
9096
|
+
* from these, so a button born in a re-render is born named.
|
|
9097
|
+
* - name_json_editor_menu(), after the render, from the form's
|
|
9098
|
+
* FSM: the aria-label of each button, with its key, so
|
|
9099
|
+
* refresh_language() re-translates it, and the state of the
|
|
9100
|
+
* mode buttons (aria-pressed). A menu item has no field for
|
|
9101
|
+
* either.
|
|
9102
|
+
*
|
|
9103
|
+
* A button is known by the CLASS the editor gives it (`jse-format`,
|
|
9104
|
+
* `jse-undo`...), never by its English title: a class is what the
|
|
9105
|
+
* editor's own stylesheet relies on. A button not listed here keeps
|
|
9106
|
+
* the editor's words.
|
|
9107
|
+
*
|
|
9108
|
+
* Its CONTEXT MENU (`onRenderContextMenu`,
|
|
9109
|
+
* json_editor_context_menu_items()) has no class on its items, so
|
|
9110
|
+
* an item is known by what it IS and where it IS: the icon the
|
|
9111
|
+
* editor draws it with (a FontAwesome name: `paste`, `scissors`),
|
|
9112
|
+
* the column of the menu it stands in, its place in a dropdown
|
|
9113
|
+
* (the main button, the first or the second of its list), the
|
|
9114
|
+
* mode of the editor (tree or table) -- never by its words. Its
|
|
9115
|
+
* text and title go back translated; after the render the same
|
|
9116
|
+
* pass names its buttons, and the arrow of each dropdown, which
|
|
9117
|
+
* the editor draws with no name at all.
|
|
9118
|
+
*
|
|
9119
|
+
* Not reached, because the editor gives them no hook: its search
|
|
9120
|
+
* box, its repair messages, the tip at the foot of the context
|
|
9121
|
+
* menu, and its modals (sort, transform). They stay in its
|
|
9122
|
+
* English.
|
|
9123
|
+
*
|
|
9124
|
+
* Copyright (c) 2026, ArtGins.
|
|
9125
|
+
* All Rights Reserved.
|
|
9126
|
+
***********************************************************************/
|
|
9127
|
+
/***************************************************************
|
|
9128
|
+
* Constants
|
|
9129
|
+
***************************************************************/
|
|
9130
|
+
var JSON_EDITOR_BUTTON_KEYS = {
|
|
9131
|
+
"jse-expand-all": "expand all",
|
|
9132
|
+
"jse-collapse-all": "collapse all",
|
|
9133
|
+
"jse-search": "search",
|
|
9134
|
+
"jse-copy": "copy",
|
|
9135
|
+
"jse-undo": "undo",
|
|
9136
|
+
"jse-redo": "redo",
|
|
9137
|
+
"jse-cancel": "cancel",
|
|
9138
|
+
"jse-format": "format json",
|
|
9139
|
+
"jse-compact": "compact json",
|
|
9140
|
+
"jse-sort": "sort",
|
|
9141
|
+
"jse-transform": "transform",
|
|
9142
|
+
"jse-contextmenu": "open context menu"
|
|
9143
|
+
};
|
|
9144
|
+
var JSON_EDITOR_MODE_NAME_KEYS = {
|
|
9145
|
+
text: "text view",
|
|
9146
|
+
tree: "tree view",
|
|
9147
|
+
table: "table view"
|
|
9148
|
+
};
|
|
9149
|
+
var JSON_EDITOR_MODE_TEXT_KEYS = {
|
|
9150
|
+
text: "text mode",
|
|
9151
|
+
tree: "tree mode",
|
|
9152
|
+
table: "table mode"
|
|
9153
|
+
};
|
|
9154
|
+
var MODE_CLASS = "yui-jse-mode-";
|
|
9155
|
+
var SHORTCUT = /\((?:Ctrl|Cmd|⌘)[^()]*\)\s*$/;
|
|
9156
|
+
var CONTEXT_BUTTON_KEYS = {
|
|
9157
|
+
"pen": "edit key",
|
|
9158
|
+
"paste": "paste",
|
|
9159
|
+
"clone": "duplicate",
|
|
9160
|
+
"crop-simple": "extract",
|
|
9161
|
+
"arrow-down-short-wide": "sort",
|
|
9162
|
+
"filter": "transform",
|
|
9163
|
+
"trash-can": "remove",
|
|
9164
|
+
"square-caret-up": "insert before",
|
|
9165
|
+
"square-caret-down": "insert after"
|
|
9166
|
+
};
|
|
9167
|
+
var CONTEXT_ROW_BUTTON_KEYS = {
|
|
9168
|
+
"pen": "edit row",
|
|
9169
|
+
"clone": "duplicate row",
|
|
9170
|
+
"trash-can": "remove row"
|
|
9171
|
+
};
|
|
9172
|
+
var CONTEXT_DROPDOWN_MAIN_KEYS = {
|
|
9173
|
+
"pen": "edit value",
|
|
9174
|
+
"scissors": "cut",
|
|
9175
|
+
"copy": "copy"
|
|
9176
|
+
};
|
|
9177
|
+
var CONTEXT_DROPDOWN_FIRST_KEYS = {
|
|
9178
|
+
"pen": "edit value",
|
|
9179
|
+
"scissors": "cut formatted",
|
|
9180
|
+
"copy": "copy formatted"
|
|
9181
|
+
};
|
|
9182
|
+
var CONTEXT_DROPDOWN_SECOND_KEYS = {
|
|
9183
|
+
"pen": "enforce string",
|
|
9184
|
+
"scissors": "cut compacted",
|
|
9185
|
+
"copy": "copy compacted"
|
|
9186
|
+
};
|
|
9187
|
+
var CONTEXT_TARGET_KEYS = {
|
|
9188
|
+
"0": "structure",
|
|
9189
|
+
"1": "object",
|
|
9190
|
+
"2": "array",
|
|
9191
|
+
"3": "value"
|
|
9192
|
+
};
|
|
9193
|
+
var TARGET_ICONS = ["arrow-right-arrow-left", "plus"];
|
|
9194
|
+
var CONTEXT_LABEL_KEYS = {
|
|
9195
|
+
convert: "convert to",
|
|
9196
|
+
insert: "insert",
|
|
9197
|
+
cell: "table cell",
|
|
9198
|
+
row: "table row"
|
|
9199
|
+
};
|
|
9200
|
+
/***************************
|
|
9201
|
+
* Local Methods
|
|
9202
|
+
***************************/
|
|
9203
|
+
function has_key(table, name) {
|
|
9204
|
+
return Object.prototype.hasOwnProperty.call(table, name);
|
|
9205
|
+
}
|
|
9206
|
+
function button_class(classes) {
|
|
9207
|
+
return (Array.isArray(classes) ? classes : String(classes || "").split(/\s+/)).find((c) => has_key(JSON_EDITOR_BUTTON_KEYS, c)) || "";
|
|
9208
|
+
}
|
|
9209
|
+
function mode_of_item(item) {
|
|
9210
|
+
if (String(item.className || "").split(/\s+/).indexOf("jse-group-button") < 0) return "";
|
|
9211
|
+
return has_key(JSON_EDITOR_MODE_NAME_KEYS, item.text) ? item.text : "";
|
|
9212
|
+
}
|
|
9213
|
+
function icon_of(item) {
|
|
9214
|
+
return item && item.icon && typeof item.icon.iconName === "string" ? item.icon.iconName : "";
|
|
9215
|
+
}
|
|
9216
|
+
function named_item(item, name) {
|
|
9217
|
+
let m = SHORTCUT.exec(String(item.title || ""));
|
|
9218
|
+
return Object.assign({}, item, {
|
|
9219
|
+
text: name,
|
|
9220
|
+
title: m ? `${name} ${m[0].trim()}` : name
|
|
9221
|
+
});
|
|
9222
|
+
}
|
|
9223
|
+
function context_dropdown(item) {
|
|
9224
|
+
let icon = icon_of(item.main);
|
|
9225
|
+
if (!has_key(CONTEXT_DROPDOWN_MAIN_KEYS, icon)) return item;
|
|
9226
|
+
let list = Array.isArray(item.items) ? item.items : [];
|
|
9227
|
+
return Object.assign({}, item, {
|
|
9228
|
+
main: named_item(item.main, (0, i18next.t)(CONTEXT_DROPDOWN_MAIN_KEYS[icon])),
|
|
9229
|
+
items: list.map(function(it, i) {
|
|
9230
|
+
if (!it || it.type !== "button") return it;
|
|
9231
|
+
if (i === 0) return named_item(it, (0, i18next.t)(CONTEXT_DROPDOWN_FIRST_KEYS[icon]));
|
|
9232
|
+
if (i === 1) return named_item(it, (0, i18next.t)(CONTEXT_DROPDOWN_SECOND_KEYS[icon]));
|
|
9233
|
+
return it;
|
|
9234
|
+
})
|
|
9235
|
+
});
|
|
9236
|
+
}
|
|
9237
|
+
function context_button(item, row_column) {
|
|
9238
|
+
let icon = icon_of(item);
|
|
9239
|
+
if (row_column && has_key(CONTEXT_ROW_BUTTON_KEYS, icon)) return named_item(item, (0, i18next.t)(CONTEXT_ROW_BUTTON_KEYS[icon]));
|
|
9240
|
+
if (has_key(CONTEXT_BUTTON_KEYS, icon)) return named_item(item, (0, i18next.t)(CONTEXT_BUTTON_KEYS[icon]));
|
|
9241
|
+
return item;
|
|
9242
|
+
}
|
|
9243
|
+
function context_column(item, table, index) {
|
|
9244
|
+
let list = Array.isArray(item.items) ? item.items : [];
|
|
9245
|
+
let buttons = list.filter((it) => it && it.type === "button");
|
|
9246
|
+
let targets = !table && buttons.length > 0 && buttons.every((it) => TARGET_ICONS.indexOf(icon_of(it)) >= 0);
|
|
9247
|
+
let row_column = table && index === 1;
|
|
9248
|
+
let label_kind = "";
|
|
9249
|
+
if (table) label_kind = index === 0 ? "cell" : index === 1 ? "row" : "";
|
|
9250
|
+
else if (targets) label_kind = icon_of(buttons[0]) === "plus" ? "insert" : "convert";
|
|
9251
|
+
let target = 0;
|
|
9252
|
+
let insert_row = 0;
|
|
9253
|
+
return Object.assign({}, item, { items: list.map(function(it) {
|
|
9254
|
+
if (!it || typeof it !== "object") return it;
|
|
9255
|
+
if (it.type === "label") return label_kind ? Object.assign({}, it, { text: (0, i18next.t)(CONTEXT_LABEL_KEYS[label_kind]) }) : it;
|
|
9256
|
+
if (it.type === "dropdown-button") return context_dropdown(it);
|
|
9257
|
+
if (it.type !== "button") return it;
|
|
9258
|
+
if (targets) return named_item(it, (0, i18next.t)(CONTEXT_TARGET_KEYS[String(target++)]));
|
|
9259
|
+
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"]));
|
|
9260
|
+
return context_button(it, row_column);
|
|
9261
|
+
}) });
|
|
9262
|
+
}
|
|
9263
|
+
function context_item(item, table) {
|
|
9264
|
+
if (!item || typeof item !== "object") return item;
|
|
9265
|
+
if (item.type === "row") {
|
|
9266
|
+
let column = 0;
|
|
9267
|
+
let list = Array.isArray(item.items) ? item.items : [];
|
|
9268
|
+
return Object.assign({}, item, { items: list.map(function(it) {
|
|
9269
|
+
if (it && it.type === "column") return context_column(it, table, column++);
|
|
9270
|
+
return context_item(it, table);
|
|
9271
|
+
}) });
|
|
9272
|
+
}
|
|
9273
|
+
if (item.type === "dropdown-button") return context_dropdown(item);
|
|
9274
|
+
if (item.type === "button") return context_button(item, false);
|
|
9275
|
+
return item;
|
|
9276
|
+
}
|
|
9277
|
+
function mode_of_button($b) {
|
|
9278
|
+
for (let c of $b.classList) if (c.indexOf(MODE_CLASS) === 0) {
|
|
9279
|
+
let mode = c.slice(13);
|
|
9280
|
+
if (has_key(JSON_EDITOR_MODE_NAME_KEYS, mode)) return mode;
|
|
9281
|
+
}
|
|
9282
|
+
return "";
|
|
9283
|
+
}
|
|
9284
|
+
/***************************
|
|
9285
|
+
* Public
|
|
9286
|
+
***************************/
|
|
9287
|
+
/************************************************************
|
|
9288
|
+
* The editor's `onRenderMenu`: the items it is about to draw,
|
|
9289
|
+
* translated. A title keeps the editor's shortcut after the
|
|
9290
|
+
* translated name ("Deshacer (Ctrl+Z)"); a mode button gets its
|
|
9291
|
+
* mode's name as title and its short text translated, and a class
|
|
9292
|
+
* that says its mode. Anything else is returned as it came.
|
|
9293
|
+
*
|
|
9294
|
+
* Pure: what it answers is data for the editor to draw.
|
|
9295
|
+
************************************************************/
|
|
9296
|
+
function json_editor_menu_items(items) {
|
|
9297
|
+
if (!Array.isArray(items)) return items;
|
|
9298
|
+
return items.map(function(item) {
|
|
9299
|
+
if (!item || item.type !== "button") return item;
|
|
9300
|
+
let mode = mode_of_item(item);
|
|
9301
|
+
if (mode) return Object.assign({}, item, {
|
|
9302
|
+
className: `${item.className} ${MODE_CLASS}${mode}`,
|
|
9303
|
+
title: (0, i18next.t)(JSON_EDITOR_MODE_NAME_KEYS[mode]),
|
|
9304
|
+
text: (0, i18next.t)(JSON_EDITOR_MODE_TEXT_KEYS[mode])
|
|
9305
|
+
});
|
|
9306
|
+
let cls = button_class(item.className);
|
|
9307
|
+
if (!cls) return item;
|
|
9308
|
+
let m = SHORTCUT.exec(String(item.title || ""));
|
|
9309
|
+
let name = (0, i18next.t)(JSON_EDITOR_BUTTON_KEYS[cls]);
|
|
9310
|
+
return Object.assign({}, item, { title: m ? `${name} ${m[0].trim()}` : name });
|
|
9311
|
+
});
|
|
9312
|
+
}
|
|
9313
|
+
/************************************************************
|
|
9314
|
+
* The editor's `onRenderContextMenu`: the items it is about to
|
|
9315
|
+
* draw, translated -- each known by its icon and its place, never
|
|
9316
|
+
* by its words (context_item()). Anything the module does not
|
|
9317
|
+
* know comes back as it came: a newer editor that moves an item
|
|
9318
|
+
* leaves it in English, it does not mislabel it.
|
|
9319
|
+
*
|
|
9320
|
+
* Pure: what it answers is data for the editor to draw.
|
|
9321
|
+
************************************************************/
|
|
9322
|
+
function json_editor_context_menu_items(items, context) {
|
|
9323
|
+
if (!Array.isArray(items)) return items;
|
|
9324
|
+
let table = !!(context && context.mode === "table");
|
|
9325
|
+
return items.map((item) => context_item(item, table));
|
|
9326
|
+
}
|
|
9327
|
+
/************************************************************
|
|
9328
|
+
* Name the buttons of a rendered editor's menu: an aria-label
|
|
9329
|
+
* with its key (data-i18n-aria-label, so a language change
|
|
9330
|
+
* reaches it), and aria-pressed on the mode buttons -- the
|
|
9331
|
+
* selected one is the mode on screen (`jse-selected`). Run
|
|
9332
|
+
* after every render of the menu: a re-render may draw new
|
|
9333
|
+
* buttons, which carry none of it.
|
|
9334
|
+
************************************************************/
|
|
9335
|
+
function name_json_editor_menu($editor) {
|
|
9336
|
+
if (!$editor || typeof $editor.querySelectorAll !== "function") return 0;
|
|
9337
|
+
let named = 0;
|
|
9338
|
+
for (let $b of $editor.querySelectorAll(".jse-menu button")) {
|
|
9339
|
+
let mode = mode_of_button($b);
|
|
9340
|
+
const key = mode ? JSON_EDITOR_MODE_NAME_KEYS[mode] : JSON_EDITOR_BUTTON_KEYS[button_class([...$b.classList])];
|
|
9341
|
+
if (!key) continue;
|
|
9342
|
+
$b.setAttribute("aria-label", (0, i18next.t)(key));
|
|
9343
|
+
$b.setAttribute("data-i18n-aria-label", key);
|
|
9344
|
+
if (mode) $b.setAttribute("aria-pressed", $b.classList.contains("jse-selected") ? "true" : "false");
|
|
9345
|
+
named++;
|
|
9346
|
+
}
|
|
9347
|
+
const MORE = "more options";
|
|
9348
|
+
for (let $b of $editor.querySelectorAll("div.jse-contextmenu button")) {
|
|
9349
|
+
if ($b.getAttribute("data-type") === "jse-open-dropdown") {
|
|
9350
|
+
$b.setAttribute("title", (0, i18next.t)(MORE));
|
|
9351
|
+
$b.setAttribute("data-i18n-title", MORE);
|
|
9352
|
+
$b.setAttribute("aria-label", (0, i18next.t)(MORE));
|
|
9353
|
+
$b.setAttribute("data-i18n-aria-label", MORE);
|
|
9354
|
+
named++;
|
|
9355
|
+
continue;
|
|
9356
|
+
}
|
|
9357
|
+
let text = ($b.textContent || "").trim();
|
|
9358
|
+
if (text) {
|
|
9359
|
+
$b.setAttribute("aria-label", text);
|
|
9360
|
+
named++;
|
|
9361
|
+
}
|
|
9362
|
+
}
|
|
9363
|
+
return named;
|
|
9364
|
+
}
|
|
9365
|
+
//#endregion
|
|
8685
9366
|
//#region src/c_yui_form.js
|
|
8686
9367
|
/***********************************************************************
|
|
8687
9368
|
* c_yui_form.js
|
|
@@ -8731,7 +9412,9 @@ var attrs_table$17 = [
|
|
|
8731
9412
|
var PRIVATE_DATA$17 = {
|
|
8732
9413
|
rearm_timer: null,
|
|
8733
9414
|
tables: null,
|
|
8734
|
-
table_seq: 0
|
|
9415
|
+
table_seq: 0,
|
|
9416
|
+
json_names_posted: false,
|
|
9417
|
+
lang_shell: null
|
|
8735
9418
|
};
|
|
8736
9419
|
var __gclass__$17 = null;
|
|
8737
9420
|
/***************************
|
|
@@ -8762,13 +9445,23 @@ function mt_destroy$17(gobj) {
|
|
|
8762
9445
|
* Framework Method start
|
|
8763
9446
|
************************************************************/
|
|
8764
9447
|
function mt_start$17(gobj) {
|
|
9448
|
+
let priv = gobj.priv;
|
|
9449
|
+
let shell = yui_shell_of(gobj);
|
|
9450
|
+
if (shell) {
|
|
9451
|
+
(0, _yuneta_gobj_js.gobj_subscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
9452
|
+
priv.lang_shell = shell;
|
|
9453
|
+
}
|
|
8765
9454
|
let record = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "record");
|
|
8766
9455
|
if (record) (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_LOAD_RECORD", record, gobj);
|
|
8767
9456
|
}
|
|
8768
9457
|
/************************************************************
|
|
8769
9458
|
* Framework Method stop
|
|
8770
9459
|
************************************************************/
|
|
8771
|
-
function mt_stop$17(gobj) {
|
|
9460
|
+
function mt_stop$17(gobj) {
|
|
9461
|
+
let priv = gobj.priv;
|
|
9462
|
+
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);
|
|
9463
|
+
priv.lang_shell = null;
|
|
9464
|
+
}
|
|
8772
9465
|
/***************************
|
|
8773
9466
|
* Local Methods
|
|
8774
9467
|
***************************/
|
|
@@ -9224,6 +9917,80 @@ function name_form_control$1($field, conf) {
|
|
|
9224
9917
|
$clear.setAttribute("data-i18n-aria-label", CLEAR_KEY);
|
|
9225
9918
|
}
|
|
9226
9919
|
}
|
|
9920
|
+
/************************************************************
|
|
9921
|
+
* The ✕ of ONE selected option of a Tom Select: its
|
|
9922
|
+
* remove_button plugin calls this for every option it draws.
|
|
9923
|
+
*
|
|
9924
|
+
* The plugin's own was a div titled "Remove" in English -- never
|
|
9925
|
+
* translated, no aria-label -- with tabindex -1, and the form
|
|
9926
|
+
* turns Backspace deletion off (no_backspace_delete): a keyboard
|
|
9927
|
+
* could not take one option out at all. Named here through t()
|
|
9928
|
+
* with its key (so a language change reaches it), and pressed by
|
|
9929
|
+
* Enter or Space as the clear button is: the key clicks it, which
|
|
9930
|
+
* runs the plugin's own handler.
|
|
9931
|
+
************************************************************/
|
|
9932
|
+
function remove_option_button() {
|
|
9933
|
+
const KEY = "remove this option";
|
|
9934
|
+
let $b = (0, _yuneta_gobj_js.createElement2)([
|
|
9935
|
+
"div",
|
|
9936
|
+
{
|
|
9937
|
+
class: "remove",
|
|
9938
|
+
role: "button",
|
|
9939
|
+
tabindex: "0",
|
|
9940
|
+
title: (0, i18next.t)(KEY),
|
|
9941
|
+
"data-i18n-title": KEY,
|
|
9942
|
+
"aria-label": (0, i18next.t)(KEY),
|
|
9943
|
+
"data-i18n-aria-label": KEY
|
|
9944
|
+
},
|
|
9945
|
+
"×"
|
|
9946
|
+
]);
|
|
9947
|
+
$b.addEventListener("keydown", function(evt) {
|
|
9948
|
+
if (evt.key === "Enter" || evt.key === " ") {
|
|
9949
|
+
evt.preventDefault();
|
|
9950
|
+
evt.stopPropagation();
|
|
9951
|
+
$b.click();
|
|
9952
|
+
}
|
|
9953
|
+
});
|
|
9954
|
+
return $b;
|
|
9955
|
+
}
|
|
9956
|
+
/************************************************************
|
|
9957
|
+
* The `onRenderMenu` of a json editor of this form.
|
|
9958
|
+
*
|
|
9959
|
+
* The editor calls it with the items it is about to draw: they go
|
|
9960
|
+
* back translated (json_editor_menu_items(), data for the editor
|
|
9961
|
+
* to draw). What no item can carry -- an aria-label, the state of
|
|
9962
|
+
* the mode buttons -- is written on the drawn buttons, after the
|
|
9963
|
+
* render, by the form's FSM (EV_NAME_JSON_EDITORS): the callback
|
|
9964
|
+
* only posts the event, once until it is handled. Posted, not
|
|
9965
|
+
* sent: when it runs the editor has not drawn the menu yet.
|
|
9966
|
+
*
|
|
9967
|
+
* A new function each call: handing an editor a new one is what
|
|
9968
|
+
* makes it draw its menu again (ac_language_changed).
|
|
9969
|
+
************************************************************/
|
|
9970
|
+
function json_editor_render_menu(gobj) {
|
|
9971
|
+
return function(items) {
|
|
9972
|
+
ask_json_editor_names(gobj);
|
|
9973
|
+
return json_editor_menu_items(items);
|
|
9974
|
+
};
|
|
9975
|
+
}
|
|
9976
|
+
/************************************************************
|
|
9977
|
+
* The `onRenderContextMenu` of a json editor of this form: the
|
|
9978
|
+
* same, for the menu it opens on a right click or Ctrl+Q. It is
|
|
9979
|
+
* built each time it opens, in the language of that moment.
|
|
9980
|
+
************************************************************/
|
|
9981
|
+
function json_editor_render_context_menu(gobj) {
|
|
9982
|
+
return function(items, context) {
|
|
9983
|
+
ask_json_editor_names(gobj);
|
|
9984
|
+
return json_editor_context_menu_items(items, context);
|
|
9985
|
+
};
|
|
9986
|
+
}
|
|
9987
|
+
function ask_json_editor_names(gobj) {
|
|
9988
|
+
let priv = gobj.priv;
|
|
9989
|
+
if (!priv.json_names_posted && !(0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) {
|
|
9990
|
+
priv.json_names_posted = true;
|
|
9991
|
+
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_NAME_JSON_EDITORS", {}, gobj);
|
|
9992
|
+
}
|
|
9993
|
+
}
|
|
9227
9994
|
function build_form(gobj) {
|
|
9228
9995
|
let form_id = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "form_id");
|
|
9229
9996
|
let $form = (0, _yuneta_gobj_js.createElement2)(["form", {
|
|
@@ -9255,7 +10022,7 @@ function build_html_form(gobj, $form, prefix, template) {
|
|
|
9255
10022
|
let label_keys = topic_name ? [topic_name + "." + field_desc.name, field_desc.name] : [field_desc.name];
|
|
9256
10023
|
const NO_I18N = "\0";
|
|
9257
10024
|
html_field_conf.label = (0, i18next.t)(label_keys, { defaultValue: field_desc.header });
|
|
9258
|
-
html_field_conf.label_i18n = (0, i18next.t)(
|
|
10025
|
+
html_field_conf.label_i18n = label_keys.find((k) => (0, i18next.t)(k, { defaultValue: NO_I18N }) !== NO_I18N) || null;
|
|
9259
10026
|
html_field_conf.placeholder = field_desc.placeholder ? (0, i18next.t)(field_desc.placeholder) : "";
|
|
9260
10027
|
let placeholders = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "placeholders");
|
|
9261
10028
|
if (placeholders[key]) html_field_conf.placeholder = placeholders[key];
|
|
@@ -9961,7 +10728,7 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
9961
10728
|
"clear_button": { "title": (0, i18next.t)("remove all selected options") },
|
|
9962
10729
|
"no_active_items": {},
|
|
9963
10730
|
"no_backspace_delete": {},
|
|
9964
|
-
"remove_button": {}
|
|
10731
|
+
"remove_button": { html: remove_option_button }
|
|
9965
10732
|
}
|
|
9966
10733
|
});
|
|
9967
10734
|
$extend.tom_select.on("change", function() {
|
|
@@ -10030,7 +10797,9 @@ function create_form_field(gobj, $form, prefix, field_desc, { tag, inputType, na
|
|
|
10030
10797
|
},
|
|
10031
10798
|
timestampTag: function({ field, value, path }) {
|
|
10032
10799
|
return is_time_field(field);
|
|
10033
|
-
}
|
|
10800
|
+
},
|
|
10801
|
+
onRenderMenu: json_editor_render_menu(gobj),
|
|
10802
|
+
onRenderContextMenu: json_editor_render_context_menu(gobj)
|
|
10034
10803
|
}
|
|
10035
10804
|
});
|
|
10036
10805
|
break;
|
|
@@ -10415,6 +11184,7 @@ function template2columns(gobj, columns, template, sub_elements) {
|
|
|
10415
11184
|
else return value;
|
|
10416
11185
|
};
|
|
10417
11186
|
if (field_desc.is_required) validator.push("required");
|
|
11187
|
+
if ((0, _yuneta_gobj_js.is_object)(value) && value.validator) validator.push(...Array.isArray(value.validator) ? value.validator : [value.validator]);
|
|
10418
11188
|
switch (field_desc.type) {
|
|
10419
11189
|
case "object":
|
|
10420
11190
|
case "dict": break;
|
|
@@ -10561,6 +11331,9 @@ function template2columns(gobj, columns, template, sub_elements) {
|
|
|
10561
11331
|
}
|
|
10562
11332
|
if (column) {
|
|
10563
11333
|
if (readonly) delete column.editor;
|
|
11334
|
+
yui_tabulator_name_editor(column, function() {
|
|
11335
|
+
return (0, i18next.t)(field_desc.header || field_desc.name);
|
|
11336
|
+
});
|
|
10564
11337
|
columns.push(column);
|
|
10565
11338
|
}
|
|
10566
11339
|
});
|
|
@@ -10631,12 +11404,20 @@ function validate_form(gobj, $form) {
|
|
|
10631
11404
|
mark_field_validity($editor);
|
|
10632
11405
|
}
|
|
10633
11406
|
});
|
|
11407
|
+
let $first_bad = null;
|
|
11408
|
+
function table_valid(tabulator) {
|
|
11409
|
+
let r = tabulator.validate();
|
|
11410
|
+
if (r === true) return true;
|
|
11411
|
+
if (!$first_bad && Array.isArray(r) && r.length > 0) $first_bad = r[0].getElement();
|
|
11412
|
+
return false;
|
|
11413
|
+
}
|
|
10634
11414
|
$form.querySelectorAll(".yui-tabulator-table").forEach(($table) => {
|
|
10635
|
-
if (
|
|
11415
|
+
if (!table_valid($table.tabulator)) validated = false;
|
|
10636
11416
|
$table.querySelectorAll(".yui-tabulator-table-nested").forEach(($table_nested) => {
|
|
10637
|
-
if (
|
|
11417
|
+
if (!table_valid($table_nested.tabulator)) validated = false;
|
|
10638
11418
|
});
|
|
10639
11419
|
});
|
|
11420
|
+
if ($first_bad) $first_bad.scrollIntoView({ block: "nearest" });
|
|
10640
11421
|
return validated;
|
|
10641
11422
|
}
|
|
10642
11423
|
/************************************************************
|
|
@@ -10756,7 +11537,13 @@ function clear_data(gobj, $form) {
|
|
|
10756
11537
|
} else if ($input.type === "checkbox") $input.checked = false;
|
|
10757
11538
|
else if ($input.type === "radio") $input.checked = false;
|
|
10758
11539
|
else if ($input.type === "datetime-local") $input.value = null;
|
|
10759
|
-
else if ($input.type === "
|
|
11540
|
+
else if ($input.type === "color") {
|
|
11541
|
+
$input.value = "#000000";
|
|
11542
|
+
if ($input.yui_color_value) {
|
|
11543
|
+
$input.yui_color_value.textContent = $input.value;
|
|
11544
|
+
$input.yui_color_value.title = $input.value;
|
|
11545
|
+
}
|
|
11546
|
+
} else if ($input.type === "select-multiple") $input.tom_select.clear();
|
|
10760
11547
|
else {
|
|
10761
11548
|
$input.value = null;
|
|
10762
11549
|
if ($input.yui_svg_preview) $input.yui_svg_preview();
|
|
@@ -11307,6 +12094,39 @@ function ac_hide$11(gobj, event, kw, src) {
|
|
|
11307
12094
|
function ac_timeout(gobj, event, kw, src) {
|
|
11308
12095
|
return 0;
|
|
11309
12096
|
}
|
|
12097
|
+
/************************************************************
|
|
12098
|
+
* EV_NAME_JSON_EDITORS {} -- a menu of a json editor of this
|
|
12099
|
+
* form was drawn, its menu or its context menu (posted by
|
|
12100
|
+
* ask_json_editor_names): name its buttons. Every editor of the
|
|
12101
|
+
* form: naming is idempotent, and a kw is plain json, which an
|
|
12102
|
+
* editor is not.
|
|
12103
|
+
************************************************************/
|
|
12104
|
+
function ac_name_json_editors(gobj, event, kw, src) {
|
|
12105
|
+
let priv = gobj.priv;
|
|
12106
|
+
priv.json_names_posted = false;
|
|
12107
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
12108
|
+
if (!$container) {
|
|
12109
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${event} without a container`);
|
|
12110
|
+
return -1;
|
|
12111
|
+
}
|
|
12112
|
+
for (let $editor of $container.querySelectorAll(".jsoneditor")) name_json_editor_menu($editor);
|
|
12113
|
+
return 0;
|
|
12114
|
+
}
|
|
12115
|
+
/************************************************************
|
|
12116
|
+
* EV_LANGUAGE_CHANGED {} -- from the shell. A json editor draws
|
|
12117
|
+
* its menu once: its titles and the text of its mode buttons stay
|
|
12118
|
+
* in the old language until it draws it again, so each is told to
|
|
12119
|
+
* (a new onRenderMenu), and the render names it again.
|
|
12120
|
+
************************************************************/
|
|
12121
|
+
function ac_language_changed$10(gobj, event, kw, src) {
|
|
12122
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
12123
|
+
if (!$container) return 0;
|
|
12124
|
+
for (let $editor of $container.querySelectorAll(".jsoneditor")) {
|
|
12125
|
+
let editor = $editor.jsoneditor;
|
|
12126
|
+
if (editor && typeof editor.updateProps === "function") editor.updateProps({ onRenderMenu: json_editor_render_menu(gobj) });
|
|
12127
|
+
}
|
|
12128
|
+
return 0;
|
|
12129
|
+
}
|
|
11310
12130
|
/***************************
|
|
11311
12131
|
* FSM
|
|
11312
12132
|
***************************/
|
|
@@ -11456,6 +12276,16 @@ function create_gclass$17(gclass_name) {
|
|
|
11456
12276
|
"EV_TIMEOUT",
|
|
11457
12277
|
ac_timeout,
|
|
11458
12278
|
null
|
|
12279
|
+
],
|
|
12280
|
+
[
|
|
12281
|
+
"EV_NAME_JSON_EDITORS",
|
|
12282
|
+
ac_name_json_editors,
|
|
12283
|
+
null
|
|
12284
|
+
],
|
|
12285
|
+
[
|
|
12286
|
+
"EV_LANGUAGE_CHANGED",
|
|
12287
|
+
ac_language_changed$10,
|
|
12288
|
+
null
|
|
11459
12289
|
]
|
|
11460
12290
|
]]];
|
|
11461
12291
|
const event_types = [
|
|
@@ -11474,7 +12304,9 @@ function create_gclass$17(gclass_name) {
|
|
|
11474
12304
|
["EV_REFRESH", 0],
|
|
11475
12305
|
["EV_SHOW", 0],
|
|
11476
12306
|
["EV_HIDE", 0],
|
|
11477
|
-
["EV_TIMEOUT", 0]
|
|
12307
|
+
["EV_TIMEOUT", 0],
|
|
12308
|
+
["EV_NAME_JSON_EDITORS", 0],
|
|
12309
|
+
["EV_LANGUAGE_CHANGED", 0]
|
|
11478
12310
|
];
|
|
11479
12311
|
__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);
|
|
11480
12312
|
if (!__gclass__$17) return -1;
|
|
@@ -11494,7 +12326,7 @@ function register_c_yui_form() {
|
|
|
11494
12326
|
*
|
|
11495
12327
|
* Utilities for maplibre
|
|
11496
12328
|
*
|
|
11497
|
-
* Copyright (c) 2025, ArtGins.
|
|
12329
|
+
* Copyright (c) 2025-2026, ArtGins.
|
|
11498
12330
|
* All Rights Reserved.
|
|
11499
12331
|
***********************************************************************/
|
|
11500
12332
|
var EditControl = class {
|
|
@@ -11690,9 +12522,14 @@ function label_ctrl($root, selector, text) {
|
|
|
11690
12522
|
$el.setAttribute("aria-label", text);
|
|
11691
12523
|
}
|
|
11692
12524
|
}
|
|
12525
|
+
function relabel_written($root, selector, was, now) {
|
|
12526
|
+
if (!$root || !now) return;
|
|
12527
|
+
for (const $el of $root.querySelectorAll(selector)) if ($el.getAttribute("aria-label") === was) $el.setAttribute("aria-label", now);
|
|
12528
|
+
}
|
|
11693
12529
|
function yui_maplibre_relocalize(map, t) {
|
|
11694
12530
|
if (!map || typeof map.getContainer !== "function") return;
|
|
11695
12531
|
const strings = yui_maplibre_locale(t);
|
|
12532
|
+
const was = Object.assign({}, map._locale);
|
|
11696
12533
|
try {
|
|
11697
12534
|
map._locale = Object.assign({}, map._locale, strings);
|
|
11698
12535
|
} catch (e) {}
|
|
@@ -11704,6 +12541,8 @@ function yui_maplibre_relocalize(map, t) {
|
|
|
11704
12541
|
label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
|
|
11705
12542
|
label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
|
|
11706
12543
|
label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
|
|
12544
|
+
relabel_written($c, ".maplibregl-canvas", was["Map.Title"], strings["Map.Title"]);
|
|
12545
|
+
relabel_written($c, ".maplibregl-marker", was["Marker.Title"], strings["Marker.Title"]);
|
|
11707
12546
|
const mac = typeof navigator !== "undefined" && (navigator.userAgent || "").includes("Mac");
|
|
11708
12547
|
const $desktop = $c.querySelector(".maplibregl-desktop-message");
|
|
11709
12548
|
if ($desktop) $desktop.textContent = mac ? strings["CooperativeGesturesHandler.MacHelpText"] : strings["CooperativeGesturesHandler.WindowsHelpText"];
|
|
@@ -14452,6 +15291,8 @@ function make_toolbar$5(gobj) {
|
|
|
14452
15291
|
type: "text",
|
|
14453
15292
|
placeholder: (0, i18next.t)("search"),
|
|
14454
15293
|
"data-i18n-placeholder": "search",
|
|
15294
|
+
title: (0, i18next.t)("search"),
|
|
15295
|
+
"data-i18n-title": "search",
|
|
14455
15296
|
"aria-label": (0, i18next.t)("search"),
|
|
14456
15297
|
"data-i18n-aria-label": "search"
|
|
14457
15298
|
},
|
|
@@ -15992,6 +16833,8 @@ function make_toolbar$4(gobj) {
|
|
|
15992
16833
|
type: "text",
|
|
15993
16834
|
placeholder: (0, i18next.t)("search"),
|
|
15994
16835
|
"data-i18n-placeholder": "search",
|
|
16836
|
+
title: (0, i18next.t)("search"),
|
|
16837
|
+
"data-i18n-title": "search",
|
|
15995
16838
|
"aria-label": (0, i18next.t)("search"),
|
|
15996
16839
|
"data-i18n-aria-label": "search"
|
|
15997
16840
|
},
|
|
@@ -19265,6 +20108,8 @@ function make_toolbar$2(gobj) {
|
|
|
19265
20108
|
type: "text",
|
|
19266
20109
|
placeholder: (0, i18next.t)("search"),
|
|
19267
20110
|
"data-i18n-placeholder": "search",
|
|
20111
|
+
title: (0, i18next.t)("search"),
|
|
20112
|
+
"data-i18n-title": "search",
|
|
19268
20113
|
"aria-label": (0, i18next.t)("search"),
|
|
19269
20114
|
"data-i18n-aria-label": "search"
|
|
19270
20115
|
},
|
|
@@ -21085,7 +21930,7 @@ function open_gclass_view(host, gclass_name, opts) {
|
|
|
21085
21930
|
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
21086
21931
|
return handle;
|
|
21087
21932
|
}
|
|
21088
|
-
let $win_parent = window_layer_of(host
|
|
21933
|
+
let $win_parent = window_layer_of(host);
|
|
21089
21934
|
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", {
|
|
21090
21935
|
$parent: $win_parent,
|
|
21091
21936
|
subscriber: null,
|
|
@@ -21153,14 +21998,19 @@ function close_gclass_view(handle) {
|
|
|
21153
21998
|
* window on `body` and mounted in the shell's popup layer
|
|
21154
21999
|
* lands BEHIND its opener whatever number it is given, and
|
|
21155
22000
|
* the button reads as one that did nothing.
|
|
22001
|
+
*
|
|
22002
|
+
* Opened from no window: null -- the window layer of the
|
|
22003
|
+
* shell, where every window lives (the legacy '#top-layer'
|
|
22004
|
+
* when a page has one). It was the shell's popup layer: above
|
|
22005
|
+
* the drawer, in the way of the toolbar's dropdowns.
|
|
21156
22006
|
************************************************************/
|
|
21157
|
-
function window_layer_of(host
|
|
22007
|
+
function window_layer_of(host) {
|
|
21158
22008
|
let $c = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(host, "$container");
|
|
21159
22009
|
if ($c && typeof $c.closest === "function") {
|
|
21160
22010
|
let $win = $c.closest(".C_YUI_WINDOW");
|
|
21161
22011
|
if ($win && $win.parentNode) return $win.parentNode;
|
|
21162
22012
|
}
|
|
21163
|
-
return typeof document !== "undefined" && document.getElementById("top-layer") ||
|
|
22013
|
+
return typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
21164
22014
|
}
|
|
21165
22015
|
/************************************************************
|
|
21166
22016
|
* A window is not a sheet: below this width there is no room
|
|
@@ -21829,6 +22679,8 @@ function make_find_items(gobj) {
|
|
|
21829
22679
|
type: "text",
|
|
21830
22680
|
placeholder: (0, i18next.t)("search"),
|
|
21831
22681
|
"data-i18n-placeholder": "search",
|
|
22682
|
+
title: (0, i18next.t)("search"),
|
|
22683
|
+
"data-i18n-title": "search",
|
|
21832
22684
|
"aria-label": (0, i18next.t)("search"),
|
|
21833
22685
|
"data-i18n-aria-label": "search"
|
|
21834
22686
|
},
|
|
@@ -23614,7 +24466,7 @@ function card_descriptor(it, show_label, badge_of) {
|
|
|
23614
24466
|
"aria-label": label || it.id
|
|
23615
24467
|
};
|
|
23616
24468
|
if (label) a_attrs["data-i18n-aria-label"] = label;
|
|
23617
|
-
let tip = it.tooltip || it.aria_label;
|
|
24469
|
+
let tip = it.tooltip || it.aria_label || label;
|
|
23618
24470
|
if (tip) {
|
|
23619
24471
|
a_attrs.title = tip;
|
|
23620
24472
|
a_attrs["data-i18n-title"] = tip;
|
|
@@ -23623,6 +24475,7 @@ function card_descriptor(it, show_label, badge_of) {
|
|
|
23623
24475
|
a_attrs["aria-disabled"] = "true";
|
|
23624
24476
|
a_attrs["tabindex"] = "-1";
|
|
23625
24477
|
}
|
|
24478
|
+
if (badge) name_control_with_badge(a_attrs, badge);
|
|
23626
24479
|
return [
|
|
23627
24480
|
"a",
|
|
23628
24481
|
a_attrs,
|
|
@@ -24025,6 +24878,7 @@ function render_tabs(gobj, items) {
|
|
|
24025
24878
|
a_attrs.title = tip;
|
|
24026
24879
|
a_attrs["data-i18n-title"] = tip;
|
|
24027
24880
|
}
|
|
24881
|
+
name_control_with_badge(a_attrs, badge_el);
|
|
24028
24882
|
let li_class = (0, _yuneta_gobj_js.empty_string)(it.class) ? "" : String(it.class);
|
|
24029
24883
|
lis.push([
|
|
24030
24884
|
"li",
|
|
@@ -24104,11 +24958,14 @@ function render_breadcrumb(gobj, items) {
|
|
|
24104
24958
|
href: it.route ? "#" + it.route : "#",
|
|
24105
24959
|
"data-item-id": it.id,
|
|
24106
24960
|
"data-route": it.route || "",
|
|
24107
|
-
"data-disabled": it.disabled ? "1" : "0"
|
|
24961
|
+
"data-disabled": it.disabled ? "1" : "0",
|
|
24962
|
+
"aria-label": it.name || it.id
|
|
24108
24963
|
};
|
|
24109
|
-
if (it.name)
|
|
24110
|
-
|
|
24111
|
-
|
|
24964
|
+
if (it.name) a_attrs["data-i18n-aria-label"] = it.name;
|
|
24965
|
+
let tip = it.tooltip || it.aria_label || it.name;
|
|
24966
|
+
if (tip) {
|
|
24967
|
+
a_attrs.title = tip;
|
|
24968
|
+
a_attrs["data-i18n-title"] = tip;
|
|
24112
24969
|
}
|
|
24113
24970
|
lis.push([
|
|
24114
24971
|
"li",
|
|
@@ -24241,17 +25098,19 @@ function render_accordion(gobj, items) {
|
|
|
24241
25098
|
"aria-expanded": "false",
|
|
24242
25099
|
"aria-controls": body_id
|
|
24243
25100
|
};
|
|
25101
|
+
let head_badge = item_badge_node(gobj, it, false);
|
|
24244
25102
|
if (!(0, _yuneta_gobj_js.empty_string)(head_text)) {
|
|
24245
25103
|
head_attrs.i18n = head_text;
|
|
24246
25104
|
head_attrs.title = head_text;
|
|
24247
25105
|
head_attrs["data-i18n-title"] = head_text;
|
|
24248
25106
|
head_attrs["aria-label"] = head_text;
|
|
24249
25107
|
head_attrs["data-i18n-aria-label"] = head_text;
|
|
25108
|
+
name_control_with_badge(head_attrs, head_badge);
|
|
24250
25109
|
}
|
|
24251
25110
|
let $hdr = (0, _yuneta_gobj_js.createElement2)([
|
|
24252
25111
|
"button",
|
|
24253
25112
|
head_attrs,
|
|
24254
|
-
[text_node(head_text),
|
|
25113
|
+
[text_node(head_text), head_badge]
|
|
24255
25114
|
]);
|
|
24256
25115
|
$container.appendChild($hdr);
|
|
24257
25116
|
let $ul = (0, _yuneta_gobj_js.createElement2)(["ul", {
|
|
@@ -24340,6 +25199,7 @@ function item_li(gobj, it, opts) {
|
|
|
24340
25199
|
a_attrs["aria-disabled"] = "true";
|
|
24341
25200
|
a_attrs["tabindex"] = "-1";
|
|
24342
25201
|
}
|
|
25202
|
+
name_control_with_badge(a_attrs, badge_el);
|
|
24343
25203
|
return [
|
|
24344
25204
|
"li",
|
|
24345
25205
|
{},
|
|
@@ -24386,6 +25246,7 @@ function item_iconbar(gobj, it, opts) {
|
|
|
24386
25246
|
a_attrs.title = tip;
|
|
24387
25247
|
a_attrs["data-i18n-title"] = tip;
|
|
24388
25248
|
}
|
|
25249
|
+
name_control_with_badge(a_attrs, badge_el);
|
|
24389
25250
|
return [
|
|
24390
25251
|
"div",
|
|
24391
25252
|
{ class: "level-item" },
|
|
@@ -24643,7 +25504,10 @@ function render_node(node) {
|
|
|
24643
25504
|
if (node.icon && /^yi-[a-z0-9-]+$/.test(node.icon)) row.push([
|
|
24644
25505
|
"span",
|
|
24645
25506
|
{ class: "icon ROUTEMAP_ICON" },
|
|
24646
|
-
[["i", {
|
|
25507
|
+
[["i", {
|
|
25508
|
+
class: node.icon,
|
|
25509
|
+
"aria-hidden": "true"
|
|
25510
|
+
}]]
|
|
24647
25511
|
]);
|
|
24648
25512
|
row.push([
|
|
24649
25513
|
"span",
|
|
@@ -24692,16 +25556,23 @@ function render_node(node) {
|
|
|
24692
25556
|
]);
|
|
24693
25557
|
let row_class = (node.current ? " ROUTEMAP_CURRENT" : "") + (node.ref ? " ROUTEMAP_IS_REF" : "");
|
|
24694
25558
|
let $row;
|
|
24695
|
-
if (node.route)
|
|
24696
|
-
|
|
24697
|
-
{
|
|
25559
|
+
if (node.route) {
|
|
25560
|
+
let a_attrs = {
|
|
24698
25561
|
class: "ROUTEMAP_LINK ROUTEMAP_ROW" + row_class,
|
|
24699
25562
|
href: "#" + node.route,
|
|
24700
25563
|
title: node.route
|
|
24701
|
-
}
|
|
24702
|
-
|
|
24703
|
-
|
|
24704
|
-
|
|
25564
|
+
};
|
|
25565
|
+
if (node.label) {
|
|
25566
|
+
a_attrs["aria-label"] = node.label;
|
|
25567
|
+
a_attrs["data-i18n-aria-label"] = node.label;
|
|
25568
|
+
}
|
|
25569
|
+
if (node.current) a_attrs["aria-current"] = "page";
|
|
25570
|
+
$row = (0, _yuneta_gobj_js.createElement2)([
|
|
25571
|
+
"a",
|
|
25572
|
+
a_attrs,
|
|
25573
|
+
row
|
|
25574
|
+
]);
|
|
25575
|
+
} else $row = (0, _yuneta_gobj_js.createElement2)([
|
|
24705
25576
|
"span",
|
|
24706
25577
|
{ class: "ROUTEMAP_ROW ROUTEMAP_STRUCT" + row_class },
|
|
24707
25578
|
row
|
|
@@ -24985,7 +25856,7 @@ function yui_shell_show_route_map(shell, opts) {
|
|
|
24985
25856
|
if ((0, _yuneta_gobj_js.gclass_find_by_name)("C_YUI_WINDOW")) {
|
|
24986
25857
|
let win_ref = { gobj: null };
|
|
24987
25858
|
let $body = build_body(shell, t);
|
|
24988
|
-
let $parent =
|
|
25859
|
+
let $parent = typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
24989
25860
|
let win = (0, _yuneta_gobj_js.gobj_create_service)(WIN_NAME$2, "C_YUI_WINDOW", {
|
|
24990
25861
|
$parent,
|
|
24991
25862
|
subscriber: null,
|
|
@@ -26059,7 +26930,13 @@ function add_tab(gobj, gobj2, id, text, icon) {
|
|
|
26059
26930
|
let $item = (0, _yuneta_gobj_js.createElement2)([
|
|
26060
26931
|
"li",
|
|
26061
26932
|
{ class: "" },
|
|
26062
|
-
[["a", {
|
|
26933
|
+
[["a", {
|
|
26934
|
+
href: id,
|
|
26935
|
+
title: (0, i18next.t)(text),
|
|
26936
|
+
"data-i18n-title": text,
|
|
26937
|
+
"aria-label": (0, i18next.t)(text),
|
|
26938
|
+
"data-i18n-aria-label": text
|
|
26939
|
+
}]]
|
|
26063
26940
|
]);
|
|
26064
26941
|
$tabs.appendChild($item);
|
|
26065
26942
|
$item.gobj = gobj2;
|
|
@@ -26067,7 +26944,10 @@ function add_tab(gobj, gobj2, id, text, icon) {
|
|
|
26067
26944
|
if (icon) $a.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
26068
26945
|
"span",
|
|
26069
26946
|
{ class: "icon is-small is-hidden-mobile" },
|
|
26070
|
-
["i", {
|
|
26947
|
+
["i", {
|
|
26948
|
+
class: `${icon}`,
|
|
26949
|
+
"aria-hidden": "true"
|
|
26950
|
+
}]
|
|
26071
26951
|
]));
|
|
26072
26952
|
$a.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
26073
26953
|
"span",
|
|
@@ -26256,7 +27136,9 @@ function add_topic_card(gobj, id, text, icon, desc) {
|
|
|
26256
27136
|
class: "yui-nav-item yui-nav-card TREEDB_TOPIC_CARD",
|
|
26257
27137
|
href: "#",
|
|
26258
27138
|
"data-topic-href": id,
|
|
26259
|
-
|
|
27139
|
+
title: (0, i18next.t)(text),
|
|
27140
|
+
"data-i18n-title": text,
|
|
27141
|
+
"aria-label": (0, i18next.t)(text),
|
|
26260
27142
|
"data-i18n-aria-label": text
|
|
26261
27143
|
},
|
|
26262
27144
|
[[
|
|
@@ -27100,7 +27982,7 @@ function open_json_viewer$1(gobj, opts) {
|
|
|
27100
27982
|
}
|
|
27101
27983
|
});
|
|
27102
27984
|
} else {
|
|
27103
|
-
let $win_parent =
|
|
27985
|
+
let $win_parent = typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
27104
27986
|
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", {
|
|
27105
27987
|
$parent: $win_parent,
|
|
27106
27988
|
subscriber: null,
|
|
@@ -27227,7 +28109,9 @@ function request_print_tranger$1(gobj, path) {
|
|
|
27227
28109
|
}, gobj);
|
|
27228
28110
|
if (ret) {
|
|
27229
28111
|
(0, _yuneta_gobj_js.log_error)(ret);
|
|
27230
|
-
|
|
28112
|
+
const refusal = refusal_text$1(ret);
|
|
28113
|
+
if (refusal) answer_print_tranger_refused$1(gobj, path, { error: refusal });
|
|
28114
|
+
else answer_print_tranger_refused$1(gobj, path, { i18n: "print-tranger failed" });
|
|
27231
28115
|
return;
|
|
27232
28116
|
}
|
|
27233
28117
|
if (path) priv.drills_in_flight.add(path);
|
|
@@ -27295,9 +28179,13 @@ function ac_mt_command_answer$2(gobj, event, kw, src) {
|
|
|
27295
28179
|
}
|
|
27296
28180
|
} else gobj.priv.drills_in_flight.clear();
|
|
27297
28181
|
if (result < 0) {
|
|
27298
|
-
if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
28182
|
+
if (path && comment) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
27299
28183
|
path,
|
|
27300
|
-
error: comment
|
|
28184
|
+
error: comment
|
|
28185
|
+
}, gobj);
|
|
28186
|
+
else if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
28187
|
+
path,
|
|
28188
|
+
i18n: "print-tranger failed"
|
|
27301
28189
|
}, gobj);
|
|
27302
28190
|
else yui_shell_show_error(yui_shell_of(gobj), comment || "print-tranger failed", { t: i18next.t });
|
|
27303
28191
|
return 0;
|
|
@@ -29082,7 +29970,7 @@ function present_json_popup(gobj, $box, opts) {
|
|
|
29082
29970
|
win: null
|
|
29083
29971
|
};
|
|
29084
29972
|
let win = (0, _yuneta_gobj_js.gobj_create_service)(opts.name, "C_YUI_WINDOW", {
|
|
29085
|
-
$parent: popup_mount_layer(
|
|
29973
|
+
$parent: popup_mount_layer(),
|
|
29086
29974
|
subscriber: null,
|
|
29087
29975
|
modal: false,
|
|
29088
29976
|
showMax: true,
|
|
@@ -29136,10 +30024,17 @@ function retire_popup_window(win) {
|
|
|
29136
30024
|
(0, _yuneta_gobj_js.log_warning)(`${GCLASS_NAME$5}: json window already gone: ${e}`);
|
|
29137
30025
|
}
|
|
29138
30026
|
}
|
|
29139
|
-
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
|
|
30027
|
+
/************************************************************
|
|
30028
|
+
* Where a json window of this view lives: null, the WINDOW
|
|
30029
|
+
* layer of the shell, where every window lives -- below the
|
|
30030
|
+
* shell's dialogs, so a confirm asked over it paints above it
|
|
30031
|
+
* (the legacy C_YUI_MAIN '#popup-layer' when a page has one).
|
|
30032
|
+
* It was the shell's popup layer: above the drawer, in the way
|
|
30033
|
+
* of the toolbar's dropdowns, and in an order of its own no
|
|
30034
|
+
* other window could rise above.
|
|
30035
|
+
************************************************************/
|
|
30036
|
+
function popup_mount_layer() {
|
|
30037
|
+
return document.getElementById("popup-layer") || null;
|
|
29143
30038
|
}
|
|
29144
30039
|
/******************************
|
|
29145
30040
|
* Framework Methods
|
|
@@ -29754,7 +30649,10 @@ function col_title_formatter(gobj, col) {
|
|
|
29754
30649
|
let text = col_label(col, topic_name);
|
|
29755
30650
|
let attrs = {};
|
|
29756
30651
|
const NO_I18N = "\0";
|
|
29757
|
-
|
|
30652
|
+
let key = null;
|
|
30653
|
+
if (topic_name && (0, i18next.t)(topic_name + "." + col.id, { defaultValue: NO_I18N }) !== NO_I18N) key = topic_name + "." + col.id;
|
|
30654
|
+
else if ((0, i18next.t)(col.id, { defaultValue: NO_I18N }) !== NO_I18N) key = col.id;
|
|
30655
|
+
if (key) attrs.i18n = key;
|
|
29758
30656
|
return (0, _yuneta_gobj_js.createElement2)([
|
|
29759
30657
|
"span",
|
|
29760
30658
|
attrs,
|
|
@@ -29848,6 +30746,9 @@ function create_tabulator(gobj) {
|
|
|
29848
30746
|
colDef.editable = function() {
|
|
29849
30747
|
return (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "editable") && !(0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "readonly");
|
|
29850
30748
|
};
|
|
30749
|
+
yui_tabulator_name_editor(colDef, function() {
|
|
30750
|
+
return col_label(col, (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "topic_name"));
|
|
30751
|
+
});
|
|
29851
30752
|
}
|
|
29852
30753
|
const FILTERABLE = [
|
|
29853
30754
|
"string",
|
|
@@ -71206,7 +72107,7 @@ function open_json_viewer(gobj) {
|
|
|
71206
72107
|
});
|
|
71207
72108
|
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
71208
72109
|
} else {
|
|
71209
|
-
let $win_parent =
|
|
72110
|
+
let $win_parent = typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
71210
72111
|
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", {
|
|
71211
72112
|
$parent: $win_parent,
|
|
71212
72113
|
subscriber: null,
|
|
@@ -71320,7 +72221,9 @@ function request_print_tranger(gobj, path) {
|
|
|
71320
72221
|
}, gobj);
|
|
71321
72222
|
if (ret) {
|
|
71322
72223
|
(0, _yuneta_gobj_js.log_error)(ret);
|
|
71323
|
-
|
|
72224
|
+
const refusal = refusal_text(ret);
|
|
72225
|
+
if (refusal) answer_print_tranger_refused(gobj, path, { error: refusal });
|
|
72226
|
+
else answer_print_tranger_refused(gobj, path, { i18n: "print-tranger failed" });
|
|
71324
72227
|
return;
|
|
71325
72228
|
}
|
|
71326
72229
|
if (path) priv.drills_in_flight.add(path);
|
|
@@ -71725,9 +72628,13 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
|
|
|
71725
72628
|
}
|
|
71726
72629
|
} else priv.drills_in_flight.clear();
|
|
71727
72630
|
if (result < 0) {
|
|
71728
|
-
if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
72631
|
+
if (path && comment) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
72632
|
+
path,
|
|
72633
|
+
error: comment
|
|
72634
|
+
}, gobj);
|
|
72635
|
+
else if (path) (0, _yuneta_gobj_js.gobj_send_event)(jv, "EV_SUBTREE_ERROR", {
|
|
71729
72636
|
path,
|
|
71730
|
-
|
|
72637
|
+
i18n: "print-tranger failed"
|
|
71731
72638
|
}, gobj);
|
|
71732
72639
|
else yui_shell_show_error(yui_shell_of(gobj), comment || "print-tranger failed", { t: i18next.t });
|
|
71733
72640
|
return 0;
|
|
@@ -83319,7 +84226,8 @@ function apply_dev_traces() {
|
|
|
83319
84226
|
* Shell-agnostic: the legacy C_YUI_MAIN shell has a
|
|
83320
84227
|
* '#top-layer' stacking element; the new C_YUI_SHELL does not.
|
|
83321
84228
|
* We pass that element when present, otherwise null — C_YUI_WINDOW
|
|
83322
|
-
*
|
|
84229
|
+
* then takes the window layer of the shell (document.body while
|
|
84230
|
+
* there is none), and follows the shell across a logout.
|
|
83323
84231
|
************************************************************/
|
|
83324
84232
|
function setup_dev(self, show) {
|
|
83325
84233
|
if (show) {
|
|
@@ -83409,7 +84317,8 @@ var WIN_NAME$1 = "Frontend-View-Window";
|
|
|
83409
84317
|
* Shell-agnostic: the legacy C_YUI_MAIN shell has a
|
|
83410
84318
|
* '#top-layer' stacking element; the new C_YUI_SHELL does not.
|
|
83411
84319
|
* We pass that element when present, otherwise null — C_YUI_WINDOW
|
|
83412
|
-
*
|
|
84320
|
+
* then takes the window layer of the shell (document.body while
|
|
84321
|
+
* there is none), and follows the shell across a logout.
|
|
83413
84322
|
*
|
|
83414
84323
|
* Returns the window gobj, or null.
|
|
83415
84324
|
************************************************************/
|