diff options
author | Cihan Demirci <femnad@users.noreply.github.com> | 2020-09-25 16:20:16 +0300 |
---|---|---|
committer | Cihan Demirci <femnad@users.noreply.github.com> | 2020-10-10 22:34:21 +0300 |
commit | 1e6b6a382b5eb9b203b1ba6c61e743aad6d560f5 (patch) | |
tree | d1e9094f114803630cadeca4f1de0f92c87a3cc9 /src/content/presenters | |
parent | 1b77885e6d964f413c7a9820d956d04cb90ced6b (diff) |
Check scrollability by actually scrolling elements
Addresses #825
In addition to style checks, actually scroll an element (and restore
back) to verify that it can be scrolled.
Inspiration from [Vimium](https://github.com/philc/vimium) scrolling
code.
Diffstat (limited to 'src/content/presenters')
-rw-r--r-- | src/content/presenters/ScrollPresenter.ts | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/src/content/presenters/ScrollPresenter.ts b/src/content/presenters/ScrollPresenter.ts index a78e4ba..a8b2034 100644 --- a/src/content/presenters/ScrollPresenter.ts +++ b/src/content/presenters/ScrollPresenter.ts @@ -7,23 +7,28 @@ const SCROLL_DELTA_Y = 64; let scrolling = false; let lastTimeoutId: number | null = null; -const isScrollableStyle = (element: Element): boolean => { - const { overflowX, overflowY, overflow } = window.getComputedStyle(element); - return !( - overflowX !== "scroll" && - overflowX !== "auto" && - overflowY !== "scroll" && - overflowY !== "auto" && - overflow !== "scroll" && - overflow !== "auto" - ); -}; +// Check if an element is scrollable by actually scrolling it. +// Only checks for vertical scrollability. +// Credit: https://github.com/philc/vimium/blob/bdf654aebe6f570f427c5f7bc9592cad86e642b5/content_scripts/scroller.js#L93 +const canBeScrolled = (element: Element): boolean => { + let scrollTopBefore = element.scrollTop; + element.scrollBy(0, 1); + let scrollTopAfter = element.scrollTop; + element.scrollBy(0, -1) + return scrollTopBefore + 1 === scrollTopAfter +} -const doneScrolling = (element: Element): boolean => { - return ( - element.scrollTop + element.clientHeight >= element.scrollHeight - 5 && - element.scrollLeft + element.clientWidth >= element.scrollWidth - 5 - ); +// Check if the element's overflow and visibility permit scrolling. +// Credit: https://github.com/philc/vimium/blob/bdf654aebe6f570f427c5f7bc9592cad86e642b5/content_scripts/scroller.js#L74 +const isScrollableStyle = (element: Element): boolean => { + const { overflowX, overflowY, overflow, visibility } = window.getComputedStyle(element); + if ([overflow, overflowX, overflowY].includes("hidden")) { + return false; + } + if (["hidden", "collapse"].includes(visibility)) { + return false; + } + return canBeScrolled(element); }; // Find a visiable and scrollable element by depth-first search. Currently @@ -31,7 +36,7 @@ const doneScrolling = (element: Element): boolean => { // method is not cached. That does not cause performance issue because in the // most pages, the window is root element i,e, documentElement. const findScrollable = (element: Element): Element | null => { - if (isScrollableStyle(element) && !doneScrolling(element)) { + if (isScrollableStyle(element)) { return element; } @@ -48,7 +53,7 @@ const findScrollable = (element: Element): Element | null => { const scrollTarget = () => { if ( window.document.scrollingElement && - !doneScrolling(window.document.scrollingElement) + isScrollableStyle(window.document.scrollingElement) ) { return window.document.scrollingElement; } |