diff --git a/src/web/stylesheets/utils/_general.css b/src/web/stylesheets/utils/_general.css
index c40c4ccd..56a8cbfe 100755
--- a/src/web/stylesheets/utils/_general.css
+++ b/src/web/stylesheets/utils/_general.css
@@ -50,6 +50,11 @@ body {
padding-left: 2px;
}
+.modal-icon {
+ position: absolute;
+ right: 25px;
+}
+
.konami {
transform: rotate(180deg);
}
diff --git a/src/web/utils/statusBar.mjs b/src/web/utils/statusBar.mjs
index 49e9a44b..81728cd9 100644
--- a/src/web/utils/statusBar.mjs
+++ b/src/web/utils/statusBar.mjs
@@ -41,6 +41,8 @@ class StatusBarPanel {
const rhs = document.createElement("div");
dom.className = "cm-status-bar";
+ dom.setAttribute("data-help-title", `${this.label} status bar`);
+ dom.setAttribute("data-help", `This status bar provides information about data in the ${this.label}. Help topics are available for each of the components by activating help when hovering over them.`);
lhs.innerHTML = this.constructLHS();
rhs.innerHTML = this.constructRHS();
@@ -184,6 +186,17 @@ class StatusBarPanel {
return;
}
+ // CodeMirror always counts line breaks as one character.
+ // We want to show an accurate reading of how many bytes there are.
+ let from = state.selection.main.from,
+ to = state.selection.main.to;
+ if (state.lineBreak.length !== 1) {
+ const fromLine = state.doc.lineAt(from).number;
+ const toLine = state.doc.lineAt(to).number;
+ from += (state.lineBreak.length * fromLine) - fromLine - 1;
+ to += (state.lineBreak.length * toLine) - toLine - 1;
+ }
+
if (selLen > 0) { // Range
const start = this.dom.querySelector(".sel-start-value"),
end = this.dom.querySelector(".sel-end-value"),
@@ -191,17 +204,15 @@ class StatusBarPanel {
selInfo.style.display = "inline-block";
curOffsetInfo.style.display = "none";
-
- start.textContent = state.selection.main.from;
- end.textContent = state.selection.main.to;
- length.textContent = state.selection.main.to - state.selection.main.from;
+ start.textContent = from;
+ end.textContent = to;
+ length.textContent = to - from;
} else { // Position
const offset = this.dom.querySelector(".cur-offset-value");
selInfo.style.display = "none";
curOffsetInfo.style.display = "inline-block";
-
- offset.textContent = state.selection.main.from;
+ offset.textContent = from;
}
}
@@ -314,21 +325,21 @@ class StatusBarPanel {
*/
constructLHS() {
return `
-
+
abc
-
+
sort
-
+
highlight_alt
\u279E
( selected)
-
+
location_on
`;
@@ -345,13 +356,23 @@ class StatusBarPanel {
`${name}`
).join("");
+ let chrEncHelpText = "",
+ eolHelpText = "";
+ if (this.label === "Input") {
+ chrEncHelpText = "The input character encoding defines how the input text is encoded into bytes which are then processed by the Recipe.
The 'Raw bytes' option attempts to treat the input as individual bytes in the range 0-255. If it detects any characters with Unicode values above 255, it will treat the entire input as UTF-8. 'Raw bytes' is usually the best option if you are inputting binary data, such as a file.";
+ eolHelpText = "The End of Line Sequence defines which bytes are considered EOL terminators. Pressing the return key will enter this value into the input and create a new line.
Changing the EOL sequence will not modify any existing data in the input but may change how previously entered line breaks are displayed. Lines added while a different EOL terminator was set may not now result in a new line, but may be displayed as control characters instead.";
+ } else {
+ chrEncHelpText = "The output character encoding defines how the output bytes are decoded into text which can be displayed to you.
The 'Raw bytes' option treats the output data as individual bytes in the range 0-255.";
+ eolHelpText = "The End of Line Sequence defines which bytes are considered EOL terminators.
Changing this value will not modify the value of the output, but may change how certain bytes are displayed and whether they result in a new line being created.";
+ }
+
return `
-
+
schedule
ms
-
+
text_fields Raw Bytes
@@ -371,7 +392,7 @@ class StatusBarPanel {
-
+
keyboard_return
diff --git a/src/web/waiters/BindingsWaiter.mjs b/src/web/waiters/BindingsWaiter.mjs
index a6bf7b65..967272ed 100755
--- a/src/web/waiters/BindingsWaiter.mjs
+++ b/src/web/waiters/BindingsWaiter.mjs
@@ -148,6 +148,12 @@ class BindingsWaiter {
}
break;
}
+ } else {
+ switch (e.code) {
+ case "F1":
+ this.contextualHelp();
+ break;
+ }
}
}
@@ -164,9 +170,14 @@ class BindingsWaiter {
}
document.getElementById("keybList").innerHTML = `
- Command |
- Shortcut (Win/Linux) |
- Shortcut (Mac) |
+ Command |
+ Shortcut (Win/Linux) |
+ Shortcut (Mac) |
+
+
+ Activate contextual help |
+ F1 |
+ F1 |
Place cursor in search field |
@@ -255,6 +266,29 @@ class BindingsWaiter {
`;
}
+ /**
+ * Shows contextual help message based on where the mouse pointer is
+ */
+ contextualHelp() {
+ const hoveredHelpEls = document.querySelectorAll(":hover[data-help]");
+
+ if (hoveredHelpEls.length) {
+ const helpEl = hoveredHelpEls[hoveredHelpEls.length - 1],
+ helpText = helpEl.getAttribute("data-help");
+ let helpTitle = helpEl.getAttribute("data-help-title");
+
+ if (helpTitle)
+ helpTitle = "Help topic: " + helpTitle;
+ else
+ helpTitle = "Help topic";
+
+ document.querySelector("#help-modal .modal-body").innerHTML = helpText;
+ document.querySelector("#help-modal #help-title").innerHTML = helpTitle;
+
+ $("#help-modal").modal();
+ }
+ }
+
}
export default BindingsWaiter;