PageSourceSearch

https://villanegyed.hu/includes/simplelightbox/dist/simple-lightbox.js

js villanegyed.hu collected 2026-10-08 23:44:22 UTC 28,238 bytes, 862 lines download raw bytes

1/*!
2	By André Rinas, www.andrerinas.de
3	Documentation, www.simplelightbox.de
4	Available for use under the MIT License
5	1.17.1
6*/
7;( function( $, window, document, undefined )
8{
9	'use strict';
10
11$.fn.simpleLightbox = function( options )
12{
13
14	var options = $.extend({
15		sourceAttr: 'href',
16		overlay: true,
17		spinner: true,
18		nav: true,
19		navText: ['‹', '›'],
20		captions: true,
21		captionDelay: 0,
22		captionSelector: 'img',
23		captionType: 'attr',
24		captionsData: 'title',
25		captionPosition: 'bottom',
26		captionClass: '',
27		close: true,
28		closeText: '×',
29		swipeClose: true,
30		showCounter: true,
31		fileExt: 'png|jpg|jpeg|gif|webp',
32		animationSlide: true,
33		animationSpeed: 250,
34		preloading: true,
35		enableKeyboard: true,
36		loop: true,
37		rel: false,
38		docClose: true,
39		swipeTolerance: 50,
40		className: 'simple-lightbox',
41		widthRatio: 0.85,
42		heightRatio: 0.9,
43		scaleImageToRatio: false,
44		disableRightClick: false,
45		disableScroll: true,
46		alertError: true,
47		alertErrorMessage: 'Image not found, next image will be loaded',
48		additionalHtml: false,
49		history: true,
50		throttleInterval: 0,
51		doubleTapZoom: 2,
52		maxZoom: 10,
53		htmlClass: 'has-lightbox'
54	}, options);
55
56	// global variables
57	var touchDevice	= ( 'ontouchstart' in window ),
58		pointerEnabled = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
59		touched = function( event ){
60			if( touchDevice ) return true;
61			if( !pointerEnabled || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) return false;
62			if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ) {
63				if( event.MSPOINTER_TYPE_MOUSE != event.pointerType ) return true;
64			}
65			else {
66				if( event.pointerType != 'mouse' ) return true;
67			}
68			return false;
69		},
70		swipeDiff = 0,
71		swipeYDiff = 0,
72		curImg = $(),
73		transPrefix = function(){
74			var s = document.body || document.documentElement;
75			s = s.style;
76			if( s.WebkitTransition === '' ) return '-webkit-';
77			if( s.MozTransition === '' ) return '-moz-';
78			if( s.OTransition === '' ) return '-o-';
79			if( s.transition === '' ) return '';
80			return false;
81		},
82		opened = false,
83		loaded = [],
84		getRelated = function(rel, jqObj) {
85			var $related = jqObj.filter(function () {
86				return ($(this).attr('rel') === rel);
87			});
88			return $related;
89		},
90		objects = (options.rel && options.rel !== false) ? getRelated(options.rel, $(this)) : this,
91		tagname = objects.get()[0].tagName,
92		transPrefix = transPrefix(),
93		globalScrollbarwidth = 0,
94		canTransisions = (transPrefix !== false) ? true : false,
95		supportsPushState = ('pushState' in history),
96		historyhasChanged = false,
97		historyUpdateTimeout,
98		winLoc = window.location,
99		getHash = function(){
100			return winLoc.hash.substring(1);
101		},
102		initialHash = getHash(),
103		updateHash = function(){
104			var hash = getHash(),
105			newHash = 'pid='+(index+1);
106			var newURL = winLoc.href.split('#')[0] + '#' + newHash;
107
108			if(supportsPushState){
109				history[historyhasChanged ? 'replaceState' : 'pushState']('', document.title, newURL);
110			}else {
111				if(historyhasChanged) {
112					winLoc.replace( newURL );
113				} else {
114					winLoc.hash = newHash;
115				}
116			}
117			historyhasChanged = true;
118		},
119		resetHash = function() {
120			if (supportsPushState) {
121				history.pushState('', document.title, winLoc.pathname + winLoc.search );
122			} else {
123				winLoc.hash = '';
124			}
125			clearTimeout(historyUpdateTimeout);
126
127		},
128		updateURL = function(){
129			if(!historyhasChanged) {
130				updateHash(); // first time
131			} else {
132				historyUpdateTimeout = setTimeout(updateHash, 800);
133			}
134		},
135		throttle = function(func, limit) {
136			var inThrottle;
137			return function() {
138				var args = arguments;
139				var context = this;
140				if (!inThrottle) {
141					func.apply(context, args);
142					inThrottle = true;
143					setTimeout(function() {
144						return inThrottle = false;
145					}, limit);
146				}
147			};
148		},
149		prefix = 'simplelb',
150		overlay = $('<div>').addClass('sl-overlay'),
151		closeBtn = $('<button>').addClass('sl-close').html(options.closeText),
152		spinner = $('<div>').addClass('sl-spinner').html('<div></div>'),
153		nav = $('<div>').addClass('sl-navigation').html('<button class="sl-prev">'+options.navText[0]+'</button><button class="sl-next">'+options.navText[1]+'</button>'),
154		counter = $('<div>').addClass('sl-counter').html('<span class="sl-current"></span>/<span class="sl-total"></span>'),
155		animating = false,
156		index = 0,
157		startIndex = 0,
158		caption = $('<div>').addClass('sl-caption '+options.captionClass+' pos-'+options.captionPosition),
159		image = $('<div>').addClass('sl-image'),
160		wrapper = $('<div>').addClass('sl-wrapper').addClass(options.className),
161		isValidLink = function( element ){
162			if(!options.fileExt) return true;
163			var filEext = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gmi;
164			var testExt = $( element ).attr( options.sourceAttr ).match(filEext);
165			return testExt && $( element ).prop( 'tagName' ).toUpperCase() == tagname && ( new RegExp( '\.(' + options.fileExt + ')$', 'i' ) ).test( testExt );
166		},
167		setup = function(){
168			if(options.close) closeBtn.appendTo(wrapper);
169			if(options.showCounter){
170				if(objects.length > 1){
171					counter.appendTo(wrapper);
172					counter.find('.sl-total').text(objects.length);
173				}
174			}
175			if(options.nav) nav.appendTo(wrapper);
176			if(options.spinner) spinner.appendTo(wrapper);
177		},
178		openImage = function(elem){
179			elem.trigger($.Event('show.simplelightbox'));
180			if(options.disableScroll) globalScrollbarwidth = handleScrollbar('hide');
181			if(options.htmlClass && options.htmlClass != '') $('html').addClass(options.htmlClass);
182			wrapper.appendTo('body');
183			image.appendTo(wrapper);
184			if(options.overlay) overlay.appendTo($('body'));
185			animating = true;
186			index = objects.index(elem);
187			curImg = $( '<img/>' )
188				.hide()
189				.attr('src', elem.attr(options.sourceAttr))
190				.attr('data-scale', 1)
191				.attr('data-translate-x', 0)
192				.attr('data-translate-y', 0);
193			if(loaded.indexOf(elem.attr(options.sourceAttr)) == -1){
194				loaded.push(elem.attr(options.sourceAttr));
195			}
196			image.html('').attr('style','');
197			curImg.appendTo(image);
198			addEvents();
199			overlay.fadeIn('fast');
200			$('.sl-close').fadeIn('fast');
201			spinner.show();
202			nav.fadeIn('fast');
203			$('.sl-wrapper .sl-counter .sl-current').text(index +1);
204			counter.fadeIn('fast');
205			adjustImage();
206			if(options.preloading) preload();
207			setTimeout( function(){ elem.trigger($.Event('shown.simplelightbox')); } ,options.animationSpeed);
208		},
209		adjustImage = function(dir){
210			if(!curImg.length) return;
211			var tmpImage 	 = new Image(),
212			windowWidth	 = window.innerWidth * options.widthRatio,
213			windowHeight = window.innerHeight * options.heightRatio;
214			tmpImage.src	= curImg.attr( 'src' );
215			curImg.data('scale',1);
216			curImg.data('translate-x',0);
217			curImg.data('translate-y',0);
218			zoomPanElement(0,0,1);
219			$(tmpImage).on('error',function(ev){
220				//no image was found
221				objects.eq(index).trigger($.Event('error.simplelightbox'));
222				animating = false;
223				opened = true;
224				spinner.hide();
225				var dirDefinined = (dir == 1 || dir == -1);
226				if(startIndex === index && dirDefinined){
227					close();
228					return;
229				}
230				if(options.alertError){
231					alert(options.alertErrorMessage);
232				}
233				if(dirDefinined){
234					loadImage(dir);
235				} else {
236					loadImage(1);
237				}
238				return;
239			});
240
241
242			tmpImage.onload = function() {
243				if (typeof dir !== 'undefined') {
244					objects.eq(index)
245						.trigger($.Event('changed.simplelightbox'))
246						.trigger($.Event( (dir===1?'nextDone':'prevDone')+'.simplelightbox'));
247				}
248
249				// history
250				if(options.history){
251					updateURL();
252				}
253
254				if(loaded.indexOf(curImg.attr( 'src' )) == -1){
255					loaded.push(curImg.attr( 'src' ));
256				}
257				var imageWidth	 = tmpImage.width,
258					imageHeight	 = tmpImage.height;
259
260				if( options.scaleImageToRatio || imageWidth > windowWidth || imageHeight > windowHeight ){
261					var ratio	 = imageWidth / imageHeight > windowWidth / windowHeight ? imageWidth / windowWidth : imageHeight / windowHeight;
262					imageWidth	/= ratio;
263					imageHeight	/= ratio;
264				}
265
266				$('.sl-image').css({
267					'top':    ( window.innerHeight - imageHeight ) / 2 + 'px',
268					'left':   ( window.innerWidth - imageWidth - globalScrollbarwidth)/ 2 + 'px',
269					'width':  imageWidth + 'px',
270					'height': imageHeight + 'px'
271				});
272				spinner.hide();
273				curImg
274				.fadeIn('fast');
275				opened = true;
276				var cSel = (options.captionSelector == 'self') ? objects.eq(index) : objects.eq(index).find(options.captionSelector);
277				var captionText;
278				if(options.captionType == 'data'){
279					captionText = cSel.data(options.captionsData);
280				} else if(options.captionType == 'text'){
281					captionText = cSel.html();
282				} else {
283					captionText = cSel.prop(options.captionsData);
284				}
285
286				if(!options.loop) {
287					if(index === 0){ $('.sl-prev').hide();}
288					if(index >= objects.length -1) {$('.sl-next').hide();}
289					if(index > 0){ $('.sl-prev').show(); }
290					if(index < objects.length -1){ $('.sl-next').show(); }
291				}
292
293				if(objects.length == 1) $('.sl-prev, .sl-next').hide();
294
295				if(dir == 1 || dir == -1){
296					var css = { 'opacity': 1.0 };
297					if( options.animationSlide ) {
298						if( canTransisions ) {
299							slide(0, 100 * dir + 'px');
300							setTimeout( function(){ slide( options.animationSpeed / 1000, 0 + 'px'); }, 50 );
301						}
302						else {
303							css.left = parseInt( $('.sl-image').css( 'left' ) ) + 100 * dir + 'px';
304						}
305					}
306
307					$('.sl-image').animate( css, options.animationSpeed, function(){
308						animating = false;
309						setCaption(captionText, imageWidth);
310					});
311				} else {
312					animating = false;
313					setCaption(captionText, imageWidth);
314				}
315				if(options.additionalHtml && $('.sl-additional-html').length === 0){
316					$('<div>').html(options.additionalHtml).addClass('sl-additional-html').appendTo($('.sl-image'));
317				}
318			};
319		},
320		setCaption = function(captiontext, imageWidth){
321			if(captiontext !== '' && typeof captiontext !== "undefined" && options.captions){
322				caption.html(captiontext).css({'width': imageWidth + 'px'}).hide().appendTo($('.sl-image')).delay(options.captionDelay).fadeIn('fast');
323			}
324		},
325		slide = function(speed, pos){
326			var styles = {};
327				styles[transPrefix + 'transform'] = 'translateX(' + pos + ')';
328				styles[transPrefix + 'transition'] = transPrefix + 'transform ' + speed + 's linear';
329				$('.sl-image').css(styles);
330		},
331		zoomPanElement = function(targetOffsetX, targetOffsetY, targetScale) {
332			var styles = {};
333			styles[transPrefix + 'transform'] = 'translate(' + targetOffsetX + ',' + targetOffsetY+ ') scale('+targetScale+')';
334			curImg.css(styles);
335		},
336		minMax = function(value, min, max) {
337			return (value < min) ? min : (value > max) ? max : value;
338		},
339		setZoomData = function(initialScale,targetOffsetX,targetOffsetY) {
340			curImg.data('scale',initialScale);
341			curImg.data('translate-x',targetOffsetX);
342			curImg.data('translate-y',targetOffsetY);
343		},
344		addEvents = function(){
345			// resize/responsive
346			$( window ).on( 'resize.'+prefix, adjustImage );
347
348			// close lightbox on close btn
349			$( document ).on('click.'+prefix+ ' touchstart.'+prefix, '.sl-close', function(e){
350				e.preventDefault();
351				if(opened){ close();}
352			});
353
354			if(options.history){
355				setTimeout(function() {
356					$(window).on('hashchange.'+prefix,function(){
357						if(opened){
358							if(getHash() === initialHash) {
359								close();
360								return;
361							}
362						}
363					});
364				}, 40);
365			}
366
367			// nav-buttons
368			nav.on('click.'+prefix, 'button', throttle(function(e){
369				e.preventDefault();
370				swipeDiff = 0;
371				loadImage( $(this).hasClass('sl-next') ? 1 : -1 );
372			}, options.throttleInterval));
373
374			// touch helpers
375			var swipeStart	 = 0,
376				swipeEnd	 = 0,
377				swipeYStart = 0,
378				swipeYEnd = 0,
379				zoomed = false,
380				mousedown = false,
381				imageLeft = 0,
382				containerHeight,
383				containerWidth,
384				containerOffsetX,
385				containerOffsetY,
386				imgHeight,
387				imgWidth,
388				capture = false,
389				initialOffsetX,
390				initialOffsetY,
391				initialPointerOffsetX,
392				initialPointerOffsetY,
393				initialPointerOffsetX2,
394				initialPointerOffsetY2,
395				initialScale = minMax(1, 1, options.maxZoom),
396				initialPinchDistance,
397				pointerOffsetX,
398				pointerOffsetY,
399				pointerOffsetX2,
400				pointerOffsetY2,
401				targetOffsetX,
402				targetOffsetY,
403				targetScale,
404				pinchOffsetX,
405				pinchOffsetY,
406				limitOffsetX,
407				limitOffsetY,
408				scaleDifference,
409				targetPinchDistance,
410				touchCount,
411				doubleTapped = false,
412				touchmoveCount = 0;
413
414			image
415			.on( 'touchstart.'+prefix+' mousedown.'+prefix, function(e)
416			{
417				if (e.target.tagName === 'A' && e.type == 'touchstart') {
418					return true;
419				}
420				e = e.originalEvent;
421				if(e.type == 'mousedown') {
422					initialPointerOffsetX = e.clientX;
423					initialPointerOffsetY = e.clientY;
424					containerHeight = image.height();
425					containerWidth = image.width();
426					imgHeight = curImg.height();
427					imgWidth = curImg.width();
428					containerOffsetX = image.position().left;
429					containerOffsetY = image.position().top;
430
431					initialOffsetX = parseFloat(curImg.data('translate-x'));
432					initialOffsetY = parseFloat(curImg.data('translate-y'));
433
434					capture = true;
435				} else {
436					touchCount = e.touches.length;
437					initialPointerOffsetX = e.touches[0].clientX;
438					initialPointerOffsetY = e.touches[0].clientY;
439					containerHeight = image.height();
440					containerWidth = image.width();
441					imgHeight = curImg.height();
442					imgWidth = curImg.width();
443					containerOffsetX = image.position().left;
444					containerOffsetY = image.position().top;
445
446					if (touchCount === 1) /* Single touch */ {
447						if(!doubleTapped) {
448							doubleTapped = true;
449							setTimeout(function(){
450								doubleTapped = false;
451							}, 300);
452						} else {
453							curImg.addClass('sl-transition');
454							if(!zoomed) {
455								initialScale = options.doubleTapZoom;
456								setZoomData(0,0, initialScale);
457								zoomPanElement(0 + "px", 0 + "px", initialScale);
458								$('.sl-caption').fadeOut(200);
459								zoomed = true;
460							} else {
461								initialScale = 1;
462								setZoomData(0,0,initialScale);
463								zoomPanElement(0 + "px", 0 + "px", initialScale);
464								zoomed = false;
465							}
466
467							setTimeout(function(){
468								curImg.removeClass('sl-transition');
469							}, 200);
470							return false;
471						}
472
473						initialOffsetX = parseFloat(curImg.data('translate-x'));
474						initialOffsetY = parseFloat(curImg.data('translate-y'));
475					}
476					else if (touchCount === 2) /* Pinch */ {
477						initialPointerOffsetX2 = e.touches[1].clientX;
478						initialPointerOffsetY2 = e.touches[1].clientY;
479						initialOffsetX = parseFloat(curImg.data('translate-x'));
480						initialOffsetY = parseFloat(curImg.data('translate-y'));
481						pinchOffsetX = (initialPointerOffsetX + initialPointerOffsetX2) / 2;
482						pinchOffsetY = (initialPointerOffsetY + initialPointerOffsetY2) / 2;
483						initialPinchDistance = Math.sqrt(((initialPointerOffsetX - initialPointerOffsetX2) * (initialPointerOffsetX - initialPointerOffsetX2)) + ((initialPointerOffsetY - initialPointerOffsetY2) * (initialPointerOffsetY - initialPointerOffsetY2)));
484					}
485					capture = true;
486				}
487
488				if(mousedown) return true;
489				if( canTransisions ) imageLeft = parseInt( image.css( 'left' ) );
490				mousedown = true;
491				swipeDiff = 0;
492				swipeYDiff = 0;
493				swipeStart = e.pageX || e.touches[ 0 ].pageX;
494				swipeYStart = e.pageY || e.touches[ 0 ].pageY;
495				return false;
496			})
497			.on( 'touchmove.'+prefix+' mousemove.'+prefix+' MSPointerMove', function(e)
498			{
499				if(!mousedown) return true;
500				e.preventDefault();
501				e = e.originalEvent;
502				/* Initialize helpers */
503				if(e.type == 'touchmove') {
504					if(capture === false) return false;
505					pointerOffsetX = e.touches[0].clientX;
506					pointerOffsetY = e.touches[0].clientY;
507					touchCount = e.touches.length;
508					touchmoveCount++;
509
510					if (touchCount > 1) /* Pinch */ {
511						pointerOffsetX2 = e.touches[1].clientX;
512						pointerOffsetY2 = e.touches[1].clientY;
513						targetPinchDistance = Math.sqrt(((pointerOffsetX - pointerOffsetX2) * (pointerOffsetX - pointerOffsetX2)) + ((pointerOffsetY - pointerOffsetY2) * (pointerOffsetY - pointerOffsetY2)));
514						if (initialPinchDistance === null) {
515							initialPinchDistance = targetPinchDistance;
516						}
517
518						if (Math.abs(initialPinchDistance - targetPinchDistance) >= 1) {
519							/* Initialize helpers */
520							targetScale = minMax(targetPinchDistance / initialPinchDistance * initialScale, 1, options.maxZoom);
521							limitOffsetX = ((imgWidth * targetScale) - containerWidth) / 2;
522							limitOffsetY = ((imgHeight * targetScale) - containerHeight) / 2;
523							scaleDifference = targetScale - initialScale;
524							targetOffsetX = (imgWidth * targetScale) <= containerWidth ? 0: minMax(initialOffsetX - ((((((pinchOffsetX - containerOffsetX) - (containerWidth / 2)) - initialOffsetX) / (targetScale - scaleDifference))) * scaleDifference), limitOffsetX * (-1), limitOffsetX);
525							targetOffsetY = (imgHeight * targetScale) <= containerHeight ? 0 : minMax(initialOffsetY - ((((((pinchOffsetY - containerOffsetY) - (containerHeight / 2)) - initialOffsetY) / (targetScale - scaleDifference))) * scaleDifference), limitOffsetY * (-1), limitOffsetY);
526
527							zoomPanElement(targetOffsetX + "px", targetOffsetY + "px", targetScale);
528
529							if (targetScale > 1) {
530								zoomed = true;
531								$('.sl-caption').fadeOut(200);
532							}
533
534							initialPinchDistance = targetPinchDistance;
535							initialScale = targetScale;
536							initialOffsetX = targetOffsetX;
537							initialOffsetY = targetOffsetY;
538						}
539					} else {
540						targetScale = initialScale;
541						limitOffsetX = ((imgWidth * targetScale) - containerWidth) / 2;
542						limitOffsetY = ((imgHeight * targetScale) - containerHeight) / 2;
543						targetOffsetX = (imgWidth * targetScale) <= containerWidth ? 0 : minMax(pointerOffsetX - (initialPointerOffsetX - initialOffsetX), limitOffsetX * (-1), limitOffsetX);
544						targetOffsetY = (imgHeight * targetScale) <= containerHeight ? 0 : minMax(pointerOffsetY - (initialPointerOffsetY - initialOffsetY), limitOffsetY * (-1), limitOffsetY);
545
546						if (Math.abs(targetOffsetX) === Math.abs(limitOffsetX)) {
547							initialOffsetX = targetOffsetX;
548							initialPointerOffsetX = pointerOffsetX;
549						}
550
551						if (Math.abs(targetOffsetY) === Math.abs(limitOffsetY)) {
552							initialOffsetY = targetOffsetY;
553							initialPointerOffsetY = pointerOffsetY;
554						}
555
556						setZoomData(initialScale,targetOffsetX,targetOffsetY);
557						zoomPanElement(targetOffsetX + "px", targetOffsetY + "px", targetScale);
558					}
559				}
560				/* Mouse Move implementation */
561				if(e.type == 'mousemove' && mousedown){
562					if(e.type == 'touchmove') return true;
563					if(capture === false) return false;
564					pointerOffsetX = e.clientX;
565					pointerOffsetY = e.clientY;
566					targetScale = initialScale;
567					limitOffsetX = ((imgWidth * targetScale) - containerWidth) / 2;
568					limitOffsetY = ((imgHeight * targetScale) - containerHeight) / 2;
569					targetOffsetX = (imgWidth * targetScale) <= containerWidth ? 0 : minMax(pointerOffsetX - (initialPointerOffsetX - initialOffsetX), limitOffsetX * (-1), limitOffsetX);
570					targetOffsetY = (imgHeight * targetScale) <= containerHeight ? 0 : minMax(pointerOffsetY - (initialPointerOffsetY - initialOffsetY), limitOffsetY * (-1), limitOffsetY);
571
572					if (Math.abs(targetOffsetX) === Math.abs(limitOffsetX)) {
573						initialOffsetX = targetOffsetX;
574						initialPointerOffsetX = pointerOffsetX;
575					}
576
577					if (Math.abs(targetOffsetY) === Math.abs(limitOffsetY)) {
578						initialOffsetY = targetOffsetY;
579						initialPointerOffsetY = pointerOffsetY;
580					}
581
582					setZoomData(initialScale,targetOffsetX,targetOffsetY);
583					zoomPanElement(targetOffsetX + "px", targetOffsetY + "px", targetScale);
584				}
585				if(!zoomed) {
586					swipeEnd = e.pageX || e.touches[ 0 ].pageX;
587					swipeYEnd = e.pageY || e.touches[ 0 ].pageY;
588					swipeDiff = swipeStart - swipeEnd;
589					swipeYDiff = swipeYStart - swipeYEnd;
590					if( options.animationSlide ) {
591						if( canTransisions ) slide( 0, -swipeDiff + 'px' );
592						else image.css( 'left', imageLeft - swipeDiff + 'px' );
593					}
594				}
595			})
596			.on( 'touchend.'+prefix+' mouseup.'+prefix+' touchcancel.'+prefix+' mouseleave.'+prefix+' pointerup pointercancel MSPointerUp MSPointerCancel',function(e)
597			{
598				e = e.originalEvent;
599				if(touchDevice && e.type =='touchend') {
600					touchCount = e.touches.length;
601					if (touchCount === 0) /* No touch */ {
602						/* Set attributes */
603						setZoomData(initialScale,targetOffsetX,targetOffsetY);
604						if(initialScale == 1) {
605							zoomed = false;
606							$('.sl-caption').fadeIn(200);
607						}
608						initialPinchDistance = null;
609						capture = false;
610					} else if (touchCount === 1) /* Single touch */ {
611						initialPointerOffsetX = e.touches[0].clientX;
612						initialPointerOffsetY = e.touches[0].clientY;
613					} else if (touchCount > 1) /* Pinch */ {
614						initialPinchDistance = null;
615					}
616				}
617
618				if(mousedown){
619					mousedown = false;
620					var possibleDir = true;
621					if(!options.loop) {
622						if(index === 0 && swipeDiff < 0){ possibleDir = false; }
623						if(index >= objects.length -1 && swipeDiff > 0) { possibleDir = false; }
624					}
625					if( Math.abs( swipeDiff ) > options.swipeTolerance && possibleDir ) {
626						loadImage( swipeDiff > 0 ? 1 : -1 );
627					}
628					else if( options.animationSlide )
629					{
630						if( canTransisions ) slide( options.animationSpeed / 1000, 0 + 'px' );
631						else image.animate({ 'left': imageLeft + 'px' }, options.animationSpeed / 2 );
632					}
633
634					if( options.swipeClose && Math.abs(swipeYDiff) > 50 && Math.abs( swipeDiff ) < options.swipeTolerance) {
635						close();
636					}
637				}
638			})
639			/** Detect Double click on image*/
640			.on( 'dblclick', function(e)
641			{
642				initialPointerOffsetX = e.clientX;
643				initialPointerOffsetY = e.clientY;
644				containerHeight = image.height();
645				containerWidth = image.width();
646				imgHeight = curImg.height();
647				imgWidth = curImg.width();
648				containerOffsetX = image.position().left;
649				containerOffsetY = image.position().top;
650
651				curImg.addClass('sl-transition');
652				if(!zoomed) {
653					initialScale = options.doubleTapZoom;
654					setZoomData(0,0, initialScale);
655					zoomPanElement(0 + "px", 0 + "px", initialScale);
656					$('.sl-caption').fadeOut(200);
657					zoomed = true;
658				} else {
659					initialScale = 1;
660					setZoomData(0,0,initialScale);
661					zoomPanElement(0 + "px", 0 + "px", initialScale);
662					zoomed = false;
663				}
664
665				setTimeout(function(){
666					curImg.removeClass('sl-transition');
667				}, 200);
668				capture = true;
669				return false;
670			});
671		},
672		removeEvents = function(){
673			nav.off('click', 'button');
674			$( document ).off('click.'+prefix, '.sl-close');
675			$( window ).off( 'resize.'+prefix);
676			$( window ).off( 'hashchange.'+prefix);
677		},
678		preload = function(){
679			var next = (index+1 < 0) ? objects.length -1: (index+1 >= objects.length -1) ? 0 : index+1,
680				prev = (index-1 < 0) ? objects.length -1: (index-1 >= objects.length -1) ? 0 : index-1;
681			$( '<img />' ).attr( 'src', objects.eq(next).attr( options.sourceAttr ) ).on('load', function(){
682				if(loaded.indexOf($(this).attr('src')) == -1){
683					loaded.push($(this).attr('src'));
684				}
685				objects.eq(index).trigger($.Event('nextImageLoaded.simplelightbox'));
686			});
687			$( '<img />' ).attr( 'src', objects.eq(prev).attr( options.sourceAttr ) ).on('load', function(){
688				if(loaded.indexOf($(this).attr('src')) == -1){
689					loaded.push($(this).attr('src'));
690				}
691				objects.eq(index).trigger($.Event('prevImageLoaded.simplelightbox'));
692			});
693
694		},
695		loadImage = function(dir){
696			objects.eq(index)
697			.trigger($.Event('change.simplelightbox'))
698			.trigger($.Event( (dir===1?'next':'prev')+'.simplelightbox'));
699
700		var newIndex = index + dir;
701			if(animating || (newIndex < 0 || newIndex >= objects.length) && options.loop === false ) return;
702			index = (newIndex < 0) ? objects.length -1: (newIndex > objects.length -1) ? 0 : newIndex;
703			$('.sl-wrapper .sl-counter .sl-current').text(index +1);
704				var css = { 'opacity': 0 };
705			if( options.animationSlide ) {
706				if( canTransisions ) slide(options.animationSpeed / 1000, ( -100 * dir ) - swipeDiff + 'px');
707				else css.left = parseInt( $('.sl-image').css( 'left' ) ) + -100 * dir + 'px';
708			}
709
710			$('.sl-image').animate( css, options.animationSpeed, function(){
711				setTimeout( function(){
712					// fadeout old image
713					var elem = objects.eq(index);
714					curImg
715					.attr('src', elem.attr(options.sourceAttr));
716
717					if(loaded.indexOf(elem.attr(options.sourceAttr)) == -1){
718						spinner.show();
719					}
720					$('.sl-caption').remove();
721					adjustImage(dir);
722					if(options.preloading) preload();
723				}, 100);
724			});
725		},
726		close = function(){
727			if(animating) return;
728			var elem = objects.eq(index),
729			triggered = false;
730
731			elem.trigger($.Event('close.simplelightbox'));
732			if(options.history){
733				resetHash();
734			}
735			$('.sl-image img, .sl-overlay, .sl-close, .sl-navigation, .sl-image .sl-caption, .sl-counter').fadeOut('fast', function(){
736				if(options.disableScroll) handleScrollbar('show');
737				if(options.htmlClass && options.htmlClass != '') $('html').removeClass(options.htmlClass);
738				$('.sl-wrapper, .sl-overlay').remove();
739				removeEvents();
740				if(!triggered) elem.trigger($.Event('closed.simplelightbox'));
741				triggered = true;
742			});
743			curImg = $();
744			opened = false;
745			animating = false;
746		},
747		handleScrollbar = function(type){
748			var scrollbarWidth = 0;
749			if(type == 'hide'){
750				var fullWindowWidth = window.innerWidth;
751				if (!fullWindowWidth) {
752					var documentElementRect = document.documentElement.getBoundingClientRect();
753					fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
754				}
755				if(document.body.clientWidth < fullWindowWidth){
756					var scrollDiv = document.createElement('div'),
757					padding = parseInt($('body').css('padding-right'),10);
758					scrollDiv.className = 'sl-scrollbar-measure';
759					$('body').append(scrollDiv);
760					scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
761					$(document.body)[0].removeChild(scrollDiv);
762					$('body').data('padding',padding);
763					if(scrollbarWidth > 0){
764						$('body').addClass('hidden-scroll').css({'padding-right':padding+scrollbarWidth});
765					}
766				}
767			} else {
768				$('body').removeClass('hidden-scroll').css({'padding-right':$('body').data('padding')});
769			}
770			return scrollbarWidth;
771		};
772
773	// events
774	setup();
775
776	// open lightbox
777	objects.on( 'click.'+prefix, function( e ){
778		if(isValidLink(this)){
779			e.preventDefault();
780			if(animating) return false;
781			var elem = $(this);
782			startIndex = objects.index(elem);
783			openImage(elem);
784		}
785	});
786
787	// close on click on doc
788	$( document ).on('click.'+prefix+ ' touchstart.'+prefix, function(e){
789		if(opened){
790			if((options.docClose && $(e.target).closest('.sl-image').length === 0 && $(e.target).closest('.sl-navigation').length === 0)){
791				close();
792			}
793		}
794	});
795
796	// disable rightclick
797	if(options.disableRightClick){
798		$( document ).on('contextmenu', '.sl-image img', function(e){
799			return false;
800		});
801	}
802
803
804	// keyboard-control
805	if( options.enableKeyboard ){
806		$( document ).on( 'keyup.'+prefix, throttle(function( e ){
807			swipeDiff = 0;
808			// keyboard control only if lightbox is open
809			var key = e.keyCode;
810			if(animating && key == 27) {
811				curImg.attr('src', '');
812				animating = false;
813				close();
814			}
815
816			if(opened){
817				e.preventDefault();
818				if( key == 27 ) {
819					close();
820				}
821				if( key == 37 || e.keyCode == 39 ) {
822					loadImage( e.keyCode == 39 ? 1 : -1 );
823				}
824			}
825		}, options.throttleInterval));
826	}
827
828	// Public methods
829	this.open = function(elem){
830		elem = elem || $(this[0]);
831		startIndex = objects.index(elem);
832		openImage(elem);
833	};
834
835	this.next = function(){
836		loadImage( 1 );
837	};
838
839	this.prev = function(){
840		loadImage( -1 );
841	};
842
843	this.close = function(){
844		close();
845	};
846
847	this.destroy = function(){
848		$( document ).off('click.'+prefix).off('keyup.'+prefix);
849		close();
850		$('.sl-overlay, .sl-wrapper').remove();
851		this.off('click');
852	};
853
854	this.refresh = function(){
855		this.destroy();
856		$(this).simpleLightbox(options);
857	};
858
859	return this;
860
861};
862})( jQuery, window, document );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.