aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dom_utils.coffee
diff options
context:
space:
mode:
authorStephen Blott2015-01-06 05:39:25 +0000
committerStephen Blott2015-01-06 05:39:25 +0000
commit30dee76c6ab1de9e2a62701dacffc29fa5be0866 (patch)
tree1aab7586b612a92222a4cfe85f4d4f5173e236bc /lib/dom_utils.coffee
parent3620fec662ab89bd4f7827e66deec49ff4d11b8e (diff)
parentfc2201b996e47ca06090e10e4ebfcd9f4b345fde (diff)
downloadvimium-30dee76c6ab1de9e2a62701dacffc29fa5be0866.tar.bz2
Merge pull request #1407 from smblott-github/post-1.46
Merge post-1.46 in its entirety
Diffstat (limited to 'lib/dom_utils.coffee')
-rw-r--r--lib/dom_utils.coffee100
1 files changed, 69 insertions, 31 deletions
diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee
index a0ac0bd3..ba5e279f 100644
--- a/lib/dom_utils.coffee
+++ b/lib/dom_utils.coffee
@@ -33,47 +33,24 @@ DomUtils =
makeXPath: (elementArray) ->
xpath = []
for element in elementArray
- xpath.push("//" + element, "//xhtml:" + element)
+ xpath.push(".//" + element, ".//xhtml:" + element)
xpath.join(" | ")
+ # Evaluates an XPath on the whole document, or on the contents of the fullscreen element if an element is
+ # fullscreen.
evaluateXPath: (xpath, resultType) ->
+ contextNode =
+ if document.webkitIsFullScreen then document.webkitFullscreenElement else document.documentElement
namespaceResolver = (namespace) ->
if (namespace == "xhtml") then "http://www.w3.org/1999/xhtml" else null
- document.evaluate(xpath, document.documentElement, namespaceResolver, resultType, null)
+ document.evaluate(xpath, contextNode, namespaceResolver, resultType, null)
#
# Returns the first visible clientRect of an element if it exists. Otherwise it returns null.
#
getVisibleClientRect: (element) ->
# Note: this call will be expensive if we modify the DOM in between calls.
- clientRects = ({
- top: clientRect.top, right: clientRect.right, bottom: clientRect.bottom, left: clientRect.left,
- width: clientRect.width, height: clientRect.height
- } for clientRect in element.getClientRects())
-
- for clientRect in clientRects
- if (clientRect.top < 0)
- clientRect.height += clientRect.top
- clientRect.top = 0
-
- if (clientRect.left < 0)
- clientRect.width += clientRect.left
- clientRect.left = 0
-
- if (clientRect.top >= window.innerHeight - 4 || clientRect.left >= window.innerWidth - 4)
- continue
-
- if (clientRect.width < 3 || clientRect.height < 3)
- continue
-
- # eliminate invisible elements (see test_harnesses/visibility_test.html)
- computedStyle = window.getComputedStyle(element, null)
- if (computedStyle.getPropertyValue('visibility') != 'visible' ||
- computedStyle.getPropertyValue('display') == 'none' ||
- computedStyle.getPropertyValue('opacity') == '0')
- continue
-
- return clientRect
+ clientRects = (Rect.copy clientRect for clientRect in element.getClientRects())
for clientRect in clientRects
# If the link has zero dimensions, it may be wrapping visible
@@ -86,11 +63,72 @@ DomUtils =
continue if (computedStyle.getPropertyValue('float') == 'none' &&
computedStyle.getPropertyValue('position') != 'absolute')
childClientRect = @getVisibleClientRect(child)
- continue if (childClientRect == null)
+ continue if childClientRect == null or childClientRect.width < 3 or childClientRect.height < 3
return childClientRect
+
+ else
+ clientRect = @cropRectToVisible clientRect
+
+ continue if clientRect == null or clientRect.width < 3 or clientRect.height < 3
+
+ # eliminate invisible elements (see test_harnesses/visibility_test.html)
+ computedStyle = window.getComputedStyle(element, null)
+ if (computedStyle.getPropertyValue('visibility') != 'visible' ||
+ computedStyle.getPropertyValue('display') == 'none')
+ continue
+
+ return clientRect
+
null
#
+ # Bounds the rect by the current viewport dimensions. If the rect is offscreen or has a height or width < 3
+ # then null is returned instead of a rect.
+ #
+ cropRectToVisible: (rect) ->
+ boundedRect = Rect.create(
+ Math.max(rect.left, 0)
+ Math.max(rect.top, 0)
+ rect.right
+ rect.bottom
+ )
+ if boundedRect.top >= window.innerHeight - 4 or boundedRect.left >= window.innerWidth - 4
+ null
+ else
+ boundedRect
+
+ #
+ # Get the client rects for the <area> elements in a <map> based on the position of the <img> element using
+ # the map. Returns an array of rects.
+ #
+ getClientRectsForAreas: (imgClientRect, areas) ->
+ rects = []
+ for area in areas
+ coords = area.coords.split(",").map((coord) -> parseInt(coord, 10))
+ shape = area.shape.toLowerCase()
+ if shape in ["rect", "rectangle"] # "rectangle" is an IE non-standard.
+ [x1, y1, x2, y2] = coords
+ else if shape in ["circle", "circ"] # "circ" is an IE non-standard.
+ [x, y, r] = coords
+ diff = r / Math.sqrt 2 # Gives us an inner square
+ x1 = x - diff
+ x2 = x + diff
+ y1 = y - diff
+ y2 = y + diff
+ else if shape == "default"
+ [x1, y1, x2, y2] = [0, 0, imgClientRect.width, imgClientRect.height]
+ else
+ # Just consider the rectangle surrounding the first two points in a polygon. It's possible to do
+ # something more sophisticated, but likely not worth the effort.
+ [x1, y1, x2, y2] = coords
+
+ rect = Rect.translate (Rect.create x1, y1, x2, y2), imgClientRect.left, imgClientRect.top
+ rect = @cropRectToVisible rect
+
+ rects.push {element: area, rect: rect} if rect and not isNaN rect.top
+ rects
+
+ #
# Selectable means that we should use the simulateSelect method to activate the element instead of a click.
#
# The html5 input types that should use simulateSelect are: