├── .babelrc
├── .editorconfig
├── .gitignore
├── .npmignore
├── README.md
├── demo
├── index.html
├── index.js
└── webpack.config.js
├── package.json
└── src
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015"
4 | ],
5 | "plugins": [
6 | "transform-object-rest-spread",
7 | "add-module-exports"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | lib
3 | demo/dist
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .babelrc
2 | src
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # isolated-scroll
2 |
3 | Prevent scroll events from bubbling up to parent elements — [View demo](https://markdalgleish.github.io/isolated-scroll).
4 |
5 | ```bash
6 | $ npm install --save isolated-scroll
7 | ```
8 |
9 | ## Usage
10 |
11 | ```js
12 | const isolatedScroll = require('isolated-scroll');
13 |
14 | // Isolate scrolling of selected element:
15 | const unbindHandlers = isolatedScroll(element);
16 |
17 | // Remove isolated scroll behaviour:
18 | unbindHandlers();
19 | ```
20 |
21 | ## Todo
22 |
23 | - Add tests.
24 |
25 | ## License
26 |
27 | [MIT](https://markdalgleish.mit-license.org/)
28 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | isolated-scroll demo
5 |
6 |
7 |
8 |
9 |
25 |
26 |
27 |
28 |
29 |
isolated-scroll demo
30 |
31 |
With isolated-scroll:
32 |
33 |
117 |
118 |
Without isolated-scroll:
119 |
120 |
121 |
122 | - List item.
123 | - List item.
124 | - List item.
125 | - List item.
126 | - List item.
127 | - List item.
128 | - List item.
129 | - List item.
130 | - List item.
131 | - List item.
132 | - List item.
133 | - List item.
134 | - List item.
135 | - List item.
136 | - List item.
137 | - List item.
138 | - List item.
139 | - List item.
140 | - List item.
141 | - List item.
142 | - List item.
143 | - List item.
144 | - List item.
145 | - List item.
146 | - List item.
147 | - List item.
148 | - List item.
149 | - List item.
150 | - List item.
151 | - List item.
152 | - List item.
153 | - List item.
154 | - List item.
155 | - List item.
156 | - List item.
157 | - List item.
158 | - List item.
159 | - List item.
160 | - List item.
161 | - List item.
162 | - List item.
163 | - List item.
164 | - List item.
165 | - List item.
166 | - List item.
167 | - List item.
168 | - List item.
169 | - List item.
170 | - List item.
171 | - List item.
172 | - List item.
173 | - List item.
174 | - List item.
175 | - List item.
176 | - List item.
177 | - List item.
178 | - List item.
179 | - List item.
180 | - List item.
181 | - List item.
182 | - List item.
183 | - List item.
184 | - List item.
185 | - List item.
186 | - List item.
187 | - List item.
188 | - List item.
189 | - List item.
190 | - List item.
191 | - List item.
192 | - List item.
193 | - List item.
194 | - List item.
195 | - List item.
196 | - List item.
197 | - List item.
198 | - List item.
199 | - List item.
200 | - List item.
201 | - List item.
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
--------------------------------------------------------------------------------
/demo/index.js:
--------------------------------------------------------------------------------
1 | require('./index.html');
2 |
3 | import isolatedScroll from '../src';
4 |
5 | const el = document.getElementById('isolated-scroll');
6 | isolatedScroll(el);
7 |
--------------------------------------------------------------------------------
/demo/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | module.exports = {
4 | context: __dirname,
5 |
6 | entry: './index.js',
7 |
8 | output: {
9 | path: path.resolve(__dirname, 'dist'),
10 | filename: 'script.js'
11 | },
12 |
13 | module: {
14 | loaders: [
15 | {
16 | test: /\.html$/,
17 | loader: 'file?name=[name].[ext]'
18 | },
19 | {
20 | test: /\.js$/,
21 | loader: 'babel'
22 | }
23 | ]
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "isolated-scroll",
3 | "version": "0.1.0",
4 | "description": "Prevent scoll events from bubbling up to parent elements",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --config demo/webpack.config.js",
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "build": "rm -rf lib/ && babel -d lib/ src/",
10 | "prepublish": "npm run build",
11 | "clean": "rm -rf demo/dist",
12 | "build": "npm run clean && webpack --config demo/webpack.config.js",
13 | "deploy": "npm run build && gh-pages -d demo/dist"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/markdalgleish/isolated-scroll.git"
18 | },
19 | "author": "Mark Dalgleish",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/markdalgleish/isolated-scroll/issues"
23 | },
24 | "homepage": "https://github.com/markdalgleish/isolated-scroll#readme",
25 | "devDependencies": {
26 | "babel-cli": "^6.11.4",
27 | "babel-core": "^6.13.2",
28 | "babel-loader": "^6.2.4",
29 | "babel-plugin-add-module-exports": "^0.2.1",
30 | "babel-plugin-transform-object-rest-spread": "^6.8.0",
31 | "babel-preset-es2015": "^6.13.2",
32 | "babel-register": "^6.11.6",
33 | "file-loader": "^0.9.0",
34 | "gh-pages": "^0.11.0",
35 | "webpack": "^1.13.1",
36 | "webpack-dev-server": "^1.14.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const calculateHeight = el => {
2 | // Source adapted from: http://youmightnotneedjquery.com/#outer_height_with_margin
3 | let height = el.offsetHeight;
4 | const { marginTop, marginBottom } = getComputedStyle(el);
5 |
6 | height += parseInt(marginTop, 10) + parseInt(marginBottom, 10);
7 | return height;
8 | };
9 |
10 | // Source adapted from: http://stackoverflow.com/a/16324762
11 | const makeHandler = el => event => {
12 | const { scrollTop, scrollHeight } = el;
13 | const { type, detail, wheelDelta } = event;
14 | const height = calculateHeight(el);
15 | const delta = (type === 'DOMMouseScroll' ? detail * -40 : wheelDelta);
16 | const up = delta > 0;
17 |
18 | const prevent = () => {
19 | event.stopPropagation();
20 | event.preventDefault();
21 | event.returnValue = false;
22 |
23 | return false;
24 | };
25 |
26 | if (!up && -delta > scrollHeight - height - scrollTop) {
27 | el.scrollTop = scrollHeight;
28 | return prevent();
29 | } else if (up && delta > scrollTop) {
30 | el.scrollTop = 0;
31 | return prevent();
32 | }
33 | };
34 |
35 | export default el => {
36 | const handler = makeHandler(el);
37 |
38 | const addEvent = (el.addEventListener || el.attachEvent).bind(el);
39 | const removeEvent = (el.removeEventListener || el.detachEvent).bind(el);
40 |
41 | addEvent('mousewheel', handler);
42 | addEvent('DOMMouseScroll', handler);
43 |
44 | return () => {
45 | removeEvent('mousewheel', handler);
46 | removeEvent('DOMMouseScroll', handler);
47 | };
48 | };
49 |
--------------------------------------------------------------------------------