Created
October 1, 2018 23:19
-
-
Save souporserious/d8a2afcd318668c463493b26e57de604 to your computer and use it in GitHub Desktop.
Locks all scrollbars by disabling mousewheel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Lock all scrollbars by disabling mousewheel and locking scrollbars in position | |
* Optionally provide an element to allow it to scroll when hovered | |
*/ | |
const lockedScrolls = [] | |
function lockScroll(node) { | |
const scrollCoords = new WeakMap() | |
const preventDefault = event => event.preventDefault() | |
const mouseOver = () => window.removeEventListener('wheel', preventDefault) | |
const mouseOut = () => window.addEventListener('wheel', preventDefault) | |
const mouseDown = event => { | |
if (event.target !== node) { | |
scrollCoords.set(event.target, { | |
x: event.target.scrollLeft, | |
y: event.target.scrollTop, | |
}) | |
} | |
} | |
const wheelLock = event => { | |
const scrollableDistance = node.scrollHeight - node.offsetHeight | |
if ( | |
(event.deltaY > 0 && node.scrollTop >= scrollableDistance) || | |
(event.deltaY < 0 && node.scrollTop <= 0) | |
) { | |
event.preventDefault() | |
} | |
} | |
const scrollLock = event => { | |
const scrollElement = | |
event.target === document ? document.documentElement : event.target | |
const scrollElementCoords = scrollCoords.get(scrollElement) | |
if (scrollElementCoords) { | |
scrollElement.scrollLeft = scrollElementCoords.x | |
scrollElement.scrollTop = scrollElementCoords.y | |
} | |
} | |
const enable = () => { | |
if (node) { | |
node.addEventListener('mouseover', mouseOver) | |
node.addEventListener('mouseout', mouseOut) | |
} | |
window.addEventListener('mousedown', mouseDown) | |
window.addEventListener('wheel', wheelLock) | |
window.addEventListener('scroll', scrollLock, true) | |
} | |
const disable = () => { | |
if (node) { | |
node.removeEventListener('mouseover', mouseOver) | |
node.removeEventListener('mouseout', mouseOut) | |
window.removeEventListener('wheel', preventDefault) | |
} | |
window.removeEventListener('mousedown', mouseDown) | |
window.removeEventListener('wheel', wheelLock) | |
window.removeEventListener('scroll', scrollLock, true) | |
} | |
const index = lockedScrolls.length | |
// check if we need to disable any current scroll locks | |
if (lockedScrolls.length > 0) { | |
lockedScrolls[lockedScrolls.length - 1].disable() | |
} | |
// store the scroll lock enable/disable methods so we can disable them when | |
// new ones are created or enable them when old ones are destroyed | |
lockedScrolls.push({ | |
enable, | |
disable, | |
}) | |
enable() | |
return () => { | |
disable() | |
// remove this scroll lock from stored scroll locks | |
lockedScrolls.splice(index, 1) | |
// enable the previous scroll lock if any are left | |
if (lockedScrolls.length > 0) { | |
lockedScrolls[lockedScrolls.length - 1].enable() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment