vCarousel/src/vCarousel.ts

79 lines
3.8 KiB
TypeScript

const Flickity = require("flickity");
/// La fonction vCarousel reçoit un tableau d'ids des conteneurs HTML des vidéos à afficher successivement.
/// Le tableau n'est pas dédoublonné, pour rester libre d'afficher plusieurs fois la même vidéo durant un tour du carrousel.
/// On peut éventuellement fournir l'id du conteneur de la première vidéo à afficher lors de l'appel
/// Ou encore indiqué qu'aucune ne doit être affichée sans action en passant une chaîne vide
/// Par défaut la première vidéo de la liste sera affichée
export const vCarousel = (vContainers:string[], firstVideoId?:string) : void =>
{
interface videoDOM
{
id: string;
containerElt: HTMLElement;
videoElt: HTMLMediaElement;
}
// On commence par vérifier que les ids de conteneurs fournis sont correctes.
// C'est-à-dire qu'il s'agit bien d'éléments HTML contenant au moins une vidéo.
const realVContainers : videoDOM[] = [];
for(let containerId of vContainers)
{
let checkContainerExist=document.getElementById(containerId);
if(checkContainerExist===null)
console.error("Aucun élément HTML trouvé dans la page pour l'id fourni "+containerId);
else
{
let checkVideoExist=<HTMLMediaElement>document.querySelector("#"+containerId+" video");
if(checkVideoExist===null)
console.error("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id "+containerId);
else
realVContainers.push({id:containerId, containerElt:checkContainerExist, videoElt:checkVideoExist});
}
}
// Si firstVideoId a été fourni, on vérifie aussi qu'il est valide.
if(firstVideoId!==undefined && firstVideoId!=="" && (realVContainers.findIndex(video => video.id === firstVideoId) === -1))
{
console.error("Vous avez fourni l'id de la vidéo à afficher en premier ("+firstVideoId+"), mais il n'est pas valide.");
firstVideoId=undefined;
}
// Il doit rester au moins deux vidéos à faire tourner.
let nbVContainers=realVContainers.length;
if(nbVContainers < 2)
console.error("Il faut fournir au moins deux conteneurs valides pour faire tourner le carrousel.");
else
{
// Tous les conteneurs sont cachés, sauf celui demandé.
// La fin de lecture d'une vidéo provoque son remplacement par la suivante.
for (let i = 0; i < nbVContainers; i++)
{
let vContainer=realVContainers[i].containerElt;
let video=realVContainers[i].videoElt;
if((firstVideoId!==undefined && realVContainers[i].id!==firstVideoId) || (firstVideoId===undefined && i!==0) || firstVideoId==="")
vContainer.style.display = "none";
else
vContainer.style.display = "block";// nécessaire dans le cas d'un réaffichage.
video.addEventListener("ended", function()
{
vContainer.style.display = "none";
let nextVContainer: HTMLElement, nextHash: string;
if(i < (nbVContainers-1))
{
nextVContainer=realVContainers[i+1].containerElt;
nextHash=realVContainers[i+1].id;
}
else
{
nextVContainer=realVContainers[0].containerElt;
nextHash=realVContainers[0].id;
}
nextVContainer.style.display = "block";
// On adapte l'ancre de l'url de manière à ce qu'elle soit cohérente avec la vidéo affichée.
// Attention car cela peut provoquer un déplacement dans la page la première fois pour atteindre l'ancre.
window.location.assign("#"+nextHash);
});
}
}
}