Skip to content

Instantly share code, notes, and snippets.

@cyrilletuzi
Last active Oct 17, 2018
Embed
What would you like to do?
interface SlideshowOptions {
delay?: number;
speed?: number;
}
export class Slideshow {
/** Delay between each automatic move */
delay: number;
/** Speed for one move */
speed: number;
/** Total of slides */
total: number;
/** Currently displayed slide */
current = 1;
/** Reference to the current timer */
timer: number;
/** Main wrapper element of all the slideshow */
elementMain: HTMLElement;
/** Wrapper element of all slides */
elementSlides: HTMLElement;
/** Pagination element */
elementPagination: HTMLElement;
/**
* Initializes a slideshow
* @param id Id of the main wrapper element of all the slideshow
* @param options Delay and speed options
*/
constructor(id: string, { delay = 5000, speed = 1000 }: SlideshowOptions = {}) {
this.delay = delay;
this.speed = speed;
/* Select HTML elements needed for running the slideshow module */
this.elementMain = document.getElementById(id) as HTMLElement;
this.elementSlides = this.elementMain.children[0] as HTMLElement;
this.elementPagination = this.elementMain.children[1] as HTMLElement;
/* Automatic dynamic configuration to adapt to all slideshows */
this.total = this.elementSlides.children.length;
/* Apply transition effects when moving */
this.elementSlides.style.transition = `transform ${speed}ms`;
this.elementSlides.addEventListener('transitionend', this.onTransitionEnd.bind(this));
/* Apply pagination data and listeners */
Array.from(this.elementPagination.children).forEach((element: HTMLElement, index) => {
element.dataset.page = `${index + 1}`;
});
this.elementPagination.addEventListener('click', this.onPaginationClick.bind(this));
/* Launches the first delay */
this.start();
}
/** Launches the automatic delay */
start() {
/* Stop any current timer to avoid concurrent timers */
this.stop();
/* Launches a new timer and then move */
this.timer = setTimeout(() => {
this.move();
}, this.delay);
}
/** Stops the current timeout */
stop() {
clearTimeout(this.timer);
}
/**
* Move to another slide
* @param next Position of the destination slide
*/
move(next = (this.current < this.total) ? (this.current + 1) : 1) {
/* Translate the slides container */
this.elementSlides.style.transform = `translateX(${(1 - next) * 100}%)`;
/* Update the new current position */
this.current = next;
/* The transitionend event (registered in constructor) will relaunch a new timer */
}
/** Transition listener handler */
onTransitionEnd(event: Event) {
/* Relaunch a new timer */
this.start();
}
/** Pagination listener handler */
onPaginationClick(event: Event) {
/* Checks the element clicked */
let target = event.target as HTMLElement;
if (target.tagName === 'LI') {
/* Stop the automatic delay as the user interacts */
this.stop();
/* Retrieves the page number in custom attributes */
let page = parseInt(target.dataset.page);
/* Move to the wanted slide */
this.move(page);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment