├── .babelrc
├── .editorconfig
├── .gitignore
├── .prettierrc.js
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── dist
├── scrollbooster.min.js
└── scrollbooster.min.js.map
├── index.html
├── package.json
├── src
└── index.js
├── test
├── bread.jpg
├── index.html
├── init.test.js
├── nobounce.test.js
├── scroll.test.js
├── scrollto.test.js
├── test.css
├── xonly.test.js
└── yonly.test.js
├── webpack.config.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"],
3 | "plugins": ["@babel/plugin-proposal-object-rest-spread", "add-module-exports"]
4 | }
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | npm-debug.log
4 | yarn-error.log
5 |
6 | # Editor directories and files
7 | .idea
8 | *.suo
9 | *.ntvs*
10 | *.njsproj
11 | *.sln
12 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | singleQuote: true,
3 | trailingComma: 'es5',
4 | arrowParens: 'always',
5 | printWidth: 120,
6 | tabWidth: 4,
7 | };
8 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are welcome!
4 |
5 | 1. Fork this repository and clone it
6 | 2. Run `yarn` to install all dependencies
7 | 3. Make your changes. Do not change `dist` directory files manually
8 | 4. Quick way to test it is to run `yarn start` and check it in your browser
9 | 5. Run `yarn build` to build minified files
10 | 6. Commit your changes and make PR
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Ilya Shubin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ScrollBooster
2 |
3 | Enjoyable drag-to-scroll micro library (~2KB gzipped). Supports smooth content scroll via mouse/touch dragging, trackpad or mouse wheel. Zero dependencies.
4 |
5 | Easy to setup yet flexible enough to support any custom scrolling logic.
6 |
7 | ### Installation
8 |
9 | You can install it via `npm` or `yarn` package manager or via `script` tag:
10 |
11 | ``` bash
12 | npm i scrollbooster
13 | ```
14 |
15 | ``` bash
16 | yarn add scrollbooster
17 | ```
18 |
19 | ``` html
20 |
21 | ```
22 |
23 | ### Usage
24 |
25 | The most simple setup with default settings:
26 |
27 | ``` js
28 | import ScrollBooster from 'scrollbooster';
29 |
30 | new ScrollBooster({
31 | viewport: document.querySelector('.viewport'),
32 | scrollMode: 'transform'
33 | });
34 | ```
35 |
36 | Please note that in order to support IE11 you should replace arrow functions and string templates from code examples to supported equivalents or just use Babel.
37 |
38 | ### Options
39 |
40 | Option | Type | Default | Description
41 | ------ | ---- | ------- | -----------
42 | viewport | DOM Node | null | Content viewport element (required)
43 | content | DOM Node | viewport child element | Scrollable content element inside viewport
44 | scrollMode | String | undefined | Scroll technique - via CSS transform or natively. Could be 'transform' or 'native'
45 | direction | String | 'all' | Scroll direction. Could be 'horizontal', 'vertical' or 'all'
46 | bounce | Boolean | true | Enables elastic bounce effect when hitting viewport borders
47 | textSelection | Boolean | false | Enables text selection inside viewport
48 | inputsFocus | Boolean | true | Enables focus for elements: 'input', 'textarea', 'button', 'select' and 'label'
49 | pointerMode | String | 'all' | Specify pointer type. Supported values - 'touch' (scroll only on touch devices), 'mouse' (scroll only on desktop), 'all' (mobile and desktop)
50 | friction | Number | 0.05 | Scroll friction factor - how fast scrolling stops after pointer release
51 | bounceForce | Number | 0.1 | Elastic bounce effect factor
52 | emulateScroll | Boolean | false | Enables mouse wheel/trackpad emulation inside viewport
53 | preventDefaultOnEmulateScroll | String | false | Prevents horizontal or vertical default when `emulateScroll` is enabled (eg. useful to prevent horizontal trackpad gestures while enabling vertical scrolling). Could be 'horizontal' or 'vertical'.
54 | lockScrollOnDragDirection | String | false | Detect drag direction and either prevent default `mousedown`/`touchstart` event or lock content scroll. Could be 'horizontal', 'vertical' or 'all'
55 | dragDirectionTolerance | Number | 40 | Tolerance for horizontal or vertical drag detection
56 | onUpdate | Function | noop | Handler function to perform actual scrolling. Receives scrolling state object with coordinates
57 | onClick | Function | noop | Click handler function. Here you can, for example, prevent default event for click on links. Receives object with scrolling metrics and event object. Calls after each `click` in scrollable area
58 | onPointerDown | Function | noop | `mousedown`/`touchstart` events handler
59 | onPointerUp | Function | noop | `mouseup`/`touchend` events handler
60 | onPointerMove | Function | noop | `mousemove`/`touchmove` events handler
61 | onWheel | Function | noop | `wheel` event handler
62 | shouldScroll | Function | noop | Function to permit or disable scrolling. Receives object with scrolling state and event object. Calls on `pointerdown` (mousedown, touchstart) in scrollable area. You can return `true` or `false` to enable or disable scrolling
63 |
64 | ### List of methods
65 |
66 | Method | Description
67 | ------ | -----------
68 | setPosition | Sets new scroll position in viewport. Receives an object with properties `x` and `y`
69 | scrollTo | Smooth scroll to position in viewport. Receives an object with properties `x` and `y`
70 | updateMetrics | Forces to recalculate elements metrics. Useful for cases when content in scrollable area change its size dynamically
71 | updateOptions | Sets option value. All properties from `Options` config object are supported
72 | getState | Returns current scroll state in a same format as `onUpdate`
73 | destroy | Removes all instance's event listeners
74 |
75 | ### Full Example
76 |
77 | ``` js
78 | const viewport = document.querySelector('.viewport');
79 | const content = document.querySelector('.scrollable-content');
80 |
81 | const sb = new ScrollBooster({
82 | viewport,
83 | content,
84 | bounce: true,
85 | textSelection: false,
86 | emulateScroll: true,
87 | onUpdate: (state) => {
88 | // state contains useful metrics: position, dragOffset, dragAngle, isDragging, isMoving, borderCollision
89 | // you can control scroll rendering manually without 'scrollMethod' option:
90 | content.style.transform = `translate(
91 | ${-state.position.x}px,
92 | ${-state.position.y}px
93 | )`;
94 | },
95 | shouldScroll: (state, event) => {
96 | // disable scroll if clicked on button
97 | const isButton = event.target.nodeName.toLowerCase() === 'button';
98 | return !isButton;
99 | },
100 | onClick: (state, event, isTouchDevice) => {
101 | // prevent default link event
102 | const isLink = event.target.nodeName.toLowerCase() === 'link';
103 | if (isLink) {
104 | event.preventDefault();
105 | }
106 | }
107 | });
108 |
109 | // methods usage examples:
110 | sb.updateMetrics();
111 | sb.scrollTo({ x: 100, y: 100 });
112 | sb.updateOptions({ emulateScroll: false });
113 | sb.destroy();
114 | ```
115 |
116 | ### [Live ScrollBooster Examples On CodeSandbox](https://codesandbox.io/s/scrollbooster-examples-3g00p)
117 |
118 | ### Browser support
119 |
120 | ScrollBooster has been tested in IE 11, Edge and other modern browsers (Chrome, Firefox, Safari).
121 |
122 | ### Special thanks
123 |
124 | David DeSandro for his talk ["Practical UI Physics"](https://www.youtube.com/watch?v=90oMnMFozEE).
125 |
126 | ### License
127 |
128 | MIT License (c) Ilya Shubin
129 |
--------------------------------------------------------------------------------
/dist/scrollbooster.min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("ScrollBooster",[],e):"object"==typeof exports?exports.ScrollBooster=e():t.ScrollBooster=e()}(this,(function(){return function(t){var e={};function i(o){if(e[o])return e[o].exports;var n=e[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,i),n.l=!0,n.exports}return i.m=t,i.c=e,i.d=function(t,e,o){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)i.d(o,n,function(e){return t[e]}.bind(null,n));return o},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){"use strict";function o(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,o)}return i}function n(t){for(var e=1;e0&&void 0!==arguments[0]?arguments[0]:{};s(this,t);var i={content:e.viewport.children[0],direction:"all",pointerMode:"all",scrollMode:void 0,bounce:!0,bounceForce:.1,friction:.05,textSelection:!1,inputsFocus:!0,emulateScroll:!1,preventDefaultOnEmulateScroll:!1,preventPointerMoveDefault:!0,lockScrollOnDragDirection:!1,pointerDownPreventDefault:!0,dragDirectionTolerance:40,onPointerDown:function(){},onPointerUp:function(){},onPointerMove:function(){},onClick:function(){},onUpdate:function(){},onWheel:function(){},shouldScroll:function(){return!0}};if(this.props=n(n({},i),e),this.props.viewport&&this.props.viewport instanceof Element)if(this.props.content){this.isDragging=!1,this.isTargetScroll=!1,this.isScrolling=!1,this.isRunning=!1;var o={x:0,y:0};this.position=n({},o),this.velocity=n({},o),this.dragStartPosition=n({},o),this.dragOffset=n({},o),this.clientOffset=n({},o),this.dragPosition=n({},o),this.targetPosition=n({},o),this.scrollOffset=n({},o),this.rafID=null,this.events={},this.updateMetrics(),this.handleEvents()}else console.error("ScrollBooster init error: Viewport does not have any content");else console.error('ScrollBooster init error: "viewport" config property must be present and must be Element')}var e,i,o;return e=t,(i=[{key:"updateOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.props=n(n({},this.props),t),this.props.onUpdate(this.getState()),this.startAnimationLoop()}},{key:"updateMetrics",value:function(){var t;this.viewport={width:this.props.viewport.clientWidth,height:this.props.viewport.clientHeight},this.content={width:(t=this.props.content,Math.max(t.offsetWidth,t.scrollWidth)),height:l(this.props.content)},this.edgeX={from:Math.min(-this.content.width+this.viewport.width,0),to:0},this.edgeY={from:Math.min(-this.content.height+this.viewport.height,0),to:0},this.props.onUpdate(this.getState()),this.startAnimationLoop()}},{key:"startAnimationLoop",value:function(){var t=this;this.isRunning=!0,cancelAnimationFrame(this.rafID),this.rafID=requestAnimationFrame((function(){return t.animate()}))}},{key:"animate",value:function(){var t=this;if(this.isRunning){this.updateScrollPosition(),this.isMoving()||(this.isRunning=!1,this.isTargetScroll=!1);var e=this.getState();this.setContentPosition(e),this.props.onUpdate(e),this.rafID=requestAnimationFrame((function(){return t.animate()}))}}},{key:"updateScrollPosition",value:function(){this.applyEdgeForce(),this.applyDragForce(),this.applyScrollForce(),this.applyTargetForce();var t=1-this.props.friction;this.velocity.x*=t,this.velocity.y*=t,"vertical"!==this.props.direction&&(this.position.x+=this.velocity.x),"horizontal"!==this.props.direction&&(this.position.y+=this.velocity.y),this.props.bounce&&!this.isScrolling||this.isTargetScroll||(this.position.x=Math.max(Math.min(this.position.x,this.edgeX.to),this.edgeX.from),this.position.y=Math.max(Math.min(this.position.y,this.edgeY.to),this.edgeY.from))}},{key:"applyForce",value:function(t){this.velocity.x+=t.x,this.velocity.y+=t.y}},{key:"applyEdgeForce",value:function(){if(this.props.bounce&&!this.isDragging){var t=this.position.xthis.edgeX.to,i=this.position.ythis.edgeY.to,n=t||e,r=i||o;if(n||r){var s=t?this.edgeX.from:this.edgeX.to,a=i?this.edgeY.from:this.edgeY.to,l=s-this.position.x,p=a-this.position.y,c={x:l*this.props.bounceForce,y:p*this.props.bounceForce},h=this.position.x+(this.velocity.x+c.x)/this.props.friction,u=this.position.y+(this.velocity.y+c.y)/this.props.friction;(t&&h>=this.edgeX.from||e&&h<=this.edgeX.to)&&(c.x=l*this.props.bounceForce-this.velocity.x),(i&&u>=this.edgeY.from||o&&u<=this.edgeY.to)&&(c.y=p*this.props.bounceForce-this.velocity.y),this.applyForce({x:n?c.x:0,y:r?c.y:0})}}}},{key:"applyDragForce",value:function(){if(this.isDragging){var t=this.dragPosition.x-this.position.x,e=this.dragPosition.y-this.position.y;this.applyForce({x:t-this.velocity.x,y:e-this.velocity.y})}}},{key:"applyScrollForce",value:function(){this.isScrolling&&(this.applyForce({x:this.scrollOffset.x-this.velocity.x,y:this.scrollOffset.y-this.velocity.y}),this.scrollOffset.x=0,this.scrollOffset.y=0)}},{key:"applyTargetForce",value:function(){this.isTargetScroll&&this.applyForce({x:.08*(this.targetPosition.x-this.position.x)-this.velocity.x,y:.08*(this.targetPosition.y-this.position.y)-this.velocity.y})}},{key:"isMoving",value:function(){return this.isDragging||this.isScrolling||Math.abs(this.velocity.x)>=.01||Math.abs(this.velocity.y)>=.01}},{key:"scrollTo",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.isTargetScroll=!0,this.targetPosition.x=-t.x||0,this.targetPosition.y=-t.y||0,this.startAnimationLoop()}},{key:"setPosition",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.velocity.x=0,this.velocity.y=0,this.position.x=-t.x||0,this.position.y=-t.y||0,this.startAnimationLoop()}},{key:"getState",value:function(){return{isMoving:this.isMoving(),isDragging:!(!this.dragOffset.x&&!this.dragOffset.y),position:{x:-this.position.x,y:-this.position.y},dragOffset:this.dragOffset,dragAngle:this.getDragAngle(this.clientOffset.x,this.clientOffset.y),borderCollision:{left:this.position.x>=this.edgeX.to,right:this.position.x<=this.edgeX.from,top:this.position.y>=this.edgeY.to,bottom:this.position.y<=this.edgeY.from}}}},{key:"getDragAngle",value:function(t,e){return Math.round(Math.atan2(t,e)*(180/Math.PI))}},{key:"getDragDirection",value:function(t,e){return Math.abs(90-Math.abs(t))<=90-e?"horizontal":"vertical"}},{key:"setContentPosition",value:function(t){"transform"===this.props.scrollMode&&(this.props.content.style.transform="translate(".concat(-t.position.x,"px, ").concat(-t.position.y,"px)")),"native"===this.props.scrollMode&&(this.props.viewport.scrollTop=t.position.y,this.props.viewport.scrollLeft=t.position.x)}},{key:"handleEvents",value:function(){var t=this,e={x:0,y:0},i={x:0,y:0},o=null,n=null,r=!1,s=function(n){if(t.isDragging){var s=r?n.touches[0]:n,a=s.pageX,l=s.pageY,p=s.clientX,c=s.clientY;t.dragOffset.x=a-e.x,t.dragOffset.y=l-e.y,t.clientOffset.x=p-i.x,t.clientOffset.y=c-i.y,(Math.abs(t.clientOffset.x)>5&&!o||Math.abs(t.clientOffset.y)>5&&!o)&&(o=t.getDragDirection(t.getDragAngle(t.clientOffset.x,t.clientOffset.y),t.props.dragDirectionTolerance)),t.props.lockScrollOnDragDirection&&"all"!==t.props.lockScrollOnDragDirection?o===t.props.lockScrollOnDragDirection&&r?(t.dragPosition.x=t.dragStartPosition.x+t.dragOffset.x,t.dragPosition.y=t.dragStartPosition.y+t.dragOffset.y):r?(t.dragPosition.x=t.dragStartPosition.x,t.dragPosition.y=t.dragStartPosition.y):(t.dragPosition.x=t.dragStartPosition.x+t.dragOffset.x,t.dragPosition.y=t.dragStartPosition.y+t.dragOffset.y):(t.dragPosition.x=t.dragStartPosition.x+t.dragOffset.x,t.dragPosition.y=t.dragStartPosition.y+t.dragOffset.y)}};this.events.pointerdown=function(o){r=!(!o.touches||!o.touches[0]),t.props.onPointerDown(t.getState(),o,r);var n=r?o.touches[0]:o,a=n.pageX,l=n.pageY,p=n.clientX,c=n.clientY,h=t.props.viewport,u=h.getBoundingClientRect();if(!(p-u.left>=h.clientLeft+h.clientWidth)&&!(c-u.top>=h.clientTop+h.clientHeight)&&t.props.shouldScroll(t.getState(),o)&&2!==o.button&&("mouse"!==t.props.pointerMode||!r)&&("touch"!==t.props.pointerMode||r)&&!(t.props.inputsFocus&&["input","textarea","button","select","label"].indexOf(o.target.nodeName.toLowerCase())>-1)){if(t.props.textSelection){if(function(t,e,i){for(var o=t.childNodes,n=document.createRange(),r=0;r=a.left&&i>=a.top&&e<=a.right&&i<=a.bottom)return s}}return!1}(o.target,p,c))return;(f=window.getSelection?window.getSelection():document.selection)&&(f.removeAllRanges?f.removeAllRanges():f.empty&&f.empty())}var f;t.isDragging=!0,e.x=a,e.y=l,i.x=p,i.y=c,t.dragStartPosition.x=t.position.x,t.dragStartPosition.y=t.position.y,s(o),t.startAnimationLoop(),!r&&t.props.pointerDownPreventDefault&&o.preventDefault()}},this.events.pointermove=function(e){!e.cancelable||"all"!==t.props.lockScrollOnDragDirection&&t.props.lockScrollOnDragDirection!==o||e.preventDefault(),s(e),t.props.onPointerMove(t.getState(),e,r)},this.events.pointerup=function(e){t.isDragging=!1,o=null,t.props.onPointerUp(t.getState(),e,r)},this.events.wheel=function(e){var i=t.getState();t.props.emulateScroll&&(t.velocity.x=0,t.velocity.y=0,t.isScrolling=!0,t.scrollOffset.x=-e.deltaX,t.scrollOffset.y=-e.deltaY,t.props.onWheel(i,e),t.startAnimationLoop(),clearTimeout(n),n=setTimeout((function(){return t.isScrolling=!1}),80),t.props.preventDefaultOnEmulateScroll&&t.getDragDirection(t.getDragAngle(-e.deltaX,-e.deltaY),t.props.dragDirectionTolerance)===t.props.preventDefaultOnEmulateScroll&&e.preventDefault())},this.events.scroll=function(){var e=t.props.viewport,i=e.scrollLeft,o=e.scrollTop;Math.abs(t.position.x+i)>3&&(t.position.x=-i,t.velocity.x=0),Math.abs(t.position.y+o)>3&&(t.position.y=-o,t.velocity.y=0)},this.events.click=function(e){var i=t.getState(),o="vertical"!==t.props.direction?i.dragOffset.x:0,n="horizontal"!==t.props.direction?i.dragOffset.y:0;Math.max(Math.abs(o),Math.abs(n))>5&&(e.preventDefault(),e.stopPropagation()),t.props.onClick(i,e,r)},this.events.contentLoad=function(){return t.updateMetrics()},this.events.resize=function(){return t.updateMetrics()},this.props.viewport.addEventListener("mousedown",this.events.pointerdown),this.props.viewport.addEventListener("touchstart",this.events.pointerdown,{passive:!1}),this.props.viewport.addEventListener("click",this.events.click),this.props.viewport.addEventListener("wheel",this.events.wheel,{passive:!1}),this.props.viewport.addEventListener("scroll",this.events.scroll),this.props.content.addEventListener("load",this.events.contentLoad,!0),window.addEventListener("mousemove",this.events.pointermove),window.addEventListener("touchmove",this.events.pointermove,{passive:!1}),window.addEventListener("mouseup",this.events.pointerup),window.addEventListener("touchend",this.events.pointerup),window.addEventListener("resize",this.events.resize)}},{key:"destroy",value:function(){this.props.viewport.removeEventListener("mousedown",this.events.pointerdown),this.props.viewport.removeEventListener("touchstart",this.events.pointerdown),this.props.viewport.removeEventListener("click",this.events.click),this.props.viewport.removeEventListener("wheel",this.events.wheel),this.props.viewport.removeEventListener("scroll",this.events.scroll),this.props.content.removeEventListener("load",this.events.contentLoad),window.removeEventListener("mousemove",this.events.pointermove),window.removeEventListener("touchmove",this.events.pointermove),window.removeEventListener("mouseup",this.events.pointerup),window.removeEventListener("touchend",this.events.pointerup),window.removeEventListener("resize",this.events.resize)}}])&&a(e.prototype,i),o&&a(e,o),t}()}]).default}));
2 | //# sourceMappingURL=scrollbooster.min.js.map
--------------------------------------------------------------------------------
/dist/scrollbooster.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://ScrollBooster/webpack/universalModuleDefinition","webpack://ScrollBooster/webpack/bootstrap","webpack://ScrollBooster/./src/index.js"],"names":["root","factory","exports","module","define","amd","this","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","getFullHeight","elem","Math","max","offsetHeight","scrollHeight","ScrollBooster","options","defaults","content","viewport","children","direction","pointerMode","scrollMode","undefined","bounce","bounceForce","friction","textSelection","inputsFocus","emulateScroll","preventDefaultOnEmulateScroll","preventPointerMoveDefault","lockScrollOnDragDirection","pointerDownPreventDefault","dragDirectionTolerance","onPointerDown","onPointerUp","onPointerMove","onClick","onUpdate","onWheel","shouldScroll","props","Element","isDragging","isTargetScroll","isScrolling","isRunning","START_COORDINATES","x","y","position","velocity","dragStartPosition","dragOffset","clientOffset","dragPosition","targetPosition","scrollOffset","rafID","events","updateMetrics","handleEvents","console","error","getState","startAnimationLoop","width","clientWidth","height","clientHeight","offsetWidth","scrollWidth","edgeX","from","min","to","edgeY","cancelAnimationFrame","requestAnimationFrame","animate","updateScrollPosition","isMoving","state","setContentPosition","applyEdgeForce","applyDragForce","applyScrollForce","applyTargetForce","inverseFriction","force","beyondXFrom","beyondXTo","beyondYFrom","beyondYTo","beyondX","beyondY","edge","distanceToEdge","restPosition","applyForce","dragVelocity","abs","dragAngle","getDragAngle","borderCollision","left","right","top","bottom","round","atan2","PI","angle","tolerance","style","transform","scrollTop","scrollLeft","dragOrigin","clientOrigin","dragDirection","wheelTimer","isTouch","setDragPosition","event","eventData","touches","pageX","pageY","clientX","clientY","getDragDirection","pointerdown","rect","getBoundingClientRect","clientLeft","clientTop","button","indexOf","target","nodeName","toLowerCase","element","nodes","childNodes","range","document","createRange","length","node","nodeType","selectNodeContents","textNodeFromPoint","selection","window","getSelection","removeAllRanges","empty","preventDefault","pointermove","cancelable","pointerup","wheel","deltaX","deltaY","clearTimeout","setTimeout","scroll","click","dragOffsetX","dragOffsetY","stopPropagation","contentLoad","resize","addEventListener","passive","removeEventListener"],"mappings":"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","file":"scrollbooster.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"ScrollBooster\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ScrollBooster\"] = factory();\n\telse\n\t\troot[\"ScrollBooster\"] = factory();\n})(this, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","const getFullWidth = (elem) => Math.max(elem.offsetWidth, elem.scrollWidth);\nconst getFullHeight = (elem) => Math.max(elem.offsetHeight, elem.scrollHeight);\n\nconst textNodeFromPoint = (element, x, y) => {\n const nodes = element.childNodes;\n const range = document.createRange();\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (node.nodeType !== 3) {\n continue;\n }\n range.selectNodeContents(node);\n const rect = range.getBoundingClientRect();\n if (x >= rect.left && y >= rect.top && x <= rect.right && y <= rect.bottom) {\n return node;\n }\n }\n return false;\n};\n\nconst clearTextSelection = () => {\n const selection = window.getSelection ? window.getSelection() : document.selection;\n if (!selection) {\n return;\n }\n if (selection.removeAllRanges) {\n selection.removeAllRanges();\n } else if (selection.empty) {\n selection.empty();\n }\n};\n\nconst CLICK_EVENT_THRESHOLD_PX = 5;\n\nexport default class ScrollBooster {\n /**\n * Create ScrollBooster instance\n * @param {Object} options - options object\n * @param {Element} options.viewport - container element\n * @param {Element} options.content - scrollable content element\n * @param {String} options.direction - scroll direction\n * @param {String} options.pointerMode - mouse or touch support\n * @param {String} options.scrollMode - predefined scrolling technique\n * @param {Boolean} options.bounce - bounce effect\n * @param {Number} options.bounceForce - bounce effect factor\n * @param {Number} options.friction - scroll friction factor\n * @param {Boolean} options.textSelection - enables text selection\n * @param {Boolean} options.inputsFocus - enables focus on input elements\n * @param {Boolean} options.emulateScroll - enables mousewheel emulation\n * @param {Function} options.onClick - click handler\n * @param {Function} options.onUpdate - state update handler\n * @param {Function} options.onWheel - wheel handler\n * @param {Function} options.shouldScroll - predicate to allow or disable scroll\n */\n constructor(options = {}) {\n const defaults = {\n content: options.viewport.children[0],\n direction: 'all', // 'vertical', 'horizontal'\n pointerMode: 'all', // 'touch', 'mouse'\n scrollMode: undefined, // 'transform', 'native'\n bounce: true,\n bounceForce: 0.1,\n friction: 0.05,\n textSelection: false,\n inputsFocus: true,\n emulateScroll: false,\n preventDefaultOnEmulateScroll: false, // 'vertical', 'horizontal'\n preventPointerMoveDefault: true,\n lockScrollOnDragDirection: false, // 'vertical', 'horizontal', 'all'\n pointerDownPreventDefault: true,\n dragDirectionTolerance: 40,\n onPointerDown() {},\n onPointerUp() {},\n onPointerMove() {},\n onClick() {},\n onUpdate() {},\n onWheel() {},\n shouldScroll() {\n return true;\n },\n };\n\n this.props = { ...defaults, ...options };\n\n if (!this.props.viewport || !(this.props.viewport instanceof Element)) {\n console.error(`ScrollBooster init error: \"viewport\" config property must be present and must be Element`);\n return;\n }\n\n if (!this.props.content) {\n console.error(`ScrollBooster init error: Viewport does not have any content`);\n return;\n }\n\n this.isDragging = false;\n this.isTargetScroll = false;\n this.isScrolling = false;\n this.isRunning = false;\n\n const START_COORDINATES = { x: 0, y: 0 };\n\n this.position = { ...START_COORDINATES };\n this.velocity = { ...START_COORDINATES };\n this.dragStartPosition = { ...START_COORDINATES };\n this.dragOffset = { ...START_COORDINATES };\n this.clientOffset = { ...START_COORDINATES };\n this.dragPosition = { ...START_COORDINATES };\n this.targetPosition = { ...START_COORDINATES };\n this.scrollOffset = { ...START_COORDINATES };\n\n this.rafID = null;\n this.events = {};\n\n this.updateMetrics();\n this.handleEvents();\n }\n\n /**\n * Update options object with new given values\n */\n updateOptions(options = {}) {\n this.props = { ...this.props, ...options };\n this.props.onUpdate(this.getState());\n this.startAnimationLoop();\n }\n\n /**\n * Update DOM container elements metrics (width and height)\n */\n updateMetrics() {\n this.viewport = {\n width: this.props.viewport.clientWidth,\n height: this.props.viewport.clientHeight,\n };\n this.content = {\n width: getFullWidth(this.props.content),\n height: getFullHeight(this.props.content),\n };\n this.edgeX = {\n from: Math.min(-this.content.width + this.viewport.width, 0),\n to: 0,\n };\n this.edgeY = {\n from: Math.min(-this.content.height + this.viewport.height, 0),\n to: 0,\n };\n\n this.props.onUpdate(this.getState());\n this.startAnimationLoop();\n }\n\n /**\n * Run animation loop\n */\n startAnimationLoop() {\n this.isRunning = true;\n cancelAnimationFrame(this.rafID);\n this.rafID = requestAnimationFrame(() => this.animate());\n }\n\n /**\n * Main animation loop\n */\n animate() {\n if (!this.isRunning) {\n return;\n }\n this.updateScrollPosition();\n // stop animation loop if nothing moves\n if (!this.isMoving()) {\n this.isRunning = false;\n this.isTargetScroll = false;\n }\n const state = this.getState();\n this.setContentPosition(state);\n this.props.onUpdate(state);\n this.rafID = requestAnimationFrame(() => this.animate());\n }\n\n /**\n * Calculate and set new scroll position\n */\n updateScrollPosition() {\n this.applyEdgeForce();\n this.applyDragForce();\n this.applyScrollForce();\n this.applyTargetForce();\n\n const inverseFriction = 1 - this.props.friction;\n this.velocity.x *= inverseFriction;\n this.velocity.y *= inverseFriction;\n\n if (this.props.direction !== 'vertical') {\n this.position.x += this.velocity.x;\n }\n if (this.props.direction !== 'horizontal') {\n this.position.y += this.velocity.y;\n }\n\n // disable bounce effect\n if ((!this.props.bounce || this.isScrolling) && !this.isTargetScroll) {\n this.position.x = Math.max(Math.min(this.position.x, this.edgeX.to), this.edgeX.from);\n this.position.y = Math.max(Math.min(this.position.y, this.edgeY.to), this.edgeY.from);\n }\n }\n\n /**\n * Increase general scroll velocity by given force amount\n */\n applyForce(force) {\n this.velocity.x += force.x;\n this.velocity.y += force.y;\n }\n\n /**\n * Apply force for bounce effect\n */\n applyEdgeForce() {\n if (!this.props.bounce || this.isDragging) {\n return;\n }\n\n // scrolled past viewport edges\n const beyondXFrom = this.position.x < this.edgeX.from;\n const beyondXTo = this.position.x > this.edgeX.to;\n const beyondYFrom = this.position.y < this.edgeY.from;\n const beyondYTo = this.position.y > this.edgeY.to;\n const beyondX = beyondXFrom || beyondXTo;\n const beyondY = beyondYFrom || beyondYTo;\n\n if (!beyondX && !beyondY) {\n return;\n }\n\n const edge = {\n x: beyondXFrom ? this.edgeX.from : this.edgeX.to,\n y: beyondYFrom ? this.edgeY.from : this.edgeY.to,\n };\n\n const distanceToEdge = {\n x: edge.x - this.position.x,\n y: edge.y - this.position.y,\n };\n\n const force = {\n x: distanceToEdge.x * this.props.bounceForce,\n y: distanceToEdge.y * this.props.bounceForce,\n };\n\n const restPosition = {\n x: this.position.x + (this.velocity.x + force.x) / this.props.friction,\n y: this.position.y + (this.velocity.y + force.y) / this.props.friction,\n };\n\n if ((beyondXFrom && restPosition.x >= this.edgeX.from) || (beyondXTo && restPosition.x <= this.edgeX.to)) {\n force.x = distanceToEdge.x * this.props.bounceForce - this.velocity.x;\n }\n\n if ((beyondYFrom && restPosition.y >= this.edgeY.from) || (beyondYTo && restPosition.y <= this.edgeY.to)) {\n force.y = distanceToEdge.y * this.props.bounceForce - this.velocity.y;\n }\n\n this.applyForce({\n x: beyondX ? force.x : 0,\n y: beyondY ? force.y : 0,\n });\n }\n\n /**\n * Apply force to move content while dragging with mouse/touch\n */\n applyDragForce() {\n if (!this.isDragging) {\n return;\n }\n\n const dragVelocity = {\n x: this.dragPosition.x - this.position.x,\n y: this.dragPosition.y - this.position.y,\n };\n\n this.applyForce({\n x: dragVelocity.x - this.velocity.x,\n y: dragVelocity.y - this.velocity.y,\n });\n }\n\n /**\n * Apply force to emulate mouse wheel or trackpad\n */\n applyScrollForce() {\n if (!this.isScrolling) {\n return;\n }\n\n this.applyForce({\n x: this.scrollOffset.x - this.velocity.x,\n y: this.scrollOffset.y - this.velocity.y,\n });\n\n this.scrollOffset.x = 0;\n this.scrollOffset.y = 0;\n }\n\n /**\n * Apply force to scroll to given target coordinate\n */\n applyTargetForce() {\n if (!this.isTargetScroll) {\n return;\n }\n\n this.applyForce({\n x: (this.targetPosition.x - this.position.x) * 0.08 - this.velocity.x,\n y: (this.targetPosition.y - this.position.y) * 0.08 - this.velocity.y,\n });\n }\n\n /**\n * Check if scrolling happening\n */\n isMoving() {\n return (\n this.isDragging ||\n this.isScrolling ||\n Math.abs(this.velocity.x) >= 0.01 ||\n Math.abs(this.velocity.y) >= 0.01\n );\n }\n\n /**\n * Set scroll target coordinate for smooth scroll\n */\n scrollTo(position = {}) {\n this.isTargetScroll = true;\n this.targetPosition.x = -position.x || 0;\n this.targetPosition.y = -position.y || 0;\n this.startAnimationLoop();\n }\n\n /**\n * Manual position setting\n */\n setPosition(position = {}) {\n this.velocity.x = 0;\n this.velocity.y = 0;\n this.position.x = -position.x || 0;\n this.position.y = -position.y || 0;\n this.startAnimationLoop();\n }\n\n /**\n * Get latest metrics and coordinates\n */\n getState() {\n return {\n isMoving: this.isMoving(),\n isDragging: !!(this.dragOffset.x || this.dragOffset.y),\n position: { x: -this.position.x, y: -this.position.y },\n dragOffset: this.dragOffset,\n dragAngle: this.getDragAngle(this.clientOffset.x, this.clientOffset.y),\n borderCollision: {\n left: this.position.x >= this.edgeX.to,\n right: this.position.x <= this.edgeX.from,\n top: this.position.y >= this.edgeY.to,\n bottom: this.position.y <= this.edgeY.from,\n },\n };\n }\n\n /**\n * Get drag angle (up: 180, left: -90, right: 90, down: 0)\n */\n getDragAngle(x, y) {\n return Math.round(Math.atan2(x, y) * (180 / Math.PI));\n }\n\n /**\n * Get drag direction (horizontal or vertical)\n */\n getDragDirection(angle, tolerance) {\n const absAngle = Math.abs(90 - Math.abs(angle));\n\n if (absAngle <= 90 - tolerance) {\n return 'horizontal';\n } else {\n return 'vertical';\n }\n }\n\n /**\n * Update DOM container elements metrics (width and height)\n */\n setContentPosition(state) {\n if (this.props.scrollMode === 'transform') {\n this.props.content.style.transform = `translate(${-state.position.x}px, ${-state.position.y}px)`;\n }\n if (this.props.scrollMode === 'native') {\n this.props.viewport.scrollTop = state.position.y;\n this.props.viewport.scrollLeft = state.position.x;\n }\n }\n\n /**\n * Register all DOM events\n */\n handleEvents() {\n const dragOrigin = { x: 0, y: 0 };\n const clientOrigin = { x: 0, y: 0 };\n let dragDirection = null;\n let wheelTimer = null;\n let isTouch = false;\n\n const setDragPosition = (event) => {\n if (!this.isDragging) {\n return;\n }\n\n const eventData = isTouch ? event.touches[0] : event;\n const { pageX, pageY, clientX, clientY } = eventData;\n\n this.dragOffset.x = pageX - dragOrigin.x;\n this.dragOffset.y = pageY - dragOrigin.y;\n\n this.clientOffset.x = clientX - clientOrigin.x;\n this.clientOffset.y = clientY - clientOrigin.y;\n\n // get dragDirection if offset threshold is reached\n if (\n (Math.abs(this.clientOffset.x) > 5 && !dragDirection) ||\n (Math.abs(this.clientOffset.y) > 5 && !dragDirection)\n ) {\n dragDirection = this.getDragDirection(\n this.getDragAngle(this.clientOffset.x, this.clientOffset.y),\n this.props.dragDirectionTolerance\n );\n }\n\n // prevent scroll if not expected scroll direction\n if (this.props.lockScrollOnDragDirection && this.props.lockScrollOnDragDirection !== 'all') {\n if (dragDirection === this.props.lockScrollOnDragDirection && isTouch) {\n this.dragPosition.x = this.dragStartPosition.x + this.dragOffset.x;\n this.dragPosition.y = this.dragStartPosition.y + this.dragOffset.y;\n } else if (!isTouch) {\n this.dragPosition.x = this.dragStartPosition.x + this.dragOffset.x;\n this.dragPosition.y = this.dragStartPosition.y + this.dragOffset.y;\n } else {\n this.dragPosition.x = this.dragStartPosition.x;\n this.dragPosition.y = this.dragStartPosition.y;\n }\n } else {\n this.dragPosition.x = this.dragStartPosition.x + this.dragOffset.x;\n this.dragPosition.y = this.dragStartPosition.y + this.dragOffset.y;\n }\n };\n\n this.events.pointerdown = (event) => {\n isTouch = !!(event.touches && event.touches[0]);\n\n this.props.onPointerDown(this.getState(), event, isTouch);\n\n const eventData = isTouch ? event.touches[0] : event;\n const { pageX, pageY, clientX, clientY } = eventData;\n\n const { viewport } = this.props;\n const rect = viewport.getBoundingClientRect();\n\n // click on vertical scrollbar\n if (clientX - rect.left >= viewport.clientLeft + viewport.clientWidth) {\n return;\n }\n\n // click on horizontal scrollbar\n if (clientY - rect.top >= viewport.clientTop + viewport.clientHeight) {\n return;\n }\n\n // interaction disabled by user\n if (!this.props.shouldScroll(this.getState(), event)) {\n return;\n }\n\n // disable right mouse button scroll\n if (event.button === 2) {\n return;\n }\n\n // disable on mobile\n if (this.props.pointerMode === 'mouse' && isTouch) {\n return;\n }\n\n // disable on desktop\n if (this.props.pointerMode === 'touch' && !isTouch) {\n return;\n }\n\n // focus on form input elements\n const formNodes = ['input', 'textarea', 'button', 'select', 'label'];\n if (this.props.inputsFocus && formNodes.indexOf(event.target.nodeName.toLowerCase()) > -1) {\n return;\n }\n\n // handle text selection\n if (this.props.textSelection) {\n const textNode = textNodeFromPoint(event.target, clientX, clientY);\n if (textNode) {\n return;\n }\n clearTextSelection();\n }\n\n this.isDragging = true;\n\n dragOrigin.x = pageX;\n dragOrigin.y = pageY;\n\n clientOrigin.x = clientX;\n clientOrigin.y = clientY;\n\n this.dragStartPosition.x = this.position.x;\n this.dragStartPosition.y = this.position.y;\n\n setDragPosition(event);\n this.startAnimationLoop();\n\n if (!isTouch && this.props.pointerDownPreventDefault) {\n event.preventDefault();\n }\n };\n\n this.events.pointermove = (event) => {\n // prevent default scroll if scroll direction is locked\n if (event.cancelable && (this.props.lockScrollOnDragDirection === 'all' ||\n this.props.lockScrollOnDragDirection === dragDirection)) {\n event.preventDefault();\n }\n setDragPosition(event);\n this.props.onPointerMove(this.getState(), event, isTouch);\n };\n\n this.events.pointerup = (event) => {\n this.isDragging = false;\n dragDirection = null;\n this.props.onPointerUp(this.getState(), event, isTouch);\n };\n\n this.events.wheel = (event) => {\n const state = this.getState();\n if (!this.props.emulateScroll) {\n return;\n }\n this.velocity.x = 0;\n this.velocity.y = 0;\n this.isScrolling = true;\n\n this.scrollOffset.x = -event.deltaX;\n this.scrollOffset.y = -event.deltaY;\n\n this.props.onWheel(state, event);\n\n this.startAnimationLoop();\n\n clearTimeout(wheelTimer);\n wheelTimer = setTimeout(() => (this.isScrolling = false), 80);\n\n // get (trackpad) scrollDirection and prevent default events\n if (\n this.props.preventDefaultOnEmulateScroll &&\n this.getDragDirection(\n this.getDragAngle(-event.deltaX, -event.deltaY),\n this.props.dragDirectionTolerance\n ) === this.props.preventDefaultOnEmulateScroll\n ) {\n event.preventDefault();\n }\n };\n\n this.events.scroll = () => {\n const { scrollLeft, scrollTop } = this.props.viewport;\n if (Math.abs(this.position.x + scrollLeft) > 3) {\n this.position.x = -scrollLeft;\n this.velocity.x = 0;\n }\n if (Math.abs(this.position.y + scrollTop) > 3) {\n this.position.y = -scrollTop;\n this.velocity.y = 0;\n }\n };\n\n this.events.click = (event) => {\n const state = this.getState();\n const dragOffsetX = this.props.direction !== 'vertical' ? state.dragOffset.x : 0;\n const dragOffsetY = this.props.direction !== 'horizontal' ? state.dragOffset.y : 0;\n if (Math.max(Math.abs(dragOffsetX), Math.abs(dragOffsetY)) > CLICK_EVENT_THRESHOLD_PX) {\n event.preventDefault();\n event.stopPropagation();\n }\n this.props.onClick(state, event, isTouch);\n };\n\n this.events.contentLoad = () => this.updateMetrics();\n this.events.resize = () => this.updateMetrics();\n\n this.props.viewport.addEventListener('mousedown', this.events.pointerdown);\n this.props.viewport.addEventListener('touchstart', this.events.pointerdown, { passive: false });\n this.props.viewport.addEventListener('click', this.events.click);\n this.props.viewport.addEventListener('wheel', this.events.wheel, { passive: false });\n this.props.viewport.addEventListener('scroll', this.events.scroll);\n this.props.content.addEventListener('load', this.events.contentLoad, true);\n window.addEventListener('mousemove', this.events.pointermove);\n window.addEventListener('touchmove', this.events.pointermove, { passive: false });\n window.addEventListener('mouseup', this.events.pointerup);\n window.addEventListener('touchend', this.events.pointerup);\n window.addEventListener('resize', this.events.resize);\n }\n\n /**\n * Unregister all DOM events\n */\n destroy() {\n this.props.viewport.removeEventListener('mousedown', this.events.pointerdown);\n this.props.viewport.removeEventListener('touchstart', this.events.pointerdown);\n this.props.viewport.removeEventListener('click', this.events.click);\n this.props.viewport.removeEventListener('wheel', this.events.wheel);\n this.props.viewport.removeEventListener('scroll', this.events.scroll);\n this.props.content.removeEventListener('load', this.events.contentLoad);\n window.removeEventListener('mousemove', this.events.pointermove);\n window.removeEventListener('touchmove', this.events.pointermove);\n window.removeEventListener('mouseup', this.events.pointerup);\n window.removeEventListener('touchend', this.events.pointerup);\n window.removeEventListener('resize', this.events.resize);\n }\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | scrollbooster mini test
7 |
29 |
30 |
31 |
32 |
33 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Exercitationem
34 | corrupti reiciendis, mollitia molestias magni quasi voluptates culpa dignissimos minima hic.
35 | Lorem ipsum dolor sit amet consectetur adipisicing elit. In praesentium odit ex officia, possimus qui omnis,
36 | facere incidunt neque ducimus suscipit! Vel, neque! Sapiente tempora veritatis voluptatem itaque! Repellendus,
37 | optio.
38 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque iusto vitae quibusdam debitis
39 | illum consequuntur iste laborum fuga laboriosam mollitia.
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aperiam aspernatur autem consequuntur corporis deleniti dolor doloremque eligendi enim eos facere facilis fuga hic iste iusto laboriosam laborum magni maiores maxime minima minus molestiae neque nisi non, odio placeat praesentium rem sint tempore temporibus veniam voluptas, voluptatibus voluptatum! Beatae dolorem earum ipsa odit optio, quaerat sint? Amet animi aperiam blanditiis, corporis culpa excepturi facilis fugiat harum, id inventore ipsum libero magni minima natus nesciunt porro praesentium quos rem sint tenetur veritatis vitae voluptas, voluptatibus! Aut cum debitis doloremque esse eum pariatur quam reiciendis similique sit sunt! A accusamus beatae consectetur cupiditate deleniti doloremque ea eaque eligendi fugiat harum necessitatibus nihil nostrum officia officiis pariatur placeat, quas saepe sapiente similique sunt vel vero voluptatem voluptatibus. Aliquam assumenda beatae, distinctio ipsa laborum molestias obcaecati quas ratione repellendus sapiente. Architecto blanditiis deserunt, ipsa officiis placeat quasi quia quos recusandae voluptate voluptatem. A ab architecto aspernatur atque beatae corporis deleniti distinctio esse eveniet ex excepturi hic illo itaque iusto labore maiores molestias necessitatibus nemo neque nesciunt nisi non officia quaerat, quam reiciendis repellat sapiente sit tempora temporibus velit veniam vitae voluptas voluptatum? Ab at enim facere iusto libero nemo numquam quasi quibusdam quod sapiente! Alias aliquid aperiam atque, cupiditate distinctio eaque eum excepturi facere facilis fugiat harum maiores molestiae molestias odio, optio perferendis provident quam quas quasi quibusdam sint ut voluptates? Amet minima optio quae voluptate? Assumenda atque consectetur corporis debitis delectus deserunt dignissimos distinctio ducimus et excepturi exercitationem, impedit iure iusto magnam magni maxime nam nihil optio quaerat quas ratione repudiandae, sit tenetur ullam vero. Architecto commodi dicta provident. Accusantium alias aperiam aspernatur atque aut, corporis deleniti eius enim eos esse eum maiores mollitia neque non nostrum odio, optio perspiciatis provident quasi quo recusandae repellat sunt temporibus veniam voluptatum. Dolor facilis fuga, fugit iure laboriosam magnam modi molestias nemo neque nesciunt nisi non nulla numquam provident quasi quibusdam ratione sequi veniam? A alias animi beatae deserunt dolor eius eligendi, enim, eum expedita hic illo, illum impedit iste laborum libero maxime nesciunt numquam officiis perferendis quaerat quas qui similique soluta suscipit tempora? Aut nisi, voluptatem! Ab ad alias animi aspernatur consectetur debitis delectus doloremque eaque eos est fuga fugiat harum ipsa ipsam, ipsum nihil officia optio quam quia ratione recusandae soluta suscipit tenetur ut velit veniam veritatis! Ab deserunt eos illo inventore perferendis qui reiciendis? Accusamus, ad aut consectetur cum cupiditate distinctio dolor exercitationem expedita illum iste labore laboriosam libero maiores perspiciatis quos repellendus reprehenderit suscipit totam ullam, ut? Accusantium adipisci animi blanditiis consequatur debitis delectus dolor dolores et expedita id in inventore iste laboriosam laudantium libero magnam maiores pariatur placeat quia quibusdam, quo repudiandae sed soluta totam unde veritatis vero? Accusantium at dolorem dolores eveniet facere fugit iure iusto magnam, neque porro possimus quia repudiandae sed veritatis, voluptates. Ab aliquid amet assumenda blanditiis, commodi consequatur corporis esse harum, labore laudantium molestias nobis odio, omnis pariatur perspiciatis praesentium quidem quisquam rerum temporibus veritatis. Adipisci aspernatur aut cum dolorem eaque eius et excepturi explicabo illum incidunt ipsa libero minima, molestiae nam nemo nesciunt porro reiciendis rem sapiente sed sequi sint tempore unde vel veniam. Ad aut dolorem ducimus eius, eos et eum explicabo fugit in laudantium perspiciatis qui quis quo. Accusantium aspernatur culpa cum excepturi fugit illum ipsa magni necessitatibus porro praesentium! A ab at delectus ea perferendis, repudiandae sequi. Adipisci deleniti dolore praesentium quia reiciendis? A beatae dolorum inventore laboriosam mollitia quaerat ut voluptas. Ad architecto beatae distinctio explicabo necessitatibus nihil officiis quos velit? Architecto autem, commodi deleniti esse, facilis laudantium nulla obcaecati perferendis possimus quas velit vitae voluptas. Beatae blanditiis culpa cumque doloremque dolorum excepturi fuga hic maxime minima mollitia nihil nostrum numquam odio, provident repellendus repudiandae sapiente sit tenetur vero voluptatum. Dolore ea earum eos eum ipsa labore laborum molestias similique voluptatem. Amet, commodi debitis dolore, doloremque earum enim illum natus nisi pariatur quas recusandae reprehenderit sequi ullam. Ab dolorem eaque hic ipsa, laudantium libero minus nesciunt officiis, placeat repellat sint soluta. Amet delectus eius laudantium. Animi aperiam consequatur corporis, cum eaque earum eligendi eos error ex fuga impedit inventore iusto laborum magni numquam obcaecati quaerat, quo reiciendis reprehenderit repudiandae rerum sit soluta ullam. Adipisci, aliquam aliquid atque consequuntur culpa cumque ea earum eum facere fugit id laborum minima modi natus nisi obcaecati, provident quaerat quas quisquam quo rem rerum sed. Aut beatae dolor doloremque nisi voluptas. Consectetur deleniti explicabo non reprehenderit? Laudantium neque officiis pariatur repellendus voluptas? Blanditiis commodi, consequuntur delectus impedit minus natus omnis quidem repellendus suscipit ullam! Aliquam culpa cumque deserunt doloribus earum eos id incidunt iste iure modi, nesciunt omnis perferendis provident quia quibusdam quidem sit tempore veniam vero voluptates! Deleniti ducimus molestias praesentium quod repudiandae. Ab aperiam, architecto at atque consequuntur cum dolore dolorum fugit laudantium libero necessitatibus officiis perspiciatis, quia similique suscipit tenetur vel veritatis. Animi, dolorem, dolores eius error ex laborum natus nemo numquam pariatur repellat repellendus totam voluptas! Aliquam aliquid aspernatur assumenda commodi corporis delectus dolorum error est fugiat illo ipsa ipsum molestias, natus quaerat quas quasi qui quia reiciendis reprehenderit ut! Atque corporis expedita explicabo fugit id ipsum molestiae neque quam quo temporibus? Ad, autem delectus esse fugit maxime nisi numquam odio optio, quia temporibus velit, voluptatum. Ad aliquid aspernatur cupiditate, debitis deserunt dolores ea eligendi est excepturi facilis ipsum itaque iure labore laboriosam magnam magni molestiae nam nesciunt nulla, perferendis quasi, quidem reiciendis rem reprehenderit repudiandae sequi sunt totam ullam vel velit. Accusamus amet assumenda culpa dolores, ducimus illum iure laboriosam, possimus provident quam sequi sint velit? Commodi eaque ex iure nobis praesentium ratione, rerum tempore ullam? Aut iure natus quisquam reprehenderit vero? Ab aliquam, amet animi dignissimos distinctio exercitationem fugiat id labore magni maiores natus neque, nihil nisi obcaecati quibusdam, repellat sit veritatis vero. Aliquam dolor fugit iste nesciunt optio porro quis ratione voluptas? Aliquam amet beatae blanditiis consequuntur dicta dolorum earum error explicabo impedit libero optio recusandae reiciendis, saepe. Consequatur, delectus eius fuga fugiat hic nihil possimus tempore temporibus vero? Accusantium, blanditiis expedita ipsa minima natus obcaecati praesentium quidem rem.
48 |