@yuneta/gobj-ui 7.23.143 → 7.23.145
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 +16 -2
- package/dist/gobj-ui.cjs.js +765 -162
- package/dist/gobj-ui.es.js +766 -163
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +50 -2
- package/src/c_yui_json_pad.css +94 -0
- package/src/c_yui_json_pad.js +567 -114
- package/src/json_view_helpers.js +56 -1
- package/src/json_view_helpers.test.js +43 -0
- package/src/yui_icons.css +12 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -7053,6 +7053,60 @@ function count_branches(value) {
|
|
|
7053
7053
|
for (let v of entries) if (has_branch(v)) n++;
|
|
7054
7054
|
return n;
|
|
7055
7055
|
}
|
|
7056
|
+
/************************************************************
|
|
7057
|
+
* What differs between two documents: one row per id of
|
|
7058
|
+
* their flat form (json2flat), sorted by id in natural order,
|
|
7059
|
+
* so `[2]` comes before `[10]`:
|
|
7060
|
+
*
|
|
7061
|
+
* [{id, kind: "added"|"removed"|"changed", from?, to?}]
|
|
7062
|
+
*
|
|
7063
|
+
* `from` is the first document's value and `to` the second's:
|
|
7064
|
+
* an added row has no `from`, a removed row no `to`.
|
|
7065
|
+
*
|
|
7066
|
+
* Two roots that are not containers of the same kind have no
|
|
7067
|
+
* ids in common to compare by: they are one value each, and
|
|
7068
|
+
* the row that says they differ has the empty id.
|
|
7069
|
+
*
|
|
7070
|
+
* Throws what json2flat throws (a document too deep).
|
|
7071
|
+
************************************************************/
|
|
7072
|
+
function json_diff_rows(doc_a, doc_b) {
|
|
7073
|
+
const kind_of = (v) => {
|
|
7074
|
+
if (Array.isArray(v)) return "array";
|
|
7075
|
+
if (v !== null && typeof v === "object") return "object";
|
|
7076
|
+
return "scalar";
|
|
7077
|
+
};
|
|
7078
|
+
let kind_a = kind_of(doc_a);
|
|
7079
|
+
if (kind_a === "scalar" || kind_a !== kind_of(doc_b)) {
|
|
7080
|
+
if (JSON.stringify(doc_a) === JSON.stringify(doc_b)) return [];
|
|
7081
|
+
return [{
|
|
7082
|
+
id: "",
|
|
7083
|
+
kind: "changed",
|
|
7084
|
+
from: doc_a,
|
|
7085
|
+
to: doc_b
|
|
7086
|
+
}];
|
|
7087
|
+
}
|
|
7088
|
+
let diff = (0, _yuneta_gobj_js.flat_diff)((0, _yuneta_gobj_js.json2flat)(doc_a), (0, _yuneta_gobj_js.json2flat)(doc_b));
|
|
7089
|
+
let rows = [];
|
|
7090
|
+
for (const id of Object.keys(diff.added)) rows.push({
|
|
7091
|
+
id,
|
|
7092
|
+
kind: "added",
|
|
7093
|
+
to: diff.added[id]
|
|
7094
|
+
});
|
|
7095
|
+
for (const id of Object.keys(diff.removed)) rows.push({
|
|
7096
|
+
id,
|
|
7097
|
+
kind: "removed",
|
|
7098
|
+
from: diff.removed[id]
|
|
7099
|
+
});
|
|
7100
|
+
for (const id of Object.keys(diff.changed)) rows.push({
|
|
7101
|
+
id,
|
|
7102
|
+
kind: "changed",
|
|
7103
|
+
from: diff.changed[id].from,
|
|
7104
|
+
to: diff.changed[id].to
|
|
7105
|
+
});
|
|
7106
|
+
const collator = new Intl.Collator("en", { numeric: true });
|
|
7107
|
+
rows.sort((x, y) => collator.compare(x.id, y.id));
|
|
7108
|
+
return rows;
|
|
7109
|
+
}
|
|
7056
7110
|
//#endregion
|
|
7057
7111
|
//#region src/c_yui_form.js
|
|
7058
7112
|
/***********************************************************************
|
|
@@ -14778,7 +14832,8 @@ function register_c_yui_json() {
|
|
|
14778
14832
|
* c_yui_json_pad.js
|
|
14779
14833
|
*
|
|
14780
14834
|
* C_YUI_JSON_PAD -- a pad to paste JSON from OUTSIDE and read it
|
|
14781
|
-
* with the library's own viewer
|
|
14835
|
+
* with the library's own viewer, and a second one to compare it
|
|
14836
|
+
* with.
|
|
14782
14837
|
*
|
|
14783
14838
|
* The viewer (C_YUI_JSON: the lazy tree, the raw text and the
|
|
14784
14839
|
* graph) only ever showed what an app fetched. A JSON that came
|
|
@@ -14787,30 +14842,63 @@ function register_c_yui_json() {
|
|
|
14787
14842
|
* at hand. This is the blank page for it: paste, and read it the
|
|
14788
14843
|
* way every other document of the app is read.
|
|
14789
14844
|
*
|
|
14845
|
+
* Two documents are the other half of the job: the config that
|
|
14846
|
+
* works and the one that does not, a record before and after. The
|
|
14847
|
+
* second pane is there on demand ("second json"), and "compare"
|
|
14848
|
+
* puts their differences in place of the two viewers -- one row
|
|
14849
|
+
* per id of the flat form (json2flat), the form a person reads
|
|
14850
|
+
* when two configurations disagree.
|
|
14851
|
+
*
|
|
14790
14852
|
* DOM (UPPER_SNAKE logical classes):
|
|
14791
14853
|
*
|
|
14792
|
-
* JSON_PAD
|
|
14793
|
-
*
|
|
14794
|
-
*
|
|
14795
|
-
*
|
|
14796
|
-
*
|
|
14797
|
-
*
|
|
14798
|
-
*
|
|
14799
|
-
*
|
|
14800
|
-
*
|
|
14801
|
-
*
|
|
14802
|
-
*
|
|
14803
|
-
*
|
|
14804
|
-
*
|
|
14805
|
-
*
|
|
14806
|
-
*
|
|
14807
|
-
*
|
|
14808
|
-
*
|
|
14809
|
-
*
|
|
14810
|
-
*
|
|
14811
|
-
*
|
|
14812
|
-
*
|
|
14813
|
-
*
|
|
14854
|
+
* JSON_PAD the root
|
|
14855
|
+
* JSON_PAD_TOOLBAR the notice and the two toggles
|
|
14856
|
+
* JSON_PAD_NOTICE "json not kept": the storage refused
|
|
14857
|
+
* JSON_PAD_SECOND show / hide the second pane
|
|
14858
|
+
* JSON_PAD_COMPARE show / hide the differences
|
|
14859
|
+
* JSON_PAD_PANES the panes, side by side (stacked when
|
|
14860
|
+
* the pad is narrow)
|
|
14861
|
+
* JSON_PAD_PANE JSON_PAD_PANE_A / JSON_PAD_PANE_B
|
|
14862
|
+
* JSON_PAD_BAR the text area and its two buttons
|
|
14863
|
+
* JSON_PAD_INPUT where the text goes
|
|
14864
|
+
* JSON_PAD_VIEW read what is in the text area
|
|
14865
|
+
* JSON_PAD_CLEAR empty the pane
|
|
14866
|
+
* JSON_PAD_ERROR "invalid JSON" and the parser's reason
|
|
14867
|
+
* JSON_PAD_BODY the pane's C_YUI_JSON child
|
|
14868
|
+
* JSON_PAD_DIFF the differences: JSON_PAD_DIFF_SUMMARY
|
|
14869
|
+
* and JSON_PAD_DIFF_TABLE, one
|
|
14870
|
+
* JSON_PAD_DIFF_ROW per id
|
|
14871
|
+
*
|
|
14872
|
+
* Every way in is an event, and a pane event names its pane
|
|
14873
|
+
* (`pane`: "a" or "b"):
|
|
14874
|
+
*
|
|
14875
|
+
* EV_PASTE {pane, text} a paste ANYWHERE in a pane replaces
|
|
14876
|
+
* its document and shows it at once --
|
|
14877
|
+
* a pane holds one document, not a
|
|
14878
|
+
* text to edit
|
|
14879
|
+
* EV_VIEW {pane} the text area as it is (typed, or
|
|
14880
|
+
* edited after a paste); also Ctrl+Enter
|
|
14881
|
+
* EV_CLEAR {pane} back to a blank pane
|
|
14882
|
+
* EV_TEXT_CHANGED {pane} the text area was edited: keep it
|
|
14883
|
+
* EV_TOGGLE_SECOND show / hide the second pane
|
|
14884
|
+
* EV_TOGGLE_DIFF show / hide the differences
|
|
14885
|
+
*
|
|
14886
|
+
* FSM: the states are the LAYOUT -- ST_SINGLE (one pane), ST_DUAL
|
|
14887
|
+
* (two), ST_DIFF (two, with their differences in place of the
|
|
14888
|
+
* viewers). Comparing needs two panes, so EV_TOGGLE_DIFF is not
|
|
14889
|
+
* defined in ST_SINGLE and its button is not on screen there.
|
|
14890
|
+
* EV_EXPAND_PATH, which a viewer publishes when a `__collapsed__`
|
|
14891
|
+
* sentinel is opened, is answered with EV_SUBTREE_ERROR to the
|
|
14892
|
+
* viewer that asked: a pasted document has no backend to fetch the
|
|
14893
|
+
* rest from -- the source truncated it, and the pad says so. It is
|
|
14894
|
+
* not defined in ST_DIFF, where no viewer is on screen.
|
|
14895
|
+
*
|
|
14896
|
+
* What is kept: both texts and the layout, in localStorage under
|
|
14897
|
+
* `storage_key` (empty: nothing is kept), written when a text is
|
|
14898
|
+
* pasted, viewed, cleared or edited and when the layout changes,
|
|
14899
|
+
* so the next pad opens as this one was left. localStorage is per
|
|
14900
|
+
* browser and per origin, and has a quota: a text too big for it
|
|
14901
|
+
* is not kept, the toolbar says so, and the log says why.
|
|
14814
14902
|
*
|
|
14815
14903
|
* Hosted by setup_json_pad() (yui_json_pad.js) in a C_YUI_WINDOW;
|
|
14816
14904
|
* any host can mount `$container` itself.
|
|
@@ -14822,19 +14910,52 @@ function register_c_yui_json() {
|
|
|
14822
14910
|
* Constants
|
|
14823
14911
|
***************************************************************/
|
|
14824
14912
|
var GCLASS_NAME$12 = "C_YUI_JSON_PAD";
|
|
14913
|
+
var PANES = ["a", "b"];
|
|
14914
|
+
var MODE_OF_STATE = {
|
|
14915
|
+
ST_SINGLE: "single",
|
|
14916
|
+
ST_DUAL: "dual",
|
|
14917
|
+
ST_DIFF: "diff"
|
|
14918
|
+
};
|
|
14919
|
+
var KIND_TAG = {
|
|
14920
|
+
added: () => [
|
|
14921
|
+
"span",
|
|
14922
|
+
{
|
|
14923
|
+
class: "tag is-success is-light",
|
|
14924
|
+
i18n: "added"
|
|
14925
|
+
},
|
|
14926
|
+
"added"
|
|
14927
|
+
],
|
|
14928
|
+
removed: () => [
|
|
14929
|
+
"span",
|
|
14930
|
+
{
|
|
14931
|
+
class: "tag is-danger is-light",
|
|
14932
|
+
i18n: "removed"
|
|
14933
|
+
},
|
|
14934
|
+
"removed"
|
|
14935
|
+
],
|
|
14936
|
+
changed: () => [
|
|
14937
|
+
"span",
|
|
14938
|
+
{
|
|
14939
|
+
class: "tag is-warning is-light",
|
|
14940
|
+
i18n: "changed"
|
|
14941
|
+
},
|
|
14942
|
+
"changed"
|
|
14943
|
+
]
|
|
14944
|
+
};
|
|
14825
14945
|
/***************************************************************
|
|
14826
14946
|
* Data
|
|
14827
14947
|
***************************************************************/
|
|
14828
14948
|
var attrs_table$12 = [
|
|
14829
14949
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "subscriber", 0, null, "Subscriber of output events"),
|
|
14950
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "storage_key", 0, "yui_json_pad", "localStorage key the two texts and the layout are kept under. Empty: nothing is kept"),
|
|
14830
14951
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$container", 0, null, "HTMLElement root, mounted by the host"),
|
|
14831
14952
|
(0, _yuneta_gobj_js.SDATA_END)()
|
|
14832
14953
|
];
|
|
14833
14954
|
var PRIVATE_DATA$12 = {
|
|
14834
|
-
|
|
14835
|
-
$
|
|
14836
|
-
$
|
|
14837
|
-
|
|
14955
|
+
panes: null,
|
|
14956
|
+
$compare: null,
|
|
14957
|
+
$notice: null,
|
|
14958
|
+
$diff: null
|
|
14838
14959
|
};
|
|
14839
14960
|
var __gclass__$12 = null;
|
|
14840
14961
|
/******************************
|
|
@@ -14849,28 +14970,36 @@ function mt_create$12(gobj) {
|
|
|
14849
14970
|
if (!subscriber) subscriber = (0, _yuneta_gobj_js.gobj_parent)(gobj);
|
|
14850
14971
|
(0, _yuneta_gobj_js.gobj_subscribe_event)(gobj, null, {}, subscriber);
|
|
14851
14972
|
build_ui$11(gobj);
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
14856
|
-
|
|
14973
|
+
for (const id of PANES) {
|
|
14974
|
+
let pane = priv.panes[id];
|
|
14975
|
+
pane.gobj_json = (0, _yuneta_gobj_js.gobj_create_pure_child)(`json_pad_view_${id}`, "C_YUI_JSON", {}, gobj);
|
|
14976
|
+
let $view = pane.gobj_json ? (0, _yuneta_gobj_js.gobj_read_attr)(pane.gobj_json, "$container") : null;
|
|
14977
|
+
if (!$view) {
|
|
14978
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: C_YUI_JSON without $container`);
|
|
14979
|
+
continue;
|
|
14980
|
+
}
|
|
14981
|
+
pane.$body.appendChild($view);
|
|
14857
14982
|
}
|
|
14858
|
-
(0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container").querySelector(".JSON_PAD_BODY").appendChild($view);
|
|
14859
14983
|
}
|
|
14860
14984
|
/***************************************************************
|
|
14861
14985
|
* Framework Method: Start
|
|
14862
14986
|
***************************************************************/
|
|
14863
14987
|
function mt_start$12(gobj) {
|
|
14864
14988
|
let priv = gobj.priv;
|
|
14865
|
-
if (priv.gobj_json) (0, _yuneta_gobj_js.gobj_start)(priv.gobj_json);
|
|
14866
|
-
|
|
14989
|
+
for (const id of PANES) if (priv.panes[id].gobj_json) (0, _yuneta_gobj_js.gobj_start)(priv.panes[id].gobj_json);
|
|
14990
|
+
restore_state(gobj);
|
|
14991
|
+
priv.panes.a.$input.focus();
|
|
14867
14992
|
}
|
|
14868
14993
|
/***************************************************************
|
|
14869
14994
|
* Framework Method: Stop
|
|
14870
14995
|
***************************************************************/
|
|
14871
14996
|
function mt_stop$12(gobj) {
|
|
14872
14997
|
let priv = gobj.priv;
|
|
14873
|
-
|
|
14998
|
+
save_state(gobj);
|
|
14999
|
+
for (const id of PANES) {
|
|
15000
|
+
let gobj_json = priv.panes[id].gobj_json;
|
|
15001
|
+
if (gobj_json && (0, _yuneta_gobj_js.gobj_is_running)(gobj_json)) (0, _yuneta_gobj_js.gobj_stop)(gobj_json);
|
|
15002
|
+
}
|
|
14874
15003
|
}
|
|
14875
15004
|
/***************************************************************
|
|
14876
15005
|
* Framework Method: Destroy
|
|
@@ -14880,37 +15009,106 @@ function mt_destroy$12(gobj) {}
|
|
|
14880
15009
|
* Local Methods
|
|
14881
15010
|
***************************/
|
|
14882
15011
|
/***************************************************************
|
|
14883
|
-
*
|
|
14884
|
-
|
|
15012
|
+
* A button of the pad: an icon, its label, and an event.
|
|
15013
|
+
***************************************************************/
|
|
15014
|
+
function pad_button(gobj, cls, icon, key, event_name, kw) {
|
|
15015
|
+
return [
|
|
15016
|
+
"button",
|
|
15017
|
+
{
|
|
15018
|
+
class: `${cls} button`,
|
|
15019
|
+
type: "button",
|
|
15020
|
+
title: (0, i18next.t)(key),
|
|
15021
|
+
"data-i18n-title": key,
|
|
15022
|
+
"aria-label": (0, i18next.t)(key),
|
|
15023
|
+
"data-i18n-aria-label": key
|
|
15024
|
+
},
|
|
15025
|
+
[yui_toolbar_icon(icon), [
|
|
15026
|
+
"span",
|
|
15027
|
+
{
|
|
15028
|
+
style: "padding-left:5px;",
|
|
15029
|
+
i18n: key
|
|
15030
|
+
},
|
|
15031
|
+
key
|
|
15032
|
+
]],
|
|
15033
|
+
{ click: (evt) => {
|
|
15034
|
+
evt.stopPropagation();
|
|
15035
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, event_name, { ...kw }, gobj);
|
|
15036
|
+
} }
|
|
15037
|
+
];
|
|
15038
|
+
}
|
|
15039
|
+
/***************************************************************
|
|
15040
|
+
* The toolbar, the two panes, and the differences.
|
|
14885
15041
|
***************************************************************/
|
|
14886
15042
|
function build_ui$11(gobj) {
|
|
14887
15043
|
let priv = gobj.priv;
|
|
14888
|
-
|
|
14889
|
-
|
|
14890
|
-
|
|
15044
|
+
priv.$notice = (0, _yuneta_gobj_js.createElement2)([
|
|
15045
|
+
"div",
|
|
15046
|
+
{
|
|
15047
|
+
class: "JSON_PAD_NOTICE is-hidden has-text-danger is-size-7",
|
|
15048
|
+
role: "status"
|
|
15049
|
+
},
|
|
15050
|
+
[[
|
|
15051
|
+
"span",
|
|
14891
15052
|
{
|
|
14892
|
-
|
|
14893
|
-
|
|
14894
|
-
title: (0, i18next.t)(key),
|
|
14895
|
-
"data-i18n-title": key,
|
|
14896
|
-
"aria-label": (0, i18next.t)(key),
|
|
14897
|
-
"data-i18n-aria-label": key
|
|
15053
|
+
style: "font-weight:600;",
|
|
15054
|
+
i18n: "json not kept"
|
|
14898
15055
|
},
|
|
14899
|
-
|
|
14900
|
-
|
|
14901
|
-
|
|
14902
|
-
|
|
14903
|
-
|
|
14904
|
-
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
|
|
14908
|
-
|
|
14909
|
-
|
|
14910
|
-
|
|
14911
|
-
]
|
|
15056
|
+
"json not kept"
|
|
15057
|
+
]]
|
|
15058
|
+
]);
|
|
15059
|
+
priv.$compare = (0, _yuneta_gobj_js.createElement2)(pad_button(gobj, "JSON_PAD_COMPARE is-hidden", "yi-right-left", "compare", "EV_TOGGLE_DIFF", {}));
|
|
15060
|
+
priv.panes = {
|
|
15061
|
+
a: build_pane(gobj, "a", "first json"),
|
|
15062
|
+
b: build_pane(gobj, "b", "second json")
|
|
15063
|
+
};
|
|
15064
|
+
priv.panes.b.$pane.classList.add("is-hidden");
|
|
15065
|
+
priv.$diff = (0, _yuneta_gobj_js.createElement2)([
|
|
15066
|
+
"div",
|
|
15067
|
+
{ class: "JSON_PAD_DIFF is-hidden" },
|
|
15068
|
+
[]
|
|
15069
|
+
]);
|
|
15070
|
+
let $container = (0, _yuneta_gobj_js.createElement2)([
|
|
15071
|
+
"div",
|
|
15072
|
+
{ class: "C_YUI_JSON_PAD JSON_PAD" },
|
|
15073
|
+
[
|
|
15074
|
+
[
|
|
15075
|
+
"div",
|
|
15076
|
+
{ class: "JSON_PAD_TOOLBAR" },
|
|
15077
|
+
[
|
|
15078
|
+
priv.$notice,
|
|
15079
|
+
pad_button(gobj, "JSON_PAD_SECOND", "yi-columns", "second json", "EV_TOGGLE_SECOND", {}),
|
|
15080
|
+
priv.$compare
|
|
15081
|
+
]
|
|
15082
|
+
],
|
|
15083
|
+
[
|
|
15084
|
+
"div",
|
|
15085
|
+
{ class: "JSON_PAD_PANES" },
|
|
15086
|
+
[priv.panes.a.$pane, priv.panes.b.$pane]
|
|
15087
|
+
],
|
|
15088
|
+
priv.$diff
|
|
15089
|
+
]
|
|
15090
|
+
]);
|
|
15091
|
+
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "$container", $container);
|
|
15092
|
+
press_toggle(gobj, ".JSON_PAD_SECOND", false);
|
|
15093
|
+
press_toggle(gobj, ".JSON_PAD_COMPARE", false);
|
|
15094
|
+
}
|
|
15095
|
+
/***************************************************************
|
|
15096
|
+
* One pane: the text area and its buttons, the error line, and
|
|
15097
|
+
* the body its viewer is mounted in. `name_key` names the pane
|
|
15098
|
+
* for a reader (its text area's title and aria-label).
|
|
15099
|
+
***************************************************************/
|
|
15100
|
+
function build_pane(gobj, id, name_key) {
|
|
15101
|
+
let pane = {
|
|
15102
|
+
$pane: null,
|
|
15103
|
+
$input: null,
|
|
15104
|
+
$error: null,
|
|
15105
|
+
$reason: null,
|
|
15106
|
+
$body: null,
|
|
15107
|
+
gobj_json: null,
|
|
15108
|
+
doc: null,
|
|
15109
|
+
has_doc: false
|
|
14912
15110
|
};
|
|
14913
|
-
|
|
15111
|
+
pane.$input = (0, _yuneta_gobj_js.createElement2)([
|
|
14914
15112
|
"textarea",
|
|
14915
15113
|
{
|
|
14916
15114
|
class: "JSON_PAD_INPUT textarea",
|
|
@@ -14918,21 +15116,26 @@ function build_ui$11(gobj) {
|
|
|
14918
15116
|
spellcheck: "false",
|
|
14919
15117
|
placeholder: (0, i18next.t)("paste json here"),
|
|
14920
15118
|
"data-i18n-placeholder": "paste json here",
|
|
14921
|
-
title: (0, i18next.t)(
|
|
14922
|
-
"data-i18n-title":
|
|
14923
|
-
"aria-label": (0, i18next.t)(
|
|
14924
|
-
"data-i18n-aria-label":
|
|
15119
|
+
title: (0, i18next.t)(name_key),
|
|
15120
|
+
"data-i18n-title": name_key,
|
|
15121
|
+
"aria-label": (0, i18next.t)(name_key),
|
|
15122
|
+
"data-i18n-aria-label": name_key,
|
|
14925
15123
|
style: "font-family:monospace; resize:vertical; min-height:4.5em;"
|
|
14926
15124
|
},
|
|
14927
15125
|
"",
|
|
14928
|
-
{
|
|
14929
|
-
|
|
14930
|
-
evt.
|
|
14931
|
-
|
|
15126
|
+
{
|
|
15127
|
+
keydown: (evt) => {
|
|
15128
|
+
if ((evt.ctrlKey || evt.metaKey) && evt.key === "Enter") {
|
|
15129
|
+
evt.preventDefault();
|
|
15130
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_VIEW", { pane: id }, gobj);
|
|
15131
|
+
}
|
|
15132
|
+
},
|
|
15133
|
+
change: () => {
|
|
15134
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TEXT_CHANGED", { pane: id }, gobj);
|
|
14932
15135
|
}
|
|
14933
|
-
}
|
|
15136
|
+
}
|
|
14934
15137
|
]);
|
|
14935
|
-
|
|
15138
|
+
pane.$reason = (0, _yuneta_gobj_js.createElement2)([
|
|
14936
15139
|
"span",
|
|
14937
15140
|
{
|
|
14938
15141
|
class: "JSON_PAD_ERROR_REASON",
|
|
@@ -14940,7 +15143,7 @@ function build_ui$11(gobj) {
|
|
|
14940
15143
|
},
|
|
14941
15144
|
""
|
|
14942
15145
|
]);
|
|
14943
|
-
|
|
15146
|
+
pane.$error = (0, _yuneta_gobj_js.createElement2)([
|
|
14944
15147
|
"div",
|
|
14945
15148
|
{
|
|
14946
15149
|
class: "JSON_PAD_ERROR is-hidden has-text-danger is-size-7",
|
|
@@ -14954,14 +15157,19 @@ function build_ui$11(gobj) {
|
|
|
14954
15157
|
i18n: "invalid json"
|
|
14955
15158
|
},
|
|
14956
15159
|
"invalid json"
|
|
14957
|
-
],
|
|
15160
|
+
], pane.$reason]
|
|
14958
15161
|
]);
|
|
14959
|
-
|
|
15162
|
+
pane.$body = (0, _yuneta_gobj_js.createElement2)([
|
|
14960
15163
|
"div",
|
|
14961
15164
|
{
|
|
14962
|
-
class: "
|
|
14963
|
-
style: "height:
|
|
15165
|
+
class: "JSON_PAD_BODY",
|
|
15166
|
+
style: "flex:1 1 auto; min-height:0; display:flex; flex-direction:column;"
|
|
14964
15167
|
},
|
|
15168
|
+
[]
|
|
15169
|
+
]);
|
|
15170
|
+
pane.$pane = (0, _yuneta_gobj_js.createElement2)([
|
|
15171
|
+
"div",
|
|
15172
|
+
{ class: `JSON_PAD_PANE JSON_PAD_PANE_${id.toUpperCase()}` },
|
|
14965
15173
|
[
|
|
14966
15174
|
[
|
|
14967
15175
|
"div",
|
|
@@ -14972,40 +15180,59 @@ function build_ui$11(gobj) {
|
|
|
14972
15180
|
[[
|
|
14973
15181
|
"div",
|
|
14974
15182
|
{ style: "flex:1 1 auto; min-width:0;" },
|
|
14975
|
-
[
|
|
15183
|
+
[pane.$input]
|
|
14976
15184
|
], [
|
|
14977
15185
|
"div",
|
|
14978
15186
|
{ style: "flex:0 0 auto; display:flex; flex-direction:column; gap:.5rem;" },
|
|
14979
|
-
[
|
|
15187
|
+
[pad_button(gobj, "JSON_PAD_VIEW", "yi-eye", "view", "EV_VIEW", { pane: id }), pad_button(gobj, "JSON_PAD_CLEAR", "yi-broom", "clear", "EV_CLEAR", { pane: id })]
|
|
14980
15188
|
]]
|
|
14981
15189
|
],
|
|
14982
|
-
|
|
14983
|
-
|
|
14984
|
-
"div",
|
|
14985
|
-
{
|
|
14986
|
-
class: "JSON_PAD_BODY",
|
|
14987
|
-
style: "flex:1 1 auto; min-height:0; display:flex; flex-direction:column;"
|
|
14988
|
-
},
|
|
14989
|
-
[]
|
|
14990
|
-
]
|
|
15190
|
+
pane.$error,
|
|
15191
|
+
pane.$body
|
|
14991
15192
|
],
|
|
14992
15193
|
{ paste: (evt) => {
|
|
14993
15194
|
let text = evt.clipboardData ? evt.clipboardData.getData("text") : "";
|
|
14994
15195
|
if (!text) return;
|
|
14995
15196
|
evt.preventDefault();
|
|
14996
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_PASTE", {
|
|
15197
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_PASTE", {
|
|
15198
|
+
pane: id,
|
|
15199
|
+
text
|
|
15200
|
+
}, gobj);
|
|
14997
15201
|
} }
|
|
14998
15202
|
]);
|
|
14999
|
-
|
|
15203
|
+
return pane;
|
|
15000
15204
|
}
|
|
15001
15205
|
/***************************************************************
|
|
15002
|
-
*
|
|
15206
|
+
* The pane a pane event names.
|
|
15003
15207
|
***************************************************************/
|
|
15004
|
-
function
|
|
15208
|
+
function pane_of(gobj, kw) {
|
|
15005
15209
|
let priv = gobj.priv;
|
|
15210
|
+
let id = kw ? kw.pane : void 0;
|
|
15211
|
+
if (!PANES.includes(id)) {
|
|
15212
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no pane '${id}'`);
|
|
15213
|
+
return null;
|
|
15214
|
+
}
|
|
15215
|
+
return priv.panes[id];
|
|
15216
|
+
}
|
|
15217
|
+
/***************************************************************
|
|
15218
|
+
* A toggle of the toolbar, pressed or not -- for the eye and
|
|
15219
|
+
* for a reader.
|
|
15220
|
+
***************************************************************/
|
|
15221
|
+
function press_toggle(gobj, selector, on) {
|
|
15222
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
15223
|
+
set_pressed_state($container, selector, on);
|
|
15224
|
+
$container.querySelectorAll(selector).forEach(($el) => {
|
|
15225
|
+
$el.setAttribute("aria-pressed", on ? "true" : "false");
|
|
15226
|
+
});
|
|
15227
|
+
}
|
|
15228
|
+
/***************************************************************
|
|
15229
|
+
* Read `text` as JSON and show it in `pane`, or say why it is
|
|
15230
|
+
* not. A text that is not JSON leaves the last document up.
|
|
15231
|
+
***************************************************************/
|
|
15232
|
+
function show_text(gobj, pane, text) {
|
|
15006
15233
|
let src = String(text || "").trim();
|
|
15007
15234
|
if (!src) {
|
|
15008
|
-
|
|
15235
|
+
clear_pane(gobj, pane, false);
|
|
15009
15236
|
return 0;
|
|
15010
15237
|
}
|
|
15011
15238
|
let doc;
|
|
@@ -15013,63 +15240,328 @@ function show_text(gobj, text) {
|
|
|
15013
15240
|
doc = JSON.parse(src);
|
|
15014
15241
|
} catch (e) {
|
|
15015
15242
|
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: the pasted text is not JSON: ${e.message}`);
|
|
15016
|
-
|
|
15017
|
-
|
|
15243
|
+
pane.$reason.textContent = e.message;
|
|
15244
|
+
pane.$error.classList.remove("is-hidden");
|
|
15245
|
+
return -1;
|
|
15246
|
+
}
|
|
15247
|
+
pane.$error.classList.add("is-hidden");
|
|
15248
|
+
pane.$reason.textContent = "";
|
|
15249
|
+
pane.doc = doc;
|
|
15250
|
+
pane.has_doc = true;
|
|
15251
|
+
(0, _yuneta_gobj_js.gobj_send_event)(pane.gobj_json, "EV_SET_JSON", { json: doc }, gobj);
|
|
15252
|
+
return 0;
|
|
15253
|
+
}
|
|
15254
|
+
/***************************************************************
|
|
15255
|
+
* A blank pane again; `with_text` empties the text area too.
|
|
15256
|
+
***************************************************************/
|
|
15257
|
+
function clear_pane(gobj, pane, with_text) {
|
|
15258
|
+
if (with_text) pane.$input.value = "";
|
|
15259
|
+
pane.$error.classList.add("is-hidden");
|
|
15260
|
+
pane.$reason.textContent = "";
|
|
15261
|
+
pane.doc = null;
|
|
15262
|
+
pane.has_doc = false;
|
|
15263
|
+
(0, _yuneta_gobj_js.gobj_send_event)(pane.gobj_json, "EV_SET_JSON", { json: null }, gobj);
|
|
15264
|
+
}
|
|
15265
|
+
/***************************************************************
|
|
15266
|
+
* A pane changed its document: the differences follow it, and
|
|
15267
|
+
* the texts are kept.
|
|
15268
|
+
***************************************************************/
|
|
15269
|
+
function document_changed(gobj) {
|
|
15270
|
+
if ((0, _yuneta_gobj_js.gobj_current_state)(gobj) === "ST_DIFF") render_diff(gobj);
|
|
15271
|
+
save_state(gobj);
|
|
15272
|
+
}
|
|
15273
|
+
/***************************************************************
|
|
15274
|
+
* Enter one of the three layouts. The state IS the layout;
|
|
15275
|
+
* this is what the screen shows for it.
|
|
15276
|
+
***************************************************************/
|
|
15277
|
+
function enter_layout(gobj, state) {
|
|
15278
|
+
let priv = gobj.priv;
|
|
15279
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
15280
|
+
let second = state !== "ST_SINGLE";
|
|
15281
|
+
let diff = state === "ST_DIFF";
|
|
15282
|
+
(0, _yuneta_gobj_js.gobj_change_state)(gobj, state);
|
|
15283
|
+
priv.panes.b.$pane.classList.toggle("is-hidden", !second);
|
|
15284
|
+
priv.$compare.classList.toggle("is-hidden", !second);
|
|
15285
|
+
press_toggle(gobj, ".JSON_PAD_SECOND", second);
|
|
15286
|
+
press_toggle(gobj, ".JSON_PAD_COMPARE", diff);
|
|
15287
|
+
$container.classList.toggle("is-comparing", diff);
|
|
15288
|
+
for (const id of PANES) priv.panes[id].$body.classList.toggle("is-hidden", diff);
|
|
15289
|
+
priv.$diff.classList.toggle("is-hidden", !diff);
|
|
15290
|
+
if (diff) render_diff(gobj);
|
|
15291
|
+
else for (const id of PANES) {
|
|
15292
|
+
if (id === "b" && !second) continue;
|
|
15293
|
+
(0, _yuneta_gobj_js.gobj_send_event)(priv.panes[id].gobj_json, "EV_REFRESH", {}, gobj);
|
|
15294
|
+
}
|
|
15295
|
+
save_state(gobj);
|
|
15296
|
+
}
|
|
15297
|
+
/***************************************************************
|
|
15298
|
+
* The differences of the two documents, in place of the two
|
|
15299
|
+
* viewers. Only a pane that shows a document takes part: a
|
|
15300
|
+
* text that is not JSON leaves its last document, as on screen.
|
|
15301
|
+
***************************************************************/
|
|
15302
|
+
function render_diff(gobj) {
|
|
15303
|
+
let priv = gobj.priv;
|
|
15304
|
+
let a = priv.panes.a;
|
|
15305
|
+
let b = priv.panes.b;
|
|
15306
|
+
priv.$diff.replaceChildren();
|
|
15307
|
+
if (!a.has_doc || !b.has_doc) {
|
|
15308
|
+
priv.$diff.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
15309
|
+
"p",
|
|
15310
|
+
{
|
|
15311
|
+
class: "JSON_PAD_DIFF_MESSAGE",
|
|
15312
|
+
i18n: "compare needs two json"
|
|
15313
|
+
},
|
|
15314
|
+
"compare needs two json"
|
|
15315
|
+
]));
|
|
15316
|
+
return 0;
|
|
15317
|
+
}
|
|
15318
|
+
let rows;
|
|
15319
|
+
try {
|
|
15320
|
+
rows = json_diff_rows(a.doc, b.doc);
|
|
15321
|
+
} catch (e) {
|
|
15322
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot compare: ${e.message}`);
|
|
15323
|
+
priv.$diff.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
15324
|
+
"p",
|
|
15325
|
+
{ class: "JSON_PAD_DIFF_MESSAGE has-text-danger" },
|
|
15326
|
+
[[
|
|
15327
|
+
"span",
|
|
15328
|
+
{
|
|
15329
|
+
style: "font-weight:600;",
|
|
15330
|
+
i18n: "cannot compare"
|
|
15331
|
+
},
|
|
15332
|
+
"cannot compare"
|
|
15333
|
+
], [
|
|
15334
|
+
"span",
|
|
15335
|
+
{
|
|
15336
|
+
class: "JSON_PAD_DIFF_REASON",
|
|
15337
|
+
style: "margin-left:.5em; font-family:monospace;"
|
|
15338
|
+
},
|
|
15339
|
+
e.message
|
|
15340
|
+
]]
|
|
15341
|
+
]));
|
|
15018
15342
|
return -1;
|
|
15019
15343
|
}
|
|
15020
|
-
|
|
15021
|
-
|
|
15022
|
-
|
|
15023
|
-
|
|
15344
|
+
if (rows.length === 0) {
|
|
15345
|
+
priv.$diff.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
15346
|
+
"p",
|
|
15347
|
+
{
|
|
15348
|
+
class: "JSON_PAD_DIFF_MESSAGE has-text-success",
|
|
15349
|
+
i18n: "no differences"
|
|
15350
|
+
},
|
|
15351
|
+
"no differences"
|
|
15352
|
+
]));
|
|
15353
|
+
return 0;
|
|
15354
|
+
}
|
|
15355
|
+
let count = {
|
|
15356
|
+
added: 0,
|
|
15357
|
+
removed: 0,
|
|
15358
|
+
changed: 0
|
|
15359
|
+
};
|
|
15360
|
+
for (const row of rows) count[row.kind]++;
|
|
15361
|
+
let value_cell = (cls, row, side) => {
|
|
15362
|
+
let has = Object.prototype.hasOwnProperty.call(row, side);
|
|
15363
|
+
return [
|
|
15364
|
+
"td",
|
|
15365
|
+
{ class: cls },
|
|
15366
|
+
has ? JSON.stringify(row[side]) : ""
|
|
15367
|
+
];
|
|
15368
|
+
};
|
|
15369
|
+
priv.$diff.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
15370
|
+
"div",
|
|
15371
|
+
{ class: "JSON_PAD_DIFF_SUMMARY" },
|
|
15372
|
+
[
|
|
15373
|
+
"removed",
|
|
15374
|
+
"added",
|
|
15375
|
+
"changed"
|
|
15376
|
+
].map((kind) => {
|
|
15377
|
+
return [
|
|
15378
|
+
"span",
|
|
15379
|
+
{ class: "JSON_PAD_DIFF_COUNT" },
|
|
15380
|
+
[KIND_TAG[kind](), [
|
|
15381
|
+
"strong",
|
|
15382
|
+
{},
|
|
15383
|
+
String(count[kind])
|
|
15384
|
+
]]
|
|
15385
|
+
];
|
|
15386
|
+
})
|
|
15387
|
+
]));
|
|
15388
|
+
priv.$diff.appendChild((0, _yuneta_gobj_js.createElement2)([
|
|
15389
|
+
"table",
|
|
15390
|
+
{ class: "JSON_PAD_DIFF_TABLE table is-fullwidth is-narrow is-hoverable" },
|
|
15391
|
+
[[
|
|
15392
|
+
"thead",
|
|
15393
|
+
{},
|
|
15394
|
+
[[
|
|
15395
|
+
"tr",
|
|
15396
|
+
{},
|
|
15397
|
+
[
|
|
15398
|
+
[
|
|
15399
|
+
"th",
|
|
15400
|
+
{},
|
|
15401
|
+
""
|
|
15402
|
+
],
|
|
15403
|
+
[
|
|
15404
|
+
"th",
|
|
15405
|
+
{ i18n: "path" },
|
|
15406
|
+
"path"
|
|
15407
|
+
],
|
|
15408
|
+
[
|
|
15409
|
+
"th",
|
|
15410
|
+
{ i18n: "first json" },
|
|
15411
|
+
"first json"
|
|
15412
|
+
],
|
|
15413
|
+
[
|
|
15414
|
+
"th",
|
|
15415
|
+
{ i18n: "second json" },
|
|
15416
|
+
"second json"
|
|
15417
|
+
]
|
|
15418
|
+
]
|
|
15419
|
+
]]
|
|
15420
|
+
], [
|
|
15421
|
+
"tbody",
|
|
15422
|
+
{},
|
|
15423
|
+
rows.map((row) => {
|
|
15424
|
+
return [
|
|
15425
|
+
"tr",
|
|
15426
|
+
{ class: `JSON_PAD_DIFF_ROW JSON_PAD_DIFF_${row.kind.toUpperCase()}` },
|
|
15427
|
+
[
|
|
15428
|
+
[
|
|
15429
|
+
"td",
|
|
15430
|
+
{},
|
|
15431
|
+
[KIND_TAG[row.kind]()]
|
|
15432
|
+
],
|
|
15433
|
+
[
|
|
15434
|
+
"td",
|
|
15435
|
+
{ class: "JSON_PAD_DIFF_PATH" },
|
|
15436
|
+
row.id
|
|
15437
|
+
],
|
|
15438
|
+
value_cell("JSON_PAD_DIFF_FROM", row, "from"),
|
|
15439
|
+
value_cell("JSON_PAD_DIFF_TO", row, "to")
|
|
15440
|
+
]
|
|
15441
|
+
];
|
|
15442
|
+
})
|
|
15443
|
+
]]
|
|
15444
|
+
]));
|
|
15024
15445
|
return 0;
|
|
15025
15446
|
}
|
|
15026
15447
|
/***************************************************************
|
|
15027
|
-
*
|
|
15448
|
+
* Keep both texts and the layout.
|
|
15449
|
+
***************************************************************/
|
|
15450
|
+
function save_state(gobj) {
|
|
15451
|
+
let priv = gobj.priv;
|
|
15452
|
+
let key = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "storage_key");
|
|
15453
|
+
if (!key) return 0;
|
|
15454
|
+
let ret = (0, _yuneta_gobj_js.kw_set_local_storage_value)(key, {
|
|
15455
|
+
a: priv.panes.a.$input.value,
|
|
15456
|
+
b: priv.panes.b.$input.value,
|
|
15457
|
+
mode: MODE_OF_STATE[(0, _yuneta_gobj_js.gobj_current_state)(gobj)] || "single"
|
|
15458
|
+
});
|
|
15459
|
+
priv.$notice.classList.toggle("is-hidden", ret === 0);
|
|
15460
|
+
return ret;
|
|
15461
|
+
}
|
|
15462
|
+
/***************************************************************
|
|
15463
|
+
* The pad as the last one was left: its texts, shown, and its
|
|
15464
|
+
* layout -- through the same events a reader would send.
|
|
15028
15465
|
***************************************************************/
|
|
15029
|
-
function
|
|
15466
|
+
function restore_state(gobj) {
|
|
15030
15467
|
let priv = gobj.priv;
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15468
|
+
let key = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "storage_key");
|
|
15469
|
+
if (!key) return 0;
|
|
15470
|
+
let kept = (0, _yuneta_gobj_js.kw_get_local_storage_value)(key, null, false);
|
|
15471
|
+
if (kept === null || kept === void 0) return 0;
|
|
15472
|
+
if (typeof kept !== "object" || Array.isArray(kept)) {
|
|
15473
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: '${key}' in localStorage is not what the pad keeps`);
|
|
15474
|
+
return -1;
|
|
15475
|
+
}
|
|
15476
|
+
for (const id of PANES) if (typeof kept[id] === "string") priv.panes[id].$input.value = kept[id];
|
|
15477
|
+
for (const id of PANES) if (priv.panes[id].$input.value.trim()) (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_VIEW", { pane: id }, gobj);
|
|
15478
|
+
if (kept.mode === "dual" || kept.mode === "diff") (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_SECOND", {}, gobj);
|
|
15479
|
+
if (kept.mode === "diff") (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_DIFF", {}, gobj);
|
|
15480
|
+
return 0;
|
|
15036
15481
|
}
|
|
15037
15482
|
/***************************
|
|
15038
15483
|
* Actions
|
|
15039
15484
|
***************************/
|
|
15040
15485
|
/***************************************************************
|
|
15041
|
-
* A paste: it becomes the text area and
|
|
15486
|
+
* A paste: it becomes the pane's text area and its document
|
|
15487
|
+
* at once.
|
|
15042
15488
|
***************************************************************/
|
|
15043
15489
|
function ac_paste(gobj, event, kw, src) {
|
|
15044
|
-
let
|
|
15045
|
-
|
|
15046
|
-
|
|
15047
|
-
|
|
15490
|
+
let pane = pane_of(gobj, kw);
|
|
15491
|
+
if (!pane) return -1;
|
|
15492
|
+
let text = typeof kw.text === "string" ? kw.text : "";
|
|
15493
|
+
pane.$input.value = text;
|
|
15494
|
+
let ret = show_text(gobj, pane, text);
|
|
15495
|
+
document_changed(gobj);
|
|
15496
|
+
return ret;
|
|
15048
15497
|
}
|
|
15049
15498
|
/***************************************************************
|
|
15050
|
-
* The text area as it is now.
|
|
15499
|
+
* The pane's text area as it is now.
|
|
15051
15500
|
***************************************************************/
|
|
15052
15501
|
function ac_view(gobj, event, kw, src) {
|
|
15053
|
-
let
|
|
15054
|
-
|
|
15502
|
+
let pane = pane_of(gobj, kw);
|
|
15503
|
+
if (!pane) return -1;
|
|
15504
|
+
let ret = show_text(gobj, pane, pane.$input.value);
|
|
15505
|
+
document_changed(gobj);
|
|
15506
|
+
return ret;
|
|
15055
15507
|
}
|
|
15056
15508
|
/***************************************************************
|
|
15057
|
-
*
|
|
15509
|
+
* A blank pane again.
|
|
15058
15510
|
***************************************************************/
|
|
15059
15511
|
function ac_clear(gobj, event, kw, src) {
|
|
15512
|
+
let pane = pane_of(gobj, kw);
|
|
15513
|
+
if (!pane) return -1;
|
|
15514
|
+
clear_pane(gobj, pane, true);
|
|
15515
|
+
pane.$input.focus();
|
|
15516
|
+
document_changed(gobj);
|
|
15517
|
+
return 0;
|
|
15518
|
+
}
|
|
15519
|
+
/***************************************************************
|
|
15520
|
+
* A text area was edited and left: keep what it holds. What
|
|
15521
|
+
* is SHOWN changes only with a view, as before.
|
|
15522
|
+
***************************************************************/
|
|
15523
|
+
function ac_text_changed(gobj, event, kw, src) {
|
|
15524
|
+
if (!pane_of(gobj, kw)) return -1;
|
|
15525
|
+
save_state(gobj);
|
|
15526
|
+
return 0;
|
|
15527
|
+
}
|
|
15528
|
+
/***************************************************************
|
|
15529
|
+
* The second pane, beside the first.
|
|
15530
|
+
***************************************************************/
|
|
15531
|
+
function ac_show_second(gobj, event, kw, src) {
|
|
15060
15532
|
let priv = gobj.priv;
|
|
15061
|
-
|
|
15062
|
-
priv.$input.focus();
|
|
15533
|
+
enter_layout(gobj, "ST_DUAL");
|
|
15534
|
+
priv.panes.b.$input.focus();
|
|
15063
15535
|
return 0;
|
|
15064
15536
|
}
|
|
15065
15537
|
/***************************************************************
|
|
15066
|
-
*
|
|
15538
|
+
* One pane again. Its text is kept: hiding is not clearing.
|
|
15539
|
+
***************************************************************/
|
|
15540
|
+
function ac_hide_second(gobj, event, kw, src) {
|
|
15541
|
+
enter_layout(gobj, "ST_SINGLE");
|
|
15542
|
+
return 0;
|
|
15543
|
+
}
|
|
15544
|
+
/***************************************************************
|
|
15545
|
+
* The differences, in place of the viewers.
|
|
15546
|
+
***************************************************************/
|
|
15547
|
+
function ac_show_diff(gobj, event, kw, src) {
|
|
15548
|
+
enter_layout(gobj, "ST_DIFF");
|
|
15549
|
+
return 0;
|
|
15550
|
+
}
|
|
15551
|
+
/***************************************************************
|
|
15552
|
+
* The viewers again.
|
|
15553
|
+
***************************************************************/
|
|
15554
|
+
function ac_hide_diff(gobj, event, kw, src) {
|
|
15555
|
+
enter_layout(gobj, "ST_DUAL");
|
|
15556
|
+
return 0;
|
|
15557
|
+
}
|
|
15558
|
+
/***************************************************************
|
|
15559
|
+
* A viewer asks for a `__collapsed__` subtree. A pasted
|
|
15067
15560
|
* document has no backend to ask for it: the SOURCE truncated
|
|
15068
|
-
* it, and that is the answer.
|
|
15561
|
+
* it, and that is the answer, to the viewer that asked.
|
|
15069
15562
|
***************************************************************/
|
|
15070
15563
|
function ac_expand_path(gobj, event, kw, src) {
|
|
15071
|
-
|
|
15072
|
-
(0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_json, "EV_SUBTREE_ERROR", {
|
|
15564
|
+
(0, _yuneta_gobj_js.gobj_send_event)(src, "EV_SUBTREE_ERROR", {
|
|
15073
15565
|
path: kw && kw.path || "",
|
|
15074
15566
|
error: (0, i18next.t)("collapsed in the source")
|
|
15075
15567
|
}, gobj);
|
|
@@ -15096,45 +15588,113 @@ function create_gclass$12(gclass_name) {
|
|
|
15096
15588
|
["EV_PASTE", 0],
|
|
15097
15589
|
["EV_VIEW", 0],
|
|
15098
15590
|
["EV_CLEAR", 0],
|
|
15591
|
+
["EV_TEXT_CHANGED", 0],
|
|
15592
|
+
["EV_TOGGLE_SECOND", 0],
|
|
15593
|
+
["EV_TOGGLE_DIFF", 0],
|
|
15099
15594
|
["EV_EXPAND_PATH", 0]
|
|
15100
|
-
], [
|
|
15101
|
-
[
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
|
|
15137
|
-
|
|
15595
|
+
], [
|
|
15596
|
+
["ST_SINGLE", [
|
|
15597
|
+
[
|
|
15598
|
+
"EV_PASTE",
|
|
15599
|
+
ac_paste,
|
|
15600
|
+
null
|
|
15601
|
+
],
|
|
15602
|
+
[
|
|
15603
|
+
"EV_VIEW",
|
|
15604
|
+
ac_view,
|
|
15605
|
+
null
|
|
15606
|
+
],
|
|
15607
|
+
[
|
|
15608
|
+
"EV_CLEAR",
|
|
15609
|
+
ac_clear,
|
|
15610
|
+
null
|
|
15611
|
+
],
|
|
15612
|
+
[
|
|
15613
|
+
"EV_TEXT_CHANGED",
|
|
15614
|
+
ac_text_changed,
|
|
15615
|
+
null
|
|
15616
|
+
],
|
|
15617
|
+
[
|
|
15618
|
+
"EV_TOGGLE_SECOND",
|
|
15619
|
+
ac_show_second,
|
|
15620
|
+
null
|
|
15621
|
+
],
|
|
15622
|
+
[
|
|
15623
|
+
"EV_EXPAND_PATH",
|
|
15624
|
+
ac_expand_path,
|
|
15625
|
+
null
|
|
15626
|
+
]
|
|
15627
|
+
]],
|
|
15628
|
+
["ST_DUAL", [
|
|
15629
|
+
[
|
|
15630
|
+
"EV_PASTE",
|
|
15631
|
+
ac_paste,
|
|
15632
|
+
null
|
|
15633
|
+
],
|
|
15634
|
+
[
|
|
15635
|
+
"EV_VIEW",
|
|
15636
|
+
ac_view,
|
|
15637
|
+
null
|
|
15638
|
+
],
|
|
15639
|
+
[
|
|
15640
|
+
"EV_CLEAR",
|
|
15641
|
+
ac_clear,
|
|
15642
|
+
null
|
|
15643
|
+
],
|
|
15644
|
+
[
|
|
15645
|
+
"EV_TEXT_CHANGED",
|
|
15646
|
+
ac_text_changed,
|
|
15647
|
+
null
|
|
15648
|
+
],
|
|
15649
|
+
[
|
|
15650
|
+
"EV_TOGGLE_SECOND",
|
|
15651
|
+
ac_hide_second,
|
|
15652
|
+
null
|
|
15653
|
+
],
|
|
15654
|
+
[
|
|
15655
|
+
"EV_TOGGLE_DIFF",
|
|
15656
|
+
ac_show_diff,
|
|
15657
|
+
null
|
|
15658
|
+
],
|
|
15659
|
+
[
|
|
15660
|
+
"EV_EXPAND_PATH",
|
|
15661
|
+
ac_expand_path,
|
|
15662
|
+
null
|
|
15663
|
+
]
|
|
15664
|
+
]],
|
|
15665
|
+
["ST_DIFF", [
|
|
15666
|
+
[
|
|
15667
|
+
"EV_PASTE",
|
|
15668
|
+
ac_paste,
|
|
15669
|
+
null
|
|
15670
|
+
],
|
|
15671
|
+
[
|
|
15672
|
+
"EV_VIEW",
|
|
15673
|
+
ac_view,
|
|
15674
|
+
null
|
|
15675
|
+
],
|
|
15676
|
+
[
|
|
15677
|
+
"EV_CLEAR",
|
|
15678
|
+
ac_clear,
|
|
15679
|
+
null
|
|
15680
|
+
],
|
|
15681
|
+
[
|
|
15682
|
+
"EV_TEXT_CHANGED",
|
|
15683
|
+
ac_text_changed,
|
|
15684
|
+
null
|
|
15685
|
+
],
|
|
15686
|
+
[
|
|
15687
|
+
"EV_TOGGLE_SECOND",
|
|
15688
|
+
ac_hide_second,
|
|
15689
|
+
null
|
|
15690
|
+
],
|
|
15691
|
+
[
|
|
15692
|
+
"EV_TOGGLE_DIFF",
|
|
15693
|
+
ac_hide_diff,
|
|
15694
|
+
null
|
|
15695
|
+
]
|
|
15696
|
+
]]
|
|
15697
|
+
], gmt$12, 0, attrs_table$12, PRIVATE_DATA$12, 0, 0, 0, 0);
|
|
15138
15698
|
if (!__gclass__$12) return -1;
|
|
15139
15699
|
return 0;
|
|
15140
15700
|
}
|
|
@@ -60175,6 +60735,23 @@ function auto_layout(gobj) {
|
|
|
60175
60735
|
return true;
|
|
60176
60736
|
}
|
|
60177
60737
|
/************************************************************
|
|
60738
|
+
* Paint the minimap again from where the nodes are NOW.
|
|
60739
|
+
*
|
|
60740
|
+
* It repaints off the graph's draw events, and a layout emits none:
|
|
60741
|
+
* G6 moves the nodes with a SILENT draw. So after a layout change
|
|
60742
|
+
* the minimap went on showing the arrangement before it.
|
|
60743
|
+
************************************************************/
|
|
60744
|
+
function repaint_minimap(gobj) {
|
|
60745
|
+
let plugin = graph_get_plugin(gobj, "minimap");
|
|
60746
|
+
if (!plugin || plugin.destroyed) return;
|
|
60747
|
+
try {
|
|
60748
|
+
plugin.renderMinimap();
|
|
60749
|
+
plugin.renderMask();
|
|
60750
|
+
} catch (e) {
|
|
60751
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: repaint_minimap failed: ${e}`);
|
|
60752
|
+
}
|
|
60753
|
+
}
|
|
60754
|
+
/************************************************************
|
|
60178
60755
|
* Show or hide the minimap, deciding by the SIZE of the graph.
|
|
60179
60756
|
*
|
|
60180
60757
|
* A minimap of a graph that already fits on screen is decoration; one
|
|
@@ -61946,7 +62523,10 @@ async function reconcile_fold_apply(gobj, opts, visible) {
|
|
|
61946
62523
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: refresh_minimap failed: ${e}`);
|
|
61947
62524
|
}
|
|
61948
62525
|
await graph_draw(gobj);
|
|
61949
|
-
if (changed || opts.relayout)
|
|
62526
|
+
if (changed || opts.relayout) {
|
|
62527
|
+
await graph_layout(gobj);
|
|
62528
|
+
repaint_minimap(gobj);
|
|
62529
|
+
}
|
|
61950
62530
|
if (!(opts.restore && await restore_camera(gobj))) {
|
|
61951
62531
|
if (opts.fit) await graph_fit_readable(gobj);
|
|
61952
62532
|
else if (opts.keep && opts.keep_vp) await yui_graph_place_at(graph, opts.keep, opts.keep_vp);
|
|
@@ -62712,15 +63292,38 @@ function ac_fullscreen(gobj, event, kw, src) {
|
|
|
62712
63292
|
}
|
|
62713
63293
|
/************************************************************
|
|
62714
63294
|
* Layout change
|
|
63295
|
+
*
|
|
63296
|
+
* A new layout moves EVERY node, so the camera cannot stay on the
|
|
63297
|
+
* coordinates it had: it would look at empty grid where the old
|
|
63298
|
+
* arrangement was. It goes through the reconcile instead, which
|
|
63299
|
+
* holds the node the reader was looking at on the same pixel (the
|
|
63300
|
+
* zoom is kept) and fits only if nothing is left in view.
|
|
62715
63301
|
************************************************************/
|
|
62716
63302
|
function ac_set_layout$1(gobj, event, kw, src) {
|
|
62717
|
-
gobj.priv;
|
|
63303
|
+
let priv = gobj.priv;
|
|
63304
|
+
let graph = priv.graph;
|
|
62718
63305
|
let layout = select_layout(gobj, kw.layout);
|
|
63306
|
+
priv._layout_asked = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "layout");
|
|
62719
63307
|
apply_layout_direction(gobj);
|
|
62720
|
-
|
|
63308
|
+
let done = () => {
|
|
62721
63309
|
configure_behaviour(gobj);
|
|
62722
63310
|
update_toolbar(gobj);
|
|
62723
|
-
}
|
|
63311
|
+
};
|
|
63312
|
+
if (!priv._fold_model || !graph || !graph.rendered) {
|
|
63313
|
+
graph_set_layout(gobj, layout).then(() => {
|
|
63314
|
+
repaint_minimap(gobj);
|
|
63315
|
+
done();
|
|
63316
|
+
});
|
|
63317
|
+
return 0;
|
|
63318
|
+
}
|
|
63319
|
+
let keep = camera_anchor_node(gobj);
|
|
63320
|
+
let vp = keep ? yui_graph_viewport_of(graph, keep) : null;
|
|
63321
|
+
graph.setLayout(layout);
|
|
63322
|
+
reconcile_fold(gobj, {
|
|
63323
|
+
relayout: true,
|
|
63324
|
+
keep,
|
|
63325
|
+
keep_vp: vp
|
|
63326
|
+
}).then(done);
|
|
62724
63327
|
return 0;
|
|
62725
63328
|
}
|
|
62726
63329
|
/************************************************************
|