Subversion-Projekte lars-tiefland.webanos.zeldi.de

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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