// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2010 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. "use strict"; /** @scope modules */ /** @instance hints */ var Hints = Module("hints", { init: function init() { const self = this; this._hintMode = null; this._submode = ""; // used for extended mode, can be "o", "t", "y", etc. this._hintString = ""; // the typed string part of the hint is in this string this._hintNumber = 0; // only the numerical part of the hint this._usedTabKey = false; // when we used to select an element this.prevInput = ""; // record previous user input type, "text" || "number" this._extendedhintCount = null; // for the count argument of Mode#action (extended hint only) this._pageHints = []; this._validHints = []; // store the indices of the "hints" array with valid elements this._activeTimeout = null; // needed for hinttimeout > 0 this._canUpdate = false; // keep track of the documents which we generated the hints for // this._docs = { doc: document, start: start_index in hints[], end: end_index in hints[] } this._docs = []; this._resizeTimer = Timer(100, 500, function () { if (self._top && (modes.extended & modes.HINTS)) { self._removeHints(0, true); self._generate(self._top); self._showHints(); } }); let appContent = document.getElementById("appcontent"); if (appContent) events.addSessionListener(appContent, "scroll", this._resizeTimer.closure.tell, false); const Mode = Hints.Mode; Mode.defaultValue("tags", function () function () options["hinttags"]); Mode.prototype.__defineGetter__("xpath", function () options.get("extendedhinttags").getKey(this.name, this.tags())); this._hintModes = {}; this.addMode(";", "Focus hint", buffer.closure.focusElement); this.addMode("?", "Show information for hint", function (elem) buffer.showElementInfo(elem)); this.addMode("s", "Save hint", function (elem) buffer.saveLink(elem, true)); this.addMode("a", "Save hint with prompt", function (elem) buffer.saveLink(elem, false)); this.addMode("f", "Focus frame", function (elem) dactyl.focus(elem.ownerDocument.defaultView)); this.addMode("F", "Focus frame or pseudo-frame", buffer.closure.focusElement, null, isScrollable); this.addMode("o", "Follow hint", function (elem) buffer.followLink(elem, dactyl.CURRENT_TAB)); this.addMode("t", "Follow hint in a new tab", function (elem) buffer.followLink(elem, dactyl.NEW_TAB)); this.addMode("b", "Follow hint in a background tab", function (elem) buffer.followLink(elem, dactyl.NEW_BACKGROUND_TAB)); this.addMode("w", "Follow hint in a new window", function (elem) buffer.followLink(elem, dactyl.NEW_WINDOW)); this.addMode("O", "Generate an ‘:open URL’ prompt", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)); this.addMode("T", "Generate a ‘:tabopen URL’ prompt", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)); this.addMode("W", "Generate a ‘:winopen URL’ prompt", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)); this.addMode("S", "Add a search keyword", function (elem) bookmarks.addSearchKeyword(elem)); this.addMode("v", "View hint source", function (elem, loc) buffer.viewSource(loc, false)); this.addMode("V", "View hint source in external editor", function (elem, loc) buffer.viewSource(loc, true)); this.addMode("y", "Yank hint location", function (elem, loc) dactyl.clipboardWrite(loc, true)); this.addMode("Y", "Yank hint description", function (elem) dactyl.clipboardWrite(elem.textContent || "", true)); this.addMode("c", "Open context menu", function (elem) buffer.openContextMenu(elem)); this.addMode("i", "Show image", function (elem) dactyl.open(elem.src)); this.addMode("I", "Show image in a new tab", function (elem) dactyl.open(elem.src, dactyl.NEW_TAB)); function isScrollable(elem) isinstance(elem, [HTMLFrameElement, HTMLIFrameElement]) || Buffer.isScrollable(elem, 0, true) || Buffer.isScrollable(elem, 0, false); }, /** * Clear any timeout which might be active after pressing a number */ clearTimeout: function () { if (this._activeTimeout) this._activeTimeout.cancel(); this._activeTimeout = null; }, /** * Reset hints, so that they can be cleanly used again. */ _reset: function _reset(slight) { if (!slight) { this.__reset(); this.prevInput = ""; this.escNumbers = false; this._usedTabKey = false; this._canUpdate = false; this._hintNumber = 0; this._hintString = ""; statusline.updateInputBuffer(""); commandline.widgets.command = ""; } this._pageHints = []; this._validHints = []; this._docs = []; this.clearTimeout(); }, __reset: function __reset() { if (!this._usedTabKey) this._hintNumber = 0; if (this._continue && this._validHints.length <= 1) { this._hintString = ""; commandline.widgets.command = this._hintString; this._showHints(); } this._updateStatusline(); }, /** * Display the current status to the user. */ _updateStatusline: function _updateStatusline() { statusline.updateInputBuffer((hints.escNumbers ? options["mapleader"] : "") + (this._hintNumber ? this.getHintString(this._hintNumber) : "")); }, /** * Get a hint for "input", "textarea" and "select". * * Tries to use