diff options
| author | jez | 2011-01-03 20:24:55 +0800 | 
|---|---|---|
| committer | jez | 2011-01-04 16:16:47 +0800 | 
| commit | a2e3ac7910630ac1233d91dec58e1f6f5f63f6b9 (patch) | |
| tree | 2ec13ef3699055730adbafa3fef5e6ab550f978c | |
| parent | ac0ffe13d9f517da8d35d386c9c75f2f25b20039 (diff) | |
| download | vimium-a2e3ac7910630ac1233d91dec58e1f6f5f63f6b9.tar.bz2 | |
Add filtering for input and image elements, together with tests.
| -rw-r--r-- | linkHints.js | 71 | ||||
| -rw-r--r-- | test_harnesses/automated.html | 39 | 
2 files changed, 92 insertions, 18 deletions
| diff --git a/linkHints.js b/linkHints.js index ca5d29dd..53ad08b7 100644 --- a/linkHints.js +++ b/linkHints.js @@ -111,9 +111,9 @@ var linkHintsBase = {    /*     * Sets the data attributes of the marker. Does not need to handle styling -   * and positioning. MUST set the hintString property. +   * and positioning. MUST set the hintString and innerHTML properties.     */  -  setMarkerAttributes: function(linkHintNumber) {}, +  setMarkerAttributes: function(marker, linkHintNumber) {},    /*     * A hook for any necessary initialization for setMarkerAttributes.  Takes an @@ -310,8 +310,8 @@ var linkHintsBase = {    createMarkerFor: function(link, linkHintNumber) {      var marker = document.createElement("div");      marker.className = "internalVimiumHintMarker vimiumHintMarker"; -    this.setMarkerAttributes(marker, link, linkHintNumber); -    marker.innerHTML = this.spanWrap(marker.getAttribute("hintString")); +    marker.clickableItem = link.element; +    this.setMarkerAttributes(marker, linkHintNumber);      // Note: this call will be expensive if we modify the DOM in between calls.      var clientRect = link.rect; @@ -321,7 +321,6 @@ var linkHintsBase = {      marker.style.left = clientRect.left + window.scrollX / zoomFactor + "px";      marker.style.top = clientRect.top  + window.scrollY / zoomFactor + "px"; -    marker.clickableItem = link.element;      return marker;    }, @@ -356,8 +355,9 @@ function initializeLinkHints() {                visibleElements.length, settings.get('linkHintCharacters').length));        }, -      setMarkerAttributes: function(marker, link, linkHintNumber) { +      setMarkerAttributes: function(marker, linkHintNumber) {          var hintString = this.numberToHintString(linkHintNumber, this.digitsNeeded); +        marker.innerHTML = this.spanWrap(hintString);          marker.setAttribute("hintString", hintString);          return marker;        }, @@ -415,14 +415,57 @@ function initializeLinkHints() {        linkTextKeystrokeQueue: [], -      setMarkerAttributes: function(marker, link, linkHintNumber) { +      labelMap: {}, + +      /* +       * Generate a map of input element => label +       */ +      initSetMarkerAttributes: function() { +        var labels = document.querySelectorAll("label"); +        for (var i = 0; i < labels.length; i++) { +          var forElement = labels[i].getAttribute("for"); +          if (forElement) { +            var labelText = labels[i].textContent.trim(); +            // remove trailing : commonly found in labels +            if (labelText[labelText.length-1] == ":") +              labelText = labelText.substr(0, labelText.length-1); +            this.labelMap[forElement] = labelText; +          } +        } +      }, + +      setMarkerAttributes: function(marker, linkHintNumber) {          var hintString = (linkHintNumber + 1).toString(); -        var linkText = link.element.innerHTML.toLowerCase(); -        if (linkText == undefined)  -          linkText = ""; +        var linkText = ""; +        var showLinkText = false; +        var element = marker.clickableItem; +        // toLowerCase is necessary as html documents return 'IMG' +        // and xhtml documents return 'img' +        var nodeName = element.nodeName.toLowerCase(); + +        if (nodeName == "input") { +          if (this.labelMap[element.id]) { +            linkText = this.labelMap[element.id]; +            showLinkText = true; +          } else if (element.type != "password") { +            linkText = element.value; +          } +          // check if there is an image embedded in the <a> tag +        } else if (nodeName == "a" && !element.textContent.trim() +            && element.firstElementChild +            && element.firstElementChild.nodeName.toLowerCase() == "img") { +          showLinkText = true; +          linkText = element.firstElementChild.alt || element.firstElementChild.title; +        } + +        if (!linkText) { +          linkText = element.textContent || element.innerHTML; +        } +        linkText = linkText.trim().toLowerCase();          marker.setAttribute("hintString", hintString); +        marker.innerHTML = this.spanWrap(hintString +            + (showLinkText ? ": " + linkText : ""));          marker.setAttribute("linkText", linkText); -        return marker;        },        normalKeyDownHandler: function(event) { @@ -495,9 +538,8 @@ function initializeLinkHints() {            } else {              if (linkMarker.style.display == "none")                linkMarker.style.display = ""; -            var newHintText = (linksMatched.length+1).toString(); -            linkMarker.innerHTML = this.spanWrap(newHintText); -            linkMarker.setAttribute("hintString", newHintText); + +            this.setMarkerAttributes(linkMarker, linksMatched.length);              linkMarker.setAttribute("filtered", "false");              linksMatched.push(linkMarker);            } @@ -507,6 +549,7 @@ function initializeLinkHints() {        deactivateMode: function() {          this.linkTextKeystrokeQueue = []; +        this.labelMap = {};          this._super('deactivateMode')();        } diff --git a/test_harnesses/automated.html b/test_harnesses/automated.html index b11bebc1..d59a31d1 100644 --- a/test_harnesses/automated.html +++ b/test_harnesses/automated.html @@ -142,7 +142,15 @@              "<a id='1' style='position: absolute; top: 17px; left: 19px;'>test</a>" +              "<a id='2'>tress</a>" +              "<a id='3'>trait</a>" + -            "<a><img alt='alt text'/></a>"; +            "<a>track<img alt='alt text'/></a>" + +            "<a><img alt='alt text'/></a>" + +            "<a><img alt='alt text' title='some title'/></a>" + +            "<a><img title='some title'/></a>" + +            "<input type='text' value='some value'/>" + +            "<input type='password' value='some value'/>" + +            "<textarea>some text</textarea>" + +            "<label for='test-input'/>a label</label><input type='text' id='test-input' value='some value'/>" + +            "<label for='test-input-2'/>a label: </label><input type='text' id='test-input-2' value='some value'/>";            document.getElementById("test-div").innerHTML = testContent;            settings.values.filterLinkHints = "true";            initializeLinkHints(); @@ -152,10 +160,10 @@            document.getElementById("test-div").innerHTML = "";            linkHints.deactivateMode();            }), -        should("label the hints correctly", function() { -          for (var i = 0; i < 3; i++) +        should("label the plain text hints", function() { +          for (var i = 0; i < 4; i++)              assert.equal((i + 1).toString(), -              linkHints.hintMarkers[i].getAttribute("hintString")); +              linkHints.hintMarkers[i].textContent.toLowerCase());            }),          should("narrow the hints", function() {            linkHints.onKeyDownInMode(mockKeyboardEvent("T")); @@ -166,6 +174,29 @@              linkHints.hintMarkers[1].getAttribute("hintString"));            assert.equal("",              linkHints.hintMarkers[1].style.display); +          linkHints.onKeyDownInMode(mockKeyboardEvent("A")); +          assert.equal("2", +            linkHints.hintMarkers[3].getAttribute("hintString")); +          }), +        should("label the images", function() { +          assert.equal("5: alt text", +            linkHints.hintMarkers[4].textContent.toLowerCase()); +          assert.equal("6: alt text", +            linkHints.hintMarkers[5].textContent.toLowerCase()); +          assert.equal("7: some title", +            linkHints.hintMarkers[6].textContent.toLowerCase()); +          }), +        should("label the input elements", function() { +          assert.equal("8", +            linkHints.hintMarkers[7].textContent.toLowerCase()); +          assert.equal("9", +            linkHints.hintMarkers[8].textContent.toLowerCase()); +          assert.equal("10", +            linkHints.hintMarkers[9].textContent.toLowerCase()); +          assert.equal("11: a label", +            linkHints.hintMarkers[10].textContent.toLowerCase()); +          assert.equal("12: a label", +            linkHints.hintMarkers[11].textContent.toLowerCase());            })          ); | 
