{title}
\nnull
\n * @param top {Number?null} Vertical scroll position, keeps current if value is null
\n * @param animate {Boolean?false} Whether the scrolling should happen using an animation\n * @param zoom {Number?null} Zoom level to go to\n */\n scrollTo: function (left, top, animate, zoom, callback) {\n\n var self = this;\n\n // Stop deceleration\n if (self.__isDecelerating) {\n Animate.stop(self.__isDecelerating);\n self.__isDecelerating = false;\n }\n\n // Correct coordinates based on new zoom level\n if (zoom != null && zoom !== self.__zoomLevel) {\n\n if (!self.options.zooming) {\n throw new Error(\"Zooming is not enabled!\");\n }\n\n left *= zoom;\n top *= zoom;\n\n // Recompute maximum values while temporary tweaking maximum scroll ranges\n self.__computeScrollMax(zoom);\n\n } else {\n\n // Keep zoom when not defined\n zoom = self.__zoomLevel;\n\n }\n\n if (!self.options.scrollingX) {\n\n left = self.__scrollLeft;\n\n } else {\n\n if (self.options.paging) {\n left = Math.round(left / self.__clientWidth) * self.__clientWidth;\n } else if (self.options.snapping) {\n left = Math.round(left / self.__snapWidth) * self.__snapWidth;\n }\n\n }\n\n if (!self.options.scrollingY) {\n\n top = self.__scrollTop;\n\n } else {\n\n if (self.options.paging) {\n top = Math.round(top / self.__clientHeight) * self.__clientHeight;\n } else if (self.options.snapping) {\n top = Math.round(top / self.__snapHeight) * self.__snapHeight;\n }\n\n }\n\n // Limit for allowed ranges\n left = Math.max(Math.min(self.__maxScrollLeft, left), 0);\n top = Math.max(Math.min(self.__maxScrollTop, top), 0);\n\n // Don't animate when no change detected, still call publish to make sure\n // that rendered position is really in-sync with internal data\n if (left === self.__scrollLeft && top === self.__scrollTop) {\n animate = false;\n if (callback) {\n callback();\n }\n }\n\n // Publish new values\n if (!self.__isTracking) {\n self.__publish(left, top, zoom, animate);\n }\n\n },\n\n\n /**\n * Scroll by the given offset\n *\n * @param left {Number ? 0} Scroll x-axis by given offset\n * @param top {Number ? 0} Scroll x-axis by given offset\n * @param animate {Boolean ? false} Whether to animate the given change\n */\n scrollBy: function (left, top, animate) {\n\n var self = this;\n\n var startLeft = self.__isAnimating ? self.__scheduledLeft : self.__scrollLeft;\n var startTop = self.__isAnimating ? self.__scheduledTop : self.__scrollTop;\n\n self.scrollTo(startLeft + (left || 0), startTop + (top || 0), animate);\n\n },\n\n\n /*\n ---------------------------------------------------------------------------\n EVENT CALLBACKS\n ---------------------------------------------------------------------------\n */\n\n /**\n * Mouse wheel handler for zooming support\n */\n doMouseZoom: function (wheelDelta, timeStamp, pageX, pageY) {\n\n var self = this;\n var change = wheelDelta > 0 ? 0.97 : 1.03;\n\n return self.zoomTo(self.__zoomLevel * change, false, pageX - self.__clientLeft, pageY - self.__clientTop);\n\n },\n\n\n /**\n * Touch start handler for scrolling support\n */\n doTouchStart: function (touches, timeStamp) {\n\n // Array-like check is enough here\n if (touches.length == null) {\n throw new Error(\"Invalid touch list: \" + touches);\n }\n\n if (timeStamp instanceof Date) {\n timeStamp = timeStamp.valueOf();\n }\n if (typeof timeStamp !== \"number\") {\n throw new Error(\"Invalid timestamp value: \" + timeStamp);\n }\n\n var self = this;\n\n // Reset interruptedAnimation flag\n self.__interruptedAnimation = true;\n\n // Stop deceleration\n if (self.__isDecelerating) {\n Animate.stop(self.__isDecelerating);\n self.__isDecelerating = false;\n self.__interruptedAnimation = true;\n }\n\n // Stop animation\n if (self.__isAnimating) {\n Animate.stop(self.__isAnimating);\n self.__isAnimating = false;\n self.__interruptedAnimation = true;\n }\n\n // Use center point when dealing with two fingers\n var currentTouchLeft, currentTouchTop;\n var isSingleTouch = touches.length === 1;\n if (isSingleTouch) {\n currentTouchLeft = touches[0].pageX;\n currentTouchTop = touches[0].pageY;\n } else {\n currentTouchLeft = Math.abs(touches[0].pageX + touches[1].pageX) / 2;\n currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2;\n }\n\n // Store initial positions\n self.__initialTouchLeft = currentTouchLeft;\n self.__initialTouchTop = currentTouchTop;\n\n // Store current zoom level\n self.__zoomLevelStart = self.__zoomLevel;\n\n // Store initial touch positions\n self.__lastTouchLeft = currentTouchLeft;\n self.__lastTouchTop = currentTouchTop;\n\n // Store initial move time stamp\n self.__lastTouchMove = timeStamp;\n\n // Reset initial scale\n self.__lastScale = 1;\n\n // Reset locking flags\n self.__enableScrollX = !isSingleTouch && self.options.scrollingX;\n self.__enableScrollY = !isSingleTouch && self.options.scrollingY;\n\n // Reset tracking flag\n self.__isTracking = true;\n\n // Reset deceleration complete flag\n self.__didDecelerationComplete = false;\n\n // Dragging starts directly with two fingers, otherwise lazy with an offset\n self.__isDragging = !isSingleTouch;\n\n // Some features are disabled in multi touch scenarios\n self.__isSingleTouch = isSingleTouch;\n\n // Clearing data structure\n self.__positions = [];\n\n },\n\n\n /**\n * Touch move handler for scrolling support\n */\n doTouchMove: function (touches, timeStamp, scale) {\n\n // Array-like check is enough here\n if (touches.length == null) {\n throw new Error(\"Invalid touch list: \" + touches);\n }\n\n if (timeStamp instanceof Date) {\n timeStamp = timeStamp.valueOf();\n }\n if (typeof timeStamp !== \"number\") {\n throw new Error(\"Invalid timestamp value: \" + timeStamp);\n }\n\n var self = this;\n\n // Ignore event when tracking is not enabled (event might be outside of element)\n if (!self.__isTracking) {\n return;\n }\n\n\n var currentTouchLeft, currentTouchTop;\n\n // Compute move based around of center of fingers\n if (touches.length === 2) {\n currentTouchLeft = Math.abs(touches[0].pageX + touches[1].pageX) / 2;\n currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2;\n } else {\n currentTouchLeft = touches[0].pageX;\n currentTouchTop = touches[0].pageY;\n }\n\n var positions = self.__positions;\n\n // Are we already is dragging mode?\n if (self.__isDragging) {\n\n // Compute move distance\n var moveX = currentTouchLeft - self.__lastTouchLeft;\n var moveY = currentTouchTop - self.__lastTouchTop;\n\n // Read previous scroll position and zooming\n var scrollLeft = self.__scrollLeft;\n var scrollTop = self.__scrollTop;\n var level = self.__zoomLevel;\n\n // Work with scaling\n if (scale != null && self.options.zooming) {\n\n var oldLevel = level;\n\n // Recompute level based on previous scale and new scale\n level = level / self.__lastScale * scale;\n\n // Limit level according to configuration\n level = Math.max(Math.min(level, self.options.maxZoom), self.options.minZoom);\n\n // Only do further compution when change happened\n if (oldLevel !== level) {\n\n // Compute relative event position to container\n var currentTouchLeftRel = currentTouchLeft - self.__clientLeft;\n var currentTouchTopRel = currentTouchTop - self.__clientTop;\n\n // Recompute left and top coordinates based on new zoom level\n scrollLeft = ((currentTouchLeftRel + scrollLeft) * level / oldLevel) - currentTouchLeftRel;\n scrollTop = ((currentTouchTopRel + scrollTop) * level / oldLevel) - currentTouchTopRel;\n\n // Recompute max scroll values\n self.__computeScrollMax(level);\n\n }\n }\n\n if (self.__enableScrollX) {\n\n scrollLeft -= moveX * this.options.speedMultiplier;\n var maxScrollLeft = self.__maxScrollLeft;\n\n if (scrollLeft > maxScrollLeft || scrollLeft < 0) {\n\n // Slow down on the edges\n if (self.options.bouncing) {\n\n scrollLeft += (moveX / 2 * this.options.speedMultiplier);\n\n } else if (scrollLeft > maxScrollLeft) {\n\n scrollLeft = maxScrollLeft;\n\n } else {\n\n scrollLeft = 0;\n\n }\n }\n }\n\n // Compute new vertical scroll position\n if (self.__enableScrollY) {\n\n scrollTop -= moveY * this.options.speedMultiplier;\n var maxScrollTop = self.__maxScrollTop;\n\n if (scrollTop > maxScrollTop || scrollTop < 0) {\n\n // Slow down on the edges\n if (self.options.bouncing) {\n\n scrollTop += (moveY / 2 * this.options.speedMultiplier);\n\n // Support pull-to-refresh (only when only y is scrollable)\n if (!self.__enableScrollX && self.__refreshHeight != null) {\n\n if (!self.__refreshActive && scrollTop <= -self.__refreshHeight) {\n\n self.__refreshActive = true;\n if (self.__refreshActivate) {\n self.__refreshActivate();\n }\n\n } else if (self.__refreshActive && scrollTop > -self.__refreshHeight) {\n\n self.__refreshActive = false;\n if (self.__refreshDeactivate) {\n self.__refreshDeactivate();\n }\n\n }\n }\n\n } else if (scrollTop > maxScrollTop) {\n\n scrollTop = maxScrollTop;\n\n } else {\n\n scrollTop = 0;\n\n }\n }\n }\n\n // Keep list from growing infinitely (holding min 10, max 20 measure points)\n if (positions.length > 60) {\n positions.splice(0, 30);\n }\n\n // Track scroll movement for decleration\n positions.push(scrollLeft, scrollTop, timeStamp);\n\n // Sync scroll position\n self.__publish(scrollLeft, scrollTop, level);\n\n // Otherwise figure out whether we are switching into dragging mode now.\n } else {\n\n var minimumTrackingForScroll = self.options.locking ? 3 : 0;\n var minimumTrackingForDrag = 5;\n\n var distanceX = Math.abs(currentTouchLeft - self.__initialTouchLeft);\n var distanceY = Math.abs(currentTouchTop - self.__initialTouchTop);\n\n self.__enableScrollX = self.options.scrollingX && distanceX >= minimumTrackingForScroll;\n self.__enableScrollY = self.options.scrollingY && distanceY >= minimumTrackingForScroll;\n\n positions.push(self.__scrollLeft, self.__scrollTop, timeStamp);\n\n self.__isDragging = (self.__enableScrollX || self.__enableScrollY) && (distanceX >= minimumTrackingForDrag || distanceY >= minimumTrackingForDrag);\n if (self.__isDragging) {\n self.__interruptedAnimation = false;\n }\n\n }\n\n // Update last touch positions and time stamp for next event\n self.__lastTouchLeft = currentTouchLeft;\n self.__lastTouchTop = currentTouchTop;\n self.__lastTouchMove = timeStamp;\n self.__lastScale = scale;\n\n },\n\n\n /**\n * Touch end handler for scrolling support\n */\n doTouchEnd: function (timeStamp) {\n\n if (timeStamp instanceof Date) {\n timeStamp = timeStamp.valueOf();\n }\n if (typeof timeStamp !== \"number\") {\n throw new Error(\"Invalid timestamp value: \" + timeStamp);\n }\n\n var self = this;\n\n // Ignore event when tracking is not enabled (no touchstart event on element)\n // This is required as this listener ('touchmove') sits on the document and not on the element itself.\n if (!self.__isTracking) {\n return;\n }\n\n // Not touching anymore (when two finger hit the screen there are two touch end events)\n self.__isTracking = false;\n\n // Be sure to reset the dragging flag now. Here we also detect whether\n // the finger has moved fast enough to switch into a deceleration animation.\n if (self.__isDragging) {\n\n // Reset dragging flag\n self.__isDragging = false;\n\n // Start deceleration\n // Verify that the last move detected was in some relevant time frame\n if (self.__isSingleTouch && self.options.animating && (timeStamp - self.__lastTouchMove) <= 100) {\n\n // Then figure out what the scroll position was about 100ms ago\n var positions = self.__positions;\n var endPos = positions.length - 1;\n var startPos = endPos;\n\n // Move pointer to position measured 100ms ago\n for (var i = endPos; i > 0 && positions[i] > (self.__lastTouchMove - 100); i -= 3) {\n startPos = i;\n }\n\n // If start and stop position is identical in a 100ms timeframe,\n // we cannot compute any useful deceleration.\n if (startPos !== endPos) {\n\n // Compute relative movement between these two points\n var timeOffset = positions[endPos] - positions[startPos];\n var movedLeft = self.__scrollLeft - positions[startPos - 2];\n var movedTop = self.__scrollTop - positions[startPos - 1];\n\n // Based on 50ms compute the movement to apply for each render step\n self.__decelerationVelocityX = movedLeft / timeOffset * (1000 / 60);\n self.__decelerationVelocityY = movedTop / timeOffset * (1000 / 60);\n\n // How much velocity is required to start the deceleration\n var minVelocityToStartDeceleration = self.options.paging || self.options.snapping ? 4 : 1;\n\n // Verify that we have enough velocity to start deceleration\n if (Math.abs(self.__decelerationVelocityX) > minVelocityToStartDeceleration || Math.abs(self.__decelerationVelocityY) > minVelocityToStartDeceleration) {\n\n // Deactivate pull-to-refresh when decelerating\n if (!self.__refreshActive) {\n self.__startDeceleration(timeStamp);\n }\n } else {\n self.options.scrollingComplete();\n }\n } else {\n self.options.scrollingComplete();\n }\n } else if ((timeStamp - self.__lastTouchMove) > 100) {\n self.options.scrollingComplete();\n }\n }\n\n // If this was a slower move it is per default non decelerated, but this\n // still means that we want snap back to the bounds which is done here.\n // This is placed outside the condition above to improve edge case stability\n // e.g. touchend fired without enabled dragging. This should normally do not\n // have modified the scroll positions or even showed the scrollbars though.\n if (!self.__isDecelerating) {\n\n if (self.__refreshActive && self.__refreshStart) {\n\n // Use publish instead of scrollTo to allow scrolling to out of boundary position\n // We don't need to normalize scrollLeft, zoomLevel, etc. here because we only y-scrolling when pull-to-refresh is enabled\n self.__publish(self.__scrollLeft, -self.__refreshHeight, self.__zoomLevel, true);\n\n if (self.__refreshStart) {\n self.__refreshStart();\n }\n\n } else {\n\n if (self.__interruptedAnimation || self.__isDragging) {\n self.options.scrollingComplete();\n }\n self.scrollTo(self.__scrollLeft, self.__scrollTop, true, self.__zoomLevel);\n\n // Directly signalize deactivation (nothing todo on refresh?)\n if (self.__refreshActive) {\n\n self.__refreshActive = false;\n if (self.__refreshDeactivate) {\n self.__refreshDeactivate();\n }\n\n }\n }\n }\n\n // Fully cleanup list\n self.__positions.length = 0;\n\n },\n\n\n /*\n ---------------------------------------------------------------------------\n PRIVATE API\n ---------------------------------------------------------------------------\n */\n\n /**\n * Applies the scroll position to the content element\n *\n * @param left {Number} Left scroll position\n * @param top {Number} Top scroll position\n * @param animate {Boolean?false} Whether animation should be used to move to the new coordinates\n */\n __publish: function (left, top, zoom, animate) {\n\n var self = this;\n\n // Remember whether we had an animation, then we try to continue based on the current \"drive\" of the animation\n var wasAnimating = self.__isAnimating;\n if (wasAnimating) {\n Animate.stop(wasAnimating);\n self.__isAnimating = false;\n }\n\n if (animate && self.options.animating) {\n\n // Keep scheduled positions for scrollBy/zoomBy functionality\n self.__scheduledLeft = left;\n self.__scheduledTop = top;\n self.__scheduledZoom = zoom;\n\n var oldLeft = self.__scrollLeft;\n var oldTop = self.__scrollTop;\n var oldZoom = self.__zoomLevel;\n\n var diffLeft = left - oldLeft;\n var diffTop = top - oldTop;\n var diffZoom = zoom - oldZoom;\n\n var step = function (percent, now, render) {\n\n if (render) {\n\n self.__scrollLeft = oldLeft + (diffLeft * percent);\n self.__scrollTop = oldTop + (diffTop * percent);\n self.__zoomLevel = oldZoom + (diffZoom * percent);\n\n // Push values out\n if (self.__callback) {\n self.__callback(self.__scrollLeft, self.__scrollTop, self.__zoomLevel);\n }\n\n }\n };\n\n var verify = function (id) {\n return self.__isAnimating === id;\n };\n\n var completed = function (renderedFramesPerSecond, animationId, wasFinished) {\n if (animationId === self.__isAnimating) {\n self.__isAnimating = false;\n }\n\n if (self.__didDecelerationComplete || wasFinished) {\n self.options.scrollingComplete();\n }\n\n if (self.options.zooming) {\n self.__computeScrollMax();\n if (self.__zoomComplete) {\n self.__zoomComplete();\n self.__zoomComplete = null;\n }\n }\n };\n\n // When continuing based on previous animation we choose an ease-out animation instead of ease-in-out\n self.__isAnimating = Animate.start(step, verify, completed, self.options.animationDuration, wasAnimating ? easeOutCubic : easeInOutCubic);\n\n } else {\n\n self.__scheduledLeft = self.__scrollLeft = left;\n self.__scheduledTop = self.__scrollTop = top;\n self.__scheduledZoom = self.__zoomLevel = zoom;\n\n // Push values out\n if (self.__callback) {\n self.__callback(left, top, zoom);\n }\n\n // Fix max scroll ranges\n if (self.options.zooming) {\n self.__computeScrollMax();\n if (self.__zoomComplete) {\n self.__zoomComplete();\n self.__zoomComplete = null;\n }\n }\n }\n },\n\n\n /**\n * Recomputes scroll minimum values based on client dimensions and content dimensions.\n */\n __computeScrollMax: function (zoomLevel) {\n\n var self = this;\n\n if (zoomLevel == null) {\n zoomLevel = self.__zoomLevel;\n }\n\n self.__maxScrollLeft = Math.max((self.__contentWidth * zoomLevel) - self.__clientWidth, 0);\n self.__maxScrollTop = Math.max((self.__contentHeight * zoomLevel) - self.__clientHeight, 0);\n\n },\n\n\n /*\n ---------------------------------------------------------------------------\n ANIMATION (DECELERATION) SUPPORT\n ---------------------------------------------------------------------------\n */\n\n /**\n * Called when a touch sequence end and the speed of the finger was high enough\n * to switch into deceleration mode.\n */\n __startDeceleration: function (timeStamp) {\n\n var self = this;\n\n if (self.options.paging) {\n\n var scrollLeft = Math.max(Math.min(self.__scrollLeft, self.__maxScrollLeft), 0);\n var scrollTop = Math.max(Math.min(self.__scrollTop, self.__maxScrollTop), 0);\n var clientWidth = self.__clientWidth;\n var clientHeight = self.__clientHeight;\n\n // We limit deceleration not to the min/max values of the allowed range, but to the size of the visible client area.\n // Each page should have exactly the size of the client area.\n self.__minDecelerationScrollLeft = Math.floor(scrollLeft / clientWidth) * clientWidth;\n self.__minDecelerationScrollTop = Math.floor(scrollTop / clientHeight) * clientHeight;\n self.__maxDecelerationScrollLeft = Math.ceil(scrollLeft / clientWidth) * clientWidth;\n self.__maxDecelerationScrollTop = Math.ceil(scrollTop / clientHeight) * clientHeight;\n\n } else {\n\n self.__minDecelerationScrollLeft = 0;\n self.__minDecelerationScrollTop = 0;\n self.__maxDecelerationScrollLeft = self.__maxScrollLeft;\n self.__maxDecelerationScrollTop = self.__maxScrollTop;\n\n }\n\n // Wrap class method\n var step = function (percent, now, render) {\n self.__stepThroughDeceleration(render);\n };\n\n // How much velocity is required to keep the deceleration running\n // added by yiminghe\n var minVelocityToKeepDecelerating = self.options.minVelocityToKeepDecelerating;\n\n if (!minVelocityToKeepDecelerating) {\n minVelocityToKeepDecelerating = self.options.snapping ? 4 : 0.001;\n }\n\n // Detect whether it's still worth to continue animating steps\n // If we are already slow enough to not being user perceivable anymore, we stop the whole process here.\n var verify = function () {\n var shouldContinue = Math.abs(self.__decelerationVelocityX) >= minVelocityToKeepDecelerating || Math.abs(self.__decelerationVelocityY) >= minVelocityToKeepDecelerating;\n if (!shouldContinue) {\n self.__didDecelerationComplete = true;\n }\n return shouldContinue;\n };\n\n var completed = function (renderedFramesPerSecond, animationId, wasFinished) {\n self.__isDecelerating = false;\n // Animate to grid when snapping is active, otherwise just fix out-of-boundary positions\n // fixed by yiminghe, in case call scrollingComplete twice\n self.scrollTo(self.__scrollLeft, self.__scrollTop, self.options.snapping, null, self.__didDecelerationComplete && self.options.scrollingComplete);\n };\n\n // Start animation and switch on flag\n self.__isDecelerating = Animate.start(step, verify, completed);\n\n },\n\n\n /**\n * Called on every step of the animation\n *\n * @param inMemory {Boolean?false} Whether to not render the current step, but keep it in memory only. Used internally only!\n */\n __stepThroughDeceleration: function (render) {\n\n var self = this;\n\n\n //\n // COMPUTE NEXT SCROLL POSITION\n //\n\n // Add deceleration to scroll position\n var scrollLeft = self.__scrollLeft + self.__decelerationVelocityX;\n var scrollTop = self.__scrollTop + self.__decelerationVelocityY;\n\n\n //\n // HARD LIMIT SCROLL POSITION FOR NON BOUNCING MODE\n //\n\n if (!self.options.bouncing) {\n\n var scrollLeftFixed = Math.max(Math.min(self.__maxDecelerationScrollLeft, scrollLeft), self.__minDecelerationScrollLeft);\n if (scrollLeftFixed !== scrollLeft) {\n scrollLeft = scrollLeftFixed;\n self.__decelerationVelocityX = 0;\n }\n\n var scrollTopFixed = Math.max(Math.min(self.__maxDecelerationScrollTop, scrollTop), self.__minDecelerationScrollTop);\n if (scrollTopFixed !== scrollTop) {\n scrollTop = scrollTopFixed;\n self.__decelerationVelocityY = 0;\n }\n\n }\n\n //\n // UPDATE SCROLL POSITION\n //\n\n if (render) {\n\n self.__publish(scrollLeft, scrollTop, self.__zoomLevel);\n\n } else {\n\n self.__scrollLeft = scrollLeft;\n self.__scrollTop = scrollTop;\n\n }\n\n\n //\n // SLOW DOWN\n //\n\n // Slow down velocity on every iteration\n if (!self.options.paging) {\n\n // This is the factor applied to every iteration of the animation\n // to slow down the process. This should emulate natural behavior where\n // objects slow down when the initiator of the movement is removed\n var frictionFactor = 0.95;\n\n self.__decelerationVelocityX *= frictionFactor;\n self.__decelerationVelocityY *= frictionFactor;\n\n }\n\n\n //\n // BOUNCING SUPPORT\n //\n\n if (self.options.bouncing) {\n\n var scrollOutsideX = 0;\n var scrollOutsideY = 0;\n\n // This configures the amount of change applied to deceleration/acceleration when reaching boundaries\n var penetrationDeceleration = self.options.penetrationDeceleration;\n var penetrationAcceleration = self.options.penetrationAcceleration;\n\n // Check limits\n if (scrollLeft < self.__minDecelerationScrollLeft) {\n scrollOutsideX = self.__minDecelerationScrollLeft - scrollLeft;\n } else if (scrollLeft > self.__maxDecelerationScrollLeft) {\n scrollOutsideX = self.__maxDecelerationScrollLeft - scrollLeft;\n }\n\n if (scrollTop < self.__minDecelerationScrollTop) {\n scrollOutsideY = self.__minDecelerationScrollTop - scrollTop;\n } else if (scrollTop > self.__maxDecelerationScrollTop) {\n scrollOutsideY = self.__maxDecelerationScrollTop - scrollTop;\n }\n\n // Slow down until slow enough, then flip back to snap position\n if (scrollOutsideX !== 0) {\n if (scrollOutsideX * self.__decelerationVelocityX <= 0) {\n self.__decelerationVelocityX += scrollOutsideX * penetrationDeceleration;\n } else {\n self.__decelerationVelocityX = scrollOutsideX * penetrationAcceleration;\n }\n }\n\n if (scrollOutsideY !== 0) {\n if (scrollOutsideY * self.__decelerationVelocityY <= 0) {\n self.__decelerationVelocityY += scrollOutsideY * penetrationDeceleration;\n } else {\n self.__decelerationVelocityY = scrollOutsideY * penetrationAcceleration;\n }\n }\n }\n }\n};\n\n// Copy over members to prototype\nfor (var key in members) {\n Scroller.prototype[key] = members[key];\n}\n\nmodule.exports = Scroller;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/zscroller/vendor/Scroller.js\n ** module id = 428\n ** module chunks = 0\n **/","import '../../style/';\nimport './index.less';\n\n\n\n/** WEBPACK FOOTER **\n ** ./components/accordion/style/index.web.tsx\n **/","import '../../style/';\nimport '../../icon/style/';\nimport './index.less';\n\n\n\n/** WEBPACK FOOTER **\n ** ./components/badge/style/index.web.tsx\n **/","import '../../style/';\nimport '../../list/style/';\nimport './index.less';\n\n\n\n/** WEBPACK FOOTER **\n ** ./components/checkbox/style/index.web.tsx\n **/"],"sourceRoot":""}