@internetguru/scrolltopable
Version:
Scrolltopable is a JavaScript module that provides ultimate scroll-to-top functionality. No dependencies and frameworks, pure JavaScript!
113 lines (108 loc) • 3.8 kB
JavaScript
var Config = {}
Config.content = '↑' // Button content (raw HTML)
Config.title = 'Top' // Button title
Config.id = 'js-scrolltopable' // Button id and class name
Config.visibleClass = 'js-scrolltopable--visible' // Class for visible button
Config.activeClass = 'js-scrolltopable--active' // Class for active button
Config.extraClass = 'noprint' // List of extra classes separated by space
Config.hideBeforeTop = 500 // No-show zone from the top (px)
Config.showBeforeBottom = 500 // No-hide zone from the button (px)
Config.showAfterUp = 200 // Show the button after scrolling up (px)
Config.hideAfterDown = 200 // Hide the button after scrolling down (px)
Config.activeTime = 0 // Keep `activeClass` after clicking the button (ms)
Config.scrollActionDelay = 200 // Wait before evaluating scrolling (ms)
let Scrolltopable = function () {
let
windowScrollTimeOut = null,
button = null,
displayed = false,
lastScrollTop = 0,
initCss = function (styles) {
const style = document.createElement('style')
style.innerHTML = Config.styles
document.head.appendChild(style)
},
getScrollTop = function () {
return document.body.scrollTop
|| document.documentElement.scrollTop
},
getDocumentHeight = function () {
const body = document.body
const html = document.documentElement
return Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight)
- Math.max(html.clientHeight, window.innerHeight || 0)
},
hideButton = function () {
displayed = false
button.classList.remove(Config.visibleClass)
},
showButton = function () {
displayed = true
button.classList.add(Config.visibleClass)
},
processScroll = function () {
window.clearTimeout(windowScrollTimeOut)
windowScrollTimeOut = window.setTimeout(function () {
if (button.classList.contains(Config.activeClass)) {
return;
}
const scrollTop = getScrollTop()
const delta = scrollTop - lastScrollTop
const deltaAbs = Math.abs(delta)
if (getDocumentHeight() - scrollTop < Config.showBeforeBottom) {
showButton()
} else if (
scrollTop <= Config.hideBeforeTop
|| (delta > 0 && deltaAbs > Config.hideAfterDown)
) {
hideButton()
} else if (deltaAbs > Config.showAfterUp) {
showButton()
}
lastScrollTop = scrollTop
}, Config.scrollActionDelay)
},
initPosition = function () {
const scrollTop = getScrollTop()
if (scrollTop <= Config.hideBeforeTop) {
return
}
showButton()
lastScrollTop = scrollTop
},
fireEvents = function () {
window.addEventListener('scroll', processScroll, false)
button.addEventListener('click', (event) => {
window.scrollTo(0, 0)
if (Config.activeTime == 0) {
return;
}
button.classList.add(Config.activeClass)
window.setTimeout(() => {
button.classList.remove(Config.activeClass)
hideButton()
}, Config.activeTime)
})
},
createButton = function () {
button = document.createElement('a')
button.id = Config.id
button.title = Config.title
button.className = `${Config.extraClass} ${Config.id}`
let span = document.createElement('span')
span.innerHTML = Config.content
button.appendChild(span)
document.body.appendChild(button)
}
return {
init: function (cfg) {
Config = {...Config, ...cfg}
createButton()
initCss(Config.styles)
fireEvents()
initPosition()
}
}
}
let instance = new Scrolltopable()
export { instance as Scrolltopable }