()
| 4 | import {Sandbox} from "./sandbox.mjs" |
| 5 | |
| 6 | function chapterInteraction() { |
| 7 | document.querySelectorAll("button.help").forEach(button => { |
| 8 | button.style.display = "inline" |
| 9 | button.addEventListener("click", showHelp) |
| 10 | }) |
| 11 | document.body.addEventListener("keydown", e => { |
| 12 | let active = document.activeElement |
| 13 | if (e.key == "?" && !e.ctrlKey && !e.altKey && !e.metaKey) { |
| 14 | if (!active || (active.contentEditable != "true" && active.nodeName != "INPUT")) { |
| 15 | e.preventDefault() |
| 16 | showHelp() |
| 17 | } |
| 18 | } |
| 19 | if (e.key == "Enter" && !e.ctrlKey && !e.altKey && !e.metaKey) { |
| 20 | let editor = active && maybeActivateCode(active) |
| 21 | if (editor) { |
| 22 | e.preventDefault() |
| 23 | editor.focus() |
| 24 | } |
| 25 | } |
| 26 | }) |
| 27 | |
| 28 | let modName = /Mac/.test(navigator.platform) ? "Cmd-" : "Ctrl-" |
| 29 | |
| 30 | function showHelp() { |
| 31 | let popup = document.body.appendChild(document.createElement("div")) |
| 32 | popup.className = "popup" |
| 33 | popup.appendChild(document.createElement("h2")).textContent = "Instructions" |
| 34 | popup.appendChild(document.createElement("p")).textContent = `Code snippets on this page can be edited and run by clicking them or moving focus to them and pressing Enter. Executed snippets share their environment with other snippets ran on the page, and some pre-defined code for the chapter. When inside the code editor, the following keyboard shortcuts are available:` |
| 35 | for (let [key, desc] of [ |
| 36 | [modName + "Enter", "Run code"], |
| 37 | [modName + "j", "Revert code"], |
| 38 | [modName + "↓", "Deactivate editor"], |
| 39 | [modName + "Escape", "Reset environment"], |
| 40 | ]) { |
| 41 | let b = popup.appendChild(document.createElement("div")) |
| 42 | b.appendChild(document.createElement("kbd")).textContent = key |
| 43 | b.appendChild(document.createTextNode(": " + desc)) |
| 44 | } |
| 45 | popup.tabIndex = 0 |
| 46 | popup.addEventListener("blur", () => popup.remove()) |
| 47 | popup.addEventListener("keydown", e => { |
| 48 | if (e.key == "Escape") { e.preventDefault(); popup.remove() } |
| 49 | }) |
| 50 | popup.focus() |
| 51 | } |
| 52 | |
| 53 | document.body.addEventListener("mousedown", e => { |
| 54 | for (let n = e.target; n; n = n.parentNode) { |
| 55 | if (n.className == "c_ident") return |
| 56 | let editor = maybeActivateCode(n) |
| 57 | if (editor) { |
| 58 | e.preventDefault() |
| 59 | setTimeout(() => { |
| 60 | let pos = editor.posAtCoords({x: e.clientX, y: e.clientY}, false) |
| 61 | editor.dispatch({selection: {anchor: pos}}) |
| 62 | editor.focus() |
| 63 | }, 20) |
no test coverage detected