imagelightbox.css
5 years ago
imagelightbox.js
5 years ago
imagelightbox.min.css
5 years ago
imagelightbox.min.js
5 years ago
imagelightbox.js
315 lines
| 1 | |
| 2 | /* |
| 3 | By Osvaldas Valutis, www.osvaldas.info |
| 4 | Available for use under the MIT License |
| 5 | */ |
| 6 | |
| 7 | ;( function( $, window, document, undefined ) |
| 8 | { |
| 9 | 'use strict'; |
| 10 | |
| 11 | var cssTransitionSupport = function() |
| 12 | { |
| 13 | var s = document.body || document.documentElement, s = s.style; |
| 14 | if( s.WebkitTransition == '' ) return '-webkit-'; |
| 15 | if( s.MozTransition == '' ) return '-moz-'; |
| 16 | if( s.OTransition == '' ) return '-o-'; |
| 17 | if( s.transition == '' ) return ''; |
| 18 | return false; |
| 19 | }, |
| 20 | |
| 21 | isCssTransitionSupport = cssTransitionSupport() === false ? false : true, |
| 22 | |
| 23 | cssTransitionTranslateX = function( element, positionX, speed ) |
| 24 | { |
| 25 | var options = {}, prefix = cssTransitionSupport(); |
| 26 | options[ prefix + 'transform' ] = 'translateX(' + positionX + ')'; |
| 27 | options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear'; |
| 28 | element.css( options ); |
| 29 | }, |
| 30 | |
| 31 | hasTouch = ( 'ontouchstart' in window ), |
| 32 | hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled, |
| 33 | wasTouched = function( event ) |
| 34 | { |
| 35 | if( hasTouch ) |
| 36 | return true; |
| 37 | |
| 38 | if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) |
| 39 | return false; |
| 40 | |
| 41 | if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ) |
| 42 | { |
| 43 | if( event.MSPOINTER_TYPE_MOUSE != event.pointerType ) |
| 44 | return true; |
| 45 | } |
| 46 | else |
| 47 | if( event.pointerType != 'mouse' ) |
| 48 | return true; |
| 49 | |
| 50 | return false; |
| 51 | }; |
| 52 | |
| 53 | $.fn.imageLightbox = function( options ) |
| 54 | { |
| 55 | var options = $.extend( |
| 56 | { |
| 57 | selector: 'id="imagelightbox"', |
| 58 | animationSpeed: 250, |
| 59 | preloadNext: true, |
| 60 | enableKeyboard: true, |
| 61 | quitOnEnd: false, |
| 62 | quitOnImgClick: false, |
| 63 | quitOnDocClick: true, |
| 64 | onStart: false, |
| 65 | onEnd: false, |
| 66 | onLoadStart: false, |
| 67 | onLoadEnd: false |
| 68 | }, |
| 69 | options ), |
| 70 | |
| 71 | targets = $([]), |
| 72 | target = $(), |
| 73 | image = $(), |
| 74 | imageWidth = 0, |
| 75 | imageHeight = 0, |
| 76 | swipeDiff = 0, |
| 77 | inProgress = false, |
| 78 | |
| 79 | setImage = function() |
| 80 | { |
| 81 | if( !image.length ) return true; |
| 82 | |
| 83 | var screenWidth = $( window ).width() * 0.8, |
| 84 | screenHeight = $( window ).height() * 0.9, |
| 85 | tmpImage = new Image(); |
| 86 | |
| 87 | tmpImage.src = image.attr( 'src' ); |
| 88 | tmpImage.onload = function() |
| 89 | { |
| 90 | imageWidth = tmpImage.width; |
| 91 | imageHeight = tmpImage.height; |
| 92 | |
| 93 | if( imageWidth > screenWidth || imageHeight > screenHeight ) |
| 94 | { |
| 95 | var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight; |
| 96 | imageWidth /= ratio; |
| 97 | imageHeight /= ratio; |
| 98 | } |
| 99 | |
| 100 | image.css( |
| 101 | { |
| 102 | 'width': imageWidth + 'px', |
| 103 | 'height': imageHeight + 'px', |
| 104 | 'top': ( $( window ).height() - imageHeight ) / 2 + 'px', |
| 105 | 'left': ( $( window ).width() - imageWidth ) / 2 + 'px' |
| 106 | }); |
| 107 | }; |
| 108 | }, |
| 109 | |
| 110 | loadImage = function( direction ) |
| 111 | { |
| 112 | if( inProgress ) return false; |
| 113 | |
| 114 | direction = typeof direction === 'undefined' ? false : direction == 'left' ? 1 : -1; |
| 115 | |
| 116 | if( image.length ) |
| 117 | { |
| 118 | if( direction !== false && ( targets.length < 2 || ( options.quitOnEnd === true && ( ( direction === -1 && targets.index( target ) == 0 ) || ( direction === 1 && targets.index( target ) == targets.length - 1 ) ) ) ) ) |
| 119 | { |
| 120 | quitLightbox(); |
| 121 | return false; |
| 122 | } |
| 123 | var params = { 'opacity': 0 }; |
| 124 | if( isCssTransitionSupport ) cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 ); |
| 125 | else params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px'; |
| 126 | image.animate( params, options.animationSpeed, function(){ removeImage(); }); |
| 127 | swipeDiff = 0; |
| 128 | } |
| 129 | |
| 130 | inProgress = true; |
| 131 | if( options.onLoadStart !== false ) options.onLoadStart(); |
| 132 | |
| 133 | setTimeout( function() |
| 134 | { |
| 135 | image = $( '<img ' + options.selector + ' />' ) |
| 136 | .attr( 'src', target.attr( 'href' ) ) |
| 137 | .on( 'load', function() |
| 138 | { |
| 139 | image.appendTo( 'body' ); |
| 140 | setImage(); |
| 141 | |
| 142 | var params = { 'opacity': 1 }; |
| 143 | |
| 144 | image.css( 'opacity', 0 ); |
| 145 | if( isCssTransitionSupport ) |
| 146 | { |
| 147 | cssTransitionTranslateX( image, -100 * direction + 'px', 0 ); |
| 148 | setTimeout( function(){ cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ) }, 50 ); |
| 149 | } |
| 150 | else |
| 151 | { |
| 152 | var imagePosLeft = parseInt( image.css( 'left' ) ); |
| 153 | params.left = imagePosLeft + 'px'; |
| 154 | image.css( 'left', imagePosLeft - 100 * direction + 'px' ); |
| 155 | } |
| 156 | |
| 157 | image.animate( params, options.animationSpeed, function() |
| 158 | { |
| 159 | inProgress = false; |
| 160 | if( options.onLoadEnd !== false ) options.onLoadEnd(); |
| 161 | }); |
| 162 | if( options.preloadNext ) |
| 163 | { |
| 164 | var nextTarget = targets.eq( targets.index( target ) + 1 ); |
| 165 | if( !nextTarget.length ) nextTarget = targets.eq( 0 ); |
| 166 | $( '<img />' ).attr( 'src', nextTarget.attr( 'href' ) ); |
| 167 | } |
| 168 | }) |
| 169 | .on( 'error', function() |
| 170 | { |
| 171 | if( options.onLoadEnd !== false ) options.onLoadEnd(); |
| 172 | }); |
| 173 | |
| 174 | var swipeStart = 0, |
| 175 | swipeEnd = 0, |
| 176 | imagePosLeft = 0; |
| 177 | |
| 178 | image.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function( e ) |
| 179 | { |
| 180 | e.preventDefault(); |
| 181 | if( options.quitOnImgClick ) |
| 182 | { |
| 183 | quitLightbox(); |
| 184 | return false; |
| 185 | } |
| 186 | if( wasTouched( e.originalEvent ) ) return true; |
| 187 | var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft; |
| 188 | target = targets.eq( targets.index( target ) - ( imageWidth / 2 > posX ? 1 : -1 ) ); |
| 189 | if( !target.length ) target = targets.eq( imageWidth / 2 > posX ? targets.length : 0 ); |
| 190 | loadImage( imageWidth / 2 > posX ? 'left' : 'right' ); |
| 191 | }) |
| 192 | .on( 'touchstart pointerdown MSPointerDown', function( e ) |
| 193 | { |
| 194 | if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; |
| 195 | if( isCssTransitionSupport ) imagePosLeft = parseInt( image.css( 'left' ) ); |
| 196 | swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; |
| 197 | }) |
| 198 | .on( 'touchmove pointermove MSPointerMove', function( e ) |
| 199 | { |
| 200 | if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; |
| 201 | e.preventDefault(); |
| 202 | swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; |
| 203 | swipeDiff = swipeStart - swipeEnd; |
| 204 | if( isCssTransitionSupport ) cssTransitionTranslateX( image, -swipeDiff + 'px', 0 ); |
| 205 | else image.css( 'left', imagePosLeft - swipeDiff + 'px' ); |
| 206 | }) |
| 207 | .on( 'touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel', function( e ) |
| 208 | { |
| 209 | if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; |
| 210 | if( Math.abs( swipeDiff ) > 50 ) |
| 211 | { |
| 212 | target = targets.eq( targets.index( target ) - ( swipeDiff < 0 ? 1 : -1 ) ); |
| 213 | if( !target.length ) target = targets.eq( swipeDiff < 0 ? targets.length : 0 ); |
| 214 | loadImage( swipeDiff > 0 ? 'right' : 'left' ); |
| 215 | } |
| 216 | else |
| 217 | { |
| 218 | if( isCssTransitionSupport ) cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); |
| 219 | else image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 ); |
| 220 | } |
| 221 | }); |
| 222 | |
| 223 | }, options.animationSpeed + 100 ); |
| 224 | }, |
| 225 | |
| 226 | removeImage = function() |
| 227 | { |
| 228 | if( !image.length ) return false; |
| 229 | image.remove(); |
| 230 | image = $(); |
| 231 | }, |
| 232 | |
| 233 | quitLightbox = function() |
| 234 | { |
| 235 | if( !image.length ) return false; |
| 236 | image.animate({ 'opacity': 0 }, options.animationSpeed, function() |
| 237 | { |
| 238 | removeImage(); |
| 239 | inProgress = false; |
| 240 | if( options.onEnd !== false ) options.onEnd(); |
| 241 | }); |
| 242 | }, |
| 243 | |
| 244 | addTargets = function( newTargets ) |
| 245 | { |
| 246 | newTargets.each( function() |
| 247 | { |
| 248 | targets = targets.add( $( this ) ); |
| 249 | }); |
| 250 | |
| 251 | newTargets.on( 'click.imageLightbox', function( e ) |
| 252 | { |
| 253 | e.preventDefault(); |
| 254 | if( inProgress ) return false; |
| 255 | inProgress = false; |
| 256 | if( options.onStart !== false ) options.onStart(); |
| 257 | target = $( this ); |
| 258 | loadImage(); |
| 259 | }); |
| 260 | }; |
| 261 | |
| 262 | $( window ).on( 'resize', setImage ); |
| 263 | |
| 264 | if( options.quitOnDocClick ) |
| 265 | { |
| 266 | $( document ).on( hasTouch ? 'touchend' : 'click', function( e ) |
| 267 | { |
| 268 | if( image.length && !$( e.target ).is( image ) ) quitLightbox(); |
| 269 | }); |
| 270 | } |
| 271 | |
| 272 | if( options.enableKeyboard ) |
| 273 | { |
| 274 | $( document ).on( 'keyup', function( e ) |
| 275 | { |
| 276 | if( !image.length ) return true; |
| 277 | e.preventDefault(); |
| 278 | if( e.keyCode == 27 ) quitLightbox(); |
| 279 | if( e.keyCode == 37 || e.keyCode == 39 ) |
| 280 | { |
| 281 | target = targets.eq( targets.index( target ) - ( e.keyCode == 37 ? 1 : -1 ) ); |
| 282 | if( !target.length ) target = targets.eq( e.keyCode == 37 ? targets.length : 0 ); |
| 283 | loadImage( e.keyCode == 37 ? 'left' : 'right' ); |
| 284 | } |
| 285 | }); |
| 286 | } |
| 287 | |
| 288 | addTargets( $( this ) ); |
| 289 | |
| 290 | this.switchImageLightbox = function( index ) |
| 291 | { |
| 292 | var tmpTarget = targets.eq( index ); |
| 293 | if( tmpTarget.length ) |
| 294 | { |
| 295 | var currentIndex = targets.index( target ); |
| 296 | target = tmpTarget; |
| 297 | loadImage( index < currentIndex ? 'left' : 'right' ); |
| 298 | } |
| 299 | return this; |
| 300 | }; |
| 301 | |
| 302 | this.addToImageLightbox = function( newTargets ) |
| 303 | { |
| 304 | addTargets( newTargets ); |
| 305 | }; |
| 306 | |
| 307 | this.quitImageLightbox = function() |
| 308 | { |
| 309 | quitLightbox(); |
| 310 | return this; |
| 311 | }; |
| 312 | |
| 313 | return this; |
| 314 | }; |
| 315 | })( jQuery, window, document ); |