@yuneta/gobj-ui 7.26.34 → 7.26.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +223 -53
- package/dist/gobj-ui.cjs.js +1109 -143
- package/dist/gobj-ui.es.js +1109 -143
- package/package.json +2 -2
- package/scripts/validate-locales.mjs +672 -96
- package/src/c_yui_form.js +186 -9
- package/src/c_yui_gclass.js +2 -0
- package/src/c_yui_gobj_tree_js.js +2 -0
- package/src/c_yui_json.js +2 -0
- package/src/c_yui_json_graph.js +2 -0
- package/src/c_yui_nav.js +23 -5
- package/src/c_yui_shell.css +16 -0
- package/src/c_yui_shell.js +282 -26
- package/src/c_yui_treedb_graph.js +26 -8
- package/src/c_yui_treedb_topic_with_form.js +40 -18
- package/src/c_yui_treedb_topics.js +34 -11
- package/src/c_yui_window.js +132 -32
- package/src/c_yui_window_manager.js +250 -46
- package/src/form_json_editor_names.js +448 -0
- package/src/form_json_editor_names.wiring.test.js +595 -0
- package/src/form_label_i18n.wiring.test.js +169 -0
- package/src/i18n_key_functions.js +14 -6
- package/src/i18n_key_functions.test.js +124 -2
- package/src/lib_maplibre.js +26 -2
- package/src/lib_maplibre_relocalize.test.js +78 -0
- package/src/named_controls.wiring.test.js +468 -0
- package/src/nav_cards_helpers.js +9 -1
- package/src/nav_item_badge.wiring.test.js +182 -1
- package/src/shell_route_map.js +25 -8
- package/src/table_editor_name.wiring.test.js +201 -0
- package/src/treedb_column_title.wiring.test.js +151 -0
- package/src/treedb_json_drill.wiring.test.js +41 -1
- package/src/window_layer.wiring.test.js +348 -43
- package/src/window_show.wiring.test.js +6 -2
- package/src/window_stacking.wiring.test.js +334 -0
- package/src/yui_badge.js +58 -13
- package/src/yui_badge.test.js +40 -3
- package/src/yui_dev.js +2 -1
- package/src/yui_file_field.js +2 -0
- package/src/yui_frontend_view.js +2 -1
- package/src/yui_gclass_view.js +9 -6
- package/src/yui_tabulator_i18n.js +42 -0
- package/src/yui_tabulator_i18n.test.js +48 -1
|
@@ -40,6 +40,8 @@ import {
|
|
|
40
40
|
gobj_short_name,
|
|
41
41
|
gobj_read_pointer_attr,
|
|
42
42
|
gobj_subscribe_event,
|
|
43
|
+
gobj_unsubscribe_event,
|
|
44
|
+
gobj_is_destroying,
|
|
43
45
|
gobj_send_event,
|
|
44
46
|
createElement2,
|
|
45
47
|
gobj_write_attr,
|
|
@@ -50,6 +52,13 @@ import {
|
|
|
50
52
|
|
|
51
53
|
import {t} from "i18next";
|
|
52
54
|
import {text_node} from "./yui_text.js";
|
|
55
|
+
import {
|
|
56
|
+
yui_shell_of,
|
|
57
|
+
yui_shell_raise_window,
|
|
58
|
+
yui_shell_watch_changes,
|
|
59
|
+
yui_shell_unwatch_changes,
|
|
60
|
+
} from "./c_yui_shell.js";
|
|
61
|
+
import {yui_shell_popup_layer} from "./shell_modals.js";
|
|
53
62
|
|
|
54
63
|
|
|
55
64
|
/***************************************************************
|
|
@@ -57,13 +66,18 @@ import {text_node} from "./yui_text.js";
|
|
|
57
66
|
***************************************************************/
|
|
58
67
|
const GCLASS_NAME = "C_YUI_WINDOW_MANAGER";
|
|
59
68
|
|
|
60
|
-
/*
|
|
61
|
-
*
|
|
69
|
+
/* The floating dock sits at the top of the layer it lives in
|
|
70
|
+
* (dock_place()), the shell's popup layer: every window is in the
|
|
71
|
+
* window layer below it, whatever number it takes, and the shell's
|
|
72
|
+
* dialogs and toasts are layers above. */
|
|
62
73
|
const DOCK_Z = 1000000;
|
|
63
74
|
|
|
64
75
|
/* Chip close glyph (currentColor → theme-aware). */
|
|
65
76
|
const 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>';
|
|
66
77
|
|
|
78
|
+
/* Unique ids for the label spans a chip is named by (aria-labelledby). */
|
|
79
|
+
let __chip_seq__ = 0;
|
|
80
|
+
|
|
67
81
|
|
|
68
82
|
/***************************************************************
|
|
69
83
|
* Data
|
|
@@ -74,16 +88,16 @@ SDATA(data_type_t.DTP_STRING, "dock_mode", 0, "floating", "floatin
|
|
|
74
88
|
SDATA(data_type_t.DTP_STRING, "dock_corner", 0, "bottom-left", "Floating placement: top-left | top-right | bottom-left | bottom-right"),
|
|
75
89
|
SDATA(data_type_t.DTP_STRING, "inline_selector", 0, "", "CSS selector of the container the dock mounts into when inline (e.g. a shell zone)"),
|
|
76
90
|
SDATA(data_type_t.DTP_STRING, "responsive_query", 0, "(max-width: 768px)", "Media query that selects inline placement when dock_mode is 'responsive'"),
|
|
77
|
-
SDATA(data_type_t.DTP_POINTER, "$parent", 0, null, "Where the floating dock mounts (default document.body)"),
|
|
91
|
+
SDATA(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)"),
|
|
78
92
|
SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "Internal: the dock element"),
|
|
79
93
|
SDATA_END()
|
|
80
94
|
];
|
|
81
95
|
|
|
82
96
|
let PRIVATE_DATA = {
|
|
83
|
-
windows: null, /* [{gobj, $chip, minimized}] */
|
|
84
|
-
z: 0, /* z-order counter handed to focused windows */
|
|
97
|
+
windows: null, /* [{gobj, $chip, minimized, title, title_key, title_prefix}] */
|
|
85
98
|
mql: null, /* MediaQueryList when dock_mode is 'responsive' */
|
|
86
99
|
mql_handler: null, /* its change listener (kept for teardown) */
|
|
100
|
+
lang_shell: null, /* the shell whose EV_LANGUAGE_CHANGED we hear */
|
|
87
101
|
};
|
|
88
102
|
|
|
89
103
|
let __gclass__ = null;
|
|
@@ -106,7 +120,6 @@ function mt_create(gobj)
|
|
|
106
120
|
let priv = gobj.priv;
|
|
107
121
|
|
|
108
122
|
priv.windows = [];
|
|
109
|
-
priv.z = 10;
|
|
110
123
|
|
|
111
124
|
/* In 'responsive' mode the placement follows a media query: watch it
|
|
112
125
|
* so the dock re-homes (floating <-> inline) when the viewport crosses
|
|
@@ -123,6 +136,14 @@ function mt_create(gobj)
|
|
|
123
136
|
|
|
124
137
|
build_dock(gobj);
|
|
125
138
|
|
|
139
|
+
/* The dock lives in a shell (its popup layer, or a zone when
|
|
140
|
+
* inline), and it outlives the shell: the app builds it once, a
|
|
141
|
+
* logout destroys the shell, the login builds another. Told when
|
|
142
|
+
* a shell is built or destroyed, it places itself again
|
|
143
|
+
* (ac_shell_changed). Unwatched in mt_destroy. */
|
|
144
|
+
yui_shell_watch_changes(gobj);
|
|
145
|
+
follow_language(gobj);
|
|
146
|
+
|
|
126
147
|
/*
|
|
127
148
|
* SERVICE subscription model
|
|
128
149
|
*/
|
|
@@ -139,6 +160,14 @@ function mt_destroy(gobj)
|
|
|
139
160
|
{
|
|
140
161
|
let priv = gobj.priv;
|
|
141
162
|
|
|
163
|
+
yui_shell_unwatch_changes(gobj);
|
|
164
|
+
if(priv.lang_shell) {
|
|
165
|
+
if(!gobj_is_destroying(priv.lang_shell)) {
|
|
166
|
+
gobj_unsubscribe_event(priv.lang_shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
167
|
+
}
|
|
168
|
+
priv.lang_shell = null;
|
|
169
|
+
}
|
|
170
|
+
|
|
142
171
|
if(priv.mql && priv.mql_handler) {
|
|
143
172
|
priv.mql.removeEventListener("change", priv.mql_handler);
|
|
144
173
|
priv.mql = null;
|
|
@@ -158,6 +187,54 @@ function mt_destroy(gobj)
|
|
|
158
187
|
|
|
159
188
|
|
|
160
189
|
|
|
190
|
+
/************************************************************
|
|
191
|
+
* Hear the language of the shell that holds the dock -- the
|
|
192
|
+
* dock outlives a shell, so it follows them: the dying one's
|
|
193
|
+
* subscription goes with it, the next one is heard. The
|
|
194
|
+
* toggle of a chip whose window's title has a DATA half has a
|
|
195
|
+
* composed title, which no key carries: it is written again in
|
|
196
|
+
* the new language (ac_language_changed).
|
|
197
|
+
************************************************************/
|
|
198
|
+
function follow_language(gobj)
|
|
199
|
+
{
|
|
200
|
+
let priv = gobj.priv;
|
|
201
|
+
|
|
202
|
+
let shell = yui_shell_of(gobj);
|
|
203
|
+
if(shell && gobj_is_destroying(shell)) {
|
|
204
|
+
shell = null;
|
|
205
|
+
}
|
|
206
|
+
if(shell === priv.lang_shell) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if(priv.lang_shell && !gobj_is_destroying(priv.lang_shell)) {
|
|
210
|
+
gobj_unsubscribe_event(priv.lang_shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
211
|
+
}
|
|
212
|
+
priv.lang_shell = null;
|
|
213
|
+
if(shell) {
|
|
214
|
+
gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
215
|
+
priv.lang_shell = shell;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/************************************************************
|
|
220
|
+
* The toggle's title and aria-label, in the current language:
|
|
221
|
+
* the same join as C_YUI_WINDOW's composed_title(), DATA half
|
|
222
|
+
* first. The title the window registered with when it gave no
|
|
223
|
+
* halves (a legacy caller).
|
|
224
|
+
************************************************************/
|
|
225
|
+
function chip_title(entry)
|
|
226
|
+
{
|
|
227
|
+
/* `title_key` is the window's title, a key its HOST chose. */
|
|
228
|
+
let kind = entry.title_key ? t(/* i18n: data */ entry.title_key) : "";
|
|
229
|
+
if(entry.title_prefix && kind) {
|
|
230
|
+
return `${entry.title_prefix} · ${kind}`;
|
|
231
|
+
}
|
|
232
|
+
return entry.title_prefix || kind || entry.title;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
161
238
|
/************************************************************
|
|
162
239
|
* Inject the dock stylesheet once (theme-aware).
|
|
163
240
|
************************************************************/
|
|
@@ -200,10 +277,18 @@ function ensure_dock_style()
|
|
|
200
277
|
}
|
|
201
278
|
.yui-dock-chip {
|
|
202
279
|
display: inline-flex; align-items: center; gap: 7px; font: inherit; font-size: 12px;
|
|
203
|
-
padding:
|
|
204
|
-
background: var(--bulma-scheme-main); color: var(--bulma-text);
|
|
280
|
+
padding: 0 5px 0 0; border: 1px solid var(--bulma-border); border-radius: 7px;
|
|
281
|
+
background: var(--bulma-scheme-main); color: var(--bulma-text); white-space: nowrap;
|
|
205
282
|
}
|
|
206
283
|
.yui-dock-chip:hover { border-color: var(--bulma-text-weak); }
|
|
284
|
+
/* The chip is the look; its toggle a button that adds none, and
|
|
285
|
+
* takes the pill's padding, so the whole label is what a press lands
|
|
286
|
+
* on and the chip reads as one pill with its ✕ at the end. */
|
|
287
|
+
.yui-dock-chip-toggle {
|
|
288
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
289
|
+
padding: 4px 0 4px 11px; margin: 0; border: 0; border-radius: 7px 0 0 7px;
|
|
290
|
+
background: transparent; font: inherit; color: inherit; cursor: pointer; white-space: nowrap;
|
|
291
|
+
}
|
|
207
292
|
/* The BORDER says active, not the text: blue ink on a blue tint is
|
|
208
293
|
* the same hue on itself -- 4.49:1 on the light chip, under the 4.5
|
|
209
294
|
* its 12px label needs. The label takes the text colour (11:1). */
|
|
@@ -307,12 +392,37 @@ function apply_placement(gobj)
|
|
|
307
392
|
$dock.classList.toggle(`yui-dock--${c}`, !inline && c === corner);
|
|
308
393
|
}
|
|
309
394
|
|
|
310
|
-
let target = inline ? $inline : (gobj_read_attr(gobj, "$parent") ||
|
|
395
|
+
let target = inline ? $inline : (gobj_read_attr(gobj, "$parent") || dock_place(gobj));
|
|
311
396
|
if($dock.parentNode !== target) {
|
|
312
397
|
target.appendChild($dock);
|
|
313
398
|
}
|
|
314
399
|
}
|
|
315
400
|
|
|
401
|
+
/************************************************************
|
|
402
|
+
* Where the FLOATING dock lives when the app names no
|
|
403
|
+
* `$parent`: the popup layer of the shell, at the top of it.
|
|
404
|
+
*
|
|
405
|
+
* It was document.body at z-index 1000000, and that put it
|
|
406
|
+
* above the WHOLE shell -- `.yui-shell` is a stacking context
|
|
407
|
+
* of its own, so its dialogs (modal layer, 99) and toasts (120)
|
|
408
|
+
* counted only inside it: the dock stayed clickable over a
|
|
409
|
+
* dialog's backdrop (a window could be closed from its chip
|
|
410
|
+
* while its own "all changes will be lost" question was open),
|
|
411
|
+
* and it covered a toast where they met.
|
|
412
|
+
*
|
|
413
|
+
* The popup layer, not the window layer: the dock has to stay
|
|
414
|
+
* above EVERY window, and windows live in two layers -- the
|
|
415
|
+
* window layer (no `$parent`) and the popup layer, where the
|
|
416
|
+
* site map and the JSON windows of the treedb views put theirs.
|
|
417
|
+
* Above both; below the dialogs, the toasts and the loading
|
|
418
|
+
* cover. No shell (before the first, between a logout and the
|
|
419
|
+
* next login): the body.
|
|
420
|
+
************************************************************/
|
|
421
|
+
function dock_place(gobj)
|
|
422
|
+
{
|
|
423
|
+
return yui_shell_popup_layer(yui_shell_of(gobj)) || document.body;
|
|
424
|
+
}
|
|
425
|
+
|
|
316
426
|
/************************************************************
|
|
317
427
|
* Destroy the dock element.
|
|
318
428
|
************************************************************/
|
|
@@ -416,7 +526,6 @@ function set_active(gobj, entry)
|
|
|
416
526
|
************************************************************/
|
|
417
527
|
function focus_entry(gobj, entry)
|
|
418
528
|
{
|
|
419
|
-
let priv = gobj.priv;
|
|
420
529
|
let $win = gobj_read_attr(entry.gobj, "$container");
|
|
421
530
|
if($win) {
|
|
422
531
|
if(entry.minimized) {
|
|
@@ -428,8 +537,10 @@ function focus_entry(gobj, entry)
|
|
|
428
537
|
entry.$chip.classList.remove('is-min');
|
|
429
538
|
}
|
|
430
539
|
}
|
|
431
|
-
|
|
432
|
-
|
|
540
|
+
/* The windows' ONE z-order, shared with the windows that have
|
|
541
|
+
* no dock (yui_shell_raise_window). A counter of its own put a
|
|
542
|
+
* window opened later without a dock UNDER every docked one. */
|
|
543
|
+
yui_shell_raise_window($win);
|
|
433
544
|
}
|
|
434
545
|
set_active(gobj, entry);
|
|
435
546
|
}
|
|
@@ -525,21 +636,53 @@ function ac_register_window(gobj, event, kw, src)
|
|
|
525
636
|
text_node(title)]); // data, not markup
|
|
526
637
|
}
|
|
527
638
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
639
|
+
/* The toggle's NAME is its label, read from the label's own spans
|
|
640
|
+
* (aria-labelledby): the data half as it is, the kind half from the
|
|
641
|
+
* node that carries its key -- so the name changes language with the
|
|
642
|
+
* label, which a composed aria-label could not. */
|
|
643
|
+
let chip_seq = ++__chip_seq__;
|
|
644
|
+
let label_ids = label_items.map(function(item, i) {
|
|
645
|
+
item[1].id = `yui-dock-chip-${chip_seq}-${i}`;
|
|
646
|
+
return item[1].id;
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
let entry = {gobj: win, $chip: null, minimized: false,
|
|
650
|
+
title: title, title_key: title_key, title_prefix: prefix};
|
|
651
|
+
/* The chip is a CONTAINER of two sibling controls, and no control
|
|
652
|
+
* itself: the TOGGLE (minimise / bring back, the whole label) and
|
|
653
|
+
* the ✕ (EV_CLOSE_WINDOW → the window's own teardown →
|
|
654
|
+
* EV_UNREGISTER_WINDOW removes this chip). Up to 7.26.34 the chip
|
|
655
|
+
* was a role=button div HOLDING the ✕ button -- one control inside
|
|
656
|
+
* another, whose name read the label and then "close", and whose
|
|
657
|
+
* ✕ a reader could not reach as a control of its own.
|
|
658
|
+
*
|
|
659
|
+
* Both are real <button>s: a key presses them, with no handler of
|
|
660
|
+
* ours. Each says what it does with a title and an aria-label: the
|
|
661
|
+
* toggle the window's composed title (with its key as
|
|
662
|
+
* data-i18n-title / -aria-label when there is no DATA half; a
|
|
663
|
+
* reader takes the aria-labelledby, which changes language with the
|
|
664
|
+
* label), the ✕ "close". The toggle's click crosses the FSM
|
|
665
|
+
* (EV_TOGGLE_WINDOW), by the window's name: a kw is plain json. */
|
|
666
|
+
let window_name = gobj_full_name(win);
|
|
535
667
|
let $chip = createElement2(
|
|
536
|
-
['div',
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
668
|
+
['div', {class: 'DOCK_CHIP yui-dock-chip'}, [
|
|
669
|
+
['button', Object.assign(
|
|
670
|
+
{class: 'DOCK_CHIP_TOGGLE yui-dock-chip-toggle', type: 'button',
|
|
671
|
+
title: title, 'aria-label': title, 'aria-labelledby': label_ids.join(" ")},
|
|
672
|
+
(!prefix && title_key) ? {
|
|
673
|
+
'data-i18n-title': /* i18n: data */ title_key,
|
|
674
|
+
'data-i18n-aria-label': /* i18n: data */ title_key
|
|
675
|
+
} : {}
|
|
676
|
+
), [
|
|
677
|
+
chip_lead(kw.icon),
|
|
678
|
+
['span', {class: 'yui-dock-label'}, label_items]
|
|
679
|
+
], {
|
|
680
|
+
click: (evt) => {
|
|
681
|
+
evt.stopPropagation();
|
|
682
|
+
gobj_send_event(gobj, "EV_TOGGLE_WINDOW", {window: window_name}, gobj);
|
|
683
|
+
}
|
|
684
|
+
}],
|
|
685
|
+
['button', {class: 'DOCK_CHIP_CLOSE yui-dock-close', type: 'button',
|
|
543
686
|
title: t('close'), 'data-i18n-title': 'close',
|
|
544
687
|
'aria-label': t('close'), 'data-i18n-aria-label': 'close'}, html_markup(WC_X), {
|
|
545
688
|
click: (evt) => {
|
|
@@ -547,26 +690,7 @@ function ac_register_window(gobj, event, kw, src)
|
|
|
547
690
|
gobj_send_event(entry.gobj, "EV_CLOSE_WINDOW", {}, gobj);
|
|
548
691
|
}
|
|
549
692
|
}],
|
|
550
|
-
]
|
|
551
|
-
click: (evt) => {
|
|
552
|
-
evt.stopPropagation();
|
|
553
|
-
on_chip_click(gobj, entry);
|
|
554
|
-
},
|
|
555
|
-
keydown: (evt) => {
|
|
556
|
-
/* Only the chip itself — Enter on the inner ✕ button
|
|
557
|
-
* already fires its own click. */
|
|
558
|
-
if(evt.target !== evt.currentTarget) {
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
if(evt.key === "Enter" || evt.key === " ") {
|
|
562
|
-
if(evt.key === " ") {
|
|
563
|
-
evt.preventDefault();
|
|
564
|
-
}
|
|
565
|
-
evt.stopPropagation();
|
|
566
|
-
on_chip_click(gobj, entry);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}]
|
|
693
|
+
]]
|
|
570
694
|
);
|
|
571
695
|
entry.$chip = $chip;
|
|
572
696
|
priv.windows.push(entry);
|
|
@@ -635,6 +759,80 @@ function ac_focus_window(gobj, event, kw, src)
|
|
|
635
759
|
return 0;
|
|
636
760
|
}
|
|
637
761
|
|
|
762
|
+
/************************************************************
|
|
763
|
+
* EV_TOGGLE_WINDOW { window } -- the toggle of a chip of THIS
|
|
764
|
+
* dock was pressed: bring a minimized or covered window to the
|
|
765
|
+
* front, send the one in front to the dock. Only the dock's own
|
|
766
|
+
* chip sends it (src is the dock): the events a window sends
|
|
767
|
+
* about itself come from the window, and this one from the chip
|
|
768
|
+
* that names it.
|
|
769
|
+
************************************************************/
|
|
770
|
+
function ac_toggle_window(gobj, event, kw, src)
|
|
771
|
+
{
|
|
772
|
+
let priv = gobj.priv;
|
|
773
|
+
|
|
774
|
+
if(src !== gobj) {
|
|
775
|
+
log_error(
|
|
776
|
+
`${gobj_short_name(gobj)}: ${event} comes from the dock's own chip, ` +
|
|
777
|
+
`not from ${is_gobj(src) ? gobj_full_name(src) : String(src)}`
|
|
778
|
+
);
|
|
779
|
+
return -1;
|
|
780
|
+
}
|
|
781
|
+
let name = kw && kw.window;
|
|
782
|
+
let entry = priv.windows.find((e) => gobj_full_name(e.gobj) === name);
|
|
783
|
+
if(!entry) {
|
|
784
|
+
log_error(`${gobj_short_name(gobj)}: ${event}: no window '${name}' in the dock`);
|
|
785
|
+
return -1;
|
|
786
|
+
}
|
|
787
|
+
on_chip_click(gobj, entry);
|
|
788
|
+
return 0;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/************************************************************
|
|
792
|
+
* EV_SHELL_CHANGED -- a shell was built, or is being destroyed
|
|
793
|
+
* (yui_shell_watch_changes()). The dock's place -- the shell's
|
|
794
|
+
* popup layer, or its zone when inline -- may have gone with
|
|
795
|
+
* it, or be in the new one: place it again. Up to 7.26.34 an
|
|
796
|
+
* inline dock stayed in the destroyed shell's zone after a
|
|
797
|
+
* logout, detached, until a window registered. Its language
|
|
798
|
+
* is the new shell's too.
|
|
799
|
+
************************************************************/
|
|
800
|
+
function ac_shell_changed(gobj, event, kw, src)
|
|
801
|
+
{
|
|
802
|
+
apply_placement(gobj);
|
|
803
|
+
follow_language(gobj);
|
|
804
|
+
return 0;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/************************************************************
|
|
808
|
+
* EV_LANGUAGE_CHANGED -- from the shell that holds the dock.
|
|
809
|
+
* A chip's label re-translates by its key (refresh_language()
|
|
810
|
+
* reaches its kind half); the toggle's title and aria-label
|
|
811
|
+
* of a window with a DATA half are COMPOSED, so no key carries
|
|
812
|
+
* them: written again here. Up to 7.26.35 they stayed in the
|
|
813
|
+
* language the window was opened in (a reader took the
|
|
814
|
+
* aria-labelledby, which changed; the tooltip did not).
|
|
815
|
+
************************************************************/
|
|
816
|
+
function ac_language_changed(gobj, event, kw, src)
|
|
817
|
+
{
|
|
818
|
+
let priv = gobj.priv;
|
|
819
|
+
|
|
820
|
+
for(let entry of priv.windows) {
|
|
821
|
+
if(!entry.title_prefix || !entry.$chip) {
|
|
822
|
+
continue; // a key alone: data-i18n-title / -aria-label re-translate it
|
|
823
|
+
}
|
|
824
|
+
let $toggle = entry.$chip.querySelector(".DOCK_CHIP_TOGGLE");
|
|
825
|
+
if(!$toggle) {
|
|
826
|
+
log_error(`${gobj_short_name(gobj)}: a chip without its toggle`);
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
let title = chip_title(entry);
|
|
830
|
+
$toggle.setAttribute("title", title);
|
|
831
|
+
$toggle.setAttribute("aria-label", title);
|
|
832
|
+
}
|
|
833
|
+
return 0;
|
|
834
|
+
}
|
|
835
|
+
|
|
638
836
|
|
|
639
837
|
|
|
640
838
|
|
|
@@ -672,6 +870,9 @@ function create_gclass(gclass_name)
|
|
|
672
870
|
["EV_UNREGISTER_WINDOW", ac_unregister_window, null],
|
|
673
871
|
["EV_MINIMIZE_WINDOW", ac_minimize_window, null],
|
|
674
872
|
["EV_FOCUS_WINDOW", ac_focus_window, null],
|
|
873
|
+
["EV_TOGGLE_WINDOW", ac_toggle_window, null],
|
|
874
|
+
["EV_SHELL_CHANGED", ac_shell_changed, null],
|
|
875
|
+
["EV_LANGUAGE_CHANGED", ac_language_changed, null],
|
|
675
876
|
]]
|
|
676
877
|
];
|
|
677
878
|
|
|
@@ -683,6 +884,9 @@ function create_gclass(gclass_name)
|
|
|
683
884
|
["EV_UNREGISTER_WINDOW", 0],
|
|
684
885
|
["EV_MINIMIZE_WINDOW", 0],
|
|
685
886
|
["EV_FOCUS_WINDOW", 0],
|
|
887
|
+
["EV_TOGGLE_WINDOW", 0],
|
|
888
|
+
["EV_SHELL_CHANGED", 0],
|
|
889
|
+
["EV_LANGUAGE_CHANGED", 0],
|
|
686
890
|
];
|
|
687
891
|
|
|
688
892
|
__gclass__ = gclass_create(
|