From 1f678d685eb39e5269cfe8f87ac99522aa1b5200 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Fri, 7 Nov 2014 10:58:39 +0000
Subject: Smooth scrolling.
---
background_scripts/settings.coffee | 1 +
content_scripts/scroller.coffee | 83 ++++++++++++++++++++++++++++------
content_scripts/vimium_frontend.coffee | 12 ++---
pages/options.coffee | 1 +
pages/options.html | 9 ++++
5 files changed, 85 insertions(+), 21 deletions(-)
diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee
index d6e8fcde..f68a51d7 100644
--- a/background_scripts/settings.coffee
+++ b/background_scripts/settings.coffee
@@ -61,6 +61,7 @@ root.Settings = Settings =
# or strings
defaults:
scrollStepSize: 60
+ smoothScroll: false
keyMappings: "# Insert your prefered key mappings here."
linkHintCharacters: "sadfjklewcmpgh"
linkHintNumbers: "0123456789"
diff --git a/content_scripts/scroller.coffee b/content_scripts/scroller.coffee
index b3a14c78..4d1109c9 100644
--- a/content_scripts/scroller.coffee
+++ b/content_scripts/scroller.coffee
@@ -5,8 +5,10 @@ window.Scroller = root = {}
# input elements. This mechanism allows us to decide whether to scroll a div or to scroll the whole document.
#
activatedElement = null
+settings = null
-root.init = ->
+root.init = (frontendSettings) ->
+ settings = frontendSettings
handlerStack.push DOMActivate: -> activatedElement = event.target
scrollProperties =
@@ -36,11 +38,13 @@ getDimension = (el, direction, name) ->
ensureScrollChange = (direction, changeFn) ->
axisName = scrollProperties[direction].axisName
element = activatedElement
+ progress = 0
loop
oldScrollValue = element[axisName]
# Elements with `overflow: hidden` should not be scrolled.
overflow = window.getComputedStyle(element).getPropertyValue("overflow-#{direction}")
changeFn(element, axisName) unless overflow == "hidden"
+ progress += element[axisName] - oldScrollValue
break unless element[axisName] == oldScrollValue && element != document.body
# we may have an orphaned element. if so, just scroll the body element.
element = element.parentElement || document.body
@@ -51,6 +55,53 @@ ensureScrollChange = (direction, changeFn) ->
rect = activatedElement.getBoundingClientRect()
if (rect.bottom < 0 || rect.top > window.innerHeight || rect.right < 0 || rect.left > window.innerWidth)
activatedElement = element
+ # Return the amount by which the scroll position has changed.
+ return progress
+
+# Scroll by a relative amount in some direction, possibly smoothly.
+# The constants below seem to roughly match chrome's scroll speeds for both short and long scrolls.
+# TODO(smblott) For very-long scrolls, chrome implements a soft landing; we don't.
+doScrollBy = do ->
+ interval = 10 # Update interval (in ms).
+ duration = 120 # This must be a multiple of interval (also in ms).
+ fudgeFactor = 25
+ timer = null
+
+ clearTimer = ->
+ if timer
+ clearInterval timer
+ timer = null
+
+ # Allow a bit longer for longer scrolls.
+ calculateExtraDuration = (amount) ->
+ extra = fudgeFactor * Math.log Math.abs amount
+ # Ensure we have a multiple of interval.
+ return interval * Math.round (extra / interval)
+
+ scroller = (direction,amount) ->
+ return ensureScrollChange direction, (element, axisName) -> element[axisName] += amount
+
+ (direction,amount,wantSmooth) ->
+ clearTimer()
+
+ unless wantSmooth and settings.get "smoothScroll"
+ scroller direction, amount
+ return
+
+ requiredTicks = (duration + calculateExtraDuration amount) / interval
+ # Round away from 0, so that we don't leave any requested scroll amount unscrolled.
+ rounder = (if 0 <= amount then Math.ceil else Math.floor)
+ delta = rounder(amount / requiredTicks)
+
+ ticks = 0
+ ticker = ->
+ # If we haven't scrolled by the expected amount, then we've hit the top, bottom or side of the activated
+ # element, so stop scrolling.
+ if scroller(direction, delta) != delta or ++ticks == requiredTicks
+ clearTimer()
+
+ timer = setInterval ticker, interval
+ ticker()
# scroll the active element in :direction by :amount * :factor.
# :factor is needed because :amount can take on string values, which scrollBy converts to element dimensions.
@@ -66,26 +117,28 @@ root.scrollBy = (direction, amount, factor = 1) ->
if (!activatedElement || !isRendered(activatedElement))
activatedElement = document.body
- ensureScrollChange direction, (element, axisName) ->
- if Utils.isString amount
- elementAmount = getDimension element, direction, amount
- else
- elementAmount = amount
- elementAmount *= factor
- element[axisName] += elementAmount
+ if Utils.isString amount
+ elementAmount = getDimension activatedElement, direction, amount
+ else
+ elementAmount = amount
+ elementAmount *= factor
+
+ doScrollBy direction, elementAmount, true
-root.scrollTo = (direction, pos) ->
+root.scrollTo = (direction, pos, wantSmooth=false) ->
return unless document.body
if (!activatedElement || !isRendered(activatedElement))
activatedElement = document.body
- ensureScrollChange direction, (element, axisName) ->
- if Utils.isString pos
- elementPos = getDimension element, direction, pos
- else
- elementPos = pos
- element[axisName] = elementPos
+ if Utils.isString pos
+ elementPos = getDimension activatedElement, direction, pos
+ else
+ elementPos = pos
+ axisName = scrollProperties[direction].axisName
+ elementAmount = elementPos - activatedElement[axisName]
+
+ doScrollBy direction, elementAmount, wantSmooth
# TODO refactor and put this together with the code in getVisibleClientRect
isRendered = (element) ->
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 118f985e..57503565 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -49,7 +49,7 @@ settings =
loadedValues: 0
valuesToLoad: ["scrollStepSize", "linkHintCharacters", "linkHintNumbers", "filterLinkHints", "hideHud",
"previousPatterns", "nextPatterns", "findModeRawQuery", "regexFindMode", "userDefinedLinkHintCss",
- "helpDialog_showAdvancedCommands"]
+ "helpDialog_showAdvancedCommands", "smoothScroll"]
isLoaded: false
eventListeners: {}
@@ -101,7 +101,7 @@ initializePreDomReady = ->
settings.addEventListener("load", LinkHints.init.bind(LinkHints))
settings.load()
- Scroller.init()
+ Scroller.init settings
checkIfEnabledForUrl()
@@ -227,10 +227,10 @@ window.focusThisFrame = (shouldHighlight) ->
setTimeout((-> document.body.style.border = borderWas), 200)
extend window,
- scrollToBottom: -> Scroller.scrollTo "y", "max"
- scrollToTop: -> Scroller.scrollTo "y", 0
- scrollToLeft: -> Scroller.scrollTo "x", 0
- scrollToRight: -> Scroller.scrollTo "x", "max"
+ scrollToBottom: -> Scroller.scrollTo "y", "max", true
+ scrollToTop: -> Scroller.scrollTo "y", 0, true
+ scrollToLeft: -> Scroller.scrollTo "x", 0, true
+ scrollToRight: -> Scroller.scrollTo "x", "max", true
scrollUp: -> Scroller.scrollBy "y", -1 * settings.get("scrollStepSize")
scrollDown: -> Scroller.scrollBy "y", settings.get("scrollStepSize")
scrollPageUp: -> Scroller.scrollBy "y", "viewSize", -1/2
diff --git a/pages/options.coffee b/pages/options.coffee
index f5968eb9..3474bcba 100644
--- a/pages/options.coffee
+++ b/pages/options.coffee
@@ -196,6 +196,7 @@ document.addEventListener "DOMContentLoaded", ->
previousPatterns: NonEmptyTextOption
regexFindMode: CheckBoxOption
scrollStepSize: NumberOption
+ smoothScroll: CheckBoxOption
searchEngines: TextOption
searchUrl: NonEmptyTextOption
userDefinedLinkHintCss: TextOption
diff --git a/pages/options.html b/pages/options.html
index 4f037ba5..d6ce2764 100644
--- a/pages/options.html
+++ b/pages/options.html
@@ -359,6 +359,15 @@ unmapAll
+
| Previous patterns |
--
cgit v1.2.3
From 1010b7868eb59dde70bc6faf8fd6fb2969688e48 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Fri, 7 Nov 2014 14:49:54 +0000
Subject: smooth scroll; fix absolute scrolling of active element.
---
content_scripts/scroller.coffee | 47 ++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 19 deletions(-)
diff --git a/content_scripts/scroller.coffee b/content_scripts/scroller.coffee
index 4d1109c9..62a930fc 100644
--- a/content_scripts/scroller.coffee
+++ b/content_scripts/scroller.coffee
@@ -23,13 +23,24 @@ scrollProperties =
viewSize: 'clientWidth'
}
-getDimension = (el, direction, name) ->
- # the clientSizes of the body are the dimensions of the entire page, but the viewport should only be the
- # part visible through the window
- if name is 'viewSize' and el is document.body
- if direction is 'x' then window.innerWidth else window.innerHeight
+getDimension = (el, direction, amount) ->
+ if Utils.isString amount
+ name = amount
+ # the clientSizes of the body are the dimensions of the entire page, but the viewport should only be the
+ # part visible through the window
+ if name is 'viewSize' and el is document.body
+ if direction is 'x' then window.innerWidth else window.innerHeight
+ else
+ el[scrollProperties[direction][name]]
else
- el[scrollProperties[direction][name]]
+ amount
+
+# Test whether element should be scrolled.
+isScrollable = (element, direction) ->
+ # Elements with `overflow: hidden` should not be scrolled.
+ overflow = window.getComputedStyle(element).getPropertyValue("overflow-#{direction}")
+ return false if overflow == "hidden"
+ return true
# Chrome does not report scrollHeight accurately for nodes with pseudo-elements of height 0 (bug 110149).
# Therefore we cannot figure out if we have scrolled to the bottom of an element by testing if scrollTop +
@@ -41,9 +52,7 @@ ensureScrollChange = (direction, changeFn) ->
progress = 0
loop
oldScrollValue = element[axisName]
- # Elements with `overflow: hidden` should not be scrolled.
- overflow = window.getComputedStyle(element).getPropertyValue("overflow-#{direction}")
- changeFn(element, axisName) unless overflow == "hidden"
+ changeFn(element, axisName) if isScrollable element, direction
progress += element[axisName] - oldScrollValue
break unless element[axisName] == oldScrollValue && element != document.body
# we may have an orphaned element. if so, just scroll the body element.
@@ -117,10 +126,7 @@ root.scrollBy = (direction, amount, factor = 1) ->
if (!activatedElement || !isRendered(activatedElement))
activatedElement = document.body
- if Utils.isString amount
- elementAmount = getDimension activatedElement, direction, amount
- else
- elementAmount = amount
+ elementAmount = getDimension activatedElement, direction, amount
elementAmount *= factor
doScrollBy direction, elementAmount, true
@@ -131,14 +137,17 @@ root.scrollTo = (direction, pos, wantSmooth=false) ->
if (!activatedElement || !isRendered(activatedElement))
activatedElement = document.body
- if Utils.isString pos
- elementPos = getDimension activatedElement, direction, pos
- else
- elementPos = pos
+ # Find the deepest scrollable element which would move if we scrolled it. This is the element which
+ # ensureScrollChange will scroll.
+ # TODO(smblott) We're pretty much copying what ensureScrollChange does here. Refactor.
+ element = activatedElement
axisName = scrollProperties[direction].axisName
- elementAmount = elementPos - activatedElement[axisName]
+ while element != document.body and
+ (getDimension(element, direction, pos) == element[axisName] or not isScrollable element, direction)
+ element = element.parentElement || document.body
- doScrollBy direction, elementAmount, wantSmooth
+ amount = getDimension(element,direction,pos) - element[axisName]
+ doScrollBy direction, amount, wantSmooth
# TODO refactor and put this together with the code in getVisibleClientRect
isRendered = (element) ->
--
cgit v1.2.3
From b8b1644a306c1fe12b5faa5204630eb30f1e64b3 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Sun, 9 Nov 2014 14:33:46 +0000
Subject: Smooth scroll; handle chrome bug and refactor.
---
content_scripts/scroller.coffee | 125 ++++++++++++++++++++--------------------
1 file changed, 62 insertions(+), 63 deletions(-)
diff --git a/content_scripts/scroller.coffee b/content_scripts/scroller.coffee
index 62a930fc..34f9b148 100644
--- a/content_scripts/scroller.coffee
+++ b/content_scripts/scroller.coffee
@@ -36,40 +36,51 @@ getDimension = (el, direction, amount) ->
amount
# Test whether element should be scrolled.
-isScrollable = (element, direction) ->
+isScrollAllowed = (element, direction) ->
# Elements with `overflow: hidden` should not be scrolled.
- overflow = window.getComputedStyle(element).getPropertyValue("overflow-#{direction}")
- return false if overflow == "hidden"
- return true
-
-# Chrome does not report scrollHeight accurately for nodes with pseudo-elements of height 0 (bug 110149).
-# Therefore we cannot figure out if we have scrolled to the bottom of an element by testing if scrollTop +
-# clientHeight == scrollHeight. So just try to increase scrollTop blindly -- if it fails we know we have
-# reached the end of the content.
-ensureScrollChange = (direction, changeFn) ->
+ window.getComputedStyle(element).getPropertyValue("overflow-#{direction}") != "hidden"
+
+# Test whether element actually scrolls in the direction required when asked to do so.
+# Due to chrome bug 110149, scrollHeight and clientHeight cannot be used to reliably determine whether an
+# element will scroll. Instead, we scroll the element by 1 or -1 and see if it moved.
+isScrollPossible = (element, direction, amount, factor) ->
+ axisName = scrollProperties[direction].axisName
+ # delta, here, is treated as a relative amount, which is correct for relative scrolls. For absolute scrolls
+ # (only gg, G, and friends), amount can be either 'max' or zero. In the former case, we're definitely
+ # scrolling forwards, so any positive value will do for delta. In the latter case, we're definitely
+ # scrolling backwards, so a delta of -1 will do.
+ delta = factor * getDimension(element, direction, amount) || -1
+ delta = delta / Math.abs delta # 1 or -1
+ before = element[axisName]
+ element[axisName] += delta
+ after = element[axisName]
+ element[axisName] = before
+ before != after
+
+# Find the element we should and can scroll.
+findScrollableElement = (element, direction, amount, factor = 1) ->
axisName = scrollProperties[direction].axisName
- element = activatedElement
- progress = 0
- loop
- oldScrollValue = element[axisName]
- changeFn(element, axisName) if isScrollable element, direction
- progress += element[axisName] - oldScrollValue
- break unless element[axisName] == oldScrollValue && element != document.body
- # we may have an orphaned element. if so, just scroll the body element.
- element = element.parentElement || document.body
-
- # if the activated element has been scrolled completely offscreen, subsequent changes in its scroll
- # position will not provide any more visual feedback to the user. therefore we deactivate it so that
- # subsequent scrolls only move the parent element.
- rect = activatedElement.getBoundingClientRect()
- if (rect.bottom < 0 || rect.top > window.innerHeight || rect.right < 0 || rect.left > window.innerWidth)
- activatedElement = element
+ while element != document.body and
+ not (isScrollPossible(element, direction, amount, factor) and isScrollAllowed(element, direction))
+ element = element.parentElement || document.body
+ element
+
+performScroll = (element, axisName, amount, checkVisibility = true) ->
+ before = element[axisName]
+ element[axisName] += amount
+
+ if checkVisibility
+ # if the activated element has been scrolled completely offscreen, subsequent changes in its scroll
+ # position will not provide any more visual feedback to the user. therefore we deactivate it so that
+ # subsequent scrolls only move the parent element.
+ rect = activatedElement.getBoundingClientRect()
+ if (rect.bottom < 0 || rect.top > window.innerHeight || rect.right < 0 || rect.left > window.innerWidth)
+ activatedElement = element
+
# Return the amount by which the scroll position has changed.
- return progress
+ element[axisName] - before
-# Scroll by a relative amount in some direction, possibly smoothly.
-# The constants below seem to roughly match chrome's scroll speeds for both short and long scrolls.
-# TODO(smblott) For very-long scrolls, chrome implements a soft landing; we don't.
+# Scroll by a relative amount (a number) in some direction, possibly smoothly.
doScrollBy = do ->
interval = 10 # Update interval (in ms).
duration = 120 # This must be a multiple of interval (also in ms).
@@ -87,30 +98,27 @@ doScrollBy = do ->
# Ensure we have a multiple of interval.
return interval * Math.round (extra / interval)
- scroller = (direction,amount) ->
- return ensureScrollChange direction, (element, axisName) -> element[axisName] += amount
-
- (direction,amount,wantSmooth) ->
+ (element, direction, amount, wantSmooth) ->
+ axisName = scrollProperties[direction].axisName
clearTimer()
unless wantSmooth and settings.get "smoothScroll"
- scroller direction, amount
- return
+ return performScroll element, axisName, amount
requiredTicks = (duration + calculateExtraDuration amount) / interval
- # Round away from 0, so that we don't leave any requested scroll amount unscrolled.
- rounder = (if 0 <= amount then Math.ceil else Math.floor)
- delta = rounder(amount / requiredTicks)
+ # Round away from 0, so that we don't leave any scroll amount unscrolled.
+ delta = (if 0 <= amount then Math.ceil else Math.floor)(amount / requiredTicks)
- ticks = 0
- ticker = ->
- # If we haven't scrolled by the expected amount, then we've hit the top, bottom or side of the activated
- # element, so stop scrolling.
- if scroller(direction, delta) != delta or ++ticks == requiredTicks
- clearTimer()
+ if delta
+ ticks = 0
+ ticker = ->
+ if performScroll(element, axisName, delta, false) != delta or ++ticks == requiredTicks
+ # One final call of performScroll to check the visibility of the activated element.
+ performScroll(element, axisName, 0, true)
+ clearTimer()
- timer = setInterval ticker, interval
- ticker()
+ timer = setInterval ticker, interval
+ ticker()
# scroll the active element in :direction by :amount * :factor.
# :factor is needed because :amount can take on string values, which scrollBy converts to element dimensions.
@@ -126,28 +134,19 @@ root.scrollBy = (direction, amount, factor = 1) ->
if (!activatedElement || !isRendered(activatedElement))
activatedElement = document.body
- elementAmount = getDimension activatedElement, direction, amount
- elementAmount *= factor
-
- doScrollBy direction, elementAmount, true
+ element = findScrollableElement activatedElement, direction, amount, factor
+ elementAmount = factor * getDimension element, direction, amount
+ doScrollBy element, direction, elementAmount, true
-root.scrollTo = (direction, pos, wantSmooth=false) ->
+root.scrollTo = (direction, pos, wantSmooth = false) ->
return unless document.body
if (!activatedElement || !isRendered(activatedElement))
activatedElement = document.body
- # Find the deepest scrollable element which would move if we scrolled it. This is the element which
- # ensureScrollChange will scroll.
- # TODO(smblott) We're pretty much copying what ensureScrollChange does here. Refactor.
- element = activatedElement
- axisName = scrollProperties[direction].axisName
- while element != document.body and
- (getDimension(element, direction, pos) == element[axisName] or not isScrollable element, direction)
- element = element.parentElement || document.body
-
- amount = getDimension(element,direction,pos) - element[axisName]
- doScrollBy direction, amount, wantSmooth
+ element = findScrollableElement activatedElement, direction, pos
+ amount = getDimension(element,direction,pos) - element[scrollProperties[direction].axisName]
+ doScrollBy element, direction, amount, wantSmooth
# TODO refactor and put this together with the code in getVisibleClientRect
isRendered = (element) ->
--
cgit v1.2.3
From df521c26fda9b8d3e8c182fc85deaf5b8c723cd4 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 10 Nov 2014 08:27:55 +0000
Subject: Change smooth scrolling to requestAnimationFrame, tidy up scroller
code
---
content_scripts/scroller.coffee | 128 ++++++++++++++++++----------------------
1 file changed, 58 insertions(+), 70 deletions(-)
diff --git a/content_scripts/scroller.coffee b/content_scripts/scroller.coffee
index 34f9b148..2e0d08ad 100644
--- a/content_scripts/scroller.coffee
+++ b/content_scripts/scroller.coffee
@@ -1,5 +1,3 @@
-window.Scroller = root = {}
-
#
# activatedElement is different from document.activeElement -- the latter seems to be reserved mostly for
# input elements. This mechanism allows us to decide whether to scroll a div or to scroll the whole document.
@@ -7,10 +5,6 @@ window.Scroller = root = {}
activatedElement = null
settings = null
-root.init = (frontendSettings) ->
- settings = frontendSettings
- handlerStack.push DOMActivate: -> activatedElement = event.target
-
scrollProperties =
x: {
axisName: 'scrollLeft'
@@ -37,8 +31,11 @@ getDimension = (el, direction, amount) ->
# Test whether element should be scrolled.
isScrollAllowed = (element, direction) ->
+ computedStyle = window.getComputedStyle(element)
# Elements with `overflow: hidden` should not be scrolled.
- window.getComputedStyle(element).getPropertyValue("overflow-#{direction}") != "hidden"
+ return computedStyle.getPropertyValue("overflow-#{direction}") != "hidden" and
+ ["hidden", "collapse"].indexOf(computedStyle.getPropertyValue("visibility")) == -1 and
+ computedStyle.getPropertyValue("display") != "none"
# Test whether element actually scrolls in the direction required when asked to do so.
# Due to chrome bug 110149, scrollHeight and clientHeight cannot be used to reliably determine whether an
@@ -58,7 +55,7 @@ isScrollPossible = (element, direction, amount, factor) ->
before != after
# Find the element we should and can scroll.
-findScrollableElement = (element, direction, amount, factor = 1) ->
+findScrollableElement = (element = document.body, direction, amount, factor = 1) ->
axisName = scrollProperties[direction].axisName
while element != document.body and
not (isScrollPossible(element, direction, amount, factor) and isScrollAllowed(element, direction))
@@ -81,75 +78,66 @@ performScroll = (element, axisName, amount, checkVisibility = true) ->
element[axisName] - before
# Scroll by a relative amount (a number) in some direction, possibly smoothly.
-doScrollBy = do ->
- interval = 10 # Update interval (in ms).
- duration = 120 # This must be a multiple of interval (also in ms).
- fudgeFactor = 25
- timer = null
+doScrollBy = (element, direction, amount, wantSmooth) ->
+ axisName = scrollProperties[direction].axisName
- clearTimer = ->
- if timer
- clearInterval timer
- timer = null
+ unless wantSmooth and settings.get "smoothScroll"
+ return performScroll element, axisName, amount
+
+ duration = 100 # Duration in ms.
+ fudgeFactor = 25
# Allow a bit longer for longer scrolls.
- calculateExtraDuration = (amount) ->
- extra = fudgeFactor * Math.log Math.abs amount
- # Ensure we have a multiple of interval.
- return interval * Math.round (extra / interval)
-
- (element, direction, amount, wantSmooth) ->
- axisName = scrollProperties[direction].axisName
- clearTimer()
-
- unless wantSmooth and settings.get "smoothScroll"
- return performScroll element, axisName, amount
-
- requiredTicks = (duration + calculateExtraDuration amount) / interval
- # Round away from 0, so that we don't leave any scroll amount unscrolled.
- delta = (if 0 <= amount then Math.ceil else Math.floor)(amount / requiredTicks)
-
- if delta
- ticks = 0
- ticker = ->
- if performScroll(element, axisName, delta, false) != delta or ++ticks == requiredTicks
- # One final call of performScroll to check the visibility of the activated element.
- performScroll(element, axisName, 0, true)
- clearTimer()
-
- timer = setInterval ticker, interval
- ticker()
-
-# scroll the active element in :direction by :amount * :factor.
-# :factor is needed because :amount can take on string values, which scrollBy converts to element dimensions.
-root.scrollBy = (direction, amount, factor = 1) ->
- # if this is called before domReady, just use the window scroll function
- if (!document.body and amount instanceof Number)
- if (direction == "x")
- window.scrollBy(amount, 0)
+ duration += fudgeFactor * Math.log Math.abs amount
+
+ roundOut = if 0 <= amount then Math.ceil else Math.floor
+
+ # Round away from 0, so that we don't leave any scroll amount unscrolled.
+ delta = roundOut(amount / duration)
+
+ animatorId = null
+ start = null
+ lastTime = null
+ scrolledAmount = 0
+
+ animate = (timestamp) ->
+ start ?= timestamp
+
+ progress = Math.min(timestamp - start, duration)
+ scrollDelta = roundOut(delta * progress) - scrolledAmount
+ scrolledAmount += scrollDelta
+
+ if performScroll(element, axisName, scrollDelta, false) != scrollDelta or
+ progress >= duration
+ # One final call of performScroll to check the visibility of the activated element.
+ performScroll(element, axisName, 0, true)
+ window.cancelAnimationFrame(animatorId)
else
- window.scrollBy(0, amount)
- return
+ animatorId = window.requestAnimationFrame(animate)
+
+ animatorId = window.requestAnimationFrame(animate)
- if (!activatedElement || !isRendered(activatedElement))
- activatedElement = document.body
+Scroller =
+ init: (frontendSettings) ->
+ settings = frontendSettings
+ handlerStack.push DOMActivate: -> activatedElement = event.target
- element = findScrollableElement activatedElement, direction, amount, factor
- elementAmount = factor * getDimension element, direction, amount
- doScrollBy element, direction, elementAmount, true
+ # scroll the active element in :direction by :amount * :factor.
+ # :factor is needed because :amount can take on string values, which scrollBy converts to element dimensions.
+ scrollBy: (direction, amount, factor = 1) ->
+ # if this is called before domReady, just use the window scroll function
+ return unless document.body
-root.scrollTo = (direction, pos, wantSmooth = false) ->
- return unless document.body
+ element = findScrollableElement activatedElement, direction, amount, factor
+ elementAmount = factor * getDimension element, direction, amount
+ doScrollBy element, direction, elementAmount, true
- if (!activatedElement || !isRendered(activatedElement))
- activatedElement = document.body
+ scrollTo: (direction, pos, wantSmooth = false) ->
+ return unless document.body
- element = findScrollableElement activatedElement, direction, pos
- amount = getDimension(element,direction,pos) - element[scrollProperties[direction].axisName]
- doScrollBy element, direction, amount, wantSmooth
+ element = findScrollableElement activatedElement, direction, pos
+ amount = getDimension(element,direction,pos) - element[scrollProperties[direction].axisName]
+ doScrollBy element, direction, amount, wantSmooth
-# TODO refactor and put this together with the code in getVisibleClientRect
-isRendered = (element) ->
- computedStyle = window.getComputedStyle(element, null)
- return !(computedStyle.getPropertyValue("visibility") != "visible" ||
- computedStyle.getPropertyValue("display") == "none")
+root = exports ? window
+root.Scroller = Scroller
--
cgit v1.2.3
|