Projet

Général

Profil

Paste
Télécharger (28,4 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / libraries / colorbox-1.6.2 / jquery.colorbox.js @ 0aee3c58

1
/*!
2
        Colorbox 1.6.2
3
        license: MIT
4
        http://www.jacklmoore.com/colorbox
5
*/
6
(function ($, document, window) {
7
        var
8
        // Default settings object.
9
        // See http://jacklmoore.com/colorbox for details.
10
        defaults = {
11
                // data sources
12
                html: false,
13
                photo: false,
14
                iframe: false,
15
                inline: false,
16

    
17
                // behavior and appearance
18
                transition: "elastic",
19
                speed: 300,
20
                fadeOut: 300,
21
                width: false,
22
                initialWidth: "600",
23
                innerWidth: false,
24
                maxWidth: false,
25
                height: false,
26
                initialHeight: "450",
27
                innerHeight: false,
28
                maxHeight: false,
29
                scalePhotos: true,
30
                scrolling: true,
31
                opacity: 0.9,
32
                preloading: true,
33
                className: false,
34
                overlayClose: true,
35
                escKey: true,
36
                arrowKey: true,
37
                top: false,
38
                bottom: false,
39
                left: false,
40
                right: false,
41
                fixed: false,
42
                data: undefined,
43
                closeButton: true,
44
                fastIframe: true,
45
                open: false,
46
                reposition: true,
47
                loop: true,
48
                slideshow: false,
49
                slideshowAuto: true,
50
                slideshowSpeed: 2500,
51
                slideshowStart: "start slideshow",
52
                slideshowStop: "stop slideshow",
53
                photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,
54

    
55
                // alternate image paths for high-res displays
56
                retinaImage: false,
57
                retinaUrl: false,
58
                retinaSuffix: '@2x.$1',
59

    
60
                // internationalization
61
                current: "image {current} of {total}",
62
                previous: "previous",
63
                next: "next",
64
                close: "close",
65
                xhrError: "This content failed to load.",
66
                imgError: "This image failed to load.",
67

    
68
                // accessbility
69
                returnFocus: true,
70
                trapFocus: true,
71

    
72
                // callbacks
73
                onOpen: false,
74
                onLoad: false,
75
                onComplete: false,
76
                onCleanup: false,
77
                onClosed: false,
78

    
79
                rel: function() {
80
                        return this.rel;
81
                },
82
                href: function() {
83
                        // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container')
84
                        return $(this).attr('href');
85
                },
86
                title: function() {
87
                        return this.title;
88
                },
89
                createImg: function() {
90
                        var img = new Image();
91
                        var attrs = $(this).data('cbox-img-attrs');
92

    
93
                        if (typeof attrs === 'object') {
94
                                $.each(attrs, function(key, val){
95
                                        img[key] = val;
96
                                });
97
                        }
98

    
99
                        return img;
100
                },
101
                createIframe: function() {
102
                        var iframe = document.createElement('iframe');
103
                        var attrs = $(this).data('cbox-iframe-attrs');
104

    
105
                        if (typeof attrs === 'object') {
106
                                $.each(attrs, function(key, val){
107
                                        iframe[key] = val;
108
                                });
109
                        }
110

    
111
                        if ('frameBorder' in iframe) {
112
                                iframe.frameBorder = 0;
113
                        }
114
                        if ('allowTransparency' in iframe) {
115
                                iframe.allowTransparency = "true";
116
                        }
117
                        iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching
118
                        iframe.allowFullscreen = true;
119

    
120
                        return iframe;
121
                }
122
        },
123

    
124
        // Abstracting the HTML and event identifiers for easy rebranding
125
        colorbox = 'colorbox',
126
        prefix = 'cbox',
127
        boxElement = prefix + 'Element',
128

    
129
        // Events
130
        event_open = prefix + '_open',
131
        event_load = prefix + '_load',
132
        event_complete = prefix + '_complete',
133
        event_cleanup = prefix + '_cleanup',
134
        event_closed = prefix + '_closed',
135
        event_purge = prefix + '_purge',
136

    
137
        // Cached jQuery Object Variables
138
        $overlay,
139
        $box,
140
        $wrap,
141
        $content,
142
        $topBorder,
143
        $leftBorder,
144
        $rightBorder,
145
        $bottomBorder,
146
        $related,
147
        $window,
148
        $loaded,
149
        $loadingBay,
150
        $loadingOverlay,
151
        $title,
152
        $current,
153
        $slideshow,
154
        $next,
155
        $prev,
156
        $close,
157
        $groupControls,
158
        $events = $('<a/>'), // $({}) would be prefered, but there is an issue with jQuery 1.4.2
159

    
160
        // Variables for cached values or use across multiple functions
161
        settings,
162
        interfaceHeight,
163
        interfaceWidth,
164
        loadedHeight,
165
        loadedWidth,
166
        index,
167
        photo,
168
        open,
169
        active,
170
        closing,
171
        loadingTimer,
172
        publicMethod,
173
        div = "div",
174
        requests = 0,
175
        previousCSS = {},
176
        init;
177

    
178
        // ****************
179
        // HELPER FUNCTIONS
180
        // ****************
181

    
182
        // Convenience function for creating new jQuery objects
183
        function $tag(tag, id, css) {
184
                var element = document.createElement(tag);
185

    
186
                if (id) {
187
                        element.id = prefix + id;
188
                }
189

    
190
                if (css) {
191
                        element.style.cssText = css;
192
                }
193

    
194
                return $(element);
195
        }
196

    
197
        // Get the window height using innerHeight when available to avoid an issue with iOS
198
        // http://bugs.jquery.com/ticket/6724
199
        function winheight() {
200
                return window.innerHeight ? window.innerHeight : $(window).height();
201
        }
202

    
203
        function Settings(element, options) {
204
                if (options !== Object(options)) {
205
                        options = {};
206
                }
207

    
208
                this.cache = {};
209
                this.el = element;
210

    
211
                this.value = function(key) {
212
                        var dataAttr;
213

    
214
                        if (this.cache[key] === undefined) {
215
                                dataAttr = $(this.el).attr('data-cbox-'+key);
216

    
217
                                if (dataAttr !== undefined) {
218
                                        this.cache[key] = dataAttr;
219
                                } else if (options[key] !== undefined) {
220
                                        this.cache[key] = options[key];
221
                                } else if (defaults[key] !== undefined) {
222
                                        this.cache[key] = defaults[key];
223
                                }
224
                        }
225

    
226
                        return this.cache[key];
227
                };
228

    
229
                this.get = function(key) {
230
                        var value = this.value(key);
231
                        return $.isFunction(value) ? value.call(this.el, this) : value;
232
                };
233
        }
234

    
235
        // Determine the next and previous members in a group.
236
        function getIndex(increment) {
237
                var
238
                max = $related.length,
239
                newIndex = (index + increment) % max;
240

    
241
                return (newIndex < 0) ? max + newIndex : newIndex;
242
        }
243

    
244
        // Convert '%' and 'px' values to integers
245
        function setSize(size, dimension) {
246
                return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10));
247
        }
248

    
249
        // Checks an href to see if it is a photo.
250
        // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex.
251
        function isImage(settings, url) {
252
                return settings.get('photo') || settings.get('photoRegex').test(url);
253
        }
254

    
255
        function retinaUrl(settings, url) {
256
                return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url;
257
        }
258

    
259
        function trapFocus(e) {
260
                if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) {
261
                        e.stopPropagation();
262
                        $box.focus();
263
                }
264
        }
