diff --git a/common/content/commandline.js b/common/content/commandline.js index cd7f8c22..77161ab0 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -165,6 +165,7 @@ const CommandWidgets = Class("CommandWidgets", { completionContainer: Class.memoize(function () this.completionList.parentNode), multilineOutput: Class.memoize(function () { let elem = document.getElementById("dactyl-multiline-output"); + elem.contentWindow.addEventListener("unload", function (event) { event.preventDefault(); }, true); elem.contentDocument.body.id = "dactyl-multiline-output-content"; ["copy", "copylink", "selectall"].forEach(function (tail) { // some host apps use "hostPrefixContext-copy" ids @@ -942,6 +943,7 @@ const CommandLine = Module("commandline", { let command = event.originalTarget.getAttributeNS(NS.uri, "command"); if (command && dactyl.commands[command]) { + event.preventDefault(); return dactyl.withSavedValues(["forceNewTab"], function () { dactyl.forceNewTab = event.ctrlKey || event.shiftKey || event.button == 1; dactyl.commands[command](event); diff --git a/common/content/commands.js b/common/content/commands.js index 7ab0d4ba..ddb9d033 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -1400,7 +1400,8 @@ const Commands = Module("commands", { description: "List all Ex commands along with their short descriptions", iterate: function (args) commands, format: { - description: function (cmd) template.linkifyHelp(cmd.description + (cmd.replacementText ? ": " + cmd.action : "")) + description: function (cmd) template.linkifyHelp(cmd.description + (cmd.replacementText ? ": " + cmd.action : "")), + help: function (cmd) ":" + cmd.name } }); diff --git a/common/content/configbase.js b/common/content/configbase.js index 9606d344..3dce275d 100644 --- a/common/content/configbase.js +++ b/common/content/configbase.js @@ -221,10 +221,9 @@ const ConfigBase = Class(ModuleBase, { Keyword color: red; Tag color: blue; - Usage - LineInfo - Usage>LineInfo display: none; - Usage:hover>LineInfo display: inline; + Usage position: relative; + Usage>LineInfo position: absolute; left: 100%; padding: 0 1em; background: white; + Usage:not(:hover)>LineInfo opacity: 0; width: 1px; overflow: hidden; !StatusLine color: white !important; background: black !important StatusLineBroken color: black !important; background: #FFa0a0 !important /* light-red */ diff --git a/common/content/dactyl.js b/common/content/dactyl.js index 70540692..938536fd 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -50,7 +50,8 @@ const Dactyl = Module("dactyl", { this.observers = {}; this.commands["dactyl.help"] = function (event) { - dactyl.help(event.originalTarget.textContent); + let elem = event.originalTarget; + dactyl.help(elem.getAttribute("tag") || elem.textContent); }; }, diff --git a/common/content/hints.js b/common/content/hints.js index df7d7327..fda1fbae 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -302,7 +302,9 @@ const Hints = Module("hints", { if (!isVisible(elem)) continue; - if (isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement])) + if (elem.hasAttributeNS(NS, "hint")) + [hint.text, hint.showText] = [elem.getAttributeNS(NS, "hint"), true]; + else if (isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement])) [hint.text, hint.showText] = this._getInputHint(elem, doc); else if (elem.firstElementChild instanceof HTMLImageElement && /^\s*$/.test(elem.textContent)) [hint.text, hint.showText] = [elem.firstElementChild.alt || elem.firstElementChild.title, true]; @@ -371,13 +373,18 @@ const Hints = Module("hints", { * @param {boolean} active Whether it is the currently active hint or not. */ _setClass: function _setClass(elem, active) { - let prefix = (elem.getAttributeNS(NS, "hl") || "") + " "; + if (!("dactylHighlight" in elem)) + elem.dactylHighlight = elem.getAttributeNS(NS, "highlight") || ""; + + let prefix = (elem.getAttributeNS(NS, "hl") || "") + " " + elem.dactylHighlight + " "; if (active) highlight.highlightNode(elem, prefix + "HintActive"); else if (active != null) highlight.highlightNode(elem, prefix + "HintElem"); - else - elem.removeAttributeNS(NS, "highlight"); + else { + highlight.highlightNode(elem, elem.dactylHighlight); + delete elem.dactylHighlight; + } }, /** @@ -402,7 +409,7 @@ const Hints = Module("hints", { hint.imgSpan.style.display = (valid ? "" : "none"); if (!valid) { - hint.elem.removeAttributeNS(NS, "highlight"); + this._setClass(hint.elem, null); continue inner; } @@ -471,7 +478,7 @@ const Hints = Module("hints", { for (let elem in util.evaluateXPath("//*[@dactyl:highlight='hints']", doc)) elem.parentNode.removeChild(elem); for (let i in util.range(start, end + 1)) - this._pageHints[i].elem.removeAttributeNS(NS, "highlight"); + this._setClass(this._pageHints[i].elem, null); } styles.removeSheet(true, "hint-positions"); diff --git a/common/content/mappings.js b/common/content/mappings.js index 8ab8fcc2..1a28a899 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -527,7 +527,9 @@ const Mappings = Module("mappings", { ? (passed by {template.helpLink("'passkeys'")}) : <>} {template.linkifyHelp(map.description + (map.rhs ? ": " + map.rhs : ""))} - ) + ), + help: function (map) let (char = array.compact(map.modes.map(function (m) m.char))[0]) + char === "n" ? map.name : char ? char + "_" + map.name : "" } } diff --git a/common/content/options.js b/common/content/options.js index 5759122b..ff527503 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -843,7 +843,8 @@ const Options = Module("options", { {opt.scope == Option.SCOPE_LOCAL ? (buffer local) : ""} {template.linkifyHelp(opt.description)} - ) + ), + help: function (opt) "'" + opt.name + "'" } }); diff --git a/common/modules/template.jsm b/common/modules/template.jsm index b0437aa9..68284b1b 100644 --- a/common/modules/template.jsm +++ b/common/modules/template.jsm @@ -79,14 +79,14 @@ const Template = Module("Template", { // }, - helpLink: function (topic, type) { + helpLink: function (topic, text, type) { if (services["dactyl:"].initialized && !set.has(services["dactyl:"].HELP_TAGS, topic)) - return <>{topic}; + return {text || topic}; XML.ignoreWhitespace = false; XML.prettyPrinting = false; - type = type || /^'.*'$/.test(topic) ? "HelpOpt" : - /^:\w/.test(topic) ? "HelpEx" : "HelpKey"; - return {topic} + type = type || (/^'.*'$/.test(topic) ? "HelpOpt" : + /^:\w/.test(topic) ? "HelpEx" : "HelpKey"); + return {text || topic} }, // if "processStrings" is true, any passed strings will be surrounded by " and @@ -314,17 +314,25 @@ const Template = Module("Template", { usage: function usage(iter, format) { XML.ignoreWhitespace = false; XML.prettyPrinting = false; let desc = format && format.description || function (item) template.linkifyHelp(item.description); + let help = format && format.help || function (item) item.name; + function sourceLink(frame) { + let source = template.sourceLink(frame); + source.@NS::hint = source.text(); + return source; + } // return { this.map(iter, function (item) - + ) }
{ - let (name = item.name || item.names[0], frame = item.definedAt) - !frame ? name : - {name} + <> + - Defined at {template.sourceLink(frame)} - } + { + let (name = item.name || item.names[0], frame = item.definedAt) + !frame ? name : + template.helpLink(help(item), name, "Title") + + Defined at {sourceLink(frame)} + } + {desc(item)}