Skip to content

Instantly share code, notes, and snippets.

@souporserious
Created October 1, 2018 23:19
Show Gist options
  • Save souporserious/d8a2afcd318668c463493b26e57de604 to your computer and use it in GitHub Desktop.
Save souporserious/d8a2afcd318668c463493b26e57de604 to your computer and use it in GitHub Desktop.
Locks all scrollbars by disabling mousewheel
/**
* 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