new feat übersetzer und faq
This commit is contained in:
81
backend/static/onboarding.js
Normal file
81
backend/static/onboarding.js
Normal file
@@ -0,0 +1,81 @@
|
||||
(() => {
|
||||
function initOnboarding(dialog) {
|
||||
const slides = Array.from(dialog.querySelectorAll("[data-onboarding-slide]"));
|
||||
const dots = Array.from(dialog.querySelectorAll("[data-onboarding-dot]"));
|
||||
const progress = dialog.querySelector("[data-onboarding-progress]");
|
||||
const backButton = dialog.querySelector("[data-onboarding-back]");
|
||||
const nextButton = dialog.querySelector("[data-onboarding-next]");
|
||||
const completeUrl = dialog.dataset.completeUrl;
|
||||
const progressTemplate = dialog.dataset.progressTemplate || "Step {current} of {total}";
|
||||
|
||||
if (!slides.length || !progress || !backButton || !nextButton || !completeUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
let currentIndex = 0;
|
||||
let completionSent = false;
|
||||
|
||||
const markComplete = () => {
|
||||
if (completionSent) {
|
||||
return;
|
||||
}
|
||||
completionSent = true;
|
||||
window.fetch(completeUrl, {
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: { "X-Requested-With": "XMLHttpRequest" },
|
||||
keepalive: true,
|
||||
}).catch(() => {
|
||||
completionSent = false;
|
||||
});
|
||||
};
|
||||
|
||||
const finish = () => {
|
||||
markComplete();
|
||||
dialog.close();
|
||||
};
|
||||
|
||||
const render = () => {
|
||||
slides.forEach((slide, index) => {
|
||||
slide.hidden = index !== currentIndex;
|
||||
});
|
||||
dots.forEach((dot, index) => {
|
||||
dot.classList.toggle("is-active", index <= currentIndex);
|
||||
});
|
||||
progress.textContent = progressTemplate
|
||||
.replace("{current}", String(currentIndex + 1))
|
||||
.replace("{total}", String(slides.length));
|
||||
backButton.hidden = currentIndex === 0;
|
||||
const isLast = currentIndex === slides.length - 1;
|
||||
nextButton.textContent = isLast ? nextButton.dataset.finishLabel : nextButton.dataset.nextLabel;
|
||||
};
|
||||
|
||||
backButton.addEventListener("click", () => {
|
||||
currentIndex = Math.max(0, currentIndex - 1);
|
||||
render();
|
||||
});
|
||||
|
||||
nextButton.addEventListener("click", () => {
|
||||
if (currentIndex === slides.length - 1) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
currentIndex += 1;
|
||||
render();
|
||||
});
|
||||
|
||||
dialog.addEventListener("cancel", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
render();
|
||||
dialog.showModal();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const dialog = document.querySelector("[data-onboarding-dialog]");
|
||||
if (dialog) {
|
||||
initOnboarding(dialog);
|
||||
}
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user