UNPKG

framework7-without-localstorage

Version:

Full featured mobile HTML framework for building iOS & Android apps

430 lines (404 loc) 17.8 kB
/*====================================================== ************ Photo Browser ************ ======================================================*/ var PhotoBrowser = function (params) { var pb = this, i; var defaults = { photos : [], initialSlide: 0, spaceBetween: 20, speed: 300, zoom: true, zoomMax: 3, zoomMin: 1, exposition: true, expositionHideCaptions: false, type: 'standalone', navbar: true, toolbar: true, theme: 'light', swipeToClose: true, backLinkText: 'Close', ofText: 'of', loop: false, lazyLoading: false, lazyLoadingInPrevNext: false, lazyLoadingOnTransitionStart: false, material: app.params.material, materialPreloaderSvg: app.params.materialPreloaderSvg, materialPreloaderHtml: app.params.materialPreloaderHtml, /* Callbacks: onLazyImageLoad(pb, slide, img) onLazyImageReady(pb, slide, img) onOpen(pb) onClose(pb) onTransitionStart(swiper) onTransitionEnd(swiper) onSlideChangeStart(swiper) onSlideChangeEnd(swiper) onTap(swiper, e) onClick(swiper, e) onDoubleTap(swiper, e) onSwipeToClose(pb) */ }; params = params || {}; if (!params.backLinkText && app.params.material) defaults.backLinkText = ''; for (var def in defaults) { if (typeof params[def] === 'undefined') { params[def] = defaults[def]; } } if (params.maxZoom) { params.zoomMax = params.maxZoom; } if (params.minZoom) { params.zoomMin = params.minZoom; } pb.params = params; pb.params.iconsColorClass = pb.params.iconsColor ? 'color-' + pb.params.iconsColor : (pb.params.theme === 'dark' ? 'color-white' : ''); pb.params.preloaderColorClass = pb.params.theme === 'dark' ? 'preloader-white' : ''; // Templates var photoTemplate = pb.params.photoTemplate || '<div class="photo-browser-slide swiper-slide">' + '<span class="swiper-zoom-container">' + '<img src="{{js "this.url || this"}}">' + '</span>' + '</div>'; var photoLazyTemplate = pb.params.lazyPhotoTemplate || '<div class="photo-browser-slide photo-browser-slide-lazy swiper-slide">' + '<div class="preloader {{@root.preloaderColorClass}}">{{#if @root.material}}{{@root.materialPreloaderHtml}}{{/if}}</div>' + '<span class="swiper-zoom-container">' + '<img data-src="{{js "this.url || this"}}" class="swiper-lazy">' + '</span>' + '</div>'; var objectTemplate = pb.params.objectTemplate || '<div class="photo-browser-slide photo-browser-object-slide swiper-slide">{{js "this.html || this"}}</div>'; var captionTemplate = pb.params.captionTemplate || '<div class="photo-browser-caption" data-caption-index="{{@index}}">' + '{{caption}}' + '</div>'; var navbarTemplate = pb.params.navbarTemplate || '<div class="navbar">' + '<div class="navbar-inner">' + '<div class="left sliding">' + '<a href="#" class="link ' + (params.type === 'popup' ? 'close-popup' : 'photo-browser-close-link')+ ' {{#unless backLinkText}}icon-only{{/unless}} {{js "this.type === \'page\' ? \'back\' : \'\'"}}">' + '<i class="icon icon-back {{iconsColorClass}}"></i>' + '{{#if backLinkText}}<span>{{backLinkText}}</span>{{/if}}' + '</a>' + '</div>' + '<div class="center sliding">' + '<span class="photo-browser-current"></span> ' + '<span class="photo-browser-of">{{ofText}}</span> ' + '<span class="photo-browser-total"></span>' + '</div>' + '<div class="right"></div>' + '</div>' + '</div>'; var toolbarTemplate = pb.params.toolbarTemplate || '<div class="toolbar tabbar">' + '<div class="toolbar-inner">' + '<a href="#" class="link photo-browser-prev">' + '<i class="icon icon-prev {{iconsColorClass}}"></i>' + '</a>' + '<a href="#" class="link photo-browser-next">' + '<i class="icon icon-next {{iconsColorClass}}"></i>' + '</a>' + '</div>' + '</div>'; var htmlTemplate = t7.compile('<div class="photo-browser photo-browser-{{theme}}">' + '<div class="view navbar-fixed toolbar-fixed">' + '{{#unless material}}{{#if navbar}}' + navbarTemplate + '{{/if}}{{/unless}}' + '<div class="page no-toolbar {{#unless navbar}}no-navbar{{/unless}} toolbar-fixed navbar-fixed" data-page="photo-browser-slides">' + '{{#if material}}{{#if navbar}}' + navbarTemplate + '{{/if}}{{/if}}' + '{{#if toolbar}}' + toolbarTemplate + '{{/if}}' + '<div class="photo-browser-captions photo-browser-captions-{{js "this.captionsTheme || this.theme"}}">' + '{{#each photos}}{{#if caption}}' + captionTemplate + '{{/if}}{{/each}}' + '</div>' + '<div class="photo-browser-swiper-container swiper-container">' + '<div class="photo-browser-swiper-wrapper swiper-wrapper">' + '{{#each photos}}' + '{{#js_compare "this.html || ((typeof this === \'string\' || this instanceof String) && (this.indexOf(\'<\') >= 0 || this.indexOf(\'>\') >= 0))"}}' + objectTemplate + '{{else}}' + '{{#if @root.lazyLoading}}' + photoLazyTemplate + '{{else}}' + photoTemplate + '{{/if}}' + '{{/js_compare}}' + '{{/each}}' + '</div>' + '</div>' + '</div>' + '</div>' + '</div>')(pb.params); pb.activeIndex = pb.params.initialSlide; pb.openIndex = pb.activeIndex; pb.opened = false; pb.open = function (index) { if (typeof index === 'undefined') index = pb.activeIndex; index = parseInt(index, 10); if (pb.opened && pb.swiper) { pb.swiper.slideTo(index); return; } pb.opened = true; pb.openIndex = index; if (pb.params.type === 'standalone') { app.root.append(htmlTemplate); } if (pb.params.type === 'popup') { pb.popup = app.popup('<div class="popup photo-browser-popup">' + htmlTemplate + '</div>'); $(pb.popup).on('popup:closed', pb.onPopupClose); } if (pb.params.type === 'page') { $(document).once('page:beforeinit', pb.onPageBeforeInit); $(document).once('page:beforeremove', pb.onPageBeforeRemove); if (!pb.params.view) pb.params.view = app.mainView; pb.params.view.loadContent(htmlTemplate); return; } pb.layout(pb.openIndex); if (pb.params.onOpen) { pb.params.onOpen(pb); } }; pb.close = function () { pb.opened = false; if (!pb.swiperContainer || pb.swiperContainer.length === 0) { return; } if (pb.params.onClose) { pb.params.onClose(pb); } // Detach events pb.attachEvents(true); // Delete from DOM if (pb.params.type === 'standalone') { pb.container.removeClass('photo-browser-in').addClass('photo-browser-out').animationEnd(function () { pb.container.remove(); }); } // Destroy slider pb.swiper.destroy(); // Delete references pb.swiper = pb.swiperContainer = pb.swiperWrapper = pb.slides = undefined; //gestureSlide = gestureImg = gestureImgWrap = undefined; }; pb.onPopupClose = function (e) { pb.close(); $(pb.popup).off('page:beforeinit', pb.onPopupClose); }; pb.onPageBeforeInit = function (e) { if (e.detail.page.name === 'photo-browser-slides') { pb.layout(pb.openIndex); if (pb.params.onOpen) { pb.params.onOpen(pb); } } }; pb.onPageBeforeRemove = function (e) { if (e.detail.page.name === 'photo-browser-slides') { pb.close(); } }; pb.onSliderTransitionStart = function (swiper) { pb.activeIndex = swiper.activeIndex; var current = swiper.activeIndex + 1; var total = swiper.slides.length; if (pb.params.loop) { total = total - 2; current = current - swiper.loopedSlides; if (current < 1) current = total + current; if (current > total) current = current - total; } pb.container.find('.photo-browser-current').text(current); pb.container.find('.photo-browser-total').text(total); $('.photo-browser-prev, .photo-browser-next').removeClass('photo-browser-link-inactive'); if (swiper.isBeginning && !pb.params.loop) { $('.photo-browser-prev').addClass('photo-browser-link-inactive'); } if (swiper.isEnd && !pb.params.loop) { $('.photo-browser-next').addClass('photo-browser-link-inactive'); } // Update captions if (pb.captions.length > 0) { pb.captionsContainer.find('.photo-browser-caption-active').removeClass('photo-browser-caption-active'); var captionIndex = pb.params.loop ? swiper.slides.eq(swiper.activeIndex).attr('data-swiper-slide-index') : pb.activeIndex; pb.captionsContainer.find('[data-caption-index="' + captionIndex + '"]').addClass('photo-browser-caption-active'); } // Stop Video var previousSlideVideo = swiper.slides.eq(swiper.previousIndex).find('video'); if (previousSlideVideo.length > 0) { if ('pause' in previousSlideVideo[0]) previousSlideVideo[0].pause(); } // Callback if (pb.params.onTransitionStart) pb.params.onTransitionStart(swiper); }; pb.onSliderTransitionEnd = function (swiper) { if (pb.params.onTransitionEnd) pb.params.onTransitionEnd(swiper); }; pb.layout = function (index) { if (pb.params.type === 'page') { pb.container = $('.photo-browser-swiper-container').parents('.view'); } else { pb.container = $('.photo-browser'); } if (pb.params.type === 'standalone') { pb.container.addClass('photo-browser-in'); app.sizeNavbars(pb.container); } pb.swiperContainer = pb.container.find('.photo-browser-swiper-container'); pb.swiperWrapper = pb.container.find('.photo-browser-swiper-wrapper'); pb.slides = pb.container.find('.photo-browser-slide'); pb.captionsContainer = pb.container.find('.photo-browser-captions'); pb.captions = pb.container.find('.photo-browser-caption'); var sliderSettings = { nextButton: pb.params.nextButton || '.photo-browser-next', prevButton: pb.params.prevButton || '.photo-browser-prev', indexButton: pb.params.indexButton, initialSlide: index, spaceBetween: pb.params.spaceBetween, speed: pb.params.speed, loop: pb.params.loop, lazyLoading: pb.params.lazyLoading, lazyLoadingInPrevNext: pb.params.lazyLoadingInPrevNext, lazyLoadingOnTransitionStart: pb.params.lazyLoadingOnTransitionStart, preloadImages: pb.params.lazyLoading ? false : true, zoom: pb.params.zoom, zoomMax: pb.params.zoomMax, zoomMin: pb.params.zoomMin, onTap: function (swiper, e) { if (pb.params.onTap) pb.params.onTap(swiper, e); }, onClick: function (swiper, e) { if (pb.params.exposition) pb.toggleExposition(); if (pb.params.onClick) pb.params.onClick(swiper, e); }, onDoubleTap: function (swiper, e) { // pb.toggleZoom(e); if (pb.params.onDoubleTap) pb.params.onDoubleTap(swiper, e); }, onTransitionStart: function (swiper) { pb.onSliderTransitionStart(swiper); }, onTransitionEnd: function (swiper) { pb.onSliderTransitionEnd(swiper); }, onSlideChangeStart: pb.params.onSlideChangeStart, onSlideChangeEnd: pb.params.onSlideChangeEnd, onLazyImageLoad: function (swiper, slide, img) { if (pb.params.onLazyImageLoad) pb.params.onLazyImageLoad(pb, slide, img); }, onLazyImageReady: function (swiper, slide, img) { $(slide).removeClass('photo-browser-slide-lazy'); if (pb.params.onLazyImageReady) pb.params.onLazyImageReady(pb, slide, img); } }; if (pb.params.swipeToClose && pb.params.type !== 'page') { sliderSettings.onTouchStart = pb.swipeCloseTouchStart; sliderSettings.onTouchMoveOpposite = pb.swipeCloseTouchMove; sliderSettings.onTouchEnd = pb.swipeCloseTouchEnd; } pb.swiper = app.swiper(pb.swiperContainer, sliderSettings); if (index === 0) { pb.onSliderTransitionStart(pb.swiper); } pb.attachEvents(); }; pb.attachEvents = function (detach) { var action = detach ? 'off' : 'on'; pb.container.find('.photo-browser-close-link')[action]('click', pb.close); }; // Expose pb.exposed = false; pb.toggleExposition = function () { if (pb.container) pb.container.toggleClass('photo-browser-exposed'); if (pb.params.expositionHideCaptions) pb.captionsContainer.toggleClass('photo-browser-captions-exposed'); pb.exposed = !pb.exposed; }; pb.enableExposition = function () { if (pb.container) pb.container.addClass('photo-browser-exposed'); if (pb.params.expositionHideCaptions) pb.captionsContainer.addClass('photo-browser-captions-exposed'); pb.exposed = true; }; pb.disableExposition = function () { if (pb.container) pb.container.removeClass('photo-browser-exposed'); if (pb.params.expositionHideCaptions) pb.captionsContainer.removeClass('photo-browser-captions-exposed'); pb.exposed = false; }; // Swipe Up To Close var swipeToCloseIsTouched = false; var allowSwipeToClose = true; var swipeToCloseDiff, swipeToCloseStart, swipeToCloseCurrent, swipeToCloseStarted = false, swipeToCloseActiveSlide, swipeToCloseTimeStart; pb.swipeCloseTouchStart = function (swiper, e) { if (!allowSwipeToClose) return; swipeToCloseIsTouched = true; }; pb.swipeCloseTouchMove = function (swiper, e) { if (!swipeToCloseIsTouched) return; if (!swipeToCloseStarted) { swipeToCloseStarted = true; swipeToCloseStart = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; swipeToCloseActiveSlide = pb.swiper.slides.eq(pb.swiper.activeIndex); swipeToCloseTimeStart = (new Date()).getTime(); } e.preventDefault(); swipeToCloseCurrent = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; swipeToCloseDiff = swipeToCloseStart - swipeToCloseCurrent; var opacity = 1 - Math.abs(swipeToCloseDiff) / 300; swipeToCloseActiveSlide.transform('translate3d(0,' + (-swipeToCloseDiff) + 'px,0)'); pb.swiper.container.css('opacity', opacity).transition(0); }; pb.swipeCloseTouchEnd = function (swiper, e) { swipeToCloseIsTouched = false; if (!swipeToCloseStarted) { swipeToCloseStarted = false; return; } swipeToCloseStarted = false; allowSwipeToClose = false; var diff = Math.abs(swipeToCloseDiff); var timeDiff = (new Date()).getTime() - swipeToCloseTimeStart; if ((timeDiff < 300 && diff > 20) || (timeDiff >= 300 && diff > 100)) { setTimeout(function () { if (pb.params.type === 'standalone') { pb.close(); } if (pb.params.type === 'popup') { app.closeModal(pb.popup); } if (pb.params.onSwipeToClose) { pb.params.onSwipeToClose(pb); } allowSwipeToClose = true; }, 0); return; } if (diff !== 0) { swipeToCloseActiveSlide.addClass('transitioning').transitionEnd(function () { allowSwipeToClose = true; swipeToCloseActiveSlide.removeClass('transitioning'); }); } else { allowSwipeToClose = true; } pb.swiper.container.css('opacity', '').transition(''); swipeToCloseActiveSlide.transform(''); }; return pb; }; app.photoBrowser = function (params) { return new PhotoBrowser(params); };