PageSourceSearch

https://divoche.media/wp-content/plugins/easy-fancybox/fancybox/2.2.0/jquery.fancybox.js?ver=1790921726

js divoche.media collected 2026-10-02 06:16:13 UTC 53,553 bytes, 2,131 lines download raw bytes

vendor: 6,764 bytes, lines 1-230
1/**
2 * fancyBox - jQuery Plugin
3 * version: 2.2.0 (Tue, 16 Sep 2022)
4 * requires jQuery v1.6 or later
5 *
6 * Licensed GPLv3 for open source use
7 * or fancyBox Commercial License for commercial use
8 *
9 * Examples at http://fancyapps.com/fancybox/
10 * License: www.fancyapps.com/fancybox/#license
11 *
12 * Copyright 2017 fancyapps.com
13 */
14
15;(function (window, document, $, undefined) {
16	"use strict";
17
18	var H = $("html"),
19		W = $(window),
20		D = $(document),
21		F = $.fancybox = function () {
22			F.open.apply( this, arguments );
23		},
24		IE = navigator.userAgent.match(/msie/i),
25		didUpdate = null,
26		isTouch	  = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0,
27
28		isQuery	= function(obj) {
29			return obj && obj.hasOwnProperty && obj instanceof $;
30		},
31		isString = function(str) {
32			return str && $.type(str) === "string";
33		},
34		isPercentage = function(str) {
35			return isString(str) && str.indexOf('%') > 0;
36		},
37		isScrollable = function(el) {
38			return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));
39		},
40		getScalar = function(orig, dim) {
41			var value = parseInt(orig, 10) || 0;
42
43			if (dim && isPercentage(orig)) {
44				value = F.getViewport()[ dim ] / 100 * value;
45			}
46
47			return Math.ceil(value);
48		},
49		getValue = function(value, dim) {
50			return getScalar(value, dim) + 'px';
51		};
52
53	$.extend(F, {
54		// The current version of fancyBox
55		version: '2.2.0',
56
57		defaults: {
58			padding : 15,
59			margin  : 20,
60
61			width     : 800,
62			height    : 600,
63			minWidth  : 100,
64			minHeight : 100,
65			maxWidth  : 9999,
66			maxHeight : 9999,
67			pixelRatio: window.devicePixelRatio || 1, // Set to 2 for retina display support
68
69			autoSize   : true,
70			autoHeight : false,
71			autoWidth  : false,
72
73			autoResize  : true,
74			autoCenter  : !isTouch,
75			fitToView   : true,
76			aspectRatio : false,
77			topRatio    : 0.5,
78			leftRatio   : 0.5,
79			minVpWidth  : 320,
80			minVpHeight : 320,
81
82			scrolling : 'auto', // 'auto', 'yes' or 'no'
83			wrapCSS   : '',
84
85			arrows     : true,
86			closeBtn   : true,
87			closeClick : false,
88			nextClick  : false,
89			zoomClick  : false,
90			mouseWheel : true,
91			swipe      : isTouch,
92			autoPlay   : false,
93			playSpeed  : 3000,
94			preload    : 3,
95			modal      : false,
96			loop       : true,
97
98			ajax  : {
99				dataType : 'html',
100				headers  : { 'X-fancyBox': true }
101			},
102			iframe : {
103				scrolling       : 'auto',
104				allowfullscreen : true,
105				preload         : true
106			},
107			svg : {},
108
109			keys  : {
110				next : {
111					13 : 'left', // enter
112					34 : 'up',   // page down
113					39 : 'left', // right arrow
114					40 : 'up'    // down arrow
115				},
116				prev : {
117					8  : 'right',  // backspace
118					33 : 'down',   // page up
119					37 : 'right',  // left arrow
120					38 : 'down'    // up arrow
121				},
122				close  : [27], // escape key
123				play   : [32], // space - start/stop slideshow
124				toggle : [70]  // letter "f" - toggle fullscreen
125			},
126
127			direction : {
128				next : 'left',
129				prev : 'right'
130			},
131
132			scrollOutside  : true,
133
134			// Override some properties
135			index   : 0,
136			type    : null,
137			href    : null,
138			content : null,
139			title   : null,
140
141			// HTML templates
142			tpl: {
143				wrap    : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',
144				image   : '<img class="fancybox-image" src="{href}" alt="" />',
145				iframe  : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" allow="autoplay; encrypted-media;"' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',
146				error   : '<p class="fancybox-error">{error}</p>',
147				close   : `<a title="${DOMPurify.sanitize((window.efb_i18n && window.efb_i18n.close) || 'Close')}" class="fancybox-item fancybox-close" href="javascript:;"></a>`,
148				next    : `<a title="${DOMPurify.sanitize((window.efb_i18n && window.efb_i18n.next) || 'Next')}" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>`,
149				prev    : `<a title="${DOMPurify.sanitize((window.efb_i18n && window.efb_i18n.prev) || 'Previous')}" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>`,
150				loading : '<div id="fancybox-loading"><div></div></div>'
151			},
152
153			// Texts
154			txt: {
155				error : {
156					content : 'The requested content cannot be loaded.<br/>Please try again later.',
157					image   : 'The requested image cannot be loaded.<br/>Please try again later.',
158					ajax    : 'An AJAX error occurred.<br/>Please contact the site administrator.',
159					href    : 'Missing media target URL.<br/>Please contact the site administrator.',
160				},
161				close : (window.efb_i18n && window.efb_i18n.close) || 'Close',
162				next  : (window.efb_i18n && window.efb_i18n.next)  || 'Next',
163				prev  : (window.efb_i18n && window.efb_i18n.prev)  || 'Previous'
164			},
165
166			// Properties for each animation type
167			// Opening fancyBox
168			openEffect  : 'fade', // 'elastic', 'fade' or 'none'
169			openSpeed   : 250,
170			openEasing  : 'swing',
171			openOpacity : true,
172			openMethod  : 'zoomIn',
173
174			// Closing fancyBox
175			closeEffect  : 'fade', // 'elastic', 'fade' or 'none'
176			closeSpeed   : 250,
177			closeEasing  : 'swing',
178			closeOpacity : true,
179			closeMethod  : 'zoomOut',
180
181			// Changing next gallery item
182			nextEffect : 'elastic', // 'elastic', 'fade' or 'none'
183			nextSpeed  : 250,
184			nextEasing : 'swing',
185			nextMethod : 'changeIn',
186
187			// Changing previous gallery item
188			prevEffect : 'elastic', // 'elastic', 'fade' or 'none'
189			prevSpeed  : 250,
190			prevEasing : 'swing',
191			prevMethod : 'changeOut',
192
193			// Enable default helpers
194			helpers : {
195				overlay : true,
196				title   : true
197			},
198
199			// Callbacks
200			onCancel     : $.noop, // If canceling
201			beforeLoad   : $.noop, // Before loading
202			afterLoad    : $.noop, // After loading
203			beforeShow   : $.noop, // Before changing in current item
204			afterShow    : $.noop, // After opening
205			beforeChange : $.noop, // Before changing gallery item
206			beforeClose  : $.noop, // Before closing
207			afterClose   : $.noop  // After closing
208		},
209
210		//Current state
211		group    : {}, // Selected group
212		opts     : {}, // Group options
213		previous : null,  // Previous element
214		coming   : null,  // Element being loaded
215		current  : null,  // Currently loaded element
216		isActive : false, // Is activated
217		isOpen   : false, // Is currently open
218		isOpened : false, // Have been fully opened at least once
219
220		wrap  : null,
221		skin  : null,
222		outer : null,
223		inner : null,
224
225		player : {
226			timer    : null,
227			isActive : false
228		},
229
230		// Loaders
vendor: 9,913 bytes, lines 231-679
231		ajaxLoad   : null,
232		imgPreload : null,
233
234		// Some collections
235		transitions : {},
236		helpers     : {},
237
238		/*
239		 *	Static methods
240		 */
241
242		open: function (group, opts) {
243			if (!group) {
244				return;
245			}
246
247			if (!$.isPlainObject(opts)) {
248				opts = {};
249			}
250
251			// Close if already active
252			if (false === F.close(true)) {
253				return;
254			}
255
256			// Normalize group
257			if (!$.isArray(group)) {
258				group = isQuery(group) ? $(group).get() : [group];
259			}
260
261			// Recheck if the type of each element is `object` and set content type (image, ajax, etc)
262			$.each(group, function(i, element) {
263				var obj = {},
264					href,
265					title,
266					content,
267					type,
268					rez,
269					hrefParts,
270					selector;
271
272				if ($.type(element) === "object") {
273					// Check if is DOM element
274					if (element.nodeType) {
275						element = $(element);
276					}
277
278					if (isQuery(element)) {
279						obj = {
280							href    : element.data('fancybox-href') || element.attr('href'),
281							title   : $('<div/>').text(DOMPurify.sanitize(
282								element.is('img') ? element.attr('title') : element.find('img').attr('title') || ''
283							)).html(),
284							isDom   : true,
285							element : element
286						};
287						console.log( element.find('img') );
288						console.log('title: ');
289						console.log( element.find('img').attr('title') );
290
291						if ($.metadata) {
292							$.extend(true, obj, element.metadata());
293						}
294					}
295					else {
296						obj = element;
297					}
298				}
299
300				href  = opts.href  || obj.href || (isString(element) ? element : null);
301				title = DOMPurify.sanitize(opts.title !== undefined ? opts.title : obj.title || '');
302
303				content = opts.content || obj.content;
304				type    = content ? 'html' : (opts.type  || obj.type);
305
306				if (!type && obj.isDom) {
307					type = element.data('fancybox-type');
308
309					if (!type) {
310						rez  = element.prop('class').match(/fancybox\.(\w+)/);
311						type = rez ? rez[1] : null;
312					}
313				}
314
315				if (isString(href)) {
316					// Try to guess the content type
317					if (!type) {
318						if (F.isImage(href)) {
319							type = 'image';
320						}
321						else if (F.isSVG(href)) {
322							type = 'svg';
323						}
324						else if (href.charAt(0) === '#') {
325							type = 'inline';
326						}
327						else if (isString(element)) {
328							type    = 'html';
329							content = element;
330						}
331					}
332
333					// Split url into two pieces with source url and content selector, e.g,
334					// "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"
335					if (type === 'ajax') {
336						hrefParts = href.split(/\s+/, 2);
337						href      = hrefParts.shift();
338						selector  = hrefParts.shift();
339					}
340				}
341
342				if (!content) {
343					if (type === 'inline') {
344						if (href) {
345							content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
346						}
347						else if (obj.isDom) {
348							content = element;
349						}
350					}
351					else if (type === 'html') {
352						content = href;
353					}
354					else if (!type && !href && obj.isDom) {
355						type    = 'inline';
356						content = element;
357					}
358				}
359
360				$.extend(obj, {
361					href     : href,
362					type     : type,
363					content  : content,
364					title    : title,
365					selector : selector
366				});
367
368				group[ i ] = obj;
369			});
370
371			// Extend the defaults
372			F.opts = $.extend(true, {}, F.defaults, opts);
373
374			// All options are merged recursive except keys
375			if (opts.keys !== undefined) {
376				F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
377			}
378
379			F.group = group;
380
381			return F._start(F.opts.index);
382		},
383
384		// Cancel image loading or abort ajax request
385		cancel: function () {
386			var coming = F.coming;
387
388			if (coming && false === F.trigger('onCancel')) {
389				return;
390			}
391
392			F.hideLoading();
393
394			if (!coming) {
395				return;
396			}
397
398			if (F.ajaxLoad) {
399				F.ajaxLoad.abort();
400			}
401
402			F.ajaxLoad = null;
403
404			if (F.imgPreload) {
405				F.imgPreload.onload = F.imgPreload.onerror = null;
406			}
407
408			if (coming.wrap) {
409				coming.wrap.stop(true, true).trigger('onReset').remove();
410			}
411
412			F.coming = null;
413
414			// If the first item has been canceled, then clear everything
415			if (!F.current) {
416				F._afterZoomOut( coming );
417			}
418		},
419
420		// Start closing animation if is open; remove immediately if opening/closing
421		close: function (event) {
422			F.cancel();
423
424			if (false === F.trigger('beforeClose')) {
425				return;
426			}
427
428			F.unbindEvents();
429
430			if (!F.isActive) {
431				return;
432			}
433
434			if (!F.isOpen || event === true) {
435				$('.fancybox-wrap').stop(true).trigger('onReset').remove();
436
437				F._afterZoomOut();
438			}
439			else {
440				F.isOpen = F.isOpened = false;
441				F.isClosing = true;
442
443				$('.fancybox-item, .fancybox-nav').remove();
444
445				F.wrap.stop(true, true).removeClass('fancybox-opened');
446
447				F.transitions[ F.current.closeMethod ]();
448			}
449		},
450
451		// Manage slideshow:
452		//   $.fancybox.play(); - toggle slideshow
453		//   $.fancybox.play( true ); - start
454		//   $.fancybox.play( false ); - stop
455		play: function ( action ) {
456			var clear = function () {
457					clearTimeout(F.player.timer);
458				},
459				set = function () {
460					clear();
461
462					if (F.current && F.player.isActive) {
463						F.player.timer = setTimeout(F.next, F.current.playSpeed);
464					}
465				},
466				stop = function () {
467					clear();
468
469					D.off('.player');
470
471					F.player.isActive = false;
472
473					F.trigger('onPlayEnd');
474				},
475				start = function () {
476					if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
477						F.player.isActive = true;
478
479						D.on({
480							'onCancel.player beforeClose.player' : stop,
481							'onUpdate.player'   : set,
482							'beforeLoad.player' : clear
483						});
484
485						set();
486
487						F.trigger('onPlayStart');
488					}
489				};
490
491			if (action === true || (!F.player.isActive && action !== false)) {
492				start();
493			}
494			else {
495				stop();
496			}
497		},
498
499		// Navigate on mousewheel, swipe or drag
500		swipe: function ( deltaX, deltaY, threshold ) {
501			if ( deltaX > threshold || deltaY > threshold ) {
502				F.wrap.off('touchstart.fb touchmove.fb touchend.fb mouseup.fb mousedown.fb mousemove.fb mousewheel.fb');
503				F.next( deltaY > threshold ? 'up' : 'left' );
504			}
505			else if ( deltaX < -threshold || deltaY < -threshold ) {
506				F.wrap.off('touchstart.fb touchmove.fb touchend.fb mouseup.fb mousedown.fb mousemove.fb mousewheel.fb');
507				F.prev( deltaY < -threshold ? 'down' : 'right' );
508			}
509		},
510
511		// Navigate to next gallery item
512		next: function ( direction ) {
513			var current = F.current;
514
515			if (current) {
516				if (!isString(direction)) {
517					direction = current.direction.next;
518				}
519
520				F.jumpto(current.index + 1, direction, 'next');
521			}
522		},
523
524		// Navigate to previous gallery item
525		prev: function ( direction ) {
526			var current = F.current;
527
528			if (current) {
529				if (!isString(direction)) {
530					direction = current.direction.prev;
531				}
532
533				F.jumpto(current.index - 1, direction, 'prev');
534			}
535		},
536
537		// Navigate to gallery item by index
538		jumpto: function ( index, direction, router ) {
539			var current = F.current;
540
541			if (!current) {
542				return;
543			}
544
545			index = getScalar(index);
546
547			F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];
548			F.router    = router || 'jumpto';
549
550			if (current.loop) {
551				if (index < 0) {
552					index = current.group.length + (index % current.group.length);
553				}
554
555				index = index % current.group.length;
556			}
557
558			if (current.group[ index ] !== undefined) {
559				F.cancel();
560				F.isJumping = true;
561				F._start(index);
562			}
563		},
564
565		canScroll: function ( target ) {
566			let canScroll = false,
567			    parent = $(target);
568
569			while (parent.length) {
570				if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {
571					break;
572				}
573				canScroll = isScrollable( parent[0] );
574				parent    = $(parent).parent();
575			}
576
577			return canScroll;
578		},
579
580		// Center inside viewport and toggle position type to fixed or absolute if needed
581		reposition: function (e, onlyAbsolute) {
582			var current = F.current,
583				wrap    = current ? current.wrap : null,
584				pos;
585
586			if (wrap) {
587				pos = F._getPosition(onlyAbsolute);
588
589				if (e && e.type === 'scroll') {
590					delete pos.position;
591
592					wrap.stop(true, true).animate(pos, 200);
593				}
594				else {
595					wrap.css(pos);
596
597					current.pos = $.extend({}, current.dim, pos);
598				}
599			}
600		},
601
602		update: function (e) {
603			var type = (e && e.originalEvent && e.originalEvent.type),
604				anyway = !type || type === 'orientationchange';
605
606			if (anyway) {
607				clearTimeout(didUpdate);
608
609				didUpdate = null;
610			}
611
612			if (!F.isOpen || didUpdate) {
613				return;
614			}
615
616			didUpdate = setTimeout(function() {
617				var current = F.current;
618
619				if (!current || F.isClosing) {
620					return;
621				}
622
623				F.wrap.removeClass('fancybox-tmp');
624
625				if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) {
626					F._setDimension();
627				}
628
629				if (!(type === 'scroll' && current.canShrink)) {
630					F.reposition(e);
631				}
632
633				if (current.zoomClick) {
634					F.inner.css('cursor', current.canExpand ? 'zoom-in' : 'zoom-out');
635				}
636
637				F.trigger('onUpdate');
638
639				didUpdate = null;
640
641			}, (anyway && !isTouch ? 0 : 300));
642		},
643
644		// Shrink content to fit inside viewport or restore if resized
645		toggle: function ( action ) {
646			if (F.isOpen) {
647				F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
648
649				// Help browser to restore document dimensions
650				if (isTouch) {
651					F.wrap.removeAttr('style').addClass('fancybox-tmp');
652
653					F.trigger('onUpdate');
654				}
655
656				F.update();
657			}
658		},
659
660		hideLoading: function () {
661			D.off('.loading');
662
663			$('#fancybox-loading').remove();
664		},
665
666		showLoading: function () {
667			var el, viewport;
668
669			F.hideLoading();
670
671			el = $(F.opts.tpl.loading).on('click',F.cancel).appendTo('body');
672
673			// If user will press the escape-button, the request will be canceled
674			D.on('keydown.loading', function(e) {
675				if ((e.which || e.keyCode) === 27) {
676					F.cancel();
677
678					e.preventDefault();
679					return false;
680				}
681			});
682
683			if (!F.defaults.fixed) {
684				viewport = F.getViewport();
685
686				el.css({
687					position : 'absolute',
688					top  : (viewport.h * 0.5) + viewport.y,
689					left : (viewport.w * 0.5) + viewport.x
690				});
691			}
692
693			F.trigger('onLoading');
694		},
695
696		getViewport: function () {
697			var locked = (F.current && F.current.locked) || false,
698				rez    = {
699					x: W.scrollLeft(),
700					y: W.scrollTop()
701				};
702
703			if (locked && locked.length) {
704				rez.w = locked[0].clientWidth;
705				rez.h = locked[0].clientHeight;
706			}
707			else {
708				// See http://bugs.jquery.com/ticket/6724
709				rez.w = isTouch && window.innerWidth  ? window.innerWidth  : W.width();
710				rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();
711			}
712
713			return rez;
714		},
715
716		// Unbind the keyboard / clicking actions
717		unbindEvents: function () {
718			if (F.wrap && isQuery(F.wrap)) {
719				F.wrap.off('.fb');
720			}
721
722			D.off('.fb');
723			W.off('.fb');
724		},
725
726		bindEvents: function () {
727			var current = F.current,
728				keys;
729
730			if (!current) {
731				return;
732			}
733
734			// Changing document height on iOS devices triggers a 'resize' event,
735			// that can change document height... repeating infinitely
736			W.on('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
737
738			keys = current.keys;
739
740			if (keys) {
741				D.on('keydown.fb', function (e) {
742					var code   = e.which || e.keyCode,
743						target = e.target || e.srcElement;
744
745					// Skip esc key if loading, because showLoading will cancel preloading
746					if (code === 27 && F.coming) {
747						return false;
748					}
749
750					// Ignore key combinations and key events within form elements
751					if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
752						$.each(keys, function(i, val) {
753							if (current.group.length > 1 && val[ code ] !== undefined) {
754								F[ i ]( val[ code ] );
755
756								e.preventDefault();
757								return false;
758							}
759
760							if ($.inArray(code, val) > -1) {
761								F[ i ] ();
762
763								e.preventDefault();
764								return false;
765							}
766						});
767					}
768				});
769			}
770
771			if (current.group.length > 1) {
772				F.wrap.css('cursor','move');
773				F.wrap.on('mousedown.fb', function(e){
774					let drag = {};
775
776					e.preventDefault();
777
778					drag.startX = typeof e.clientX !== 'undefined' ? e.clientX : e.originalEvent.clientX;
779					drag.startY = typeof e.clientY !== 'undefined' ? e.clientY : e.originalEvent.clientY;
780
781					F.wrap.on('mousemove.fb',function(e) {
782						e.preventDefault();
783
784						drag.endX = typeof e.clientX !== 'undefined' ? e.clientX : e.originalEvent.clientX;
785						drag.endY = typeof e.clientY !== 'undefined' ? e.clientY : e.originalEvent.clientY;
786					});
787
788					F.wrap.on('mouseup.fb', function(){
789						F.wrap.off('mousemove.fb');
790						F.swipe(drag.startX - drag.endX, drag.startY - drag.endY, 100);
791					});
792				});
793
794				if (current.swipe) {
795					F.wrap.on('touchstart.fb', function(e){
796						let target  = e.target || null,
797							touch   = {},
798							fingers = typeof e.touches !== 'undefined' ? e.touches.length : e.originalEvent.touches.length;
799
800						if ( current.canShrink || fingers > 1 || F.canScroll( target ) ) {
801							return;
802						}
803
804						e.preventDefault();
805
806						touch.startX = typeof e.touches !== 'undefined' ? e.touches[0].clientX : e.originalEvent.touches[0].clientX;
807						touch.startY = typeof e.touches !== 'undefined' ? e.touches[0].clientY : e.originalEvent.touches[0].clientY;
808
809						F.wrap.on('touchmove.fb',function(e) {
810							fingers = typeof e.touches !== 'undefined' ? e.touches.length : e.originalEvent.touches.length;
811							if ( fingers > 1 ) {
812								return;
813							}
814							e.preventDefault();
815
816							let x  = typeof e.touches !== 'undefined' ? e.touches[0].clientX : e.originalEvent.touches[0].clientX,
817								y  = typeof e.touches !== 'undefined' ? e.touches[0].clientY : e.originalEvent.touches[0].clientY;
818
819							F.swipe(touch.startX - x, touch.startY - y, 100);
820						});
821					});
822					F.wrap.on('touchend.fb', function(){
823						F.wrap.off('touchmove.fb');
824					});
825				}
826
827				if ($.fn.mousewheel && current.mouseWheel) {
828					F.wrap.on('mousewheel.fb', function (e, delta, deltaX, deltaY) {
829						let target = e.target || null;
830
831						if (current.canShrink || delta === 0 || F.canScroll(target)) {
832							return;
833						}
834
835						e.preventDefault();
836
837						F.swipe(-deltaX, -deltaY, 0);
838					});
839				}
840			}
841		},
842
843		trigger: function (event, o) {
844			var ret, obj = o || F.coming || F.current;
845
846			if (obj) {
847				if ($.isFunction( obj[event] )) {
848					ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
849				}
850
851				if (ret === false) {
852					return false;
vendor: 28,838 bytes, lines 853-2002
853				}
854
855				if (obj.helpers) {
856					$.each(obj.helpers, function (helper, opts) {
857						if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {
858							F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);
859						}
860					});
861				}
862			}
863
864			D.trigger(event);
865		},
866
867		isImage: function (str) {
868			return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
869		},
870
871		isSVG: function (str) {
872			return isString(str) && str.match(/\.(svg)((\?|#).*)?$/i);
873		},
874
875		_start: function (index) {
876			var coming = {},
877				obj,
878				href,
879				type,
880				margin,
881				padding;
882
883			index = getScalar( index );
884			obj   = F.group[ index ] || null;
885
886			if (!obj) {
887				return false;
888			}
889
890			coming = $.extend(true, {}, F.opts, obj);
891
892			// Convert margin and padding properties to array - top, right, bottom, left
893			margin  = coming.margin;
894			padding = coming.padding;
895
896			if ($.type(margin) === 'number') {
897				coming.margin = [margin, margin, margin, margin];
898			}
899
900			if ($.type(padding) === 'number') {
901				coming.padding = [padding, padding, padding, padding];
902			}
903
904			// 'modal' propery is just a shortcut
905			if (coming.modal) {
906				$.extend(true, coming, {
907					closeBtn   : false,
908					closeClick : false,
909					nextClick  : false,
910					zoomClick  : false,
911					arrows     : false,
912					mouseWheel : false,
913					keys       : null,
914					helpers: {
915						overlay : {
916							closeClick : false
917						}
918					}
919				});
920			}
921
922			// 'autoSize' property is a shortcut, too
923			if (coming.autoSize) {
924				coming.autoWidth = coming.autoHeight = true;
925			}
926
927			if (coming.width === 'auto') {
928				coming.autoWidth = true;
929			}
930
931			if (coming.height === 'auto') {
932				coming.autoHeight = true;
933			}
934
935			/*
936			 * Add reference to the group, so it`s possible to access from callbacks, example:
937			 * afterLoad : function() {
938			 *     this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
939			 * }
940			 */
941
942			coming.group  = F.group;
943			coming.index  = index;
944
945			// Give a chance for callback or helpers to update coming item (type, title, etc)
946			F.coming = coming;
947
948			if (false === F.trigger('beforeLoad')) {
949				F.coming = null;
950
951				return;
952			}
953
954			type = coming.type;
955			href = coming.href;
956
957			if (!type) {
958				F.coming = null;
959
960				//If we can not determine content type then drop silently or display next/prev item if looping through gallery
961				if (F.current && F.router && F.router !== 'jumpto') {
962					F.current.index = index;
963
964					return F[ F.router ]( F.direction );
965				}
966
967				return false;
968			}
969
970			F.isActive = true;
971
972			if (type === 'image' || type === 'svg') {
973				coming.autoHeight = coming.autoWidth = false;
974				coming.scrolling  = 'visible';
975				coming.aspectRatio = true;
976			}
977
978			if (type === 'iframe' && isTouch) {
979				coming.scrolling = 'scroll';
980			}
981
982			// Build the neccessary markup
983			coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' );
984
985			$.extend(coming, {
986				skin  : $('.fancybox-skin',  coming.wrap),
987				outer : $('.fancybox-outer', coming.wrap),
988				inner : $('.fancybox-inner', coming.wrap)
989			});
990
991			$.each(["Top", "Right", "Bottom", "Left"], function(i, v) {
992				coming.skin.css('padding' + v, getValue(coming.padding[ i ]));
993			});
994
995			F.trigger('onReady');
996
997			// Check before try to load; 'inline' and 'html' types need content, others - href
998			if (type === 'inline' || type === 'html') {
999				if (!coming.content || !coming.content.length) {
1000					return F._error( 'content' );
1001				}
1002			}
1003			else if (!href) {
1004				return F._error( 'href' );
1005			}
1006
1007			if (type === 'image') {
1008				F._loadImage();
1009			}
1010			else if (type === 'ajax') {
1011				F._loadAjax();
1012			}
1013			else if (type === 'iframe') {
1014				F._loadIframe();
1015			}
1016			else {
1017				F._afterLoad();
1018			}
1019		},
1020
1021		_error: function ( type ) {
1022			let msg = F.coming.txt.error[type] || F.coming.txt.error['content'];
1023			if( arguments.length > 1 ) {
1024				msg = msg + '<br/><br/>' + arguments[1];
1025			}
1026			$.extend(F.coming, {
1027				type       : 'html',
1028				autoWidth  : true,
1029				autoHeight : true,
1030				minWidth   : 0,
1031				minHeight  : 0,
1032				scrolling  : 'no',
1033				content    : F.coming.tpl.error.replace(/\{error\}/g, msg)
1034			});
1035
1036			F._afterLoad();
1037		},
1038
1039		_loadImage: function () {
1040			// Reset preload image so it is later possible to check "complete" property
1041			var img = F.imgPreload = new Image();
1042
1043			img.onload = function () {
1044				this.onload = this.onerror = null;
1045
1046				F.coming.width  = this.width / F.opts.pixelRatio;
1047				F.coming.height = this.height / F.opts.pixelRatio;
1048
1049				F._afterLoad();
1050			};
1051
1052			img.onerror = function () {
1053				this.onload = this.onerror = null;
1054
1055				F._error( 'image' );
1056			};
1057
1058			img.src = F.coming.href;
1059
1060			if (img.complete !== true) {
1061				F.showLoading();
1062			}
1063		},
1064
1065		_loadAjax: function () {
1066			var coming = F.coming;
1067
1068			F.showLoading();
1069
1070			F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
1071				url: coming.href,
1072				error: function (jqXHR, textStatus) {
1073					if (F.coming && textStatus !== 'abort') {
1074						F._error( 'ajax', jqXHR );
1075					}
1076					else {
1077						F.hideLoading();
1078					}
1079				},
1080				success: function (data, textStatus) {
1081					if (textStatus === 'success') {
1082						coming.content = data;
1083
1084						F._afterLoad();
1085					}
1086				}
1087			}));
1088		},
1089
1090		_loadIframe: function() {
1091			var coming = F.coming,
1092				iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))
1093					.attr({
1094						'scrolling' : (isTouch ? 'auto' : coming.iframe.scrolling),
1095					    'src' : coming.href,
1096						'webkitallowfullscreen' : coming.iframe.allowfullscreen,
1097						'mozallowfullscreen' : coming.iframe.allowfullscreen,
1098						'allowfullscreen' : coming.iframe.allowfullscreen
1099					});
1100
1101			// This helps IE
1102			$(coming.wrap).on('onReset', function () {
1103				try {
1104					$(this).find('iframe').hide().attr('src', '//about:blank').end().empty();
1105				} catch (e) {}
1106			});
1107
1108			if (coming.iframe.preload) {
1109				F.showLoading();
1110
1111				iframe.one('load', function() {
1112					$(this).data('ready', 1);
1113
1114					// iOS will lose scrolling if we resize
1115					if (!isTouch) {
1116						$(this).on('load.fb', F.update);
1117					}
1118
1119					// Without this trick:
1120					//   - iframe won't scroll on iOS devices
1121					//   - IE7 sometimes displays empty iframe
1122					$(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();
1123
1124					F._afterLoad();
1125				});
1126			}
1127
1128			coming.content = iframe.appendTo( coming.inner );
1129
1130			if (!coming.iframe.preload) {
1131				F._afterLoad();
1132			}
1133		},
1134
1135		_preloadImages: function() {
1136			var group   = F.group,
1137				current = F.current,
1138				len     = group.length,
1139				cnt     = current.preload ? Math.min(current.preload, len - 1) : 0,
1140				item,
1141				i;
1142
1143			for (i = 1; i <= cnt; i += 1) {
1144				item = group[ (current.index + i ) % len ];
1145
1146				if (item.type === 'image' && item.href) {
1147					new Image().src = item.href;
1148				}
1149			}
1150		},
1151
1152		_afterLoad: function () {
1153			var coming   = F.coming,
1154				previous = F.current,
1155				placeholder = 'fancybox-placeholder',
1156				current,
1157				content,
1158				type,
1159				scrolling,
1160				href,
1161				embed;
1162
1163			F.hideLoading();
1164
1165			if (!coming || F.isActive === false) {
1166				return;
1167			}
1168
1169			if (false === F.trigger('afterLoad', coming, previous)) {
1170				coming.wrap.stop(true).trigger('onReset').remove();
1171
1172				F.coming = null;
1173
1174				return;
1175			}
1176
1177			if (previous) {
1178				F.trigger('beforeChange', previous);
1179
1180				previous.wrap.stop(true).removeClass('fancybox-opened')
1181					.find('.fancybox-item, .fancybox-nav')
1182					.remove();
1183			}
1184
1185			F.unbindEvents();
1186
1187			current   = coming;
1188			content   = coming.content;
1189			type      = coming.type;
1190			scrolling = coming.scrolling;
1191
1192			$.extend(F, {
1193				wrap  : current.wrap,
1194				skin  : current.skin,
1195				outer : current.outer,
1196				inner : current.inner,
1197				current  : current,
1198				previous : previous
1199			});
1200
1201			href = current.href;
1202
1203			switch (type) {
1204				case 'image':
1205					// Build the <img> via DOM APIs and set src with .attr() so an entity-decoded
1206					// href cannot break out of the src="{href}" attribute (also covers auto-detected
1207					// SVG, which is routed through isImage()).
1208					content = $( current.tpl.image.replace(/\{href\}/g, '') ).attr('src', href);
1209				break;
1210
1211				case 'svg':
1212					content = $('<object/>', {
1213						type   : 'image/svg+xml',
1214						width  : '100%',
1215						height : '100%'
1216					}).attr('data', href);
1217				break;
1218
1219				case 'inline':
1220				case 'ajax':
1221				case 'html':
1222					if (current.selector) {
1223						content = $('<div>').html(content).find(current.selector);
1224					}
1225					else if (isQuery(content)) {
1226						if (!content.data(placeholder)) {
1227							content.data(placeholder, content.clone().removeAttr('id').addClass(placeholder).insertAfter( content ) );
1228						}
1229
1230						content = content.detach();
1231
1232						current.wrap.on('onReset', function () {
1233							if ($(this).find(content).length) {
1234								content.replaceAll( content.data(placeholder) ).data(placeholder, false);
1235							}
1236						});
1237					}
1238				break;
1239			}
1240
1241			if (!(isQuery(content) && content.parent().is(current.inner))) {
1242				current.inner.append( content );
1243			}
1244
1245			// Give a chance for helpers or callbacks to update elements
1246			F.trigger('beforeShow');
1247
1248			// Set scrolling before calculating dimensions
1249			current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));
1250
1251			// Set initial dimensions and start position
1252			F._setDimension();
1253
1254			F.reposition();
1255
1256			F.isOpen = false;
1257			F.coming = null;
1258
1259			F.bindEvents();
1260
1261			if (!F.isOpened) {
1262				$('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();
1263			}
1264			else if (previous.prevMethod) {
1265				F.transitions[ previous.prevMethod ]();
1266			}
1267
1268			F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();
1269
1270			F._preloadImages();
1271		},
1272
1273		_setDimension: function () {
1274			var viewport   = F.getViewport(),
1275				steps      = 0,
1276				canShrink  = false,
1277				canExpand  = false,
1278				wrap       = F.wrap,
1279				skin       = F.skin,
1280				inner      = F.inner,
1281				current    = F.current,
1282				width      = current.width,
1283				height     = current.height,
1284				minWidth   = current.minWidth,
1285				minHeight  = current.minHeight,
1286				maxWidth   = current.maxWidth,
1287				maxHeight  = current.maxHeight,
1288				scrolling  = current.scrolling,
1289				scrollOut  = current.scrollOutside ? current.scrollbarWidth : 0,
1290				margin     = current.margin,
1291				wMargin    = getScalar(margin[1] + margin[3]),
1292				hMargin    = getScalar(margin[0] + margin[2]),
1293				wPadding,
1294				hPadding,
1295				wSpace,
1296				hSpace,
1297				origWidth,
1298				origHeight,
1299				origMaxWidth,
1300				origMaxHeight,
1301				ratio,
1302				width_,
1303				height_,
1304				maxWidth_,
1305				maxHeight_,
1306				iframe,
1307				body;
1308
1309			// Reset dimensions so we could re-check actual size
1310			wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp');
1311
1312			wPadding = getScalar(skin.outerWidth(true)  - skin.width());
1313			hPadding = getScalar(skin.outerHeight(true) - skin.height());
1314
1315			// Any space between content and viewport (margin, padding, border, title)
1316			wSpace = wMargin + wPadding;
1317			hSpace = hMargin + hPadding;
1318
1319			origWidth  = isPercentage(width)  ? (viewport.w - wSpace) * getScalar(width)  / 100 : width;
1320			origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;
1321
1322			if (current.type === 'iframe') {
1323				iframe = current.content;
1324
1325				if (current.autoHeight && iframe && iframe.data('ready') === 1) {
1326					try {
1327						if (iframe[0].contentWindow.document.location) {
1328							inner.width( origWidth ).height(9999);
1329
1330							body = iframe.contents().find('body');
1331
1332							if (scrollOut) {
1333								body.css('overflow-x', 'hidden');
1334							}
1335
1336							origHeight = body.outerHeight(true);
1337						}
1338
1339					} catch (e) {}
1340				}
1341			}
1342			else if (current.autoWidth || current.autoHeight) {
1343				inner.addClass( 'fancybox-tmp' );
1344
1345				// Set width or height in case we need to calculate only one dimension
1346				if (!current.autoWidth) {
1347					inner.width( origWidth );
1348				}
1349
1350				if (!current.autoHeight) {
1351					inner.height( origHeight );
1352				}
1353
1354				if (current.autoWidth) {
1355					origWidth = inner.width();
1356				}
1357
1358				if (current.autoHeight) {
1359					origHeight = inner.height();
1360				}
1361
1362				inner.removeClass( 'fancybox-tmp' );
1363			}
1364
1365			width  = getScalar( origWidth );
1366			height = getScalar( origHeight );
1367
1368			ratio  = origWidth / origHeight;
1369
1370			// Calculations for the content
1371			minWidth  = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);
1372			maxWidth  = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);
1373
1374			minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);
1375			maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);
1376
1377			// These will be used to determine if wrap can fit in the viewport
1378			origMaxWidth  = maxWidth;
1379			origMaxHeight = maxHeight;
1380
1381			if (current.fitToView) {
1382				maxWidth  = Math.min(viewport.w - wSpace, maxWidth);
1383				maxHeight = Math.min(viewport.h - hSpace, maxHeight);
1384			}
1385
1386			maxWidth_  = viewport.w - wMargin;
1387			maxHeight_ = viewport.h - hMargin;
1388
1389			if (current.aspectRatio) {
1390				if (width > maxWidth) {
1391					width  = maxWidth;
1392					height = getScalar(width / ratio);
1393				}
1394
1395				if (height > maxHeight) {
1396					height = maxHeight;
1397					width  = getScalar(height * ratio);
1398				}
1399
1400				if (width < minWidth) {
1401					width  = minWidth;
1402					height = getScalar(width / ratio);
1403				}
1404
1405				if (height < minHeight) {
1406					height = minHeight;
1407					width  = getScalar(height * ratio);
1408				}
1409			}
1410			else {
1411				width = Math.max(minWidth, Math.min(width, maxWidth));
1412
1413				if (current.autoHeight && current.type !== 'iframe') {
1414					inner.width( width );
1415
1416					height = inner.height();
1417				}
1418
1419				height = Math.max(minHeight, Math.min(height, maxHeight));
1420			}
1421
1422			// Try to fit inside viewport (including the title)
1423			if (current.fitToView) {
1424				inner.width( width ).height( height );
1425
1426				wrap.width( width + wPadding );
1427
1428				// Real wrap dimensions
1429				width_  = wrap.width();
1430				height_ = wrap.height();
1431
1432				if (current.aspectRatio) {
1433					while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
1434						if (steps++ > 19) {
1435							break;
1436						}
1437
1438						height = Math.max(minHeight, Math.min(maxHeight, height - 10));
1439						width  = getScalar(height * ratio);
1440
1441						if (width < minWidth) {
1442							width  = minWidth;
1443							height = getScalar(width / ratio);
1444						}
1445
1446						if (width > maxWidth) {
1447							width  = maxWidth;
1448							height = getScalar(width / ratio);
1449						}
1450
1451						inner.width( width ).height( height );
1452
1453						wrap.width( width + wPadding );
1454
1455						width_  = wrap.width();
1456						height_ = wrap.height();
1457					}
1458				}
1459				else {
1460					width  = Math.max(minWidth,  Math.min(width,  width  - (width_  - maxWidth_)));
1461					height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));
1462				}
1463			}
1464
1465			if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {
1466				width += scrollOut;
1467			}
1468
1469			inner.width( width ).height( height );
1470
1471			wrap.width( width + wPadding );
1472
1473			width_  = wrap.width();
1474			height_ = wrap.height();
1475
1476			canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
1477			canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));
1478
1479			$.extend(current, {
1480				dim : {
1481					width	: getValue( width_ ),
1482					height	: getValue( height_ )
1483				},
1484				origWidth  : origWidth,
1485				origHeight : origHeight,
1486				canShrink  : canShrink,
1487				canExpand  : canExpand,
1488				wPadding   : wPadding,
1489				hPadding   : hPadding,
1490				wrapSpace  : height_ - skin.outerHeight(true),
1491				skinSpace  : skin.height() - height
1492			});
1493
1494			if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
1495				inner.height('auto');
1496			}
1497		},
1498
1499		_getPosition: function (onlyAbsolute) {
1500			var current  = F.current,
1501				viewport = F.getViewport(),
1502				margin   = current.margin,
1503				width    = F.wrap.width()  + margin[1] + margin[3],
1504				height   = F.wrap.height() + margin[0] + margin[2],
1505				rez      = {
1506					position: 'absolute',
1507					top  : margin[0],
1508					left : margin[3]
1509				};
1510
1511			if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {
1512				rez.position = 'fixed';
1513			}
1514			else if (!current.locked) {
1515				rez.top  += viewport.y;
1516				rez.left += viewport.x;
1517			}
1518
1519			rez.top  = getValue(Math.max(rez.top,  rez.top  + ((viewport.h - height) * current.topRatio)));
1520			rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width)  * current.leftRatio)));
1521
1522			return rez;
1523		},
1524
1525		_afterZoomIn: function () {
1526			var current = F.current;
1527
1528			if (!current) {
1529				return;
1530			}
1531
1532			F.isOpen = F.isOpened = true;
1533
1534			F.wrap.css('overflow', 'visible').addClass('fancybox-opened').hide().show(0);
1535
1536			F.update();
1537
1538			// Assign a click event
1539			if ( current.zoomClick || current.closeClick || (current.nextClick && F.group.length > 1) ) {
1540				F.inner.css('cursor', !current.zoomClick ? 'pointer' : (current.canExpand ? 'zoom-in' : 'zoom-out')).on('click.fb', function(e) {
1541					if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {
1542						e.preventDefault();
1543
1544						F[ current.zoomClick && (current.canExpand || current.canShrink) ? 'toggle' : ( current.closeClick ? 'close' : 'next' ) ]();
1545					}
1546				});
1547			}
1548
1549			// Create a close button
1550			if (current.closeBtn) {
1551				$(current.tpl.close.replace(/\{close\}/g, current.txt.close)).appendTo(F.skin).on('click.fb touchend', function(e) {
1552					e.preventDefault();
1553					F.close();
1554				});
1555			}
1556
1557			// Create navigation arrows
1558			if (current.arrows && F.group.length > 1) {
1559				if (current.loop || current.index > 0) {
1560					$(current.tpl.prev.replace(/\{prev\}/g, current.txt.prev)).appendTo(F.outer).on('click.fb touchend', F.prev);
1561				}
1562
1563				if (current.loop || current.index < F.group.length - 1) {
1564					$(current.tpl.next.replace(/\{next\}/g, current.txt.next)).appendTo(F.outer).on('click.fb touchend', F.next);
1565				}
1566			}
1567
1568			F.trigger('afterShow');
1569
1570			// Stop the slideshow if this is the last item
1571			if (!current.loop && current.index === current.group.length - 1) {
1572
1573				F.play( false );
1574			}
1575			else if (F.opts.autoPlay && !F.player.isActive) {
1576				F.opts.autoPlay = false;
1577
1578				F.play(true);
1579			}
1580		},
1581
1582		_afterZoomOut: function ( obj ) {
1583			obj = obj || F.current;
1584
1585			$('.fancybox-wrap').trigger('onReset').remove();
1586
1587			$.extend(F, {
1588				group  : {},
1589				opts   : {},
1590				router : false,
1591				current   : null,
1592				isActive  : false,
1593				isOpened  : false,
1594				isOpen    : false,
1595				isClosing : false,
1596				wrap   : null,
1597				skin   : null,
1598				outer  : null,
1599				inner  : null
1600			});
1601
1602			F.trigger('afterClose', obj);
1603		}
1604	});
1605
1606	/*
1607	 *	Default transitions
1608	 */
1609
1610	F.transitions = {
1611		getOrigPosition: function () {
1612			var current  = F.current,
1613				element  = current.element,
1614				orig     = current.orig,
1615				pos      = {},
1616				width    = 50,
1617				height   = 50,
1618				hPadding = current.hPadding,
1619				wPadding = current.wPadding,
1620				viewport = F.getViewport();
1621
1622			if (!orig && current.isDom && element.is(':visible')) {
1623				orig = element.find('img:first');
1624
1625				if (!orig.length) {
1626					orig = element;
1627				}
1628			}
1629
1630			if (isQuery(orig)) {
1631				pos = orig.offset();
1632
1633				if (orig.is('img')) {
1634					width  = orig.outerWidth();
1635					height = orig.outerHeight();
1636				}
1637			}
1638			else {
1639				pos.top  = viewport.y + (viewport.h - height) * current.topRatio;
1640				pos.left = viewport.x + (viewport.w - width)  * current.leftRatio;
1641			}
1642
1643			if (F.wrap.css('position') === 'fixed' || current.locked) {
1644				pos.top  -= viewport.y;
1645				pos.left -= viewport.x;
1646			}
1647
1648			pos = {
1649				top     : getValue(pos.top  - hPadding * current.topRatio),
1650				left    : getValue(pos.left - wPadding * current.leftRatio),
1651				width   : getValue(width  + wPadding),
1652				height  : getValue(height + hPadding)
1653			};
1654
1655			return pos;
1656		},
1657
1658		step: function (now, fx) {
1659			var ratio,
1660				padding,
1661				value,
1662				prop       = fx.prop,
1663				current    = F.current,
1664				wrapSpace  = current.wrapSpace,
1665				skinSpace  = current.skinSpace;
1666
1667			if (prop === 'width' || prop === 'height') {
1668				ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);
1669
1670				if (F.isClosing) {
1671					ratio = 1 - ratio;
1672				}
1673
1674				padding = prop === 'width' ? current.wPadding : current.hPadding;
1675				value   = now - padding;
1676
1677				F.skin[ prop ](  getScalar( prop === 'width' ?  value : value - (wrapSpace * ratio) ) );
1678				F.inner[ prop ]( getScalar( prop === 'width' ?  value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );
1679			}
1680		},
1681
1682		zoomIn: function () {
1683			var current  = F.current,
1684				startPos = current.pos,
1685				effect   = current.openEffect,
1686				elastic  = effect === 'elastic',
1687				endPos   = $.extend({opacity : 1}, startPos);
1688
1689			// Remove "position" property that breaks older IE
1690			delete endPos.position;
1691
1692			if (elastic) {
1693				startPos = this.getOrigPosition();
1694
1695				if (current.openOpacity) {
1696					startPos.opacity = 0.1;
1697				}
1698			}
1699			else if (effect === 'fade') {
1700				startPos.opacity = 0.1;
1701			}
1702
1703			F.wrap.css(startPos).animate(endPos, {
1704				duration : effect === 'none' ? 0 : current.openSpeed,
1705				easing   : current.openEasing,
1706				step     : elastic ? this.step : null,
1707				complete : F._afterZoomIn
1708			});
1709		},
1710
1711		zoomOut: function () {
1712			var current  = F.current,
1713				effect   = current.closeEffect,
1714				elastic  = effect === 'elastic',
1715				endPos   = {opacity : 0.1};
1716
1717			if (elastic) {
1718				endPos = this.getOrigPosition();
1719
1720				if (current.closeOpacity) {
1721					endPos.opacity = 0.1;
1722				}
1723			}
1724
1725			F.wrap.animate(endPos, {
1726				duration : effect === 'none' ? 0 : current.closeSpeed,
1727				easing   : current.closeEasing,
1728				step     : elastic ? this.step : null,
1729				complete : F._afterZoomOut
1730			});
1731		},
1732
1733		changeIn: function () {
1734			var current   = F.current,
1735				effect    = current.nextEffect,
1736				startPos  = current.pos,
1737				endPos    = { opacity : 1 },
1738				direction = F.direction,
1739				distance  = 200,
1740				field;
1741
1742			startPos.opacity = 0.1;
1743
1744			if (effect === 'elastic') {
1745				field = direction === 'down' || direction === 'up' ? 'top' : 'left';
1746
1747				if (direction === 'down' || direction === 'right') {
1748					startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);
1749					endPos[ field ]   = '+=' + distance + 'px';
1750				}
1751				else {
1752					startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);
1753					endPos[ field ]   = '-=' + distance + 'px';
1754				}
1755			}
1756
1757			// Workaround for http://bugs.jquery.com/ticket/12273
1758			if (effect === 'none') {
1759				F._afterZoomIn();
1760			}
1761			else {
1762				F.wrap.css(startPos).animate(endPos, {
1763					duration : current.nextSpeed,
1764					easing   : current.nextEasing,
1765					complete : F._afterZoomIn
1766				});
1767			}
1768		},
1769
1770		changeOut: function () {
1771			var previous  = F.previous,
1772				effect    = previous.prevEffect,
1773				endPos    = { opacity : 0.1 },
1774				direction = F.direction,
1775				distance  = 200;
1776
1777			if (effect === 'elastic') {
1778				endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';
1779			}
1780
1781			previous.wrap.animate(endPos, {
1782				duration : effect === 'none' ? 0 : previous.prevSpeed,
1783				easing   : previous.prevEasing,
1784				complete : function () {
1785					$(this).trigger('onReset').remove();
1786				}
1787			});
1788		}
1789	};
1790
1791	/*
1792	 *	Overlay helper
1793	 */
1794
1795	F.helpers.overlay = {
1796		defaults : {
1797			closeClick : true,      // if true, fancyBox will be closed when user clicks on the overlay
1798			speedOut   : 200,       // duration of fadeOut animation
1799			showEarly  : true,      // indicates if should be opened immediately or wait until the content is ready
1800			css        : {},        // custom CSS properties
1801			locked     : !isTouch,  // if true, the content will be locked into overlay
1802			fixed      : true       // if false, the overlay CSS position property will not be set to "fixed"
1803		},
1804
1805		overlay : null,      // current handle
1806		fixed   : false,     // indicates if the overlay has position "fixed"
1807		el      : $('html'), // element that contains "the lock"
1808
1809		// Public methods
1810		create : function(opts) {
1811			var parent;
1812
1813			opts = $.extend({}, this.defaults, opts);
1814
1815			if (this.overlay) {
1816				this.close();
1817			}
1818
1819			parent = F.coming ? F.coming.parent : opts.parent;
1820
1821			this.overlay = $('<div class="fancybox-overlay"></div>').appendTo( parent && parent.length ? parent : 'body' );
1822			this.fixed   = false;
1823
1824			if (opts.fixed && F.defaults.fixed) {
1825				this.overlay.addClass('fancybox-overlay-fixed');
1826
1827				this.fixed = true;
1828			}
1829		},
1830
1831		open : function(opts) {
1832			var that = this;
1833
1834			opts = $.extend({}, this.defaults, opts);
1835
1836			if (this.overlay) {
1837				this.overlay.off('.overlay').width('auto').height('auto');
1838			}
1839			else {
1840				this.create(opts);
1841			}
1842
1843			if (!this.fixed) {
1844				W.on('resize.overlay', $.proxy( this.update, this) );
1845
1846				this.update();
1847			}
1848
1849			if (opts.closeClick) {
1850				this.overlay.on('click.overlay', function(e) {
1851					if ($(e.target).hasClass('fancybox-overlay')) {
1852						if (F.isActive) {
1853							F.close();
1854						}
1855						else {
1856							that.close();
1857						}
1858						return false;
1859					}
1860				});
1861			}
1862
1863			this.overlay.css( opts.css ).show();
1864		},
1865
1866		close : function() {
1867			W.off('resize.overlay');
1868
1869			if (this.el.hasClass('fancybox-lock')) {
1870				$('.fancybox-margin').removeClass('fancybox-margin');
1871
1872				this.el.removeClass('fancybox-lock');
1873
1874				W.scrollTop( this.scrollV ).scrollLeft( this.scrollH );
1875			}
1876
1877			$('.fancybox-overlay').remove().hide();
1878
1879			$.extend(this, {
1880				overlay : null,
1881				fixed   : false
1882			});
1883		},
1884
1885		// Private, callbacks
1886
1887		update : function () {
1888			var width = '100%', offsetWidth;
1889
1890			// Reset width/height so it will not mess
1891			this.overlay.width(width).height('100%');
1892
1893			// jQuery does not return reliable result for IE
1894			if (IE) {
1895				offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
1896
1897				if (D.width() > offsetWidth) {
1898					width = D.width();
1899				}
1900			}
1901			else if (D.width() > W.width()) {
1902				width = D.width();
1903			}
1904
1905			this.overlay.width(width).height(D.height());
1906		},
1907
1908		// This is where we can manipulate DOM, because later it would cause iframes to reload
1909		onReady : function (opts, obj) {
1910			var overlay = this.overlay;
1911
1912			$('.fancybox-overlay').stop(true, true);
1913
1914			if (!overlay) {
1915				this.create(opts);
1916			}
1917
1918			if (opts.locked && this.fixed && obj.fixed) {
1919				obj.locked = this.overlay.append( obj.wrap );
1920				obj.fixed  = false;
1921			}
1922
1923			if (opts.showEarly === true) {
1924				this.beforeShow.apply(this, arguments);
1925			}
1926		},
1927
1928		beforeShow : function(opts, obj) {
1929			if (obj.locked && !this.el.hasClass('fancybox-lock')) {
1930				if (this.fixPosition !== false) {
1931					$('*:not(object)').filter(function(){
1932						return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") );
1933					}).addClass('fancybox-margin');
1934				}
1935
1936				this.el.addClass('fancybox-margin');
1937
1938				this.scrollV = W.scrollTop();
1939				this.scrollH = W.scrollLeft();
1940
1941				this.el.addClass('fancybox-lock');
1942
1943				W.scrollTop( this.scrollV ).scrollLeft( this.scrollH );
1944			}
1945
1946			this.open(opts);
1947		},
1948
1949		// afterShow: function (opts) {
1950		// 	// Prevent background scrolling.
1951		// 	$("html, body").css("overflow","hidden");
1952		// },
1953
1954		onUpdate : function() {
1955			if (!this.fixed) {
1956				this.update();
1957			}
1958		},
1959
1960		afterClose: function (opts) {
1961			// Undo prevent background scrolling.
1962			// $("html, body").css("overflow","auto");
1963			// Remove overlay if exists and fancyBox is not opening
1964			// (e.g., it is not being open using afterClose callback)
1965			if (this.overlay && !F.coming) {
1966				this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this ));
1967			}
1968		}
1969	};
1970
1971	/*
1972	 *	Title helper
1973	 */
1974
1975	F.helpers.title = {
1976		defaults : {
1977			type     : 'float', // 'float', 'inside', 'outside' or 'over',
1978			position : 'bottom' // 'top' or 'bottom'
1979		},
1980
1981		beforeShow: function (opts) {
1982			var current = F.current,
1983				text    = current.title,
1984				type    = opts.type,
1985				title,
1986				target;
1987
1988			if ($.isFunction(text)) {
1989				text = text.call(current.element, current);
1990			}
1991
1992			if (!isString(text) || $.trim(text) === '') {
1993				return;
1994			}
1995
1996			title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">' + DOMPurify.sanitize(text) + '</div>');
1997
1998			switch (type) {
1999				case 'inside':
2000					target = F.skin;
2001				break;
2002
vendor: 3,314 bytes, lines 2003-2131
2003				case 'outside':
2004					target = F.wrap;
2005				break;
2006
2007				case 'over':
2008					target = F.inner;
2009				break;
2010
2011				default: // 'float'
2012					target = F.skin;
2013
2014					title.appendTo('body');
2015
2016					if (IE) {
2017						title.width( title.width() );
2018					}
2019
2020					title.wrapInner('<span class="child"></span>');
2021
2022					//Increase bottom margin so this title will also fit into viewport
2023					F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );
2024				break;
2025			}
2026
2027			title[ (opts.position === 'top' ? 'prependTo'  : 'appendTo') ](target);
2028		}
2029	};
2030
2031	// jQuery plugin initialization
2032	$.fn.fancybox = function (options) {
2033		var index,
2034			that     = $(this),
2035			selector = this.selector || '',
2036			run      = function(e) {
2037				var what = $(this).blur(), idx = index, relType, relVal;
2038
2039				if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {
2040					relType = options.groupAttr || 'data-fancybox-group';
2041					relVal  = what.attr(relType);
2042
2043					if (!relVal) {
2044						relType = 'rel';
2045						relVal  = what.get(0)[ relType ];
2046					}
2047
2048					if (relVal && relVal !== '' && relVal !== 'nofollow') {
2049						what = selector.length ? $(selector) : that;
2050						what = what.filter('[' + relType + '="' + relVal + '"]');
2051						idx  = what.index(this);
2052					}
2053
2054					options.index = idx;
2055
2056					// Abort if not enough screen space
2057					var viewport = F.getViewport();
2058					if ( (options.minVpWidth && viewport.w < options.minVpWidth) || (options.minVpHeight && viewport.h < options.minVpHeight) ) {
2059						return;
2060					}
2061
2062					// Stop an event from bubbling if everything is fine
2063					if (F.open(what, options) !== false) {
2064						e.preventDefault();
2065						return false;
2066					}
2067				}
2068			};
2069
2070		options = options || {};
2071		index   = options.index || 0;
2072
2073		if (!selector || options.live === false) {
2074			that.off('click.fb-start').on('click.fb-start', run);
2075		}
2076		else {
2077			D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
2078		}
2079
2080		this.filter('[data-fancybox-start=1]').trigger('click');
2081
2082		return this;
2083	};
2084
2085	// Tests that need a body at doc ready
2086	D.ready(function() {
2087		var w1, w2;
2088
2089		if ( $.scrollbarWidth === undefined ) {
2090			// http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth
2091			$.scrollbarWidth = function() {
2092				var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),
2093					child  = parent.children(),
2094					width  = child.innerWidth() - child.height( 99 ).innerWidth();
2095
2096				parent.remove();
2097
2098				return width;
2099			};
2100		}
2101
2102		if ( $.support.fixedPosition === undefined ) {
2103			$.support.fixedPosition = (function() {
2104				var elem  = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'),
2105					fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );
2106
2107				elem.remove();
2108
2109				return fixed;
2110			}());
2111		}
2112
2113		$.extend(F.defaults, {
2114			scrollbarWidth : $.scrollbarWidth(),
2115			fixed  : $.support.fixedPosition,
2116			parent : $('body')
2117		});
2118
2119		//Get real width of page scroll-bar
2120		w1 = $(window).width();
2121
2122		H.addClass('fancybox-lock-test');
2123
2124		w2 = $(window).width();
2125
2126		H.removeClass('fancybox-lock-test');
2127
2128		$("<style type='text/css'>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head");
2129	});
2130
2131}(window, document, 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.