From e707a08a84189406498835344ab7f6b4e62571b7 Mon Sep 17 00:00:00 2001 From: tophf Date: Sun, 26 Apr 2015 15:34:59 +0300 Subject: [PATCH] Editor: showHelp() as html, add help for hotkeys --- edit.html | 68 ++++++++++++++++++++++++++++++++++++++++----- edit.js | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 138 insertions(+), 12 deletions(-) diff --git a/edit.html b/edit.html index 08960f0c..d5473844 100644 --- a/edit.html +++ b/edit.html @@ -61,11 +61,16 @@ .aligned { display: table-row; } - .aligned > * { + .aligned > *:not(img) { display: table-cell; margin-top: 0.1rem; min-height: 1.4rem; } + img[src="help.png"] { + cursor: pointer; + vertical-align: middle; + margin-left: 0.2rem; + } input[type="checkbox"] { margin-left: 0.1rem; } @@ -88,11 +93,6 @@ margin-right: 0.5rem; margin-bottom: 0.5rem; } - #actions img { - margin-left: 0.2rem; - position: relative; - top: 0.2rem; - } /* options */ #options [type="number"] { max-width: 2.5rem; @@ -202,6 +202,55 @@ .applies-to img { vertical-align: bottom; } + /************ help popup ************/ + #help-popup { + top: 3rem; + right: 3rem; + max-width: 50vw; + position: fixed; + display: none; + background-color: white; + box-shadow: 3px 3px 30px rgba(0, 0, 0, 0.5); + padding: 0.5rem; + z-index: 9999; + } + #help-popup .title { + font-weight: bold; + background-color: rgba(0,0,0,0.05); + margin: -0.5rem -0.5rem 0.5rem; + padding: 0.5rem; + } + #help-popup .contents { + max-height: calc(100vh - 8rem); + overflow-y: auto; + } + #help-popup .close-icon { + cursor: pointer; + width: 8px; + height: 8px; + position: absolute; + right: 0.5rem; + top: 0.75rem; + background: linear-gradient(-45deg, transparent 5px, black 5px, black 6px, transparent 6.5px), linear-gradient(45deg, transparent 5px, black 5px, black 6px, transparent 6.5px); + } + + .keymap-list { + font-size: 85%; + line-height: 1.0; + border-spacing: 0; + word-break: break-all; + } + .keymap-list input { + width: 100%; + } + .keymap-list tr:nth-child(odd) { + background-color: rgba(0, 0, 0, 0.07); + } + .keymap-list td:first-child { + white-space: nowrap; + font-family: monospace; + padding-right: 0.5rem; + } /************ reponsive layouts ************/ @media(max-width:737px) { @@ -248,7 +297,7 @@ #options { -webkit-column-count: 2; } - #options .aligned > * { + #options .aligned > *:not(img) { margin: 1px 0 0 0; /* workaround the flowing-padding column bug in webkit */ padding-right: 0.4rem; vertical-align: baseline; @@ -336,6 +385,7 @@
+
@@ -346,5 +396,9 @@

+
+
+
+
diff --git a/edit.js b/edit.js index cf3cc63a..63488d60 100644 --- a/edit.js +++ b/edit.js @@ -703,6 +703,7 @@ function initHooks() { document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false); document.getElementById("save-button").addEventListener("click", save, false); document.getElementById("sections-help").addEventListener("click", showSectionHelp, false); + document.getElementById("keyMap-help").addEventListener("click", showKeyMapHelp, false); setupGlobalSearch(); setCleanGlobal(); @@ -835,19 +836,90 @@ function toMozillaFormat() { } function showSectionHelp() { - showHelp(t("sectionHelp")); + showHelp(t("styleSectionsTitle"), t("sectionHelp")); } function showAppliesToHelp() { - showHelp(t("appliesHelp")); + showHelp(t("appliesLabel"), t("appliesHelp")); } function showToMozillaHelp() { - showHelp(t("styleToMozillaFormatHelp")); + showHelp(t("styleToMozillaFormat"), t("styleToMozillaFormatHelp")); } -function showHelp(text) { - alert(text); +function showKeyMapHelp() { + var keyMap = mergeKeyMaps({}, prefs.getPref("editor.keyMap"), CodeMirror.defaults.extraKeys); + var keyMapSorted = Object.keys(keyMap) + .map(function(key) { return {key: key, cmd: keyMap[key]} }) + .sort(function(a, b) { return a.cmd < b.cmd || (a.cmd == b.cmd && a.key < b.key) ? -1 : 1 }); + showHelp(t("cm_keyMap") + ": " + prefs.getPref("editor.keyMap"), + '' + + "" + + "" + keyMapSorted.map(function(value) { + return ""; + }).join("") + + "" + + "
" + value.key + "" + value.cmd + "
"); + document.querySelector("#help-popup table").addEventListener("input", function(event) { + var input = event.target; + var query = new RegExp(input.value.replace(/([{}()\[\]\/\\.+?^$:=*!|])/g, "\\$1"), "gi"); + var col = input.parentNode.cellIndex; + this.tBodies[0].childNodes.forEach(function(row) { + var cell = row.children[col]; + if (query.test(cell.textContent)) { + row.style.display = ""; + cell.innerHTML = cell.textContent.replace(query, "$&"); + } else { + row.style.display = "none"; + } + }); + }); + + function mergeKeyMaps(merged) { + [].slice.call(arguments, 1).forEach(function(keyMap) { + if (typeof keyMap == "string") { + keyMap = CodeMirror.keyMap[keyMap]; + } + Object.keys(keyMap).forEach(function(key) { + var cmd = keyMap[key]; + // filter out '...', 'attach', etc. (hotkeys start with an uppercase letter) + if (!merged[key] && !key.match(/^[a-z]/) && cmd != "...") { + if (typeof cmd == "function") { + // for 'emacs' keymap: provide at least something meaningful (hotkeys and the function body) + // for 'vim*' keymaps: almost nothing as it doesn't rely on CM keymap mechanism + cmd = cmd.toString().replace(/^function.*?\{[\s\r\n]*([\s\S]+?)[\s\r\n]*\}$/, "$1"); + merged[key] = cmd.length <= 200 ? cmd : cmd.substr(0, 200) + "..."; + } else { + merged[key] = cmd; + } + } + }); + if (keyMap.fallthrough) { + merged = mergeKeyMaps(merged, keyMap.fallthrough); + } + }); + return merged; + } +} + +function showHelp(title, text) { + var div = document.getElementById("help-popup"); + div.querySelector(".contents").innerHTML = text; + div.querySelector(".title").innerHTML = title; + + if (getComputedStyle(div).display == "none") { + document.addEventListener("keydown", closeHelp); + div.querySelector(".close-icon").onclick = closeHelp; // avoid chaining on multiple showHelp() calls + } + + div.style.display = "block"; + + function closeHelp(e) { + if (e.type == "click" || (e.keyCode == 27 && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey)) { + div.style.display = ""; + document.removeEventListener("keydown", closeHelp); + } + } } function getParams() {