Skip to content

Instantly share code, notes, and snippets.

@namklabs
Created February 16, 2017 19:33
Show Gist options
  • Save namklabs/90b58a90525f396fa8dabfa3eb7d6c98 to your computer and use it in GitHub Desktop.
Save namklabs/90b58a90525f396fa8dabfa3eb7d6c98 to your computer and use it in GitHub Desktop.
Fantastic responsive image lightbox from https://osvaldas.info/image-lightbox-responsive-touch-friendly
/*
By Osvaldas Valutis, www.osvaldas.info
https://osvaldas.info/image-lightbox-responsive-touch-friendly
Available for use under the MIT License
*/
;( function( $, window, document, undefined )
{
'use strict';
var cssTransitionSupport = function()
{
var s = document.body || document.documentElement, s = s.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 )
{
var options = {}, 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 )
{
var options = $.extend(
{
selector: 'id="imagelightbox"',
animationSpeed: 250,
preloadNext: true,
enableKeyboard: true,
quitOnEnd: false,
quitOnImgClick: false,
quitOnDocClick: true,
onStart: false,
onEnd: false,
onLoadStart: false,
onLoadEnd: false
},
options ),
targets = $([]),
target = $(),
image = $(),
imageWidth = 0,
imageHeight = 0,
swipeDiff = 0,
inProgress = false,
setImage = function()
{
if( !image.length ) return true;
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;
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 = $( '<img ' + options.selector + ' />' )
.attr( 'src', target.attr( 'href' ) )
.on( '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 );
$( '<img />' ).attr( 'src', nextTarget.attr( 'href' ) );
}
})
.on( '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 pointercancel MSPointerUp MSPointerCancel', 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();
});
},
addTargets = function( newTargets )
{
newTargets.each( function()
{
targets = targets.add( $( this ) );
});
newTargets.on( 'click.imageLightbox', function( e )
{
e.preventDefault();
if( inProgress ) return false;
inProgress = false;
if( options.onStart !== false ) options.onStart();
target = $( this );
loadImage();
});
};
$( 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' );
}
});
}
addTargets( $( 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.addToImageLightbox = function( newTargets )
{
addTargets( newTargets );
};
this.quitImageLightbox = function()
{
quitLightbox();
return this;
};
return this;
};
})( jQuery, window, document );
/*
By Osvaldas Valutis, www.osvaldas.info
https://osvaldas.info/examples/image-lightbox-responsive-touch-friendly
Available for use under the MIT License
*/
!function(n,t,e,i){"use strict";var o=function(){var n=e.body||e.documentElement,n=n.style;return""==n.WebkitTransition?"-webkit-":""==n.MozTransition?"-moz-":""==n.OTransition?"-o-":""==n.transition?"":!1},r=o()===!1?!1:!0,a=function(n,t,e){var i={},r=o();i[r+"transform"]="translateX("+t+")",i[r+"transition"]=r+"transform "+e+"s linear",n.css(i)},u="ontouchstart"in t,d=t.navigator.pointerEnabled||t.navigator.msPointerEnabled,c=function(n){if(u)return!0;if(!d||"undefined"==typeof n||"undefined"==typeof n.pointerType)return!1;if("undefined"!=typeof n.MSPOINTER_TYPE_MOUSE){if(n.MSPOINTER_TYPE_MOUSE!=n.pointerType)return!0}else if("mouse"!=n.pointerType)return!0;return!1};n.fn.imageLightbox=function(i){var i=n.extend({selector:'id="imagelightbox"',animationSpeed:250,preloadNext:!0,enableKeyboard:!0,quitOnEnd:!1,quitOnImgClick:!1,quitOnDocClick:!0,onStart:!1,onEnd:!1,onLoadStart:!1,onLoadEnd:!1},i),o=n([]),f=n(),l=n(),p=0,g=0,s=0,h=!1,m=function(){if(!l.length)return!0;var e=.8*n(t).width(),i=.9*n(t).height(),o=new Image;o.src=l.attr("src"),o.onload=function(){if(p=o.width,g=o.height,p>e||g>i){var r=p/g>e/i?p/e:g/i;p/=r,g/=r}l.css({width:p+"px",height:g+"px",top:(n(t).height()-g)/2+"px",left:(n(t).width()-p)/2+"px"})}},v=function(t){if(h)return!1;if(t="undefined"==typeof t?!1:"left"==t?1:-1,l.length){if(t!==!1&&(o.length<2||i.quitOnEnd===!0&&(-1===t&&0==o.index(f)||1===t&&o.index(f)==o.length-1)))return E(),!1;var e={opacity:0};r?a(l,100*t-s+"px",i.animationSpeed/1e3):e.left=parseInt(l.css("left"))+100*t+"px",l.animate(e,i.animationSpeed,function(){x()}),s=0}h=!0,i.onLoadStart!==!1&&i.onLoadStart(),setTimeout(function(){l=n("<img "+i.selector+" />").attr("src",f.attr("href")).on("load",function(){l.appendTo("body"),m();var e={opacity:1};if(l.css("opacity",0),r)a(l,-100*t+"px",0),setTimeout(function(){a(l,"0px",i.animationSpeed/1e3)},50);else{var u=parseInt(l.css("left"));e.left=u+"px",l.css("left",u-100*t+"px")}if(l.animate(e,i.animationSpeed,function(){h=!1,i.onLoadEnd!==!1&&i.onLoadEnd()}),i.preloadNext){var d=o.eq(o.index(f)+1);d.length||(d=o.eq(0)),n("<img />").attr("src",d.attr("href"))}}).on("error",function(){i.onLoadEnd!==!1&&i.onLoadEnd()});var e=0,u=0,g=0;l.on(d?"pointerup MSPointerUp":"click",function(n){if(n.preventDefault(),i.quitOnImgClick)return E(),!1;if(c(n.originalEvent))return!0;var t=(n.pageX||n.originalEvent.pageX)-n.target.offsetLeft;f=o.eq(o.index(f)-(p/2>t?1:-1)),f.length||(f=o.eq(p/2>t?o.length:0)),v(p/2>t?"left":"right")}).on("touchstart pointerdown MSPointerDown",function(n){return!c(n.originalEvent)||i.quitOnImgClick?!0:(r&&(g=parseInt(l.css("left"))),void(e=n.originalEvent.pageX||n.originalEvent.touches[0].pageX))}).on("touchmove pointermove MSPointerMove",function(n){return!c(n.originalEvent)||i.quitOnImgClick?!0:(n.preventDefault(),u=n.originalEvent.pageX||n.originalEvent.touches[0].pageX,s=e-u,void(r?a(l,-s+"px",0):l.css("left",g-s+"px")))}).on("touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel",function(n){return!c(n.originalEvent)||i.quitOnImgClick?!0:void(Math.abs(s)>50?(f=o.eq(o.index(f)-(0>s?1:-1)),f.length||(f=o.eq(0>s?o.length:0)),v(s>0?"right":"left")):r?a(l,"0px",i.animationSpeed/1e3):l.animate({left:g+"px"},i.animationSpeed/2))})},i.animationSpeed+100)},x=function(){return l.length?(l.remove(),void(l=n())):!1},E=function(){return l.length?void l.animate({opacity:0},i.animationSpeed,function(){x(),h=!1,i.onEnd!==!1&&i.onEnd()}):!1},y=function(t){t.each(function(){o=o.add(n(this))}),t.on("click.imageLightbox",function(t){return t.preventDefault(),h?!1:(h=!1,i.onStart!==!1&&i.onStart(),f=n(this),void v())})};return n(t).on("resize",m),i.quitOnDocClick&&n(e).on(u?"touchend":"click",function(t){l.length&&!n(t.target).is(l)&&E()}),i.enableKeyboard&&n(e).on("keyup",function(n){return l.length?(n.preventDefault(),27==n.keyCode&&E(),void((37==n.keyCode||39==n.keyCode)&&(f=o.eq(o.index(f)-(37==n.keyCode?1:-1)),f.length||(f=o.eq(37==n.keyCode?o.length:0)),v(37==n.keyCode?"left":"right")))):!0}),y(n(this)),this.switchImageLightbox=function(n){var t=o.eq(n);if(t.length){var e=o.index(f);f=t,v(e>n?"left":"right")}return this},this.addToImageLightbox=function(n){y(n)},this.quitImageLightbox=function(){return E(),this},this}}(jQuery,window,document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment