@fancyapps/ui
Version:
JavaScript UI Component Library
156 lines (122 loc) • 3.73 kB
JavaScript
const defaults = {
friction: 0.92,
};
export class Sync {
constructor(carousel) {
this.carousel = carousel;
this.selectedIndex = null;
this.friction = 0;
this.onNavReady = this.onNavReady.bind(this);
this.onNavClick = this.onNavClick.bind(this);
this.onNavCreateSlide = this.onNavCreateSlide.bind(this);
this.onTargetChange = this.onTargetChange.bind(this);
}
/**
* Make this one as main carousel and selected carousel as navigation
* @param {Object} nav Carousel
*/
addAsTargetFor(nav) {
this.target = this.carousel;
this.nav = nav;
this.attachEvents();
}
/**
* Make this one as navigation carousel for selected carousel
* @param {Object} target
*/
addAsNavFor(target) {
this.target = target;
this.nav = this.carousel;
this.attachEvents();
}
/**
* Attach event listeners on both carousels
*/
attachEvents() {
this.nav.options.initialSlide = this.target.options.initialPage;
this.nav.on("ready", this.onNavReady);
this.nav.on("createSlide", this.onNavCreateSlide);
this.nav.on("Panzoom.click", this.onNavClick);
this.target.on("change", this.onTargetChange);
this.target.on("Panzoom.afterUpdate", this.onTargetChange);
}
/**
* Process main carousel `ready` event; bind events and set initial page
*/
onNavReady() {
this.onTargetChange(true);
}
/**
* Process main carousel `click` event
* @param {Object} panzoom
* @param {Object} event
*/
onNavClick(carousel, panzoom, event) {
const clickedNavSlide = event.target.closest(".carousel__slide");
if (!clickedNavSlide) {
return;
}
event.stopPropagation();
const selectedNavIndex = parseInt(clickedNavSlide.dataset.index, 10);
const selectedSyncPage = this.target.findPageForSlide(selectedNavIndex);
if (this.target.page !== selectedSyncPage) {
this.target.slideTo(selectedSyncPage, { friction: this.friction });
}
this.markSelectedSlide(selectedNavIndex);
}
/**
* Process main carousel `createSlide` event
* @param {Object} carousel
* @param {Object} slide
*/
onNavCreateSlide(carousel, slide) {
if (slide.index === this.selectedIndex) {
this.markSelectedSlide(slide.index);
}
}
/**
* Process target carousel `change` event
* @param {Object} target
*/
onTargetChange() {
const targetIndex = this.target.pages[this.target.page].indexes[0];
const selectedNavPage = this.nav.findPageForSlide(targetIndex);
this.nav.slideTo(selectedNavPage);
this.markSelectedSlide(targetIndex);
}
/**
* Toggle classname for slides that marks currently selected slides
* @param {Number} selectedIndex
*/
markSelectedSlide(selectedIndex) {
this.selectedIndex = selectedIndex;
[...this.nav.slides].filter((slide) => slide.$el && slide.$el.classList.remove("is-nav-selected"));
const slide = this.nav.slides[selectedIndex];
if (slide && slide.$el) slide.$el.classList.add("is-nav-selected");
}
attach(carousel) {
const sync = carousel.options.Sync;
if (!sync.target && !sync.nav) {
return;
}
if (sync.target) {
this.addAsNavFor(sync.target);
} else if (sync.nav) {
this.addAsTargetFor(sync.nav);
}
this.friction = sync.friction;
}
detach() {
if (this.nav) {
this.nav.off("ready", this.onNavReady);
this.nav.off("Panzoom.click", this.onNavClick);
this.nav.off("createSlide", this.onNavCreateSlide);
}
if (this.target) {
this.target.off("Panzoom.afterUpdate", this.onTargetChange);
this.target.off("change", this.onTargetChange);
}
}
}
// Expose defaults
Sync.defaults = defaults;