265

    
266
        function setClass(str) {
267
                if (setClass.str !== str) {
268
                        $box.add($overlay).removeClass(setClass.str).addClass(str);
269
                        setClass.str = str;
270
                }
271
        }
272

    
273
        function getRelated(rel) {
274
                index = 0;
275

    
276
                if (rel && rel !== false && rel !== 'nofollow') {
277
                        $related = $('.' + boxElement).filter(function () {
278
                                var options = $.data(this, colorbox);
279
                                var settings = new Settings(this, options);
280
                                return (settings.get('rel') === rel);
281
                        });
282
                        index = $related.index(settings.el);
283

    
284
                        // Check direct calls to Colorbox.
285
                        if (index === -1) {
286
                                $related = $related.add(settings.el);
287
                                index = $related.length - 1;
288
                        }
289
                } else {
290
                        $related = $(settings.el);
291
                }
292
        }
293

    
294
        function trigger(event) {
295
                // for external use
296
                $(document).trigger(event);
297
                // for internal use
298
                $events.triggerHandler(event);
299
        }
300

    
301
        var slideshow = (function(){
302
                var active,
303
                        className = prefix + "Slideshow_",
304
                        click = "click." + prefix,
305
                        timeOut;
306

    
307
                function clear () {
308
                        clearTimeout(timeOut);
309
                }
310

    
311
                function set() {
312
                        if (settings.get('loop') || $related[index + 1]) {
313
                                clear();
314
                                timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed'));
315
                        }
316
                }
317

    
318
                function start() {
319
                        $slideshow
320
                                .html(settings.get('slideshowStop'))
321
                                .unbind(click)
322
                                .one(click, stop);
323

    
324
                        $events
325
                                .bind(event_complete, set)
326
                                .bind(event_load, clear);
327

    
328
                        $box.removeClass(className + "off").addClass(className + "on");
329
                }
330

    
331
                function stop() {
332
                        clear();
333

    
334
                        $events
335
                                .unbind(event_complete, set)
336
                                .unbind(event_load, clear);
337

    
338
                        $slideshow
339
                                .html(settings.get('slideshowStart'))
340
                                .unbind(click)
341
                                .one(click, function () {
342
                                        publicMethod.next();
343
                                        start();
344
                                });
345

    
346
                        $box.removeClass(className + "on").addClass(className + "off");
347
                }
348

    
349
                function reset() {
350
                        active = false;
351
                        $slideshow.hide();
352
                        clear();
353
                        $events
354
                                .unbind(event_complete, set)
355
                                .unbind(event_load, clear);
356
                        $box.removeClass(className + "off " + className + "on");
357
                }
358

    
359
                return function(){
360
                        if (active) {
361
                                if (!settings.get('slideshow')) {
362
                                        $events.unbind(event_cleanup, reset);
363
                                        reset();
364
                                }
365
                        } else {
366
                                if (settings.get('slideshow') && $related[1]) {
367
                                        active = true;
368
                                        $events.one(event_cleanup, reset);
369
                                        if (settings.get('slideshowAuto')) {
370
                                                start();
371
                                        } else {
372
                                                stop();
373
                                        }
374
                                        $slideshow.show();
375
                                }
376
                        }
377
                };
378

    
379
        }());
