/*! touch-imagelightbox - v0.1.0 - 2014-06-27 * https://github.com/victorhaggqvist/touch-imagelightbox * Copyright (c) 2014 Osvaldas Valutis (www.osvaldas.info); Licensed MIT * Contributors Victor Häggqvist (victorhaggqvist.com) */ ;( function( $, window, document, undefined ) { 'use strict'; var options, cssTransitionSupport = function() { var d = document.body || document.documentElement, s = d.style; if ( s.WebkitTransition === '' ) return '-webkit-'; if ( s.MozTransition === '' ) return '-moz-'; if ( s.OTransition === '' ) return '-o-'; if ( s.transition === '' ) return ''; return false; }, isCssTransitionSupport = cssTransitionSupport() === false ? false : true, cssTransitionTranslateX = function( element, positionX, speed ) { options = {}; var prefix = cssTransitionSupport(); options[ prefix + 'transform' ] = 'translateX(' + positionX + ')'; options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear'; element.css( options ); }, hasTouch = ( 'ontouchstart' in window ), hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled, wasTouched = function( event ) { if( hasTouch ) return true; if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) return false; if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ) { if( event.MSPOINTER_TYPE_MOUSE !== event.pointerType ) return true; } else { if( event.pointerType !== 'mouse' ) return true; } return false; }; $.fn.imageLightbox = function( options ) { options = $.extend( { selector: 'id="imagelightbox"', allowedTypes: 'png|jpg|jpeg|gif', animationSpeed: 250, preloadNext: true, enableKeyboard: true, quitOnEnd: false, quitOnImgClick: false, quitOnDocClick: true, onStart: false, onEnd: false, onLoadStart: false, onLoadEnd: false }, options); var targets = $([]), target = $(), image = $(), imageWidth = 0, imageHeight = 0, swipeDiff = 0, inProgress = false, isTargetValid = function( element ) { /*jshint -W044*/ options.regexValidObject = new RegExp("(\.("+options.allowedTypes+")$)"); /*jshint +W044*/ return $( element ).prop( 'tagName' ).toLowerCase() === 'a' && options.regexValidObject.test($(element).attr('href') ); }, setImage = function() { if( !image.length ) return false; var screenWidth = $( window ).width() * 0.8, screenHeight = $( window ).height() * 0.9, tmpImage = new Image(); tmpImage.src = image.attr( 'src' ); tmpImage.onload = function() { imageWidth = tmpImage.width; imageHeight = tmpImage.height; if( imageWidth > screenWidth || imageHeight > screenHeight ) { var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight; imageWidth /= ratio; imageHeight /= ratio; } image.css( { 'width': imageWidth + 'px', 'height': imageHeight + 'px', 'top': ( $( window ).height() - imageHeight ) / 2 + 'px', 'left': ( $( window ).width() - imageWidth ) / 2 + 'px' } ); }; }, loadImage = function( direction ) { if( inProgress ) return false; direction = typeof direction === 'undefined' ? false : direction === 'left' ? 1 : -1; // BIG if if( image.length ) { if( direction !== false && ( targets.length < 2 || ( options.quitOnEnd === true && ( ( direction === -1 && targets.index( target ) === 0 ) || ( direction === 1 && targets.index( target ) === targets.length - 1 ) ) ) ) ) { quitLightbox(); return false; } var params = { 'opacity': 0 }; if( isCssTransitionSupport ){ cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 ); } else { params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px'; } image.animate( params, options.animationSpeed, function(){ removeImage(); }); swipeDiff = 0; } inProgress = true; if( options.onLoadStart !== false ) options.onLoadStart(); setTimeout( function() { image = $( '' ) .attr( 'src', target.attr( 'href' ) ) .load( function() { image.appendTo( 'body' ); setImage(); var params = { 'opacity': 1 }; image.css( 'opacity', 0 ); if( isCssTransitionSupport ) { cssTransitionTranslateX( image, -100 * direction + 'px', 0 ); setTimeout( function(){ cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); }, 50 ); } else { var imagePosLeft = parseInt( image.css( 'left' ) ); params.left = imagePosLeft + 'px'; image.css( 'left', imagePosLeft - 100 * direction + 'px' ); } image.animate( params, options.animationSpeed, function() { inProgress = false; if( options.onLoadEnd !== false ) options.onLoadEnd(); }); if( options.preloadNext ) { var nextTarget = targets.eq( targets.index( target ) + 1 ); if( !nextTarget.length ) nextTarget = targets.eq( 0 ); $( '' ).attr( 'src', nextTarget.attr( 'href' ) ).load(); } }) .error( function() { if( options.onLoadEnd !== false ) options.onLoadEnd(); }); var swipeStart = 0, swipeEnd = 0, imagePosLeft = 0; image.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function( e ) { e.preventDefault(); if( options.quitOnImgClick ) { quitLightbox(); return false; } if( wasTouched( e.originalEvent ) ) return true; var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft; target = targets.eq( targets.index( target ) - ( imageWidth / 2 > posX ? 1 : -1 ) ); if( !target.length ) target = targets.eq( imageWidth / 2 > posX ? targets.length : 0 ); loadImage( imageWidth / 2 > posX ? 'left' : 'right' ); }) .on( 'touchstart pointerdown MSPointerDown', function( e ) { if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; if( isCssTransitionSupport ) imagePosLeft = parseInt( image.css( 'left' ) ); swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; }) .on( 'touchmove pointermove MSPointerMove', function( e ) { if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; e.preventDefault(); swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; swipeDiff = swipeStart - swipeEnd; if( isCssTransitionSupport ) cssTransitionTranslateX( image, -swipeDiff + 'px', 0 ); else image.css( 'left', imagePosLeft - swipeDiff + 'px' ); }) .on( 'touchend touchcancel pointerup MSPointerUp', function( e ) { if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; if( Math.abs( swipeDiff ) > 50 ) { target = targets.eq( targets.index( target ) - ( swipeDiff < 0 ? 1 : -1 ) ); if( !target.length ) target = targets.eq( swipeDiff < 0 ? targets.length : 0 ); loadImage( swipeDiff > 0 ? 'right' : 'left' ); } else { if( isCssTransitionSupport ) cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); else image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 ); } }); }, options.animationSpeed + 100 ); }, removeImage = function() { if( !image.length ) return false; image.remove(); image = $(); }, quitLightbox = function() { if( !image.length ) return false; image.animate({ 'opacity': 0 }, options.animationSpeed, function() { removeImage(); inProgress = false; if( options.onEnd !== false ) options.onEnd(); }); }; $( window ).on( 'resize', setImage ); if( options.quitOnDocClick ) { $( document ).on( hasTouch ? 'touchend' : 'click', function( e ) { if( image.length && !$( e.target ).is( image ) ) quitLightbox(); }); } if( options.enableKeyboard ) { $( document ).on( 'keyup', function( e ) { if( !image.length ) return true; e.preventDefault(); if( e.keyCode === 27 ) quitLightbox(); if( e.keyCode === 37 || e.keyCode === 39 ) { target = targets.eq( targets.index( target ) - ( e.keyCode === 37 ? 1 : -1 ) ); if( !target.length ) target = targets.eq( e.keyCode === 37 ? targets.length : 0 ); loadImage( e.keyCode === 37 ? 'left' : 'right' ); } }); } $( document ).on( 'click', this.selector, function( e ) { if( !isTargetValid( this ) ) return true; e.preventDefault(); if( inProgress ) return false; inProgress = false; if( options.onStart !== false ) options.onStart(); target = $( this ); loadImage(); }); this.each( function() { if( !isTargetValid( this ) ) return true; targets = targets.add( $( this ) ); }); this.switchImageLightbox = function( index ) { var tmpTarget = targets.eq( index ); if( tmpTarget.length ) { var currentIndex = targets.index( target ); target = tmpTarget; loadImage( index < currentIndex ? 'left' : 'right' ); } return this; }; this.quitImageLightbox = function() { quitLightbox(); return this; }; return this; }; })( jQuery, window, document );