/** * cbpGridGallery.js v1.0.0 */ ; (function (window) { 'use strict'; var docElem = window.document.documentElement, transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' }, transEndEventName = transEndEventNames[Modernizr.prefixed('transition')], support = { transitions: Modernizr.csstransitions, support3d: Modernizr.csstransforms3d }; function setTransform(el, transformStr) { el.style.WebkitTransform = transformStr; el.style.msTransform = transformStr; el.style.transform = transformStr; } function getViewportW() { var client = docElem['clientWidth'], inner = window['innerWidth']; if (client < inner) return inner; else return client; } function extend(a, b) { for (var key in b) { if (b.hasOwnProperty(key)) { a[key] = b[key]; } } return a; } function CBPGridGallery(el, options) { this.el = el; this.options = extend({}, this.options); extend(this.options, options); this._init(); } CBPGridGallery.prototype.options = {}; CBPGridGallery.prototype._init = function () { // main grid this.grid = this.el.querySelector('.grid-wrap > ul.grid'); // main grid items this.gridItems = [].slice.call(this.grid.querySelectorAll('li:not(.grid-sizer)')); // items total this.itemsCount = this.gridItems.length; // slideshow grid this.slideshow = this.el.querySelector('.slideshow > ul'); // slideshow grid items this.slideshowItems = [].slice.call(this.slideshow.children); // index of current slideshow item this.current = -1; // slideshow control buttons this.ctrlPrev = this.el.querySelector('.slideshow > nav > span.nav-prev'); this.ctrlNext = this.el.querySelector('.slideshow > nav > span.nav-next'); this.ctrlClose = this.el.querySelector('.slideshow > nav > span.nav-close'); // init masonry grid //this._initMasonry(); // init events this._initEvents(); }; CBPGridGallery.prototype._initEvents = function () { var self = this; // open the slideshow when clicking on the main grid items this.gridItems.forEach(function (item, idx) { item.addEventListener('click', function () { self._openSlideshow(idx); }); }); // slideshow controls this.ctrlPrev.addEventListener('click', function () { self._navigate('prev'); }); this.ctrlNext.addEventListener('click', function () { self._navigate('next'); }); this.ctrlClose.addEventListener('click', function () { self._closeSlideshow(); }); // window resize window.addEventListener('resize', function () { self._resizeHandler(); }); // keyboard navigation events document.addEventListener('keydown', function (ev) { if (self.isSlideshowVisible) { var keyCode = ev.keyCode || ev.which; switch (keyCode) { case 37: self._navigate('prev'); break; case 39: self._navigate('next'); break; case 27: self._closeSlideshow(''); break; } } }); // trick to prevent scrolling when slideshow is visible window.addEventListener('scroll', function () { if (self.isSlideshowVisible) { window.scrollTo(self.scrollPosition ? self.scrollPosition.x : 0, self.scrollPosition ? self.scrollPosition.y : 0); } else { self.scrollPosition = { x: window.pageXOffset || docElem.scrollLeft, y: window.pageYOffset || docElem.scrollTop }; } }); }; CBPGridGallery.prototype._openSlideshow = function (pos) { this.isSlideshowVisible = true; this.current = pos; classie.addClass(this.el, 'slideshow-open'); /* position slideshow items */ // set viewport items (current, next and previous) this._setViewportItems(); // add class "current" and "show" to currentItem classie.addClass(this.currentItem, 'current'); classie.addClass(this.currentItem, 'show'); // add class show to next and previous items // position previous item on the left side and the next item on the right side if (this.prevItem) { classie.addClass(this.prevItem, 'show'); var translateVal = Number(-1 * (getViewportW() / 2 + this.prevItem.offsetWidth / 2)); setTransform(this.prevItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)'); } if (this.nextItem) { classie.addClass(this.nextItem, 'show'); var translateVal = Number(getViewportW() / 2 + this.nextItem.offsetWidth / 2); setTransform(this.nextItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)'); } }; CBPGridGallery.prototype._navigate = function (dir) { if (this.isAnimating) return; if (dir === 'next' && this.current === this.itemsCount - 1 || dir === 'prev' && this.current === 0) { this._closeSlideshow(); return; } this.isAnimating = true; // reset viewport items this._setViewportItems(); var self = this, itemWidth = this.currentItem.offsetWidth, // positions for the centered/current item, both the side items and the incoming ones transformLeftStr = support.support3d ? 'translate3d(-' + Number(getViewportW() / 2 + itemWidth / 2) + 'px, 0, -150px)' : 'translate(-' + Number(getViewportW() / 2 + itemWidth / 2) + 'px)', transformRightStr = support.support3d ? 'translate3d(' + Number(getViewportW() / 2 + itemWidth / 2) + 'px, 0, -150px)' : 'translate(' + Number(getViewportW() / 2 + itemWidth / 2) + 'px)', transformCenterStr = '', transformOutStr, transformIncomingStr, // incoming item incomingItem; if (dir === 'next') { transformOutStr = support.support3d ? 'translate3d( -' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px, 0, -150px )' : 'translate(-' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px)'; transformIncomingStr = support.support3d ? 'translate3d( ' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px, 0, -150px )' : 'translate(' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px)'; } else { transformOutStr = support.support3d ? 'translate3d( ' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px, 0, -150px )' : 'translate(' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px)'; transformIncomingStr = support.support3d ? 'translate3d( -' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px, 0, -150px )' : 'translate(-' + Number((getViewportW() * 2) / 2 + itemWidth / 2) + 'px)'; } // remove class animatable from the slideshow grid (if it has already) classie.removeClass(self.slideshow, 'animatable'); if (dir === 'next' && this.current < this.itemsCount - 2 || dir === 'prev' && this.current > 1) { // we have an incoming item! incomingItem = this.slideshowItems[dir === 'next' ? this.current + 2 : this.current - 2]; setTransform(incomingItem, transformIncomingStr); classie.addClass(incomingItem, 'show'); } var slide = function () { // add class animatable to the slideshow grid classie.addClass(self.slideshow, 'animatable'); // overlays: classie.removeClass(self.currentItem, 'current'); var nextCurrent = dir === 'next' ? self.nextItem : self.prevItem; classie.addClass(nextCurrent, 'current'); setTransform(self.currentItem, dir === 'next' ? transformLeftStr : transformRightStr); if (self.nextItem) { setTransform(self.nextItem, dir === 'next' ? transformCenterStr : transformOutStr); } if (self.prevItem) { setTransform(self.prevItem, dir === 'next' ? transformOutStr : transformCenterStr); } if (incomingItem) { setTransform(incomingItem, dir === 'next' ? transformRightStr : transformLeftStr); } var onEndTransitionFn = function (ev) { if (support.transitions) { if (ev.propertyName.indexOf('transform') === -1) return false; this.removeEventListener(transEndEventName, onEndTransitionFn); } if (self.prevItem && dir === 'next') { classie.removeClass(self.prevItem, 'show'); } else if (self.nextItem && dir === 'prev') { classie.removeClass(self.nextItem, 'show'); } if (dir === 'next') { self.prevItem = self.currentItem; self.currentItem = self.nextItem; if (incomingItem) { self.nextItem = incomingItem; } } else { self.nextItem = self.currentItem; self.currentItem = self.prevItem; if (incomingItem) { self.prevItem = incomingItem; } } self.current = dir === 'next' ? self.current + 1 : self.current - 1; self.isAnimating = false; }; if (support.transitions) { self.currentItem.addEventListener(transEndEventName, onEndTransitionFn); } else { onEndTransitionFn(); } }; setTimeout(slide, 25); } CBPGridGallery.prototype._closeSlideshow = function (pos) { // remove class slideshow-open from the grid gallery elem classie.removeClass(this.el, 'slideshow-open'); // remove class animatable from the slideshow grid classie.removeClass(this.slideshow, 'animatable'); var self = this, onEndTransitionFn = function (ev) { if (support.transitions) { if (ev.target.tagName.toLowerCase() !== 'ul') return; this.removeEventListener(transEndEventName, onEndTransitionFn); } // remove classes show and current from the slideshow items classie.removeClass(self.currentItem, 'current'); classie.removeClass(self.currentItem, 'show'); if (self.prevItem) { classie.removeClass(self.prevItem, 'show'); } if (self.nextItem) { classie.removeClass(self.nextItem, 'show'); } // also reset any transforms for all the items self.slideshowItems.forEach(function (item) { setTransform(item, ''); }); self.isSlideshowVisible = false; }; if (support.transitions) { this.el.addEventListener(transEndEventName, onEndTransitionFn); } else { onEndTransitionFn(); } }; CBPGridGallery.prototype._setViewportItems = function () { this.currentItem = null; this.prevItem = null; this.nextItem = null; if (this.current > 0) { this.prevItem = this.slideshowItems[this.current - 1]; } if (this.current < this.itemsCount - 1) { this.nextItem = this.slideshowItems[this.current + 1]; } this.currentItem = this.slideshowItems[this.current]; } CBPGridGallery.prototype._resizeHandler = function () { var self = this; function delayed() { self._resize(); self._resizeTimeout = null; } if (this._resizeTimeout) { clearTimeout(this._resizeTimeout); } this._resizeTimeout = setTimeout(delayed, 50); } CBPGridGallery.prototype._resize = function () { if (this.isSlideshowVisible) { // update width value if (this.prevItem) { var translateVal = Number(-1 * (getViewportW() / 2 + this.prevItem.offsetWidth / 2)); setTransform(this.prevItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)'); } if (this.nextItem) { var translateVal = Number(getViewportW() / 2 + this.nextItem.offsetWidth / 2); setTransform(this.nextItem, support.support3d ? 'translate3d(' + translateVal + 'px, 0, -150px)' : 'translate(' + translateVal + 'px)'); } } } // add to global namespace window.CBPGridGallery = CBPGridGallery; })(window);