-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathHTMLNotification.html
156 lines (141 loc) · 6.5 KB
/
HTMLNotification.html
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
152
153
154
155
156
<!--
Author Lililele <[email protected]>
run `const showNotification = notification()` first,
and access global notification by `showNotification(content, type, duration)`
copy the first script tag and css tag to your project and start use!
-->
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
/**
* Create recorders and returns function to show notification
* @param {Element} notificationContainer - optional, if not passed, a container will be generated
* @returns showNotification - Function to show notification.
*/
function notification(notificationContainer = null) {
let notifications = [];
let totalHeight = 0;
if(!notificationContainer) {
notificationContainer = document.createElement('div');
notificationContainer.id = 'notification-container';
document.body.appendChild(notificationContainer);
}
function updateTransform(isRemoving = false, removeNode = null) {
const transform = `translateY(calc(0px - (var(--notification-margin) * ${notifications.length}) - ${totalHeight}px))`;
if(!isRemoving) {
notifications.forEach(e=>e.style.transform = transform)
} else {
const all_notifications = Array.from(removeNode.parentNode.children);
const notifs_after = all_notifications.slice(all_notifications.indexOf(removeNode))
notifs_after.forEach(e=>{
e.style.transitionDuration = '0s';
})
notifications.forEach(e=>e.style.transform = transform)
notificationContainer.clientHeight;
notifs_after.forEach(e=>{
e.style.transitionDuration = '.5s';
})
}
}
async function removeElem(elem, elemHeight) {
if(notifications.filter(e=>e===elem).length) {
const hidePosition = notificationContainer.clientHeight - elem.getBoundingClientRect().top + 20;
const transformStr = elem.style.transform
new Animation(new KeyframeEffect(elem, [
{'transform': transformStr},
{'transform': `${transformStr.slice(0, -2)} - 10px))`},
{'transform': `${transformStr.slice(0, -2)} - 10px + ${hidePosition}px))`},
], { duration: 500, fill: 'forwards' }), document.timeline).play()
await new Promise(s=>setTimeout(s, 500));
notifications = notifications.filter(e=>e!==elem);
totalHeight = Math.max(totalHeight - elemHeight, 0);
updateTransform(true, elem);
elem.remove();
}
}
/**
* Display a notification
* @param {String} content - Content to show in notification
* @param {String} type - Default 'info', available 'info', 'success', 'err' or 'error', 'warn' or'warning'.
* @param {Number} time - Time in millisecond that notification last, default 5000
*/
return function showNotification(content, type = 'info', time = 5000) {
const elem = document.createElement('div');
elem.className = `notification ${type} clickable`;
elem.textContent = content;
notificationContainer.appendChild(elem);
const height = elem.clientHeight;
totalHeight += height;
notifications.push(elem);
updateTransform();
elem.onclick = () => removeElem(elem, height)
setTimeout(()=>removeElem(elem, height), time)
}
}
</script>
<style type="text/css">
#notification-container {
width: 100vw;
height: 100dvh;
position: fixed;
top: 0;
left: 0;
pointer-events: none;
z-index: 100;
--notification-margin: 20px;
}
#notification-container .notification {
position: relative;
top: 100%;
transition-duration: .5s;
margin: auto;
margin-bottom: var(--notification-margin);
width: 20%;
height: fit-content;
padding: 20px;
color: white;
z-index: 5;
pointer-events: initial;
border-radius: 7px;
font-size: 15px;
text-align: center;
}
#notification-container .notification:hover {
cursor: pointer;
}
#notification-container, #notification-container .notification {
display: block;
box-sizing: border-box;
}
#notification-container .info { background-color: dodgerblue; }
#notification-container .success { background-color: limegreen; }
#notification-container .err,
#notification-container .error { background-color: red; }
#notification-container .warn,
#notification-container .warning { background-color: gold; color: black;}
@media screen and (max-width: 1023px) {
#notification-container .notification {
width: 50%;
font-size: 40px;
border-radius: 15px;
}
}
</style>
<script>
let showNotification;
window.onload = () => {
showNotification = notification();
}
function displayNotifications() {
showNotification('This is an info')
showNotification('This is an error', 'error')
showNotification('This is a warn', 'warn')
showNotification('This is a success', 'success')
}
</script>
</head>
<body>
<button onclick="displayNotifications()">click me</button>
</body>
</html>