PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.37
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.37
3.37 3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 All 142 releases
photonic / include / ext / colorbox / colorbox.js

colorbox.js in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 3.37, at include/ext/colorbox/colorbox.js

1,105 lines 28.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*!
2 Colorbox 1.6.4
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 preferred, 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 = $('<button type="button"/>').attr({id:prefix+'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).eq(0);
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 occasionally 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));