82 lines
2.4 KiB
JavaScript
82 lines
2.4 KiB
JavaScript
(() => {
|
|
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);
|
|
}
|
|
});
|
|
})();
|