Created
December 11, 2019 22:13
-
-
Save laphilosophia/70d731c098041821e8cc08a2db782354 to your computer and use it in GitHub Desktop.
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
export default () => { | |
let docElem = document.documentElement | |
let active = false | |
let hasDeactivated = false | |
let eventsBound = false | |
let mouseWheelHandler | |
let scrollHandler | |
const scrollCallback = (offset, event, callback) => { | |
if (!active) return true | |
let delta | |
let numPixelsPerStep | |
let change | |
let newOffset | |
let docOffset | |
let scrollWidth | |
let winWidth | |
let maxOffset | |
delta = 0 | |
numPixelsPerStep = 10 | |
docOffset = (docElem ? docElem.offsetWidth : 0) || 0 | |
scrollWidth = document.body.scrollWidth || 0 | |
winWidth = docElem ? docElem.clientWidth : 0 | |
maxOffset = Math.max(docOffset, scrollWidth) - winWidth | |
if (Math.abs(event.wheelDeltaX) > Math.abs(event.wheelDeltaY)) return true | |
if (event.detail) { | |
delta = event.detail * -240 | |
} else if (event.wheelDelta) { | |
delta = event.wheelDelta * 5 | |
} | |
change = delta / 120 * numPixelsPerStep | |
newOffset = offset.x - change | |
if (newOffset >= 0 && newOffset <= maxOffset) { | |
offset.x = newOffset | |
offset.setByScript = true | |
window.scrollTo(offset.x, offset.y) | |
} else if (offset.x !== 0 && offset.x !== maxOffset) { | |
offset.x = newOffset > maxOffset ? maxOffset : 0 | |
offset.setByScript = true | |
window.scrollTo(offset.x, offset.y) | |
} | |
if (typeof callback === "function") { | |
callback(offset) | |
} | |
return false | |
} | |
const getOffset = axis => { | |
axis = axis.toUpperCase() | |
let pageOffset = "page" + axis + "Offset" | |
let scrollValue = "scroll" + axis | |
let scrollDir = "scroll" + (axis === "X" ? "Left" : "Top") | |
return window[pageOffset] || window[scrollValue] || (function () { | |
var rootElem = document.documentElement || document.body.parentNode | |
return ((typeof rootElem[scrollDir] === "number") ? rootElem : document.body)[scrollDir] | |
}()) | |
} | |
const bindEvents = (offset, cb) => { | |
const callback = e => { | |
e = e || window.event | |
let shouldPreventDefault = scrollCallback(offset, e, cb) === false | |
if (shouldPreventDefault) { | |
if (e.preventDefault && e.stopPropagation) { | |
e.preventDefault() | |
e.stopPropagation() | |
} else { | |
return false | |
} | |
} | |
} | |
const updateOffsetOnScroll = () => { | |
if (!offset.setByScript) { | |
offset.x = getOffset("x") | |
offset.y = getOffset("y") | |
} | |
offset.setByScript = false | |
} | |
mouseWheelHandler = callback | |
scrollHandler = updateOffsetOnScroll | |
if (window.addEventListener) { | |
if ("onmousewheel" in window) { | |
window.addEventListener("mousewheel", mouseWheelHandler, false) | |
window.addEventListener("scroll", scrollHandler, false) | |
} else { | |
window.addEventListener("DOMMouseScroll", mouseWheelHandler, false) | |
window.addEventListener("scroll", scrollHandler, false) | |
} | |
} else { | |
document.attachEvent("onmousewheel", mouseWheelHandler) | |
window.attachEvent("onscroll", scrollHandler) | |
} | |
} | |
const unbindEvents = () => { | |
if (!mouseWheelHandler && !scrollHandler) return | |
if (window.removeEventListener) { | |
if ("onmousewheel" in window) { | |
window.removeEventListener("mousewheel", mouseWheelHandler, false) | |
window.removeEventListener("scroll", scrollHandler, false) | |
} else { | |
window.removeEventListener("DOMMouseScroll", mouseWheelHandler, false) | |
window.removeEventListener("scroll", scrollHandler, false) | |
} | |
} else { | |
document.detachEvent("onmousewheel", mouseWheelHandler) | |
window.detachEvent("onscroll", scrollHandler) | |
} | |
} | |
const deactivateAllScrolling = e => { | |
e.preventDefault() | |
e.stopPropagation() | |
return false | |
} | |
return { | |
activate: callback => { | |
active = true | |
if (!eventsBound) { | |
let offset = { | |
x: 0, | |
y: 0 | |
} | |
bindEvents(offset, callback) | |
eventsBound = true | |
} | |
if (hasDeactivated) { | |
if (window.addEventListener) { | |
window.removeEventListener("scroll", deactivateScrolling, true) | |
} else { | |
window.detachEvent("onscroll", deactivateScrolling) | |
} | |
hasDeactivated = false | |
} | |
}, | |
deactivate: () => { | |
active = false | |
if (eventsBound) { | |
unbindEvents() | |
eventsBound = false | |
} | |
}, | |
deactivateAllScrolling: () => { | |
active = false | |
hasDeactivated = true | |
if (window.addEventListener) { | |
window.addEventListener("scroll", deactivateScrolling, true) | |
} else { | |
window.attachEvent("onscroll", deactivateScrolling) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment