UNPKG

@fancyapps/ui

Version:

JavaScript UI Component Library

156 lines (122 loc) 3.73 kB
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;