-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
151 lines (135 loc) · 4.56 KB
/
Copy pathindex.js
File metadata and controls
151 lines (135 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
"use strict";
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory)
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
factory(exports)
} else {
factory((root.commonJsStrict = {}))
}
}(typeof self !== 'undefined' ? self : this, function (exports) {
exports.addBackToTop = addBackToTop
// FUNCTION START
'use strict'
function addBackToTop (params = {}) {
const {
backgroundColor = '#000',
cornerOffset = 20, // px
diameter = 56, // px
ease = inOutSine, // any one from https://www.npmjs.com/package/ease-component will do
id = 'back-to-top',
innerHTML = '<svg viewBox="0 0 24 24"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path></svg>', // https://material.io/icons/#ic_keyboard_arrow_up
onClickScrollTo = 0, // px, or a function returning number
scrollContainer = document.body, // or a DOM element, e.g., document.getElementById('content')
scrollDuration = 100, // ms
showWhenScrollTopIs = 1, // px
size = diameter, // alias for diameter
textColor = '#fff',
zIndex = 1,
className = '' // custom class name
} = params
const scrollContainerIsBody = scrollContainer === document.body
const scrollDocumentElement = scrollContainerIsBody && document.documentElement
appendStyles()
const upEl = appendElement()
let hidden = true
const scrollEmitter = scrollContainerIsBody ? window : scrollContainer
scrollEmitter.addEventListener('scroll', adapt)
adapt()
function adapt () {
getScrollTop() >= showWhenScrollTopIs ?
show() :
hide()
}
function show () {
if (!hidden) { return }
upEl.className = className // Apply the custom class name
hidden = false
}
function hide () {
if (hidden) { return }
upEl.className = `${className} hidden`.trim() // Keep the custom class and add 'hidden'
hidden = true
}
function appendElement () {
const upEl = document.createElement('div')
upEl.id = id
upEl.className = `hidden ${className}`.trim() // Include the custom class in the initial state
upEl.innerHTML = innerHTML
upEl.addEventListener('click', event => {
event.preventDefault()
scrollUp()
})
document.body.appendChild(upEl)
return upEl
}
function appendStyles () {
const svgSize = Math.round(0.43 * size);
const svgTop = Math.round(0.29 * size);
const styles = /*css*/`
#${id} {
background: ${backgroundColor};
border-radius: 50%;
bottom: ${cornerOffset}px;
color: ${textColor};
cursor: pointer;
display: block;
height: ${size}px;
opacity: 1;
outline: none;
position: fixed;
right: ${cornerOffset}px;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
transition: bottom 0.2s, opacity 0.2s;
user-select: none;
width: ${size}px;
z-index: ${zIndex};
}
#${id} svg {
display: block;
fill: currentColor;
height: ${svgSize}px;
margin: ${svgTop}px auto 0;
width: ${svgSize}px;
}
#${id}.hidden {
bottom: -${size}px;
opacity: 0;
}
`;
const styleEl = document.createElement('style');
styleEl.appendChild(document.createTextNode(styles));
document.head.insertAdjacentElement('afterbegin', styleEl);
}
function scrollUp () {
const scrollTo = typeof onClickScrollTo === 'function' ? onClickScrollTo() : onClickScrollTo
const { performance, requestAnimationFrame } = window
if (scrollDuration <= 0 || typeof performance === 'undefined' || typeof requestAnimationFrame === 'undefined') {
return setScrollTop(scrollTo)
}
const start = performance.now()
const initScrollTop = getScrollTop()
const pxsToScrollBy = initScrollTop - scrollTo
requestAnimationFrame(step)
function step (timestamp) {
const progress = Math.min((timestamp - start) / scrollDuration, 1)
setScrollTop(initScrollTop - Math.round(ease(progress) * pxsToScrollBy))
if (progress < 1) { requestAnimationFrame(step) }
}
}
function getScrollTop () {
return scrollContainer.scrollTop || (scrollDocumentElement && document.documentElement.scrollTop || 0)
}
function setScrollTop (value) {
scrollContainer.scrollTop = value
if (scrollDocumentElement) {
document.documentElement.scrollTop = value
}
}
function inOutSine (n) {
return 0.5 * (1 - Math.cos(Math.PI * n))
}
}
// FUNCTION END
}))