2023-12-19 09:13:33 +01:00
|
|
|
class Slider {
|
|
|
|
|
|
2024-02-19 16:36:55 +01:00
|
|
|
imageTypes = ["png", "gif", "webp", "jpg"];
|
|
|
|
|
videoTypes = ["mp4", "webm"];
|
|
|
|
|
|
|
|
|
|
data;
|
2023-12-19 09:13:33 +01:00
|
|
|
element;
|
|
|
|
|
template;
|
2024-02-19 16:36:55 +01:00
|
|
|
slides = [];
|
2023-12-19 09:13:33 +01:00
|
|
|
activeSlide = 0;
|
|
|
|
|
slideDuration;
|
2024-02-19 16:36:55 +01:00
|
|
|
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);
|
2024-02-19 16:36:55 +01:00
|
|
|
let type = this.getType(i);
|
2023-12-19 09:13:33 +01:00
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
// image
|
2024-02-19 16:36:55 +01:00
|
|
|
case "image":
|
2023-12-19 09:13:33 +01:00
|
|
|
let img = document.createElement("img");
|
2024-02-19 16:36:55 +01:00
|
|
|
img.src = "./slides/" + this.data[i].image;
|
2023-12-19 09:13:33 +01:00
|
|
|
slide.querySelector(".image").appendChild(img);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-19 16:36:55 +01:00
|
|
|
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) {
|
2024-02-19 16:36:55 +01:00
|
|
|
// 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;
|
2024-02-19 16:36:55 +01:00
|
|
|
description.prepend(title);
|
2023-12-19 09:13:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// slide
|
2024-02-19 16:36:55 +01:00
|
|
|
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);
|
2024-02-19 16:36:55 +01:00
|
|
|
this.slides.push(slideNode);
|
2023-12-19 09:13:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// observe scroll position
|
|
|
|
|
this.element.onscroll = e => this.onScroll(e);
|
|
|
|
|
|
|
|
|
|
// start auto play
|
2024-02-19 16:36:55 +01:00
|
|
|
this.start();
|
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);
|
|
|
|
|
if(this.activeSlide != newSlide) {
|
|
|
|
|
this.handleVideoPlayback(this.activeSlide, newSlide);
|
|
|
|
|
this.activeSlide = newSlide;
|
|
|
|
|
}
|
2023-12-19 09:13:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
next() {
|
2024-02-19 16:36:55 +01:00
|
|
|
// scroll to next slide
|
2023-12-19 09:13:33 +01:00
|
|
|
let targetSlide = this.activeSlide >= (this.data.length - 1) ? 0 : this.activeSlide + 1;
|
2024-02-19 16:36:55 +01:00
|
|
|
this.element.scrollTo(targetSlide * 800, 0);
|
|
|
|
|
|
2024-02-19 17:12:43 +01:00
|
|
|
this.handleVideoPlayback(this.activeSlide, targetSlide);
|
|
|
|
|
|
|
|
|
|
this.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleVideoPlayback(oldSlideIndex, newSlideIndex) {
|
|
|
|
|
|
|
|
|
|
// stop old video
|
|
|
|
|
if (this.getType(oldSlideIndex) == "video") {
|
|
|
|
|
this.slides[oldSlideIndex].querySelector("video").pause();
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-19 16:36:55 +01:00
|
|
|
// 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");
|
2024-02-19 16:36:55 +01:00
|
|
|
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
|
2024-02-19 16:36:55 +01:00
|
|
|
this.element.scrollTo(targetSlide * 800, 0);
|
|
|
|
|
|
2024-02-19 17:12:43 +01:00
|
|
|
this.handleVideoPlayback(this.activeSlide, targetSlide);
|
|
|
|
|
|
2024-02-19 16:36:55 +01:00
|
|
|
this.start();
|
2023-12-19 09:13:33 +01:00
|
|
|
}
|
|
|
|
|
|
2024-02-19 16:36:55 +01:00
|
|
|
start(timeout = this.slideDuration) {
|
|
|
|
|
clearTimeout(this.slideTimeout);
|
|
|
|
|
this.slideTimeout = setTimeout(() => { this.next(); }, timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|