380

    
381

    
382
        function launch(element) {
383
                var options;
384

    
385
                if (!closing) {
386

    
387
                        options = $(element).data(colorbox);
388

    
389
                        settings = new Settings(element, options);
390

    
391
                        getRelated(settings.get('rel'));
392

    
393
                        if (!open) {
394
                                open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
395

    
396
                                setClass(settings.get('className'));
397

    
398
                                // Show colorbox so the sizes can be calculated in older versions of jQuery
399
                                $box.css({visibility:'hidden', display:'block', opacity:''});
400

    
401
                                $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden');
402
                                $content.css({width:'', height:''}).append($loaded);
403

    
404
                                // Cache values needed for size calculations
405
                                interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();
406
                                interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
407
                                loadedHeight = $loaded.outerHeight(true);
408
                                loadedWidth = $loaded.outerWidth(true);
409

    
410
                                // Opens inital empty Colorbox prior to content being loaded.
411
                                var initialWidth = setSize(settings.get('initialWidth'), 'x');
412
                                var initialHeight = setSize(settings.get('initialHeight'), 'y');
413
                                var maxWidth = settings.get('maxWidth');
414
                                var maxHeight = settings.get('maxHeight');
415

    
416
                                settings.w = (maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth;
417
                                settings.h = (maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight;
418

    
419
                                $loaded.css({width:'', height:settings.h});
420
                                publicMethod.position();
421

    
422
                                trigger(event_open);
423
                                settings.get('onOpen');
424

    
425
                                $groupControls.add($title).hide();
426

    
427
                                $box.focus();
428

    
429
                                if (settings.get('trapFocus')) {
430
                                        // Confine focus to the modal
431
                                        // Uses event capturing that is not supported in IE8-
432
                                        if (document.addEventListener) {
433

    
434
                                                document.addEventListener('focus', trapFocus, true);
435

    
436
                                                $events.one(event_closed, function () {
437
                                                        document.removeEventListener('focus', trapFocus, true);
438
                                                });
439
                                        }
440
                                }
441

    
442
                                // Return focus on closing
443
                                if (settings.get('returnFocus')) {
444
                                        $events.one(event_closed, function () {
445
                                                $(settings.el).focus();
446
                                        });
447
                                }
448
                        }
449

    
450
                        var opacity = parseFloat(settings.get('opacity'));
451
                        $overlay.css({
452
                                opacity: opacity === opacity ? opacity : '',
453
                                cursor: settings.get('overlayClose') ? 'pointer' : '',
454
                                visibility: 'visible'
455
                        }).show();
456

    
457
                        if (settings.get('closeButton')) {
458
                                $close.html(settings.get('close')).appendTo($content);
459
                        } else {
460
                                $close.appendTo('<div/>'); // replace with .detach() when dropping jQuery < 1.4
461
                        }
462

    
463
                        load();
464
                }
465
        }
466

    
467
        // Colorbox's markup needs to be added to the DOM prior to being called
468
        // so that the browser will go ahead and load the CSS background images.
469
        function appendHTML() {
470
                if (!$box) {
471
                        init = false;
472
                        $window = $(window);
473
                        $box = $tag(div).attr({
474
                                id: colorbox,
475
                                'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS.
476
                                role: 'dialog',
477
                                tabindex: '-1'
478
                        }).hide();
479
                        $overlay = $tag(div, "Overlay").hide();
480
                        $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]);
481
                        $wrap = $tag(div, "Wrapper");
482
                        $content = $tag(div, "Content").append(
483
                                $title = $tag(div, "Title"),
484
                                $current = $tag(div, "Current"),
485
                                $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}),
486
                                $next = $('<button type="button"/>').attr({id:prefix+'Next'}),
487
                                $slideshow = $tag('button', "Slideshow"),
488
                                $loadingOverlay
489
                        );
