Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- Migrated project license from GPL-3 to the MIT License.

- Added a `?` button to the reactlog header. Hover over it or click it to see every keyboard shortcut, with key names for your operating system. The navigation button tooltips now also use your operating system's key names. The vignette has the same list (#73)

- Documented that `reactlog_show()` passes `...` on to `reactlog_render()`, so `session_token` can be set from `reactlog_show()`. The docs used to say `...` was ignored (#120)

- Fixed `reactlog_render()` printing "Loading required namespace: shiny" (#120)
Expand Down
4 changes: 4 additions & 0 deletions inst/reactlog/reactlog.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
<div id="filter">
<input id="search" type="text" size="12" placeholder="Search Labels..."/>
</div>
<div id="shortcuts">
<button id="shortcutsButton" type="button" aria-label="Keyboard shortcuts" aria-expanded="false" aria-controls="shortcutsPopup">?</button>
<div id="shortcutsPopup"></div>
</div>
</div> <!-- end statusHeader -->

<div id="timeline" style="z-index:1;">
Expand Down
48 changes: 48 additions & 0 deletions inst/reactlog/reactlogAsset/reactlog.css
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,54 @@ text {
margin-left: 5px;
margin-right: 5px;
}
#shortcuts {
position: relative;
margin-right: 8px;
}
#shortcutsButton {
display: block;
width: 16px;
height: 16px;
padding: 0;
border: 1px solid #d0d0d0;
border-radius: 50%;
background: transparent;
color: #a0a0a0;
font-family: inherit;
font-size: 11px;
line-height: 14px;
cursor: pointer;
}
#shortcutsButton:hover,
#shortcuts.open #shortcutsButton {
border-color: #a0a0a0;
color: #606060;
}
#shortcutsPopup {
display: none;
position: absolute;
top: 100%;
right: 0;
z-index: 2000;
padding: 8px 12px;
background: #fff;
border: 1px solid #d0d0d0;
border-radius: 5px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
font-size: 12px;
}
#shortcuts:hover #shortcutsPopup,
#shortcuts.open #shortcutsPopup {
display: block;
}
#shortcutsPopup th {
text-align: left;
font-weight: 600;
padding: 8px 0 4px;
}
#shortcutsPopup td {
padding: 2px 12px 2px 0;
}
#search {
background: url("images/iconSearch.svg") no-repeat scroll 0 0;
background-size: 20px 20px;
Expand Down
10 changes: 5 additions & 5 deletions inst/reactlog/reactlogAsset/reactlog.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions inst/reactlog/reactlogAsset/reactlog.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions srcts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import colors from "./style/colors";
import * as cytoscapeInit from "./cyto/cytoscapeInit";

import * as layoutKeydown from "./layout/keydown";
import * as shortcuts from "./layout/shortcuts";

import * as updateGraph from "./updateGraph";

