PageSourceSearch

https://www.astoria-luzern.ch/global/js/jquery.fancybox.pack.js

js astoria-luzern.ch collected 2026-10-04 19:13:22 UTC 56,179 bytes, 2,378 lines download raw bytes

1/*!
2 * fancyBox - jQuery Plugin
3 * version: 3.0.0 Beta 1 (Tue, 29 Jan 2013)
4 * @requires jQuery v1.7 or later
5 *
6 * Examples at http://fancyapps.com/fancybox/
7 * License: www.fancyapps.com/fancybox/#license
8 *
9 * Copyright 2013 Janis Skarnelis - [email protected]
10 *
11 */
12
13(function (window, document, $, undefined) {
14	"use strict";
15
16	var W  = $(window),
17		D  = $(document),
18		H  = $('html');
19
20	var F = $.fancybox = function () {
21		F.open.apply( this, arguments );
22	};
23
24	var isTouch = F.isTouch = (document.createTouch !== undefined || window.ontouchstart !== undefined);
25
26	var isQuery = function(object) {
27		return object && object.hasOwnProperty && object instanceof $;
28	};
29
30	var isString = function(str) {
31		return str && $.type(str) === "string";
32	};
33
34	var isPercentage = function(str) {
35		return isString(str) && str.indexOf('%') > 0;
36	};
37
38	var getScalar = function(orig, dim) {
39		var value = parseFloat(orig, 10) || 0;
40
41		if (dim && isPercentage(orig)) {
42			value = F.getViewport()[ dim ] / 100 * value;
43		}
44
45		return Math.ceil(value);
46	};
47
48	var getValue = function(value, dim) {
49		return getScalar(value, dim) + 'px';
50	};
51
52	var getTime = Date.now || function() {
53		return +new Date;
54	};
55
56	var removeWrap = function(what) {
57		var el = isString(what) ? $(what) : what;
58
59		if (el && el.length) {
60			el.removeClass('fancybox-wrap').stop(true).trigger('onReset').hide().unbind();
61
62			try {
63				el.find('iframe').unbind().attr('src', isTouch ? '' : '//about:blank');
64
65				// Give the document in the iframe to get a chance to unload properly before remove
66				setTimeout(function () {
67					el.empty().remove();
68
69					// Remove the lock if there are no elements
70					if (F.lock && !F.coming && !F.current) {
71						var scrollV, scrollH;
72
73						$('.fancybox-margin').removeClass('fancybox-margin');
74
75						scrollV = W.scrollTop();
76						scrollH = W.scrollLeft();
77
78						H.removeClass('fancybox-lock');
79
80						F.lock.remove();
81
82						F.lock = null;
83
84						W.scrollTop( scrollV ).scrollLeft( scrollH );
85					}
86				}, 150);
87
88			} catch(e) {}
89		}
90	};
91
92	$.extend(F, {
93		// The current version of fancyBox
94		version: '3.0.0',
95
96		defaults: {
97			theme     : 'default',          // 'default', dark', 'light'
98			padding   : 0,					// space inside box, around content
99			margin    : [30, 55, 30, 55],	// space between viewport and the box
100			loop      : true,               // Continuous gallery item loop
101
102			arrows    : true,
103			closeBtn  : true,
104			expander  : !isTouch,
105
106			caption : {
107				type     : 'over'	// 'float', 'inside', 'outside' or 'over',
108			},
109
110			overlay : {
111				closeClick : true,      // if true, fancyBox will be closed when user clicks on the overlay
112				speedIn    : 0,         // duration of fadeIn animation
113				speedOut   : 250,       // duration of fadeOut animation
114				showEarly  : true,      // indicates if should be opened immediately or wait until the content is ready
115				css        : {}			// custom CSS properties
116			},
117
118			helpers : {},				// list of enabled helpers
119
120			// Dimensions
121			width       : 800,
122			height      : 450,
123			minWidth    : 100,
124			minHeight   : 100,
125			maxWidth    : 99999,
126			maxHeight   : 99999,
127			aspectRatio : false,
128			fitToView   : true,
129
130			autoHeight  : true,
131			autoWidth   : true,
132			autoResize  : true,
133
134			// Location
135			autoCenter  : !isTouch,
136			topRatio    : 0.5,
137			leftRatio   : 0.5,
138
139			// Opening animation
140			openEffect  : 'elastic',		// 'elastic', 'fade', 'drop' or 'none'
141			openSpeed   : 350,
142			openEasing  : 'easeOutQuad',
143
144			// Closing animation
145			closeEffect : 'elastic',		// 'elastic', 'fade', 'drop' or 'none'
146			closeSpeed  : 350,
147			closeEasing : 'easeOutQuad',
148
149			// Animation for next gallery item
150			nextEffect : 'elastic',		// 'elastic', 'fade', 'drop' or 'none'
151			nextSpeed  : 350,
152			nextEasing : 'easeOutQuad',
153
154			// Animation for previous gallery item
155			prevEffect : 'elastic',		// 'elastic', 'fade', 'drop' or 'none'
156			prevSpeed  : 350,
157			prevEasing : 'easeOutQuad',
158
159			// Slideshow
160			autoPlay   : false,
161			playSpeed  : 3000,
162
163			/*
164				Advanced
165			*/
166
167			// Callbacks
168			onCancel     : $.noop, // If canceling
169			beforeLoad   : $.noop, // Before loading
170			afterLoad    : $.noop, // After loading
171			beforeShow   : $.noop, // Before changing in current item
172			afterShow    : $.noop, // After opening
173			beforeClose  : $.noop, // Before closing
174			afterClose   : $.noop,  // After closing
175
176			// Properties specific to content type
177			ajax  : {
178				dataType : 'html',
179				headers  : { 'X-fancyBox': true }
180			},
181
182			iframe : {
183				scrolling : 'auto',
184				preload   : true
185			},
186
187			swf : {
188				wmode             : 'transparent',
189				allowfullscreen   : 'true',
190				allowscriptaccess : 'always'
191			},
192
193			// Default keyboard
194			keys  : {
195				next : {
196					13 : 'left', // enter
197					34 : 'up',   // page down
198					39 : 'left', // right arrow
199					40 : 'up'    // down arrow
200				},
201				prev : {
202					8  : 'right',  // backspace
203					33 : 'down',   // page up
204					37 : 'right',  // left arrow
205					38 : 'down'    // up arrow
206				},
207				close  : [27], // escape key
208				play   : [32], // space - start/stop slideshow
209				toggle : [70]  // letter "f" - toggle fullscreen
210			},
211
212			// Default direction
213			direction : {
214				next : 'left',
215				prev : 'right'
216			},
217
218			// HTML templates
219			tpl: {
220				wrap     : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-inner"></div></div>',
221				iframe   : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true"></iframe>',
222				error    : '<p class="fancybox-error">{{ERROR}}</p>',
223				closeBtn : '<a title="{{CLOSE}}" class="fancybox-close" href="javascript:;"></a>',
224				next     : '<a title="{{NEXT}}" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',
225				prev     : '<a title="{{PREV}}" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>'
226			},
227
228			// Localization
229			locale  : 'en',
230			locales : {
231				'en' : {
232					CLOSE      : 'Close',
233					NEXT       : 'Next',
234					PREV       : 'Previous',
235					ERROR      : 'The requested content cannot be loaded. <br/> Please try again later.',
236					EXPAND     : 'Display actual size',
237					SHRINK     : 'Fit to the viewport',
238					PLAY_START : 'Start slideshow',
239					PLAY_STOP  : 'Pause slideshow'
240				},
241				'de' : {
242					CLOSE      : 'Schliessen',
243					NEXT       : 'Vorwärts',
244					PREV       : 'Zurück',
245					ERROR      : 'Die angeforderten Daten konnten nicht geladen werden. <br/>
245 Bitte versuchen Sie es später nochmal.',
246					EXPAND     : '',
247					SHRINK     : '',
248					PLAY_START : '',
249					PLAY_STOP  : ''
250				}
251			},
252
253			// Override some properties
254			index     : 0,
255			content   : null,
256			href      : null,
257
258			// Various
259			wrapCSS       : '',         // CSS class name for the box
260			modal         : false,
261			locked        : false,
262			preload       : 3,			// Number of gallery images to preload
263			mouseWheel    : true,		// Enable or disable mousewheel support
264			scrolling     : 'auto',     // 'yes', 'no', any valid value for CSS "overflow" property
265			scrollOutside : true		// If trye, fancyBox will try to set scrollbars outside the content
266		},
267
268		// Current state
269		current  : null,
270		coming   : null,
271		group    : [],
272		index    : 0,
273		isActive : false,	// Is activated
274		isOpen   : false,	// Is currently open
275		isOpened : false,	// Have been fully opened at least once
276		isMaximized : false,
277
278		player : {
279			timer    : null,
280			isActive : false
281		},
282
283		// Loaders
284		ajaxLoad   : null,
285		imgPreload : null,
286
287		// Object containing all helpers
288		helpers    : {},
289
290		// Open fancyBox
291		open: function( items, options ) {
292			if (!items) {
293				return;
294			}
295
296			// Close if already active
297			if (false === F.close(true)) {
298				return;
299			}
300
301			if (!$.isPlainObject( options )) {
302				options = {};
303			}
304
305			F.opts = $.extend(true, {}, F.defaults, options);
306
307			F.populate( items );
308
309			if (F.group.length) {
310				F._start( F.opts.index );
311			}
312		},
313
314		// Add new items to the group
315		populate : function( items ) {
316			var group = [];
317
318			if ( !$.isArray( items )) {
319				items = [ items ];
320			}
321
322			// Build group array, each item is object containing element
323			// and most important attributes - href, title and type
324			$.each(items, function(i, element) {
325				var defaults = $.extend(true, {}, F.opts),
326					item,
327					obj,
328					type,
329					margin,
330					padding;
331
332				if ($.isPlainObject(element)) {
333					item = element;
334
335				} else if (isString(element)) {
336					item = { href : element };
337
338				} else if (isQuery(element) || $.type(element) === 'object' && element.nodeType) {
339					obj  = $(element);
340					item = $(obj).get(0);
341
342					if (!item.href) {
343						item = { href : element };
344					}
345
346					item = $.extend({
347						href    : obj.data('fancybox-href')  || obj.attr('href')  || item.href,
348						title   : obj.data('fancybox-title') || obj.attr('title') || item.title,
349						type    : obj.data('fancybox-type'),
350						element : obj
351					}, obj.data('fancybox-options') );
352
353				} else {
354					return;
355				}
356
357				// If the type has not specified, then try to guess
358				if (!item.type && (item.content || item.href)) {
359					item.type = item.content ? "html" : F.guessType( obj, item.href );
360				}
361
362				// Adjust some defaults depending on content type
363				type = item.type || F.opts.type;
364
365				if (type === 'image' || type === 'swf') {
366					defaults.autoWidth = defaults.autoHeight = false;
367					defaults.scrolling = 'visible';
368				}
369
370				if (type === 'image') {
371					defaults.aspectRatio = true;
372				}
373
374				if (type === 'iframe') {
375					defaults.autoWidth = false;
376					defaults.scrolling = isTouch ? 'scroll' : 'visible';
377				}
378
379				if (items.length < 2) {
380					defaults.margin = 30;
381				}
382
383				item = $.extend(true, {}, defaults, item);
384
385				// Recheck some parameters
386				margin  = item.margin;
387				padding = item.padding;
388
389				// Convert margin and padding properties to array - top, right, bottom, left
390				if ($.type(margin) === 'number') {
391					item.margin = [margin, margin, margin, margin];
392				}
393
394				if ($.type(padding) === 'number') {
395					item.padding = [padding, padding, padding, padding];
396				}
397
398				// 'modal' propery is just a shortcut
399				if (item.modal) {
400					$.extend(true, item, {
401						closeBtn   : false,
402						closeClick : false,
403						nextClick  : false,
404						arrows     : false,
405						mouseWheel : false,
406						keys       : null,
407						overlay : {
408							closeClick : false
409						}
410					});
411				}
412
413				if (item.autoSize !== undefined) {
414					item.autoWidth = item.autoHeight = !!item.autoSize;
415				}
416
417				if (item.width === 'auto') {
418					item.autoWidth = true;
419				}
420
421				if (item.height === 'auto') {
422					item.autoHeight = true;
423				}
424
425				group.push( item );
426			});
427
428			F.group = F.group.concat( group );
429		},
430
431		// Cancel image loading and abort ajax request
432		cancel: function () {
433			var coming = F.coming;
434
435			if (!coming || false === F.trigger('onCancel')) {
436				return;
437			}
438
439			F.hideLoading();
440
441			if (F.ajaxLoad) {
442				F.ajaxLoad.abort();
443			}
444
445			if (F.imgPreload) {
446				F.imgPreload.onload = F.imgPreload.onerror = null;
447			}
448
449			if (coming.wrap) {
450				removeWrap( coming.wrap );
451			}
452
453			F.ajaxLoad = F.imgPreload = F.coming = null;
454
455			// If the first item has been canceled, then clear everything
456			if (!F.current) {
457				F._afterZoomOut( coming );
458			}
459		},
460
461		// Start closing or remove immediately if is opening/closing
462		close: function (e) {
463			if (e && $.type(e) === 'object') {
464				e.preventDefault();
465			}
466
467			F.cancel();
468
469			// Do not close if:
470			//   - the script has not been activated
471			//   - cancel event has triggered opening a new item
472			//   - "beforeClose" trigger has returned false
473			if (!F.isActive || F.coming || false === F.trigger('beforeClose')) {
474				return;
475			}
476
477			F.unbind();
478
479			F.isClosing = true;
480
481			if (F.lock) {
482				F.lock.css('overflow', 'hidden');
483			}
484
485			if (!F.isOpen || e === true) {
486				F._afterZoomOut();
487
488			} else {
489				F.isOpen = F.isOpened = false;
490
491				F.transitions.close();
492			}
493		},
494
495		prev : function( direction ) {
496			var current = F.current;
497
498			if (current) {
499				F.jumpto( current.index - 1, (isString(direction) ? direction : current.direction.prev) );
500			}
501		},
502
503		next : function( direction ) {
504			var current = F.current;
505
506			if (current) {
507				F.jumpto( current.index + 1, (isString(direction) ? direction : current.direction.next) );
508			}
509		},
510
511		jumpto : function( index, direction ) {
512			var current = F.current;
513
514			if (!(F.coming && F.coming.index === index)) {
515				F.cancel();
516
517				if (current.index == index) {
518					direction = null;
519
520				} else if (!direction) {
521					direction = current.direction[ index > current.index ? 'next' : 'prev' ];
522				}
523
524				F.direction = direction;
525
526				F._start( index );
527			}
528		}
529	});
530
531	$.extend(F, {
532		guessType : function(item, href) {
533			var rez  = item && item.prop('class') ? item.prop('class').match(/fancybox\.(\w+)/) : 0,
534				type = false;
535
536			if (rez) {
537				return rez[1];
538			}
539
540			if (isString(href)) {
541				if (href.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp)((\?|#).*)?$)/i)) {
542					type = 'image';
543
544				} else if (href.match(/\.(swf)((\?|#).*)?$/i)) {
545					type = 'swf';
546
547				} else if (href.charAt(0) === '#') {
548					type = 'inline';
549				}
550
551			} else if (isString(item)) {
552				type = 'html';
553			}
554
555			return type;
556		},
557
558		trigger: function (event, o) {
559			var ret, obj = o || F.coming || F.current;
560
561			if (!obj) {
562				return;
563			}
564
565			if ($.isFunction( obj[event] )) {
566				ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
567			}
568
569			// Cancel further execution if afterClose callback has opened new instance
570			if (ret === false || (event === 'afterClose' && F.isActive) ) {
571				return false;
572			}
573
574			if (obj.helpers) {
575				$.each(obj.helpers, function (helper, opts) {
576					var helperObject = F.helpers[helper],
577						helperOpts;
578
579					if (opts && helperObject && $.isFunction(helperObject[event])) {
580						helperOpts = $.extend(true, {}, helperObject.defaults, opts);
581
582						helperObject.opts = helperOpts;
583
584						helperObject[event](helperOpts, obj );
585					}
586				});
587			}
588
589			$.event.trigger(event);
590		},
591
592		// Center inside viewport
593		reposition: function (e, object) {
594			var obj  = object || F.current,
595				wrap = obj && obj.wrap,
596				pos;
597
598			if (F.isOpen && wrap) {
599				pos = F._getPosition( obj );
600
601				if (e === false || (e && e.type === 'scroll')) {
602					wrap.stop(true).animate(pos, 200).css('overflow', 'visible');
603
604				} else {
605					wrap.css(pos);
606				}
607			}
608		},
609
610		update: function (e) {
611			var type    = (e && e.type),
612				timeNow = getTime(),
613				current = F.current,
614				width;
615
616			if (!current || !F.isOpen ) {
617				return;
618			}
619
620			if (type === 'scroll') {
621				if (F.wrap.outerHeight(true) > F.getViewport().h) {
622					return;
623				}
624
625				if (F.didUpdate) {
626					clearTimeout( F.didUpdate );
627				}
628
629				F.didUpdate = setTimeout(function() {
630					F.reposition(e);
631
632					F.didUpdate = null;
633				}, 50);
634
635				return;
636			}
637
638			if (F.lock) {
639				F.lock.css('overflow', 'hidden');
640			}
641
642			F._setDimension();
643
644			F.reposition(e);
645
646			if (F.lock) {
647				F.lock.css('overflow', 'auto');
648			}
649
650			// Re-center float type caption
651			if (current.caption.type === 'float') {
652				width = F.getViewport().w - (F.wrap.outerWidth(true)  - F.inner.width() );
653
654				current.caption.wrap.css('width', width).css('marginLeft', (width * 0.5 - F.inner.width() * 0.5) * -1 );
655			}
656
657			if (current.expander) {
658				if ( current.canShrink) {
659					$(".fancybox-expand").show().attr('title', current.locales[ current.locale ].SHRINK  );
660
661				} else if (current.canExpand) {
662					$(".fancybox-expand").show().attr('title', current.locales[ current.locale ].EXPAND   );
663
664				} else {
665					$(".fancybox-expand").hide();
666				}
667			}
668
669			F.trigger('onUpdate');
670		},
671
672		// Shrink content to fit inside viewport or restore if resized
673		toggle: function ( action ) {
674			var current = F.current;
675
676			if (current && F.isOpen) {
677				F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
678
679				F.update( true );
680			}
681		},
682
683		hideLoading: function () {
684			$('#fancybox-loading').remove();
685		},
686
687		showLoading: function () {
688			var el, view;
689
690			F.hideLoading();
691
692			el = $('<div id="fancybox-loading"></div>').click(F.cancel).appendTo('body');
693
694			if (!F.defaults.fixed) {
695				view = F.getViewport();
696
697				el.css({
698					position : 'absolute',
699					top  : (view.h * 0.5) + view.y,
700					left : (view.w * 0.5) + view.x
701				});
702			}
703		},
704
705		getViewport: function () {
706			var rez;
707
708			if (F.lock) {
709				rez = {
710					x: F.lock.scrollLeft(),
711					y: F.lock.scrollTop(),
712					w: F.lock[0].clientWidth,
713					h: F.lock[0].clientHeight
714				};
715
716			} else {
717				rez = {
718					x: W.scrollLeft(),
719					y: W.scrollTop(),
720
721					// See http://bugs.jquery.com/ticket/6724
722					w : isTouch && window.innerWidth  ? window.innerWidth  : W.width(),
723					h : isTouch && window.innerHeight ? window.innerHeight : W.height()
724				};
725			}
726
727			return rez;
728		},
729
730		unbind : function() {
731			if (isQuery(F.wrap)) {
732				F.wrap.unbind('.fb');
733			}
734
735			if (isQuery(F.inner)) {
736				F.inner.unbind('.fb');
737			}
738
739			D.unbind('.fb');
740			W.unbind('.fb');
741		},
742
743		rebind: function () {
744			var current = F.current,
745				keys;
746
747			F.unbind();
748
749			if (!current || !F.isOpen) {
750				return;
751			}
752
753			// Changing document height on iOS devices triggers a 'resize' event,
754			// that can change document height... repeating infinitely
755			W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
756
757			keys = current.keys;
758
759			if (keys) {
760				D.bind('keydown.fb', function (e) {
761					var code   = e.which || e.keyCode,
762						target = e.target || e.srcElement;
763
764					// Skip esc key if loading, because showLoading will cancel preloading
765					if (code === 27 && F.coming) {
766						return false;
767					}
768
769					// Ignore key combinations and key events within form elements
770					if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
771						$.each(keys, function(i, val) {
772							//if (current.group.length > 1 && val[ code ] !== undefined) {
773							if (val[ code ] !== undefined) {
774								e.preventDefault();
775
776								if (current.group.length > 1) {
777									F[ i ]( val[ code ] );
778								}
779
780								return false;
781							}
782
783							if ($.inArray(code, val) > -1) {
784								e.preventDefault();
785
786								if (i === 'play') {
787									F.slideshow.toggle();
788								} else {
789									F[ i ] ();
790								}
791
792								return false;
793							}
794						});
795					}
796				});
797			}
798
799			F.lastScroll = getTime();
800
801			if (current.mouseWheel && F.group.length > 1) {
802				F.wrap.bind('DOMMouseScroll.fb mousewheel.fb MozMousePixelScroll.fb', function (event) {
803					var e       = event.originalEvent,
804						el      = e.target || 0,
805						delta   = (e.wheelDelta || e.detail || 0),
806						deltaX  = e.wheelDeltaX || 0,
807						deltaY  = e.wheelDeltaY || 0,
808						now     = getTime();
809
810					if (((el && el.style && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)))) ) {
811						return;
812					}
813
814					if (delta === 0 || (F.current && F.current.canShrink)) {
815						return;
816					}
817
818					e.stopPropagation();
819
820					if (F.lastScroll && (now - F.lastScroll) < 80) {
821						F.lastScroll = now;
822						return;
823					}
824
825					F.lastScroll = now;
826
827					if (e.axis) {
828						if (e.axis === e.HORIZONTAL_AXIS) {
829							deltaX = delta * -1;
830
831						} else if (e.axis === e.VERTICAL_AXIS) {
832							deltaY = delta * -1;
833						}
834					}
835
836					if ( deltaX === 0 ) {
837						if (deltaY > 0) {
838							F.prev( 'down' );
839
840						} else {
841							F.next( 'up' );
842						}
843
844					} else {
845						if (deltaX > 0) {
846							F.prev( 'right' );
847
848						} else {
849							F.next( 'left' );
850						}
851					}
852				});
853			}
854
855			F.touch.init();
856		},
857
858		rebuild : function() {
859			var current = F.current;
860
861			current.wrap.find('.fancybox-nav, .fancybox-close, .fancybox-expand').remove();
862
863			// Create navigation arrows
864			if (current.arrows && F.group.length > 1) {
865				if (current.loop || current.index > 0) {
866					$( F._translate( current.tpl.prev) ).appendTo(F.inner).bind('click.fb', F.prev);
867				}
868
869				if (current.loop || current.index < F.group.length - 1) {
870					$( F._translate( current.tpl.next) ).appendTo(F.inner).bind('click.fb', F.next);
871				}
872			}
873
874			// Create a close button
875			if (current.closeBtn) {
876				$( F._translate( current.tpl.closeBtn) ).appendTo(F.wrap).bind('click.fb', F.close);
877			}
878
879			// Add expand button to image
880			if (current.expander && current.type === 'image') {
881				$('<a title="Expand image" class="fancybox-expand" href="javascript:;"></a>')
882					.appendTo( F.inner )
883					.bind('click.fb', F.toggle);
884
885				if ( !current.canShrink && !current.canExpand) {
886
887				}
888			}
889		},
890
891		// Create upcoming object and prepare for loading the content
892		_start: function( index ) {
893			var coming,
894				type;
895
896			// Check index and get object from the groups
897			if (F.opts.loop) {
898				if (index < 0) {
899					index = F.group.length + (index % F.group.length);
900				}
901
902				index = index % F.group.length;
903			}
904
905			coming = F.group[ index ];
906
907			if (!coming) {
908				return false;
909			}
910
911			// Add all properties
912			coming = $.extend(true, {}, F.opts, coming);
913
914			/*
915			 * Add reference to the group, so it`s possible to access from callbacks, example:
916			 * afterLoad : function() {
917			 *     this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
918			 * }
919			 */
920
921			coming.group  = F.group;
922			coming.index  = index;
923
924			// Give a chance for callback or helpers to update coming item (type, title, etc)
925			F.coming = coming;
926
927			if (false === F.trigger('beforeLoad')) {
928				F.coming = null;
929
930				return;
931			}
932
933			F.isActive = true;
934
935			// Build the neccessary markup
936			F._build();
937
938			// If user will press the escape-button, the request will be canceled
939			D.bind('keydown.loading', function(e) {
940				if ((e.which || e.keyCode) === 27) {
941					D.unbind('.loading');
942
943					e.preventDefault();
944
945					F.cancel();
946				}
947			});
948
949			// Show overlay
950			if (coming.overlay && coming.overlay.showEarly) {
951				F.overlay.open( coming.overlay );
952			}
953
954			// Load content
955			type = coming.type;
956
957			if (type === 'image') {
958				F._loadImage();
959
960			} else if (type === 'ajax') {
961				F._loadAjax();
962
963			} else if (type === 'iframe') {
964				F._loadIframe();
965
966			} else if (type === 'inline') {
967				F._loadInline();
968
969			} else if (type === 'html' || type === 'swf') {
970				F._afterLoad();
971
972			} else {
973				F._error();
974			}
975		},
976
977		_build : function() {
978			var coming  = F.coming,
979				captionType = coming.caption.type,
980				wrap,
981				inner,
982				scrollV,
983				scrollH;
984
985			coming.wrap  = wrap  = $('<div class="fancybox-wrap"></div>').appendTo( coming.parent || 'body' ).addClass('fancybox-' + coming.theme);
986			coming.inner = inner = $('<div class="fancybox-inner"></div>').appendTo( wrap );
987
988			coming[ captionType === 'outside' || captionType === 'float' ? 'inner' : 'wrap' ].addClass('fancybox-skin fancybox-' + coming.theme + '-skin');
989
990			if (coming.locked && coming.overlay && F.defaults.fixed) {
991				if (!F.lock) {
992					F.lock = $('<div id="fancybox-lock"></div>').appendTo( wrap.parent() );
993				}
994
995				F.lock.unbind().append( wrap );
996
997				if (coming.overlay.closeClick) {
998					F.lock.click(function(e) {
999						if ($(e.target).is(F.lock)) {
1000							F.close();
1001						}
1002					});
1003				}
1004
1005				// Compensate missing page scrolling by increasing margin
1006				if (D.height() > W.height() || H.css('overflow-y') === 'scroll') {
1007					$('*:visible').filter(function(){
1008						return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && $(this).attr('id') !== "fancybox-lock");
1009					}).addClass('fancybox-margin');
1010
1011					H.addClass('fancybox-margin');
1012				}
1013
1014				// Workaround for FF jumping bug
1015				scrollV = W.scrollTop();
1016				scrollH = W.scrollLeft();
1017
1018				H.addClass('fancybox-lock');
1019
1020				W.scrollTop( scrollV ).scrollLeft( scrollH );
1021			}
1022
1023			F.trigger('onReady');
1024		},
1025
1026		_error: function ( type ) {
1027			if (!F.coming) {
1028				return;
1029			}
1030
1031			$.extend(F.coming, {
1032				type       : 'html',
1033				autoWidth  : true,
1034				autoHeight : true,
1035				closeBtn   : true,
1036				minWidth   : 0,
1037				minHeight  : 0,
1038				padding    : [15, 15, 15, 15],
1039				scrolling  : 'visible',
1040				hasError   : type,
1041				content    : F._translate( F.coming.tpl.error )
1042			});
1043
1044			F._afterLoad();
1045		},
1046
1047		_loadImage: function () {
1048			// Reset preload image so it is later possible to check "complete" property
1049			var img = F.imgPreload = new Image();
1050
1051			img.onload = function () {
1052				this.onload = this.onerror = null;
1053
1054				$.extend(F.coming, {
1055					width   : this.width,
1056					height  : this.height,
1057					content : $(this).addClass('fancybox-image')
1058				});
1059
1060				F._afterLoad();
1061			};
1062
1063			img.onerror = function () {
1064				this.onload = this.onerror = null;
1065
1066				F._error( 'image' );
1067			};
1068
1069			img.src = F.coming.href;
1070
1071			if (img.complete !== true || img.width < 1) {
1072				F.showLoading();
1073			}
1074		},
1075
1076		_loadAjax: function () {
1077			var coming = F.coming,
1078				href   = coming.href,
1079				hrefParts,
1080				selector;
1081
1082			hrefParts = href.split(/\s+/, 2);
1083			href      = hrefParts.shift();
1084			selector  = hrefParts.shift();
1085
1086			F.showLoading();
1087
1088			F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
1089				url: coming.href,
1090				error: function (jqXHR, textStatus) {
1091					if (F.coming && textStatus !== 'abort') {
1092						F._error( 'ajax', jqXHR );
1093
1094					} else {
1095						F.hideLoading();
1096					}
1097				},
1098				success: function (data, textStatus) {
1099					if (textStatus === 'success') {
1100						if (selector) {
1101							data = $('<div>').html(data).find(selector);
1102						}
1103
1104						coming.content = data;
1105
1106						F._afterLoad();
1107					}
1108				}
1109			}));
1110		},
1111
1112		_loadIframe: function() {
1113			var coming = F.coming,
1114				iframe;
1115
1116			coming.content = iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))
1117				.attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling);
1118
1119			if (coming.iframe.preload) {
1120				F.showLoading();
1121
1122				F._setDimension( coming );
1123
1124				coming.wrap.addClass('fancybox-tmp');
1125
1126				iframe.one('load.fb', function() {
1127					if (coming.iframe.preload) {
1128						$(this).data('ready', 1);
1129
1130						$(this).bind('load.fb', F.update);
1131
1132						F._afterLoad();
1133					}
1134				});
1135			}
1136
1137			iframe.attr('src', coming.href).appendTo(coming.inner);
1138
1139			if (!coming.iframe.preload) {
1140				F._afterLoad();
1141
1142			} else if (iframe.data('ready') !== 1) {
1143				F.showLoading();
1144			}
1145		},
1146
1147		_loadInline : function() {
1148			var coming = F.coming,
1149				href   = coming.href;
1150
1151			coming.content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
1152
1153			if (coming.content.length) {
1154				F._afterLoad();
1155
1156			} else {
1157				F._error();
1158			}
1159		},
1160
1161		_preloadImages: function() {
1162			var group   = F.group,
1163				current = F.current,
1164				len     = group.length,
1165				cnt     = current.preload ? Math.min(current.preload, len - 1) : 0,
1166				item,
1167				i;
1168
1169			for (i = 1; i <= cnt; i += 1) {
1170				item = group[ (current.index + i ) % len ];
1171
1172				if (item && item.type === 'image' && item.href) {
1173					new Image().src = item.href;
1174				}
1175			}
1176		},
1177
1178		_afterLoad : function() {
1179			var current  = F.coming,
1180				previous = F.current;
1181
1182			D.unbind('.loading');
1183
1184			if (!current || F.isActive === false || false === F.trigger('afterLoad', current, previous)) {
1185				F.hideLoading();
1186
1187				if (current && current.wrap) {
1188					removeWrap( current.wrap );
1189				}
1190
1191				if (!previous) {
1192					F._afterZoomOut( current );
1193				}
1194
1195				F.coming = null;
1196
1197				return;
1198			}
1199
1200			$.extend(F, {
1201				wrap     : current.wrap.addClass('fancybox-type-' + current.type + ' fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-' + current.theme + '-' +  (isTouch ? 'mobile' : 'desktop')  + ' ' + current.wrapCSS),
1202				inner    : current.inner,
1203				current  : current,
1204				previous : previous
1205			});
1206
1207			// Set content, margin/padding, caption, etc
1208			F._prepare();
1209
1210			// Give a chance for helpers or callbacks to update elements
1211			F.trigger('beforeShow', current, previous);
1212
1213			F.isOpen = false;
1214			F.coming = null;
1215
1216			// Set initial dimension
1217			F._setDimension();
1218
1219			F.hideLoading();
1220
1221			// Open overlay if is not yet open
1222			if (current.overlay && !F.overlay.el) {
1223				F.overlay.open( current.overlay );
1224			}
1225
1226			F.transitions.open();
1227		},
1228
1229		_prepare : function() {
1230			var current     = F.current,
1231				content     = current.content || '',
1232				wrap        = current.wrap,
1233				inner       = current.inner,
1234				margin      = current.margin,
1235				padding     = current.padding,
1236				href        = current.href,
1237				type        = current.type,
1238				scrolling   = current.scrolling,
1239				caption     = current.caption,
1240				captionText = current.title,
1241				captionType = caption.type,
1242				placeholder = 'fancybox-placeholder',
1243				display     = 'fancybox-display',
1244				embed;
1245
1246			if (type !== 'iframe' && isQuery(content) && content.length) {
1247				if (!content.data(placeholder)) {
1248					content.data(display, content.css('display'))
1249						.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() );
1250				}
1251
1252				content = content.show().detach();
1253
1254				current.wrap.bind('onReset', function () {
1255					if ($(this).find(content).length) {
1256						content.css('display', content.data(display))
1257							.replaceAll( content.data(placeholder) )
1258							.data(placeholder, false)
1259							.data(display, false);
1260					}
1261				});
1262			}
1263
1264			if (type === 'swf') {
1265				content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>';
1266				embed   = '';
1267
1268				$.each(current.swf, function(name, val) {
1269					content += '<param name="' + name + '" value="' + val + '"></param>';
1270					embed   += ' ' + name + '="' + val + '"';
1271				});
1272
1273				content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>';
1274			}
1275
1276			if (!(isQuery(content) && content.parent().is(current.inner))) {
1277				current.inner.append( content );
1278
1279				current.content = current.inner.children(':last');
1280			}
1281
1282			// Add margin / padding
1283			$.each(["Top", "Right", "Bottom", "Left"], function(i, v) {
1284				if (margin[ i ]) {
1285					wrap.css('margin' + v, getValue(margin[ i ]));
1286				}
1287
1288				if (padding[ i ]) {
1289					if (!(v === 'Bottom' && captionType === 'outside')) {
1290						wrap.css('padding' + v, getValue(padding[ i ])  );
1291					}
1292
1293					if (captionType === 'outside' || captionType === 'float') {
1294
1295						inner.css('border' + v + 'Width', getValue(padding[ i ]));
1296
1297						if (v === 'Top' || v === 'Left') {
1298							inner.css('margin' + v, getValue(padding[ i ] * -1));
1299						}
1300					}
1301				}
1302			});
1303
1304			// Add caption
1305			if ($.isFunction(captionText)) {
1306				captionText = captionText.call(current.element, current);
1307			}
1308
1309			if (isString(captionText) && $.trim(captionText) !== '') {
1310				current.caption.wrap = $('<div class="fancybox-title fancybox-title-' + captionType + '-wrap">' + captionText + '</div>').appendTo( current[ captionType === 'over' ? 'inner' : 'wrap' ] );
1311
1312				if (captionType === 'float') {
1313					current.caption.wrap.width( F.getViewport().w - (F.wrap.outerWidth(true)  - F.inner.width() ) ).wrapInner('<div></div>');
1314				}
1315			}
1316		},
1317
1318		_setDimension: function( object ) {
1319			var view      = F.getViewport(),
1320				current   = object || F.current,
1321				wrap      = current.wrap,
1322				inner     = current.inner,
1323				width     = current.width,
1324				height    = current.height,
1325				minWidth  = current.minWidth,
1326				minHeight = current.minHeight,
1327				maxWidth  = current.maxWidth,
1328				maxHeight = current.maxHeight,
1329				margin    = current.margin,
1330				scrollOut = current.scrollOutside ? current.scrollbarWidth : 0,
1331				margin    = current.margin,
1332				padding   = current.padding,
1333				scrolling = current.scrolling,
1334				steps     = 1,
1335				scrollingX,
1336				scrollingY,
1337				hSpace,
1338				wSpace,
1339				origWidth,
1340				origHeight,
1341				ratio,
1342				iframe,
1343				body,
1344				maxWidth_,
1345				maxHeight_,
1346				width_,
1347				height_,
1348				canShrink,
1349				canExpand;
1350
1351			// Set scrolling
1352			scrolling  = scrolling.split(',');
1353			scrollingX = scrolling[0];
1354			scrollingY = scrolling[1] || scrollingX;
1355
1356			current.inner
1357				.css('overflow-x', scrollingX === 'yes' ? 'scroll' : (scrollingX === 'no' ? 'hidden' : scrollingX))
1358				.css('overflow-y', scrollingY === 'yes' ? 'scroll' : (scrollingY === 'no' ? 'hidden' : scrollingY));
1359
1360			wSpace = margin[1] + margin[3] + padding[1] + padding[3];
1361			hSpace = margin[0] + margin[2] + padding[0] + padding[2];
1362
1363			// Calculations for the content
1364			minWidth  = getScalar( isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth );
1365			maxWidth  = getScalar( isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth );
1366
1367			minHeight = getScalar( isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight );
1368			maxHeight = getScalar( isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight );
1369
1370			origWidth  = getScalar( isPercentage(width)  ? getScalar(width,  'w') - wSpace : width  );
1371			origHeight = getScalar( isPercentage(height) ? getScalar(height, 'h') - hSpace : height );
1372
1373			if (current.fitToView) {
1374				maxWidth  = Math.min(maxWidth,  getScalar('100%', 'w') - wSpace );
1375				maxHeight = Math.min(maxHeight, getScalar('100%', 'h') - hSpace );
1376			}
1377
1378			maxWidth_  = view.w;
1379			maxHeight_ = view.h;
1380
1381			if (current.type === 'iframe') {
1382				iframe = current.content;
1383
1384				wrap.removeClass('fancybox-tmp');
1385
1386				if ((current.autoWidth || current.autoHeight) && iframe && iframe.data('ready') === 1) {
1387
1388					try {
1389						if (iframe[0].contentWindow && iframe[0].contentWindow.document.location) {
1390							body = iframe.contents().find('body');
1391
1392							inner.addClass( 'fancybox-tmp' );
1393
1394							inner.width( screen.width - wSpace ).height( 99999 );
1395
1396							if (scrollOut) {
1397								body.css('overflow-x', 'hidden');
1398							}
1399
1400							if (current.autoWidth) {
1401								origWidth = body.outerWidth(true);
1402							}
1403
1404							if (current.autoHeight) {
1405								origHeight = body.outerHeight(true);
1406							}
1407
1408							inner.removeClass( 'fancybox-tmp' );
1409						}
1410
1411					} catch (e) {}
1412				}
1413
1414			} else if ( (current.autoWidth || current.autoHeight) && !(current.type === 'image' || current.type === 'swf') ) {
1415				inner.addClass( 'fancybox-tmp' );
1416
1417				// Set width or height in case we need to calculate only one dimension
1418				if (current.autoWidth) {
1419					inner.width( 'auto' );
1420
1421				} else {
1422					inner.width( maxWidth );
1423				}
1424
1425				if (current.autoHeight) {
1426					inner.height( 'auto' );
1427
1428				} else {
1429					inner.height( maxHeight );
1430				}
1431
1432				if (current.autoWidth) {
1433					origWidth = inner[0].scrollWidth || inner.width();
1434				}
1435
1436				if (current.autoHeight) {
1437					origHeight = inner[0].scrollHeight || inner.height();
1438				}
1439
1440				inner.removeClass( 'fancybox-tmp' );
1441			}
1442
1443			width  = origWidth;
1444			height = origHeight;
1445			ratio  = origWidth / origHeight;
1446
1447			if (!current.autoResize) {
1448				wrap.css({
1449					width  : getValue( width ),
1450					height : 'auto'
1451				});
1452
1453				inner.css({
1454					width  : getValue( width ),
1455					height : getValue( height )
1456				});
1457				return;
1458			}
1459
1460			if (current.aspectRatio) {
1461				if (width > maxWidth) {
1462					width  = maxWidth;
1463					height = width / ratio;
1464				}
1465
1466				if (height > maxHeight) {
1467					height = maxHeight;
1468					width  = height * ratio;
1469				}
1470
1471				if (width < minWidth) {
1472					width  = minWidth;
1473					height = width / ratio;
1474				}
1475
1476				if (height < minHeight) {
1477					height = minHeight;
1478					width  = height * ratio;
1479				}
1480
1481			} else {
1482				width = Math.max(minWidth, Math.min(width, maxWidth));
1483
1484				if (current.autoHeight && current.type !== 'iframe') {
1485					inner.width( width );
1486
1487					origHeight = height = inner[0].scrollHeight;
1488				}
1489
1490				height = Math.max(minHeight, Math.min(height, maxHeight));
1491			}
1492
1493			// Wrap element has to have fixed width, because long title can expand it
1494			wrap.css({
1495				width  : getValue( width ),
1496				height : 'auto'
1497			});
1498
1499			inner.css({
1500				width  : getValue( width ),
1501				height : getValue( height )
1502			});
1503
1504			width_  = getScalar( wrap.outerWidth(true) );
1505			height_ = getScalar( wrap.outerHeight(true) );
1506
1507			if (current.fitToView) {
1508				// Since we do not know how many lines will be at the final, we need to
1509				// resize box till it fits inside max dimensions
1510				if (current.aspectRatio) {
1511					while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
1512						if (steps++ > 30) {
1513							break;
1514						}
1515
1516						height = Math.max(minHeight, Math.min(maxHeight, height - 10));
1517						width  = getScalar(height * ratio);
1518
1519						if (width < minWidth) {
1520							width  = minWidth;
1521							height = getScalar(width / ratio);
1522						}
1523
1524						if (width > maxWidth) {
1525							width  = maxWidth;
1526							height = getScalar(width / ratio);
1527						}
1528
1529						wrap.css({
1530							width  : getValue( width )
1531						});
1532
1533						inner.css({
1534							width  : getValue( width ),
1535							height : getValue( height )
1536						});
1537
1538						width_  = getScalar( wrap.outerWidth(true) );
1539						height_ = getScalar( wrap.outerHeight(true) );
1540					}
1541
1542				} else {
1543					width  = Math.max(minWidth,  Math.min(width,  width  - (width_  - maxWidth_  )));
1544					height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_ )));
1545				}
1546			}
1547
1548
1549			if (scrollOut && scrollingX === 'auto' && (height < inner[0].scrollHeight || (isQuery(current.content) && current.content[0] && height < current.content[0].offsetHeight)) && (width + wSpace + scrollOut) < maxWidth) {
1550				width += scrollOut;
1551			}
1552
1553			wrap.css({
1554				width  : width
1555			});
1556
1557			inner.css({
1558				width  : getValue( width ),
1559				height : getValue( height )
1560			});
1561
1562			width_  = getScalar( wrap.outerWidth(true) );
1563			height_ = getScalar( wrap.outerHeight(true) );
1564
1565			canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
1566			canExpand = (width_ < maxWidth_ || height_ < maxHeight_) && ( current.aspectRatio ? (width < maxWidth && height < maxHeight && width < origWidth && height < origHeight) : ((width < maxWidth || height < maxHeight) && (width < origWidth || height < origHeight)) );
1567
1568			current.canShrink = canShrink;
1569			current.canExpand = canExpand;
1570
1571			if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
1572				inner.height('auto');
1573			}
1574		},
1575
1576		_getPosition: function( object ) {
1577			var obj   = object || F.current,
1578				wrap  = obj.wrap,
1579				view  = F.getViewport(),
1580				pos   = {},
1581				top   = view.y,
1582				left  = view.x;
1583
1584			pos = {
1585				top    : getValue( Math.max(top,  top  + ((view.h - wrap.outerHeight(true)) * obj.topRatio)) ),
1586				left   : getValue( Math.max(left, left + ((view.w - wrap.outerWidth(true))  * obj.leftRatio)) ),
1587				width  : getValue( wrap.width() ),
1588				height : getValue( wrap.height() )
1589			};
1590
1591			return pos;
1592		},
1593
1594		_afterZoomIn : function() {
1595			var current   = F.current;
1596
1597			if (!current) {
1598				return;
1599			}
1600
1601			if (F.lock) {
1602				F.lock.css('overflow', 'auto');
1603			}
1604
1605			F.isOpen = F.isOpened = true;
1606
1607			F.rebuild();
1608
1609			F.rebind();
1610
1611			if (current.caption && current.caption.wrap) {
1612				current.caption.wrap.show().css({
1613					'visibility' : 'visible',
1614					'opacity'    : 0,
1615					'left'       : 0
1616				})
1617				.animate({opacity:1}, "fast");
1618			}
1619
1620			F.update();
1621
1622			F.wrap.css('overflow', 'visible').addClass('fancybox-open').focus();
1623
1624			F[ F.wrap.hasClass('fancybox-skin') ? 'wrap' : 'inner' ].addClass('fancybox-' + current.theme + '-skin-open');
1625
1626			if (current.caption && current.caption.wrap) {
1627				current.caption.wrap.show().css('left', 0).animate({opacity:1}, "fast");
1628			}
1629
1630			// Add empty element to simulate bottom margin, this trick helps to avoid extra element
1631			if (current.margin[2] > 0) {
1632				$('<div class="fancybox-spacer"></div>').css('height', getValue( current.margin[2] - 2) ).appendTo( F.wrap );
1633			}
1634
1635			F.trigger('afterShow');
1636
1637			F._preloadImages();
1638
1639			if (current.autoPlay && !F.slideshow.isActive) {
1640				F.slideshow.start();
1641			}
1642		},
1643
1644		_afterZoomOut : function(obj) {
1645			var cleanup = function() {
1646				removeWrap('.fancybox-wrap');
1647			};
1648
1649			F.hideLoading();
1650
1651			obj = obj || F.current;
1652
1653			if (obj && obj.wrap) {
1654				obj.wrap.hide();
1655			}
1656
1657			$.extend(F, {
1658				group     : [],
1659				opts      : {},
1660				coming    : null,
1661				current   : null,
1662				isActive  : false,
1663				isOpened  : false,
1664				isOpen    : false,
1665				isClosing : false,
1666				wrap      : null,
1667				skin      : null,
1668				inner     : null
1669			});
1670
1671			F.trigger('afterClose', obj);
1672
1673			if (!F.coming && !F.current) {
1674				if (obj.overlay) {
1675					F.overlay.close( obj.overlay, cleanup );
1676				} else {
1677					cleanup();
1678				}
1679			}
1680		},
1681
1682		_translate : function( str ) {
1683			var obj = F.coming || F.current,
1684				arr = obj.locales[ obj.locale ];
1685
1686			return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
1687				var value = arr[n];
1688
1689				if (value === undefined) {
1690					return match;
1691				}
1692
1693				return value;
1694			});
1695		}
1696	});
1697
1698	/*
1699	 *	Transition object
1700	 */
1701
1702	F.transitions = {
1703		_getOrig: function( object ) {
1704			var obj     = object || F.current,
1705				wrap    = obj.wrap,
1706				element = obj.element,
1707				orig    = obj.orig,
1708				view    = F.getViewport(),
1709				pos     = {},
1710				width   = 50,
1711				height  = 50;
1712
1713			if (!orig && element && element.is(':visible')) {
1714				orig = element.find('img:first:visible');
1715
1716				if (!orig.length) {
1717					orig = element;
1718				}
1719			}
1720
1721			// If there is no orig element, maybe only the first thumbnail is visible
1722			if (!orig && obj.group[0].element) {
1723				orig = obj.group[0].element.find('img:visible:first');
1724			}
1725
1726			if (isQuery(orig) && orig.is(':visible')) {
1727				pos = orig.offset();
1728
1729				if (orig.is('img')) {
1730					width  = orig.outerWidth();
1731					height = orig.outerHeight();
1732				}
1733
1734				if (F.lock) {
1735					pos.top  -= W.scrollTop();
1736					pos.left -= W.scrollLeft();
1737				}
1738
1739			} else {
1740				pos.top  = view.y + (view.h - height) * obj.topRatio;
1741				pos.left = view.x + (view.w - width)  * obj.leftRatio;
1742			}
1743
1744			pos = {
1745				top      : getValue( pos.top  - (wrap.outerHeight(true) - wrap.height() ) * 0.5 ),
1746				left     : getValue( pos.left - (wrap.outerWidth(true)  - wrap.width() )  * 0.5 ),
1747				width    : getValue( width ),
1748				height   : getValue( height )
1749			};
1750
1751			return pos;
1752		},
1753
1754		_getCenter: function( object ) {
1755			var obj   = object || F.current,
1756				wrap  = obj.wrap,
1757				view  = F.getViewport(),
1758				pos   = {},
1759				top   = view.y,
1760				left  = view.x;
1761
1762			pos = {
1763				top    : getValue( Math.max(top,  top  + ((view.h - wrap.outerHeight(true)) * obj.topRatio)) ),
1764				left   : getValue( Math.max(left, left + ((view.w - wrap.outerWidth(true))  * obj.leftRatio)) ),
1765				width  : getValue( wrap.width() ),
1766				height : getValue( wrap.height() )
1767			};
1768
1769			return pos;
1770		},
1771
1772		_prepare : function( object, forClosing ) {
1773			var obj   = object || F.current,
1774				wrap  = obj.wrap,
1775				inner = obj.inner;
1776
1777			// Little trick to avoid animating both elements and to improve performance
1778			wrap.height( wrap.height() );
1779
1780			inner.css({
1781				'width'  : (inner.width() *  100 / wrap.width() )  + '%',
1782				'height' : (Math.floor( (inner.height() * 100 / wrap.height() ) * 100 ) / 100 ) + '%'
1783			});
1784
1785			if (forClosing === true) {
1786				wrap.find('.fancybox-title, .fancybox-spacer, .fancybox-close, .fancybox-nav').remove();
1787			}
1788
1789			inner.css('overflow', 'hidden');
1790		},
1791
1792		fade : function( object, stage ) {
1793			var pos = this._getCenter( object ),
1794				opa = {opacity: 0};
1795
1796			return ((stage === 'open' || stage === 'changeIn') ? [ $.extend(pos, opa), {opacity: 1} ] : [ {}, opa ]);
1797		},
1798
1799		drop : function( object, stage ) {
1800			var a = $.extend(this._getCenter( object ), {opacity: 1}),
1801				b = $.extend({}, a, {opacity: 0, top: getValue( Math.max( F.getViewport().y - object.margin[0], getScalar( a.top ) - 200 ) )});
1802
1803			return ((stage === 'open' || stage === 'changeIn') ? [ b, a ] : [ {}, b ]);
1804		},
1805
1806		elastic : function( object, stage ) {
1807			var wrap      = object.wrap,
1808				margin    = object.margin,
1809				view      = F.getViewport(),
1810				direction = F.direction,
1811				pos       = this._getCenter( object ),
1812				from      = $.extend({}, pos),
1813				to        = $.extend({}, pos),
1814				prop,
1815				amount,
1816				value;
1817
1818			if (stage === 'open') {
1819				from = this._getOrig( object );
1820
1821			} else if (stage === 'close') {
1822				from = {};
1823				to   = this._getOrig( object );
1824
1825			} else if (direction) {
1826				// Calculate max distance and try to avoid scrollbars
1827				prop    = (direction === 'up' || direction === 'down') ? 'top' : 'left';
1828				amount  = (direction === 'up' || direction === 'left') ? 200 : -200;
1829
1830				if (stage === 'changeIn') {
1831					value = getScalar(from[ prop ]) + amount;
1832
1833					if (direction === 'left') {
1834						// from viewport right to center
1835						value = Math.min( value, view.x + view.w - margin[3] - wrap.outerWidth() - 1 );
1836
1837					} else if (direction === 'right') {
1838						// from viewport left to center
1839						value = Math.max( value, view.x - margin[1] );
1840
1841					} else if (direction === 'up') {
1842						// from viewport bottom to center
1843						value = Math.min( value, view.y + view.h - margin[0] - wrap.outerHeight() - 1);
1844
1845					} else {
1846						// down - from viewport top to center
1847						value = Math.max( value, view.y - margin[2] );
1848					}
1849
1850					from[ prop ] = value;
1851
1852				} else {
1853					value = getScalar(wrap.css(prop)) - amount;
1854					from  = {};
1855
1856					if (direction === 'left') {
1857						// from viewport center to left
1858						value = Math.max( value, view.x - margin[3] );
1859
1860					} else if (direction === 'right') {
1861						// from viewport center to right
1862						value = Math.min( value, view.x + view.w - margin[1]  - wrap.outerWidth() - 1 );
1863
1864					} else if (direction === 'up') {
1865						// from viewport center to top
1866						value = Math.max( value, view.y - margin[0]  );
1867
1868					} else {
1869						// down - from center to bottom
1870						value = Math.min( value, view.y + view.h - margin[2] - wrap.outerHeight() - 1 );
1871					}
1872
1873					to[ prop ] = value;
1874				}
1875			}
1876
1877			if (stage === 'open' || stage === 'changeIn') {
1878				from.opacity = 0;
1879				to.opacity   = 1;
1880
1881			} else {
1882				to.opacity   = 0;
1883			}
1884
1885			return [ from, to ];
1886		},
1887
1888		open : function() {
1889			var current   = F.current,
1890				previous  = F.previous,
1891				direction = F.direction,
1892				effect,
1893				pos,
1894				speed,
1895				easing,
1896				stage;
1897
1898			if (previous) {
1899				previous.wrap.stop(true).removeClass('fancybox-opened');
1900			}
1901
1902    		if ( F.isOpened ) {
1903    			effect = current.nextEffect,
1904				speed  = current.nextSpeed;
1905				easing = current.nextEasing;
1906				stage  = 'changeIn';
1907
1908			} else {
1909				effect = current.openEffect;
1910				speed  = current.openSpeed;
1911				easing = current.openEasing;
1912				stage  = 'open';
1913			}
1914
1915			/*
1916			 *	Open current item
1917			 */
1918
1919			if (effect === 'none') {
1920				F._afterZoomIn();
1921
1922			} else {
1923				pos = this[ effect ]( current, stage );
1924
1925				if (effect === 'elastic') {
1926					this._prepare( current );
1927				}
1928
1929				current.wrap.css( pos[ 0 ] );
1930
1931				current.wrap.animate(
1932					pos[ 1 ],
1933					speed,
1934					easing,
1935					F._afterZoomIn
1936				);
1937			}
1938
1939			/*
1940			 *	Close previous item
1941			 */
1942			if (previous) {
1943				if (!F.isOpened || previous.prevEffect === 'none') {
1944					// Remove previous item if it has not fully opened
1945					removeWrap( $('.fancybox-wrap').not( current.wrap ) );
1946
1947				} else {
1948					previous.wrap.stop(true).removeClass('fancybox-opened');
1949
1950					pos = this[ previous.prevEffect ]( previous, 'changeOut' );
1951
1952					this._prepare( previous, true );
1953
1954					previous.wrap.animate(
1955						pos[ 1 ],
1956						previous.prevSpeed,
1957						previous.prevEasing,
1958						function() {
1959							removeWrap( previous.wrap );
1960						}
1961					);
1962				}
1963			}
1964		},
1965
1966		close : function() {
1967			var current  = F.current,
1968				wrap     = current.wrap.stop(true).removeClass('fancybox-opened'),
1969				effect   = current.closeEffect,
1970				pos;
1971
1972			if (effect === 'none') {
1973				return F._afterZoomOut();
1974			}
1975
1976			this._prepare( current, true );
1977
1978			pos = this[ effect ]( current, 'close' );
1979
1980			wrap.addClass('fancybox-animating')
1981				.animate(
1982					pos[ 1 ],
1983					current.closeSpeed,
1984					current.closeEasing,
1985					F._afterZoomOut
1986				);
1987		}
1988	};
1989
1990	/*
1991	 *	Slideshow object
1992	 */
1993
1994	F.slideshow = {
1995		_clear : function () {
1996			if (this._timer) {
1997				clearTimeout(this._timer);
1998			}
1999		},
2000		_set : function () {
2001			this._clear();
2002
2003			if (F.current && this.isActive) {
2004				this._timer = setTimeout(F.next, this._speed);
2005			}
2006		},
2007
2008		_timer   : null,
2009		_speed   : null,
2010
2011		isActive : false,
2012
2013		start : function ( speed ) {
2014			var current = F.current;
2015
2016			if (current && (current.loop || current.index < current.group.length - 1)) {
2017				this.stop();
2018
2019				this.isActive = true;
2020				this._speed   = speed || current.playSpeed;
2021
2022				D.bind({
2023					'beforeLoad.player' : $.proxy(this._clear, this),
2024					'onUpdate.player'   : $.proxy(this._set, this),
2025					'onCancel.player beforeClose.player' : $.proxy(this.stop, this)
2026				});
2027
2028				this._set();
2029
2030				F.trigger('onPlayStart');
2031			}
2032		},
2033
2034		stop : function () {
2035			this._clear();
2036
2037			D.unbind('.player');
2038
2039			this.isActive = false;
2040			this._timer   = this._speed = null;
2041
2042			F.trigger('onPlayEnd');
2043		},
2044
2045		toggle : function() {
2046			if (this.isActive) {
2047				this.stop();
2048
2049			} else {
2050				this.start.apply(this, arguments );
2051			}
2052		}
2053	};
2054
2055	/*
2056	 *	Overlay object
2057	 */
2058
2059	F.overlay = {
2060		el    : null,  // current handle
2061		theme : '',    // current theme
2062
2063		// Public methods
2064		open : function(opts) {
2065			var that  = this,
2066				el    = this.el,
2067				fixed = F.defaults.fixed,
2068				opacity,
2069				theme;
2070
2071			opts = $.extend({}, F.defaults.overlay, opts);
2072
2073			if (el) {
2074				el.stop(true).removeAttr('style').unbind('.overlay');
2075
2076			} else {
2077				el = $('<div class="fancybox-overlay' + (fixed ? ' fancybox-overlay-fixed' : '' ) + '"></div>').appendTo( opts.parent || 'body' );
2078			}
2079
2080			if (opts.closeClick) {
2081				el.bind('click.overlay', function(e) {
2082					// fix Android touch event bubbling issue
2083					if (F.lastTouch && (getTime() - F.lastTouch) < 300) {
2084						return false;
2085					}
2086
2087					if (F.isActive) {
2088						F.close();
2089					} else {
2090						that.close();
2091					}
2092
2093					return false;
2094				});
2095			}
2096
2097			theme = opts.theme || (F.coming ? F.coming.theme : 'default');
2098
2099			if (theme !== this.theme) {
2100				el.removeClass('fancybox-' + this.theme + '-overlay')
2101			}
2102
2103			this.theme = theme;
2104
2105			el.addClass('fancybox-' + theme + '-overlay').css( opts.css );
2106
2107			opacity = el.css('opacity');
2108
2109			if (!this.el && opacity < 1 && opts.speedIn) {
2110				el.css({
2111					opacity : 0,
2112					filter  : 'alpha(opacity=0)'  // This fixes IE flickering
2113				})
2114				.fadeTo( opts.speedIn, opacity );
2115			}
2116
2117			this.el = el;
2118
2119			if (!fixed) {
2120				W.bind('resize.overlay', $.proxy( this.update, this) );
2121
2122				this.update();
2123			}
2124		},
2125
2126		close : function(opts, callback) {
2127			opts = $.extend({}, F.defaults.overlay, opts);
2128
2129			if (this.el) {
2130				this.el.stop(true).fadeOut(opts.speedOut, function() {
2131					W.unbind('resize.overlay');
2132
2133					$('.fancybox-overlay').remove();
2134
2135					F.overlay.el = null;
2136
2137					if ($.isFunction(callback)) {
2138						callback();
2139					}
2140				});
2141			}
2142		},
2143
2144		update : function () {
2145			// Reset width/height so it will not mess
2146			this.el.css({width: '100%', height: '100%'});
2147
2148			this.el.width(D.width()).height(D.height());
2149		}
2150	};
2151
2152	/*
2153	 *	Touch object - adds swipe left/right events
2154	 */
2155
2156	F.touch = {
2157		startX   : 0,
2158		wrapX    : 0,
2159		dx       : 0,
2160		isMoving : false,
2161
2162		_start : function(e) {
2163			var current = F.current,
2164				data    = e.originalEvent.touches ? e.originalEvent.touches[0] : e,
2165				now     = getTime();
2166
2167			if (!F.isOpen || F.wrap.is(':animated')  || !( $(e.target).is(F.inner) || $(e.target).parent().is(F.inner) )) {
2168				return;
2169			}
2170
2171			if (F.lastTouch && (now - F.lastTouch) < 300) {
2172				e.preventDefault();
2173
2174				F.lastTouch = now;
2175
2176				this._cancel(true);
2177
2178				F.toggle();
2179
2180				return false;
2181			}
2182
2183			F.lastTouch = now;
2184
2185			if (F.wrap &&  F.wrap.outerWidth() > F.getViewport().w) {
2186				return;
2187			}
2188
2189			e.preventDefault();
2190
2191			if (data && F.wrap &&  F.wrap.outerWidth() < F.getViewport().w) {
2192				this.startX   = data.pageX;
2193				this.wrapX    = F.wrap.position().left;
2194				this.isMoving = true;
2195
2196				F.inner
2197					.bind('touchmove.fb', $.proxy(this._move, this) )
2198					.one("touchend.fb touchcancel.fb", $.proxy(this._cancel, this) );
2199			}
2200		},
2201
2202		_move : function(e) {
2203			var data = e.originalEvent.touches ? e.originalEvent.touches[0] : e,
2204				dx   = this.startX - data.pageX;
2205
2206			if (!this.isMoving || !F.isOpen) {
2207				return;
2208			}
2209
2210			this.dx = dx;
2211
2212			if (F.current.wrap.outerWidth(true) <= W.width()) {
2213
2214				if (Math.abs(dx) >= 50) {
2215					e.preventDefault();
2216
2217					this.last = 0;
2218
2219					this._cancel(true);
2220
2221					if (dx > 0) {
2222						F.next('left');
2223
2224					} else {
2225						F.prev('right');
2226					}
2227
2228				} else if (Math.abs(dx) > 3) {
2229					e.preventDefault();
2230
2231					this.last = 0;
2232
2233					F.wrap.css('left', this.wrapX - dx);
2234				}
2235			}
2236		},
2237
2238		_clear : function() {
2239			this.startX   = this.wrapX = this.dx = 0;
2240			this.isMoving = false;
2241		},
2242
2243		_cancel : function( stop ) {
2244			if (F.inner) {
2245				F.inner.unbind('touchmove.fb');
2246			}
2247
2248			if (F.isOpen && Math.abs(this.dx) > 3) {
2249				F.reposition(false);
2250			}
2251
2252			this._clear();
2253		},
2254
2255		init : function() {
2256			var that = this;
2257
2258			if (F.inner && F.touch) {
2259				this._cancel(true);
2260
2261				F.inner.bind('touchstart.fb', $.proxy(this._start, this));
2262			}
2263		}
2264	};
2265
2266	/*
2267	 *	Add default easing
2268	 */
2269
2270	if (!$.easing.easeOutQuad) {
2271		$.easing.easeOutQuad = function (x, t, b, c, d) {
2272			return -c *(t/=d)*(t-2) + b;
2273		};
2274	}
2275
2276	/*
2277	 *
2278	 */
2279
2280	D.ready(function() {
2281		var w1, w2, scrollV, scrollH;
2282
2283		// Tests that need a body at doc ready
2284		if ( $.scrollbarWidth === undefined ) {
2285			$.scrollbarWidth = function() {
2286				var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),
2287					child  = parent.children(),
2288					width  = child.innerWidth() - child.height( 99 ).innerWidth();
2289
2290				parent.remove();
2291
2292				return width;
2293			};
2294		}
2295
2296		if ( $.support.fixedPosition === undefined ) {
2297			$.support.fixedPosition = (function() {
2298				var elem  = $('<div style="position:fixed;top:20px;padding:0;margin:0;border:0;"></div>').appendTo('body'),
2299					fixed = elem.css( 'position' ) === 'fixed' && ((elem[0].offsetTop > 18 && elem[0].offsetTop < 22) || elem[0].offsetTop === 15 );
2300
2301				elem.remove();
2302
2303				return fixed;
2304			}());
2305		}
2306
2307		$.extend(F.defaults, {
2308			scrollbarWidth : $.scrollbarWidth(),
2309			fixed  : $.support.fixedPosition,
2310			parent : $('body')
2311		});
2312
2313		// Quick and dirty code to get page scroll-bar width and create CSS style
2314		// Workaround for FF jumping bug
2315		scrollV = W.scrollTop();
2316		scrollH = W.scrollLeft();
2317
2318		w1 = $(window).width();
2319
2320		H.addClass('fancybox-lock-test');
2321
2322		w2 = $(window).width();
2323
2324		H.removeClass('fancybox-lock-test');
2325
2326		W.scrollTop( scrollV ).scrollLeft( scrollH );
2327
2328		F.lockMargin = (w2 - w1);
2329
2330		$("<style type='text/css'>.fancybox-margin{margin-right:" + F.lockMargin + "px;}</style>").appendTo("head");
2331
2332		
2333	});
2334
2335	// jQuery plugin initialization
2336	$.fn.fancybox = function (options) {
2337		var that     = this,
2338			selector = this.length ? this.selector : false,
2339			live     = (selector && selector.indexOf('()') < 0 && !(options && options.live === false));
2340
2341		var handler  = function(e) {
2342			var collection = live ? $(selector) : that,
2343				group  = $(this).blur(),
2344				param  = options.groupAttr || 'data-fancybox-group',
2345				value  = group.attr( param ),
2346				tmp    = this.rel;
2347
2348			if (!value && tmp && tmp !== 'nofollow') {
2349				param = 'rel';
2350				value = tmp;
2351			}
2352
2353			if (value) {
2354				group = collection.filter('[' + param + '="' + value + '"]');
2355
2356				options.index = group.index( this );
2357			}
2358
2359			if (group.length) {
2360				e.preventDefault();
2361
2362				F.open(group.get(), options);
2363			}
2364		};
2365
2366		options = options || {};
2367
2368		if (live) {
2369			D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-close,.fancybox-nav,.fancybox-wrap')", 'click.fb-start', handler);
2370
2371		} else {
2372			that.unbind('click.fb-start').bind('click.fb-start', handler);
2373		}
2374
2375		return this;
2376	};
2377
2378}(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.