490

    
491
                        $close = $('<button type="button"/>').attr({id:prefix+'Close'});
492

    
493
                        $wrap.append( // The 3x3 Grid that makes up Colorbox
494
                                $tag(div).append(
495
                                        $tag(div, "TopLeft"),
496
                                        $topBorder = $tag(div, "TopCenter"),
497
                                        $tag(div, "TopRight")
498
                                ),
499
                                $tag(div, false, 'clear:left').append(
500
                                        $leftBorder = $tag(div, "MiddleLeft"),
501
                                        $content,
502
                                        $rightBorder = $tag(div, "MiddleRight")
503
                                ),
504
                                $tag(div, false, 'clear:left').append(
505
                                        $tag(div, "BottomLeft"),
506
                                        $bottomBorder = $tag(div, "BottomCenter"),
507
                                        $tag(div, "BottomRight")
508
                                )
509
                        ).find('div div').css({'float': 'left'});
510

    
511
                        $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;');
512

    
513
                        $groupControls = $next.add($prev).add($current).add($slideshow);
514
                }
515
                if (document.body && !$box.parent().length) {
516
                        $(document.body).append($overlay, $box.append($wrap, $loadingBay));
517
                }
518
        }
519

    
520
        // Add Colorbox's event bindings
521
        function addBindings() {
522
                function clickHandler(e) {
523
                        // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt.
524
                        // See: http://jacklmoore.com/notes/click-events/
525
                        if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) {
526
                                e.preventDefault();
527
                                launch(this);
528
                        }
529
                }
530

    
531
                if ($box) {
532
                        if (!init) {
533
                                init = true;
534

    
535
                                // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly.
536
                                $next.click(function () {
537
                                        publicMethod.next();
538
                                });
539
                                $prev.click(function () {
540
                                        publicMethod.prev();
541
                                });
542
                                $close.click(function () {
543
                                        publicMethod.close();
544
                                });
545
                                $overlay.click(function () {
546
                                        if (settings.get('overlayClose')) {
547
                                                publicMethod.close();
548
                                        }
549
                                });
550

    
551
                                // Key Bindings
552
                                $(document).bind('keydown.' + prefix, function (e) {
553
                                        var key = e.keyCode;
554
                                        if (open && settings.get('escKey') && key === 27) {
555
                                                e.preventDefault();
556
                                                publicMethod.close();
557
                                        }
558
                                        if (open && settings.get('arrowKey') && $related[1] && !e.altKey) {
559
                                                if (key === 37) {
560
                                                        e.preventDefault();
561
                                                        $prev.click();
562
                                                } else if (key === 39) {
563
                                                        e.preventDefault();
564
                                                        $next.click();
565
                                                }
566
                                        }
567
                                });
568

    
569
                                if ($.isFunction($.fn.on)) {
570
                                        // For jQuery 1.7+
571
                                        $(document).on('click.'+prefix, '.'+boxElement, clickHandler);
572
                                } else {
573
                                        // For jQuery 1.3.x -> 1.6.x
574
                                        // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed.
575
                                        // This is not here for jQuery 1.9, it's here for legacy users.
576
                                        $('.'+boxElement).live('click.'+prefix, clickHandler);
577
                                }
578
                        }
579
                        return true;
580
                }
