Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 espaco 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">The requested content cannot be loaded.<br/>Please try again later.</p>',
141
                                closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',
142
                                next     : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',
143
                                prev     : '<a title="Previous" 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));