mirror of
https://github.com/dawidolko/Website-Templates.git
synced 2025-10-27 16:03:10 +01:00
371 lines
12 KiB
JavaScript
371 lines
12 KiB
JavaScript
/**
|
|
* cbpGridGallery.js v1.0.0
|
|
* http://www.codrops.com
|
|
*
|
|
* Licensed under the MIT license.
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
*
|
|
* Copyright 2014, Codrops
|
|
* http://www.codrops.com
|
|
*/
|
|
;( 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;
|
|
}
|
|
|
|
// from http://responsejs.com/labs/dimensions/
|
|
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( 'section.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( 'section.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( 'section.slideshow > nav > span.nav-prev' );
|
|
this.ctrlNext = this.el.querySelector( 'section.slideshow > nav > span.nav-next' );
|
|
this.ctrlClose = this.el.querySelector( 'section.slideshow > nav > span.nav-close' );
|
|
// init masonry grid
|
|
this._initMasonry();
|
|
// init events
|
|
this._initEvents();
|
|
};
|
|
|
|
CBPGridGallery.prototype._initMasonry = function() {
|
|
var grid = this.grid;
|
|
imagesLoaded( grid, function() {
|
|
new Masonry( grid, {
|
|
itemSelector: 'li',
|
|
columnWidth: grid.querySelector( '.grid-sizer' )
|
|
});
|
|
});
|
|
};
|
|
|
|
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 ];
|
|
}
|
|
|
|
// taken from https://github.com/desandro/vanilla-masonry/blob/master/masonry.js by David DeSandro
|
|
// original debounce by John Hann
|
|
// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
|
|
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 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new CBPGridGallery( document.getElementById( 'grid-gallery' ) ); |