581
                return false;
582
        }
583

    
584
        // Don't do anything if Colorbox already exists.
585
        if ($[colorbox]) {
586
                return;
587
        }
588

    
589
        // Append the HTML when the DOM loads
590
        $(appendHTML);
591

    
592

    
593
        // ****************
594
        // PUBLIC FUNCTIONS
595
        // Usage format: $.colorbox.close();
596
        // Usage from within an iframe: parent.jQuery.colorbox.close();
597
        // ****************
598

    
599
        publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
600
                var settings;
601
                var $obj = this;
602

    
603
                options = options || {};
604

    
605
                if ($.isFunction($obj)) { // assume a call to $.colorbox
606
                        $obj = $('<a/>');
607
                        options.open = true;
608
                }
609

    
610
                if (!$obj[0]) { // colorbox being applied to empty collection
611
                        return $obj;
612
                }
613

    
614
                appendHTML();
615

    
616
                if (addBindings()) {
617

    
618
                        if (callback) {
619
                                options.onComplete = callback;
620
                        }
621

    
622
                        $obj.each(function () {
623
                                var old = $.data(this, colorbox) || {};
624
                                $.data(this, colorbox, $.extend(old, options));
625
                        }).addClass(boxElement);
626

    
627
                        settings = new Settings($obj[0], options);
628

    
629
                        if (settings.get('open')) {
630
                                launch($obj[0]);
631
                        }
632
                }
633

    
634
                return $obj;
635
        };
636

    
637
        publicMethod.position = function (speed, loadedCallback) {
638
                var
639
                css,
640
                top = 0,
641
                left = 0,
642
                offset = $box.offset(),
643
                scrollTop,
644
                scrollLeft;
645

    
646
                $window.unbind('resize.' + prefix);
647

    
648
                // remove the modal so that it doesn't influence the document width/height
649
                $box.css({top: -9e4, left: -9e4});
650

    
651
                scrollTop = $window.scrollTop();
652
                scrollLeft = $window.scrollLeft();
653

    
654
                if (settings.get('fixed')) {
655
                        offset.top -= scrollTop;
656
                        offset.left -= scrollLeft;
657
                        $box.css({position: 'fixed'});
658
                } else {
659
                        top = scrollTop;
660
                        left = scrollLeft;
661
                        $box.css({position: 'absolute'});
662
                }
663

    
664
                // keeps the top and left positions within the browser's viewport.
665
                if (settings.get('right') !== false) {
666
                        left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.get('right'), 'x'), 0);
667
                } else if (settings.get('left') !== false) {
668
                        left += setSize(settings.get('left'), 'x');
669
                } else {
670
                        left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2);
671
                }
672

    
673
                if (settings.get('bottom') !== false) {
674
                        top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.get('bottom'), 'y'), 0);
675
                } else if (settings.get('top') !== false) {
676
                        top += setSize(settings.get('top'), 'y');
677
                } else {
678
                        top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2);
679
                }
680

    
681
                $box.css({top: offset.top, left: offset.left, visibility:'visible'});
682

    
683
                // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
684
                // but it has to be shrank down around the size of div#colorbox when it's done.  If not,
685
                // it can invoke an obscure IE bug when using iframes.
686
                $wrap[0].style.width = $wrap[0].style.height = "9999px";
687

    
688
                function modalDimensions() {
689
                        $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px';
690
                        $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px';
691
                }
692

    
693
                css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left};
694

    
695
                // setting the speed to 0 if the content hasn't changed size or position
696
                if (speed) {
697
                        var tempSpeed = 0;
698
                        $.each(css, function(i){
699
                                if (css[i] !== previousCSS[i]) {
700
                                        tempSpeed = speed;
701
                                        return;
702
                                }
703
                        });
704
                        speed = tempSpeed;
705
                }
706

    
707
                previousCSS = css;
708

    
709
                if (!speed) {
710
                        $box.css(css);
711
                }
712

    
713
                $box.dequeue().animate(css, {
714
                        duration: speed || 0,
715
                        complete: function () {
716
                                modalDimensions();
717

    
718
                                active = false;
719

    
720
                                // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
721
                                $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
722
                                $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
723

    
724
                                if (settings.get('reposition')) {
725
                                        setTimeout(function () {  // small delay before binding onresize due to an IE8 bug.
726
                                                $window.bind('resize.' + prefix, publicMethod.position);
727
                                        }, 1);
728
                                }
729

    
730
                                if ($.isFunction(loadedCallback)) {
731
                                        loadedCallback();
732
                                }
733
                        },
734
                        step: modalDimensions
735
                });
736
        };
737

    
738
        publicMethod.resize = function (options) {
739
                var scrolltop;
740

    
741
                if (open) {
742
                        options = options || {};
743

    
744
                        if (options.width) {
745
                                settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
746
                        }
747

    
748
                        if (options.innerWidth) {
749
                                settings.w = setSize(options.innerWidth, 'x');
750
                        }
751

    
752
                        $loaded.css({width: settings.w});
753

    
754
                        if (options.height) {
755
                                settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
756
                        }
757

    
758
                        if (options.innerHeight) {
759
                                settings.h = setSize(options.innerHeight, 'y');
760
                        }
761

    
762
                        if (!options.innerHeight && !options.height) {
763
                                scrolltop = $loaded.scrollTop();
764
                                $loaded.css({height: "auto"});
765
                                settings.h = $loaded.height();
766
                        }
767

    
768
                        $loaded.css({height: settings.h});
769

    
770
                        if(scrolltop) {
771
                                $loaded.scrollTop(scrolltop);
772
                        }
773

    
774
                        publicMethod.position(settings.get('transition') === "none" ? 0 : settings.get('speed'));
775
                }
776
        };
777

    
778
        publicMethod.prep = function (object) {
779
                if (!open) {
780
                        return;
781
                }
782

    
783
                var callback, speed = settings.get('transition') === "none" ? 0 : settings.get('speed');
784

    
785
                $loaded.remove();
786

    
787
                $loaded = $tag(div, 'LoadedContent').append(object);
788

    
789
                function getWidth() {
790
                        settings.w = settings.w || $loaded.width();
791
                        settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
792
                        return settings.w;
793
                }
794
                function getHeight() {
795
                        settings.h = settings.h || $loaded.height();
796
                        settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
797
                        return settings.h;
798
                }
799

    
800
                $loaded.hide()
801
                .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
802
                .css({width: getWidth(), overflow: settings.get('scrolling') ? 'auto' : 'hidden'})
803
                .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
804
                .prependTo($content);
805

    
806
                $loadingBay.hide();
807

    
808
                // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
809

    
810
                $(photo).css({'float': 'none'});
811

    
812
                setClass(settings.get('className'));
813

    
814
                callback = function () {
815
                        var total = $related.length,
816
                                iframe,
817
                                complete;
818

    
819
                        if (!open) {
820
                                return;
821
                        }
822

    
823
                        function removeFilter() { // Needed for IE8 in versions of jQuery prior to 1.7.2
824
                                if ($.support.opacity === false) {
825
                                        $box[0].style.removeAttribute('filter');
826
                                }
827
                        }
828

    
829
                        complete = function () {
830
                                clearTimeout(loadingTimer);
831
                                $loadingOverlay.hide();
832
                                trigger(event_complete);
833
                                settings.get('onComplete');
834
                        };
835

    
836

    
837
                        $title.html(settings.get('title')).show();
838
                        $loaded.show();
839

    
840
                        if (total > 1) { // handle grouping
841
                                if (typeof settings.get('current') === "string") {
842
                                        $current.html(settings.get('current').replace('{current}', index + 1).replace('{total}', total)).show();
843
                                }
844

    
845
                                $next[(settings.get('loop') || index < total - 1) ? "show" : "hide"]().html(settings.get('next'));
846
                                $prev[(settings.get('loop') || index) ? "show" : "hide"]().html(settings.get('previous'));
847

    
848
                                slideshow();
849

    
850
                                // Preloads images within a rel group
851
                                if (settings.get('preloading')) {
852
                                        $.each([getIndex(-1), getIndex(1)], function(){
853
                                                var img,
854
                                                        i = $related[this],
855
                                                        settings = new Settings(i, $.data(i, colorbox)),
856
                                                        src = settings.get('href');
857

    
858
                                                if (src && isImage(settings, src)) {
859
                                                        src = retinaUrl(settings, src);
860
                                                        img = document.createElement('img');
861
                                                        img.src = src;
862
                                                }
863
                                        });
864
                                }
865
                        } else {
866
                                $groupControls.hide();
867
                        }
868

    
869
                        if (settings.get('iframe')) {
870

    
871
                                iframe = settings.get('createIframe');
872

    
873
                                if (!settings.get('scrolling')) {
874
                                        iframe.scrolling = "no";
875
                                }
876

    
877
                                $(iframe)
878
                                        .attr({
879
                                                src: settings.get('href'),
880
                                                'class': prefix + 'Iframe'
881
                                        })
882
                                        .one('load', complete)
883
                                        .appendTo($loaded);
884

    
885
                                $events.one(event_purge, function () {
886
                                        iframe.src = "//about:blank";
887
                                });
888

    
889
                                if (settings.get('fastIframe')) {
890
                                        $(iframe).trigger('load');
891
                                }
892
                        } else {
893
                                complete();
894
                        }
895

    
896
                        if (settings.get('transition') === 'fade') {
897
                                $box.fadeTo(speed, 1, removeFilter);
898
                        } else {
899
                                removeFilter();
900
                        }
901
                };
902

    
903
                if (settings.get('transition') === 'fade') {
904
                        $box.fadeTo(speed, 0, function () {
905
                                publicMethod.position(0, callback);
906
                        });
907
                } else {
908
                        publicMethod.position(speed, callback);
909
                }
910
        };
