function Toastra() { let options = {}; let globals = { type: "default", mode: "default-mode", position: "top-right", duration: 3000, selector: "body", icon: null, progressbar: false, close: false, title: "", badge: null, text: "Hi Guys, i'am Toastra!", onComplete: null, onCompleteParams: {}, offset: { top: "", left: "", right: "", bottom: "", }, style: { color: "", background: "", }, animation: "slide-right", classname: "", }; const icons = { default: '', success: '', info: '', warning: '', error: '', update: '', }; function config(default_option = {}) { Object.assign(globals, default_option); } function notify(option) { options = { ...globals, ...option }; let animationTime = 500; let notification = document.createElement("div"); notification.className = `notification ${options.position} ${options.mode} ${options.classname}`; notification.id = "notification"; Object.keys(options.offset).forEach((key) => { notification.style[key] = options.offset[key]; }); let notificationContainer = document.createElement("div"); notificationContainer.className = `notification-container notification-toast-${options.type} ${options.animation} ${options.classname}`; Object.keys(options.style).forEach((key) => { notificationContainer.style[key] = options.style[key]; }); notificationContainer.classList.add("slide-in"); let notificationBlock = document.createElement("div"); notificationBlock.className = "notification-block"; notificationContainer.appendChild(notificationBlock); if (options.icon !== null) { let notificationIcon = document.createElement("div"); notificationIcon.className = "notification-icon"; notificationIcon.innerHTML = icons[options.type] ?? icons.default; notificationBlock.appendChild(notificationIcon); } let notificationMessage = document.createElement("div"); notificationMessage.className = "notification-message"; notificationBlock.appendChild(notificationMessage); if (options.title.length !== 0) { let notificationTitle = document.createElement("div"); notificationTitle.className = "notification-title"; // notificationTitle.innerHTML = "" + options.title + ""; // notificationMessage.appendChild(notificationTitle); // NEW: badge element (instead of data-attr + ::before) if (options.badge) { const badgeEl = document.createElement("span"); badgeEl.className = "notification-badge"; badgeEl.textContent = String(options.badge).toUpperCase(); notificationTitle.appendChild(badgeEl); } // Title text (keep your current behavior) if (options.title && options.title.length) { const titleText = document.createElement("span"); titleText.className = "notification-title"; titleText.innerHTML = "" + options.title + ""; notificationTitle.appendChild(titleText); } notificationMessage.appendChild(notificationTitle); // NEW: optional subtitle (e.g. domain shown below) if (options.subtitle && options.subtitle.length) { const subtitleEl = document.createElement("div"); subtitleEl.className = "notification-subtitle"; subtitleEl.textContent = options.subtitle; notificationMessage.appendChild(subtitleEl); } } let notificationText = document.createElement("div"); notificationText.className = "notification-text"; notificationText.innerHTML = "" + options.text + ""; notificationMessage.appendChild(notificationText); if (options.close) { let notificationDismissButton = document.createElement("button"); notificationDismissButton.className = "notification-dismiss-btn"; notificationDismissButton.innerHTML = ''; notificationBlock.appendChild(notificationDismissButton); notificationDismissButton.addEventListener("click", () => { notificationContainer.classList.remove("slide-in"); notificationContainer.classList.add("slide-out"); notificationContainer.addEventListener("animationend", () => { notificationContainer.remove(); }); }); } if (options.progressbar && options.duration !== -1) { notificationContainer.addEventListener("animationend", () => { let currentProgress = 0; let notificationProgressbar = document.createElement("div"); notificationProgressbar.className = "notification-progressbar"; notificationBlock.appendChild(notificationProgressbar); let count = setInterval(() => { if (currentProgress < 100) { currentProgress += 1; notificationProgressbar.dataset.duration = (options.duration ?? globals.duration); notificationProgressbar.style.width = "100%"; // currentProgress + "%"; } else { clearInterval(count); } }, (options.duration ?? globals.duration) / 100); }); } if (document.getElementById(notification.id) === null) { document.querySelector(options.selector).appendChild(notification); } document .getElementById(notification.id) .insertBefore( notificationContainer, document.getElementById(notification.id).children[0], ); function removeToast() { notificationContainer.classList.remove("slide-in"); notificationContainer.classList.add("slide-out"); notificationContainer.addEventListener("animationend", () => { notificationContainer.remove(); }); } const totalDelay = (options.duration ?? globals.duration) + animationTime; setTimeout(() => { const funcName = options.onComplete; if (typeof funcName === "string") { if (typeof window[funcName] === "function") { window[funcName](options.onCompleteParams); } else if (typeof window.Callbacks?.[funcName] === "function") { window.Callbacks[funcName](options.onCompleteParams); } else { console.warn(`[Toastra] Callback '${funcName}' nicht gefunden.`); } } else if (typeof options.onComplete === "function") { options.onComplete(options.onCompleteParams); } if (options.duration !== -1) { removeToast(); } }, totalDelay + 500); // if ( // typeof options.onComplete === "string" && // typeof window.Callbacks[options.onComplete] === "function" // ) { // window.Callbacks[options.onComplete](options.onCompleteParams); // } else { // for (const [key, value] of Object.entries(options)) { // setTimeout(() => { // if (key === "duration" && value !== -1) // { // removeToast(); // } // }, (options.duration ?? globals.duration) + animationTime); // } // } } function createQueue() { const queue = []; let isRunning = false; function runQueue() { if (queue.length === 0) { isRunning = false; return; } isRunning = true; const next = queue.shift(); // Wrappe onComplete, damit nach dem Toast automatisch der nächste kommt const userOnComplete = next.onComplete; next.onComplete = (params) => { // Benutzerdefinierte Funktion aufrufen (optional) if (typeof userOnComplete === 'function') { userOnComplete(params); } else if (typeof userOnComplete === 'string') { if (typeof window[userOnComplete] === 'function') { window[userOnComplete](params); } else if (typeof window.Callbacks?.[userOnComplete] === 'function') { window.Callbacks[userOnComplete](params); } } runQueue(); // Weiter mit dem nächsten Toast }; // Toast anzeigen toastra.notify(next); } return { add(toast) { queue.push(toast); if (!isRunning) runQueue(); } }; } let globalQueue = null; function getGlobalQueue() { if (!globalQueue) { globalQueue = createQueue(); } return globalQueue; } return { notify, queue: getGlobalQueue, config, }; } window.toastra = Toastra();