@yuneta/gobj-ui 7.23.1 → 7.23.2
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 +13 -2
- package/dist/gobj-ui.cjs.js +262 -24
- package/dist/gobj-ui.es.js +262 -24
- package/package.json +1 -1
- package/src/c_yui_json.js +15 -1
- package/src/c_yui_json_graph.js +147 -4
- package/src/c_yui_treedb_topic_with_form.js +152 -10
package/src/c_yui_json_graph.js
CHANGED
|
@@ -74,6 +74,73 @@ const GCLASS_NAME = "C_YUI_JSON_GRAPH";
|
|
|
74
74
|
*/
|
|
75
75
|
const FOLD_SWALLOWED_EVENTS = ["pointerdown", "pointerup", "mousedown", "click"];
|
|
76
76
|
|
|
77
|
+
/*
|
|
78
|
+
* Layouts, same shape the gobj tree's registry uses
|
|
79
|
+
* (`c_yui_gobj_tree_js.js`): a G6 layout config plus the edge type
|
|
80
|
+
* that matches its direction — a vertical layout with horizontal
|
|
81
|
+
* cubics draws every edge going the wrong way round.
|
|
82
|
+
*
|
|
83
|
+
* `json-tree` is this gclass's own layout, the one it always had, and
|
|
84
|
+
* it stays the default: it sizes each level from the real card widths,
|
|
85
|
+
* which a generic layout cannot do with `html` nodes. The dagre pair
|
|
86
|
+
* is there for the documents it does badly — a wide, shallow object
|
|
87
|
+
* reads better left→right, which is also the house direction for a
|
|
88
|
+
* topology.
|
|
89
|
+
*/
|
|
90
|
+
const LAYOUTS = {
|
|
91
|
+
"json-tree": {
|
|
92
|
+
label: "vertical tree",
|
|
93
|
+
g6_layout: {type: 'json-tree-layout'},
|
|
94
|
+
edge_type: 'cubic-vertical',
|
|
95
|
+
},
|
|
96
|
+
"dagre-tb": {
|
|
97
|
+
label: "dagre top-down",
|
|
98
|
+
g6_layout: {type: 'antv-dagre', rankdir: 'TB', nodesep: 20, ranksep: 40},
|
|
99
|
+
edge_type: 'polyline',
|
|
100
|
+
},
|
|
101
|
+
"dagre-lr": {
|
|
102
|
+
label: "dagre left-right",
|
|
103
|
+
g6_layout: {type: 'antv-dagre', rankdir: 'LR', nodesep: 20, ranksep: 40},
|
|
104
|
+
edge_type: 'polyline',
|
|
105
|
+
},
|
|
106
|
+
/* `compact-box` is NOT here on purpose: it lays out from a fixed
|
|
107
|
+
* node size, and an `html` card is nothing like it — every card
|
|
108
|
+
* landed on top of the next. A layout that draws the document
|
|
109
|
+
* unreadable is worse than one option fewer. dagre reads the real
|
|
110
|
+
* sizes, which is why both of its directions are here. */
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const DEFAULT_LAYOUT = "json-tree";
|
|
114
|
+
|
|
115
|
+
function get_layout_cfg(key)
|
|
116
|
+
{
|
|
117
|
+
return LAYOUTS[key] || LAYOUTS[DEFAULT_LAYOUT];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/************************************************************
|
|
121
|
+
* A layout's label, with every key SPELLED OUT inside t().
|
|
122
|
+
*
|
|
123
|
+
* Never t(LAYOUTS[key].label) nor a `data-i18n` fed from that
|
|
124
|
+
* table: the apps' validate-locales scans for t("literal"),
|
|
125
|
+
* so a key reached through a variable is a key it cannot
|
|
126
|
+
* demand — and i18next answers an undefined key with the key
|
|
127
|
+
* itself, which renders in lower-case English and never
|
|
128
|
+
* changes language. Twice already in this component's
|
|
129
|
+
* history (7.20.0 `tree view`, and this table on its first
|
|
130
|
+
* draft).
|
|
131
|
+
************************************************************/
|
|
132
|
+
function layout_label(key)
|
|
133
|
+
{
|
|
134
|
+
switch(key) {
|
|
135
|
+
case "dagre-tb":
|
|
136
|
+
return t("dagre top-down");
|
|
137
|
+
case "dagre-lr":
|
|
138
|
+
return t("dagre left-right");
|
|
139
|
+
default:
|
|
140
|
+
return t("vertical tree");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
77
144
|
/***************************************************************
|
|
78
145
|
* Data
|
|
79
146
|
***************************************************************/
|
|
@@ -91,6 +158,7 @@ SDATA(data_type_t.DTP_STRING, "canvas_id", 0, "", "Canvas ID"),
|
|
|
91
158
|
|
|
92
159
|
/*---------------- Graph Settings ----------------*/
|
|
93
160
|
SDATA(data_type_t.DTP_STRING, "wide", 0, "36px", "Height of header"),
|
|
161
|
+
SDATA(data_type_t.DTP_STRING, "layout", 0, "json-tree", "Layout key (see LAYOUTS)"),
|
|
94
162
|
|
|
95
163
|
SDATA_END()
|
|
96
164
|
];
|
|
@@ -110,6 +178,7 @@ let PRIVATE_DATA = {
|
|
|
110
178
|
match_count: 0, // matches of the last find, for the count chip
|
|
111
179
|
find_timer: null, // rate-limits the find box
|
|
112
180
|
fold_listener: null, // delegated click on the card fold handles
|
|
181
|
+
$layout_select: null, // the layout picker
|
|
113
182
|
$find_input: null,
|
|
114
183
|
$find_result: null,
|
|
115
184
|
$find_count: null,
|
|
@@ -351,6 +420,7 @@ function build_ui(gobj)
|
|
|
351
420
|
log_error(`${gobj_short_name(gobj)}: no canvas mount, fold handles are dead`);
|
|
352
421
|
}
|
|
353
422
|
|
|
423
|
+
priv.$layout_select = $container.querySelector('.JSON_GRAPH_LAYOUT');
|
|
354
424
|
priv.$find_input = $container.querySelector('.JSON_GRAPH_FIND_INPUT');
|
|
355
425
|
priv.$find_result = $container.querySelector('.JSON_GRAPH_FIND_RESULT');
|
|
356
426
|
priv.$find_count = $container.querySelector('.JSON_GRAPH_FIND_COUNT');
|
|
@@ -516,7 +586,38 @@ function make_toolbar(gobj)
|
|
|
516
586
|
* went; "expand all" puts it back. Same chevron as the lazy tree,
|
|
517
587
|
* rotated to point down for the open state.
|
|
518
588
|
*/
|
|
589
|
+
/*
|
|
590
|
+
* A layout picker, same shape as the gobj tree's. One layout
|
|
591
|
+
* cannot serve every document: the built-in one sizes each level
|
|
592
|
+
* from the real card widths, dagre packs a wide shallow object
|
|
593
|
+
* far better, and left→right is the house direction for reading a
|
|
594
|
+
* topology.
|
|
595
|
+
*/
|
|
596
|
+
let current_layout = gobj_read_str_attr(gobj, "layout") || DEFAULT_LAYOUT;
|
|
597
|
+
let options = Object.keys(LAYOUTS).map(function(key) {
|
|
598
|
+
let attrs = {value: key, 'data-i18n': LAYOUTS[key].label};
|
|
599
|
+
if(key === current_layout) {
|
|
600
|
+
attrs.selected = "selected";
|
|
601
|
+
}
|
|
602
|
+
return ['option', attrs, layout_label(key)];
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
let $layout_select = createElement2(
|
|
606
|
+
['select', {
|
|
607
|
+
class: 'JSON_GRAPH_LAYOUT select',
|
|
608
|
+
style: {height: toolbar_wide, "margin-left": "0.5em"},
|
|
609
|
+
title: t("layout"), 'data-i18n-title': "layout",
|
|
610
|
+
'aria-label': t("layout"), 'data-i18n-aria-label': "layout"
|
|
611
|
+
}, options, {
|
|
612
|
+
change: (evt) => {
|
|
613
|
+
evt.stopPropagation();
|
|
614
|
+
gobj_send_event(gobj, "EV_CHANGE_LAYOUT", {layout: evt.target.value}, gobj);
|
|
615
|
+
}
|
|
616
|
+
}]
|
|
617
|
+
);
|
|
618
|
+
|
|
519
619
|
let right_items = [
|
|
620
|
+
$layout_select,
|
|
520
621
|
graph_fold_button(gobj, "EV_EXPAND_ALL", "expand all", true),
|
|
521
622
|
graph_fold_button(gobj, "EV_COLLAPSE_ALL", "collapse all", false),
|
|
522
623
|
];
|
|
@@ -537,6 +638,7 @@ function make_toolbar(gobj)
|
|
|
537
638
|
function build_graph(gobj)
|
|
538
639
|
{
|
|
539
640
|
let priv = gobj.priv;
|
|
641
|
+
let layout_cfg = get_layout_cfg(gobj_read_str_attr(gobj, "layout"));
|
|
540
642
|
|
|
541
643
|
const graph = priv.graph = new Graph({
|
|
542
644
|
container: priv.canvas_id,
|
|
@@ -551,7 +653,7 @@ function build_graph(gobj)
|
|
|
551
653
|
},
|
|
552
654
|
|
|
553
655
|
edge: {
|
|
554
|
-
type:
|
|
656
|
+
type: layout_cfg.edge_type,
|
|
555
657
|
style: {
|
|
556
658
|
stroke: '#999',
|
|
557
659
|
lineWidth: 1,
|
|
@@ -559,9 +661,7 @@ function build_graph(gobj)
|
|
|
559
661
|
},
|
|
560
662
|
},
|
|
561
663
|
|
|
562
|
-
layout:
|
|
563
|
-
type: 'json-tree-layout',
|
|
564
|
-
},
|
|
664
|
+
layout: layout_cfg.g6_layout,
|
|
565
665
|
|
|
566
666
|
behaviors: [
|
|
567
667
|
'drag-canvas',
|
|
@@ -1207,6 +1307,47 @@ function ac_refresh(gobj, event, kw, src)
|
|
|
1207
1307
|
|
|
1208
1308
|
/************************************************************
|
|
1209
1309
|
* {theme: "dark"|"light"} — the app switched theme.
|
|
1310
|
+
* EV_CHANGE_LAYOUT { layout }
|
|
1311
|
+
*
|
|
1312
|
+
* The layout AND the edge type move together — a vertical
|
|
1313
|
+
* layout with horizontal cubics draws every edge the wrong way
|
|
1314
|
+
* round — and then the graph is rebuilt and refitted, because a
|
|
1315
|
+
* new layout is a new shape and the old camera framed the old
|
|
1316
|
+
* one.
|
|
1317
|
+
************************************************************/
|
|
1318
|
+
function ac_change_layout(gobj, event, kw, src)
|
|
1319
|
+
{
|
|
1320
|
+
let priv = gobj.priv;
|
|
1321
|
+
let key = (kw && kw.layout) || "";
|
|
1322
|
+
|
|
1323
|
+
if(!LAYOUTS[key]) {
|
|
1324
|
+
log_error(`${gobj_short_name(gobj)}: unknown layout '${key}'`);
|
|
1325
|
+
return -1;
|
|
1326
|
+
}
|
|
1327
|
+
if(key === gobj_read_str_attr(gobj, "layout")) {
|
|
1328
|
+
return 0;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
gobj_write_str_attr(gobj, "layout", key);
|
|
1332
|
+
|
|
1333
|
+
/* Keep the picker in step when the event came from elsewhere. */
|
|
1334
|
+
if(priv.$layout_select && priv.$layout_select.value !== key) {
|
|
1335
|
+
priv.$layout_select.value = key;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
let cfg = get_layout_cfg(key);
|
|
1339
|
+
if(priv.graph) {
|
|
1340
|
+
priv.graph.setOptions({
|
|
1341
|
+
layout: cfg.g6_layout,
|
|
1342
|
+
edge: {type: cfg.edge_type},
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
refresh_json(gobj);
|
|
1346
|
+
update_find_result(gobj);
|
|
1347
|
+
return 0;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
/************************************************************
|
|
1210
1351
|
* EV_TOGGLE_FOLD { path } — fold or unfold ONE card.
|
|
1211
1352
|
*
|
|
1212
1353
|
* The camera does not move: folding one branch is a local
|
|
@@ -1489,6 +1630,7 @@ function create_gclass(gclass_name)
|
|
|
1489
1630
|
["EV_REFRESH", ac_refresh, null],
|
|
1490
1631
|
["EV_FIND_NODES", ac_find_nodes, null],
|
|
1491
1632
|
["EV_TOGGLE_FOLD", ac_toggle_fold, null],
|
|
1633
|
+
["EV_CHANGE_LAYOUT", ac_change_layout, null],
|
|
1492
1634
|
["EV_EXPAND_ALL", ac_expand_all, null],
|
|
1493
1635
|
["EV_COLLAPSE_ALL", ac_collapse_all, null],
|
|
1494
1636
|
["EV_THEME", ac_theme, null],
|
|
@@ -1511,6 +1653,7 @@ function create_gclass(gclass_name)
|
|
|
1511
1653
|
["EV_REFRESH", 0],
|
|
1512
1654
|
["EV_FIND_NODES", 0],
|
|
1513
1655
|
["EV_TOGGLE_FOLD", 0],
|
|
1656
|
+
["EV_CHANGE_LAYOUT", 0],
|
|
1514
1657
|
["EV_EXPAND_ALL", 0],
|
|
1515
1658
|
["EV_COLLAPSE_ALL", 0],
|
|
1516
1659
|
["EV_THEME", 0],
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
kwid_get_ids,
|
|
43
43
|
gobj_create_pure_child,
|
|
44
44
|
gobj_start,
|
|
45
|
+
gobj_create_service,
|
|
46
|
+
gobj_is_destroying,
|
|
45
47
|
gobj_stop,
|
|
46
48
|
gobj_destroy,
|
|
47
49
|
gobj_is_running,
|
|
@@ -170,9 +172,11 @@ let PRIVATE_DATA = {
|
|
|
170
172
|
form: null, // hosted C_YUI_FORM child (while dialog open)
|
|
171
173
|
form_modal: null, // { close } handle of the adaptive dialog
|
|
172
174
|
schema_gobj: null, // hosted C_YUI_JSON child (while schema open)
|
|
173
|
-
schema_modal: null, // { close } handle of the schema dialog
|
|
175
|
+
schema_modal: null, // { close } handle of the schema dialog (phone)
|
|
176
|
+
schema_win: null, // C_YUI_WINDOW presenting it (laptop)
|
|
174
177
|
cell_json_gobj: null, // hosted C_YUI_JSON child (while a cell is open)
|
|
175
|
-
cell_json_modal: null, // { close } handle of the cell dialog
|
|
178
|
+
cell_json_modal: null, // { close } handle of the cell dialog (phone)
|
|
179
|
+
cell_json_win: null, // C_YUI_WINDOW presenting it (laptop)
|
|
176
180
|
};
|
|
177
181
|
|
|
178
182
|
let __gclass__ = null;
|
|
@@ -184,6 +188,120 @@ let __gclass__ = null;
|
|
|
184
188
|
* stacking context below body-level modals). The legacy
|
|
185
189
|
* C_YUI_MAIN "#popup-layer" and document.body (Bulma `.modal` is
|
|
186
190
|
* position:fixed) remain the shell-less fallbacks. */
|
|
191
|
+
/* True on a phone-width viewport (Bulma's mobile breakpoint). */
|
|
192
|
+
function is_mobile()
|
|
193
|
+
{
|
|
194
|
+
return typeof window !== "undefined" && window.innerWidth <= 768;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/************************************************************
|
|
198
|
+
* Present a JSON viewer's $container.
|
|
199
|
+
*
|
|
200
|
+
* On a LAPTOP a floating C_YUI_WINDOW: a JSON document is
|
|
201
|
+
* something you read WHILE looking at the table behind it —
|
|
202
|
+
* you move it, you resize it, you maximise it when the
|
|
203
|
+
* document is big. A modal can do none of that, and it
|
|
204
|
+
* darkens exactly the rows you opened the cell from.
|
|
205
|
+
*
|
|
206
|
+
* On a phone the modal sheet stays: there is no room to
|
|
207
|
+
* arrange anything, and the sheet already carries the shell's
|
|
208
|
+
* Escape / Back handling.
|
|
209
|
+
*
|
|
210
|
+
* Returns {win, modal} — exactly one of them is set.
|
|
211
|
+
************************************************************/
|
|
212
|
+
function present_json_popup(gobj, $box, opts)
|
|
213
|
+
{
|
|
214
|
+
let shell = yui_shell_of(gobj);
|
|
215
|
+
if(!shell) {
|
|
216
|
+
log_error(`${gobj_short_name(gobj)}: no shell, cannot present the json`);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if(is_mobile()) {
|
|
221
|
+
return {
|
|
222
|
+
modal: yui_shell_show_modal(shell, $box, {
|
|
223
|
+
dialog: true,
|
|
224
|
+
logical_class: opts.logical_class + "_SHEET",
|
|
225
|
+
title_prefix: opts.title_prefix,
|
|
226
|
+
title: opts.title,
|
|
227
|
+
t: t,
|
|
228
|
+
on_close: opts.on_close
|
|
229
|
+
}),
|
|
230
|
+
win: null
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let win = gobj_create_service(
|
|
235
|
+
opts.name,
|
|
236
|
+
"C_YUI_WINDOW",
|
|
237
|
+
{
|
|
238
|
+
$parent: popup_mount_layer(gobj),
|
|
239
|
+
subscriber: null,
|
|
240
|
+
modal: false,
|
|
241
|
+
showMax: true,
|
|
242
|
+
showFooter: false,
|
|
243
|
+
resizable: true,
|
|
244
|
+
center: true,
|
|
245
|
+
auto_save_size_and_position: true,
|
|
246
|
+
width: 720,
|
|
247
|
+
height: 620,
|
|
248
|
+
logical_class: opts.logical_class + "_WINDOW",
|
|
249
|
+
title_prefix: opts.title_prefix,
|
|
250
|
+
title: opts.title,
|
|
251
|
+
icon: opts.icon,
|
|
252
|
+
body: $box,
|
|
253
|
+
manager: null,
|
|
254
|
+
/* C_YUI_WINDOW.close_window() calls this and THEN stops and
|
|
255
|
+
* destroys itself, so a teardown that also destroys the
|
|
256
|
+
* window destroys it twice — two "gobj NULL or DESTROYED".
|
|
257
|
+
* `opts.forget_window()` drops the host's reference first;
|
|
258
|
+
* the ✕ path is the window retiring ITSELF. */
|
|
259
|
+
on_close: function() {
|
|
260
|
+
if(gobj_is_destroying(gobj)) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
opts.forget_window();
|
|
264
|
+
opts.on_close();
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
gobj
|
|
268
|
+
);
|
|
269
|
+
if(!win) {
|
|
270
|
+
log_error(`${gobj_short_name(gobj)}: cannot create the json window`);
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
gobj_start(win);
|
|
274
|
+
return {win: win, modal: null};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/************************************************************
|
|
278
|
+
* Retire a presenting window: reference cleared FIRST, then
|
|
279
|
+
* stop, then destroy.
|
|
280
|
+
*
|
|
281
|
+
* The order is the whole content of this function. The ✕ of
|
|
282
|
+
* the window calls back into the teardown that calls this, so
|
|
283
|
+
* clearing the reference first is what stops the recursion.
|
|
284
|
+
* And it is STOP then destroy because the window was started
|
|
285
|
+
* on open: handing a running gobj to gobj_destroy() makes the
|
|
286
|
+
* framework rescue it and say so — "Destroying a RUNNING
|
|
287
|
+
* gobj" — which is a caller's bug, not a framework message.
|
|
288
|
+
* Same lesson `c_tranger_view.close_json_viewer` carries.
|
|
289
|
+
************************************************************/
|
|
290
|
+
function retire_popup_window(win)
|
|
291
|
+
{
|
|
292
|
+
if(!win) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
if(gobj_is_running(win)) {
|
|
297
|
+
gobj_stop(win);
|
|
298
|
+
}
|
|
299
|
+
gobj_destroy(win);
|
|
300
|
+
} catch(e) {
|
|
301
|
+
log_warning(`${GCLASS_NAME}: json window already gone: ${e}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
187
305
|
function popup_mount_layer(gobj)
|
|
188
306
|
{
|
|
189
307
|
let $layer = yui_shell_popup_layer(yui_shell_of(gobj));
|
|
@@ -1864,16 +1982,25 @@ function open_schema_dialog(gobj)
|
|
|
1864
1982
|
/* Title split in two halves: the topic name is DATA (never
|
|
1865
1983
|
* translated) and "schema" is the kind (carries its i18n key), so
|
|
1866
1984
|
* the header re-translates on a language switch. */
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
logical_class: "
|
|
1985
|
+
let presented = present_json_popup(gobj, $box, {
|
|
1986
|
+
name: "schemawin_" + clean_name(gobj_name(gobj)),
|
|
1987
|
+
logical_class: "TREEDB_SCHEMA",
|
|
1870
1988
|
title_prefix: gobj_read_str_attr(gobj, "topic_name"),
|
|
1871
1989
|
title: "schema",
|
|
1872
|
-
|
|
1990
|
+
icon: "yi-table",
|
|
1991
|
+
forget_window: function() {
|
|
1992
|
+
priv.schema_win = null;
|
|
1993
|
+
},
|
|
1873
1994
|
on_close: function() {
|
|
1874
1995
|
teardown_schema_child(gobj);
|
|
1875
1996
|
}
|
|
1876
1997
|
});
|
|
1998
|
+
if(!presented) {
|
|
1999
|
+
teardown_schema_child(gobj); // Error already logged
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
priv.schema_modal = presented.modal;
|
|
2003
|
+
priv.schema_win = presented.win;
|
|
1877
2004
|
|
|
1878
2005
|
/* EV_SET_JSON and not the `json_data` attr: the attr renders the
|
|
1879
2006
|
* tree but leaves the viewer in ST_IDLE, where a click to expand a
|
|
@@ -1896,6 +2023,9 @@ function teardown_schema_child(gobj)
|
|
|
1896
2023
|
gobj_destroy(priv.schema_gobj);
|
|
1897
2024
|
priv.schema_gobj = null;
|
|
1898
2025
|
}
|
|
2026
|
+
let win = priv.schema_win;
|
|
2027
|
+
priv.schema_win = null;
|
|
2028
|
+
retire_popup_window(win);
|
|
1899
2029
|
priv.schema_modal = null;
|
|
1900
2030
|
}
|
|
1901
2031
|
|
|
@@ -1982,16 +2112,25 @@ function open_cell_json_dialog(gobj, row_id, col_id)
|
|
|
1982
2112
|
* i18n key — the shared `col.id` one, so the header re-translates on a
|
|
1983
2113
|
* language switch and reads as the raw id where the app defines no key
|
|
1984
2114
|
* (exactly what an untranslated column header already shows). */
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
logical_class: "
|
|
2115
|
+
let presented = present_json_popup(gobj, $box, {
|
|
2116
|
+
name: "cellwin_" + clean_name(gobj_name(gobj)),
|
|
2117
|
+
logical_class: "TREEDB_CELL_JSON",
|
|
1988
2118
|
title_prefix: String(row_id),
|
|
1989
2119
|
title: col_id,
|
|
1990
|
-
|
|
2120
|
+
icon: "yi-js-square",
|
|
2121
|
+
forget_window: function() {
|
|
2122
|
+
priv.cell_json_win = null;
|
|
2123
|
+
},
|
|
1991
2124
|
on_close: function() {
|
|
1992
2125
|
teardown_cell_json_child(gobj);
|
|
1993
2126
|
}
|
|
1994
2127
|
});
|
|
2128
|
+
if(!presented) {
|
|
2129
|
+
teardown_cell_json_child(gobj); // Error already logged
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
2132
|
+
priv.cell_json_modal = presented.modal;
|
|
2133
|
+
priv.cell_json_win = presented.win;
|
|
1995
2134
|
|
|
1996
2135
|
/* EV_SET_JSON and not the `json_data` attr: the attr renders the
|
|
1997
2136
|
* tree but leaves the viewer in ST_IDLE, where a click to expand a
|
|
@@ -2014,6 +2153,9 @@ function teardown_cell_json_child(gobj)
|
|
|
2014
2153
|
gobj_destroy(priv.cell_json_gobj);
|
|
2015
2154
|
priv.cell_json_gobj = null;
|
|
2016
2155
|
}
|
|
2156
|
+
let win = priv.cell_json_win;
|
|
2157
|
+
priv.cell_json_win = null;
|
|
2158
|
+
retire_popup_window(win);
|
|
2017
2159
|
priv.cell_json_modal = null;
|
|
2018
2160
|
}
|
|
2019
2161
|
|