911

    
912
        function load () {
913
                var href, setResize, prep = publicMethod.prep, $inline, request = ++requests;
914

    
915
                active = true;
916

    
917
                photo = false;
918

    
919
                trigger(event_purge);
920
                trigger(event_load);
921
                settings.get('onLoad');
922

    
923
                settings.h = settings.get('height') ?
924
                                setSize(settings.get('height'), 'y') - loadedHeight - interfaceHeight :
925
                                settings.get('innerHeight') && setSize(settings.get('innerHeight'), 'y');
926

    
927
                settings.w = settings.get('width') ?
928
                                setSize(settings.get('width'), 'x') - loadedWidth - interfaceWidth :
929
                                settings.get('innerWidth') && setSize(settings.get('innerWidth'), 'x');
930

    
931
                // Sets the minimum dimensions for use in image scaling
932
                settings.mw = settings.w;
933
                settings.mh = settings.h;
934

    
935
                // Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
936
                // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
937
                if (settings.get('maxWidth')) {
938
                        settings.mw = setSize(settings.get('maxWidth'), 'x') - loadedWidth - interfaceWidth;
939
                        settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
940
                }
941
                if (settings.get('maxHeight')) {
942
                        settings.mh = setSize(settings.get('maxHeight'), 'y') - loadedHeight - interfaceHeight;
943
                        settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
944
                }
945

    
946
                href = settings.get('href');
947

    
948
                loadingTimer = setTimeout(function () {
949
                        $loadingOverlay.show();
950
                }, 100);
951

    
952
                if (settings.get('inline')) {
953
                        var $target = $(href);
954
                        // Inserts an empty placeholder where inline content is being pulled from.
955
                        // An event is bound to put inline content back when Colorbox closes or loads new content.
956
                        $inline = $('<div>').hide().insertBefore($target);
957

    
958
                        $events.one(event_purge, function () {
959
                                $inline.replaceWith($target);
960
                        });
961

    
962
                        prep($target);
963
                } else if (settings.get('iframe')) {
964
                        // IFrame element won't be added to the DOM until it is ready to be displayed,
965
                        // to avoid problems with DOM-ready JS that might be trying to run in that iframe.
966
                        prep(" ");
967
                } else if (settings.get('html')) {
968
                        prep(settings.get('html'));
969
                } else if (isImage(settings, href)) {
970

    
971
                        href = retinaUrl(settings, href);
972

    
973
                        photo = settings.get('createImg');
974

    
975
                        $(photo)
976
                        .addClass(prefix + 'Photo')
977
                        .bind('error.'+prefix,function () {
978
                                prep($tag(div, 'Error').html(settings.get('imgError')));
979
                        })
980
                        .one('load', function () {
981
                                if (request !== requests) {
982
                                        return;
983
                                }
984

    
985
                                // A small pause because some browsers will occassionaly report a
986
                                // img.width and img.height of zero immediately after the img.onload fires
987
                                setTimeout(function(){
988
                                        var percent;
989

    
990
                                        if (settings.get('retinaImage') && window.devicePixelRatio > 1) {
991
                                                photo.height = photo.height / window.devicePixelRatio;
992
                                                photo.width = photo.width / window.devicePixelRatio;
993
                                        }
994

    
995
                                        if (settings.get('scalePhotos')) {
996
                                                setResize = function () {
997
                                                        photo.height -= photo.height * percent;
998
                                                        photo.width -= photo.width * percent;
999
                                                };
1000
                                                if (settings.mw && photo.width > settings.mw) {
1001
                                                        percent = (photo.width - settings.mw) / photo.width;
1002
                                                        setResize();
1003
                                                }
1004
                                                if (settings.mh && photo.height > settings.mh) {
1005
                                                        percent = (photo.height - settings.mh) / photo.height;
1006
                                                        setResize();
1007
                                                }
1008
                                        }
1009

    
1010
                                        if (settings.h) {
1011
                                                photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px';
1012
                                        }
1013

    
1014
                                        if ($related[1] && (settings.get('loop') || $related[index + 1])) {
1015
                                                photo.style.cursor = 'pointer';
1016

    
1017
                                                $(photo).bind('click.'+prefix, function () {
1018
                                                        publicMethod.next();
1019
                                                });
1020
                                        }
1021

    
1022
                                        photo.style.width = photo.width + 'px';
1023
                                        photo.style.height = photo.height + 'px';
1024
                                        prep(photo);
1025
                                }, 1);
1026
                        });
1027

    
1028
                        photo.src = href;
1029

    
1030
                } else if (href) {
1031
                        $loadingBay.load(href, settings.get('data'), function (data, status) {
1032
                                if (request === requests) {
1033
                                        prep(status === 'error' ? $tag(div, 'Error').html(settings.get('xhrError')) : $(this).contents());
1034
                                }
1035
                        });
1036
                }
1037
        }
