X-Git-Url: https://git.donarmstrong.com/dactyl.git?a=blobdiff_plain;f=common%2Fcontent%2Fhints.js;h=035f821327f9a9320fb257bfa734c6dbbafbb32c;hb=247daf849abc85f4cfb10fa358c62c8daf8db95b;hp=af09ad4dd499498ef16561971e67bb3a09af3c68;hpb=354a049cce8415487552ce405cce167b7071fe1f;p=dactyl.git diff --git a/common/content/hints.js b/common/content/hints.js index af09ad4..035f821 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -1,6 +1,6 @@ // Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2011 by Doug Kearns -// Copyright (c) 2008-2013 Kris Maglione +// Copyright (c) 2008-2014 Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. @@ -12,7 +12,7 @@ var HintSession = Class("HintSession", CommandMode, { get extendedMode() modes.HINTS, - init: function init(mode, opts = {}) { + init: function init(mode, opts={}) { init.supercall(this); if (!opts.window) @@ -24,7 +24,7 @@ var HintSession = Class("HintSession", CommandMode, { this.activeTimeout = null; // needed for hinttimeout > 0 this.continue = Boolean(opts.continue); this.docs = []; - this.hintKeys = DOM.Event.parse(options["hintkeys"]).map(DOM.Event.closure.stringify); + this.hintKeys = DOM.Event.parse(options["hintkeys"]).map(DOM.Event.bound.stringify); this.hintNumber = 0; this.hintString = opts.filter || ""; this.pageHints = []; @@ -36,8 +36,8 @@ var HintSession = Class("HintSession", CommandMode, { this.open(); this.top = opts.window || content; - this.top.addEventListener("resize", this.closure._onResize, true); - this.top.addEventListener("dactyl-commandupdate", this.closure._onResize, false, true); + this.top.addEventListener("resize", this.bound._onResize, true); + this.top.addEventListener("dactyl-commandupdate", this.bound._onResize, false, true); this.generate(); @@ -101,8 +101,8 @@ var HintSession = Class("HintSession", CommandMode, { if (hints.hintSession == this) hints.hintSession = null; if (this.top) { - this.top.removeEventListener("resize", this.closure._onResize, true); - this.top.removeEventListener("dactyl-commandupdate", this.closure._onResize, true); + this.top.removeEventListener("resize", this.bound._onResize, true); + this.top.removeEventListener("dactyl-commandupdate", this.bound._onResize, true); } this.removeHints(0); @@ -305,6 +305,8 @@ var HintSession = Class("HintSession", CommandMode, { return false; let computedStyle = doc.defaultView.getComputedStyle(elem, null); + if (!computedStyle) + return false; if (computedStyle.visibility != "visible" || computedStyle.display == "none") return false; return true; @@ -332,7 +334,7 @@ var HintSession = Class("HintSession", CommandMode, { __proto__: this.Hint }); - for (let hint in values(_hints)) { + for (let hint of _hints) { let { elem, rect } = hint; if (elem.hasAttributeNS(NS, "hint")) @@ -695,7 +697,7 @@ var HintSession = Class("HintSession", CommandMode, { updateValidNumbers: function updateValidNumbers(always) { let string = this.getHintString(this.hintNumber); for (let hint in values(this.validHints)) - hint.valid = always || hint.span.getAttribute("number").indexOf(string) == 0; + hint.valid = always || hint.span.getAttribute("number").startsWith(string); }, tab: function tab(previous) { @@ -748,19 +750,29 @@ var Hints = Module("hints", { let appContent = document.getElementById("appcontent"); if (appContent) - events.listen(appContent, "scroll", this.resizeTimer.closure.tell, false); + events.listen(appContent, "scroll", this.resizeTimer.bound.tell, false); const Mode = Hints.Mode; Mode.prototype.__defineGetter__("matcher", function () options.get("extendedhinttags").getKey(this.name, options.get("hinttags").matcher)); + function cleanLoc(loc) { + try { + let uri = util.newURI(loc); + if (uri.scheme == "mailto" && !~uri.path.indexOf("?")) + return uri.path; + } + catch (e) {} + return loc; + } + this.modes = {}; - this.addMode(";", "Focus hint", buffer.closure.focusElement); + this.addMode(";", "Focus hint", buffer.bound.focusElement); this.addMode("?", "Show information for hint", elem => buffer.showElementInfo(elem)); // TODO: allow for ! override to overwrite existing paths -- where? --djk this.addMode("s", "Save hint", elem => buffer.saveLink(elem, false)); this.addMode("f", "Focus frame", elem => dactyl.focus(elem.ownerDocument.defaultView)); - this.addMode("F", "Focus frame or pseudo-frame", buffer.closure.focusElement, isScrollable); + this.addMode("F", "Focus frame or pseudo-frame", buffer.bound.focusElement, isScrollable); this.addMode("o", "Follow hint", elem => buffer.followLink(elem, dactyl.CURRENT_TAB)); this.addMode("t", "Follow hint in a new tab", elem => buffer.followLink(elem, dactyl.NEW_TAB)); this.addMode("b", "Follow hint in a background tab", elem => buffer.followLink(elem, dactyl.NEW_BACKGROUND_TAB)); @@ -772,7 +784,7 @@ var Hints = Module("hints", { this.addMode("S", "Add a search keyword", elem => bookmarks.addSearchKeyword(elem)); this.addMode("v", "View hint source", (elem, loc) => buffer.viewSource(loc, false)); this.addMode("V", "View hint source in external editor", (elem, loc) => buffer.viewSource(loc, true)); - this.addMode("y", "Yank hint location", (elem, loc) => editor.setRegister(null, loc, true)); + this.addMode("y", "Yank hint location", (elem, loc) => editor.setRegister(null, cleanLoc(loc), true)); this.addMode("Y", "Yank hint description", elem => editor.setRegister(null, elem.textContent || "", true)); this.addMode("A", "Yank hint anchor url", function (elem) { let uri = elem.ownerDocument.documentURIObject.clone(); @@ -1042,7 +1054,7 @@ var Hints = Module("hints", { let indexOf = String.indexOf; if (options.get("hintmatching").has("transliterated")) - indexOf = Hints.closure.indexOf; + indexOf = Hints.bound.indexOf; switch (options["hintmatching"][0]) { case "contains" : return containsMatcher(hintString); @@ -1054,24 +1066,24 @@ var Hints = Module("hints", { return null; }, //}}} - open: function open(mode, opts = {}) { + open: function open(mode, opts={}) { this._extendedhintCount = opts.count; mappings.pushCommand(); - commandline.input(["Normal", mode], null, { + commandline.input(["Normal", mode], { autocomplete: false, completer: function (context) { context.compare = () => 0; context.completions = [[k, v.prompt] for ([k, v] in Iterator(hints.modes))]; }, - onCancel: mappings.closure.popCommand, + onCancel: mappings.bound.popCommand, onSubmit: function (arg) { if (arg) hints.show(arg, opts); mappings.popCommand(); }, onChange: function (arg) { - if (Object.keys(hints.modes).some(m => m != arg && m.indexOf(arg) == 0)) + if (Object.keys(hints.modes).some(m => m != arg && m.startsWith(arg))) return; this.accepted = true; @@ -1299,23 +1311,29 @@ var Hints = Module("hints", { }, { keepQuotes: true, + getKey: function (val, default_) - let (res = array.nth(this.value, re => let (match = re.exec(val)) match && match[0] == val, 0)) - res ? res.matcher : default_, + let (res = this.value.find(re => let (match = re.exec(val)) match && match[0] == val)) + res ? res.matcher + : default_, + parse: function parse(val) { let vals = parse.supercall(this, val); for (let value in values(vals)) value.matcher = DOM.compileMatcher(Option.splitList(value.result)); return vals; }, + testValues: function testValues(vals, validator) vals.every(re => Option.splitList(re).every(validator)), + validator: DOM.validateMatcher }); options.add(["hinttags", "ht"], "XPath or CSS selector strings of hintable elements for Hints mode", // Make sure to update the docs when you change this. - "stringlist", ":-moz-any-link,area,button,iframe,input:not([type=hidden]),label[for],select,textarea," + + "stringlist", ":-moz-any-link,area,button,iframe,input:not([type=hidden]):not([disabled])," + + "label[for],select,textarea," + "[onclick],[onmouseover],[onmousedown],[onmouseup],[oncommand]," + "[tabindex],[role=link],[role=button],[contenteditable=true]", { @@ -1335,7 +1353,7 @@ var Hints = Module("hints", { "asdfg;lkjh": "Home Row" }, validator: function (value) { - let values = DOM.Event.parse(value).map(DOM.Event.closure.stringify); + let values = DOM.Event.parse(value).map(DOM.Event.bound.stringify); return Option.validIf(array.uniq(values).length === values.length && values.length > 1, _("option.hintkeys.duplicate")); }