aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content_scripts/link_hints.coffee2
-rw-r--r--content_scripts/vimium_frontend.coffee2
-rw-r--r--lib/dom_utils.coffee14
-rw-r--r--tests/dom_tests/dom_utils_test.coffee28
4 files changed, 25 insertions, 21 deletions
diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee
index 51e5df35..3fa6f20f 100644
--- a/content_scripts/link_hints.coffee
+++ b/content_scripts/link_hints.coffee
@@ -197,7 +197,7 @@ LinkHints =
isClickable = onlyHasTabIndex = true
if isClickable
- clientRect = DomUtils.getVisibleClientRect element
+ clientRect = DomUtils.getVisibleClientRect element, true
if clientRect != null
visibleElements.push {element: element, rect: clientRect, secondClassCitizen: onlyHasTabIndex}
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index e7aea163..967e1e1e 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -395,7 +395,7 @@ extend window,
visibleInputs =
for i in [0...resultSet.snapshotLength] by 1
element = resultSet.snapshotItem i
- rect = DomUtils.getVisibleClientRect element
+ rect = DomUtils.getVisibleClientRect element, true
continue if rect == null
{ element: element, rect: rect }
diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee
index e0ab09e2..30b9f68c 100644
--- a/lib/dom_utils.coffee
+++ b/lib/dom_utils.coffee
@@ -55,21 +55,25 @@ DomUtils =
#
# Returns the first visible clientRect of an element if it exists. Otherwise it returns null.
#
- getVisibleClientRect: (element) ->
+ # WARNING: If testChildren = true then the rects of visible (eg. floated) children may be returned instead.
+ # This is used for LinkHints and focusInput, **BUT IS UNSUITABLE FOR MOST OTHER PURPOSES**.
+ #
+ getVisibleClientRect: (element, testChildren = false) ->
# Note: this call will be expensive if we modify the DOM in between calls.
clientRects = (Rect.copy clientRect for clientRect in element.getClientRects())
for clientRect in clientRects
- # If the link has zero dimensions, it may be wrapping visible
- # but floated elements. Check for this.
- if (clientRect.width == 0 || clientRect.height == 0)
+ # If the link has zero dimensions, it may be wrapping visible but floated elements. Check for this.
+ if (clientRect.width == 0 or clientRect.height == 0) and testChildren
for child in element.children
computedStyle = window.getComputedStyle(child, null)
# Ignore child elements which are not floated and not absolutely positioned for parent elements with
# zero width/height
+ # NOTE(mrmr1993): This ignores floated/absolutely positioned descendants nested within inline
+ # children.
continue if (computedStyle.getPropertyValue('float') == 'none' &&
computedStyle.getPropertyValue('position') != 'absolute')
- childClientRect = @getVisibleClientRect(child)
+ childClientRect = @getVisibleClientRect child, true
continue if childClientRect == null or childClientRect.width < 3 or childClientRect.height < 3
return childClientRect
diff --git a/tests/dom_tests/dom_utils_test.coffee b/tests/dom_tests/dom_utils_test.coffee
index ad8bde3c..e98dc958 100644
--- a/tests/dom_tests/dom_utils_test.coffee
+++ b/tests/dom_tests/dom_utils_test.coffee
@@ -4,19 +4,19 @@ context "Check visibility",
document.getElementById("test-div").innerHTML = """
<div id='foo'>test</div>
"""
- assert.isTrue (DomUtils.getVisibleClientRect document.getElementById 'foo') != null
+ assert.isTrue (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true) != null
should "detect display:none links as hidden", ->
document.getElementById("test-div").innerHTML = """
<a id='foo' style='display:none'>test</a>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)
should "detect visibility:hidden links as hidden", ->
document.getElementById("test-div").innerHTML = """
<a id='foo' style='visibility:hidden'>test</a>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)
should "detect elements nested in display:none elements as hidden", ->
document.getElementById("test-div").innerHTML = """
@@ -24,7 +24,7 @@ context "Check visibility",
<a id='foo'>test</a>
</div>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)
should "detect links nested in visibility:hidden elements as hidden", ->
document.getElementById("test-div").innerHTML = """
@@ -32,23 +32,23 @@ context "Check visibility",
<a id='foo'>test</a>
</div>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)
should "detect links outside viewport as hidden", ->
document.getElementById("test-div").innerHTML = """
<a id='foo' style='position:absolute;top:-2000px'>test</a>
<a id='bar' style='position:absolute;left:2000px'>test</a>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'bar'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'bar'), true)
should "detect links only partially outside viewport as visible", ->
document.getElementById("test-div").innerHTML = """
<a id='foo' style='position:absolute;top:-10px'>test</a>
<a id='bar' style='position:absolute;left:-10px'>test</a>
"""
- assert.isTrue (DomUtils.getVisibleClientRect document.getElementById 'foo') != null
- assert.isTrue (DomUtils.getVisibleClientRect document.getElementById 'bar') != null
+ assert.isTrue (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true) != null
+ assert.isTrue (DomUtils.getVisibleClientRect (document.getElementById 'bar'), true) != null
should "detect links that contain only floated / absolutely-positioned divs as visible", ->
document.getElementById("test-div").innerHTML = """
@@ -56,14 +56,14 @@ context "Check visibility",
<div style='float:left'>test</div>
</a>
"""
- assert.isTrue (DomUtils.getVisibleClientRect document.getElementById 'foo') != null
+ assert.isTrue (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true) != null
document.getElementById("test-div").innerHTML = """
<a id='foo'>
<div style='position:absolute;top:0;left:0'>test</div>
</a>
"""
- assert.isTrue (DomUtils.getVisibleClientRect document.getElementById 'foo') != null
+ assert.isTrue (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true) != null
should "detect links that contain only invisible floated divs as invisible", ->
document.getElementById("test-div").innerHTML = """
@@ -71,7 +71,7 @@ context "Check visibility",
<div style='float:left;visibility:hidden'>test</div>
</a>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)
should "detect links inside opacity:0 elements as visible", ->
# XXX This is an expected failure. See issue #16.
@@ -80,7 +80,7 @@ context "Check visibility",
<a id='foo'>test</a>
</div>
"""
- assert.isTrue (DomUtils.getVisibleClientRect document.getElementById 'foo') != null
+ assert.isTrue (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true) != null
should "Detect links within SVGs as visible", ->
# XXX this is an expected failure
@@ -91,4 +91,4 @@ context "Check visibility",
</a>
</svg>
"""
- assert.equal null, DomUtils.getVisibleClientRect document.getElementById 'foo'
+ assert.equal null, (DomUtils.getVisibleClientRect (document.getElementById 'foo'), true)