PageSourceSearch

https://www.e-flux.com/js/cblightbox.js

js e-flux.com collected 2026-09-24 08:25:34 UTC 73,643 bytes, 2,420 lines download raw bytes

1/*
2 * CBLightbox 3.13.8 jQuery
3 * 2021-07-04
4 * Copyright Christin Bombelka
5 * https://github.com/ChristinBombelka/cblightbox
6 */
7
8(function($){
9	var caption,
10		opening,
11		closing,
12		slideing = false,
13		slides,
14		firstLoad,
15		pinching = false,
16		isDraggable = false;
17
18	$.fn.cblightbox = function(options){
19
20		function cleanDom(){
21			return $('html').width();
22		}
23
24		function is_touch_device() {
25			return (('ontouchstart' in window)  || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
26		}
27
28		if(is_touch_device()){
29			$("html").addClass("cb-lightbox-touch");
30		}else{
31			$("html").addClass("cb-lightbox-no-touch");
32		}
33
34		function getScrollbarWidth() {
35			// Creating invisible container
36			const outer = document.createElement('div');
37			outer.style.visibility = 'hidden';
38			outer.style.overflow = 'scroll'; // forcing scrollbar to appear
39			outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps
40			document.body.appendChild(outer);
41
42			// Creating inner element and placing it in the container
43			const inner = document.createElement('div');
44			outer.appendChild(inner);
45
46			// Calculating difference between container's full width and the child width
47			const scrollbarWidth = (outer.offsetWidth - inner.offsetWidth);
48
49			// Removing temporary elements from the DOM
50			outer.parentNode.removeChild(outer);
51
52			return scrollbarWidth;
53		}
54
55		if(!$(".cb-lightbox-margin").length){
56			$("<style type='text/css'>.cb-lightbox-margin{margin-right:" + getScrollbarWidth() + "px;}</style>").appendTo($("head"));
57		}
58
59		var defaults = {
60			maxHeight: 9999,
61			maxWidth: 9999,
62			margin: 40,
63			mobilemargin: 0,
64            insidearrows: false, 
65			zoom : false,
66			zoomDuration : 300,
67			zoomOffset : 0,
68            zoomControlls: false,
69            zoomMap: false,
70            zoomSteps: 3,
71			disableOnMobile: false,
72			breakpoint: 800,
73			counter: true,
74			captionPosition: 'outside', //inside, outside
75			openCloseEffect: 'fade', //fade, zoom
76			openCloseDuration: 250,
77			slideDuration: 250,
78			slideEffect: 'fade', //slide, fade
79			previewSource: false, //define preview image source on use lazyloading
80            previewimage: true,
81			dragSlide: true,
82            closeOutsideClick: true,
83			alignHorizontal: 'center', //center, left, right
84			alignVertical: 'center', //center, top, bottom
85			afterInit: $.noop,
86			afterFit: $.noop,
87			afterSlide: $.noop,
88			beforeOpen: $.noop,
89			afterOpen: $.noop,
90			beforeClose: $.noop,
91			afterClose: $.noop,
92			onResize: $.noop,
93		}
94
95		function error(container, slide){
96			$('<div class="cb-lightbox-error">Sorry, this image can\'t loaded!</div>').appendTo(slide);
97
98			slide.find('.cb-lightbox-slide-image').remove();
99			slide.removeClass('cb-lightbox-image-hide');
100
101			var $s = container.data('settings');
102
103			_animate(container, false, $s.openCloseDuration);
104			_animate(container.find('.cb-lightbox-content'), false, $s.openCloseDuration);
105
106			clearTimeout(container.data('watch'));
107			container.removeClass('cb-lightbox-is-loading');
108			container.addClass('cb-lightbox-run-opening');
109
110			setTimeout(function(){
111				container
112					.removeClass('cb-lightbox-is-loading')
113					.addClass('cb-lightbox-is-error');
114			});
115		}
116
117		//global momentum variables
118	    var speed = {},
119	    	maxSpeedX = 10,
120			maxSpeedY = 10,
121	    	timeDiff,
122	    	distance = {},
123	    	lastPoint = {},
124			currentPoint = {},
125			lastTimeMouseMoved,
126			mouseUp = true,
127			positionInterval,
128			momentTimer,
129			slowDownRatio = {},
130			slowDownRatioReverse = {},
131 			speedDecleration = {},
132 			speedDecelerationRatioAbs = {};
133
134		function calculateAnimtionOffset(axis){
135			speedDecleration[axis] = speedDecleration[axis] * (slowDownRatio[axis] + slowDownRatioReverse[axis] - slowDownRatioReverse[axis] * timeDiff / 10);
136			speedDecelerationRatioAbs[axis] = Math.abs(speed[axis] * speedDecleration[axis]);
137			distanceOffset = speed[axis] * speedDecleration[axis] * timeDiff;
138
139			return distanceOffset;
140		}
141
142		function getNewBouncePosition(maxMin, current, time, duration){
143			return (maxMin - current) * time / duration + current;
144		}
145
146	    function logMousePosition(){
147			if(mouseUp){
148				return;
149			}
150
151			//log mouse positions
152	       	positionInterval = setTimeout(function(){
153
154	         	currentT = new Date().getTime();
155	         	timeDiff = currentT - lastT;
156
157	         	distance = {
158	         		x: (currentPoint.x - lastPoint.x) / 1.5,
159	         		y: (currentPoint.y - lastPoint.y) / 1.5
160	         	};
161
162	         	lastPoint = {
163	         		x: currentPoint.x,
164	         		y: currentPoint.y
165	         	};
166
167				lastT = currentT;
168
169				logMousePosition();
170	       	}, 20);
171		}
172
173        function getImageSizes(currentImage){
174             
175            return {
176                width: currentImage.data('fullWidth') * (currentImage.data('currentPercentage') / 100),
177                height: currentImage.data('fullHeight') * (currentImage.data('currentPercentage') / 100),
178            };
179        }
180
181        function zoomMapPosition(x,y){
182            var container = $('.cb-lightbox');
183
184            if(!container.length){
185            	return;
186            }
187
188            var $s = container.data('settings');
189
190            if(!$s.zoomMap){
191                return;
192            }
193
194            var currentImage = $('.cb-lightbox-slide-current .cb-lightbox-slide-image'),
195                imageWidth = currentImage.data('fullWidth') * (currentImage.data('currentPercentage') / 100),
196                imageHeight = currentImage.data('fullHeight') * (currentImage.data('currentPercentage') / 100),
197                windowHeight = $(window).height(),
198                windowWidth = $(window).width();
199
200            //set limits
201            if(y >= 0){
202                y = 0
203            }else if(Math.abs(y) > imageHeight - windowHeight && imageHeight > windowHeight){
204                y = windowHeight - imageHeight;
205            }
206
207            if(x >= 0){
208                x = 0
209            }else if(Math.abs(x) > imageWidth - windowWidth && imageWidth > windowWidth){
210                x = windowWidth - imageWidth;
211            }
212
213            var zoomMapContainer = $('.cb-lightbox__zoomMap'),
214                zoomMapWidthRatio = windowWidth / imageWidth,
215                zoomMapHeightRatio = windowHeight / imageHeight,
216                zoomMapTop = (Math.max(Math.abs(y), 1) / imageHeight),
217                zoomMapLeft = (Math.max(Math.abs(x), 1) / imageWidth);
218
219            var zoomMapWidth = zoomMapWidthRatio * zoomMapContainer.width();
220            if(zoomMapWidth >= zoomMapContainer.width()){
221                zoomMapWidth = zoomMapContainer.width();
222            }
223
224            var zoomMapHeight = zoomMapHeightRatio * zoomMapContainer.height();
225            if(zoomMapHeight >= zoomMapContainer.height()){
226                zoomMapHeight = zoomMapContainer.height();
227            }
228
229            zoomMapContainer.find('.cb-lightbox__zoomMap-handle').css({
230                'width': zoomMapWidth,
231                'height': zoomMapHeight,
232                'top': zoomMapTop * zoomMapContainer.height(),
233                'left': zoomMapLeft * zoomMapContainer.width()
234            });
235        }
236
237        function getZoomDistance(f1, f2) {
238            var dx = f1.clientX - f2.clientX;
239            var dy = f1.clientY - f2.clientY;
240            return Math.sqrt(dx * dx + dy * dy);
241        }
242
243         function checkZoomLimit(newSize, direction, value){
244        	//check zoom limits
245
246        	var windowSize = $(window).width();
247
248        	if(direction == 'height'){
249        		windowSize = $(window).height();
250        	}
251
252        	if(newSize <= windowSize){
253                value = (windowSize - newSize) / 2;
254            }else if(value > 0 && newSize > windowSize){
255                value = 0;
256            }else if(value < windowSize - newSize){
257                value = windowSize - newSize;
258            }
259
260            return value;
261        }
262
263        function getLastTransform(slideImage){
264    		var lastOffset = slideImage.data('lastTransform'),
265    			x,
266    			y;
267
268    		if(lastOffset){
269    			x = lastOffset.x ? lastOffset.x : 0;
270    			y = lastOffset.y ? lastOffset.y : 0;
271    		}else{
272				x = 0;
273				y = 0;
274    		}
275    		
276    		return {
277    			x: x,
278    			y: y
279    		};
280    	}
281
282		function initMoveMoment(slideImage){
283			var $s = $('.cb-lightbox').data('settings'),
284				minX = $s.zoomOffset[3],
285				maxX = $(window).width() - slideImage.width() -  $s.zoomOffset[1],
286				minY = $s.zoomOffset[0],
287				maxY = $(window).height() - slideImage.height() -  $s.zoomOffset[2],
288				startTimeX = false,
289	 			startTimeY = false,
290	 			completeX = false,
291	 			completeY = false,
292	 			setCurrentPointX = false,
293	 			setCurrentPointY = false;
294
295            if(pinching == true){
296                clearTimeout(momentTimer);
297                return;
298            }
299
300 			speedDecleration = {
301 				x: 1,
302 				y: 1
303 			};
304
305 			//stow down
306 			slowDownRatio = {
307 				x: 0.95,
308 				y: 0.95,
309 			};
310
311 			slowDownRatioReverse = {
312				x: 1 - slowDownRatio.x,
313				y: 1 - slowDownRatio.y
314			};
315
316			// Speed in px/ms velocity
317			speed.x = Math.max(Math.min(distance.x / timeDiff, maxSpeedX), -maxSpeedX);
318			speed.y = Math.max(Math.min(distance.y / timeDiff, maxSpeedY), -maxSpeedY);
319
320	 		//min distence to move object
321	 		if(Math.abs(distance.x) > 1 || Math.abs(distance.y) > 1){
322
323				function moveMoment(){
324					momentTimer = setTimeout(function(){
325
326						if(startTimeX === false){
327							speedX = calculateAnimtionOffset('x');
328						}
329
330						if(startTimeY === false){
331							speedY = calculateAnimtionOffset('y');
332						}
333
334						if((Math.abs(speedX) > 0.1 || (currentPoint.x > minX || currentPoint.x < maxX)) && getImageSizes(slideImage).width > $(window).width()){
335							//In bouncing area left/right
336							if(currentPoint.x > minX || currentPoint.x < maxX){
337								if(Math.abs(speedX) < 0.08){
338									if(startTimeX === false){
339										startTimeX = new Date().getTime();
340									}
341
342									tX = new Date().getTime() - startTimeX;
343
344									if(tX >= 300){
345										//set to end position
346										if(currentPoint.x > minX){
347											setCurrentPointX = minX;
348										}else{
349											setCurrentPointX = maxX;
350										}
351
352										speedX = 0;
353										completeX = true;
354
355									}else{
356										if(currentPoint.x > minX){
357											setCurrentPointX = getNewBouncePosition(minX, currentPoint.x, tX, 300);
358										}else{
359											setCurrentPointX = getNewBouncePosition(maxX, currentPoint.x, tX, 300);
360										}
361									}
362								}
363
364								slowDownRatio.x = 0.7;
365							}
366
367						}else{
368							completeX = true;
369						}
370
371						if(!startTimeX){
372							setCurrentPointX = currentPoint.x + speedX;
373						}
374
375						if((Math.abs(speedY) > 0.1 || (currentPoint.y > minY || currentPoint.y < maxY)) && getImageSizes(slideImage).height > $(window).height()){
376							//In bouncing area top/bottom
377							if(currentPoint.y > minY || currentPoint.y < maxY){
378
379								if(Math.abs(speedY) < 0.08){
380									if(startTimeY === false){
381										startTimeY = new Date().getTime();
382									}
383
384									tY = new Date().getTime() - startTimeY;
385
386									if(tY >= 300){
387										//set to end position
388										if(currentPoint.y > minY){
389											setCurrentPointY = minY;
390										}else{
391											setCurrentPointY = maxY;
392										}
393
394										speedY = 0;
395										completeY = true;
396
397									}else{
398
399										if(currentPoint.y > minY){
400											setCurrentPointY = getNewBouncePosition(minY, currentPoint.y, tY, 300);
401										}else{
402											setCurrentPointY = getNewBouncePosition(maxY, currentPoint.y, tY, 300);
403										}
404									}
405								}
406
407								slowDownRatio.y = 0.7;
408							}
409						}else{
410							completeY = true;
411						}
412
413						if(!startTimeY){
414							setCurrentPointY = currentPoint.y + speedY;
415						}
416
417						//set points
418						currentPoint.x = setCurrentPointX ? setCurrentPointX : currentPoint.x;
419						currentPoint.y = setCurrentPointY ? setCurrentPointY : currentPoint.y;
420
421						//move to points
422						setTranslate(slideImage, {
423							left: currentPoint.x,
424							top: currentPoint.y
425						});
426
427                        zoomMapPosition(currentPoint.x, currentPoint.y);
428
429						if(completeX && completeY){
430							clearTimeout(momentTimer);
431							return;
432						}
433
434						moveMoment();
435
436					}, 10);
437				}
438
439				moveMoment();
440
441		    }else{
442		    	reposition();
443		    }
444		}
445
446		function setTranslate(el, values){
447			var str = '',
448				css = {};
449
450			if(!el.length){
451				return;
452			}
453
454			if(values.top !== undefined || values.left !== undefined){
455				str = (values.left === undefined ? el.position().left : values.left) + 'px, ' + (values.top === undefined ? el.position().top : values.top) + 'px';
456				str = 'translate(' + str + ')';
457
458				el.data('lastTransform', {x: values.left, y: values.top});
459			}
460
461			if(values.scaleX && values.scaleY){
462				str = (str.length ? str + ' ' : '') + 'scale(' + values.scaleX + ', ' + values.scaleY + ')';
463			}
464
465			if (str.length) {
466                css.transform = str;
467            }
468
469            if(values.width !== undefined){
470            	css.width = values.width;
471            }
472
473            if(values.height !== undefined){
474            	css.height = values.height;
475            }
476
477            if(values.opacity !== undefined){
478            	css.opacity = values.opacity;
479            }
480
481           	return el.css(css);
482		}
483
484		function _animateDurationSet(el, duration){
485			el.css('transition-duration', duration + 'ms');
486		}
487
488		function _animateDurationRemove(el){
489			el.css('transition-duration', '');
490		}
491
492		function _animateEnd(el, to){
493			_animateDurationRemove(el);
494
495			if(el.closest('.cb-lightbox').hasClass('cb-lightbox-init-closing')){
496				return;
497			}
498
499			if(to.scaleX !== undefined && to.scaleY !== undefined){
500				var currentSlide = $('.cb-lightbox-slide-current').find(".cb-lightbox-slide-image");
501
502				if(to.toWidth && to.toHeight){
503					to.width = to.toWidth;
504					to.height = to.toHeight
505				}else if($('.cb-lightbox-is-zoomed').length){
506                    to.width = getImageSizes(el).width;
507					to.height = getImageSizes(el).height;
508				}else{
509					to.width = currentSlide.data('fitWidth');
510					to.height = currentSlide.data('fitHeight');
511				}
512
513				to.scaleX = 1;
514				to.scaleY = 1;
515
516				setTranslate(el, to);
517			}
518		}
519
520		function _animate(el, to, duration){
521			_animateDurationSet(el, duration)
522
523			setTranslate(el, to);
524
525			clearTimeout(el.data('timer'));
526
527			el.data('timer', setTimeout(function(){
528				_animateEnd(el, to);
529			}, duration + 20));
530		}
531
532		function initDraggable(slideImage, userX, userY){
533	    	if($(".cb-lightbox").hasClass("cb-lightbox-is-zoomed") || $('.cb-lightbox').hasClass('cb-lightbox-is-loading')){
534	    		return;
535	    	}
536
537	    	if(closing){
538	    		return;
539	    	}
540
541	    	$('.cb-lightbox').addClass('cb-lightbox-is-zoomed cb-lightbox-run-zoom');
542
543	        var $s = $('.cb-lightbox').data('settings'),
544	        	slide = slideImage.closest('.cb-lightbox-slide'),
545	        	clickX = userX / slideImage.width(),
546				clickY = userY / slideImage.height();
547
548			slideImage.data('currentZoomStep', $s.zoomSteps);
549
550			if(slideImage.data('fullWidth') > $(window).width()){
551				var positionX = Math.max(slideImage.data('fullWidth') * clickX - ($(window).width() / 2) - $s.zoomOffset[3], -$s.zoomOffset[3]);
552					positionX = -Math.min(slideImage.data('fullWidth') - $(window).width() + $s.zoomOffset[1], positionX);
553			}else{
554				var positionX = ($(window).width() - slideImage.data('fullWidth')) / 2;
555			}
556
557			if(slideImage.data('fullHeight') > $(window).height()){
558				var positionY = Math.max(slideImage.data('fullHeight') * clickY - ($(window).height() / 2) - $s.zoomOffset[0], -$s.zoomOffset[0]),
559					positionY = -Math.min(slideImage.data('fullHeight') - $(window).height() + $s.zoomOffset[2], positionY);
560			}else{
561				var positionY = ($(window).height() - slideImage.data('fullHeight')) / 2;
562			}
563
564			scaleWidth = slideImage.data('fullWidth') / slideImage.width();
565	        scaleHeight = slideImage.data('fullHeight') / slideImage.height();
566
567			_animate(slideImage, {
568				top: positionY,
569				left: positionX,
570				scaleX: scaleWidth,
571				scaleY: scaleHeight
572			}, $s.zoomDuration);
573
574			setTimeout(function(){
575				isDraggable = true;
576
577                $('.cb-lightbox').removeClass('cb-lightbox-run-zoom');
578
579			}, $s.zoomDuration);
580
581            slideImage.data('currentPercentage', 100);
582            zoomMapPosition(positionX, positionY);
583	    }
584
585	    function detroyDraggable(slideImage, disableAnimation){
586	    	var container = $(".cb-lightbox");
587
588	    	if(!container.length || !slideImage.length){
589	    		return;
590	    	}
591
592			var $s = slideImage.closest('.cb-lightbox').data('settings'),
593				slide = slideImage.closest('.cb-lightbox-slide'),
594				duration = $s.zoomDuration;
595
596			if(!container.hasClass("cb-lightbox-is-zoomed")){
597				return;
598			}
599
600	    	isDraggable = false;
601
602            container.addClass('cb-lightbox-run-zoom');
603            slideImage.data('currentZoomStep', 0);
604
605	    	var	scaleWidth = slideImage.data('fitWidth') / slideImage.width(),
606	       		scaleHeight = slideImage.data('fitHeight') / slideImage.height();
607
608	    	if(typeof disableAnimation !== 'undefined'){
609	    		duration = 0;
610	    		disableAnimation = false;
611	    	}
612
613    		_animate(slideImage, {
614    			toWidth: slideImage.data('fitWidth'),
615				toHeight: slideImage.data('fitHeight'),
616				top: slideImage.data('fitTop'),
617				left: slideImage.data('fitLeft'),
618				scaleX: scaleWidth,
619				scaleY: scaleHeight
620			}, duration);
621
622    		setTimeout(function(){
623    			container.removeClass('cb-lightbox-is-zoomed cb-lightbox-run-zoom');
624    		}, duration + 30);
625
626            slideImage.data('currentPercentage', slideImage.data('fitPercentage'));
627
628            zoomMapPosition(slideImage.data('fitLeft'), slideImage.data('fitTop'));
629	    }
630
631	    function getImageFit(slideImage){
632			var container = $('.cb-lightbox'),
633				$s = container.data('settings'),
634				type = slideImage.data('type');
635
636			if(type == 'image'){
637				if(typeof slideImage != 'undefined'){
638					imgWidth = slideImage.data('fullWidth');
639					imgHeight = slideImage.data('fullHeight');
640				}
641				else{
642					imgWidth = $(".cb-lightbox-image").width();
643					imgHeight = $(".cb-lightbox-image").height();
644				}
645			}else{
646
647				if(slideImage.data('fullHeight') && slideImage.data('fullWidth')){
648					imgHeight = container.height();
649					imgWidth = imgHeight / slideImage.data("fullHeight") * slideImage.data("fullWidth");
650				}else{
651					//Default 16/9
652					imgHeight = container.height();
653					imgWidth = imgHeight / 9 * 16;
654				}
655			}
656
657			var wrapperHeight = container.height() - ($s.margin[0] + $s.margin[2]),
658				wrapperWidth = container.width() - ($s.margin[1] + $s.margin[3]),
659				windowHeight = window.innerHeight ? window.innerHeight : $(window).height();
660
661			var captionHeight = 0;
662			if($(".cb-lightbox-info").length){
663				captionHeight = $(".cb-lightbox-info").outerHeight();
664			}
665
666			if(wrapperHeight - captionHeight < imgHeight || wrapperWidth < imgWidth ) {
667				var minRatio = Math.min(1, wrapperWidth / imgWidth, (wrapperHeight - captionHeight) / imgHeight);
668
669				newImgWidth = Math.floor(minRatio * imgWidth);
670				newImgHeight = Math.floor(minRatio * imgHeight);
671			}
672			else{
673				newImgWidth = imgWidth;
674				newImgHeight = imgHeight;
675			}
676
677			if($s.alignVertical == 'top'){
678				positionTop = $s.margin[0];
679			}else if($s.alignVertical == 'bottom'){
680				positionTop = windowHeight - newImgHeight - $s.margin[2];
681			}else{
682
683				var marginDiff = 1,
684					divider = 2;
685
686				if($s.margin[0] > 0 && $s.margin[2] > 0){
687					marginDiff = $s.margin[0] / $s.margin[2];
688					divider = (divider + (divider / marginDiff)) / 2;
689				}
690
691				var verticalCenter = (windowHeight - newImgHeight - captionHeight) / divider;
692				positionTop = Math.max(verticalCenter, $s.margin[0]);
693	
694			}
695
696			if($s.alignHorizontal == 'left'){
697				positionLeft = $s.margin[3];
698			}else if($s.alignHorizontal == 'right'){
699				positionLeft = container.width() - newImgWidth - $s.margin[1];
700			}else{
701				positionLeft = (container.width() - newImgWidth) / 2;
702			}
703
704			var	scaleWidth = newImgWidth / slideImage.data('holderWidth'),
705   				scaleHeight = newImgHeight / slideImage.data('holderHeight');
706
707			slideImage.data({
708	 			'fitHeight': newImgHeight,
709	 			'fitWidth': newImgWidth,
710	 			'fitLeft': positionLeft,
711	 			'fitTop': positionTop,
712                'fitPercentage': minRatio ? (minRatio * 100) : false,
713                'currentPercentage': minRatio ? (minRatio * 100) : false
714	 		});
715
716			if((imgWidth > $(window).width() || imgHeight > windowHeight) && $s.zoom){
717				slideImage.addClass('cb-lightbox-slide-draggable');
718			}else{
719				slideImage.removeClass('cb-lightbox-slide-draggable');
720			}
721
722			if ($.isFunction($s.afterFit)) {
723				$s.afterFit.call(this, container, slideImage.closest('.cb-lightbox-slide'));
724			}
725
726	 		return {
727	 			width: newImgWidth,
728	 			height: newImgHeight,
729	 			top: positionTop,
730	 			left: positionLeft,
731	 			scaleX: scaleWidth,
732	 			scaleY: scaleHeight
733	 		};
734		};
735
736		function reposition(){
737	    	//reset dragging position
738		    var slide = $('.cb-lightbox-slide.cb-lightbox-slide-current'),
739				$s = slide.closest('.cb-lightbox').data('settings'),
740		    	slideImage = slide.find('.cb-lightbox-slide-image'),
741		    	lastoffset = slideImage.data('lastTransform'),
742		    	windowWidth = $(window).width(),
743		    	windowHeight = window.innerHeight ? window.innerHeight : $(window).height(),
744		    	imageWidth = getImageSizes(slideImage).width,
745		    	imageHeight = getImageSizes(slideImage).height;
746
747		    if(!lastoffset){
748		    	return;
749		    }
750
751		    if(lastoffset.x > $s.zoomOffset[3] && imageWidth > windowWidth){
752		    	moveX = $s.zoomOffset[3];
753		    }else if(Math.abs(lastoffset.x) - $s.zoomOffset[1] > imageWidth - windowWidth && imageWidth > windowWidth){
754		    	moveX = windowWidth - imageWidth - $s.zoomOffset[1];
755		    }else{
756		    	moveX = lastoffset.x;
757		    }
758
759		    if(lastoffset.y > $s.zoomOffset[0] && imageHeight > windowHeight){
760		    	moveY = $s.zoomOffset[0];
761		    }else if(Math.abs(lastoffset.y) - $s.zoomOffset[2] > imageHeight - windowHeight && imageHeight > windowHeight){
762		    	moveY = windowHeight - imageHeight - $s.zoomOffset[2];
763		    }
764		    else{
765		    	moveY = lastoffset.y;
766		    }
767
768		    if(lastoffset.x != moveX || lastoffset.y != moveY){
769		    	_animate(slideImage, {
770		    		top: moveY,
771		    		left: moveX,
772		    	}, 250);
773		    }
774	    }
775
776	    function captionInsidePosition(caption, slideImage){
777	    	var $s = slideImage.closest('.cb-lightbox').data('settings'),
778	    		positionBottom = window.innerHeight - slideImage.data('fitHeight');
779
780	    	if($s.alignVertical == 'top'){
781				positionBottom = positionBottom - $s.margin[0];
782			}else if($s.alignVertical == 'bottom'){
783				positionBottom = $s.margin[2];
784			}else{
785				positionBottom = positionBottom - slideImage.data('fitTop');
786			}
787
788	    	caption.css({
789				bottom: positionBottom,
790				left: slideImage.data('fitLeft'),
791				width: slideImage.data('fitWidth'),
792			});
793	    }
794
795	    function updateCaption(item, slide, $s){
796	    	var caption = item.data("caption"),
797				captionTpl = $("<div class='cb-lightbox-caption'>"+ caption +"</div>");
798
799			if($s.captionPosition == 'inside'){
800
801				slide.addClass('cb-lightbox-slide-with-caption');
802
803				if(!slide){
804					var slide = $('.cb-lightbox-slide-current');
805				}
806
807				if(slide.find('.cb-lightbox-caption').length){
808					return;
809				}
810
811				setTimeout(function(){
812					captionInsidePosition(captionTpl, slide.find('.cb-lightbox-slide-image'));
813				});
814
815				var addTo = slide;
816
817			}else{
818				$(".cb-lightbox-caption").remove();
819
820				var addTo = $(".cb-lightbox-info");
821			}
822
823			if(caption){
824				var slideCaption = captionTpl.appendTo(addTo);
825			}
826		}
827
828		function watchLoading(slide){
829			if(slide.length){
830
831				if(slide.hasClass('cb-lightbox-slide-complete')){
832					$('.cb-lightbox').removeClass('cb-lightbox-is-loading');
833
834					clearTimeout($('.cb-lightbox').data('watch'));
835					return;
836
837				}else{
838					$('.cb-lightbox').addClass('cb-lightbox-is-loading');
839				}
840
841				$('.cb-lightbox').data('watch', setTimeout(function(){
842					watchLoading(slide);
843				}, 100));
844			}
845		}
846
847		function getImageSize(el, img, slide, callback) {
848		    var $img = $(img);
849
850		    if(el.data('width') && el.data('height')){
851		    	callback.apply(this, [el.data('width'), el.data('height'), slide]);
852		    }else{
853		    	var wait = setInterval(function() {
854			        var w = $img[0].naturalWidth,
855			            h = $img[0].naturalHeight;
856			        if (w && h) {
857			            clearInterval(wait);
858			            callback.apply(this, [w, h, slide]);
859			        }
860			    }, 100);
861			}
862		}
863
864		function setImageFit(slideImage){
865			var values = getImageFit(slideImage);
866
867			setTranslate(slideImage, {
868				width: values.width,
869				height: values.height,
870			});
871		}
872
873		function setImage(slide, source, item, p){
874			var elementPlaceholder = slide.find('.cb-lightbox-image-placeholder'),
875				container = $('.cb-lightbox'),
876				slideImage = slide.find('.cb-lightbox-slide-image'),
877				$s = container.data('settings'),
878				loadingTimeout,
879				loadingImage = true;
880
881			if(typeof slides === "undefined"){
882				cachedSlide = false;
883			}else{
884				cachedSlide = slides[slideImage.data('index')];
885			}
886
887			if(cachedSlide.image && cachedSlide.status == 'complete'){
888				var $img = cachedSlide.image.clone().appendTo(slideImage);
889
890				if($img[0].complete){
891					loadingImage = false;
892				}
893			}
894
895			if(loadingImage){
896				if(typeof $img !== "undefined" && $img.length){
897					$img.remove();
898				}
899
900				var $img = $('<img />');
901
902				$img.addClass('cb-lightbox-image')
903					.attr('src', source)
904					.appendTo(slideImage);
905
906				$img.one('error', function(){
907
908					clearTimeout(loadingTimeout);
909
910					$img.remove();
911					elementPlaceholder.remove();
912					error(container, slide);
913
914				}).one('load', function(e){
915					imageHeight = $(this).data('height') || this.naturalHeight;
916
917					slide.removeClass('cb-lightbox-slide-hide');
918
919					if(firstLoad){
920						initPreload(container);
921					}
922
923					setTimeout(function(){
924
925						elementPlaceholder.hide();
926
927						slide
928							.removeClass('cb-lightbox-image-hide')
929							.addClass('cb-lightbox-slide-complete');
930
931						if(slides[slideImage.data('index')]){
932							slides[slideImage.data('index')].image = $img;
933							slides[slideImage.data('index')].status = 'complete';
934						}
935
936					}, Math.min( 300, Math.max( 1000, imageHeight / 1600 )));
937				});
938			}
939
940			getImageSize(item, $img, slideImage,  function(width, height, slideImage){
941				slideImage.data({
942					'fullWidth': width,
943					'fullHeight': height,
944				});
945
946				setImageFit(slideImage);
947
948				var values = getImageFit(slideImage);
949				setTranslate(slideImage, {
950					top: values.top,
951					left: values.left,
952				});
953			});
954
955			if(loadingImage == false && ($img[0].complete || $img[0].readyState == 'complete') && $img[0].naturalWi
955dth && $img[0].naturalHeight){
956				elementPlaceholder.hide();
957
958				slide
959					.removeClass('cb-lightbox-slide-hide cb-lightbox-image-hide')
960					.addClass('cb-lightbox-slide-complete');
961
962				if(firstLoad){
963					initPreload(container);
964				}
965			}
966		}
967
968		function setSlide(item, i, p){
969			if(typeof i !== "undefined"){
970				$(".counter-current").text(i + 1);
971			}
972
973			var container = $('.cb-lightbox'),
974				$s = container.data('settings'),
975				source = item.attr('href'),
976				cachedSlide = slides[i];
977
978			if(!cachedSlide){
979				cacheSlides(item, i, p);
980				cachedSlide = slides[i];
981			}
982
983			container.removeClass('cb-lightbox-is-error');
984
985			var slide = $('<div class="cb-lightbox-slide cb-lightbox-slide-' + p + ' cb-lightbox-image-hide"></div>'),
986				wrapImage = $('<div class="cb-lightbox-slide-image"></div>');
987
988			wrapImage.appendTo(slide);
989
990			if(p == 'previews'){
991				slide.prependTo($('.cb-lightbox-slides'));
992			}else{
993				slide.appendTo($('.cb-lightbox-slides'));
994			}
995
996			if(p == 'current'){
997				clearTimeout($('.cb-lightbox').data('watch'));
998				watchLoading(slide);
999			}
1000
1001            if(container.data('grouplength') > 1 && $s.insidearrows){
1002                var arrows = $('<div class="cb-lightbox-arrow-prev cb-lightbox-arrow cb-lightbox-arrow--inside"><span></span></div><div class="cb-lightbox-arrow-next cb-lightbox-arrow cb-lightbox-arrow--inside"><span></span></div>');
1003                arrows.appendTo(wrapImage);
1004            }
1005
1006			wrapImage.data({
1007				'type': cachedSlide.type,
1008				'index': i,
1009				'holderWidth': item.find('img').width(),
1010				'holderHeight': item.find('img').height(),
1011                'currentZoomStep': 0,
1012			});
1013
1014			$('.cb-lightbox-error').remove();
1015			$('.cb-lightbox-content').removeClass('cb-lightbox-is-error');
1016
1017			if(cachedSlide.type == "image"){
1018
1019                if($s.previewimage){
1020                    var elementPlaceholder = cachedSlide.placeholder.clone().appendTo(wrapImage);
1021
1022                    elementPlaceholder.show();
1023
1024                    if((elementPlaceholder[0].complete || elementPlaceholder[0].readyState == 'complete') && elementPlaceholder[0].naturalWidth && elementPlaceholder[0].naturalHeight ) {
1025                        slide.removeClass('cb-lightbox-slide-hide');
1026                        setImage(slide, source, item, p);
1027                    }else{
1028
1029                        elementPlaceholder.one('error', function(){
1030                            elementPlaceholder.remove();
1031                        }).one('load', function(){
1032                            slide.removeClass('cb-lightbox-slide-hide');
1033
1034                            setImage(slide, source, item, p);
1035
1036                            slides[wrapImage.data('index')].placeholder = elementPlaceholder;
1037                        });
1038                    }
1039
1040                    if(p == 'current'){
1041                        container.find('.cb-lightbox__zoomMap-image').append('<img src="'+elementPlaceholder.attr('src')+'">');
1042                    }
1043                }else{
1044                    slide.removeClass('cb-lightbox-slide-hide');
1045                    setImage(slide, source, item, p);
1046                }
1047				
1048
1049			}else if(cachedSlide.type == "iframe"){
1050
1051				var iframe = cachedSlide.iframe.clone().appendTo(wrapImage);
1052
1053				if(p == 'current'){
1054					container.addClass('cb-lightbox-is-iframe');
1055				}
1056
1057				wrapImage
1058					.data({
1059						'fullWidth': item.data('width') ? item.data('width') : 16,
1060						'fullHeight': item.data('height') ? item.data('height') : 9,
1061					});
1062
1063				iframe.on("load", function(){
1064					slide
1065						.removeClass('cb-lightbox-slide-hide cb-lightbox-image-hide')
1066						.addClass('cb-lightbox-slide-complete');
1067				});
1068			}
1069
1070			return slide;
1071		}
1072
1073	    function slideTo(direction, effect){
1074	    	if(typeof effect === "undefined"){
1075	    		effect = false;
1076	    	}
1077
1078			$('.cb-lightbox-slide').removeClass('cb-lightbox-is-sliding');
1079
1080	    	firstLoad = false;
1081
1082		   	var container = $(".cb-lightbox"),
1083				$s = container.data('settings'),
1084	    		group = container.data('group'),
1085				items = $('a[data-group="'+ group +'"]'),
1086				oldCurrent = $('.cb-lightbox-slide.cb-lightbox-slide-current');
1087
1088			if(container.hasClass('cb-lightbox-is-zoomed') || slideing || items.length <= 1){
1089				return;
1090			}
1091
1092			slideing = true;
1093
1094			if(direction == 'previews'){
1095				_this_index = _this_index - 1;
1096
1097				if(_this_index < 0){
1098					_this = items.length - 1;
1099					_this_index = _this;
1100				}
1101
1102				var newCurrent = oldCurrent.prev();
1103
1104				//cache prev slide
1105				var _slideIndex = _this_index - 1;
1106
1107				if(_slideIndex < 0){
1108					_this = items.length - 1;
1109					_slideIndex = _this;
1110				}
1111
1112				//change current slide
1113				var oldCurrentDirection = 'next';
1114
1115			}else if(direction == 'next'){
1116				_this_index = _this_index + 1;
1117
1118				if(_this_index > items.length - 1){
1119					_this_index = 0;
1120				}
1121
1122				var newCurrent = oldCurrent.next();
1123
1124				//cache next slide
1125				var _slideIndex = _this_index + 1;
1126
1127				if(_slideIndex > items.length - 1){
1128					_slideIndex = 0;
1129				}
1130
1131				//change current slide
1132				var oldCurrentDirection = 'previews';
1133			}
1134
1135			container.find('.cb-counter-current').text(_this_index + 1);
1136
1137			$('.cb-lightbox-is-selected').removeClass('cb-lightbox-is-selected');
1138			items.eq(_this_index).addClass('cb-lightbox-is-selected');
1139
1140			//remove previews slide
1141			$('.cb-lightbox-slide.cb-lightbox-slide-' + oldCurrentDirection).remove();
1142
1143			oldCurrent
1144				.removeClass('cb-lightbox-slide-current')
1145				.addClass('cb-lightbox-slide-' + oldCurrentDirection);
1146
1147			if($s.slideEffect == 'slide' || effect == 'slide'){
1148
1149				if(direction == 'previews'){
1150					var slideOut = $(window).width();
1151				}else{
1152					var slideOut = -$(window).width();
1153				}
1154
1155				_animate(oldCurrent, {
1156					left: slideOut,
1157					opacity: 0,
1158				}, $s.slideDuration);
1159			}else{
1160				_animate(oldCurrent, {
1161					opacity: 0,
1162				}, $s.slideDuration);
1163			}
1164
1165			//check new Current exist
1166			if(!newCurrent.length){
1167				newCurrent = setSlide(items.eq(_this_index), _this_index, 'current');
1168			}
1169
1170			cachedSlide = slides[_this_index];
1171
1172			newCurrent
1173				.removeClass('cb-lightbox-slide-previews cb-lightbox-slide-next')
1174				.addClass('cb-lightbox-slide-current');
1175
1176			//set new caption befor calc slide height
1177			updateCaption(items.eq(_this_index), newCurrent, $s);
1178
1179			var newCurrentImage = newCurrent.find('.cb-lightbox-slide-image');
1180
1181			values = getImageFit(newCurrentImage);
1182
1183			setTranslate(newCurrentImage, {
1184				width: values.width,
1185				height: values.height,
1186				left: values.left,
1187				top: values.top,
1188			});
1189
1190			//set current slide start position
1191			if($s.slideEffect == 'slide' || effect == 'slide'){
1192				if(direction == 'previews'){
1193					var slideIn = -$(window).width();
1194				}else{
1195					var slideIn = $(window).width();
1196				}
1197
1198				setTranslate(newCurrent, {
1199					left: slideIn,
1200					opacity: 0,
1201				});
1202			}else{
1203				setTranslate(newCurrent, {
1204					left: 0,
1205					opacity: 0,
1206				});
1207			}
1208
1209			clearTimeout($('.cb-lightbox').data('watch'));
1210			watchLoading(newCurrent);
1211
1212			if($s.slideEffect == 'slide' || effect == 'slide'){
1213				setTimeout(function(){
1214					_animate(newCurrent, {
1215						top: 0,
1216						left: 0,
1217						opacity: 1,
1218					},  $s.slideDuration);
1219				});
1220			}else{
1221				setTimeout(function(){
1222					_animate(newCurrent, {
1223						opacity: 1,
1224					},  $s.slideDuration);
1225				});
1226			}
1227
1228			setTimeout(function(){
1229				if ($.isFunction($s.afterSlide)) {
1230			 	   $s.afterSlide.call(this, container, newCurrent);
1231				}
1232			}, $s.slideDuration + 10);
1233
1234			setTimeout(function(){
1235				slideing = false;
1236			}, 200);
1237
1238			if(container.find('.cb-lightbox__zoomMap-image').length){
1239				var previewElement = items.eq(_this_index);
1240
1241				if($s.previewSource){
1242					if(previewElement.attr($s.previewSource)){
1243	                    placeholderImage = previewElement.attr($s.previewSource);
1244	                }else if(previewElement.find('img')){
1245	                    placeholderImage = previewElement.find('img').attr( $s.previewSource );
1246	                }
1247	            }else{
1248	            	placeholderImage = previewElement.find('img').attr('src');
1249	            }
1250
1251                container.find('.cb-lightbox__zoomMap-image')
1252                	.empty()
1253                	.append('<img src="' + placeholderImage + '">');
1254
1255                setTimeout(function(){
1256                	zoomMapPosition(0, 0);
1257                }, 10);
1258            }
1259
1260			//set new previews/next slide
1261			setSlide(items.eq(_slideIndex), _slideIndex, direction);
1262	    }
1263
1264	    function initPreload(container){
1265	    	if(!firstLoad){
1266	    		return;
1267	    	}
1268
1269    		var group = container.data('group'),
1270				items = $('a[data-group="'+ group +'"]');
1271
1272			if(items.length > 1){
1273				//cache prev slide
1274				var _slideIndex = _this_index - 1;
1275
1276				if(_slideIndex < 0){
1277					_this = items.length - 1;
1278					_slideIndex = _this;
1279				}
1280
1281				var prevItem = items.eq(_slideIndex);
1282				var preSlide = setSlide(prevItem, _slideIndex, 'previews');
1283
1284				//cache next slide
1285				var _slideIndex = _this_index + 1;
1286
1287				if(_slideIndex > items.length - 1){
1288					_slideIndex = 0;
1289				}
1290
1291				var nextItem = items.eq(_slideIndex);
1292				var postSlide = setSlide(nextItem, _slideIndex, 'next');
1293			}
1294
1295			firstLoad = false;
1296	    }
1297
1298	    function getType(source){
1299	    /*	if(source.match(/\.(jpg|jpeg|png|gif)/)) {
1300                type = 'image';
1301            }else if(source){
1302            	type = 'iframe';
1303            }else{
1304            	type = 'error';
1305            }*/
1306			type = 'image';
1307            return type;
1308	    }
1309
1310		function cacheSlides(item, i, p){
1311			var container = $('.cb-lightbox'),
1312				$s = container.data('settings');
1313
1314			if(!slides[i]){
1315				var source = item.attr('href'),
1316					placeholder = false,
1317					iframe = false,
1318					image = false,
1319					type = false,
1320					status = 'load';
1321
1322				type = getType(source);
1323
1324				if(type == "image"){
1325
1326                    if($s.previewimage){
1327                        previewImage = item.find('img');
1328
1329                        if(previewImage.length && previewImage.attr('src') && previewImage.attr('src').substr(0, 21) != 'data:image/png;base64'){
1330                            placeholderImage = item.find('img').attr('src');
1331                        }else if($s.previewSource){
1332
1333                            if(item.attr($s.previewSource)){
1334                                placeholderImage = item.attr($s.previewSource);
1335                            }else if(item.find('img')){
1336                                placeholderImage = item.find('img').attr( $s.previewSource );
1337                            }
1338                            
1339                        }else{
1340                            placeholderImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
1341                        }
1342
1343                        placeholder = $('<img />')
1344                            .addClass('cb-lightbox-image-placeholder')
1345                            .attr('src', placeholderImage);
1346                    }
1347
1348					image = $('<img/>')
1349						.addClass('cb-lightbox-image')
1350						.attr('src', source);
1351
1352					setTimeout(function(){
1353						if(image[0].complete){
1354							status = 'complete';
1355						}
1356					});
1357
1358				}else if(type == "iframe"){
1359					var iframe = $('<iframe src="" class="cb-lightbox-image cb-lightbox-iframe" allow="autoplay, fullscreen" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>');
1360
1361					iframe.attr("src", source);
1362				}
1363
1364				slides[i] = {
1365					index: i,
1366					type: type,
1367					placeholder: placeholder,
1368					image: image,
1369					status: status,
1370					iframe: iframe,
1371				};
1372			}
1373		}
1374
1375        function calcZoomSize(item, customStep){
1376            var $s = item.closest('.cb-lightbox').data('settings'),
1377                zoomStep = customStep ? customStep : item.data('currentZoomStep'),
1378                fitScale = item.data('fitPercentage'),
1379                a = 2 ** zoomStep;
1380
1381            if(zoomStep == 0){
1382            	a = 0
1383            }
1384
1385            return fitScale + a * (100 - fitScale) / 2 ** $s.zoomSteps;
1386        }
1387
1388		function open(item, i, $s){
1389			var source = item.attr('href'),
1390				slide = setSlide(item, i, 'current'),
1391				slideImage = slide.find('.cb-lightbox-slide-image'),
1392				container = $('.cb-lightbox'),
1393				cachedSlide = slides[i];
1394
1395			container.addClass('cb-lightbox-init-transitions');
1396
1397			setTranslate(slide, {
1398				top: 0,
1399				left: 0,
1400			});
1401
1402			setTranslate(slideImage, {
1403				opacity: 0,
1404			});
1405
1406			_animateDurationSet(container, $s.openCloseDuration);
1407			_animateDurationSet(container.find('.cb-lightbox-content'), $s.openCloseDuration);
1408
1409			if(cachedSlide.type == 'error'){
1410				error(container, slide);
1411			}if (slideImage.data('fullHeight') === undefined) {
1412				//wait for imagesize;
1413				var wait = setInterval(function() {
1414					if(typeof slide === "undefined"){
1415						clearInterval(wait);
1416						return;
1417					}
1418
1419			        if (slideImage.data('fullHeight') !== undefined) {
1420			            openStart();
1421			            clearInterval(wait);
1422			        }
1423			    }, 100);
1424			}else{
1425				openStart();
1426			}
1427
1428			function openStart(){
1429				if ($.isFunction($s.beforeOpen)) {
1430				 	$s.beforeOpen.call(this, container, slide);
1431				}
1432
1433				updateCaption(item, slide, $s);
1434
1435				if(slide && $s.openCloseEffect == 'zoom'){
1436					var previewImage = item.find('img');
1437
1438					if(!previewImage.length){
1439						previewImage = item;
1440					}
1441
1442					var	offsetTop = previewImage.offset().top - $(window).scrollTop(),
1443						offsetLeft = previewImage.offset().left;
1444
1445					setTranslate(slideImage, {
1446						width: previewImage.width(),
1447						height: previewImage.height(),
1448						top: offsetTop,
1449						left: offsetLeft,
1450						opacity: 1,
1451					});
1452
1453					var values = getImageFit(slideImage);
1454
1455					_animate(slideImage, {
1456						top: values.top,
1457						left: values.left,
1458						scaleX: values.scaleX,
1459						scaleY: values.scaleY
1460					}, $s.openCloseDuration);
1461
1462				}else if(slide && $s.openCloseEffect == 'fade'){
1463
1464					var values = getImageFit(slideImage);
1465
1466					setTranslate(slideImage, {
1467						width: values.width,
1468						height: values.height,
1469						top: values.top,
1470						left: values.left,
1471						opacity: 0
1472					});
1473
1474					setTimeout(function(){
1475						_animate(slideImage, {
1476							opacity: 1,
1477						}, $s.openCloseDuration);
1478					}, 20);
1479				}
1480
1481				container.addClass('cb-lightbox-run-opening');
1482
1483				setTimeout(function(){
1484					if(closing){
1485						return;
1486					}
1487
1488					opening = false;
1489
1490					_animateDurationRemove(container);
1491					_animateDurationRemove(container.find('.cb-lightbox-content'));
1492
1493					container.removeClass('cb-lightbox-init-opening cb-lightbox-run-opening cb-lightbox-init-transitions');
1494				}, $s.openCloseDuration);
1495
1496				setTimeout(function(){
1497					if ($.isFunction($s.afterOpen)) {
1498				 	   $s.afterOpen.call(this, container, slide);
1499					}
1500
1501				}, $s.openCloseDuration + 30);
1502			}
1503		}
1504
1505		function onScroll(event){
1506			event.preventDefault();
1507		}
1508
1509		function close(){
1510			closing = true;
1511
1512			clearTimeout(momentTimer);
1513
1514			var el = $(".cb-lightbox-is-selected"),
1515				previewImage = el.find('img'),
1516				container = $('.cb-lightbox'),
1517				$s = container.data('settings'),
1518				slide = container.find('.cb-lightbox-slide.cb-lightbox-slide-current'),
1519				slideImage = slide.find('.cb-lightbox-slide-image');
1520
1521			container.addClass('cb-lightbox-init-closing cb-lightbox-init-transitions');	
1522
1523			clearTimeout(container.data('watch'));
1524
1525			if ($.isFunction($s.beforeClose)) {
1526				$s.beforeClose.call(this, container, slide);
1527			}
1528
1529			if(!previewImage.length){
1530				previewImage = el;
1531			}
1532
1533			_animate(container, false, $s.openCloseDuration);
1534			_animate(container.find('.cb-lightbox-content'), false, $s.openCloseDuration);
1535
1536			container.addClass('cb-lightbox-run-closing');
1537
1538			if($s.openCloseEffect == 'zoom' && el.is(':visible')){
1539				var	scaleWidth =  previewImage.width() / slideImage.width(),
1540					scaleHeight = previewImage.height() / slideImage.height(),
1541					offsetTop = previewImage.offset().top - $(window).scrollTop();
1542					offsetLeft = previewImage.offset().left;
1543
1544				_animate(slideImage, {
1545					top: offsetTop,
1546					left: offsetLeft,
1547					scaleX: scaleWidth,
1548					scaleY: scaleHeight,
1549				}, $s.openCloseDuration);
1550
1551			}else if($s.openCloseEffect == 'fade'){
1552
1553				_animate(slide, {
1554					opacity: 0,
1555				}, $s.openCloseDuration);
1556			}
1557
1558			setTimeout(function(){
1559				detroyDraggable(slide);
1560				$(".cb-lightbox").remove();
1561				$("html").removeClass("cb-lightbox-lock cb-lightbox-margin");
1562				el.removeClass('cb-lightbox-is-selected');
1563				closing = false;
1564
1565				if ($.isFunction($s.afterClose)) {
1566				 	$s.afterClose.call(this, container);
1567				}
1568
1569			}, $s.openCloseDuration + 20);
1570
1571			//disable scroll events
1572			$('.cb-lightbox')[0].removeEventListener ('mousewheel', onScroll, false);
1573			$('.cb-lightbox')[0].removeEventListener ('touchmove', onScroll, false);
1574		}
1575
1576		function init(item, settings){
1577			var $s = settings,
1578				group = item.data("group"),
1579				grouplength = 0;
1580
1581			firstLoad = true;
1582			opening = true;
1583
1584			slides = [];
1585
1586			if(typeof group !== 'undefined'){
1587				items = $('a[data-group="'+ group +'"]');
1588				grouplength = items.length;
1589
1590				_this_index = item.index('a[data-group="'+ group +'"]');
1591			}else{
1592
1593				_this_index = item.index(item, settings);
1594			}
1595
1596			var tpl = $('<div class="cb-lightbox cb-lightbox-init-opening"></div>').append('<div class="cb-lightbox-overlay"></div>');
1597			
1598            var tplContent = $('<div class="cb-lightbox-content"></div>');
1599
1600            tplContent.append('<div class="cb-lightbox-close"></div><div class="cb-lightbox-loading"><div class="cb-lightbox-loading-animation"></div></div><div class="cb-lightbox-slides"></div>');
1601
1602            if($s.zoomMap && $s.zoom){
1603                tplContent.append('<div class="cb-lightbox__zoomMap"><div class="cb-lightbox__zoomMap-image"></div><div class="cb-lightbox__zoomMap-handle"></div></div>');
1604            }
1605
1606            if($s.zoomControlls && $s.zoom){
1607            	tplContent.append('<div class="cb-lightbox__zoomButtons"><div class="cb-lightbox__zoomButton cb-lightbox__zoomButton--in"></div><div class="cb-lightbox__zoomButton cb-lightbox__zoomButton--out cb-lightbox__zoomButton--disabled"></div></div>');
1608            }
1609
1610            tpl.append(tplContent);
1611
1612			if(grouplength > 1 && !$s.insidearrows){
1613				var arrows = $('<div class="cb-lightbox-arrow-prev cb-lightbox-arrow"><span></span></div><div class="cb-lightbox-arrow-next cb-lightbox-arrow"><span></span></div>');
1614				arrows.appendTo(tpl.find(".cb-lightbox-content"));
1615			}
1616
1617			var captionTpl = $('<div class="cb-lightbox-info"></div>');
1618
1619	    	captionTpl.appendTo(tpl.find(".cb-lightbox-content"));
1620
1621			if(grouplength > 1 && $s.counter){
1622				var counter = $('<div class="cb-lightbox-counter"></div>');
1623
1624				$('<span class="cb-counter-current"></span><span class="cb-counter-seperator">/</span><span class="cb-counter-total"></span>').appendTo(counter);
1625
1626				counter.find(".cb-counter-total").text($('a[data-group="'+ group +'"]').length);
1627				counter.find(".cb-counter-current").text(_this_index + 1);
1628
1629				tpl.find(".cb-lightbox-info").append(counter);
1630			}
1631
1632			if(grouplength <= 1){
1633				tpl.addClass('cb-lightbox-is-single');
1634			}
1635
1636			//lock background
1637			if($("body").height() > $(window).height()){
1638				$("html").addClass("cb-lightbox-lock cb-lightbox-margin");
1639			}
1640
1641			//set zoomOffset
1642			var zoomOffset = $s.zoomOffset;
1643
1644			if ($.type(zoomOffset) === "number" ) {
1645                zoomOffset = [ zoomOffset, zoomOffset, zoomOffset, zoomOffset ];
1646            }
1647
1648            if (zoomOffset.length == 2) {
1649                zoomOffset = [zoomOffset[0], zoomOffset[1], zoomOffset[0], zoomOffset[1]];
1650            }
1651
1652            $s.zoomOffset = zoomOffset;
1653
1654            //set margins
1655            if ($(window).width() < $s.breakpoint) {
1656				var margin = $s.mobilemargin;
1657			}else{
1658				var margin = $s.margin;
1659			}
1660
1661			if ($.type(margin) === "number" ) {
1662                margin = [ margin, margin, margin, margin ];
1663            }
1664
1665            if (margin.length == 2) {
1666                margin = [margin[0], margin[1], margin[0], margin[1]];
1667            }
1668
1669            $s.margin = margin;
1670
1671			tpl.data({
1672				'group': group,
1673                'grouplength': grouplength,
1674				'settings': $s
1675			});
1676
1677			tpl.appendTo($('body'));
1678
1679			if ($.isFunction($s.afterInit)) {
1680		 	   $s.afterInit.call(this, tpl);
1681			}
1682
1683			item.addClass("cb-lightbox-is-selected");
1684
1685			//cache current slide
1686			cacheSlides(item, _this_index, 'current');
1687
1688			//block scroll events
1689			$('.cb-lightbox')[0].addEventListener ('mousewheel', onScroll, {passive: false});
1690			$('.cb-lightbox')[0].addEventListener ('touchmove', onScroll, {passive: false});
1691
1692			open(item, _this_index, $s);
1693		}
1694
1695		if (!$(document).data('cb-lightbox-initialized')) {
1696			var clickTimer = false,
1697				userXTouch = 0,
1698				userYTouch = 0,
1699				firstTouch;
1700
1701			$(document).on('click', '.cb-lightbox-arrow', function(){
1702				if($(this).hasClass('cb-lightbox-arrow-prev')){
1703					slideTo('previews');
1704					$(window).trigger('resize')
1705				}else{
1706					slideTo('next');
1707					$(window).trigger('resize')
1708				}
1709			});
1710
1711			$(document).on("keyup", function(e){
1712				if(e.keyCode == 37){
1713					slideTo('previews');
1714					$(window).trigger('resize')
1715				}else if(e.keyCode == 39){
1716					slideTo('next');
1717					$(window).trigger('resize')
1718				}
1719			});
1720
1721			$(document).on("click", ".cb-lightbox-slide, .cb-lightbox-close", function(e){
1722				if($('.cb-lightbox').hasClass('cb-lightbox-init-closing')){
1723					return;
1724				}
1725
1726                var container = $('.cb-lightbox'),
1727                    $s = container.data('settings');
1728
1729				if((($(e.target).hasClass("cb-lightbox-slide") && $s.closeOutsideClick) || $(e.target).hasClass("cb-lightbox-close")) && !$(e.target).hasClass("cb-lightbox-arrow")){
1730					close();
1731				}
1732			});
1733
1734			$(document).on(is_touch_device() ? 'touchstart' : 'mousedown', '.cb-lightbox-slide-current .cb-lightbox-slide-image', function(e){
1735				if(!is_touch_device()){
1736			    	e.preventDefault();
1737			    }
1738
1739			    if(closing || opening || $(e.target).hasClass('cb-lightbox-arrow')){
1740					return;
1741				}
1742
1743				clickTimer = true;
1744				setTimeout(function(){
1745					clickTimer = false;
1746				}, 200);
1747
1748				//detekt two fingers
1749				if(e.type == "touchstart" && e.originalEvent.touches.length >= 2){
1750					var secondTouch = new Date().getTime();
1751
1752					if(secondTouch - firstTouch <= 200){
1753						pinching = true;
1754					}
1755				}
1756
1757				firstTouch = new Date().getTime(); 
1758
1759				var container = $('.cb-lightbox'),
1760					$s = container.data('settings'),
1761					slideImage = $(this),
1762					slide = slideImage.closest('.cb-lightbox-slide'),
1763					imageSizes = getImageSizes(slideImage);
1764
1765                if(e.type == "mousedown"){
1766                    if(e.which != 1){
1767                        return false;
1768                    }
1769                }else{
1770                    userXTouch = e.originalEvent.touches[0].clientX - $(this).offset().left;
1771                    userYTouch = e.originalEvent.touches[0].clientY - $(this).offset().top;
1772                }
1773
1774                //detect pan
1775                if(e.type == "touchstart" && e.originalEvent.touches.length >= 2){
1776
1777                    if(slide.hasClass('cb-lightbox-is-sliding')){
1778                        return;
1779                    }
1780
1781                    var currentScale = slideImage.data('currentPercentage'),
1782                        touchStart1 = e.originalEvent.touches[0],
1783                        touchStart2 = e.originalEvent.touches[1],
1784                        lastTransform = getLastTransform(slideImage),
1785                        imageWidth = imageSizes.width;
1786                        imageHeight = imageSizes.height;
1787
1788                    var centerPointStartX = (touchStart1.clientX + touchStart2.clientX) * 0.5,
1789                        centerPointStartY = (touchStart1.clientY + touchStart2.clientY) * 0.5,
1790                        pinchPercentagePintX = (centerPointStartX - lastTransform.x) / imageWidth,
1791                        pinchPercentagePintY = (centerPointStartY - lastTransform.y) / imageHeight,
1792                        startPinch = getZoomDistance(touchStart1, touchStart2);
1793
1794                    slideImage.addClass('cb-lightbox-is-pinching');
1795                    slideImage.data('currentZoomStep', 'auto');
1796
1797                    $(document).bind(is_touch_device() ? 'touchmove.cb-lightbox' : 'mousemove.cb-lightbox', function(e){
1798                            
1799                        isDraggable = true;
1800                        container.addClass('cb-lightbox-is-zoomed');
1801
1802                        var touchEnd1 = e.originalEvent.touches[0],
1803                            touchEnd2 = e.originalEvent.touches[1],
1804                            currentPinch = getZoomDistance(touchEnd1, touchEnd2),
1805                            pinchDistance = (currentPinch - startPinch),
1806                            newScale = currentScale + (pinchDistance / 3);
1807
1808                        if(newScale > 100){
1809
1810                            container.find('.cb-lightbox__zoomButton--out').removeClass('cb-lightbox__zoomButton--disabled');
1811							container.find('.cb-lightbox__zoomButton--in').addClass('cb-lightbox__zoomButton--disabled');
1812
1813                            newScale = 100;
1814
1815                        }else if(newScale.toFixed(6) <= parseFloat(slideImage.data('fitPercentage').toFixed(6))){
1816                            newScale = slideImage.data('fitPercentage');
1817
1818                            isDraggable = false;
1819                            container.removeClass('cb-lightbox-is-zoomed');
1820
1821                            container.find('.cb-lightbox__zoomButton--out').addClass('cb-lightbox__zoomButton--disabled');
1822							container.find('.cb-lightbox__zoomButton--in').removeClass('cb-lightbox__zoomButton--disabled');
1823
1824                        }else{
1825                        	container.find('.cb-lightbox__zoomButton').removeClass('cb-lightbox__zoomButton--disabled');
1826                        }
1827
1828                        //set new scale percentage
1829                        slideImage.data('currentPercentage', newScale);
1830
1831                        //center point 
1832                        var centerPointEndX = (touchEnd1.clientX + touchEnd2.clientX) * 0.5,
1833                            centerPointEndY = (touchEnd1.clientY + touchEnd2.clientY) * 0.5;
1834
1835                        //get new image size
1836                        var newWidth = getImageSizes(slideImage).width,
1837                            newHeight = getImageSizes(slideImage).height;
1838
1839                        var pinchTranslateFromTranslatingX = centerPointEndX - centerPointStartX,
1840                            pinchTranslateFromTranslatingY = centerPointEndY - centerPointStartY;
1841
1842                        var pinchTranslateFromZoomX = (imageWidth - newWidth) * pinchPercentagePintX,
1843                            pinchTranslateFromZoomY = (imageHeight - newHeight) * pinchPercentagePintY;
1844
1845                        var newX = lastTransform.x + (pinchTranslateFromZoomX + pinchTranslateFromTranslatingX),
1846                            newY = lastTransform.y + (pinchTranslateFromZoomY + pinchTranslateFromTranslatingY);
1847
1848                        setTranslate(slideImage, {
1849							top: checkZoomLimit(newHeight, 'height', newY),
1850                    		left: checkZoomLimit(newWidth, 'width', newX),
1851                            width: newWidth,
1852                            height: newHeight,
1853                        });
1854                            
1855                        zoomMapPosition(newX, newY);
1856
1857                    });
1858
1859                } else if(!container.hasClass('cb-lightbox-is-zoomed') && !container.hasClass('cb-lightbox-is-single')){
1860					if(!$s.dragSlide || opening || isDraggable){
1861						return;
1862					}
1863
1864					var imageWidth = slideImage.data('fullWidth'),
1865						windowWidth = $(window).width(),
1866						windowHeight = $(window).height(),
1867						moveDirection = false;
1868
1869					if(e.type == "mousedown"){
1870						var pageXStart = e.pageX,
1871							pageYStart = e.pageY;
1872					}else{
1873						var pageXStart = e.originalEvent.touches[0].pageX,
1874							pageYStart = e.originalEvent.touches[0].pageY;
1875					}
1876
1877					var dragWidth = windowWidth,
1878						dragPosX = dragWidth - pageXStart,
1879						dragHeight = windowHeight,
1880						dragPosY = dragHeight - pageYStart;
1881
1882					$(document).bind(is_touch_device() ? 'touchmove.cb-lightbox' : 'mousemove.cb-lightbox', function(e){
1883
1884						if(pinching){
1885							return;
1886						}
1887
1888						if(e.type == "mousemove"){
1889							var pageXMove = e.pageX,
1890								pageYMove = e.pageY;
1891						}else{
1892							var pageXMove = e.originalEvent.touches[0].pageX,
1893								pageYMove = e.originalEvent.touches[0].pageY;
1894						}
1895
1896						var dragLeft = pageXMove + dragPosX - dragWidth,
1897							dragTop = pageYMove + dragPosY - dragHeight;
1898
1899						if(dragLeft == 0 && dragTop == 0){
1900							return;
1901						}
1902
1903						var angle = Math.abs((Math.atan2(dragTop, dragLeft) * 180) / Math.PI),
1904							direction = angle > 45 && angle < 135 ? "y" : "x";
1905
1906						if(!moveDirection){
1907							moveDirection = direction;
1908						}
1909
1910						if(moveDirection == 'y'){
1911							setTranslate(slideImage, {
1912					        	top: slideImage.data('fitTop') + dragTop,
1913					        });
1914
1915							slide
1916				        		.addClass('cb-lightbox-is-sliding')
1917				        		.data('slideY', dragTop);
1918
1919						}else if(moveDirection == 'x'){
1920							setTranslate(slide, {
1921					        	left: dragLeft,
1922					        });
1923
1924					        slide
1925				        		.addClass('cb-lightbox-is-sliding')
1926				        		.data('slideX', dragLeft);
1927						}
1928					});
1929				
1930                }else{
1931
1932    				container.addClass('cb-lightbox-is-grabbing');
1933
1934    				if(!slideImage.hasClass('cb-lightbox-slide-draggable')){
1935    					return;
1936    				}
1937
1938    			    var imageWidth = imageSizes.width,
1939    					windowWidth = $(window).width(),
1940    					windowHeight = $(window).height(),
1941    			    	lastTransform = getLastTransform(slideImage),
1942    			    	lastTransformX = lastTransform.x,
1943    			        lastTransformY = lastTransform.y,
1944    					imageHeight = imageSizes.height,
1945    			    	maxX = windowWidth - imageWidth,
1946    			    	maxY = windowHeight - imageHeight,
1947                        startX, 
1948                        startY;
1949
1950    			    if(e.type == "touchstart"){
1951    			    	startX = e.originalEvent.touches[0].pageX - lastTransformX;
1952    					startY = e.originalEvent.touches[0].pageY - lastTransformY;
1953    			    }else{
1954    			    	startX = e.pageX - lastTransformX;
1955    			    	startY = e.pageY - lastTransformY;
1956    			    }
1957
1958    			    clearTimeout(momentTimer);
1959    			    lastT = new Date().getTime();
1960
1961    			    mouseUp = false;
1962    			    logMousePosition();
1963
1964    			    $(document).bind(is_touch_device() ? 'touchmove.cb-lightbox' : 'mousemove.cb-lightbox', function(e){
1965    			    	if(e.type == "touchmove"){
1966    			    		var newX = e.originalEvent.touches[0].pageX - startX,
1967    				            newY = e.originalEvent.touches[0].pageY - startY;
1968    			    	}else{
1969    				        var newX = e.pageX - startX,
1970    				            newY = e.pageY - startY;
1971    			        }
1972
1973    			        //check element is dragging
1974    			        if(Math.abs(lastTransformX - newX) > 2 || Math.abs(lastTransformY - newY) > 2){
1975    						slideImage.addClass("cb-lightbox-slide-dragging");
1976    						clickTimer = false;
1977    			        }
1978
1979    			        if(!isDraggable || pinching){
1980    			        	return;
1981    			        }
1982
1983    			        if(imageWidth < windowWidth){
1984    			        	newX = (windowWidth - imageWidth) / 2;
1985    			        }else if(newX > $s.zoomOffset[3]){
1986    			        	newX = ((newX - $s.zoomOffset[3]) / 3) + $s.zoomOffset[3];
1987    			        }else if(Math.abs(newX) - $s.zoomOffset[1] > imageWidth - windowWidth && imageWidth > windowWidth){
1988    			        	newX = ((-Math.abs(newX + $s.zoomOffset[1]) - maxX) / 3) + maxX - $s.zoomOffset[1];
1989    			        }
1990
1991    			        if(imageHeight < windowHeight){
1992    			        	newY = (windowHeight - imageHeight) / 2;
1993    			        }else if(newY > $s.zoomOffset[0]){
1994    			        	newY = ((newY - $s.zoomOffset[0]) / 3) + $s.zoomOffset[0];
1995    			        }else if(Math.abs(newY) - $s.zoomOffset[2] > imageHeight - windowHeight && imageHeight > windowHeight){
1996    			        	newY = ((-Math.abs(newY + $s.zoomOffset[2]) - maxY) / 3) + maxY - $s.zoomOffset[2];
1997    			        }
1998
1999    			        currentPoint = {x: newX, y: newY};
2000
2001                        zoomMapPosition(newX, newY);
2002
2003    			        setTranslate(slideImage, {
2004    			        	top: newY,
2005    			        	left: newX
2006    			        });
2007			        }); 
2008                }
2009			});
2010
2011            $(document).on(is_touch_device() ? 'touchstart' : 'mousedown', '.cb-lightbox__zoomMap', function(e){
2012                if(!is_touch_device()){
2013                    e.preventDefault();
2014                }
2015
2016                if(closing || opening || !isDraggable){
2017                    return;
2018                }
2019
2020                var container = $('.cb-lightbox'),
2021                    $s = container.data('settings'),
2022                    slide = $('.cb-lightbox-slide-current'),
2023                    slideImage = slide.find('.cb-lightbox-slide-image');
2024
2025                if(e.type == "mousedown"){
2026                    if(e.which != 1){
2027                        return false;
2028                    }
2029                }
2030
2031                container.addClass('cb-lightbox-is-grabbing');
2032                slideImage.addClass('cb-lightbox-slide-dragging-zoommap');
2033
2034                if(!slideImage.hasClass('cb-lightbox-slide-draggable')){
2035                    return;
2036                }
2037
2038                var area = $(this),
2039                    handel = area.find('.cb-lightbox__zoomMap-handle'),
2040                    handelWidth = handel.outerWidth(),
2041                    handelHeight = handel.outerHeight(),
2042                    areaWidth = area.width(),
2043                    areaHeight = area.height(),
2044                    lastOffsetX = parseInt(handel.css('left')),
2045                    lastOffsetY = parseInt(handel.css('top')),
2046                    startX,
2047                    startY,
2048                    imageWidth = slideImage.data('fullWidth') * (slideImage.data('currentPercentage') / 100),
2049                    imageHeight = slideImage.data('fullHeight') * (slideImage.data('currentPercentage') / 100);
2050
2051                if(e.type == "touchstart"){
2052                    startX = e.originalEvent.touches[0].pageX - lastOffsetX;
2053                    startY = e.originalEvent.touches[0].pageY - lastOffsetY;
2054                }else{
2055                    startX = e.pageX - lastOffsetX;
2056                    startY = e.pageY - lastOffsetY;
2057                }
2058
2059                $(document).bind(is_touch_device() ? 'touchmove.cb-lightbox' : 'mousemove.cb-lightbox', function(e){
2060                    if(e.type == "touchmove"){
2061                        var newX = e.originalEvent.touches[0].pageX - startX,
2062                            newY = e.originalEvent.touches[0].pageY - startY;
2063                    }else{
2064                        var newX = e.pageX - startX,
2065                            newY = e.pageY - startY;
2066                    }        
2067            
2068                    if(newY < 0){
2069                        newY = 0;
2070                    }else if((newY / areaHeight * imageHeight) > imageHeight - $(window).height()){
2071                        
2072                        if(imageHeight > $(window).height()){
2073                            newY = (Math.abs(imageHeight - $(window).height()) / imageHeight) * areaHeight;
2074                        }else{
2075                            newY = 0;
2076                        }
2077                    }
2078
2079                    if(newX < 0){
2080                        newX = 0;
2081                    }else if((newX / areaWidth * imageWidth) > imageWidth - $(window).width()){
2082                            
2083                        if(imageWidth > $(window).width()){
2084                            newX = (Math.abs(imageWidth - $(window).width()) / imageWidth) * areaWidth;
2085                        }else{
2086                            newX = 0;
2087                        }
2088                    }
2089
2090                    handel.css({
2091                        top: newY,
2092                        left: newX
2093                    });
2094
2095                    var imageLeft = (newX / areaWidth * imageWidth);
2096                    if(imageLeft > imageWidth - $(window).width()){
2097                        imageLeft = (imageWidth - $(window).width()) / 2;
2098                    }
2099
2100                    var imageTop = (newY / areaHeight * imageHeight);
2101                    if(imageTop > imageHeight - $(window).height()){
2102                        imageTop = (imageHeight - $(window).height()) / 2;
2103                    }
2104                    
2105                    setTranslate(slideImage, {
2106                        top: -imageTop,
2107                        left: -imageLeft,
2108                    });
2109                });
2110            });
2111
2112			$(document).on(is_touch_device() ? 'touchend' : 'mouseup', function(e){
2113
2114				mouseUp = true;
2115				clearTimeout(positionInterval);
2116				clearTimeout(momentTimer);
2117
2118				var container = $('.cb-lightbox');
2119
2120				container.removeClass('cb-lightbox-is-grabbing');
2121				$(this).unbind("mousemove.cb-lightbox touchmove.cb-lightbox");
2122
2123				if($(e.target).hasClass('cb-lightbox-close') || $(e.target).hasClass('cb-lightbox-content') || container.hasClass('cb-lightbox-init-closing') || $(e.target).hasClass('cb-lightbox__zoomButton')){
2124					return;
2125				}
2126
2127				if(e.which != 1 && e.which != 0 ){
2128					return
2129				}
2130
2131				if(e.type == 'mouseup' || e.type == 'touchend'){
2132					var slide = $(".cb-lightbox-slide-current"),
2133						slideImage = slide.find('.cb-lightbox-slide-image');
2134
2135					if(slide.hasClass('cb-lightbox-is-sliding')){
2136						//handle slide
2137						var tolerance = 40,
2138							resetSlide = false;
2139
2140						if(slide.data('slideX')){
2141							if(slide.data('slideX') > 0){
2142								if(slide.data('slideX') > 0 + tolerance){
2143									slideTo('previews', 'slide');
2144								}else{
2145									resetSlide = true;
2146								}
2147
2148							}else{
2149								if(slide.data('slideX') < 0 - tolerance){
2150									slideTo('next', 'slide');
2151								}else{
2152									resetSlide = true;
2153								}
2154							}
2155
2156							slide.data('slideX', false);
2157
2158							if(resetSlide){
2159								_animate(slide, {
2160									left: 0,
2161								}, 250);
2162
2163								slide.removeClass('cb-lightbox-is-sliding');
2164							}
2165
2166						}else if(slide.data('slideY')){
2167							if(Math.abs(slide.data('slideY')) > tolerance){
2168								close();
2169							}else{
2170								_animate(slideImage, {
2171									'top': slideImage.data('fitTop')
2172								}, 250);
2173
2174								slide.removeClass('cb-lightbox-is-sliding');
2175							}
2176
2177							slide.data('slideY', false);
2178						}
2179					}else{
2180						if($('.cb-lightbox').hasClass('cb-lightbox-is-loading')){
2181							return false
2182						}
2183
2184						if(clickTimer){
2185							//handle after click
2186							if(!slideImage.hasClass("cb-lightbox-slide-dragging")){
2187								if(!slideImage.hasClass('cb-lightbox-slide-draggable')){
2188									return;
2189								}
2190
2191								//move to click position
2192								if(e.type == "mouseup"){
2193									var userX = e.offsetX,
2194										userY = e.offsetY;
2195								}else{
2196									var userX = userXTouch,
2197										userY = userYTouch;
2198								}
2199
2200							   	if($(".cb-lightbox").hasClass("cb-lightbox-is-zoomed")){
2201							   		container.find('.cb-lightbox__zoomButton--out').addClass('cb-lightbox__zoomButton--disabled');
2202									container.find('.cb-lightbox__zoomButton--in').removeClass('cb-lightbox__zoomButton--disabled');
2203							   		detroyDraggable(slideImage);
2204							   	}else{
2205							   		container.find('.cb-lightbox__zoomButton--out').removeClass('cb-lightbox__zoomButton--disabled');
2206									container.find('.cb-lightbox__zoomButton--in').addClass('cb-lightbox__zoomButton--disabled');
2207									initDraggable(slideImage, userX, userY);
2208							   	}
2209
2210							}else{
2211							    $(this).off("mousemove.cb-lightbox touchmove.cb-lightbox");
2212							}
2213
2214						}else if(slideImage.hasClass('cb-lightbox-slide-dragging-zoommap')){
2215
2216                        }else if(slideImage.hasClass('cb-lightbox-is-pinching')){
2217
2218                        }else if(!pinching){
2219                            if($('.cb-lightbox-is-zoomed').length && isDraggable){
2220                                initMoveMoment(slideImage);
2221                            }
2222						}
2223					}
2224
2225					pinching = false;
2226
2227                    slideImage.removeClass('cb-lightbox-is-pinching');
2228					slideImage.removeClass("cb-lightbox-slide-dragging");
2229                    slideImage.removeClass('cb-lightbox-slide-dragging-zoommap');
2230				}
2231			});
2232
2233            $(document).on('click', '.cb-lightbox__zoomButton', function(){
2234                var container = $('.cb-lightbox'),
2235                    $s = container.data('settings'),
2236                    button = $(this),
2237                    buttons = button.closest('.cb-lightbox__zoomButtons'),
2238                    currentSlide = $('.cb-lightbox-slide-current');
2239                    slideImage = currentSlide.find('.cb-lightbox-slide-image');
2240
2241                if(button.hasClass('cb-lightbox__zoomButton--disabled')){
2242                	return;
2243                }
2244
2245                var currentScale = slideImage.data('currentPercentage'),
2246                    currentZoomStep = slideImage.data('currentZoomStep');
2247
2248
2249                if(button.hasClass('cb-lightbox__zoomButton--in')){
2250                    isDraggable = true;
2251                    container.addClass('cb-lightbox-is-zoomed');
2252
2253                    let newZoom;
2254                    if(currentZoomStep == 'auto'){
2255                    	for (var i = 0; i <= $s.zoomSteps; i++) {
2256                    		calculatedScale = calcZoomSize(slideImage, i);
2257
2258                    		if(calculatedScale >= currentScale){
2259                    			newZoom = i;
2260                    			break;
2261                    		}
2262                    	}
2263                    }else{
2264                    	newZoom = currentZoomStep + 1;
2265	                    if(newZoom > $s.zoomSteps){
2266	                    	newZoom = $s.zoomSteps;
2267	                    }
2268                    }
2269
2270                    slideImage.data('currentZoomStep', newZoom);
2271
2272                    var newScale = calcZoomSize(slideImage, false); //currentScale + 20;
2273
2274                    buttons.find('.cb-lightbox__zoomButton--out').removeClass('cb-lightbox__zoomButton--disabled');
2275
2276                    if(newScale >= 100){
2277                        newScale = 100;
2278
2279                        button.addClass('cb-lightbox__zoomButton--disabled');
2280                    }
2281
2282                }else if(button.hasClass('cb-lightbox__zoomButton--out')){
2283
2284                	let newZoom;
2285					if(currentZoomStep == 'auto'){
2286                    	for (var i = $s.zoomSteps; i >= 0; i--) {
2287                    		calculatedScale = calcZoomSize(slideImage, i);
2288
2289                    		if(calculatedScale <= currentScale){
2290                    			newZoom = i;
2291                    			break;
2292                    		}
2293                    	}
2294                    }else{
2295	                    newZoom = currentZoomStep - 1;
2296	                    if(newZoom <= 0){
2297	                    	newZoom = 0;
2298	                    }
2299	                }
2300
2301                    slideImage.data('currentZoomStep', newZoom);
2302
2303                    var newScale = calcZoomSize(slideImage, false); //currentScale - 20;
2304
2305                    buttons.find('.cb-lightbox__zoomButton--in').removeClass('cb-lightbox__zoomButton--disabled');
2306
2307                    //round number
2308                    if(newScale.toFixed(6) <= parseFloat(slideImage.data('fitPercentage').toFixed(6))){
2309                        newScale = slideImage.data('fitPercentage');
2310
2311                        isDraggable = false;
2312
2313                        button.addClass('cb-lightbox__zoomButton--disabled');
2314                    }
2315                }
2316
2317                slideImage.data('currentPercentage', newScale);
2318
2319                var newWidth = getImageSizes(slideImage).width,
2320                    newHeight = getImageSizes(slideImage).height,
2321                    diffWidth = newWidth - (slideImage.data('fullWidth') * (currentScale / 100)),
2322                    diffHeight = newHeight - (slideImage.data('fullHeight') * (currentScale / 100)),
2323                    lastTransform = getLastTransform(slideImage),
2324                    newY = lastTransform.y - (diffHeight / 2),
2325                    newX = lastTransform.x - (diffWidth / 2),
2326                    scaleWidth = newWidth / slideImage.width(),
2327                    scaleHeight = newHeight / slideImage.height();
2328
2329                //more to original position
2330                if(!isDraggable){
2331                	newY = slideImage.data('fitTop');
2332                	newX = slideImage.data('fitLeft');
2333                }else{
2334                	newY = checkZoomLimit(newHeight, 'height', newY);
2335                	newX = checkZoomLimit(newWidth, 'width', newX);
2336                }
2337
2338                container.addClass('cb-lightbox-run-zoom');
2339
2340                _animate(slideImage, {
2341                    top: newY,
2342                    left: newX,
2343                    scaleX: scaleWidth,
2344                    scaleY: scaleHeight,
2345                }, $s.zoomDuration);
2346                    
2347                zoomMapPosition(newX, newY);
2348
2349                setTimeout(function(){
2350                    container.removeClass('cb-lightbox-run-zoom');
2351
2352	                if(!isDraggable){
2353	                	container.removeClass('cb-lightbox-is-zoomed');
2354	                }
2355
2356                }, $s.zoomDuration);
2357            });
2358
2359			$(window).on("resize", function(){
2360				if(!$("html").hasClass("cb-lightbox-touch") && $('.cb-lightbox').hasClass('cb-lightbox-is-zoomed')){
2361					detroyDraggable($('.cb-lightbox-slide-current .cb-lightbox-slide-image'), true);
2362				}
2363
2364				let lightbox = $('.cb-lightbox');
2365
2366				if(lightbox.length){
2367					var $s = lightbox.data('settings');
2368
2369					$('.cb-lightbox-slide').each(function(){
2370						var slide = $(this),
2371							slideImage = slide.find('.cb-lightbox-slide-image'),
2372							caption = slide.find('.cb-lightbox-caption');
2373
2374						values = getImageFit(slideImage);
2375
2376						setTranslate(slideImage, {
2377							width: values.width,
2378							height: values.height,
2379							top: values.top,
2380							left: values.left,
2381						});
2382
2383						if(caption.length){
2384							captionInsidePosition(caption, slideImage);
2385						}
2386
2387						if(slide.hasClass('cb-lightbox-slide-current')){
2388							if ($.isFunction($s.onResize)) {
2389								$s.onResize.call(this, $('.cb-lightbox'), slide);
2390							}
2391						}
2392					});
2393
2394					lightbox.find('.cb-lightbox__zoomButton--out').addClass('cb-lightbox__zoomButton--disabled');
2395					lightbox.find('.cb-lightbox__zoomButton--in').removeClass('cb-lightbox__zoomButton--disabled');
2396
2397				}
2398			});
2399
2400			$(document).data('cb-lightbox-initialized', true);
2401		}
2402
2403		return $(this).each(function(){
2404			var item = $(this);
2405
2406			var settings = $.extend({}, defaults, options);
2407
2408			item.on("click", function(e){
2409				e.stopPropagation();
2410				e.preventDefault();
2411
2412				if(settings.disableOnMobile && $(window).width() < settings.breakpoint){
2413					return;
2414				}
2415
2416				init(item, settings);
2417			});
2418		});
2419	}
2420})(jQuery);

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.