285 lines
13 KiB
JavaScript
285 lines
13 KiB
JavaScript
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:
|
|
'<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.7281 3.88396C17.1624 2.44407 19.2604 2.41383 20.4219 3.57981C21.5856 4.74798 21.5542 6.85922 20.1189 8.30009L17.6951 10.7333C17.4028 11.0268 17.4037 11.5017 17.6971 11.794C17.9906 12.0863 18.4655 12.0854 18.7578 11.7919L21.1816 9.35869C23.0929 7.43998 23.3329 4.37665 21.4846 2.5212C19.6342 0.663551 16.5776 0.905664 14.6653 2.82536L9.81768 7.69182C7.90639 9.61053 7.66643 12.6739 9.5147 14.5293C9.80702 14.8228 10.2819 14.8237 10.5754 14.5314C10.8688 14.2391 10.8697 13.7642 10.5774 13.4707C9.41376 12.3026 9.4451 10.1913 10.8804 8.75042L15.7281 3.88396Z" fill="rgb(0,191,255)"></path><path opacity="0.5" d="M14.4846 9.4707C14.1923 9.17724 13.7174 9.17632 13.4239 9.46864C13.1305 9.76097 13.1296 10.2358 13.4219 10.5293C14.5856 11.6975 14.5542 13.8087 13.1189 15.2496L8.27129 20.1161C6.83696 21.556 4.73889 21.5862 3.57742 20.4202C2.41376 19.2521 2.4451 17.1408 3.8804 15.6999L6.30424 13.2666C6.59657 12.9732 6.59565 12.4983 6.30219 12.206C6.00873 11.9137 5.53386 11.9146 5.24153 12.208L2.81769 14.6413C0.906387 16.56 0.666428 19.6234 2.5147 21.4788C4.36518 23.3365 7.42173 23.0944 9.334 21.1747L14.1816 16.3082C16.0929 14.3895 16.3329 11.3262 14.4846 9.4707Z" fill="#000000"></path></svg>',
|
|
success:
|
|
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="#20b2aa"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',
|
|
info: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="#8F8F8FFF"><path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" /></svg>',
|
|
warning:
|
|
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="orange"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /></svg>',
|
|
error: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="red"><path stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>',
|
|
update: '<svg class="notification-animation" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M32 3C35.8083 3 39.5794 3.75011 43.0978 5.20749C46.6163 6.66488 49.8132 8.80101 52.5061 11.4939C55.199 14.1868 57.3351 17.3837 58.7925 20.9022C60.2499 24.4206 61 28.1917 61 32C61 35.8083 60.2499 39.5794 58.7925 43.0978C57.3351 46.6163 55.199 49.8132 52.5061 52.5061C49.8132 55.199 46.6163 57.3351 43.0978 58.7925C39.5794 60.2499 35.8083 61 32 61C28.1917 61 24.4206 60.2499 20.9022 58.7925C17.3837 57.3351 14.1868 55.199 11.4939 52.5061C8.801 49.8132 6.66487 46.6163 5.20749 43.0978C3.7501 39.5794 3 35.8083 3 32C3 28.1917 3.75011 24.4206 5.2075 20.9022C6.66489 17.3837 8.80101 14.1868 11.4939 11.4939C14.1868 8.80099 17.3838 6.66487 20.9022 5.20749C24.4206 3.7501 28.1917 3 32 3L32 3Z" stroke="#e0e0e0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"></path><path d="M32 3C36.5778 3 41.0906 4.08374 45.1692 6.16256C49.2477 8.24138 52.7762 11.2562 55.466 14.9605C58.1558 18.6647 59.9304 22.9531 60.6448 27.4748C61.3591 31.9965 60.9928 36.6232 59.5759 40.9762" stroke="#42424a" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"></path></svg>',
|
|
};
|
|
|
|
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 = "<b>" + options.title + "</b>";
|
|
// 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 = "<b>" + options.title + "</b>";
|
|
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 = "<small>" + options.text + "</small>";
|
|
notificationMessage.appendChild(notificationText);
|
|
|
|
if (options.close) {
|
|
let notificationDismissButton = document.createElement("button");
|
|
notificationDismissButton.className = "notification-dismiss-btn";
|
|
notificationDismissButton.innerHTML =
|
|
'<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16 8L8 16M12 12L16 16M8 8L10 10" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
|
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();
|
|
|