Expand Down Expand Up @@ -128,6 +129,7 @@ $(function () {
);

updateGraph.searchStringContainer($("#search"));
shortcuts.setup();

{
let docBody = document.body;
Expand Down
102 changes: 102 additions & 0 deletions srcts/layout/shortcuts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import $ from "jquery";

const isMac = /Mac|iPhone|iPad/.test(navigator.userAgent);

const alt = isMac ? "Option" : "Alt";
const shift = "Shift";
const ctrl = isMac ? "Cmd" : "Ctrl";
// Mac laptops have no Home / End keys
const home = isMac ? ["Fn", "←"] : ["Home"];
const end = isMac ? ["Fn", "→"] : ["End"];

let comboText = function (keys: string[]): string {
return keys.join(" + ");
};

// each row: alternative key combos, then the action
type Row = [string[][], string];

const reactlogRows: Row[] = [
[[["→"], ["Space"]], "Next step"],
[[["←"]], "Previous step"],
[
[
[shift, "←"],
[shift, "→"],
],
"Previous / next log entry",
],
[
[
[alt, "←"],
[alt, "→"],
],
"Previous / next output calculation",
],
[
[
[alt, shift, "←"],
[alt, shift, "→"],
],
"Previous / next idle",
],
[[home, end], "Previous / next user mark"],
[[["s"]], "Focus the search bar"],
[[["Esc"]], "Leave search; clear highlight and filter"],
[[["f"]], "Fit the graph to the window"],
[[["l"]], "Show / hide log entry details"],
];
const shinyRows: Row[] = [
[[[ctrl, "F3"]], "Open reactlog"],
[
[
[ctrl, shift, "F3"],
[ctrl, "F4"],
],
"Add a user mark",
],
];

let sectionHtml = function (title: string, rows: Row[]): string {
let body = rows
.map(
([combos, action]) =>
`<tr><td class="monospaced-pre">${combos.map(comboText).join(" / ")}</td><td>${action}</td></tr>`
)
.join("");
return `<tr><th colspan="2">${title}</th></tr>${body}`;
};

let setup = function (): void {
$("#shortcutsPopup").html(
"<table>" +
sectionHtml("Keyboard shortcuts", reactlogRows) +
sectionHtml("In the Shiny app", shinyRows) +
"</table>"
);

let wrapper = $("#shortcuts");
$("#shortcutsButton").on("click", function () {
wrapper.toggleClass("open");
$(this).attr("aria-expanded", String(wrapper.hasClass("open")));
// keep focus off the button so Space / arrow keys still move the graph
$(this).trigger("blur");
});

// navigation button tooltips
let titles: [string, string, string[]][] = [
["prevUserMarkButton", "Previous User Mark", home],
["prevIdleButton", "Previous idle", [alt, shift, "←"]],
["prevOutputCalcButton", "Previous output calculation", [alt, "←"]],
["prevStepButton", "Previous step", ["←"]],
["nextStepButton", "Next step", ["→"]],
["nextOutputCalcButton", "Next output calculation", [alt, "→"]],
["nextIdleButton", "Next idle", [alt, shift, "→"]],
["nextUserMarkButton", "Next User Mark", end],
];
titles.forEach(([id, label, keys]) => {
$(`#${id}`).attr("title", `${label} (${comboText(keys)})`);
});
};

export { setup };
28 changes: 28 additions & 0 deletions vignettes/reactlog.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ knitr::include_graphics("images/navigation.png")

> Tip: Hold `SHIFT` with the `Left/Right Arrow keys` to move one log entry at a time, including entries that are not shown as their own step.

> All key bindings are listed in [Keyboard shortcuts](#keyboard-shortcuts).

##### Search Bar

The search bar matches the name or ID of each reactive graph element. All matching elements are increased in size to signify a match and all matching elements' family trees are displayed. The search becomes active after three characters, and if no matches are found, the full graph is displayed.
Expand Down Expand Up @@ -349,6 +351,32 @@ knitr::include_graphics("images/elements.png")

Fortunately, **shiny**'s `reactive()` and `observe()` functions have a `label` argument. If provided, **reactlog** will use this value to label the corresponding nodes.

### Keyboard shortcuts {#keyboard-shortcuts}

Hover over or click the `?` button at the top right of **reactlog** to see these shortcuts with the key names for your computer.

Inside the **shiny** application (Mac users: use `Cmd` in place of `Ctrl`):

| Keys | Action |
|------|--------|
| `Ctrl + F3` | Open **reactlog** |
| `Ctrl + Shift + F3` or `Ctrl + F4` | Add a user mark at the current time |

Inside **reactlog** (`Alt` is `Option` on a Mac):

| Keys | Action |
|------|--------|
| `Right Arrow` or `Space` | Next step |
| `Left Arrow` | Previous step |
| `Shift + Left/Right Arrow` | Previous / next log entry, including entries that are not shown as their own step |
| `Alt + Left/Right Arrow` | Previous / next reactive endpoint calculation |
| `Alt + Shift + Left/Right Arrow` | Previous / next idle step |
| `Home` / `End` | Previous / next user mark (or the start / end of the log) |
| `s` | Focus the search bar |
| `Esc` | Leave the search bar; otherwise clear the highlight and filter |
| `f` | Fit the graph to the window |
| `l` | Show or hide detailed information about the current step |

## Learn more {#learn-more}

This vignette explains the **reactlog** interface, which requires a basic understanding of **shiny** and reactive programming. There are many other useful existing articles and resources that may help advance your understanding of **reactlog** and **shiny**, including but not limited to:
Expand Down
Loading