]> git.donarmstrong.com Git - dactyl.git/blobdiff - common/content/hints.js
Import r6948 from upstream hg supporting Firefox up to 24.*
[dactyl.git] / common / content / hints.js
index 96fe44acbbbfa5399fa2a7aed63596d6fa999051..d151c2c3d688f439cc802ea732309d23ec896495 100644 (file)
@@ -1,10 +1,10 @@
 // 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 */
@@ -312,11 +312,11 @@ var HintSession = Class("HintSession", CommandMode, {
 
         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);
@@ -337,9 +337,11 @@ var HintSession = Class("HintSession", CommandMode, {
 
                 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();
@@ -349,7 +351,7 @@ var HintSession = Class("HintSession", CommandMode, {
                 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(""));
@@ -490,6 +492,10 @@ var HintSession = Class("HintSession", CommandMode, {
 
         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);
@@ -569,7 +575,9 @@ var HintSession = Class("HintSession", CommandMode, {
     /**
      * 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;
@@ -581,19 +589,22 @@ var HintSession = Class("HintSession", CommandMode, {
 
         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",
@@ -605,7 +616,7 @@ var HintSession = Class("HintSession", CommandMode, {
 
                 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")
@@ -746,6 +757,7 @@ var Hints = Module("hints", {
         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);
@@ -771,7 +783,8 @@ var Hints = Module("hints", {
         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);
     },
 
@@ -840,7 +853,7 @@ var Hints = Module("hints", {
         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];
                     }
@@ -856,7 +869,8 @@ var Hints = Module("hints", {
                 }
                 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];
                     }
@@ -1301,7 +1315,7 @@ var Hints = Module("hints", {
         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]",
             {
@@ -1338,7 +1352,7 @@ var Hints = Module("hints", {
             {
                 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>."
                 }
             });
 
@@ -1375,4 +1389,4 @@ var Hints = Module("hints", {
     }
 });
 
-// vim: set fdm=marker sw=4 ts=4 et:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et: