// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
/** @scope modules */
/** @instance hints */
let body = doc.body || doc.querySelector("body");
if (body) {
- let fragment = DOM(<div highlight="hints"/>, doc).appendTo(body);
+ let fragment = DOM(["div", { highlight: "hints" }], doc).appendTo(body);
fragment.style.height; // Force application of binding.
let container = doc.getAnonymousElementByAttribute(fragment[0], "anonid", "hints") || fragment[0];
- let baseNode = DOM(<span highlight="Hint" style="display: none;"/>, doc)[0];
+ let baseNode = DOM(["span", { highlight: "Hint", style: "display: none;" }], doc)[0];
let mode = this.hintMode;
let res = mode.matcher(doc);
if (elem.hasAttributeNS(NS, "hint"))
[hint.text, hint.showText] = [elem.getAttributeNS(NS, "hint"), true];
- else if (isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement]))
+ else if (isinstance(elem, [Ci.nsIDOMHTMLInputElement,
+ Ci.nsIDOMHTMLSelectElement,
+ Ci.nsIDOMHTMLTextAreaElement]))
[hint.text, hint.showText] = hints.getInputHint(elem, doc);
- else if (elem.firstElementChild instanceof HTMLImageElement && /^\s*$/.test(elem.textContent))
+ else if (elem.firstElementChild instanceof Ci.nsIDOMHTMLImageElement && /^\s*$/.test(elem.textContent))
[hint.text, hint.showText] = [elem.firstElementChild.alt || elem.firstElementChild.title, true];
else
hint.text = elem.textContent.toLowerCase();
let leftPos = Math.max((rect.left + offsetX), offsetX);
let topPos = Math.max((rect.top + offsetY), offsetY);
- if (elem instanceof HTMLAreaElement)
+ if (elem instanceof Ci.nsIDOMHTMLAreaElement)
[leftPos, topPos] = this.getAreaOffset(elem, leftPos, topPos);
hint.span.setAttribute("style", ["display: none; left:", leftPos, "px; top:", topPos, "px"].join(""));
let n = 5;
(function next() {
+ if (Cu.isDeadWrapper && Cu.isDeadWrapper(elem))
+ // Hint document has been unloaded.
+ return;
+
let hinted = n || this.validHints.some(function (h) h.elem === elem);
if (!hinted)
hints.setClass(elem, null);
/**
* Display the hints in pageHints that are still valid.
*/
+ showCount: 0,
show: function _show() {
+ let count = ++this.showCount;
let hintnum = 1;
let validHint = hints.hintMatcher(this.hintString.toLowerCase());
let activeHint = this.hintNumber || 1;
inner:
for (let i in (util.interruptibleRange(start, end + 1, 500))) {
+ if (this.showCount != count)
+ return;
+
let hint = this.pageHints[i];
hint.valid = validHint(hint.text);
if (!hint.valid)
continue inner;
- if (hint.text == "" && hint.elem.firstChild && hint.elem.firstChild instanceof HTMLImageElement) {
+ if (hint.text == "" && hint.elem.firstChild && hint.elem.firstChild instanceof Ci.nsIDOMHTMLImageElement) {
if (!hint.imgSpan) {
let rect = hint.elem.firstChild.getBoundingClientRect();
if (!rect)
continue;
- hint.imgSpan = DOM(<span highlight="Hint" dactyl:hl="HintImage" xmlns:dactyl={NS}/>, doc).css({
+ hint.imgSpan = DOM(["span", { highlight: "Hint", "dactyl:hl": "HintImage" }], doc).css({
display: "none",
left: (rect.left + offsetX) + "px",
top: (rect.top + offsetY) + "px",
let str = this.getHintString(hintnum);
let text = [];
- if (hint.elem instanceof HTMLInputElement)
+ if (hint.elem instanceof Ci.nsIDOMHTMLInputElement)
if (hint.elem.type === "radio")
text.push(UTF8(hint.elem.checked ? "⊙" : "○"));
else if (hint.elem.type === "checkbox")
this.modes = {};
this.addMode(";", "Focus hint", buffer.closure.focusElement);
this.addMode("?", "Show information for hint", function (elem) buffer.showElementInfo(elem));
+ // TODO: allow for ! override to overwrite existing paths -- where? --djk
this.addMode("s", "Save hint", 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, isScrollable);
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]) ||
+ function isScrollable(elem) isinstance(elem, [Ci.nsIDOMHTMLFrameElement,
+ Ci.nsIDOMHTMLIFrameElement]) ||
Buffer.isScrollable(elem, 0, true) || Buffer.isScrollable(elem, 0, false);
},
else {
for (let [, option] in Iterator(options["hintinputs"])) {
if (option == "value") {
- if (elem instanceof HTMLSelectElement) {
+ if (elem instanceof Ci.nsIDOMHTMLSelectElement) {
if (elem.selectedIndex >= 0)
return [elem.item(elem.selectedIndex).text.toLowerCase(), false];
}
}
else if (option == "label") {
if (elem.id) {
- let label = elem.ownerDocument.dactylLabels[elem.id];
+ let label = (elem.ownerDocument.dactylLabels || {})[elem.id];
+ // Urgh.
if (label)
return [label.textContent.toLowerCase(), true];
}
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]),select,textarea," +
+ "stringlist", ":-moz-any-link,area,button,iframe,input:not([type=hidden]),label[for],select,textarea," +
"[onclick],[onmouseover],[onmousedown],[onmouseup],[oncommand]," +
"[tabindex],[role=link],[role=button],[contenteditable=true]",
{
{
values: {
"0": "Follow the first hint as soon as typed text uniquely identifies it. Follow the selected hint on <Return>.",
- "1": "Follow the selected hint on <Return>.",
+ "1": "Follow the selected hint on <Return>."
}
});
}
});
-// vim: set fdm=marker sw=4 ts=4 et:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et: