-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbutterup.js
313 lines (285 loc) · 14.5 KB
/
butterup.js
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
var butterup = {
options:{
maxToasts: 5, // Max number of toasts that can be on the screen at once
toastLife: 5000, // How long a toast will stay on the screen before fading away
currentToasts: 0, // Current number of toasts on the screen
},
toast:function({title, message, type, location, icon, theme, customIcon, dismissable, onClick, onRender, onTimeout, customHTML, primaryButton, secondaryButton}){
/* Check if the toaster exists. If it doesn't, create it. If it does, check if there are too many toasts on the screen.
If there are too many, delete the oldest one and create a new one. If there aren't too many, create a new one. */
if(document.getElementById('toaster') == null){
// toaster doesn't exist, create it
const toaster = document.createElement('div');
toaster.id = 'toaster';
if(location == null){
toaster.className = 'toaster top-right';
}else{
toaster.className = 'toaster ' + location;
}
// Create the toasting rack inside of the toaster
document.body.appendChild(toaster);
// Create the toasting rack inside of the toaster
if(document.getElementById('butterupRack') == null){
const rack = document.createElement('ol');
rack.id = 'butterupRack';
rack.className = 'rack';
toaster.appendChild(rack);
}
}else{
const toaster = document.getElementById('toaster');
// check what location the toaster is in
toaster.classList.forEach(function(item){
// remove any location classes from the toaster
if(item.includes('top-right') || item.includes('top-center') || item.includes('top-left') || item.includes('bottom-right') || item.includes('bottom-center') || item.includes('bottom-left')){
toaster.classList.remove(item);
}
});
if(location == null){
toaster.className = 'toaster top-right';
}else{
toaster.className = 'toaster ' + location;
}
const rack = document.getElementById('butterupRack');
}
// Check if there are too many toasts on the screen
if(butterup.options.currentToasts >= butterup.options.maxToasts){
// there are too many toasts on the screen, delete the oldest one
var oldestToast = document.getElementById('butterupRack').firstChild;
document.getElementById('butterupRack').removeChild(oldestToast);
butterup.options.currentToasts--;
}
// Create the toast
const toast = document.createElement('li');
butterup.options.currentToasts++;
toast.className = 'butteruptoast';
// Add entrance animation class
toast.className += ' toast-enter';
// if the toast class contains a top or bottom location, add the appropriate class to the toast
if(toaster.className.includes('top-right') || toaster.className.includes('top-center') || toaster.className.includes('top-left')){
toast.className += ' toastDown';
}
if(toaster.className.includes('bottom-right') || toaster.className.includes('bottom-center') || toaster.className.includes('bottom-left')){
toast.className += ' toastUp';
}
toast.id = 'butterupToast-' + butterup.options.currentToasts;
if(type != null){
toast.className += ' ' + type;
}
if(theme != null){
toast.className += ' ' + theme;
}
// Add the toast to the rack
document.getElementById('butterupRack').appendChild(toast);
// check if the user wants an icon
if(icon != null && icon == true){
// add a div inside the toast with a class of icon
const toastIcon = document.createElement('div');
toastIcon.className = 'icon';
toast.appendChild(toastIcon);
// check if the user has added a custom icon
if(customIcon){
toastIcon.innerHTML = customIcon;
}
if(type != null && customIcon == null){
// add the type class to the toast
toast.className += ' ' + type;
if(type == 'success'){
toastIcon.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">'+
'<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />'+
'</svg>';
}
if(type == 'error'){
toastIcon.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">'+
'<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />'+
'</svg>'
}
if(type == 'warning'){
toastIcon.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">'+
'<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />'+
'</svg>'
}
if(type == 'info'){
toastIcon.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">'+
'<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" />'+
'</svg>'
}
}
}
// add a div inside the toast with a class of notif
const toastNotif = document.createElement('div');
toastNotif.className = 'notif';
toast.appendChild(toastNotif);
// add a div inside of notif with a class of desc
const toastDesc = document.createElement('div');
toastDesc.className = 'desc';
toastNotif.appendChild(toastDesc);
// check if the user added a title
if(title != null){
const toastTitle = document.createElement('div');
toastTitle.className = 'title';
toastTitle.innerHTML = title;
toastDesc.appendChild(toastTitle);
}
if(customHTML != null){
const toastHTML = document.createElement('div');
toastHTML.className = 'message';
toastHTML.innerHTML = customHTML;
toastDesc.appendChild(toastHTML);
}
// check if the user added a message
if(message != null){
const toastMessage = document.createElement('div');
toastMessage.className = 'message';
toastMessage.innerHTML = message;
toastDesc.appendChild(toastMessage);
}
// Add buttons if specified
if (primaryButton || secondaryButton) {
const buttonContainer = document.createElement('div');
buttonContainer.className = 'toast-buttons';
toastNotif.appendChild(buttonContainer);
if (primaryButton) {
const primaryBtn = document.createElement('button');
primaryBtn.className = 'toast-button primary';
primaryBtn.textContent = primaryButton.text;
primaryBtn.onclick = function(event) {
event.stopPropagation();
primaryButton.onClick(event);
};
buttonContainer.appendChild(primaryBtn);
}
if (secondaryButton) {
const secondaryBtn = document.createElement('button');
secondaryBtn.className = 'toast-button secondary';
secondaryBtn.textContent = secondaryButton.text;
secondaryBtn.onclick = function(event) {
event.stopPropagation();
secondaryButton.onClick(event);
};
buttonContainer.appendChild(secondaryBtn);
}
}
// Check if the user has mapped any custom click functions
if(onClick && typeof onClick === 'function') {
toast.addEventListener('click', function(event){
// Prevent the click event from triggering dismissal if the toast is dismissable
event.stopPropagation();
onClick(event);
});
}
// Call onRender callback if provided
if(onRender && typeof onRender === 'function') {
onRender(toast);
}
if(dismissable != null && dismissable == true){
// Add a class to the toast to make it dismissable
toast.className += ' dismissable';
// when the item is clicked on, remove it from the DOM
toast.addEventListener('click', function(){
butterup.despawnToast(toast.id);
});
}
// Remove the entrance animation class after the animation has finished
setTimeout(function(){
toast.classList.remove('toast-enter');
}, 300); // Adjust timing as needed
// despawn the toast after the specified time
setTimeout(function(){
if(onTimeout && typeof onTimeout === 'function') {
onTimeout(toast);
}
butterup.despawnToast(toast.id);
}, butterup.options.toastLife);
},
despawnToast(toastId, onClosed){
var toast = document.getElementById(toastId);
if(toast != null){
toast.classList.add('toast-exit');
setTimeout(function(){
try{
toast.parentNode.removeChild(toast);
butterup.options.currentToasts--;
if(onClosed && typeof onClosed === 'function') {
onClosed(toast);
}
}catch(e){
// do nothing
}
// if this was the last toast on the screen, remove the toaster
if(butterup.options.currentToasts == 0){
var toaster = document.getElementById('toaster');
toaster.parentNode.removeChild(toaster);
}
}, 300); // Adjust timing to match your CSS animation duration
}
},
promise: function({promise, loadingMessage, successMessage, errorMessage, location, theme}) {
const toastId = 'butterupToast-' + (butterup.options.currentToasts + 1);
// Create initial loading toast
this.toast({
message: loadingMessage || 'Loading...',
location: location,
theme: theme,
icon: true,
customIcon: '<svg class="animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>',
dismissable: false
});
// Update toast based on promise outcome
return promise.then(
(result) => {
this.updatePromiseToast(toastId, {
type: 'success',
message: successMessage || 'Operation successful',
icon: true
});
return result;
},
(error) => {
this.updatePromiseToast(toastId, {
type: 'error',
message: errorMessage || 'An error occurred',
icon: true
});
throw error;
}
);
},
updatePromiseToast: function(toastId, {type, message, icon}) {
const toast = document.getElementById(toastId);
if (toast) {
toast.className = toast.className.replace(/success|error|warning|info/g, '');
toast.classList.add(type);
const messageEl = toast.querySelector('.message');
if (messageEl) {
messageEl.textContent = message;
}
const iconEl = toast.querySelector('.icon');
if (iconEl && icon) {
iconEl.innerHTML = this.getIconForType(type);
}
// Reset the toast lifetime
clearTimeout(toast.timeoutId);
toast.timeoutId = setTimeout(() => {
this.despawnToast(toastId);
}, this.options.toastLife);
}
},
getIconForType: function(type) {
switch(type) {
case 'success':
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" /></svg>';
case 'error':
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" /></svg>';
case 'warning':
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" /></svg>';
case 'info':
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" /></svg>';
default:
return '';
}
},
};