@yuneta/gobj-ui 7.23.139 → 7.23.140
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/dist/gobj-ui.cjs.js +80 -6
- package/dist/gobj-ui.es.js +80 -6
- package/package.json +1 -1
- package/src/c_yui_node.js +6 -0
- package/src/c_yui_shell.js +54 -0
- package/src/c_yui_treedb_topics.js +62 -16
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -911,6 +911,7 @@ var PRIVATE_DATA$21 = {
|
|
|
911
911
|
navs: [],
|
|
912
912
|
item_index: {},
|
|
913
913
|
section_pos: {},
|
|
914
|
+
route_mru: [],
|
|
914
915
|
sub_routes: {},
|
|
915
916
|
event_handlers: {},
|
|
916
917
|
hash_handler: null,
|
|
@@ -1619,6 +1620,7 @@ function navigate_to(gobj, route, depth, no_drain) {
|
|
|
1619
1620
|
stage.active_route = matched_route;
|
|
1620
1621
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "current_route", route);
|
|
1621
1622
|
remember_position(gobj, route);
|
|
1623
|
+
remember_route(gobj, route);
|
|
1622
1624
|
update_secondary_nav_visibility(gobj, entry);
|
|
1623
1625
|
close_all_drawers(gobj);
|
|
1624
1626
|
close_toolbar_dropdown(gobj);
|
|
@@ -2645,6 +2647,40 @@ function remembered_position(gobj, route) {
|
|
|
2645
2647
|
return last;
|
|
2646
2648
|
}
|
|
2647
2649
|
/************************************************************
|
|
2650
|
+
* Every route the shell lands on, newest last, a route once.
|
|
2651
|
+
* Bounded: it answers "where was the reader last under X", and
|
|
2652
|
+
* a page that has been open all day has no business growing it.
|
|
2653
|
+
************************************************************/
|
|
2654
|
+
var ROUTE_MRU_MAX = 64;
|
|
2655
|
+
function remember_route(gobj, route) {
|
|
2656
|
+
let mru = gobj.priv.route_mru;
|
|
2657
|
+
let i = mru.indexOf(route);
|
|
2658
|
+
if (i >= 0) mru.splice(i, 1);
|
|
2659
|
+
mru.push(route);
|
|
2660
|
+
if (mru.length > ROUTE_MRU_MAX) mru.splice(0, mru.length - ROUTE_MRU_MAX);
|
|
2661
|
+
}
|
|
2662
|
+
/************************************************************
|
|
2663
|
+
* Where the reader last was UNDER `route`: the most recent
|
|
2664
|
+
* visited route that is `route` itself or lies below it, or
|
|
2665
|
+
* `route` when none does. A mirror of the url for the page, like
|
|
2666
|
+
* the section memory -- never stored, never applied on its own:
|
|
2667
|
+
* a control that wants to go back to a view AS IT WAS LEFT asks,
|
|
2668
|
+
* and navigates there itself.
|
|
2669
|
+
*
|
|
2670
|
+
* What it is for: a treedb graph's focus lives in the url
|
|
2671
|
+
* (`<graph>/<topic>`), so a button that opened the bare route
|
|
2672
|
+
* took the focus away every time it was used.
|
|
2673
|
+
************************************************************/
|
|
2674
|
+
function yui_shell_last_route_under(shell_gobj, route) {
|
|
2675
|
+
let priv = shell_gobj && shell_gobj.priv;
|
|
2676
|
+
if (!priv || !(0, _yuneta_gobj_js.is_array)(priv.route_mru) || !route) return route;
|
|
2677
|
+
for (let i = priv.route_mru.length - 1; i >= 0; i--) {
|
|
2678
|
+
let r = priv.route_mru[i];
|
|
2679
|
+
if (r === route || r.indexOf(route + "/") === 0) return r;
|
|
2680
|
+
}
|
|
2681
|
+
return route;
|
|
2682
|
+
}
|
|
2683
|
+
/************************************************************
|
|
2648
2684
|
* Resolve the shell that governs `gobj`: the nearest
|
|
2649
2685
|
* C_YUI_SHELL ancestor, else the last shell created on the
|
|
2650
2686
|
* page (apps have exactly one). Null when no shell exists —
|
|
@@ -21908,15 +21944,12 @@ function cmd_get_topic_data$1(gobj, cmd, kw, src) {
|
|
|
21908
21944
|
************************************************************/
|
|
21909
21945
|
function build_ui$6(gobj) {
|
|
21910
21946
|
let source_url = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "source_url") || "";
|
|
21911
|
-
let
|
|
21912
|
-
let graph_tpl = (0, _yuneta_gobj_js.is_object)(routes) && typeof routes.graph === "string" ? routes.graph : "";
|
|
21913
|
-
let graph_href = /\/\{topic\}$/.test(graph_tpl) ? graph_tpl.replace(/\/\{topic\}$/, "") : "";
|
|
21947
|
+
let graph_href = graph_route_of(gobj);
|
|
21914
21948
|
let graph_items = [];
|
|
21915
21949
|
if (graph_href) graph_items.push([
|
|
21916
|
-
"
|
|
21950
|
+
"button",
|
|
21917
21951
|
{
|
|
21918
21952
|
class: "button TREEDB_GRAPH_BTN",
|
|
21919
|
-
href: graph_href,
|
|
21920
21953
|
style: "margin-left:auto;",
|
|
21921
21954
|
title: (0, i18next.t)("graph"),
|
|
21922
21955
|
"aria-label": (0, i18next.t)("graph"),
|
|
@@ -21931,7 +21964,11 @@ function build_ui$6(gobj) {
|
|
|
21931
21964
|
"span",
|
|
21932
21965
|
{ i18n: "graph" },
|
|
21933
21966
|
"graph"
|
|
21934
|
-
]]
|
|
21967
|
+
]],
|
|
21968
|
+
{ click: (evt) => {
|
|
21969
|
+
evt.stopPropagation();
|
|
21970
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_OPEN_GRAPH", {}, gobj);
|
|
21971
|
+
} }
|
|
21935
21972
|
]);
|
|
21936
21973
|
let $container = (0, _yuneta_gobj_js.createElement2)([
|
|
21937
21974
|
"div",
|
|
@@ -22092,6 +22129,17 @@ function build_ui$6(gobj) {
|
|
|
22092
22129
|
if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "with_cards_landing")) show_topics_landing(gobj);
|
|
22093
22130
|
}
|
|
22094
22131
|
/************************************************************
|
|
22132
|
+
* The graph's route with no topic: the host's card template
|
|
22133
|
+
* `card_action_routes.graph` without its trailing `/{topic}`,
|
|
22134
|
+
* as a ROUTE (no `#`). "" when the host gives no such template.
|
|
22135
|
+
************************************************************/
|
|
22136
|
+
function graph_route_of(gobj) {
|
|
22137
|
+
let routes = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "card_action_routes");
|
|
22138
|
+
let tpl = (0, _yuneta_gobj_js.is_object)(routes) && typeof routes.graph === "string" ? routes.graph : "";
|
|
22139
|
+
if (!/\/\{topic\}$/.test(tpl)) return "";
|
|
22140
|
+
return tpl.replace(/\/\{topic\}$/, "").replace(/^#/, "");
|
|
22141
|
+
}
|
|
22142
|
+
/************************************************************
|
|
22095
22143
|
* Is the backend session live? The Raw JSON viewer issues a remote
|
|
22096
22144
|
* print-tranger, so it only makes sense with a session — the remote
|
|
22097
22145
|
* (C_IEVENT_CLI) is in ST_SESSION exactly while connected.
|
|
@@ -23460,6 +23508,26 @@ function ac_open_json$1(gobj, event, kw, src) {
|
|
|
23460
23508
|
return 0;
|
|
23461
23509
|
}
|
|
23462
23510
|
/********************************************
|
|
23511
|
+
* Open the graph where the reader left it: its last visited
|
|
23512
|
+
* route under the graph's base -- `<graph>/<topic>` when a topic
|
|
23513
|
+
* was focused there -- or the bare base when the graph was never
|
|
23514
|
+
* opened in this page. A user move: pushed, so Back returns.
|
|
23515
|
+
********************************************/
|
|
23516
|
+
function ac_open_graph(gobj, event, kw, src) {
|
|
23517
|
+
let base = graph_route_of(gobj);
|
|
23518
|
+
if (!base) {
|
|
23519
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: open graph with no graph route`);
|
|
23520
|
+
return -1;
|
|
23521
|
+
}
|
|
23522
|
+
let shell = yui_shell_of(gobj);
|
|
23523
|
+
if (!shell) {
|
|
23524
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: open graph with no shell`);
|
|
23525
|
+
return -1;
|
|
23526
|
+
}
|
|
23527
|
+
yui_shell_navigate(shell, yui_shell_last_route_under(shell, base), { push: true });
|
|
23528
|
+
return 0;
|
|
23529
|
+
}
|
|
23530
|
+
/********************************************
|
|
23463
23531
|
* The viewer asked to load a collapsed subtree (tranger mode only):
|
|
23464
23532
|
* re-issue print-tranger for that path.
|
|
23465
23533
|
********************************************/
|
|
@@ -23558,6 +23626,11 @@ function create_gclass$6(gclass_name) {
|
|
|
23558
23626
|
ac_open_json$1,
|
|
23559
23627
|
null
|
|
23560
23628
|
],
|
|
23629
|
+
[
|
|
23630
|
+
"EV_OPEN_GRAPH",
|
|
23631
|
+
ac_open_graph,
|
|
23632
|
+
null
|
|
23633
|
+
],
|
|
23561
23634
|
[
|
|
23562
23635
|
"EV_EXPAND_PATH",
|
|
23563
23636
|
ac_json_expand_path$1,
|
|
@@ -23622,6 +23695,7 @@ function create_gclass$6(gclass_name) {
|
|
|
23622
23695
|
["EV_RECORD_WRITTEN", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT | _yuneta_gobj_js.event_flag_t.EVF_NO_WARN_SUBS],
|
|
23623
23696
|
["EV_REFRESH_TOPIC", 0],
|
|
23624
23697
|
["EV_OPEN_JSON", 0],
|
|
23698
|
+
["EV_OPEN_GRAPH", 0],
|
|
23625
23699
|
["EV_EXPAND_PATH", 0],
|
|
23626
23700
|
["EV_JSON_CLOSED", 0],
|
|
23627
23701
|
["EV_SHOW", 0],
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -906,6 +906,7 @@ var PRIVATE_DATA$21 = {
|
|
|
906
906
|
navs: [],
|
|
907
907
|
item_index: {},
|
|
908
908
|
section_pos: {},
|
|
909
|
+
route_mru: [],
|
|
909
910
|
sub_routes: {},
|
|
910
911
|
event_handlers: {},
|
|
911
912
|
hash_handler: null,
|
|
@@ -1614,6 +1615,7 @@ function navigate_to(gobj, route, depth, no_drain) {
|
|
|
1614
1615
|
stage.active_route = matched_route;
|
|
1615
1616
|
gobj_write_attr(gobj, "current_route", route);
|
|
1616
1617
|
remember_position(gobj, route);
|
|
1618
|
+
remember_route(gobj, route);
|
|
1617
1619
|
update_secondary_nav_visibility(gobj, entry);
|
|
1618
1620
|
close_all_drawers(gobj);
|
|
1619
1621
|
close_toolbar_dropdown(gobj);
|
|
@@ -2640,6 +2642,40 @@ function remembered_position(gobj, route) {
|
|
|
2640
2642
|
return last;
|
|
2641
2643
|
}
|
|
2642
2644
|
/************************************************************
|
|
2645
|
+
* Every route the shell lands on, newest last, a route once.
|
|
2646
|
+
* Bounded: it answers "where was the reader last under X", and
|
|
2647
|
+
* a page that has been open all day has no business growing it.
|
|
2648
|
+
************************************************************/
|
|
2649
|
+
var ROUTE_MRU_MAX = 64;
|
|
2650
|
+
function remember_route(gobj, route) {
|
|
2651
|
+
let mru = gobj.priv.route_mru;
|
|
2652
|
+
let i = mru.indexOf(route);
|
|
2653
|
+
if (i >= 0) mru.splice(i, 1);
|
|
2654
|
+
mru.push(route);
|
|
2655
|
+
if (mru.length > ROUTE_MRU_MAX) mru.splice(0, mru.length - ROUTE_MRU_MAX);
|
|
2656
|
+
}
|
|
2657
|
+
/************************************************************
|
|
2658
|
+
* Where the reader last was UNDER `route`: the most recent
|
|
2659
|
+
* visited route that is `route` itself or lies below it, or
|
|
2660
|
+
* `route` when none does. A mirror of the url for the page, like
|
|
2661
|
+
* the section memory -- never stored, never applied on its own:
|
|
2662
|
+
* a control that wants to go back to a view AS IT WAS LEFT asks,
|
|
2663
|
+
* and navigates there itself.
|
|
2664
|
+
*
|
|
2665
|
+
* What it is for: a treedb graph's focus lives in the url
|
|
2666
|
+
* (`<graph>/<topic>`), so a button that opened the bare route
|
|
2667
|
+
* took the focus away every time it was used.
|
|
2668
|
+
************************************************************/
|
|
2669
|
+
function yui_shell_last_route_under(shell_gobj, route) {
|
|
2670
|
+
let priv = shell_gobj && shell_gobj.priv;
|
|
2671
|
+
if (!priv || !is_array(priv.route_mru) || !route) return route;
|
|
2672
|
+
for (let i = priv.route_mru.length - 1; i >= 0; i--) {
|
|
2673
|
+
let r = priv.route_mru[i];
|
|
2674
|
+
if (r === route || r.indexOf(route + "/") === 0) return r;
|
|
2675
|
+
}
|
|
2676
|
+
return route;
|
|
2677
|
+
}
|
|
2678
|
+
/************************************************************
|
|
2643
2679
|
* Resolve the shell that governs `gobj`: the nearest
|
|
2644
2680
|
* C_YUI_SHELL ancestor, else the last shell created on the
|
|
2645
2681
|
* page (apps have exactly one). Null when no shell exists —
|
|
@@ -21903,15 +21939,12 @@ function cmd_get_topic_data$1(gobj, cmd, kw, src) {
|
|
|
21903
21939
|
************************************************************/
|
|
21904
21940
|
function build_ui$6(gobj) {
|
|
21905
21941
|
let source_url = gobj_read_str_attr(gobj, "source_url") || "";
|
|
21906
|
-
let
|
|
21907
|
-
let graph_tpl = is_object(routes) && typeof routes.graph === "string" ? routes.graph : "";
|
|
21908
|
-
let graph_href = /\/\{topic\}$/.test(graph_tpl) ? graph_tpl.replace(/\/\{topic\}$/, "") : "";
|
|
21942
|
+
let graph_href = graph_route_of(gobj);
|
|
21909
21943
|
let graph_items = [];
|
|
21910
21944
|
if (graph_href) graph_items.push([
|
|
21911
|
-
"
|
|
21945
|
+
"button",
|
|
21912
21946
|
{
|
|
21913
21947
|
class: "button TREEDB_GRAPH_BTN",
|
|
21914
|
-
href: graph_href,
|
|
21915
21948
|
style: "margin-left:auto;",
|
|
21916
21949
|
title: t("graph"),
|
|
21917
21950
|
"aria-label": t("graph"),
|
|
@@ -21926,7 +21959,11 @@ function build_ui$6(gobj) {
|
|
|
21926
21959
|
"span",
|
|
21927
21960
|
{ i18n: "graph" },
|
|
21928
21961
|
"graph"
|
|
21929
|
-
]]
|
|
21962
|
+
]],
|
|
21963
|
+
{ click: (evt) => {
|
|
21964
|
+
evt.stopPropagation();
|
|
21965
|
+
gobj_send_event(gobj, "EV_OPEN_GRAPH", {}, gobj);
|
|
21966
|
+
} }
|
|
21930
21967
|
]);
|
|
21931
21968
|
let $container = createElement2([
|
|
21932
21969
|
"div",
|
|
@@ -22087,6 +22124,17 @@ function build_ui$6(gobj) {
|
|
|
22087
22124
|
if (gobj_read_bool_attr(gobj, "with_cards_landing")) show_topics_landing(gobj);
|
|
22088
22125
|
}
|
|
22089
22126
|
/************************************************************
|
|
22127
|
+
* The graph's route with no topic: the host's card template
|
|
22128
|
+
* `card_action_routes.graph` without its trailing `/{topic}`,
|
|
22129
|
+
* as a ROUTE (no `#`). "" when the host gives no such template.
|
|
22130
|
+
************************************************************/
|
|
22131
|
+
function graph_route_of(gobj) {
|
|
22132
|
+
let routes = gobj_read_attr(gobj, "card_action_routes");
|
|
22133
|
+
let tpl = is_object(routes) && typeof routes.graph === "string" ? routes.graph : "";
|
|
22134
|
+
if (!/\/\{topic\}$/.test(tpl)) return "";
|
|
22135
|
+
return tpl.replace(/\/\{topic\}$/, "").replace(/^#/, "");
|
|
22136
|
+
}
|
|
22137
|
+
/************************************************************
|
|
22090
22138
|
* Is the backend session live? The Raw JSON viewer issues a remote
|
|
22091
22139
|
* print-tranger, so it only makes sense with a session — the remote
|
|
22092
22140
|
* (C_IEVENT_CLI) is in ST_SESSION exactly while connected.
|
|
@@ -23455,6 +23503,26 @@ function ac_open_json$1(gobj, event, kw, src) {
|
|
|
23455
23503
|
return 0;
|
|
23456
23504
|
}
|
|
23457
23505
|
/********************************************
|
|
23506
|
+
* Open the graph where the reader left it: its last visited
|
|
23507
|
+
* route under the graph's base -- `<graph>/<topic>` when a topic
|
|
23508
|
+
* was focused there -- or the bare base when the graph was never
|
|
23509
|
+
* opened in this page. A user move: pushed, so Back returns.
|
|
23510
|
+
********************************************/
|
|
23511
|
+
function ac_open_graph(gobj, event, kw, src) {
|
|
23512
|
+
let base = graph_route_of(gobj);
|
|
23513
|
+
if (!base) {
|
|
23514
|
+
log_error(`${gobj_short_name(gobj)}: open graph with no graph route`);
|
|
23515
|
+
return -1;
|
|
23516
|
+
}
|
|
23517
|
+
let shell = yui_shell_of(gobj);
|
|
23518
|
+
if (!shell) {
|
|
23519
|
+
log_error(`${gobj_short_name(gobj)}: open graph with no shell`);
|
|
23520
|
+
return -1;
|
|
23521
|
+
}
|
|
23522
|
+
yui_shell_navigate(shell, yui_shell_last_route_under(shell, base), { push: true });
|
|
23523
|
+
return 0;
|
|
23524
|
+
}
|
|
23525
|
+
/********************************************
|
|
23458
23526
|
* The viewer asked to load a collapsed subtree (tranger mode only):
|
|
23459
23527
|
* re-issue print-tranger for that path.
|
|
23460
23528
|
********************************************/
|
|
@@ -23553,6 +23621,11 @@ function create_gclass$6(gclass_name) {
|
|
|
23553
23621
|
ac_open_json$1,
|
|
23554
23622
|
null
|
|
23555
23623
|
],
|
|
23624
|
+
[
|
|
23625
|
+
"EV_OPEN_GRAPH",
|
|
23626
|
+
ac_open_graph,
|
|
23627
|
+
null
|
|
23628
|
+
],
|
|
23556
23629
|
[
|
|
23557
23630
|
"EV_EXPAND_PATH",
|
|
23558
23631
|
ac_json_expand_path$1,
|
|
@@ -23617,6 +23690,7 @@ function create_gclass$6(gclass_name) {
|
|
|
23617
23690
|
["EV_RECORD_WRITTEN", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
23618
23691
|
["EV_REFRESH_TOPIC", 0],
|
|
23619
23692
|
["EV_OPEN_JSON", 0],
|
|
23693
|
+
["EV_OPEN_GRAPH", 0],
|
|
23620
23694
|
["EV_EXPAND_PATH", 0],
|
|
23621
23695
|
["EV_JSON_CLOSED", 0],
|
|
23622
23696
|
["EV_SHOW", 0],
|
package/package.json
CHANGED
package/src/c_yui_node.js
CHANGED
|
@@ -1324,6 +1324,12 @@ function ac_add_node(gobj, event, kw, src)
|
|
|
1324
1324
|
if(spec.link) {
|
|
1325
1325
|
kw_child.link = spec.link;
|
|
1326
1326
|
}
|
|
1327
|
+
/* A declared attr of this gclass that the spec could not reach: a
|
|
1328
|
+
* node whose children are workspaces (a treedb: its topics, its
|
|
1329
|
+
* graph) is declared in the config like every other one. */
|
|
1330
|
+
if(spec.remember_position) {
|
|
1331
|
+
kw_child.remember_position = true;
|
|
1332
|
+
}
|
|
1327
1333
|
let child = gobj_create_pure_child(spec.id, GCLASS_NAME, kw_child, gobj);
|
|
1328
1334
|
|
|
1329
1335
|
let index = (typeof kw.index === "number") ? kw.index : priv.children.length;
|
package/src/c_yui_shell.js
CHANGED
|
@@ -117,6 +117,10 @@ let PRIVATE_DATA = {
|
|
|
117
117
|
/* Section route -> last position visited inside it. Mirrors the
|
|
118
118
|
* url for the duration of the page; see remember_position(). */
|
|
119
119
|
section_pos: {},
|
|
120
|
+
/* The routes visited, newest last, bounded -- for "where did the
|
|
121
|
+
* reader leave this subtree" (yui_shell_last_route_under). Same
|
|
122
|
+
* nature as section_pos: a mirror of the url, for the page. */
|
|
123
|
+
route_mru: [],
|
|
120
124
|
/* Sub-route contributor registry (ROUTING.md): a mounted view
|
|
121
125
|
* declares the deep, view-owned children of its base route
|
|
122
126
|
* (topics, /info, /schema, focus topics — subpaths that are NOT
|
|
@@ -1465,6 +1469,7 @@ function navigate_to(gobj, route, depth, no_drain)
|
|
|
1465
1469
|
stage.active_route = matched_route;
|
|
1466
1470
|
gobj_write_attr(gobj, "current_route", route);
|
|
1467
1471
|
remember_position(gobj, route);
|
|
1472
|
+
remember_route(gobj, route);
|
|
1468
1473
|
|
|
1469
1474
|
/* Show/hide secondary navs according to parent item */
|
|
1470
1475
|
update_secondary_nav_visibility(gobj, entry);
|
|
@@ -3187,6 +3192,54 @@ function remembered_position(gobj, route)
|
|
|
3187
3192
|
return last;
|
|
3188
3193
|
}
|
|
3189
3194
|
|
|
3195
|
+
/************************************************************
|
|
3196
|
+
* Every route the shell lands on, newest last, a route once.
|
|
3197
|
+
* Bounded: it answers "where was the reader last under X", and
|
|
3198
|
+
* a page that has been open all day has no business growing it.
|
|
3199
|
+
************************************************************/
|
|
3200
|
+
const ROUTE_MRU_MAX = 64;
|
|
3201
|
+
|
|
3202
|
+
function remember_route(gobj, route)
|
|
3203
|
+
{
|
|
3204
|
+
let priv = gobj.priv;
|
|
3205
|
+
let mru = priv.route_mru;
|
|
3206
|
+
let i = mru.indexOf(route);
|
|
3207
|
+
if(i >= 0) {
|
|
3208
|
+
mru.splice(i, 1);
|
|
3209
|
+
}
|
|
3210
|
+
mru.push(route);
|
|
3211
|
+
if(mru.length > ROUTE_MRU_MAX) {
|
|
3212
|
+
mru.splice(0, mru.length - ROUTE_MRU_MAX);
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
/************************************************************
|
|
3217
|
+
* Where the reader last was UNDER `route`: the most recent
|
|
3218
|
+
* visited route that is `route` itself or lies below it, or
|
|
3219
|
+
* `route` when none does. A mirror of the url for the page, like
|
|
3220
|
+
* the section memory -- never stored, never applied on its own:
|
|
3221
|
+
* a control that wants to go back to a view AS IT WAS LEFT asks,
|
|
3222
|
+
* and navigates there itself.
|
|
3223
|
+
*
|
|
3224
|
+
* What it is for: a treedb graph's focus lives in the url
|
|
3225
|
+
* (`<graph>/<topic>`), so a button that opened the bare route
|
|
3226
|
+
* took the focus away every time it was used.
|
|
3227
|
+
************************************************************/
|
|
3228
|
+
function yui_shell_last_route_under(shell_gobj, route)
|
|
3229
|
+
{
|
|
3230
|
+
let priv = shell_gobj && shell_gobj.priv;
|
|
3231
|
+
if(!priv || !is_array(priv.route_mru) || !route) {
|
|
3232
|
+
return route;
|
|
3233
|
+
}
|
|
3234
|
+
for(let i = priv.route_mru.length - 1; i >= 0; i--) {
|
|
3235
|
+
let r = priv.route_mru[i];
|
|
3236
|
+
if(r === route || r.indexOf(route + "/") === 0) {
|
|
3237
|
+
return r;
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
return route;
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3190
3243
|
/************************************************************
|
|
3191
3244
|
* Resolve the shell that governs `gobj`: the nearest
|
|
3192
3245
|
* C_YUI_SHELL ancestor, else the last shell created on the
|
|
@@ -3609,6 +3662,7 @@ export {
|
|
|
3609
3662
|
yui_shell_of,
|
|
3610
3663
|
yui_shell_zone,
|
|
3611
3664
|
yui_shell_navigate,
|
|
3665
|
+
yui_shell_last_route_under,
|
|
3612
3666
|
yui_shell_nav_map,
|
|
3613
3667
|
yui_shell_set_sub_routes,
|
|
3614
3668
|
yui_shell_register_event_handler,
|
|
@@ -58,7 +58,12 @@ import {
|
|
|
58
58
|
import "./c_yui_treedb_topics.css";
|
|
59
59
|
|
|
60
60
|
import {yui_shell_show_error, yui_shell_show_modal, yui_shell_popup_layer} from "./shell_modals.js";
|
|
61
|
-
import {
|
|
61
|
+
import {
|
|
62
|
+
yui_shell_of,
|
|
63
|
+
yui_shell_set_sub_routes,
|
|
64
|
+
yui_shell_navigate,
|
|
65
|
+
yui_shell_last_route_under,
|
|
66
|
+
} from "./c_yui_shell.js";
|
|
62
67
|
import {nodes_answer} from "./nodes_answer.js";
|
|
63
68
|
import {yui_toolbar_icon} from "./yui_toolbar.js";
|
|
64
69
|
|
|
@@ -254,26 +259,28 @@ function build_ui(gobj)
|
|
|
254
259
|
{
|
|
255
260
|
let source_url = gobj_read_str_attr(gobj, "source_url") || "";
|
|
256
261
|
|
|
257
|
-
/* The
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
let
|
|
264
|
-
let graph_tpl = is_object(routes) && typeof routes.graph === "string"? routes.graph : "";
|
|
265
|
-
let graph_href = /\/\{topic\}$/.test(graph_tpl)? graph_tpl.replace(/\/\{topic\}$/, "") : "";
|
|
262
|
+
/* The treedb as a graph, AS THE READER LEFT IT. The route is the
|
|
263
|
+
* card template without its `/{topic}`; a host whose template does
|
|
264
|
+
* not end in it, or gives none, gets no button. Not a fixed link:
|
|
265
|
+
* the graph's focus lives in its url (`<graph>/<topic>`), so the
|
|
266
|
+
* bare route took it away every time -- the click asks the shell
|
|
267
|
+
* where the reader last was under that route (ac_open_graph). */
|
|
268
|
+
let graph_href = graph_route_of(gobj);
|
|
266
269
|
let graph_items = [];
|
|
267
270
|
if(graph_href) {
|
|
268
271
|
graph_items.push(
|
|
269
|
-
['
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
'data-i18n-title': 'graph', 'data-i18n-aria-label': 'graph'}, [
|
|
272
|
+
['button', {class: 'button TREEDB_GRAPH_BTN',
|
|
273
|
+
style: 'margin-left:auto;',
|
|
274
|
+
title: t('graph'), 'aria-label': t('graph'),
|
|
275
|
+
'data-i18n-title': 'graph', 'data-i18n-aria-label': 'graph'}, [
|
|
274
276
|
['span', {class: 'icon'}, [yui_toolbar_icon('yi-hexagon-nodes')]],
|
|
275
277
|
['span', {i18n: 'graph'}, 'graph']
|
|
276
|
-
]
|
|
278
|
+
], {
|
|
279
|
+
click: (evt) => {
|
|
280
|
+
evt.stopPropagation();
|
|
281
|
+
gobj_send_event(gobj, "EV_OPEN_GRAPH", {}, gobj);
|
|
282
|
+
}
|
|
283
|
+
}]
|
|
277
284
|
);
|
|
278
285
|
}
|
|
279
286
|
|
|
@@ -389,6 +396,21 @@ function build_ui(gobj)
|
|
|
389
396
|
}
|
|
390
397
|
}
|
|
391
398
|
|
|
399
|
+
/************************************************************
|
|
400
|
+
* The graph's route with no topic: the host's card template
|
|
401
|
+
* `card_action_routes.graph` without its trailing `/{topic}`,
|
|
402
|
+
* as a ROUTE (no `#`). "" when the host gives no such template.
|
|
403
|
+
************************************************************/
|
|
404
|
+
function graph_route_of(gobj)
|
|
405
|
+
{
|
|
406
|
+
let routes = gobj_read_attr(gobj, "card_action_routes");
|
|
407
|
+
let tpl = (is_object(routes) && typeof routes.graph === "string")? routes.graph : "";
|
|
408
|
+
if(!/\/\{topic\}$/.test(tpl)) {
|
|
409
|
+
return "";
|
|
410
|
+
}
|
|
411
|
+
return tpl.replace(/\/\{topic\}$/, "").replace(/^#/, "");
|
|
412
|
+
}
|
|
413
|
+
|
|
392
414
|
/************************************************************
|
|
393
415
|
* Is the backend session live? The Raw JSON viewer issues a remote
|
|
394
416
|
* print-tranger, so it only makes sense with a session — the remote
|
|
@@ -2476,6 +2498,28 @@ function ac_open_json(gobj, event, kw, src)
|
|
|
2476
2498
|
return 0;
|
|
2477
2499
|
}
|
|
2478
2500
|
|
|
2501
|
+
/********************************************
|
|
2502
|
+
* Open the graph where the reader left it: its last visited
|
|
2503
|
+
* route under the graph's base -- `<graph>/<topic>` when a topic
|
|
2504
|
+
* was focused there -- or the bare base when the graph was never
|
|
2505
|
+
* opened in this page. A user move: pushed, so Back returns.
|
|
2506
|
+
********************************************/
|
|
2507
|
+
function ac_open_graph(gobj, event, kw, src)
|
|
2508
|
+
{
|
|
2509
|
+
let base = graph_route_of(gobj);
|
|
2510
|
+
if(!base) {
|
|
2511
|
+
log_error(`${gobj_short_name(gobj)}: open graph with no graph route`);
|
|
2512
|
+
return -1;
|
|
2513
|
+
}
|
|
2514
|
+
let shell = yui_shell_of(gobj);
|
|
2515
|
+
if(!shell) {
|
|
2516
|
+
log_error(`${gobj_short_name(gobj)}: open graph with no shell`);
|
|
2517
|
+
return -1;
|
|
2518
|
+
}
|
|
2519
|
+
yui_shell_navigate(shell, yui_shell_last_route_under(shell, base), {push: true});
|
|
2520
|
+
return 0;
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2479
2523
|
/********************************************
|
|
2480
2524
|
* The viewer asked to load a collapsed subtree (tranger mode only):
|
|
2481
2525
|
* re-issue print-tranger for that path.
|
|
@@ -2556,6 +2600,7 @@ function create_gclass(gclass_name)
|
|
|
2556
2600
|
["EV_DELETE_RECORD", ac_delete_record, null],
|
|
2557
2601
|
["EV_REFRESH_TOPIC", ac_refresh_topic, null],
|
|
2558
2602
|
["EV_OPEN_JSON", ac_open_json, null],
|
|
2603
|
+
["EV_OPEN_GRAPH", ac_open_graph, null],
|
|
2559
2604
|
["EV_EXPAND_PATH", ac_json_expand_path, null],
|
|
2560
2605
|
["EV_JSON_CLOSED", ac_json_closed, null],
|
|
2561
2606
|
["EV_SHOW", ac_show, null],
|
|
@@ -2586,6 +2631,7 @@ function create_gclass(gclass_name)
|
|
|
2586
2631
|
event_flag_t.EVF_NO_WARN_SUBS],
|
|
2587
2632
|
["EV_REFRESH_TOPIC", 0],
|
|
2588
2633
|
["EV_OPEN_JSON", 0],
|
|
2634
|
+
["EV_OPEN_GRAPH", 0],
|
|
2589
2635
|
["EV_EXPAND_PATH", 0],
|
|
2590
2636
|
["EV_JSON_CLOSED", 0],
|
|
2591
2637
|
["EV_SHOW", 0],
|