new Vue({ el: "#app", data: { files: [], index: 0, interval: null, carouselTimeout: 20000, carouselActive: true, videoSrc: null, isDownloading: false, controlsTimeout: null, }, methods: { next: function () { if (this.index + 1 < this.files.length) { this.index++; } else { this.index = 0; } this.refreshVideoSrc(); }, nextClick: function () { this.next(); this.startCarousel(); }, prev: function () { if (this.index - 1 >= 0) { this.index--; } else { this.index = this.files.length - 1; } this.refreshVideoSrc(); }, prevClick: function () { this.next(); this.startCarousel(); }, loadData: function () { this.isDownloading = true; const prom = fetch('api/files').then(response => response.json()); prom.then( data => { this.files = data.resource || []; this.startCarousel(); this.refreshVideoSrc(); this.isDownloading = false; setTimeout(() => this.loadData(), (this.files.length*this.carouselTimeout)+1000); } ); return prom; }, refreshVideoSrc: function () { // force video src reload this.videoSrc = null; setTimeout(() => { if (this.files[this.index].mime.includes('video')) { this.videoSrc = '/files/'+this.files[this.index].basename; } }, 100); }, startCarousel: function (time = this.carouselTimeout) { this.carouselActive = true; clearInterval(this.interval); this.interval = setInterval(this.next, time); }, stopCarousel: function () { this.carouselActive = false; clearInterval(this.interval); }, toggleCarousel: function () { if (this.carouselActive) { this.stopCarousel(); } else { this.startCarousel(); } }, toggleControls: function () { clearTimeout(this.controlsTimeout) if (document.querySelector('.controls').style.display === "none") { document.querySelector('.controls').style.display = ""; this.animateCSS('.floatBtn.left', 'fadeInLeft'); this.animateCSS('.floatBtn.right', 'fadeInRight'); this.animateCSS('.floatBtn.bottom', 'fadeInUp'); this.controlsTimeout = setTimeout(() => this.toggleControls(), 15000); } else { Promise.all([ this.animateCSS('.floatBtn.left', 'fadeOutLeft'), this.animateCSS('.floatBtn.right', 'fadeOutRight'), this.animateCSS('.floatBtn.bottom', 'fadeOutDown') ]).then(data => { document.querySelector('.controls').style.display = "none" }); } }, animateCSS: function (element, animation, prefix = 'animate__') { // We create a Promise and return it return new Promise((resolve, reject) => { const animationName = `${prefix}${animation}`; const node = document.querySelector(element); node.classList.add(`${prefix}animated`, animationName); // When the animation ends, we clean the classes and resolve the Promise function handleAnimationEnd() { node.classList.remove(`${prefix}animated`, animationName); node.removeEventListener('animationend', handleAnimationEnd); resolve('Animation ended'); } node.addEventListener('animationend', handleAnimationEnd); }) } }, mounted() { this.loadData().then(data => { setTimeout(() => { this.animateCSS('.floatBtn.left', 'fadeInLeft'); this.animateCSS('.floatBtn.right', 'fadeInRight'); this.animateCSS('.floatBtn.bottom', 'fadeInUp'); this.controlsTimeout = setTimeout(() => this.toggleControls(), 2500); }, 0); }); } })