fancybox 0.0.1

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