]> git.mxchange.org Git - friendica.git/blob - library/colorbox/jquery.colorbox.js
Merge pull request #3874 from tobiasd/20171009-checkversion
[friendica.git] / library / colorbox / jquery.colorbox.js
1 /*!
2         Colorbox 1.6.3
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 = Math.max((maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth, 0);
417                                 settings.h = Math.max((maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight, 0);
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));