217
206
// Usage from within an iframe: parent.$.fn.colorbox.close();
218
207
// ****************
220
cboxPublic = $.fn.colorbox = function (options, callback) {
209
publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
221
210
var $this = this;
224
if ($this.selector === '') { // empty selector means a direct call, ie: $.fn.colorbox();
227
} else { // else the selector didn't match anything, and colorbox should go ahead and return.
212
if (!$this[0] && $this.selector) { // if a selector was given and it didn't match any elements, go ahead and exit.
216
options = options || {};
219
options.onComplete = callback;
222
if (!$this[0] || $this.selector === undefined) { // detects $.colorbox() and $.fn.colorbox()
224
options.open = true; // assume an immediate open
232
227
$this.each(function () {
233
var data = $.extend({}, $(this).data(colorbox) ? $(this).data(colorbox) : defaults, options);
235
$(this).data(colorbox, data).addClass("cboxElement");
238
$(this).data(colorbox).onComplete = callback;
228
$(this).data(colorbox, $.extend({}, $(this).data(colorbox) || defaults, options)).addClass(boxElement);
242
if (options && options.open) {
249
238
// Initialize ColorBox: store common calculations, preload the interface graphics, append the html.
250
239
// This preps colorbox for a speedy open when clicked, and lightens the burdon on the browser by only
251
240
// having to run once, instead of each time colorbox is opened.
252
cboxPublic.init = function () {
254
// jQuery object generator to save a bit of space
256
return $('<div id="cbox' + id + '"/>');
241
publicMethod.init = function () {
259
242
// Create & Append jQuery Objects
260
243
$window = $(window);
261
$cbox = $('<div id="colorbox"/>');
262
$overlay = $div("Overlay").hide();
244
$box = $div().attr({id: colorbox, 'class': isIE ? prefix + 'IE' : ''});
245
$overlay = $div("Overlay", isIE6 ? 'position:absolute' : '').hide();
263
247
$wrap = $div("Wrapper");
264
248
$content = $div("Content").append(
265
$loaded = $div("LoadedContent").css({width: 0, height: 0}),
266
$loadingOverlay = $div("LoadingOverlay"),
267
$loadingGraphic = $div("LoadingGraphic"),
249
$loaded = $div("LoadedContent", 'width:0; height:0'),
250
$loadingOverlay = $div("LoadingOverlay").add($div("LoadingGraphic")),
268
251
$title = $div("Title"),
269
252
$current = $div("Current"),
270
$slideshow = $div("Slideshow"),
271
253
$next = $div("Next"),
272
254
$prev = $div("Previous"),
255
$slideshow = $div("Slideshow"),
273
256
$close = $div("Close")
275
258
$wrap.append( // The 3x3 Grid that makes up ColorBox
278
261
$topBorder = $div("TopCenter"),
282
265
$leftBorder = $div("MiddleLeft"),
284
267
$rightBorder = $div("MiddleRight")
287
270
$div("BottomLeft"),
288
271
$bottomBorder = $div("BottomCenter"),
289
272
$div("BottomRight")
291
274
).children().children().css({'float': 'left'});
293
$loadingBay = $("<div style='position:absolute; top:0; left:0; width:9999px; height:0;'/>");
295
$('body').prepend($overlay, $cbox.append($wrap, $loadingBay));
298
$cbox.addClass('cboxIE');
300
$overlay.css('position', 'absolute');
304
// Add rollover event to navigation elements
276
$loadingBay = $div(false, 'position:absolute; width:9999px; visibility:hidden; display:none');
278
$('body').prepend($overlay, $box.append($wrap, $loadingBay));
305
280
$content.children()
306
.bind('mouseover mouseout', function(){
307
$(this).toggleClass(hover);
282
$(this).addClass('hover');
284
$(this).removeClass('hover');
285
}).addClass('hover');
310
287
// Cache values needed for size calculations
311
interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(TRUE) - $content.height();//Subtraction needed for IE6
312
interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(TRUE) - $content.width();
313
loadedHeight = $loaded.outerHeight(TRUE);
314
loadedWidth = $loaded.outerWidth(TRUE);
288
interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();//Subtraction needed for IE6
289
interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
290
loadedHeight = $loaded.outerHeight(true);
291
loadedWidth = $loaded.outerWidth(true);
316
293
// Setting padding to remove the need to do size conversions during the animation step.
317
$cbox.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();
294
$box.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();
319
// Setup button & key events.
320
$next.click(cboxPublic.next);
321
$prev.click(cboxPublic.prev);
322
$close.click(cboxPublic.close);
296
// Setup button events.
297
$next.click(publicMethod.next);
298
$prev.click(publicMethod.prev);
299
$close.click(publicMethod.close);
324
301
// Adding the 'hover' class allowed the browser to load the hover-state
325
302
// background graphics. The class can now can be removed.
326
$content.children().removeClass(hover);
303
$content.children().removeClass('hover');
328
$('.cboxElement').live('click', function (e) {
329
if (e.button !== 0 && typeof e.button !== 'undefined') {// checks to see if it was a non-left mouse-click.
305
$('.' + boxElement).live('click', function (e) {
306
// checks to see if it was a non-left mouse-click and for clicks modified with ctrl, shift, or alt.
307
if ((e.button !== 0 && typeof e.button !== 'undefined') || e.ctrlKey || e.shiftKey || e.altKey) {
315
$overlay.click(function () {
316
if (settings.overlayClose) {
317
publicMethod.close();
321
// Set Navigation Key Bindings
322
$(document).bind("keydown", function (e) {
323
if (open && settings.escKey && e.keyCode === 27) {
325
publicMethod.close();
327
if (open && settings.arrowKey && !active && $related[1]) {
328
if (e.keyCode === 37 && (index || settings.loop)) {
331
} else if (e.keyCode === 39 && (index < $related.length - 1 || settings.loop)) {
339
publicMethod.remove = function () {
340
$box.add($overlay).remove();
341
$('.' + boxElement).die('click').removeData(colorbox).removeClass(boxElement);
338
cboxPublic.position = function (speed, loadedCallback) {
344
publicMethod.position = function (speed, loadedCallback) {
341
winHeight = $window.height(),
342
347
// keeps the top and left positions within the browser's viewport.
343
posTop = Math.max(winHeight - settings.h - loadedHeight - interfaceHeight,0)/2 + $window.scrollTop(),
344
posLeft = Math.max(document.documentElement.clientWidth - settings.w - loadedWidth - interfaceWidth,0)/2 + $window.scrollLeft();
348
posTop = Math.max($window.height() - settings.h - loadedHeight - interfaceHeight, 0) / 2 + $window.scrollTop(),
349
posLeft = Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2 + $window.scrollLeft();
346
351
// setting the speed to 0 to reduce the delay between same-sized content.
347
animate_speed = ($cbox.width() === settings.w+loadedWidth && $cbox.height() === settings.h+loadedHeight) ? 0 : speed;
352
animate_speed = ($box.width() === settings.w + loadedWidth && $box.height() === settings.h + loadedHeight) ? 0 : speed;
349
354
// this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
350
355
// but it has to be shrank down around the size of div#colorbox when it's done. If not,
351
356
// it can invoke an obscure IE bug when using iframes.
352
357
$wrap[0].style.width = $wrap[0].style.height = "9999px";
354
function modalDimensions (that) {
355
// loading overlay size has to be sure that IE6 uses the correct height.
359
function modalDimensions(that) {
360
// loading overlay height has to be explicitly set for IE6.
356
361
$topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = that.style.width;
357
$loadingGraphic[0].style.height = $loadingOverlay[0].style.height = $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height;
362
$loadingOverlay[0].style.height = $loadingOverlay[1].style.height = $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height;
360
$cbox.dequeue().animate({width:settings.w+loadedWidth, height:settings.h+loadedHeight, top:posTop, left:posLeft}, {duration: animate_speed,
361
complete: function(){
365
$box.dequeue().animate({width: settings.w + loadedWidth, height: settings.h + loadedHeight, top: posTop, left: posLeft}, {
366
duration: animate_speed,
367
complete: function () {
362
368
modalDimensions(this);
366
372
// shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
367
$wrap[0].style.width = (settings.w+loadedWidth+interfaceWidth) + "px";
368
$wrap[0].style.height = (settings.h+loadedHeight+interfaceHeight) + "px";
373
$wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
374
$wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
370
if (loadedCallback) {loadedCallback();}
376
if (loadedCallback) {
373
381
modalDimensions(this);
378
cboxPublic.resize = function (object) {
388
speed = settings.transition==="none" ? 0 : settings.speed;
390
$window.unbind(cbox_resize);
393
timeout = setTimeout(function(){ // timer allows IE to render the dimensions before attempting to calculate the height
386
publicMethod.resize = function (options) {
388
options = options || {};
391
settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
393
if (options.innerWidth) {
394
settings.w = setSize(options.innerWidth, 'x');
396
$loaded.css({width: settings.w});
398
if (options.height) {
399
settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
401
if (options.innerHeight) {
402
settings.h = setSize(options.innerHeight, 'y');
404
if (!options.innerHeight && !options.height) {
394
405
var $child = $loaded.wrapInner("<div style='overflow:auto'></div>").children(); // temporary wrapper to get an accurate estimate of just how high the total content should be.
395
406
settings.h = $child.height();
396
$loaded.css({height:settings.h});
397
407
$child.replaceWith($child.children()); // ditch the temporary wrapper div used in height calculation
398
cboxPublic.position(speed);
409
$loaded.css({height: settings.h});
411
publicMethod.position(settings.transition === "none" ? 0 : settings.speed);
415
publicMethod.prep = function (object) {
421
speed = settings.transition === "none" ? 0 : settings.speed;
423
$window.unbind('resize.' + prefix);
403
424
$loaded.remove();
404
$loaded = $('<div id="cboxLoadedContent"/>').html(object);
425
$loaded = $div('LoadedContent').html(object);
427
function getWidth() {
407
428
settings.w = settings.w || $loaded.width();
408
429
settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
409
430
return settings.w;
411
function getHeight(){
432
function getHeight() {
412
433
settings.h = settings.h || $loaded.height();
413
434
settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
414
435
return settings.h;
418
.appendTo($loadingBay)// content has to be appended to the DOM for accurate size calculations. Appended to an absolutely positioned element, rather than BODY, which avoids an extremely brief display of the vertical scrollbar in Firefox that can occur for a small minority of websites.
419
.css({width:getWidth(), overflow:settings.scrolling ? 'auto' : 'hidden'})
420
.css({height:getHeight()})// sets the height independently from the width in case the new width influences the value of height.
439
.appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
440
.css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'})
441
.css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
421
442
.prependTo($content);
423
$('#cboxPhoto').css({cssFloat:'none'});// 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.
446
$('#' + prefix + 'Photo').css({cssFloat: 'none'});// 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.
425
448
// Hides SELECT elements in IE6 because they would otherwise sit on top of the overlay.
427
$('select:not(#colorbox select)').filter(function(){
450
$('select').not($box.find('select')).filter(function () {
428
451
return this.style.visibility !== 'hidden';
429
}).css({'visibility':'hidden'}).one(cbox_cleanup, function(){
452
}).css({'visibility': 'hidden'}).one(event_cleanup, function () {
430
453
this.style.visibility = 'inherit';
434
function setPosition (s) {
435
cboxPublic.position(s, function(){
436
if (!open) { return; }
457
function setPosition(s) {
458
var prev, prevSrc, next, nextSrc, total = $related.length, loop = settings.loop;
459
publicMethod.position(s, function () {
460
function defilter() {
462
//IE adds a filter when ColorBox fades in and out that can cause problems if the loaded content contains transparent pngs.
463
$box[0].style.removeAttribute("filter");
439
472
//This fadeIn helps the bicubic resampling to kick-in.
440
if( photo ){$loaded.fadeIn(100);}
441
//IE adds a filter when ColorBox fades in and out that can cause problems if the loaded content contains transparent pngs.
442
$cbox[0].style.removeAttribute("filter");
445
478
//Waited until the iframe is added to the DOM & it is visible before setting the src.
446
479
//This increases compatability with pages using DOM dependent JavaScript.
448
$loaded.append("<iframe id='cboxIframe'" + (settings.scrolling ? " " : "scrolling='no'") + " name='iframe_"+new Date().getTime()+"' frameborder=0 src='"+settings.href+"' " + (isIE ? "allowtransparency='true'" : '') + " />");
480
if (settings.iframe) {
481
$("<iframe frameborder=0" + (settings.scrolling ? "" : " scrolling='no'") + (isIE ? " allowtransparency='true'" : '') + "/>")
482
.attr({src: settings.href, name: new Date().getTime()})
453
488
$title.show().html(settings.title);
455
if ($related.length>1) {
456
$current.html(settings.current.replace(/\{current\}/, index+1).replace(/\{total\}/, $related.length)).show();
457
$next.html(settings.next).show();
458
$prev.html(settings.previous).show();
460
if(settings.slideshow){
490
if (total > 1) { // handle grouping
491
$current.html(settings.current.replace(/\{current\}/, index + 1).replace(/\{total\}/, total)).show();
493
$next[(loop || index < total - 1) ? "show" : "hide"]().html(settings.next);
494
$prev[(loop || index) ? "show" : "hide"]().html(settings.previous);
496
prev = index ? $related[index - 1] : $related[total - 1];
497
next = index < total - 1 ? $related[index + 1] : $related[0];
499
if (settings.slideshow) {
461
500
$slideshow.show();
501
if (index === total - 1 && !loop && $box.is('.' + prefix + 'Slideshow_on')) {
506
// Preloads images within a rel group
507
if (settings.preloading) {
508
nextSrc = $(next).data(colorbox).href || next.href;
509
prevSrc = $(prev).data(colorbox).href || prev.href;
511
if (isImage(nextSrc)) {
512
$('<img/>')[0].src = nextSrc;
515
if (isImage(prevSrc)) {
516
$('<img/>')[0].src = prevSrc;
465
521
$loadingOverlay.hide();
466
$loadingGraphic.hide();
468
$.event.trigger(cbox_complete);
523
if (settings.transition === 'fade') {
524
$box.fadeTo(speed, 1, function () {
531
$window.bind('resize.' + prefix, function () {
532
publicMethod.position(0);
535
$.event.trigger(event_complete);
469
536
if (settings.onComplete) {
470
537
settings.onComplete.call(element);
473
if (settings.transition === 'fade'){
474
$cbox.fadeTo(speed, 1, function(){
475
if(isIE){$cbox[0].style.removeAttribute("filter");}
479
$window.bind(cbox_resize, function(){
480
cboxPublic.position(0);
485
if((settings.transition === 'fade' && $cbox.fadeTo(speed, 0, function(){setPosition(0);})) || setPosition(speed)){}
487
// Preloads images within a rel group
488
if (settings.preloading && $related.length>1) {
489
prev = index > 0 ? $related[index-1] : $related[$related.length-1];
490
next = index < $related.length-1 ? $related[index+1] : $related[0];
491
nextSrc = $(next).data(colorbox).href || next.href;
492
prevSrc = $(prev).data(colorbox).href || prev.href;
494
if(isImage(nextSrc)){
495
$('<img />').attr('src', nextSrc);
498
if(isImage(prevSrc)){
499
$('<img />').attr('src', prevSrc);
542
if (settings.transition === 'fade') {
543
$box.fadeTo(speed, 0, function () {
504
cboxPublic.load = function () {
505
var href, img, setResize, resize = cboxPublic.resize;
511
// I decided to comment this out because I can see it causing problems as users
512
// really should just set the dimensions on their IMG elements instead,
513
// but I'm leaving the code in as it may be useful to someone.
514
// To use, uncomment the function and change 'if(textStatus === "success"){ resize(this); }'
515
// to 'if(textStatus === "success"){ preload(this); }'
517
// Preload loops through the HTML to find IMG elements and loads their sources.
518
// This allows the resize method to accurately estimate the dimensions of the new content.
519
function preload(html){
522
$imgs = $ajax.find('img'),
526
var img = new Image();
529
img.onload = loadloop;
530
img.src = $imgs[x].src;
551
publicMethod.load = function () {
552
var href, img, setResize, prep = publicMethod.prep;
540
556
element = $related[index];
542
settings = $(element).data(colorbox);
558
settings = $.extend({}, $(element).data(colorbox));
544
560
//convert functions to static values
547
$.event.trigger(cbox_load);
563
$.event.trigger(event_load);
548
564
if (settings.onLoad) {
549
565
settings.onLoad.call(element);
552
// Evaluate the height based on the optional height and width settings.
553
568
settings.h = settings.height ?
554
569
setSize(settings.height, 'y') - loadedHeight - interfaceHeight :
555
settings.innerHeight ?
556
setSize(settings.innerHeight, 'y') :
570
settings.innerHeight && setSize(settings.innerHeight, 'y');
558
572
settings.w = settings.width ?
559
573
setSize(settings.width, 'x') - loadedWidth - interfaceWidth :
560
settings.innerWidth ?
561
setSize(settings.innerWidth, 'x') :
574
settings.innerWidth && setSize(settings.innerWidth, 'x');
564
576
// Sets the minimum dimensions for use in image scaling
565
577
settings.mw = settings.w;
579
591
href = settings.href;
581
593
$loadingOverlay.show();
582
$loadingGraphic.show();
584
595
if (settings.inline) {
585
596
// Inserts an empty placeholder where inline content is being pulled from.
586
597
// An event is bound to put inline content back when ColorBox closes or loads new content.
587
$('<div id="cboxInlineTemp" />').hide().insertBefore($(href)[0]).bind(cbox_load+' '+cbox_cleanup, function(){
598
$div('InlineTemp').hide().insertBefore($(href)[0]).bind(event_load + ' ' + event_cleanup, function () {
588
599
$(this).replaceWith($loaded.children());
591
602
} else if (settings.iframe) {
592
603
// IFrame element won't be added to the DOM until it is ready to be displayed,
593
604
// to avoid problems with DOM-ready JS that might be trying to run in that iframe.
595
606
} else if (settings.html) {
596
resize(settings.html);
597
} else if (isImage(href)){
608
} else if (isImage(href)) {
598
609
img = new Image();
599
img.onload = function(){
610
img.onload = function () {
602
613
img.onload = null;
604
img.id = 'cboxPhoto';
606
$(img).css({margin:'auto', border:'none', display:'block', cssFloat:'left'});
608
if(settings.scalePhotos){
609
setResize = function(){
614
img.id = prefix + 'Photo';
615
$(img).css({margin: 'auto', border: 'none', display: 'block', cssFloat: 'left'});
617
if (settings.scalePhotos) {
618
setResize = function () {
610
619
img.height -= img.height * percent;
611
620
img.width -= img.width * percent;
613
if(settings.mw && img.width > settings.mw){
622
if (settings.mw && img.width > settings.mw) {
614
623
percent = (img.width - settings.mw) / img.width;
617
if(settings.mh && img.height > settings.mh){
626
if (settings.mh && img.height > settings.mh) {
618
627
percent = (img.height - settings.mh) / img.height;
623
632
if (settings.h) {
624
img.style.marginTop = Math.max(settings.h - img.height,0)/2 + 'px';
629
if($related.length > 1){
630
$(img).css({cursor:'pointer'}).click(cboxPublic.next);
634
img.style.msInterpolationMode='bicubic';
633
img.style.marginTop = Math.max(settings.h - img.height, 0) / 2 + 'px';
636
setTimeout(function () { // Chrome will sometimes report a 0 by 0 size if there isn't pause in execution
640
if ($related[1] && (index < $related.length - 1 || settings.loop)) {
641
$(img).css({cursor: 'pointer'}).click(publicMethod.next);
645
img.style.msInterpolationMode = 'bicubic';
639
$('<div />').appendTo($loadingBay).load(href, function(data, textStatus){
640
if(textStatus === "success"){
643
resize($("<p>Request unsuccessful.</p>"));
650
$div().appendTo($loadingBay).load(href, function (data, status, xhr) {
651
prep(status === 'error' ? 'Request unsuccessful: ' + xhr.statusText : this);
649
656
// Navigates to the next page/image in a set.
650
cboxPublic.next = function () {
652
index = index < $related.length-1 ? index+1 : 0;
657
publicMethod.next = function () {
659
index = index < $related.length - 1 ? index + 1 : 0;
657
cboxPublic.prev = function () {
659
index = index > 0 ? index-1 : $related.length-1;
664
publicMethod.prev = function () {
666
index = index ? index - 1 : $related.length - 1;
664
cboxPublic.slideshow = function () {
665
var stop, timeOut, className = 'cboxSlideshow_';
671
publicMethod.slideshow = function () {
672
var stop, timeOut, className = prefix + 'Slideshow_';
667
$slideshow.bind(cbox_closed, function(){
674
$slideshow.bind(event_closed, function () {
668
675
$slideshow.unbind();
669
676
clearTimeout(timeOut);
670
$cbox.removeClass(className+"off"+" "+className+"on");
677
$box.removeClass(className + "off " + className + "on");
675
682
.text(settings.slideshowStop)
676
.bind(cbox_complete, function(){
677
timeOut = setTimeout(cboxPublic.next, settings.slideshowSpeed);
683
.bind(event_complete, function () {
684
timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);
679
.bind(cbox_load, function(){
686
.bind(event_load, function () {
680
687
clearTimeout(timeOut);
681
}).one("click", function(){
688
}).one("click", function () {
683
$(this).removeClass(hover);
685
$cbox.removeClass(className+"off").addClass(className+"on");
691
$box.removeClass(className + "off").addClass(className + "on");
689
695
clearTimeout(timeOut);
691
697
.text(settings.slideshowStart)
692
.unbind(cbox_complete+' '+cbox_load)
693
.one("click", function(){
698
.unbind(event_complete + ' ' + event_load)
699
.one("click", function () {
695
timeOut = setTimeout(cboxPublic.next, settings.slideshowSpeed);
696
$(this).removeClass(hover);
701
timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);
698
$cbox.removeClass(className+"on").addClass(className+"off");
703
$box.removeClass(className + "on").addClass(className + "off");
701
if(settings.slideshow && $related.length>1){
702
if(settings.slideshowAuto){
706
if (settings.slideshow && $related[1]) {
707
if (settings.slideshowAuto) {