Files
Tooloop-Packages/onboarding/package/assets/data/js/Slider.js
T

155 lines
5.0 KiB
JavaScript
Raw Normal View History

2023-12-19 09:13:33 +01:00
class Slider {
imageTypes = ["png", "gif", "webp", "jpg"];
videoTypes = ["mp4", "webm"];
data;
2023-12-19 09:13:33 +01:00
element;
2024-02-21 10:20:24 +01:00
progressBar;
2023-12-19 09:13:33 +01:00
template;
slides = [];
2023-12-19 09:13:33 +01:00
activeSlide = 0;
slideDuration;
slideTimeout;
2023-12-19 09:13:33 +01:00
constructor(element, template, data, slideDuration = 10000) {
this.element = document.querySelector(element);
this.template = document.querySelector(template);
this.data = data;
this.slideDuration = slideDuration;
this.ip = location.host;
// append slides
for (let i = 0; i < this.data.length; i++) {
let slide = this.template.content.cloneNode(true);
let type = this.getType(i);
2023-12-19 09:13:33 +01:00
switch (type) {
// image
case "image":
2023-12-19 09:13:33 +01:00
let img = document.createElement("img");
img.src = "./slides/" + this.data[i].image;
2023-12-19 09:13:33 +01:00
slide.querySelector(".image").appendChild(img);
break;
case "video":
2023-12-19 09:13:33 +01:00
let video = document.createElement("video");
video.autoplay = true;
video.loop = true;
video.muted = true;
video.src = "./slides/" + this.data[i].image;
slide.querySelector(".image").appendChild(video);
break;
default:
break;
}
// texts
let hasText = this.data[i].title || this.data[i].description;
if (hasText) {
// let title = slide.querySelector(".description h1");
// title.textContent = this.data[i].title;
let description = slide.querySelector(".description");
description.innerHTML = marked.parse(this.data[i].description);
let title = document.createElement("h1");
2023-12-19 09:13:33 +01:00
title.textContent = this.data[i].title;
description.prepend(title);
2023-12-19 09:13:33 +01:00
}
// slide
this.element.appendChild(slide);
2023-12-19 09:13:33 +01:00
let slideNode = document.querySelector(element + " .slide:last-child");
slideNode.id = "slide-" + i;
slideNode.classList.toggle("no-text", !hasText);
this.slides.push(slideNode);
2023-12-19 09:13:33 +01:00
}
2024-02-21 10:20:24 +01:00
// append progress bar
let progressBar = document.createElement("div");
progressBar.classList.add("progressBar");
this.progressBar = this.element.appendChild(progressBar);
document.querySelector(":root").style.setProperty("--slide-duration", this.slideDuration / 1000 + "s");
2023-12-19 09:13:33 +01:00
// observe scroll position
this.element.onscroll = e => this.onScroll(e);
2024-02-21 10:58:51 +01:00
// keyboard shortcuts
document.addEventListener("keydown", (e) => {
2024-02-23 11:36:39 +01:00
if (e.code === "ArrowLeft" || e.code === "ArrowRight")
e.preventDefault();
2024-02-21 10:58:51 +01:00
});
document.addEventListener("keyup", (e) => {
if (e.code === "ArrowLeft") this.previous();
if (e.code === "ArrowRight") this.next();
});
2023-12-19 09:13:33 +01:00
// start auto play
2024-02-21 10:20:24 +01:00
this.startTimeout();
2023-12-19 09:13:33 +01:00
}
onScroll(e) {
2024-02-19 17:12:43 +01:00
let newSlide = Math.round(e.target.scrollLeft / 800);
2024-02-21 10:20:24 +01:00
if (this.activeSlide != newSlide) {
2024-02-19 17:12:43 +01:00
this.handleVideoPlayback(this.activeSlide, newSlide);
this.activeSlide = newSlide;
2024-02-21 10:20:24 +01:00
this.startTimeout();
2024-02-19 17:12:43 +01:00
}
2023-12-19 09:13:33 +01:00
}
next() {
// scroll to next slide
2023-12-19 09:13:33 +01:00
let targetSlide = this.activeSlide >= (this.data.length - 1) ? 0 : this.activeSlide + 1;
this.element.scrollTo(targetSlide * 800, 0);
2024-02-19 17:12:43 +01:00
this.handleVideoPlayback(this.activeSlide, targetSlide);
}
handleVideoPlayback(oldSlideIndex, newSlideIndex) {
// stop old video
if (this.getType(oldSlideIndex) == "video") {
this.slides[oldSlideIndex].querySelector("video").pause();
}
// start new video and timeout
2024-02-19 17:12:43 +01:00
if (this.getType(newSlideIndex) == "video") {
let video = this.slides[newSlideIndex].querySelector("video");
video.currentTime = 0
video.play();
}
2023-12-19 09:13:33 +01:00
}
previous() {
let targetSlide = this.activeSlide <= 0 ? (this.data.length - 1) : this.activeSlide - 1
this.element.scrollTo(targetSlide * 800, 0);
2024-02-19 17:12:43 +01:00
this.handleVideoPlayback(this.activeSlide, targetSlide);
2023-12-19 09:13:33 +01:00
}
2024-02-21 10:20:24 +01:00
startTimeout(timeout = this.slideDuration) {
clearTimeout(this.slideTimeout);
this.slideTimeout = setTimeout(() => { this.next(); }, timeout);
2024-02-21 10:20:24 +01:00
// restart progress animation
// https://css-tricks.com/restart-css-animation/
this.progressBar.classList.remove("playing");
void this.progressBar.offsetWidth;
this.progressBar.classList.add("playing");
}
getType(slideIndex) {
let type = this.data[slideIndex].image.split('.').pop().toLowerCase();
if (this.imageTypes.includes(type)) return "image";
if (this.videoTypes.includes(type)) return "video";
return false;
2023-12-19 09:13:33 +01:00
}
}