Nouvelle version vCarousel en POO

This commit is contained in:
Fabrice PENHOËT 2021-04-29 17:40:20 +02:00
parent 21d7e82264
commit 67aecd77db
10 changed files with 460 additions and 4107 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "vCarousel", "name": "vCarousel",
"version": "0.2.0", "version": "0.3.0",
"description": "Video carousel, a new video appears when the previous one finishes playing.", "description": "Video carousel, a new video appears when the previous one finishes playing.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@ -29,6 +29,6 @@
"flickity": "^2.2.2" "flickity": "^2.2.2"
}, },
"dependenciesComments": { "dependenciesComments": {
"flickity": "Cette dépendance peut être retirée (ainsi que ce commentaire :)), si vous n'utilisez pas Flickity dans votre application" "flickity": "This dependency can be removed (as well as this comment!), if you don't use Flickity in your application"
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,25 @@
"use strict"; "use strict";
exports.__esModule = true; Object.defineProperty(exports, "__esModule", { value: true });
/// Exemple d'utilisation simple de vCarousel avec 3 vidéos // Exemple d'utilisation simple de vCarousel avec 3 vidéos
var vCarousel_1 = require("./vCarousel"); var vCarousel_1 = require("./vCarousel");
try { try {
// Liste des id des contenants des vidéos à faire tourner : // Initialisation vCarousel :
var videosContainers_1 = ["vFunanbule", "vForgeron", "vCircuit"]; var videosContainers = ["vFunanbule", "vForgeron", "vCircuit"];
var testvCarousel_1 = new vCarousel_1.vCarousel();
testvCarousel_1.vContainers = videosContainers;
// Si un id est fourni par l'url, on affiche cette vidéo en premier : // Si un id est fourni par l'url, on affiche cette vidéo en premier :
if (window.location.hash !== undefined && window.location.hash !== "") if (window.location.hash !== undefined && window.location.hash !== "")
vCarousel_1.vCarousel(videosContainers_1, { firstVideoId: window.location.hash.replace("#", "") }); testvCarousel_1.firstVideoId = window.location.hash.replace("#", "");
else // On lance le carrousel :
vCarousel_1.vCarousel(videosContainers_1); testvCarousel_1.run();
// Dans le cas où l'utilisateur clique pour sélectionner une vidéo à afficher, on actualise l'affichage : // Dans le cas où l'utilisateur clique pour sélectionner une vidéo à afficher, on actualise l'affichage :
var selectLinks = document.querySelectorAll(".selectVideo"); var selectLinks = document.querySelectorAll(".selectVideo");
var _loop_1 = function (i) { var _loop_1 = function (i) {
var link = selectLinks[i]; var link = selectLinks[i];
link.addEventListener("click", function (e) { link.addEventListener("click", function (e) {
vCarousel_1.vCarousel(videosContainers_1, { firstVideoId: link.hash.replace("#", ""), playFirstVideo: true }); // ici je demande à ce que la lecture de la vidéo choisie soit lancée automatiquement. testvCarousel_1.firstVideoId = link.hash.replace("#", "");
testvCarousel_1.playFirstVideo = true; // ici je demande à ce que la lecture de la vidéo choisie soit lancée automatiquement.
testvCarousel_1.run();
}); });
}; };
for (var i = 0; i < selectLinks.length; i++) { for (var i = 0; i < selectLinks.length; i++) {

View File

@ -1,15 +1,18 @@
/// Exemple d'utilisation simple de vCarousel avec 3 vidéos // Exemple d'utilisation simple de vCarousel avec 3 vidéos
import { vCarousel } from "./vCarousel"; import { vCarousel } from "./vCarousel";
try try
{ {
// Liste des id des contenants des vidéos à faire tourner : // Initialisation vCarousel :
const videosContainers=["vFunanbule", "vForgeron", "vCircuit"]; const videosContainers=["vFunanbule", "vForgeron", "vCircuit"];
const testvCarousel=new vCarousel();
testvCarousel.vContainers=videosContainers;
// Si un id est fourni par l'url, on affiche cette vidéo en premier : // Si un id est fourni par l'url, on affiche cette vidéo en premier :
if(window.location.hash!==undefined && window.location.hash!=="") if(window.location.hash!==undefined && window.location.hash!=="")
vCarousel(videosContainers, { firstVideoId:window.location.hash.replace("#","") }); testvCarousel.firstVideoId=window.location.hash.replace("#","");
else // On lance le carrousel :
vCarousel(videosContainers); testvCarousel.run();
// Dans le cas où l'utilisateur clique pour sélectionner une vidéo à afficher, on actualise l'affichage : // Dans le cas où l'utilisateur clique pour sélectionner une vidéo à afficher, on actualise l'affichage :
let selectLinks=document.querySelectorAll(".selectVideo"); let selectLinks=document.querySelectorAll(".selectVideo");
@ -18,7 +21,9 @@ try
let link=<HTMLAnchorElement>selectLinks[i]; let link=<HTMLAnchorElement>selectLinks[i];
link.addEventListener("click", function(e) link.addEventListener("click", function(e)
{ {
vCarousel(videosContainers, { firstVideoId:link.hash.replace("#",""), playFirstVideo:true });// ici je demande à ce que la lecture de la vidéo choisie soit lancée automatiquement. testvCarousel.firstVideoId=link.hash.replace("#","");
testvCarousel.playFirstVideo=true;// ici je demande à ce que la lecture de la vidéo choisie soit lancée automatiquement.
testvCarousel.run();
}); });
} }
} }

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
exports.__esModule = true; Object.defineProperty(exports, "__esModule", { value: true });
/// Exemple d'utilisation de vCarousel avec 3 vidéos, proposées via un carrousel d'images Flickity // Exemple d'utilisation de vCarousel avec 3 vidéos, proposées via un carrousel d'images Flickity
var Flickity = require("flickity"); var Flickity = require("flickity");
var vCarousel_1 = require("./vCarousel"); var vCarousel_1 = require("./vCarousel");
// Cette fonction sert à synchroniser si besoin l'image sélectionnée dans le carrousel Flickity avec le hash de l'url. // Cette fonction sert à synchroniser si besoin l'image sélectionnée dans le carrousel Flickity avec le hash de l'url.
@ -25,7 +25,7 @@ var selectFlickityForHash = function (flickityCarousel, urlHash) {
console.error("L'ancre fournie par l'url n'a pas été trouvée dans le carrousel Flickity."); console.error("L'ancre fournie par l'url n'a pas été trouvée dans le carrousel Flickity.");
}; };
try { try {
// Carrousel Flickity : // Initialisation Flickity :
var imgCarousel = document.querySelector(".img-carousel"); var imgCarousel = document.querySelector(".img-carousel");
var flktyCarousel_1 = new Flickity(imgCarousel, { var flktyCarousel_1 = new Flickity(imgCarousel, {
// options : https://flickity.metafizzy.co/options.html // options : https://flickity.metafizzy.co/options.html
@ -33,23 +33,30 @@ try {
cellAlign: "center", cellAlign: "center",
contain: true, contain: true,
rightToLeft: true, rightToLeft: true,
wrapAround: true wrapAround: true,
}); });
// Liste des id des contenants des vidéos à faire tourner : // Initialisation vCarousel :
var videosContainers_1 = ["vFunanbule", "vForgeron", "vCircuit"]; var videosContainers = ["vFunanbule", "vForgeron", "vCircuit"];
var testvCarousel_1 = new vCarousel_1.vCarousel();
testvCarousel_1.vContainers = videosContainers;
// Si un id est fourni par l'url, on affiche cette vidéo en premier : // Si un id est fourni par l'url, on affiche cette vidéo en premier :
if (window.location.hash !== undefined && window.location.hash !== "") { if (window.location.hash !== undefined && window.location.hash !== "") {
vCarousel_1.vCarousel(videosContainers_1, { firstVideoId: window.location.hash.replace("#", "") }); testvCarousel_1.firstVideoId = window.location.hash.replace("#", "");
selectFlickityForHash(flktyCarousel_1, location.hash); selectFlickityForHash(flktyCarousel_1, location.hash);
} }
else else
vCarousel_1.vCarousel(videosContainers_1, { firstVideoId: "" }); // dans cet exemple, on cache toutes les vidéos avant que l'utilisateur ne fasse son choix dans le carrousel d'images. testvCarousel_1.firstVideoId = ""; // dans cet exemple, on cache toutes les vidéos avant que l'utilisateur ne fasse son choix dans le carrousel d'images.
testvCarousel_1.run();
// Lorsque l'utilisateur clique sur une des images pour sélectionner une vidéo à afficher, on actualise l'affichage : // Lorsque l'utilisateur clique sur une des images pour sélectionner une vidéo à afficher, on actualise l'affichage :
var selectLinks = document.querySelectorAll(".selectVideo"); var selectLinks = document.querySelectorAll(".selectVideo");
var _loop_1 = function (i) { var _loop_1 = function (i) {
var link = selectLinks[i]; var link = selectLinks[i];
link.addEventListener("click", function (e) { link.addEventListener("click", function (e) {
vCarousel_1.vCarousel(videosContainers_1, { firstVideoId: link.hash.replace("#", ""), playFirstVideo: true, playNextVideos: true }); // les vidéos successives sont lancées automatiquement testvCarousel_1.firstVideoId = link.hash.replace("#", "");
// ici on demande la lecture automatique de toutes les vidéos :
testvCarousel_1.playFirstVideo = true;
testvCarousel_1.playNextVideo = true;
testvCarousel_1.run();
}); });
}; };
for (var i = 0; i < selectLinks.length; i++) { for (var i = 0; i < selectLinks.length; i++) {

View File

@ -1,4 +1,4 @@
/// Exemple d'utilisation de vCarousel avec 3 vidéos, proposées via un carrousel d'images Flickity // Exemple d'utilisation de vCarousel avec 3 vidéos, proposées via un carrousel d'images Flickity
const Flickity = require("flickity"); const Flickity = require("flickity");
import { vCarousel } from "./vCarousel"; import { vCarousel } from "./vCarousel";
@ -30,7 +30,7 @@ const selectFlickityForHash = (flickityCarousel:any, urlHash:string) : void =>
try try
{ {
// Carrousel Flickity : // Initialisation Flickity :
const imgCarousel = document.querySelector(".img-carousel"); const imgCarousel = document.querySelector(".img-carousel");
const flktyCarousel = new Flickity(imgCarousel, const flktyCarousel = new Flickity(imgCarousel,
{ {
@ -42,16 +42,20 @@ try
wrapAround: true, wrapAround: true,
}); });
// Liste des id des contenants des vidéos à faire tourner : // Initialisation vCarousel :
const videosContainers=["vFunanbule", "vForgeron", "vCircuit"]; const videosContainers=["vFunanbule", "vForgeron", "vCircuit"];
const testvCarousel=new vCarousel();
testvCarousel.vContainers=videosContainers;
// Si un id est fourni par l'url, on affiche cette vidéo en premier : // Si un id est fourni par l'url, on affiche cette vidéo en premier :
if(window.location.hash!==undefined && window.location.hash!=="") if(window.location.hash!==undefined && window.location.hash!=="")
{ {
vCarousel(videosContainers, { firstVideoId:window.location.hash.replace("#","") }); testvCarousel.firstVideoId=window.location.hash.replace("#","");
selectFlickityForHash(flktyCarousel, location.hash); selectFlickityForHash(flktyCarousel, location.hash);
} }
else else
vCarousel(videosContainers, { firstVideoId:"" }); // dans cet exemple, on cache toutes les vidéos avant que l'utilisateur ne fasse son choix dans le carrousel d'images. testvCarousel.firstVideoId="";// dans cet exemple, on cache toutes les vidéos avant que l'utilisateur ne fasse son choix dans le carrousel d'images.
testvCarousel.run();
// Lorsque l'utilisateur clique sur une des images pour sélectionner une vidéo à afficher, on actualise l'affichage : // Lorsque l'utilisateur clique sur une des images pour sélectionner une vidéo à afficher, on actualise l'affichage :
let selectLinks=document.querySelectorAll(".selectVideo"); let selectLinks=document.querySelectorAll(".selectVideo");
@ -60,7 +64,11 @@ try
let link=<HTMLAnchorElement>selectLinks[i]; let link=<HTMLAnchorElement>selectLinks[i];
link.addEventListener("click", function(e) link.addEventListener("click", function(e)
{ {
vCarousel(videosContainers, { firstVideoId:link.hash.replace("#",""),playFirstVideo:true,playNextVideos:true });// les vidéos successives sont lancées automatiquement testvCarousel.firstVideoId=link.hash.replace("#","");
// ici on demande la lecture automatique de toutes les vidéos :
testvCarousel.playFirstVideo=true;
testvCarousel.playNextVideo=true;
testvCarousel.run();
}); });
} }
// De même quand le hash change, on adapte l'item sélectionné de flickity // De même quand le hash change, on adapte l'item sélectionné de flickity

View File

@ -1,82 +1,124 @@
"use strict"; "use strict";
exports.__esModule = true; Object.defineProperty(exports, "__esModule", { value: true });
exports.vCarousel = void 0; exports.vCarousel = void 0;
var Flickity = require("flickity"); var vCarousel = /** @class */ (function () {
/// La fonction vCarousel reçoit un tableau d'ids des conteneurs HTML des vidéos à afficher successivement. function vCarousel() {
/// Le tableau n'est pas dédoublonné, pour rester libre d'afficher plusieurs fois la même vidéo durant un tour du carrousel. this._vContainers = [];
/// Plusieurs options sont possibles : this._playFirstVideo = false;
/// - firstVideoId est une chaîne permettant de fournir l'id du conteneur de la première vidéo à afficher lors de l'appel. Par défaut la première vidéo de la liste sera affichée. Si on passe une chaîne vide, aucune ne sera affichée. this._playNextVideos = false;
/// - playFirstVideo et playNextVideos demandent de lancer automatiquement la lecture respectivement de la vidéo demandée et de celles automatiquement chargée par la fonction. Ce n'est pas le cas par défaut et peut être bloqué par le navigateur. this._noStop = false;
/// - noStop permet de demander à ce que les vidéos continuent à tourner même quand toutes ont été affichées. Par défaut, le carrousel s'arrête. this.nbVContainers = 0;
exports.vCarousel = function (vContainers, opts) { }
if (opts === void 0) { opts = {}; } Object.defineProperty(vCarousel.prototype, "vContainers", {
// On commence par vérifier que les ids de conteneurs fournis sont correctes. // Les ids reçus doivent correspondre à des éléments HTML contenant une vidéo.
// C'est-à-dire qu'il s'agit bien d'éléments HTML contenant au moins une vidéo. set: function (vContainersIds) {
var realVContainers = []; for (var _i = 0, vContainersIds_1 = vContainersIds; _i < vContainersIds_1.length; _i++) {
for (var _i = 0, vContainers_1 = vContainers; _i < vContainers_1.length; _i++) { var containerId = vContainersIds_1[_i];
var containerId = vContainers_1[_i];
var checkContainerExist = document.getElementById(containerId); var checkContainerExist = document.getElementById(containerId);
if (checkContainerExist === null) if (checkContainerExist === null)
console.error("Aucun élément HTML trouvé dans la page pour l'id fourni " + containerId); throw new Error("Aucun élément HTML trouvé dans la page pour l'id " + containerId + ".");
else { else {
var checkVideoExist = document.querySelector("#" + containerId + " video"); var checkVideoExist = document.querySelector("#" + containerId + " video");
if (checkVideoExist === null) if (checkVideoExist === null)
console.error("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id " + containerId); throw new Error("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id " + containerId + ".");
else else
realVContainers.push({ id: containerId, containerElt: checkContainerExist, videoElt: checkVideoExist }); this._vContainers.push({ id: containerId, containerElt: checkContainerExist, videoElt: checkVideoExist });
} }
} }
// Si opts.firstVideoId a été fourni, on vérifie aussi qu'il est valide. // Il faut au moins 2 vidéos à faire tourner.
if (opts.firstVideoId !== undefined && opts.firstVideoId !== "" && (realVContainers.findIndex(function (video) { return video.id === opts.firstVideoId; }) === -1)) { this.nbVContainers = this._vContainers.length;
console.error("Vous avez fourni l'id de la vidéo à afficher en premier (" + opts.firstVideoId + "), mais il n'est pas valide."); if (this.nbVContainers < 2)
opts.firstVideoId = undefined; throw new Error("Il faut fournir au moins deux conteneurs de vidéo pour pouvoir faire tourner le carrousel.");
} },
// Il doit rester au moins deux vidéos à faire tourner. enumerable: false,
var nbVContainers = realVContainers.length; configurable: true
if (nbVContainers < 2) });
console.error("Il faut fournir au moins deux conteneurs valides pour faire tourner le carrousel."); Object.defineProperty(vCarousel.prototype, "firstVideoId", {
else { // Si this._firstVideoId a été fourni, on vérifie qu'il est présent dans la liste des conteneurs de vidéos.
set: function (firstVideo) {
if (firstVideo !== "" && this._vContainers.findIndex(function (video) { return video.id === firstVideo; }) === -1)
console.error("Vous avez fourni l'id de la vidéo à afficher en premier (" + this._firstVideoId + "), mais il n'est pas valide.");
else
this._firstVideoId = firstVideo;
},
enumerable: false,
configurable: true
});
Object.defineProperty(vCarousel.prototype, "playFirstVideo", {
set: function (playFirstVideo) {
this._playFirstVideo = playFirstVideo;
},
enumerable: false,
configurable: true
});
Object.defineProperty(vCarousel.prototype, "playNextVideo", {
set: function (playNextVideo) {
this._playNextVideos = playNextVideo;
},
enumerable: false,
configurable: true
});
Object.defineProperty(vCarousel.prototype, "noStop", {
set: function (noStop) {
this._noStop = noStop;
},
enumerable: false,
configurable: true
});
vCarousel.prototype.run = function () {
var vCarousel = this; // évite les confusions avec le "this" des événements.
if (vCarousel.nbVContainers < 2) // dans le cas où on lancerait run() sans passer par le setter.
throw new Error("Il faut fournir au moins deux conteneurs valides pour faire tourner le carrousel.");
var _loop_1 = function (i) { var _loop_1 = function (i) {
var vContainer = realVContainers[i].containerElt; var vContainer = vCarousel._vContainers[i].containerElt;
var video = realVContainers[i].videoElt; var video = vCarousel._vContainers[i].videoElt;
if ((opts.firstVideoId !== undefined && realVContainers[i].id !== opts.firstVideoId) || (opts.firstVideoId === undefined && i !== 0) || opts.firstVideoId === "") if ((vCarousel._firstVideoId !== undefined && vCarousel._vContainers[i].id !== vCarousel._firstVideoId) || (vCarousel._firstVideoId === undefined && i !== 0) || vCarousel._firstVideoId === "")
vContainer.style.display = "none"; vContainer.style.display = "none";
else { else {
// Si une vidéo est déjà visible et en cours de lecture, je la stoppe et remets à 0
// Sinon elle risque de continuer à être lue tout en étant cachée.
if (vCarousel.currentVideo !== undefined && !vCarousel.currentVideo.paused) {
vCarousel.currentVideo.pause();
vCarousel.currentVideo.currentTime = 0;
}
// J'affiche la première vidéo et j'essaye de la lancer, si cela est demandé
vContainer.style.display = "block"; vContainer.style.display = "block";
if (opts.firstVideoId !== undefined && opts.playFirstVideo === true) vCarousel.currentVideo = video;
if (vCarousel._playFirstVideo === true)
video.play(); video.play();
} }
nbTurn = 0; nbTurn = 0;
video.addEventListener("ended", function () { video.addEventListener("ended", function () {
// Sauf si demandé en option, le carrousel s'arrête lorsque toutes les vidéos ont été affichées une fois. // Sauf si demandé, le carrousel s'arrête lorsque toutes les vidéos ont été affichées une fois.
if (nbTurn < (nbVContainers - 1) || opts.noStop === true) { if (nbTurn < (vCarousel.nbVContainers - 1) || vCarousel._noStop === true) {
vContainer.style.display = "none"; vContainer.style.display = "none";
var nextVContainer = void 0, nextVideo = void 0, nextHash = void 0; var nextVContainer = void 0, nextVideo = void 0, nextHash = void 0;
if (i < (nbVContainers - 1)) { if (i < (vCarousel.nbVContainers - 1)) {
nextVContainer = realVContainers[i + 1].containerElt; nextVContainer = vCarousel._vContainers[i + 1].containerElt;
nextVideo = realVContainers[i + 1].videoElt; nextVideo = vCarousel._vContainers[i + 1].videoElt;
nextHash = realVContainers[i + 1].id; nextHash = vCarousel._vContainers[i + 1].id;
} }
else { else {
nextVContainer = realVContainers[0].containerElt; nextVContainer = vCarousel._vContainers[0].containerElt;
nextVideo = realVContainers[0].videoElt; nextVideo = vCarousel._vContainers[0].videoElt;
nextHash = realVContainers[0].id; nextHash = vCarousel._vContainers[0].id;
} }
nextVContainer.style.display = "block"; 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. // 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. // Attention car cela peut provoquer un déplacement dans la page pour atteindre l'ancre.
window.location.assign("#" + nextHash); window.location.assign("#" + nextHash);
if (opts.playNextVideos === true) if (vCarousel._playNextVideos === true)
nextVideo.play(); nextVideo.play();
vCarousel.currentVideo = nextVideo;
nbTurn++; nbTurn++;
} }
}); });
}; };
var nbTurn; var nbTurn;
// Tous les conteneurs sont cachés, sauf celui demandé. for (var i = 0; i < vCarousel.nbVContainers; i++) {
// La fin de lecture d'une vidéo provoque son remplacement par la suivante.
for (var i = 0; i < nbVContainers; i++) {
_loop_1(i); _loop_1(i);
} }
}
}; };
return vCarousel;
}());
exports.vCarousel = vCarousel;

View File

@ -1,22 +1,9 @@
const Flickity = require("flickity"); // La classe vCarousel est instanciée en recevant 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.
interface options // Plusieurs options sont possibles :
{ // - firstVideoId est une chaîne permettant de fournir l'id du conteneur de la première vidéo à afficher lors de l'appel. Par défaut la première vidéo de la liste sera affichée. Si on passe une chaîne vide, aucune ne sera affichée.
firstVideoId?: string; // - playFirstVideo et playNextVideos demandent de lancer automatiquement la lecture respectivement de la vidéo demandée et de celles automatiquement chargée par la fonction. Ce n'est pas le cas par défaut et peut être bloqué par le navigateur.
playFirstVideo?: boolean; // - noStop permet de demander à ce que les vidéos continuent à tourner même quand toutes ont été affichées. Par défaut, le carrousel s'arrête.
playNextVideos?: boolean;
noStop?: boolean;
}
/// 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.
/// Plusieurs options sont possibles :
/// - firstVideoId est une chaîne permettant de fournir l'id du conteneur de la première vidéo à afficher lors de l'appel. Par défaut la première vidéo de la liste sera affichée. Si on passe une chaîne vide, aucune ne sera affichée.
/// - playFirstVideo et playNextVideos demandent de lancer automatiquement la lecture respectivement de la vidéo demandée et de celles automatiquement chargée par la fonction. Ce n'est pas le cas par défaut et peut être bloqué par le navigateur.
/// - noStop permet de demander à ce que les vidéos continuent à tourner même quand toutes ont été affichées. Par défaut, le carrousel s'arrête.
export const vCarousel = (vContainers:string[], opts:options={}) : void =>
{
interface videoDOM interface videoDOM
{ {
id: string; id: string;
@ -24,77 +11,117 @@ export const vCarousel = (vContainers:string[], opts:options={}) : void =>
videoElt: HTMLMediaElement; videoElt: HTMLMediaElement;
} }
// On commence par vérifier que les ids de conteneurs fournis sont correctes. export class vCarousel
// C'est-à-dire qu'il s'agit bien d'éléments HTML contenant au moins une vidéo. {
const realVContainers : videoDOM[] = []; private _vContainers: videoDOM[] = [];
for(let containerId of vContainers) private _firstVideoId: string;
private _playFirstVideo: boolean = false;
private _playNextVideos: boolean = false;
private _noStop: boolean = false;
private nbVContainers: number = 0;
private currentVideo: HTMLMediaElement;
// Les ids reçus doivent correspondre à des éléments HTML contenant une vidéo.
set vContainers(vContainersIds: string[])
{
for(let containerId of vContainersIds)
{ {
let checkContainerExist=document.getElementById(containerId); let checkContainerExist=document.getElementById(containerId);
if(checkContainerExist === null) if(checkContainerExist === null)
console.error("Aucun élément HTML trouvé dans la page pour l'id fourni "+containerId); throw new Error("Aucun élément HTML trouvé dans la page pour l'id "+containerId+".");
else else
{ {
let checkVideoExist=<HTMLMediaElement>document.querySelector("#"+containerId+" video"); let checkVideoExist=<HTMLMediaElement>document.querySelector("#"+containerId+" video");
if(checkVideoExist === null) if(checkVideoExist === null)
console.error("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id "+containerId); throw new Error("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id "+containerId+".");
else else
realVContainers.push({id:containerId, containerElt:checkContainerExist, videoElt:checkVideoExist}); this._vContainers.push({id:containerId, containerElt:checkContainerExist, videoElt:checkVideoExist});
} }
} }
// Il faut au moins 2 vidéos à faire tourner.
this.nbVContainers=this._vContainers.length;
if(this.nbVContainers < 2)
throw new Error("Il faut fournir au moins deux conteneurs de vidéo pour pouvoir faire tourner le carrousel.");
}
// Si opts.firstVideoId a été fourni, on vérifie aussi qu'il est valide. // Si this._firstVideoId a été fourni, on vérifie qu'il est présent dans la liste des conteneurs de vidéos.
if(opts.firstVideoId!==undefined && opts.firstVideoId!=="" && (realVContainers.findIndex(video => video.id === opts.firstVideoId) === -1)) set firstVideoId(firstVideo: string)
{ {
console.error("Vous avez fourni l'id de la vidéo à afficher en premier ("+opts.firstVideoId+"), mais il n'est pas valide."); if(firstVideo!=="" && this._vContainers.findIndex(video => video.id === firstVideo) === -1)
opts.firstVideoId=undefined; console.error("Vous avez fourni l'id de la vidéo à afficher en premier ("+this._firstVideoId+"), mais il n'est pas valide.");
else
this._firstVideoId=firstVideo;
} }
// Il doit rester au moins deux vidéos à faire tourner. set playFirstVideo(playFirstVideo: boolean)
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é. this._playFirstVideo=playFirstVideo;
// La fin de lecture d'une vidéo provoque son remplacement par la suivante. }
for (let i = 0; i < nbVContainers; i++)
set playNextVideo(playNextVideo: boolean)
{ {
let vContainer=realVContainers[i].containerElt; this._playNextVideos=playNextVideo;
let video=realVContainers[i].videoElt; }
if((opts.firstVideoId!==undefined && realVContainers[i].id!==opts.firstVideoId) || (opts.firstVideoId===undefined && i!==0) || opts.firstVideoId==="")
set noStop(noStop: boolean)
{
this._noStop=noStop;
}
public run(): void
{
const vCarousel=this;// évite les confusions avec le "this" des événements.
if(vCarousel.nbVContainers < 2) // dans le cas où on lancerait run() sans passer par le setter.
throw new Error("Il faut fournir au moins deux conteneurs valides pour faire tourner le carrousel.");
for (let i = 0; i < vCarousel.nbVContainers; i++)
{
let vContainer=vCarousel._vContainers[i].containerElt;
let video=vCarousel._vContainers[i].videoElt;
if((vCarousel._firstVideoId!==undefined && vCarousel._vContainers[i].id!==vCarousel._firstVideoId) || (vCarousel._firstVideoId===undefined && i!==0) || vCarousel._firstVideoId==="")
vContainer.style.display = "none"; vContainer.style.display = "none";
else else
{ {
// Si une vidéo est déjà visible et en cours de lecture, je la stoppe et remets à 0
// Sinon elle risque de continuer à être lue tout en étant cachée.
if(vCarousel.currentVideo!==undefined && !vCarousel.currentVideo.paused)
{
vCarousel.currentVideo.pause();
vCarousel.currentVideo.currentTime = 0;
}
// J'affiche la première vidéo et j'essaye de la lancer, si cela est demandé
vContainer.style.display = "block"; vContainer.style.display = "block";
if(opts.firstVideoId!==undefined && opts.playFirstVideo===true) vCarousel.currentVideo=video;
if(vCarousel._playFirstVideo===true)
video.play(); video.play();
} }
var nbTurn=0; var nbTurn=0;
video.addEventListener("ended", function() video.addEventListener("ended", function()
{ {
// Sauf si demandé en option, le carrousel s'arrête lorsque toutes les vidéos ont été affichées une fois. // Sauf si demandé, le carrousel s'arrête lorsque toutes les vidéos ont été affichées une fois.
if(nbTurn < (nbVContainers-1) || opts.noStop===true) if(nbTurn < (vCarousel.nbVContainers-1) || vCarousel._noStop===true)
{ {
vContainer.style.display = "none"; vContainer.style.display = "none";
let nextVContainer: HTMLElement, nextVideo: HTMLMediaElement, nextHash: string; let nextVContainer: HTMLElement, nextVideo: HTMLMediaElement, nextHash: string;
if(i < (nbVContainers-1)) if(i < (vCarousel.nbVContainers-1))
{ {
nextVContainer=realVContainers[i+1].containerElt; nextVContainer=vCarousel._vContainers[i+1].containerElt;
nextVideo=realVContainers[i+1].videoElt; nextVideo=vCarousel._vContainers[i+1].videoElt;
nextHash=realVContainers[i+1].id; nextHash=vCarousel._vContainers[i+1].id;
} }
else else
{ {
nextVContainer=realVContainers[0].containerElt; nextVContainer=vCarousel._vContainers[0].containerElt;
nextVideo=realVContainers[0].videoElt; nextVideo=vCarousel._vContainers[0].videoElt;
nextHash=realVContainers[0].id; nextHash=vCarousel._vContainers[0].id;
} }
nextVContainer.style.display = "block"; 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. // 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. // Attention car cela peut provoquer un déplacement dans la page pour atteindre l'ancre.
window.location.assign("#"+nextHash); window.location.assign("#"+nextHash);
if(opts.playNextVideos===true) if(vCarousel._playNextVideos===true)
nextVideo.play(); nextVideo.play();
vCarousel.currentVideo=nextVideo;
nbTurn++; nbTurn++;
} }
}); });

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"outDir": "./public/JS", "outDir": "./src",
"noImplicitAny": true, "noImplicitAny": true,
"module": "es6", "module": "es6",
"target": "es5", // compilation en JS compatible ES5 "target": "es5", // compilation en JS compatible ES5