1038

    
1039
        // Navigates to the next page/image in a set.
1040
        publicMethod.next = function () {
1041
                if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) {
1042
                        index = getIndex(1);
1043
                        launch($related[index]);
1044
                }
1045
        };
1046

    
1047
        publicMethod.prev = function () {
1048
                if (!active && $related[1] && (settings.get('loop') || index)) {
1049
                        index = getIndex(-1);
1050
                        launch($related[index]);
1051
                }
1052
        };
1053

    
1054
        // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close();
1055
        publicMethod.close = function () {
1056
                if (open && !closing) {
1057

    
1058
                        closing = true;
1059
                        open = false;
1060
                        trigger(event_cleanup);
1061
                        settings.get('onCleanup');
1062
                        $window.unbind('.' + prefix);
1063
                        $overlay.fadeTo(settings.get('fadeOut') || 0, 0);
1064

    
1065
                        $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () {
1066
                                $box.hide();
1067
                                $overlay.hide();
1068
                                trigger(event_purge);
1069
                                $loaded.remove();
1070

    
1071
                                setTimeout(function () {
1072
                                        closing = false;
1073
                                        trigger(event_closed);
1074
                                        settings.get('onClosed');
1075
                                }, 1);
1076
                        });
1077
                }
1078
        };
1079

    
1080
        // Removes changes Colorbox made to the document, but does not remove the plugin.
1081
        publicMethod.remove = function () {
1082
                if (!$box) { return; }
1083

    
1084
                $box.stop();
1085
                $[colorbox].close();
1086
                $box.stop(false, true).remove();
1087
                $overlay.remove();
1088
                closing = false;
1089
                $box = null;
1090
                $('.' + boxElement)
1091
                        .removeData(colorbox)
1092
                        .removeClass(boxElement);
1093

    
1094
                $(document).unbind('click.'+prefix).unbind('keydown.'+prefix);
1095
        };
1096

    
1097
        // A method for fetching the current element Colorbox is referencing.
1098
        // returns a jQuery object.
1099
        publicMethod.element = function () {
1100
                return $(settings.el);
1101
        };
1102

    
1103
        publicMethod.settings = defaults;
1104

    
1105
}(jQuery, document, window));