diff options
| author | Stephen Blott | 2016-03-16 12:09:25 +0000 | 
|---|---|---|
| committer | Stephen Blott | 2016-03-28 05:58:42 +0100 | 
| commit | f49d4b2f5980d48e76fd2e32491c9793f5f6fdf8 (patch) | |
| tree | 12538bf3064deb3180034f2ac938d28c87af5b0e | |
| parent | 2a62e4811fc2360257dd99066b4caa3e95025cbf (diff) | |
| download | vimium-f49d4b2f5980d48e76fd2e32491c9793f5f6fdf8.tar.bz2 | |
Make scrollable elements selectable with hints.
Fixes #425.
Conflicts:
	content_scripts/scroller.coffee
| -rw-r--r-- | content_scripts/link_hints.coffee | 25 | ||||
| -rw-r--r-- | content_scripts/scroller.coffee | 13 | 
2 files changed, 26 insertions, 12 deletions
| diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee index 3088812b..994d99b5 100644 --- a/content_scripts/link_hints.coffee +++ b/content_scripts/link_hints.coffee @@ -190,6 +190,7 @@ LocalHints =      isClickable = false      onlyHasTabIndex = false      visibleElements = [] +    reason = null      # Insert area elements that provide click functionality to an img.      if tagName == "img" @@ -254,8 +255,15 @@ LocalHints =        when "label"          isClickable ||= element.control? and (@getVisibleClickable element.control).length == 0        when "body" -        isClickable ||= element == document.body and not document.hasFocus() and -          window.innerWidth > 3 and window.innerHeight > 3 +        isClickable ||= +          if element == document.body and not document.hasFocus() and +              window.innerWidth > 3 and window.innerHeight > 3 and +              document.body?.tagName.toLowerCase() != "frameset" +            reason = "Frame." +      when "div", "ol", "ul" +        isClickable ||= +          if Scroller.isScrollableElement element +            reason = "Scroll."      # Elements with tabindex are sometimes useful, but usually not. We can treat them as second class      # citizens when it improves UX, so take special note of them. @@ -267,7 +275,7 @@ LocalHints =      if isClickable        clientRect = DomUtils.getVisibleClientRect element, true        if clientRect != null -        visibleElements.push {element: element, rect: clientRect, secondClassCitizen: onlyHasTabIndex} +        visibleElements.push {element: element, rect: clientRect, secondClassCitizen: onlyHasTabIndex, reason}      visibleElements @@ -313,7 +321,7 @@ LocalHints =          # Subtract negativeRect from every rect in rects, and concatenate the arrays of rects that result.          rects = [].concat (rects.map (rect) -> Rect.subtract rect, negativeRect)...        if rects.length > 0 -        nonOverlappingElements.push {element: visibleElement.element, rect: rects[0]} +        nonOverlappingElements.push extend visibleElement, rect: rects[0]        else          # Every part of the element is covered by some other element, so just insert the whole element's          # rect. Except for elements with tabIndex set (second class citizens); these are often more trouble @@ -325,7 +333,7 @@ LocalHints =      hint.hasHref = hint.element.href? for hint in localHints      if Settings.get "filterLinkHints"        @withLabelMap (labelMap) => -        extend hint, @generateLinkText labelMap, hint.element for hint in localHints +        extend hint, @generateLinkText labelMap, hint for hint in localHints      localHints    # Generate a map of input element => label text, call a callback with it. @@ -342,7 +350,8 @@ LocalHints =          labelMap[forElement] = labelText      callback labelMap -  generateLinkText: (labelMap, element) -> +  generateLinkText: (labelMap, hint) -> +    element = hint.element      linkText = ""      showLinkText = false      # toLowerCase is necessary as html documents return "IMG" and xhtml documents return "img" @@ -362,8 +371,8 @@ LocalHints =          element.firstElementChild.nodeName.toLowerCase() == "img"        linkText = element.firstElementChild.alt || element.firstElementChild.title        showLinkText = true if linkText -    else if element == document.body -      linkText = "Frame." +    else if hint.reason? +      linkText = hint.reason        showLinkText = true      else        linkText = (element.textContent.trim() || element.innerHTML.trim())[...512] diff --git a/content_scripts/scroller.coffee b/content_scripts/scroller.coffee index f83d0e87..7b46bab0 100644 --- a/content_scripts/scroller.coffee +++ b/content_scripts/scroller.coffee @@ -77,12 +77,14 @@ doesScroll = (element, direction, amount, factor) ->    delta = getSign delta # 1 or -1    performScroll(element, direction, delta) and performScroll(element, direction, -delta) +isScrollableElement = (element, direction = "y", amount = 1, factor = 1) -> +  doesScroll(element, direction, amount, factor) and shouldScroll element, direction +  # From element and its parents, find the first which we should scroll and which does scroll.  findScrollableElement = (element, direction, amount, factor) -> -  while element != document.body and -    not (doesScroll(element, direction, amount, factor) and shouldScroll(element, direction)) -      element = (DomUtils.getContainingElement element) ? document.body -  if element == document.body then firstScrollableElement element else element +  while element != document.body and not isScrollableElement element, direction, amount, factor +    element = DomUtils.getContainingElement(element) ? document.body +  element  # On some pages, document.body is not scrollable.  Here, we search the document for the largest visible  # element which does scroll vertically. This is used to initialize activatedElement. See #1358. @@ -257,6 +259,9 @@ Scroller =      amount = getDimension(element,direction,pos) - element[scrollProperties[direction].axisName]      CoreScroller.scroll element, direction, amount +  isScrollableElement: (element) -> +    isScrollableElement element +    # Scroll the top, bottom, left and right of element into view.  The is used by visual mode to ensure the    # focus remains visible.    scrollIntoView: (element) -> | 
