diff options
| author | Jez Ng | 2012-01-09 16:47:17 +0800 | 
|---|---|---|
| committer | Jez Ng | 2012-01-09 17:14:49 +0800 | 
| commit | 34bc211a866e3623bdc461d4cf183b08bf229822 (patch) | |
| tree | c87926050262968dd1451825f823041e6c2af109 /linkHints.js | |
| parent | a89f2dbd45871487efb998efc466765a42f11311 (diff) | |
| download | vimium-34bc211a866e3623bdc461d4cf183b08bf229822.tar.bz2 | |
Consider all clientRects when checking for visibility.
Fixes issue #235.
Diffstat (limited to 'linkHints.js')
| -rw-r--r-- | linkHints.js | 81 | 
1 files changed, 42 insertions, 39 deletions
| diff --git a/linkHints.js b/linkHints.js index 604e91e9..d37d2d7c 100644 --- a/linkHints.js +++ b/linkHints.js @@ -118,28 +118,10 @@ var linkHints = {      // Find all visible clickable elements.      for (var i = 0, count = resultSet.snapshotLength; i < count; i++) {        var element = resultSet.snapshotItem(i); -      // Note: this call will be expensive if we modify the DOM in between calls. -      var clientRect = element.getClientRects()[0]; - -      if (this.isVisible(element, clientRect)) +      var clientRect = this.getVisibleClientRect(element, clientRect); +      if (clientRect !== null)          visibleElements.push({element: element, rect: clientRect}); -      // If the link has zero dimensions, it may be wrapping visible -      // but floated elements. Check for this. -      if (clientRect && (clientRect.width == 0 || clientRect.height == 0)) { -        for (var j = 0, childrenCount = element.children.length; j < childrenCount; j++) { -          var computedStyle = window.getComputedStyle(element.children[j], null); -          // Ignore child elements which are not floated and not absolutely positioned for parent elements with zero width/height -          if (computedStyle.getPropertyValue('float') == 'none' && computedStyle.getPropertyValue('position') != 'absolute') -            continue; -          var childClientRect = element.children[j].getClientRects()[0]; -          if (!this.isVisible(element.children[j], childClientRect)) -            continue; -          visibleElements.push({element: element.children[j], rect: childClientRect}); -          break; -        } -      } -        if (element.localName === "area") {          var map = element.parentElement;          var img = document.querySelector("img[usemap='#" + map.getAttribute("name") + "']"); @@ -161,26 +143,47 @@ var linkHints = {      return visibleElements;    }, -  /* -   * Returns true if element is visible. +  /** +   * Returns the first visible clientRect of an element if it exists. Otherwise it returns null.     */ -  isVisible: function(element, clientRect) { -    // Exclude links which have just a few pixels on screen, because the link hints won't show for them -    // anyway. -    if (!clientRect || clientRect.top < 0 || clientRect.top >= window.innerHeight - 4 || -        clientRect.left < 0 || clientRect.left  >= window.innerWidth - 4) -      return false; - -    if (clientRect.width < 3 || clientRect.height < 3) -      return false; - -    // eliminate invisible elements (see test_harnesses/visibility_test.html) -    var computedStyle = window.getComputedStyle(element, null); -    if (computedStyle.getPropertyValue('visibility') != 'visible' || -        computedStyle.getPropertyValue('display') == 'none') -      return false; - -    return true; +  getVisibleClientRect: function(element) { +    // Note: this call will be expensive if we modify the DOM in between calls. +    var clientRects = element.getClientRects(); + +    for (var i = 0, len = clientRects.length; i < len; i++) { +      // Exclude links which have just a few pixels on screen, because the link hints won't show for them +      // anyway. +      if (clientRects[i].top < 0 || clientRects[i].top >= window.innerHeight - 4 || +          clientRects[i].left < 0 || clientRects[i].left  >= window.innerWidth - 4) +        continue; + +      if (clientRects[i].width < 3 || clientRects[i].height < 3) +        continue; + +      // eliminate invisible elements (see test_harnesses/visibility_test.html) +      var computedStyle = window.getComputedStyle(element, null); +      if (computedStyle.getPropertyValue('visibility') != 'visible' || +          computedStyle.getPropertyValue('display') == 'none') +        continue; + +      // If the link has zero dimensions, it may be wrapping visible +      // but floated elements. Check for this. +      if (clientRects[i].width == 0 || clientRects[i].height == 0) { +        for (var j = 0, childrenCount = element.children.length; j < childrenCount; j++) { +          var computedStyle = window.getComputedStyle(element.children[j], null); +          // Ignore child elements which are not floated and not absolutely positioned for parent elements with zero width/height +          if (computedStyle.getPropertyValue('float') == 'none' && computedStyle.getPropertyValue('position') != 'absolute') +            continue; +          var childClientRect = this.getVisibleClientRect(element.children[j]); +          if (childClientRect === null) +            continue; +          return childClientRect; +        } +      } + +      return clientRects[i]; +    }; +    return null;    },    /* | 
