132 lines
4.0 KiB
JavaScript
132 lines
4.0 KiB
JavaScript
class ToastManager {
|
|
constructor() {
|
|
this.container = document.getElementById('toast-container');
|
|
this.toastCount = 0;
|
|
}
|
|
|
|
show(type = 'info', message = '', title = '', duration = 4000) {
|
|
const toastId = `toast-${++this.toastCount}`;
|
|
const icons = {
|
|
success: 'fas fa-check-circle',
|
|
error: 'fas fa-exclamation-circle',
|
|
warning: 'fas fa-exclamation-triangle',
|
|
info: 'fas fa-info-circle'
|
|
};
|
|
|
|
const titles = {
|
|
success: title || 'Success',
|
|
error: title || 'Error',
|
|
warning: title || 'Warning',
|
|
info: title || 'Information'
|
|
};
|
|
|
|
const toastHTML = `
|
|
<div class="toast custom-toast ${type}" id="${toastId}" role="alert" aria-live="assertive" aria-atomic="true">
|
|
<div class="toast-header">
|
|
<i class="toast-icon ${icons[type]} ${type}"></i>
|
|
<strong class="me-auto">${titles[type]}</strong>
|
|
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
</div>
|
|
<div class="toast-body">
|
|
${message}
|
|
</div>
|
|
<div class="toast-progress" style="width: 100%"></div>
|
|
</div>
|
|
`;
|
|
|
|
this.container.insertAdjacentHTML('afterbegin', toastHTML);
|
|
const toastElement = document.getElementById(toastId);
|
|
const progressBar = toastElement.querySelector('.toast-progress');
|
|
|
|
// Show toast
|
|
const bsToast = new bootstrap.Toast(toastElement, {
|
|
autohide: false // We'll handle auto-hide manually for progress bar
|
|
});
|
|
bsToast.show();
|
|
|
|
// Progress bar animation
|
|
if (duration > 0) {
|
|
setTimeout(() => {
|
|
progressBar.style.transition = `width ${duration}ms linear`;
|
|
progressBar.style.width = '0%';
|
|
}, 100);
|
|
|
|
// Auto hide
|
|
setTimeout(() => {
|
|
this.hide(toastElement);
|
|
}, duration);
|
|
}
|
|
|
|
// Handle manual close
|
|
toastElement.addEventListener('hidden.bs.toast', () => {
|
|
toastElement.remove();
|
|
});
|
|
|
|
return toastElement;
|
|
}
|
|
|
|
hide(toastElement) {
|
|
toastElement.classList.add('toast-slide-out');
|
|
setTimeout(() => {
|
|
const bsToast = bootstrap.Toast.getInstance(toastElement);
|
|
if (bsToast) {
|
|
bsToast.hide();
|
|
}
|
|
}, 300);
|
|
}
|
|
|
|
success(message, title, duration) {
|
|
return this.show('success', message, title, duration);
|
|
}
|
|
|
|
error(message, title, duration) {
|
|
return this.show('error', message, title, duration);
|
|
}
|
|
|
|
warning(message, title, duration) {
|
|
return this.show('warning', message, title, duration);
|
|
}
|
|
|
|
info(message, title, duration) {
|
|
return this.show('info', message, title, duration);
|
|
}
|
|
|
|
clear() {
|
|
const toasts = this.container.querySelectorAll('.toast');
|
|
toasts.forEach(toast => {
|
|
const bsToast = bootstrap.Toast.getInstance(toast);
|
|
if (bsToast) {
|
|
bsToast.hide();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Create global instance
|
|
const toastManager = new ToastManager();
|
|
|
|
// Global function for easy use
|
|
function showToast(type, message, title, duration) {
|
|
return toastManager.show(type, message, title, duration);
|
|
}
|
|
|
|
// Convenience functions
|
|
function showSuccess(message, title, duration) {
|
|
return toastManager.success(message, title, duration);
|
|
}
|
|
|
|
function showError(message, title, duration) {
|
|
return toastManager.error(message, title, duration);
|
|
}
|
|
|
|
function showWarning(message, title, duration) {
|
|
return toastManager.warning(message, title, duration);
|
|
}
|
|
|
|
function showInfo(message, title, duration) {
|
|
return toastManager.info(message, title, duration);
|
|
}
|
|
|
|
function clearAllToasts() {
|
|
toastManager.clear();
|
|
} |