// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 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. /** @scope modules */ /** @instance hints */ const Hints = Module("hints", { requires: ["config"], init: function () { 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 = []; const Mode = Hints.Mode; Mode.defaultValue("tags", function () function () options.hinttags); function extended() options.extendedhinttags; function images() util.makeXPath(["img"]); this._hintModes = { ";": Mode("Focus hint", function (elem) buffer.focusElement(elem), extended), "?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), extended), s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)), a: Mode("Save hint with prompt", function (elem) buffer.saveLink(elem, false)), f: Mode("Focus frame", function (elem) elem.ownerDocument.defaultView.focus(), function () util.makeXPath(["body"])), o: Mode("Follow hint", function (elem) buffer.followLink(elem, liberator.CURRENT_TAB)), t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, liberator.NEW_TAB)), b: Mode("Follow hint in a background tab", function (elem) buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB)), w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, liberator.NEW_WINDOW), extended), F: Mode("Open multiple hints in tabs", followAndReshow), O: Mode("Generate an ':open URL' using hint", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)), T: Mode("Generate a ':tabopen URL' using hint", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)), W: Mode("Generate a ':winopen URL' using hint", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)), v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), extended), V: Mode("View hint source in external editor", function (elem, loc) buffer.viewSource(loc, true), extended), y: Mode("Yank hint location", function (elem, loc) util.copyToClipboard(loc, true)), Y: Mode("Yank hint description", function (elem) util.copyToClipboard(elem.textContent || "", true), extended), c: Mode("Open context menu", function (elem) buffer.openContextMenu(elem), extended), i: Mode("Show image", function (elem) liberator.open(elem.src), images), I: Mode("Show image in a new tab", function (elem) liberator.open(elem.src, liberator.NEW_TAB), images) }; /** * Follows the specified hint and then reshows all hints. Used to open * multiple hints in succession. * * @param {Node} elem The selected hint. */ function followAndReshow(elem) { buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB); // TODO: Maybe we find a *simple* way to keep the hints displayed rather than // showing them again, or is this short flash actually needed as a "usability // feature"? --mst hints.show("F"); } }, /** * Reset hints, so that they can be cleanly used again. */ _reset: function () { statusline.updateInputBuffer(""); this._hintString = ""; this._hintNumber = 0; this._usedTabKey = false; this._prevInput = ""; this._pageHints = []; this._validHints = []; this._canUpdate = false; this._docs = []; hints.escNumbers = false; if (this._activeTimeout) clearTimeout(this._activeTimeout); this._activeTimeout = null; }, /** * Display the current status to the user. */ _updateStatusline: function () { statusline.updateInputBuffer((hints.escNumbers ? mappings.getMapLeader() : "") + (this._hintNumber || "")); }, /** * Get a hint for "input", "textarea" and "select". * * Tries to use