@yuneta/gobj-ui 7.26.39 → 7.26.41
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 +37 -2
- package/dist/gobj-ui.cjs.js +135 -75
- package/dist/gobj-ui.es.js +135 -75
- package/package.json +1 -1
- package/src/c_yui_form.js +80 -68
- package/src/c_yui_uplot.js +8 -58
- package/src/form_table_edits_ask.wiring.test.js +398 -0
- package/src/form_table_rearm.wiring.test.js +9 -7
- package/src/uplot_ink.test.js +105 -0
- package/src/yui_tabulator_i18n.js +21 -1
- package/src/yui_tabulator_i18n.test.js +39 -0
- package/src/yui_text.js +10 -0
- package/src/yui_text.test.js +13 -0
- package/src/yui_uplot_ink.js +94 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -500,8 +500,16 @@ function text_node(value) {
|
|
|
500
500
|
* Tabulator puts a STRING title in with innerHTML, so a title taken
|
|
501
501
|
* from a schema (`header`, which the schema editor writes) is markup
|
|
502
502
|
* unless the column carries a formatter that returns a Node.
|
|
503
|
+
*
|
|
504
|
+
* And it APPENDS that Node to the title's holder, which it never
|
|
505
|
+
* empties -- while it runs the formatter again on every setLocale()
|
|
506
|
+
* (yui_tabulator_relocalize()). Until 7.26.40 each change of language
|
|
507
|
+
* added one more copy of every title ("Id dispositivoId dispositivo").
|
|
508
|
+
* The holder (the mock cell's element) is emptied first.
|
|
503
509
|
************************************************************/
|
|
504
510
|
function text_title_formatter(cell) {
|
|
511
|
+
const $holder = typeof cell.getElement === "function" ? cell.getElement() : null;
|
|
512
|
+
if ($holder) $holder.textContent = "";
|
|
505
513
|
return text_node(cell.getValue());
|
|
506
514
|
}
|
|
507
515
|
/************************************************************
|
|
@@ -7101,6 +7109,12 @@ function register_c_yui_wizard() {
|
|
|
7101
7109
|
* new Tabulator($el, {..., ...yui_tabulator_lang(t)});
|
|
7102
7110
|
* yui_tabulator_relocalize(table, t); // on a language change
|
|
7103
7111
|
*
|
|
7112
|
+
* A view whose COLUMN TITLES change language hands them too, in the
|
|
7113
|
+
* new language, by field -- Tabulator binds each column's title to its
|
|
7114
|
+
* locale, so they change with it and no column is rebuilt:
|
|
7115
|
+
*
|
|
7116
|
+
* yui_tabulator_relocalize(table, t, {device_id: t("device id")});
|
|
7117
|
+
*
|
|
7104
7118
|
* Every key carries an English `defaultValue`, so an app that does not
|
|
7105
7119
|
* define it renders exactly what Tabulator rendered before — the
|
|
7106
7120
|
* keys are an OPPORTUNITY to translate, never a requirement.
|
|
@@ -7259,11 +7273,23 @@ function yui_tabulator_name_editor(column_def, name_of) {
|
|
|
7259
7273
|
return Object.assign({}, params, { elementAttributes: attrs });
|
|
7260
7274
|
};
|
|
7261
7275
|
}
|
|
7262
|
-
|
|
7276
|
+
/***************************************************************
|
|
7277
|
+
* yui_tabulator_relocalize() -- see "Put an EXISTING table in the
|
|
7278
|
+
* current language" above.
|
|
7279
|
+
*
|
|
7280
|
+
* `titles`, optional: {field: title}, the titles of the columns in
|
|
7281
|
+
* the new language, already translated. They go in the locale
|
|
7282
|
+
* (`columns`), where Tabulator binds each column's title: setLocale()
|
|
7283
|
+
* draws them again without rebuilding a column -- updateDefinition()
|
|
7284
|
+
* re-renders every row, and a row whose formatter builds something (a
|
|
7285
|
+
* nested table) builds it anew. A field left out keeps its title.
|
|
7286
|
+
***************************************************************/
|
|
7287
|
+
function yui_tabulator_relocalize(table, t, titles) {
|
|
7263
7288
|
if (!table) return;
|
|
7264
7289
|
try {
|
|
7265
7290
|
let name = next_lang_name();
|
|
7266
7291
|
let strings = tabulator_strings(t);
|
|
7292
|
+
if (titles && typeof titles === "object") strings.columns = Object.assign({}, titles);
|
|
7267
7293
|
table.options.langs = table.options.langs || {};
|
|
7268
7294
|
table.options.langs[name] = strings;
|
|
7269
7295
|
let localize = table.modules && table.modules.localize;
|
|
@@ -9482,7 +9508,7 @@ var attrs_table$17 = [
|
|
|
9482
9508
|
SDATA_END()
|
|
9483
9509
|
];
|
|
9484
9510
|
var PRIVATE_DATA$17 = {
|
|
9485
|
-
|
|
9511
|
+
loading_rows: 0,
|
|
9486
9512
|
tables: null,
|
|
9487
9513
|
table_seq: 0,
|
|
9488
9514
|
json_names_posted: false,
|
|
@@ -9538,18 +9564,12 @@ function mt_stop$17(gobj) {
|
|
|
9538
9564
|
* Local Methods
|
|
9539
9565
|
***************************/
|
|
9540
9566
|
/************************************************************
|
|
9541
|
-
*
|
|
9542
|
-
|
|
9543
|
-
function isEventSet(table, event) {
|
|
9544
|
-
let eventListeners = table.externalEvents.events;
|
|
9545
|
-
return eventListeners && eventListeners[event] && eventListeners[event].length > 0;
|
|
9546
|
-
}
|
|
9547
|
-
/************************************************************
|
|
9548
|
-
*
|
|
9567
|
+
* `changes` and the save/undo buttons. What the tables say is
|
|
9568
|
+
* not switched here: they always say it (create_tabulator).
|
|
9549
9569
|
************************************************************/
|
|
9550
9570
|
function set_changed_stated(gobj, changed) {
|
|
9551
9571
|
let $container = gobj_read_attr(gobj, "$container");
|
|
9552
|
-
|
|
9572
|
+
$container.querySelector("form");
|
|
9553
9573
|
const enable = ($btn, on, color) => {
|
|
9554
9574
|
if (!$btn) return;
|
|
9555
9575
|
if (on) $btn.removeAttribute("disabled");
|
|
@@ -9564,35 +9584,11 @@ function set_changed_stated(gobj, changed) {
|
|
|
9564
9584
|
gobj_write_bool_attr(gobj, "changes", true);
|
|
9565
9585
|
enable($button_save, true, "MediumSeaGreen");
|
|
9566
9586
|
enable($button_undo, true, "Magenta");
|
|
9567
|
-
$form.querySelectorAll(".yui-tabulator-table").forEach(($table) => {
|
|
9568
|
-
if ($table.tabulator && isEventSet($table.tabulator, "dataChanged")) $table.tabulator.off("dataChanged");
|
|
9569
|
-
$table.querySelectorAll(".yui-tabulator-table-nested").forEach(($table_nested) => {
|
|
9570
|
-
if ($table_nested.tabulator && isEventSet($table_nested.tabulator, "dataChanged")) $table_nested.tabulator.off("dataChanged");
|
|
9571
|
-
});
|
|
9572
|
-
});
|
|
9573
9587
|
} else {
|
|
9574
9588
|
gobj_write_bool_attr(gobj, "changes", false);
|
|
9575
9589
|
gobj_write_bool_attr(gobj, "edited", false);
|
|
9576
9590
|
enable($button_save, false, OFF_COLOR);
|
|
9577
9591
|
enable($button_undo, false, OFF_COLOR);
|
|
9578
|
-
if (gobj.priv.rearm_timer) clearTimeout(gobj.priv.rearm_timer);
|
|
9579
|
-
gobj.priv.rearm_timer = setTimeout(function() {
|
|
9580
|
-
gobj.priv.rearm_timer = null;
|
|
9581
|
-
if (gobj_is_destroying(gobj)) return;
|
|
9582
|
-
const rearm = (tabulator) => {
|
|
9583
|
-
if (!tabulator) return;
|
|
9584
|
-
if (isEventSet(tabulator, "dataChanged")) tabulator.off("dataChanged");
|
|
9585
|
-
tabulator.on("dataChanged", function(data) {
|
|
9586
|
-
gobj_send_event(gobj, "EV_RECORD_CHANGED", {}, gobj);
|
|
9587
|
-
});
|
|
9588
|
-
};
|
|
9589
|
-
$form.querySelectorAll(".yui-tabulator-table").forEach(($table) => {
|
|
9590
|
-
rearm($table.tabulator);
|
|
9591
|
-
$table.querySelectorAll(".yui-tabulator-table-nested").forEach(($table_nested) => {
|
|
9592
|
-
rearm($table_nested.tabulator);
|
|
9593
|
-
});
|
|
9594
|
-
});
|
|
9595
|
-
}, 200);
|
|
9596
9592
|
}
|
|
9597
9593
|
}
|
|
9598
9594
|
/************************************************************
|
|
@@ -9829,10 +9825,6 @@ function build_ui$15(gobj) {
|
|
|
9829
9825
|
* Destroy UI
|
|
9830
9826
|
************************************************************/
|
|
9831
9827
|
function destroy_ui$10(gobj) {
|
|
9832
|
-
if (gobj.priv && gobj.priv.rearm_timer) {
|
|
9833
|
-
clearTimeout(gobj.priv.rearm_timer);
|
|
9834
|
-
gobj.priv.rearm_timer = null;
|
|
9835
|
-
}
|
|
9836
9828
|
let $container = gobj_read_attr(gobj, "$container");
|
|
9837
9829
|
if ($container) {
|
|
9838
9830
|
destroy_widgets(gobj, $container);
|
|
@@ -11226,6 +11218,10 @@ function create_tabulator$1(gobj, $extend, name, template) {
|
|
|
11226
11218
|
hozAlign: "center"
|
|
11227
11219
|
};
|
|
11228
11220
|
let tabulator = new TabulatorFull($extend, tabulator_settings);
|
|
11221
|
+
tabulator.on("dataChanged", function() {
|
|
11222
|
+
if (gobj.priv.loading_rows > 0) return;
|
|
11223
|
+
gobj_send_event(gobj, "EV_RECORD_CHANGED", {}, gobj);
|
|
11224
|
+
});
|
|
11229
11225
|
tabulator.on("renderComplete", function() {
|
|
11230
11226
|
yui_tabulator_name_row_selects(tabulator, t);
|
|
11231
11227
|
});
|
|
@@ -11243,6 +11239,24 @@ function create_tabulator$1(gobj, $extend, name, template) {
|
|
|
11243
11239
|
return tabulator;
|
|
11244
11240
|
}
|
|
11245
11241
|
/******************************************************************
|
|
11242
|
+
* The title of a table's column: the schema's header, or the
|
|
11243
|
+
* field's name, translated.
|
|
11244
|
+
******************************************************************/
|
|
11245
|
+
function column_title(field_desc) {
|
|
11246
|
+
return t(field_desc.header || field_desc.name);
|
|
11247
|
+
}
|
|
11248
|
+
/******************************************************************
|
|
11249
|
+
* {field: title} of a table's template, in the current language.
|
|
11250
|
+
******************************************************************/
|
|
11251
|
+
function table_column_titles(template) {
|
|
11252
|
+
let titles = {};
|
|
11253
|
+
Object.entries(template || {}).forEach(([key, value]) => {
|
|
11254
|
+
const field_desc = template_get_field_desc(key, value);
|
|
11255
|
+
titles[field_desc.name] = column_title(field_desc);
|
|
11256
|
+
});
|
|
11257
|
+
return titles;
|
|
11258
|
+
}
|
|
11259
|
+
/******************************************************************
|
|
11246
11260
|
* Convert a template's items in tabulator columns
|
|
11247
11261
|
******************************************************************/
|
|
11248
11262
|
function template2columns(gobj, columns, template, sub_elements) {
|
|
@@ -11255,7 +11269,7 @@ function template2columns(gobj, columns, template, sub_elements) {
|
|
|
11255
11269
|
let validator = [];
|
|
11256
11270
|
let column = {
|
|
11257
11271
|
field: field_desc.name,
|
|
11258
|
-
title:
|
|
11272
|
+
title: column_title(field_desc),
|
|
11259
11273
|
titleFormatter: text_title_formatter,
|
|
11260
11274
|
editable: get_editable_state,
|
|
11261
11275
|
editor: false,
|
|
@@ -12110,7 +12124,14 @@ function ac_add_table_row(gobj, event, kw, src) {
|
|
|
12110
12124
|
}
|
|
12111
12125
|
let record = kw.record;
|
|
12112
12126
|
let loading = kw.loading;
|
|
12113
|
-
|
|
12127
|
+
let added;
|
|
12128
|
+
if (loading) gobj.priv.loading_rows++;
|
|
12129
|
+
try {
|
|
12130
|
+
added = tabulator.addRow(record);
|
|
12131
|
+
} finally {
|
|
12132
|
+
if (loading) gobj.priv.loading_rows--;
|
|
12133
|
+
}
|
|
12134
|
+
added.then(function(row) {
|
|
12114
12135
|
if (loading) {
|
|
12115
12136
|
let template = $table.template;
|
|
12116
12137
|
Object.entries(template).forEach(([key, template_value]) => {
|
|
@@ -12217,6 +12238,10 @@ function ac_language_changed$10(gobj, event, kw, src) {
|
|
|
12217
12238
|
let editor = $editor.jsoneditor;
|
|
12218
12239
|
if (editor && typeof editor.updateProps === "function") editor.updateProps({ onRenderMenu: json_editor_render_menu(gobj) });
|
|
12219
12240
|
}
|
|
12241
|
+
for (let $table of $container.querySelectorAll(".yui-tabulator-table, .yui-tabulator-table-nested")) {
|
|
12242
|
+
let tabulator = $table.tabulator;
|
|
12243
|
+
if (tabulator && tabulator.initialized && $table.template) yui_tabulator_relocalize(tabulator, t, table_column_titles($table.template));
|
|
12244
|
+
}
|
|
12220
12245
|
return 0;
|
|
12221
12246
|
}
|
|
12222
12247
|
/***************************
|
|
@@ -13391,41 +13416,58 @@ function register_c_yui_map() {
|
|
|
13391
13416
|
return create_gclass$16(GCLASS_NAME$16);
|
|
13392
13417
|
}
|
|
13393
13418
|
//#endregion
|
|
13394
|
-
//#region src/
|
|
13419
|
+
//#region src/yui_uplot_ink.js
|
|
13395
13420
|
/***********************************************************************
|
|
13396
|
-
*
|
|
13421
|
+
* yui_uplot_ink.js
|
|
13397
13422
|
*
|
|
13398
|
-
*
|
|
13423
|
+
* The ink of a uPlot chart, on both schemes, and its palette.
|
|
13399
13424
|
*
|
|
13400
|
-
*
|
|
13425
|
+
* uPlot is built for a white page: its axis labels are `#000`
|
|
13426
|
+
* and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
|
|
13427
|
+
* 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
|
|
13428
|
+
* not there. The inks here are handed to uPlot as FUNCTIONS: it
|
|
13429
|
+
* calls them when it draws, so the value can never be stale --
|
|
13430
|
+
* what goes stale is the canvas, and a change of the theme has to
|
|
13431
|
+
* ask for a redraw (yui_watch_theme() turns it into an event).
|
|
13432
|
+
*
|
|
13433
|
+
* uPlot ALWAYS draws a Y axis: its setDefaults() makes axes[1]
|
|
13434
|
+
* whether it was given or not, with its own black. So the axes are
|
|
13435
|
+
* padded to two before they are inked. C_YUI_UPLOT's default is
|
|
13436
|
+
* `[{}]`, the X axis alone, and until 7.26.40 every chart of the
|
|
13437
|
+
* library had a Y axis whose values could not be read in the dark.
|
|
13438
|
+
*
|
|
13439
|
+
* C_YUI_UPLOT uses it, and so can an app that builds a uPlot of its
|
|
13440
|
+
* own:
|
|
13441
|
+
*
|
|
13442
|
+
* import {yui_uplot_axes} from "@yuneta/gobj-ui/src/yui_uplot_ink.js";
|
|
13443
|
+
*
|
|
13444
|
+
* const chart = new uPlot({
|
|
13445
|
+
* width: 600, height: 300,
|
|
13446
|
+
* series: [{}, {label: "temperature"}],
|
|
13447
|
+
* axes: yui_uplot_axes([{}]), // X and Y, with the ink of the theme
|
|
13448
|
+
* }, data, $el);
|
|
13449
|
+
*
|
|
13450
|
+
* The palette is six colours that clear 3:1 on BOTH grounds
|
|
13451
|
+
* (worst 3.39 on white, 3.71 on near-black), ordered so the first
|
|
13452
|
+
* two are the pair that survives colour blindness -- blue and
|
|
13453
|
+
* orange, never red and green as the opening pair.
|
|
13454
|
+
*
|
|
13455
|
+
* Copyright (c) 2026, ArtGins.
|
|
13401
13456
|
* All Rights Reserved.
|
|
13402
13457
|
***********************************************************************/
|
|
13403
|
-
|
|
13404
|
-
* The ink of
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
* and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
|
|
13408
|
-
* 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
|
|
13409
|
-
* not there. And the series were CSS colour names: `blue` is
|
|
13410
|
-
* 2.11:1 on the dark ground, `orange` 1.97 on the light one, so
|
|
13411
|
-
* whichever scheme you were in, one of the lines was a rumour.
|
|
13412
|
-
*
|
|
13413
|
-
* These are given to uPlot as FUNCTIONS: it calls them when it
|
|
13414
|
-
* draws, so the value can never be stale -- what goes stale is
|
|
13415
|
-
* the canvas, and that is what EV_THEME redraws.
|
|
13416
|
-
*
|
|
13417
|
-
* The palette is six colours that clear 3:1 on BOTH grounds
|
|
13418
|
-
* (worst 3.39 on white, 3.71 on near-black), ordered so the
|
|
13419
|
-
* first two are the pair that survives colour blindness -- blue
|
|
13420
|
-
* and orange, never red and green as the opening pair.
|
|
13421
|
-
***************************************************************/
|
|
13422
|
-
function axis_ink() {
|
|
13458
|
+
/************************************************************
|
|
13459
|
+
* The ink of the labels of an axis.
|
|
13460
|
+
************************************************************/
|
|
13461
|
+
function yui_uplot_axis_ink() {
|
|
13423
13462
|
return yui_is_dark() ? "#c7cdd8" : "#2e333d";
|
|
13424
13463
|
}
|
|
13425
|
-
|
|
13464
|
+
/************************************************************
|
|
13465
|
+
* The ink of the grid and of the ticks.
|
|
13466
|
+
************************************************************/
|
|
13467
|
+
function yui_uplot_grid_ink() {
|
|
13426
13468
|
return yui_is_dark() ? "rgba(199,205,216,0.16)" : "rgba(46,51,61,0.12)";
|
|
13427
13469
|
}
|
|
13428
|
-
var
|
|
13470
|
+
var YUI_UPLOT_PALETTE = [
|
|
13429
13471
|
{
|
|
13430
13472
|
stroke: "#2f6fd0",
|
|
13431
13473
|
fill: "rgba(47,111,208,0.10)"
|
|
@@ -13451,15 +13493,33 @@ var CHART_PALETTE = [
|
|
|
13451
13493
|
fill: "rgba(209,52,75,0.10)"
|
|
13452
13494
|
}
|
|
13453
13495
|
];
|
|
13454
|
-
|
|
13455
|
-
|
|
13496
|
+
/************************************************************
|
|
13497
|
+
* The axes the host asked for -- at least the X and the Y,
|
|
13498
|
+
* the two uPlot always draws -- with the ink it did not ask
|
|
13499
|
+
* about. A stroke, a grid or a ticks the host gave is kept.
|
|
13500
|
+
* Answers new objects: the host's are not touched.
|
|
13501
|
+
************************************************************/
|
|
13502
|
+
function yui_uplot_axes(axes) {
|
|
13503
|
+
let list = Array.isArray(axes) ? axes.slice() : [axes || {}];
|
|
13504
|
+
while (list.length < 2) list.push({});
|
|
13505
|
+
return list.map((ax) => {
|
|
13456
13506
|
let a = Object.assign({}, ax || {});
|
|
13457
|
-
if (a.stroke === void 0) a.stroke =
|
|
13458
|
-
a.grid = Object.assign({ stroke:
|
|
13459
|
-
a.ticks = Object.assign({ stroke:
|
|
13507
|
+
if (a.stroke === void 0) a.stroke = yui_uplot_axis_ink;
|
|
13508
|
+
a.grid = Object.assign({ stroke: yui_uplot_grid_ink }, a.grid || {});
|
|
13509
|
+
a.ticks = Object.assign({ stroke: yui_uplot_grid_ink }, a.ticks || {});
|
|
13460
13510
|
return a;
|
|
13461
13511
|
});
|
|
13462
13512
|
}
|
|
13513
|
+
//#endregion
|
|
13514
|
+
//#region src/c_yui_uplot.js
|
|
13515
|
+
/***********************************************************************
|
|
13516
|
+
* c_yui_uplot.js
|
|
13517
|
+
*
|
|
13518
|
+
* Graphics, Charts with uPlot
|
|
13519
|
+
*
|
|
13520
|
+
* Copyright (c) 2025-2026, ArtGins.
|
|
13521
|
+
* All Rights Reserved.
|
|
13522
|
+
***********************************************************************/
|
|
13463
13523
|
/***************************************************************
|
|
13464
13524
|
* Constants
|
|
13465
13525
|
***************************************************************/
|
|
@@ -13477,7 +13537,7 @@ var attrs_table$15 = [
|
|
|
13477
13537
|
SDATA(data_type_t.DTP_JSON, "axes", 0, [{}], "Chart axes"),
|
|
13478
13538
|
SDATA(data_type_t.DTP_JSON, "scales", 0, {}, "Chart scales"),
|
|
13479
13539
|
SDATA(data_type_t.DTP_JSON, "data", 0, [[]], "Chart data"),
|
|
13480
|
-
SDATA(data_type_t.DTP_JSON, "colors", 0,
|
|
13540
|
+
SDATA(data_type_t.DTP_JSON, "colors", 0, YUI_UPLOT_PALETTE, "Series colours, in order. The default palette clears 3:1 on both schemes and opens with the colour-blind-safe pair (blue, orange)"),
|
|
13481
13541
|
SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "HTML container for the chart"),
|
|
13482
13542
|
SDATA(data_type_t.DTP_BOOLEAN, "own_container", 0, false, "If true, container is gobj-managed"),
|
|
13483
13543
|
SDATA(data_type_t.DTP_POINTER, "uplot", 0, null, "uPlot instance"),
|
|
@@ -13544,7 +13604,7 @@ function build_ui$14(gobj) {
|
|
|
13544
13604
|
width: gobj_read_attr(gobj, "width"),
|
|
13545
13605
|
height: gobj_read_attr(gobj, "height"),
|
|
13546
13606
|
series: gobj_read_attr(gobj, "series"),
|
|
13547
|
-
axes:
|
|
13607
|
+
axes: yui_uplot_axes(gobj_read_attr(gobj, "axes")),
|
|
13548
13608
|
scales: gobj_read_attr(gobj, "scales")
|
|
13549
13609
|
};
|
|
13550
13610
|
let uplot = new uPlot(uPlot_options, gobj_read_attr(gobj, "data"), $container);
|
|
@@ -13645,7 +13705,7 @@ function ac_add_serie(gobj, event, kw, src) {
|
|
|
13645
13705
|
}
|
|
13646
13706
|
}
|
|
13647
13707
|
let colors = gobj_read_attr(gobj, "colors");
|
|
13648
|
-
if (!Array.isArray(colors) || !colors.length) colors =
|
|
13708
|
+
if (!Array.isArray(colors) || !colors.length) colors = YUI_UPLOT_PALETTE;
|
|
13649
13709
|
let color = colors[Math.max(0, idx - 1) % colors.length];
|
|
13650
13710
|
if (kw.stroke === void 0) kw.stroke = color.stroke;
|
|
13651
13711
|
if (kw.fill === void 0) kw.fill = color.fill;
|
package/package.json
CHANGED
package/src/c_yui_form.js
CHANGED
|
@@ -55,7 +55,11 @@ import {
|
|
|
55
55
|
|
|
56
56
|
import {t} from "i18next";
|
|
57
57
|
|
|
58
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
yui_tabulator_name_row_selects,
|
|
60
|
+
yui_tabulator_name_editor,
|
|
61
|
+
yui_tabulator_relocalize
|
|
62
|
+
} from "./yui_tabulator_i18n.js";
|
|
59
63
|
import "tom-select/dist/css/tom-select.css"; // Import Tom-Select CSS
|
|
60
64
|
import TomSelect from "tom-select"; // Import Tom-Select JS
|
|
61
65
|
|
|
@@ -172,9 +176,10 @@ SDATA_END()
|
|
|
172
176
|
];
|
|
173
177
|
|
|
174
178
|
let PRIVATE_DATA = {
|
|
175
|
-
/*
|
|
176
|
-
*
|
|
177
|
-
|
|
179
|
+
/* > 0 while the FORM adds rows (a record loaded, a nested table
|
|
180
|
+
* filled): what a table says then is no change of the reader's
|
|
181
|
+
* (see create_tabulator's dataChanged). */
|
|
182
|
+
loading_rows: 0,
|
|
178
183
|
/* table_id -> WeakRef of its element: EV_ADD_TABLE_ROW names a
|
|
179
184
|
* table by id (a kw is plain json), see table_identity(). */
|
|
180
185
|
tables: null,
|
|
@@ -281,17 +286,8 @@ function mt_stop(gobj)
|
|
|
281
286
|
|
|
282
287
|
|
|
283
288
|
/************************************************************
|
|
284
|
-
*
|
|
285
|
-
|
|
286
|
-
function isEventSet(table, event)
|
|
287
|
-
{
|
|
288
|
-
// Access the event listeners directly from the Tabulator instance
|
|
289
|
-
let eventListeners = table.externalEvents.events;
|
|
290
|
-
return eventListeners && eventListeners[event] && eventListeners[event].length > 0;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/************************************************************
|
|
294
|
-
*
|
|
289
|
+
* `changes` and the save/undo buttons. What the tables say is
|
|
290
|
+
* not switched here: they always say it (create_tabulator).
|
|
295
291
|
************************************************************/
|
|
296
292
|
function set_changed_stated(gobj, changed)
|
|
297
293
|
{
|
|
@@ -333,18 +329,6 @@ function set_changed_stated(gobj, changed)
|
|
|
333
329
|
enable($button_save, true, "MediumSeaGreen");
|
|
334
330
|
enable($button_undo, true, "Magenta");
|
|
335
331
|
|
|
336
|
-
$form.querySelectorAll('.yui-tabulator-table').forEach($table => {
|
|
337
|
-
if($table.tabulator && isEventSet($table.tabulator, "dataChanged")) {
|
|
338
|
-
$table.tabulator.off("dataChanged");
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
$table.querySelectorAll('.yui-tabulator-table-nested').forEach($table_nested => {
|
|
342
|
-
if($table_nested.tabulator && isEventSet($table_nested.tabulator, "dataChanged")) {
|
|
343
|
-
$table_nested.tabulator.off("dataChanged");
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
|
|
348
332
|
} else {
|
|
349
333
|
/*
|
|
350
334
|
* Data not changed, disable buttons to save/undo
|
|
@@ -354,41 +338,6 @@ function set_changed_stated(gobj, changed)
|
|
|
354
338
|
|
|
355
339
|
enable($button_save, false, OFF_COLOR);
|
|
356
340
|
enable($button_undo, false, OFF_COLOR);
|
|
357
|
-
|
|
358
|
-
/*
|
|
359
|
-
* TODO improve. The tables are re-wired a moment later, once the
|
|
360
|
-
* data just loaded has settled. The timer is kept so that
|
|
361
|
-
* destroy_ui() cancels it: a form closed right after a save (what
|
|
362
|
-
* a dialog does) destroyed its widgets first, and the timer then
|
|
363
|
-
* called .on() on a null tabulator -- an uncaught TypeError.
|
|
364
|
-
*/
|
|
365
|
-
if(gobj.priv.rearm_timer) {
|
|
366
|
-
clearTimeout(gobj.priv.rearm_timer);
|
|
367
|
-
}
|
|
368
|
-
gobj.priv.rearm_timer = setTimeout(function() {
|
|
369
|
-
gobj.priv.rearm_timer = null;
|
|
370
|
-
if(gobj_is_destroying(gobj)) {
|
|
371
|
-
return; // destroy_ui() cancels it; this is the belt
|
|
372
|
-
}
|
|
373
|
-
const rearm = (tabulator) => {
|
|
374
|
-
if(!tabulator) {
|
|
375
|
-
return; // destroyed with its form
|
|
376
|
-
}
|
|
377
|
-
if(isEventSet(tabulator, "dataChanged")) {
|
|
378
|
-
tabulator.off("dataChanged");
|
|
379
|
-
}
|
|
380
|
-
tabulator.on("dataChanged", function(data) {
|
|
381
|
-
//data - the updated table data
|
|
382
|
-
gobj_send_event(gobj, "EV_RECORD_CHANGED", {}, gobj);
|
|
383
|
-
});
|
|
384
|
-
};
|
|
385
|
-
$form.querySelectorAll('.yui-tabulator-table').forEach($table => {
|
|
386
|
-
rearm($table.tabulator);
|
|
387
|
-
$table.querySelectorAll('.yui-tabulator-table-nested').forEach($table_nested => {
|
|
388
|
-
rearm($table_nested.tabulator);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
}, 200);
|
|
392
341
|
}
|
|
393
342
|
}
|
|
394
343
|
|
|
@@ -562,10 +511,6 @@ function build_ui(gobj)
|
|
|
562
511
|
************************************************************/
|
|
563
512
|
function destroy_ui(gobj)
|
|
564
513
|
{
|
|
565
|
-
if(gobj.priv && gobj.priv.rearm_timer) {
|
|
566
|
-
clearTimeout(gobj.priv.rearm_timer);
|
|
567
|
-
gobj.priv.rearm_timer = null;
|
|
568
|
-
}
|
|
569
514
|
let $container = gobj_read_attr(gobj, "$container");
|
|
570
515
|
if($container) {
|
|
571
516
|
destroy_widgets(gobj, $container);
|
|
@@ -2332,6 +2277,22 @@ function create_tabulator(gobj, $extend, name, template)
|
|
|
2332
2277
|
$extend,
|
|
2333
2278
|
tabulator_settings
|
|
2334
2279
|
);
|
|
2280
|
+
/* What the READER does to a table -- edits a cell, adds or deletes a
|
|
2281
|
+
* row -- reaches the form only through `dataChanged`. Wired here, on
|
|
2282
|
+
* every table, nested ones included (a row's formatter builds them
|
|
2283
|
+
* whenever the row is drawn), and never switched off: until 7.26.40
|
|
2284
|
+
* it was unwired whenever the form was CHANGED and re-wired only by a
|
|
2285
|
+
* save, an undo or a load of what is stored, so a form that opened
|
|
2286
|
+
* changed (a field its record lacks, filled with its default) never
|
|
2287
|
+
* heard its tables -- an edit there was not `edited`, and closing lost
|
|
2288
|
+
* it without a question. The rows the form adds itself say nothing
|
|
2289
|
+
* (`loading_rows`, ac_add_table_row). */
|
|
2290
|
+
tabulator.on("dataChanged", function() {
|
|
2291
|
+
if(gobj.priv.loading_rows > 0) {
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
gobj_send_event(gobj, "EV_RECORD_CHANGED", {}, gobj);
|
|
2295
|
+
});
|
|
2335
2296
|
/* Tabulator hard-codes `aria-label="Select Row"` on the box its
|
|
2336
2297
|
* rowSelection formatter draws, and it draws a fresh one on EVERY
|
|
2337
2298
|
* render -- so this hangs off `renderComplete`, not `tableBuilt`:
|
|
@@ -2369,6 +2330,28 @@ function create_tabulator(gobj, $extend, name, template)
|
|
|
2369
2330
|
return tabulator;
|
|
2370
2331
|
}
|
|
2371
2332
|
|
|
2333
|
+
/******************************************************************
|
|
2334
|
+
* The title of a table's column: the schema's header, or the
|
|
2335
|
+
* field's name, translated.
|
|
2336
|
+
******************************************************************/
|
|
2337
|
+
function column_title(field_desc)
|
|
2338
|
+
{
|
|
2339
|
+
return t(/* i18n: data */ field_desc.header || field_desc.name); // the host's schema
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
/******************************************************************
|
|
2343
|
+
* {field: title} of a table's template, in the current language.
|
|
2344
|
+
******************************************************************/
|
|
2345
|
+
function table_column_titles(template)
|
|
2346
|
+
{
|
|
2347
|
+
let titles = {};
|
|
2348
|
+
Object.entries(template || {}).forEach(([key, value]) => {
|
|
2349
|
+
const field_desc = template_get_field_desc(key, value);
|
|
2350
|
+
titles[field_desc.name] = column_title(field_desc);
|
|
2351
|
+
});
|
|
2352
|
+
return titles;
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2372
2355
|
/******************************************************************
|
|
2373
2356
|
* Convert a template's items in tabulator columns
|
|
2374
2357
|
******************************************************************/
|
|
@@ -2388,7 +2371,7 @@ function template2columns(gobj, columns, template, sub_elements)
|
|
|
2388
2371
|
let validator = [];
|
|
2389
2372
|
let column = {
|
|
2390
2373
|
field: field_desc.name,
|
|
2391
|
-
title:
|
|
2374
|
+
title: column_title(field_desc),
|
|
2392
2375
|
titleFormatter: text_title_formatter,
|
|
2393
2376
|
editable: get_editable_state,
|
|
2394
2377
|
editor: false,
|
|
@@ -3793,7 +3776,23 @@ function ac_add_table_row(gobj, event, kw, src)
|
|
|
3793
3776
|
let record = kw.record;
|
|
3794
3777
|
let loading = kw.loading;
|
|
3795
3778
|
|
|
3796
|
-
|
|
3779
|
+
/* Tabulator says `dataChanged` INSIDE addRow(), synchronously: a row
|
|
3780
|
+
* loaded from the record is muted there, whenever it lands -- also
|
|
3781
|
+
* from a `tableBuilt` that comes after the load returned, which is
|
|
3782
|
+
* why no timer can tell the two apart. */
|
|
3783
|
+
let added;
|
|
3784
|
+
if(loading) {
|
|
3785
|
+
gobj.priv.loading_rows++;
|
|
3786
|
+
}
|
|
3787
|
+
try {
|
|
3788
|
+
added = tabulator.addRow(record);
|
|
3789
|
+
} finally {
|
|
3790
|
+
if(loading) {
|
|
3791
|
+
gobj.priv.loading_rows--;
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
|
|
3795
|
+
added
|
|
3797
3796
|
.then(function(row) {
|
|
3798
3797
|
if(loading) {
|
|
3799
3798
|
/*
|
|
@@ -3955,6 +3954,19 @@ function ac_language_changed(gobj, event, kw, src)
|
|
|
3955
3954
|
editor.updateProps({onRenderMenu: json_editor_render_menu(gobj)});
|
|
3956
3955
|
}
|
|
3957
3956
|
}
|
|
3957
|
+
|
|
3958
|
+
/* The titles of the columns of every table, nested ones included:
|
|
3959
|
+
* Tabulator draws them at build, so they stayed in the language the
|
|
3960
|
+
* form was built in. Through the table's LOCALE, never by
|
|
3961
|
+
* updateDefinition(): rebuilding a column re-renders every row, and
|
|
3962
|
+
* a row's formatter builds its nested tables anew -- empty. A table
|
|
3963
|
+
* not built yet is drawn in the current language when it is. */
|
|
3964
|
+
for(let $table of $container.querySelectorAll(".yui-tabulator-table, .yui-tabulator-table-nested")) {
|
|
3965
|
+
let tabulator = $table.tabulator;
|
|
3966
|
+
if(tabulator && tabulator.initialized && $table.template) {
|
|
3967
|
+
yui_tabulator_relocalize(tabulator, t, table_column_titles($table.template));
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3958
3970
|
return 0;
|
|
3959
3971
|
}
|
|
3960
3972
|
|