diff options
| -rw-r--r-- | content_scripts/link_hints.coffee | 51 | ||||
| -rw-r--r-- | lib/dom_utils.coffee | 28 |
2 files changed, 44 insertions, 35 deletions
diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee index 18e9741d..dd359a70 100644 --- a/content_scripts/link_hints.coffee +++ b/content_scripts/link_hints.coffee @@ -131,19 +131,23 @@ LinkHints = # getVisibleClickableElements: -> elements = Array::slice.call(document.documentElement.getElementsByTagName "*") - resultSet = [] + visibleElements = [] for element in elements tagName = element.tagName.toLowerCase() + isClickable = false # Insert area elements that provide click functionality to an img. if tagName == "img" mapName = element.getAttribute "usemap" if mapName + imgClientRects = element.getClientRects() mapName = mapName.replace(/^#/, "").replace("\"", "\\\"") map = document.querySelector "map[name=\"#{mapName}\"]" - areas = if map then Array::slice.call(map.getElementsByTagName "area") else [] - resultSet = resultSet.concat areas + if map and imgClientRects.length > 0 + areas = map.getElementsByTagName "area" + areaRects = DomUtils.getClientRectsForAreas imgClientRects[0], areas + visibleElements = visibleElements.concat areaRects # Check for attributes that make an element clickable regardless of its tagName. if (element.hasAttribute "onclick" or @@ -151,46 +155,23 @@ LinkHints = element.getAttribute "role" in ["button", "link"] or element.getAttribute("class")?.toLowerCase().indexOf("button") >= 0 or element.getAttribute("contentEditable")?.toLowerCase() in ["", "contentEditable", "true"]) - resultSet.push element - continue + isClickable = true + # Check for tagNames which are natively clickable. switch tagName when "a" - resultSet.push element + isClickable = true when "textarea", "input" unless (tagName == "input" and element.getAttribute("type")?.toLowerCase() == "hidden") or element.disabled or (element.readOnly and DomUtils.isSelectable element) - resultSet.push element + isClickable = true when "button", "select" - resultSet.push element unless element.disabled - - visibleElements = [] + isClickable = not element.disabled - # Find all visible clickable elements. - for element in resultSet - clientRect = DomUtils.getVisibleClientRect(element, clientRect) - if (clientRect != null) - visibleElements.push({element: element, rect: clientRect}) - - if (element.localName == "area") - map = element.parentElement - continue unless map - img = document.querySelector("img[usemap='#" + map.getAttribute("name") + "']") - continue unless img - imgClientRects = img.getClientRects() - continue if (imgClientRects.length == 0) - c = element.coords.split(/,/) - coords = [parseInt(c[0], 10), parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10)] - rect = { - top: imgClientRects[0].top + coords[1], - left: imgClientRects[0].left + coords[0], - right: imgClientRects[0].left + coords[2], - bottom: imgClientRects[0].top + coords[3], - width: coords[2] - coords[0], - height: coords[3] - coords[1] - } - - visibleElements.push({element: element, rect: rect}) + continue unless isClickable # If the element isn't clickable, do nothing. + clientRect = DomUtils.getVisibleClientRect element + if clientRect != null + visibleElements.push {element: element, rect: clientRect} visibleElements diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index a0ac0bd3..3d7e805f 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -90,6 +90,34 @@ DomUtils = return childClientRect null + getClientRectsForAreas: (imgClientRect, areas) -> + rects = [] + for area in areas + coords = area.coords.split(",").map((coord) -> parseInt(coord, 10)) + shape = area.shape.toLowerCase() + if shape == "rect" + [x1, y1, x2, y2] = coords + else if shape == "circle" + [x, y, r] = coords + x1 = x - r + x2 = x + r + y1 = y - r + y2 = y + r + else # For polygons and unknown shapes, don't return a rectangle. + # TODO(mrmr1993): revisit this. + continue + + rect = + top: imgClientRect.top + y1 + left: imgClientRect.left + x1 + right: imgClientRect.left + x2 + bottom: imgClientRect.top + y2 + width: x2 - x1 + height: y2 - y1 + + rects.push {element: area, rect: rect} unless isNaN rect.top + rects + # # Selectable means that we should use the simulateSelect method to activate the element instead of a click. # |
