1 | /*! |
---|
2 | Colorbox v1.4.27 - 2013-07-16 |
---|
3 | jQuery lightbox and modal window plugin |
---|
4 | (c) 2013 Jack Moore - http://www.jacklmoore.com/colorbox |
---|
5 | license: http://www.opensource.org/licenses/mit-license.php |
---|
6 | */ |
---|
7 | (function ($, document, window) { |
---|
8 | var |
---|
9 | // Default settings object. |
---|
10 | // See http://jacklmoore.com/colorbox for details. |
---|
11 | defaults = { |
---|
12 | transition: "elastic", |
---|
13 | speed: 300, |
---|
14 | fadeOut: 300, |
---|
15 | width: false, |
---|
16 | initialWidth: "600", |
---|
17 | innerWidth: false, |
---|
18 | maxWidth: false, |
---|
19 | height: false, |
---|
20 | initialHeight: "450", |
---|
21 | innerHeight: false, |
---|
22 | maxHeight: false, |
---|
23 | scalePhotos: true, |
---|
24 | scrolling: true, |
---|
25 | inline: false, |
---|
26 | html: false, |
---|
27 | iframe: false, |
---|
28 | fastIframe: true, |
---|
29 | photo: false, |
---|
30 | href: false, |
---|
31 | title: false, |
---|
32 | rel: false, |
---|
33 | opacity: 0.9, |
---|
34 | preloading: true, |
---|
35 | className: false, |
---|
36 | |
---|
37 | // alternate image paths for high-res displays |
---|
38 | retinaImage: false, |
---|
39 | retinaUrl: false, |
---|
40 | retinaSuffix: '@2x.$1', |
---|
41 | |
---|
42 | // internationalization |
---|
43 | current: "image {current} of {total}", |
---|
44 | previous: "previous", |
---|
45 | next: "next", |
---|
46 | close: "close", |
---|
47 | xhrError: "This content failed to load.", |
---|
48 | imgError: "This image failed to load.", |
---|
49 | |
---|
50 | open: false, |
---|
51 | returnFocus: true, |
---|
52 | trapFocus: true, |
---|
53 | reposition: true, |
---|
54 | loop: true, |
---|
55 | slideshow: false, |
---|
56 | slideshowAuto: true, |
---|
57 | slideshowSpeed: 2500, |
---|
58 | slideshowStart: "start slideshow", |
---|
59 | slideshowStop: "stop slideshow", |
---|
60 | photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp)((#|\?).*)?$/i, |
---|
61 | |
---|
62 | onOpen: false, |
---|
63 | onLoad: false, |
---|
64 | onComplete: false, |
---|
65 | onCleanup: false, |
---|
66 | onClosed: false, |
---|
67 | |
---|
68 | overlayClose: true, |
---|
69 | escKey: true, |
---|
70 | arrowKey: true, |
---|
71 | top: false, |
---|
72 | bottom: false, |
---|
73 | left: false, |
---|
74 | right: false, |
---|
75 | fixed: false, |
---|
76 | data: undefined, |
---|
77 | closeButton: true |
---|
78 | }, |
---|
79 | |
---|
80 | // Abstracting the HTML and event identifiers for easy rebranding |
---|
81 | colorbox = 'colorbox', |
---|
82 | prefix = 'cbox', |
---|
83 | boxElement = prefix + 'Element', |
---|
84 | |
---|
85 | // Events |
---|
86 | event_open = prefix + '_open', |
---|
87 | event_load = prefix + '_load', |
---|
88 | event_complete = prefix + '_complete', |
---|
89 | event_cleanup = prefix + '_cleanup', |
---|
90 | event_closed = prefix + '_closed', |
---|
91 | event_purge = prefix + '_purge', |
---|
92 | |
---|
93 | // Cached jQuery Object Variables |
---|
94 | $overlay, |
---|
95 | $box, |
---|
96 | $wrap, |
---|
97 | $content, |
---|
98 | $topBorder, |
---|
99 | $leftBorder, |
---|
100 | $rightBorder, |
---|
101 | $bottomBorder, |
---|
102 | $related, |
---|
103 | $window, |
---|
104 | $loaded, |
---|
105 | $loadingBay, |
---|
106 | $loadingOverlay, |
---|
107 | $title, |
---|
108 | $current, |
---|
109 | $slideshow, |
---|
110 | $next, |
---|
111 | $prev, |
---|
112 | $close, |
---|
113 | $groupControls, |
---|
114 | $events = $('<a/>'), |
---|
115 | |
---|
116 | // Variables for cached values or use across multiple functions |
---|
117 | settings, |
---|
118 | interfaceHeight, |
---|
119 | interfaceWidth, |
---|
120 | loadedHeight, |
---|
121 | loadedWidth, |
---|
122 | element, |
---|
123 | index, |
---|
124 | photo, |
---|
125 | open, |
---|
126 | active, |
---|
127 | closing, |
---|
128 | loadingTimer, |
---|
129 | publicMethod, |
---|
130 | div = "div", |
---|
131 | className, |
---|
132 | requests = 0, |
---|
133 | previousCSS = {}, |
---|
134 | init; |
---|
135 | |
---|
136 | // **************** |
---|
137 | // HELPER FUNCTIONS |
---|
138 | // **************** |
---|
139 | |
---|
140 | // Convenience function for creating new jQuery objects |
---|
141 | function $tag(tag, id, css) { |
---|
142 | var element = document.createElement(tag); |
---|
143 | |
---|
144 | if (id) { |
---|
145 | element.id = prefix + id; |
---|
146 | } |
---|
147 | |
---|
148 | if (css) { |
---|
149 | element.style.cssText = css; |
---|
150 | } |
---|
151 | |
---|
152 | return $(element); |
---|
153 | } |
---|
154 | |
---|
155 | // Get the window height using innerHeight when available to avoid an issue with iOS |
---|
156 | // http://bugs.jquery.com/ticket/6724 |
---|
157 | function winheight() { |
---|
158 | return window.innerHeight ? window.innerHeight : $(window).height(); |
---|
159 | } |
---|
160 | |
---|
161 | // Determine the next and previous members in a group. |
---|
162 | function getIndex(increment) { |
---|
163 | var |
---|
164 | max = $related.length, |
---|
165 | newIndex = (index + increment) % max; |
---|
166 | |
---|
167 | return (newIndex < 0) ? max + newIndex : newIndex; |
---|
168 | } |
---|
169 | |
---|
170 | // Convert '%' and 'px' values to integers |
---|
171 | function setSize(size, dimension) { |
---|
172 | return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10)); |
---|
173 | } |
---|
174 | |
---|
175 | // Checks an href to see if it is a photo. |
---|
176 | // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex. |
---|
177 | function isImage(settings, url) { |
---|
178 | return settings.photo || settings.photoRegex.test(url); |
---|
179 | } |
---|
180 | |
---|
181 | function retinaUrl(settings, url) { |
---|
182 | return settings.retinaUrl && window.devicePixelRatio > 1 ? url.replace(settings.photoRegex, settings.retinaSuffix) : url; |
---|
183 | } |
---|
184 | |
---|
185 | function trapFocus(e) { |
---|
186 | if ('contains' in $box[0] && !$box[0].contains(e.target)) { |
---|
187 | e.stopPropagation(); |
---|
188 | $box.focus(); |
---|
189 | } |
---|
190 | } |
---|
191 | |
---|
192 | // Assigns function results to their respective properties |
---|
193 | function makeSettings() { |
---|
194 | var i, |
---|
195 | data = $.data(element, colorbox); |
---|
196 | |
---|
197 | if (data == null) { |
---|
198 | settings = $.extend({}, defaults); |
---|
199 | if (console && console.log) { |
---|
200 | console.log('Error: cboxElement missing settings object'); |
---|
201 | } |
---|
202 | } else { |
---|
203 | settings = $.extend({}, data); |
---|
204 | } |
---|
205 | |
---|
206 | for (i in settings) { |
---|
207 | if ($.isFunction(settings[i]) && i.slice(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time. |
---|
208 | settings[i] = settings[i].call(element); |
---|
209 | } |
---|
210 | } |
---|
211 | |
---|
212 | settings.rel = settings.rel || element.rel || $(element).data('rel') || 'nofollow'; |
---|
213 | settings.href = settings.href || $(element).attr('href'); |
---|
214 | settings.title = settings.title || element.title; |
---|
215 | |
---|
216 | if (typeof settings.href === "string") { |
---|
217 | settings.href = $.trim(settings.href); |
---|
218 | } |
---|
219 | } |
---|
220 | |
---|
221 | function trigger(event, callback) { |
---|
222 | // for external use |
---|
223 | $(document).trigger(event); |
---|
224 | |
---|
225 | // for internal use |
---|
226 | $events.trigger(event); |
---|
227 | |
---|
228 | if ($.isFunction(callback)) { |
---|
229 | callback.call(element); |
---|
230 | } |
---|
231 | } |
---|
232 | |
---|
233 | // Slideshow functionality |
---|
234 | function slideshow() { |
---|
235 | var |
---|
236 | timeOut, |
---|
237 | className = prefix + "Slideshow_", |
---|
238 | click = "click." + prefix, |
---|
239 | clear, |
---|
240 | set, |
---|
241 | start, |
---|
242 | stop; |
---|
243 | |
---|
244 | if (settings.slideshow && $related[1]) { |
---|
245 | clear = function () { |
---|
246 | clearTimeout(timeOut); |
---|
247 | }; |
---|
248 | |
---|
249 | set = function () { |
---|
250 | if (settings.loop || $related[index + 1]) { |
---|
251 | timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed); |
---|
252 | } |
---|
253 | }; |
---|
254 | |
---|
255 | start = function () { |
---|
256 | $slideshow |
---|
257 | .html(settings.slideshowStop) |
---|
258 | .unbind(click) |
---|
259 | .one(click, stop); |
---|
260 | |
---|
261 | $events |
---|
262 | .bind(event_complete, set) |
---|
263 | .bind(event_load, clear) |
---|
264 | .bind(event_cleanup, stop); |
---|
265 | |
---|
266 | $box.removeClass(className + "off").addClass(className + "on"); |
---|
267 | }; |
---|
268 | |
---|
269 | stop = function () { |
---|
270 | clear(); |
---|
271 | |
---|
272 | $events |
---|
273 | .unbind(event_complete, set) |
---|
274 | .unbind(event_load, clear) |
---|
275 | .unbind(event_cleanup, stop); |
---|
276 | |
---|
277 | $slideshow |
---|
278 | .html(settings.slideshowStart) |
---|
279 | .unbind(click) |
---|
280 | .one(click, function () { |
---|
281 | publicMethod.next(); |
---|
282 | start(); |
---|
283 | }); |
---|
284 | |
---|
285 | $box.removeClass(className + "on").addClass(className + "off"); |
---|
286 | }; |
---|
287 | |
---|
288 | if (settings.slideshowAuto) { |
---|
289 | start(); |
---|
290 | } else { |
---|
291 | stop(); |
---|
292 | } |
---|
293 | } else { |
---|
294 | $box.removeClass(className + "off " + className + "on"); |
---|
295 | } |
---|
296 | } |
---|
297 | |
---|
298 | function launch(target) { |
---|
299 | if (!closing) { |
---|
300 | |
---|
301 | element = target; |
---|
302 | |
---|
303 | makeSettings(); |
---|
304 | |
---|
305 | $related = $(element); |
---|
306 | |
---|
307 | index = 0; |
---|
308 | |
---|
309 | if (settings.rel !== 'nofollow') { |
---|
310 | $related = $('.' + boxElement).filter(function () { |
---|
311 | var data = $.data(this, colorbox), |
---|
312 | relRelated; |
---|
313 | |
---|
314 | if (data) { |
---|
315 | relRelated = $(this).data('rel') || data.rel || this.rel; |
---|
316 | } |
---|
317 | |
---|
318 | return (relRelated === settings.rel); |
---|
319 | }); |
---|
320 | index = $related.index(element); |
---|
321 | |
---|
322 | // Check direct calls to Colorbox. |
---|
323 | if (index === -1) { |
---|
324 | $related = $related.add(element); |
---|
325 | index = $related.length - 1; |
---|
326 | } |
---|
327 | } |
---|
328 | |
---|
329 | $overlay.css({ |
---|
330 | opacity: parseFloat(settings.opacity), |
---|
331 | cursor: settings.overlayClose ? "pointer" : "auto", |
---|
332 | visibility: 'visible' |
---|
333 | }).show(); |
---|
334 | |
---|
335 | |
---|
336 | if (className) { |
---|
337 | $box.add($overlay).removeClass(className); |
---|
338 | } |
---|
339 | if (settings.className) { |
---|
340 | $box.add($overlay).addClass(settings.className); |
---|
341 | } |
---|
342 | className = settings.className; |
---|
343 | |
---|
344 | if (settings.closeButton) { |
---|
345 | $close.html(settings.close).appendTo($content); |
---|
346 | } else { |
---|
347 | $close.appendTo('<div/>'); |
---|
348 | } |
---|
349 | |
---|
350 | if (!open) { |
---|
351 | open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. |
---|
352 | |
---|
353 | // Show colorbox so the sizes can be calculated in older versions of jQuery |
---|
354 | $box.css({visibility:'hidden', display:'block'}); |
---|
355 | |
---|
356 | $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden'); |
---|
357 | $content.css({width:'', height:''}).append($loaded); |
---|
358 | |
---|
359 | // Cache values needed for size calculations |
---|
360 | interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height(); |
---|
361 | interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width(); |
---|
362 | loadedHeight = $loaded.outerHeight(true); |
---|
363 | loadedWidth = $loaded.outerWidth(true); |
---|
364 | |
---|
365 | // Opens inital empty Colorbox prior to content being loaded. |
---|
366 | settings.w = setSize(settings.initialWidth, 'x'); |
---|
367 | settings.h = setSize(settings.initialHeight, 'y'); |
---|
368 | publicMethod.position(); |
---|
369 | |
---|
370 | slideshow(); |
---|
371 | |
---|
372 | trigger(event_open, settings.onOpen); |
---|
373 | |
---|
374 | $groupControls.add($title).hide(); |
---|
375 | |
---|
376 | $box.focus(); |
---|
377 | |
---|
378 | |
---|
379 | if (settings.trapFocus) { |
---|
380 | // Confine focus to the modal |
---|
381 | // Uses event capturing that is not supported in IE8- |
---|
382 | if (document.addEventListener) { |
---|
383 | |
---|
384 | document.addEventListener('focus', trapFocus, true); |
---|
385 | |
---|
386 | $events.one(event_closed, function () { |
---|
387 | document.removeEventListener('focus', trapFocus, true); |
---|
388 | }); |
---|
389 | } |
---|
390 | } |
---|
391 | |
---|
392 | // Return focus on closing |
---|
393 | if (settings.returnFocus) { |
---|
394 | $events.one(event_closed, function () { |
---|
395 | $(element).focus(); |
---|
396 | }); |
---|
397 | } |
---|
398 | } |
---|
399 | |
---|
400 | load(); |
---|
401 | } |
---|
402 | } |
---|
403 | |
---|
404 | // Colorbox's markup needs to be added to the DOM prior to being called |
---|
405 | // so that the browser will go ahead and load the CSS background images. |
---|
406 | function appendHTML() { |
---|
407 | if (!$box && document.body) { |
---|
408 | init = false; |
---|
409 | $window = $(window); |
---|
410 | $box = $tag(div).attr({ |
---|
411 | id: colorbox, |
---|
412 | 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS. |
---|
413 | role: 'dialog', |
---|
414 | tabindex: '-1' |
---|
415 | }).hide(); |
---|
416 | $overlay = $tag(div, "Overlay").hide(); |
---|
417 | $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]); |
---|
418 | $wrap = $tag(div, "Wrapper"); |
---|
419 | $content = $tag(div, "Content").append( |
---|
420 | $title = $tag(div, "Title"), |
---|
421 | $current = $tag(div, "Current"), |
---|
422 | $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}), |
---|
423 | $next = $('<button type="button"/>').attr({id:prefix+'Next'}), |
---|
424 | $slideshow = $tag('button', "Slideshow"), |
---|
425 | $loadingOverlay |
---|
426 | ); |
---|
427 | |
---|
428 | $close = $('<button type="button"/>').attr({id:prefix+'Close'}); |
---|
429 | |
---|
430 | $wrap.append( // The 3x3 Grid that makes up Colorbox |
---|
431 | $tag(div).append( |
---|
432 | $tag(div, "TopLeft"), |
---|
433 | $topBorder = $tag(div, "TopCenter"), |
---|
434 | $tag(div, "TopRight") |
---|
435 | ), |
---|
436 | $tag(div, false, 'clear:left').append( |
---|
437 | $leftBorder = $tag(div, "MiddleLeft"), |
---|
438 | $content, |
---|
439 | $rightBorder = $tag(div, "MiddleRight") |
---|
440 | ), |
---|
441 | $tag(div, false, 'clear:left').append( |
---|
442 | $tag(div, "BottomLeft"), |
---|
443 | $bottomBorder = $tag(div, "BottomCenter"), |
---|
444 | $tag(div, "BottomRight") |
---|
445 | ) |
---|
446 | ).find('div div').css({'float': 'left'}); |
---|
447 | |
---|
448 | $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none'); |
---|
449 | |
---|
450 | $groupControls = $next.add($prev).add($current).add($slideshow); |
---|
451 | |
---|
452 | $(document.body).append($overlay, $box.append($wrap, $loadingBay)); |
---|
453 | } |
---|
454 | } |
---|
455 | |
---|
456 | // Add Colorbox's event bindings |
---|
457 | function addBindings() { |
---|
458 | function clickHandler(e) { |
---|
459 | // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt. |
---|
460 | // See: http://jacklmoore.com/notes/click-events/ |
---|
461 | if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) { |
---|
462 | e.preventDefault(); |
---|
463 | launch(this); |
---|
464 | } |
---|
465 | } |
---|
466 | |
---|
467 | if ($box) { |
---|
468 | if (!init) { |
---|
469 | init = true; |
---|
470 | |
---|
471 | // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly. |
---|
472 | $next.click(function () { |
---|
473 | publicMethod.next(); |
---|
474 | }); |
---|
475 | $prev.click(function () { |
---|
476 | publicMethod.prev(); |
---|
477 | }); |
---|
478 | $close.click(function () { |
---|
479 | publicMethod.close(); |
---|
480 | }); |
---|
481 | $overlay.click(function () { |
---|
482 | if (settings.overlayClose) { |
---|
483 | publicMethod.close(); |
---|
484 | } |
---|
485 | }); |
---|
486 | |
---|
487 | // Key Bindings |
---|
488 | $(document).bind('keydown.' + prefix, function (e) { |
---|
489 | var key = e.keyCode; |
---|
490 | if (open && settings.escKey && key === 27) { |
---|
491 | e.preventDefault(); |
---|
492 | publicMethod.close(); |
---|
493 | } |
---|
494 | if (open && settings.arrowKey && $related[1] && !e.altKey) { |
---|
495 | if (key === 37) { |
---|
496 | e.preventDefault(); |
---|
497 | $prev.click(); |
---|
498 | } else if (key === 39) { |
---|
499 | e.preventDefault(); |
---|
500 | $next.click(); |
---|
501 | } |
---|
502 | } |
---|
503 | }); |
---|
504 | |
---|
505 | if ($.isFunction($.fn.on)) { |
---|
506 | // For jQuery 1.7+ |
---|
507 | $(document).on('click.'+prefix, '.'+boxElement, clickHandler); |
---|
508 | } else { |
---|
509 | // For jQuery 1.3.x -> 1.6.x |
---|
510 | // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed. |
---|
511 | // This is not here for jQuery 1.9, it's here for legacy users. |
---|
512 | $('.'+boxElement).live('click.'+prefix, clickHandler); |
---|
513 | } |
---|
514 | } |
---|
515 | return true; |
---|
516 | } |
---|
517 | return false; |
---|
518 | } |
---|
519 | |
---|
520 | // Don't do anything if Colorbox already exists. |
---|
521 | if ($.colorbox) { |
---|
522 | return; |
---|
523 | } |
---|
524 | |
---|
525 | // Append the HTML when the DOM loads |
---|
526 | $(appendHTML); |
---|
527 | |
---|
528 | |
---|
529 | // **************** |
---|
530 | // PUBLIC FUNCTIONS |
---|
531 | // Usage format: $.colorbox.close(); |
---|
532 | // Usage from within an iframe: parent.jQuery.colorbox.close(); |
---|
533 | // **************** |
---|
534 | |
---|
535 | publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) { |
---|
536 | var $this = this; |
---|
537 | |
---|
538 | options = options || {}; |
---|
539 | |
---|
540 | appendHTML(); |
---|
541 | |
---|
542 | if (addBindings()) { |
---|
543 | if ($.isFunction($this)) { // assume a call to $.colorbox |
---|
544 | $this = $('<a/>'); |
---|
545 | options.open = true; |
---|
546 | } else if (!$this[0]) { // colorbox being applied to empty collection |
---|
547 | return $this; |
---|
548 | } |
---|
549 | |
---|
550 | if (callback) { |
---|
551 | options.onComplete = callback; |
---|
552 | } |
---|
553 | |
---|
554 | $this.each(function () { |
---|
555 | $.data(this, colorbox, $.extend({}, $.data(this, colorbox) || defaults, options)); |
---|
556 | }).addClass(boxElement); |
---|
557 | |
---|
558 | if (($.isFunction(options.open) && options.open.call($this)) || options.open) { |
---|
559 | launch($this[0]); |
---|
560 | } |
---|
561 | } |
---|
562 | |
---|
563 | return $this; |
---|
564 | }; |
---|
565 | |
---|
566 | publicMethod.position = function (speed, loadedCallback) { |
---|
567 | var |
---|
568 | css, |
---|
569 | top = 0, |
---|
570 | left = 0, |
---|
571 | offset = $box.offset(), |
---|
572 | scrollTop, |
---|
573 | scrollLeft; |
---|
574 | |
---|
575 | $window.unbind('resize.' + prefix); |
---|
576 | |
---|
577 | // remove the modal so that it doesn't influence the document width/height |
---|
578 | $box.css({top: -9e4, left: -9e4}); |
---|
579 | |
---|
580 | scrollTop = $window.scrollTop(); |
---|
581 | scrollLeft = $window.scrollLeft(); |
---|
582 | |
---|
583 | if (settings.fixed) { |
---|
584 | offset.top -= scrollTop; |
---|
585 | offset.left -= scrollLeft; |
---|
586 | $box.css({position: 'fixed'}); |
---|
587 | } else { |
---|
588 | top = scrollTop; |
---|
589 | left = scrollLeft; |
---|
590 | $box.css({position: 'absolute'}); |
---|
591 | } |
---|
592 | |
---|
593 | // keeps the top and left positions within the browser's viewport. |
---|
594 | if (settings.right !== false) { |
---|
595 | left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.right, 'x'), 0); |
---|
596 | } else if (settings.left !== false) { |
---|
597 | left += setSize(settings.left, 'x'); |
---|
598 | } else { |
---|
599 | left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2); |
---|
600 | } |
---|
601 | |
---|
602 | if (settings.bottom !== false) { |
---|
603 | top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.bottom, 'y'), 0); |
---|
604 | } else if (settings.top !== false) { |
---|
605 | top += setSize(settings.top, 'y'); |
---|
606 | } else { |
---|
607 | top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2); |
---|
608 | } |
---|
609 | |
---|
610 | $box.css({top: offset.top, left: offset.left, visibility:'visible'}); |
---|
611 | |
---|
612 | // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly, |
---|
613 | // but it has to be shrank down around the size of div#colorbox when it's done. If not, |
---|
614 | // it can invoke an obscure IE bug when using iframes. |
---|
615 | $wrap[0].style.width = $wrap[0].style.height = "9999px"; |
---|
616 | |
---|
617 | function modalDimensions() { |
---|
618 | $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px'; |
---|
619 | $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px'; |
---|
620 | } |
---|
621 | |
---|
622 | css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left}; |
---|
623 | |
---|
624 | // setting the speed to 0 if the content hasn't changed size or position |
---|
625 | if (speed) { |
---|
626 | var tempSpeed = 0; |
---|
627 | $.each(css, function(i){ |
---|
628 | if (css[i] !== previousCSS[i]) { |
---|
629 | tempSpeed = speed; |
---|
630 | return; |
---|
631 | } |
---|
632 | }); |
---|
633 | speed = tempSpeed; |
---|
634 | } |
---|
635 | |
---|
636 | previousCSS = css; |
---|
637 | |
---|
638 | if (!speed) { |
---|
639 | $box.css(css); |
---|
640 | } |
---|
641 | |
---|
642 | $box.dequeue().animate(css, { |
---|
643 | duration: speed || 0, |
---|
644 | complete: function () { |
---|
645 | modalDimensions(); |
---|
646 | |
---|
647 | active = false; |
---|
648 | |
---|
649 | // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation. |
---|
650 | $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px"; |
---|
651 | $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px"; |
---|
652 | |
---|
653 | if (settings.reposition) { |
---|
654 | setTimeout(function () { // small delay before binding onresize due to an IE8 bug. |
---|
655 | $window.bind('resize.' + prefix, publicMethod.position); |
---|
656 | }, 1); |
---|
657 | } |
---|
658 | |
---|
659 | if (loadedCallback) { |
---|
660 | loadedCallback(); |
---|
661 | } |
---|
662 | }, |
---|
663 | step: modalDimensions |
---|
664 | }); |
---|
665 | }; |
---|
666 | |
---|
667 | publicMethod.resize = function (options) { |
---|
668 | var scrolltop; |
---|
669 | |
---|
670 | if (open) { |
---|
671 | options = options || {}; |
---|
672 | |
---|
673 | if (options.width) { |
---|
674 | settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth; |
---|
675 | } |
---|
676 | |
---|
677 | if (options.innerWidth) { |
---|
678 | settings.w = setSize(options.innerWidth, 'x'); |
---|
679 | } |
---|
680 | |
---|
681 | $loaded.css({width: settings.w}); |
---|
682 | |
---|
683 | if (options.height) { |
---|
684 | settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight; |
---|
685 | } |
---|
686 | |
---|
687 | if (options.innerHeight) { |
---|
688 | settings.h = setSize(options.innerHeight, 'y'); |
---|
689 | } |
---|
690 | |
---|
691 | if (!options.innerHeight && !options.height) { |
---|
692 | scrolltop = $loaded.scrollTop(); |
---|
693 | $loaded.css({height: "auto"}); |
---|
694 | settings.h = $loaded.height(); |
---|
695 | } |
---|
696 | |
---|
697 | $loaded.css({height: settings.h}); |
---|
698 | |
---|
699 | if(scrolltop) { |
---|
700 | $loaded.scrollTop(scrolltop); |
---|
701 | } |
---|
702 | |
---|
703 | publicMethod.position(settings.transition === "none" ? 0 : settings.speed); |
---|
704 | } |
---|
705 | }; |
---|
706 | |
---|
707 | publicMethod.prep = function (object) { |
---|
708 | if (!open) { |
---|
709 | return; |
---|
710 | } |
---|
711 | |
---|
712 | var callback, speed = settings.transition === "none" ? 0 : settings.speed; |
---|
713 | |
---|
714 | $loaded.empty().remove(); // Using empty first may prevent some IE7 issues. |
---|
715 | |
---|
716 | $loaded = $tag(div, 'LoadedContent').append(object); |
---|
717 | |
---|
718 | function getWidth() { |
---|
719 | settings.w = settings.w || $loaded.width(); |
---|
720 | settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w; |
---|
721 | return settings.w; |
---|
722 | } |
---|
723 | function getHeight() { |
---|
724 | settings.h = settings.h || $loaded.height(); |
---|
725 | settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h; |
---|
726 | return settings.h; |
---|
727 | } |
---|
728 | |
---|
729 | $loaded.hide() |
---|
730 | .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations. |
---|
731 | .css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'}) |
---|
732 | .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height. |
---|
733 | .prependTo($content); |
---|
734 | |
---|
735 | $loadingBay.hide(); |
---|
736 | |
---|
737 | // 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. |
---|
738 | |
---|
739 | $(photo).css({'float': 'none'}); |
---|
740 | |
---|
741 | callback = function () { |
---|
742 | var total = $related.length, |
---|
743 | iframe, |
---|
744 | frameBorder = 'frameBorder', |
---|
745 | allowTransparency = 'allowTransparency', |
---|
746 | complete; |
---|
747 | |
---|
748 | if (!open) { |
---|
749 | return; |
---|
750 | } |
---|
751 | |
---|
752 | function removeFilter() { // Needed for IE7 & IE8 in versions of jQuery prior to 1.7.2 |
---|
753 | if ($.support.opacity === false) { |
---|
754 | $box[0].style.removeAttribute('filter'); |
---|
755 | } |
---|
756 | } |
---|
757 | |
---|
758 | complete = function () { |
---|
759 | clearTimeout(loadingTimer); |
---|
760 | $loadingOverlay.hide(); |
---|
761 | trigger(event_complete, settings.onComplete); |
---|
762 | }; |
---|
763 | |
---|
764 | |
---|
765 | $title.html(settings.title).add($loaded).show(); |
---|
766 | |
---|
767 | if (total > 1) { // handle grouping |
---|
768 | if (typeof settings.current === "string") { |
---|
769 | $current.html(settings.current.replace('{current}', index + 1).replace('{total}', total)).show(); |
---|
770 | } |
---|
771 | |
---|
772 | $next[(settings.loop || index < total - 1) ? "show" : "hide"]().html(settings.next); |
---|
773 | $prev[(settings.loop || index) ? "show" : "hide"]().html(settings.previous); |
---|
774 | |
---|
775 | if (settings.slideshow) { |
---|
776 | $slideshow.show(); |
---|
777 | } |
---|
778 | |
---|
779 | // Preloads images within a rel group |
---|
780 | if (settings.preloading) { |
---|
781 | $.each([getIndex(-1), getIndex(1)], function(){ |
---|
782 | var src, |
---|
783 | img, |
---|
784 | i = $related[this], |
---|
785 | data = $.data(i, colorbox); |
---|
786 | |
---|
787 | if (data && data.href) { |
---|
788 | src = data.href; |
---|
789 | if ($.isFunction(src)) { |
---|
790 | src = src.call(i); |
---|
791 | } |
---|
792 | } else { |
---|
793 | src = $(i).attr('href'); |
---|
794 | } |
---|
795 | |
---|
796 | if (src && isImage(data, src)) { |
---|
797 | src = retinaUrl(data, src); |
---|
798 | img = document.createElement('img'); |
---|
799 | img.src = src; |
---|
800 | } |
---|
801 | }); |
---|
802 | } |
---|
803 | } else { |
---|
804 | $groupControls.hide(); |
---|
805 | } |
---|
806 | |
---|
807 | if (settings.iframe) { |
---|
808 | iframe = $tag('iframe')[0]; |
---|
809 | |
---|
810 | if (frameBorder in iframe) { |
---|
811 | iframe[frameBorder] = 0; |
---|
812 | } |
---|
813 | |
---|
814 | if (allowTransparency in iframe) { |
---|
815 | iframe[allowTransparency] = "true"; |
---|
816 | } |
---|
817 | |
---|
818 | if (!settings.scrolling) { |
---|
819 | iframe.scrolling = "no"; |
---|
820 | } |
---|
821 | |
---|
822 | $(iframe) |
---|
823 | .attr({ |
---|
824 | src: settings.href, |
---|
825 | name: (new Date()).getTime(), // give the iframe a unique name to prevent caching |
---|
826 | 'class': prefix + 'Iframe', |
---|
827 | allowFullScreen : true, // allow HTML5 video to go fullscreen |
---|
828 | webkitAllowFullScreen : true, |
---|
829 | mozallowfullscreen : true |
---|
830 | }) |
---|
831 | .one('load', complete) |
---|
832 | .appendTo($loaded); |
---|
833 | |
---|
834 | $events.one(event_purge, function () { |
---|
835 | iframe.src = "//about:blank"; |
---|
836 | }); |
---|
837 | |
---|
838 | if (settings.fastIframe) { |
---|
839 | $(iframe).trigger('load'); |
---|
840 | } |
---|
841 | } else { |
---|
842 | complete(); |
---|
843 | } |
---|
844 | |
---|
845 | if (settings.transition === 'fade') { |
---|
846 | $box.fadeTo(speed, 1, removeFilter); |
---|
847 | } else { |
---|
848 | removeFilter(); |
---|
849 | } |
---|
850 | }; |
---|
851 | |
---|
852 | if (settings.transition === 'fade') { |
---|
853 | $box.fadeTo(speed, 0, function () { |
---|
854 | publicMethod.position(0, callback); |
---|
855 | }); |
---|
856 | } else { |
---|
857 | publicMethod.position(speed, callback); |
---|
858 | } |
---|
859 | }; |
---|
860 | |
---|
861 | function load () { |
---|
862 | var href, setResize, prep = publicMethod.prep, $inline, request = ++requests; |
---|
863 | |
---|
864 | active = true; |
---|
865 | |
---|
866 | photo = false; |
---|
867 | |
---|
868 | element = $related[index]; |
---|
869 | |
---|
870 | makeSettings(); |
---|
871 | |
---|
872 | trigger(event_purge); |
---|
873 | |
---|
874 | trigger(event_load, settings.onLoad); |
---|
875 | |
---|
876 | settings.h = settings.height ? |
---|
877 | setSize(settings.height, 'y') - loadedHeight - interfaceHeight : |
---|
878 | settings.innerHeight && setSize(settings.innerHeight, 'y'); |
---|
879 | |
---|
880 | settings.w = settings.width ? |
---|
881 | setSize(settings.width, 'x') - loadedWidth - interfaceWidth : |
---|
882 | settings.innerWidth && setSize(settings.innerWidth, 'x'); |
---|
883 | |
---|
884 | // Sets the minimum dimensions for use in image scaling |
---|
885 | settings.mw = settings.w; |
---|
886 | settings.mh = settings.h; |
---|
887 | |
---|
888 | // Re-evaluate the minimum width and height based on maxWidth and maxHeight values. |
---|
889 | // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead. |
---|
890 | if (settings.maxWidth) { |
---|
891 | settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth; |
---|
892 | settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw; |
---|
893 | } |
---|
894 | if (settings.maxHeight) { |
---|
895 | settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight; |
---|
896 | settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh; |
---|
897 | } |
---|
898 | |
---|
899 | href = settings.href; |
---|
900 | |
---|
901 | loadingTimer = setTimeout(function () { |
---|
902 | $loadingOverlay.show(); |
---|
903 | }, 100); |
---|
904 | |
---|
905 | if (settings.inline) { |
---|
906 | // Inserts an empty placeholder where inline content is being pulled from. |
---|
907 | // An event is bound to put inline content back when Colorbox closes or loads new content. |
---|
908 | $inline = $tag(div).hide().insertBefore($(href)[0]); |
---|
909 | |
---|
910 | $events.one(event_purge, function () { |
---|
911 | $inline.replaceWith($loaded.children()); |
---|
912 | }); |
---|
913 | |
---|
914 | prep($(href)); |
---|
915 | } else if (settings.iframe) { |
---|
916 | // IFrame element won't be added to the DOM until it is ready to be displayed, |
---|
917 | // to avoid problems with DOM-ready JS that might be trying to run in that iframe. |
---|
918 | prep(" "); |
---|
919 | } else if (settings.html) { |
---|
920 | prep(settings.html); |
---|
921 | } else if (isImage(settings, href)) { |
---|
922 | |
---|
923 | href = retinaUrl(settings, href); |
---|
924 | |
---|
925 | photo = document.createElement('img'); |
---|
926 | |
---|
927 | $(photo) |
---|
928 | .addClass(prefix + 'Photo') |
---|
929 | .bind('error',function () { |
---|
930 | settings.title = false; |
---|
931 | prep($tag(div, 'Error').html(settings.imgError)); |
---|
932 | }) |
---|
933 | .one('load', function () { |
---|
934 | var percent; |
---|
935 | |
---|
936 | if (request !== requests) { |
---|
937 | return; |
---|
938 | } |
---|
939 | |
---|
940 | photo.alt = $(element).attr('alt') || $(element).attr('data-alt') || ''; |
---|
941 | |
---|
942 | if (settings.retinaImage && window.devicePixelRatio > 1) { |
---|
943 | photo.height = photo.height / window.devicePixelRatio; |
---|
944 | photo.width = photo.width / window.devicePixelRatio; |
---|
945 | } |
---|
946 | |
---|
947 | if (settings.scalePhotos) { |
---|
948 | setResize = function () { |
---|
949 | photo.height -= photo.height * percent; |
---|
950 | photo.width -= photo.width * percent; |
---|
951 | }; |
---|
952 | if (settings.mw && photo.width > settings.mw) { |
---|
953 | percent = (photo.width - settings.mw) / photo.width; |
---|
954 | setResize(); |
---|
955 | } |
---|
956 | if (settings.mh && photo.height > settings.mh) { |
---|
957 | percent = (photo.height - settings.mh) / photo.height; |
---|
958 | setResize(); |
---|
959 | } |
---|
960 | } |
---|
961 | |
---|
962 | if (settings.h) { |
---|
963 | photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px'; |
---|
964 | } |
---|
965 | |
---|
966 | if ($related[1] && (settings.loop || $related[index + 1])) { |
---|
967 | photo.style.cursor = 'pointer'; |
---|
968 | photo.onclick = function () { |
---|
969 | publicMethod.next(); |
---|
970 | }; |
---|
971 | } |
---|
972 | |
---|
973 | photo.style.width = photo.width + 'px'; |
---|
974 | photo.style.height = photo.height + 'px'; |
---|
975 | |
---|
976 | setTimeout(function () { // A pause because Chrome will sometimes report a 0 by 0 size otherwise. |
---|
977 | prep(photo); |
---|
978 | }, 1); |
---|
979 | }); |
---|
980 | |
---|
981 | setTimeout(function () { // A pause because Opera 10.6+ will sometimes not run the onload function otherwise. |
---|
982 | photo.src = href; |
---|
983 | }, 1); |
---|
984 | } else if (href) { |
---|
985 | $loadingBay.load(href, settings.data, function (data, status) { |
---|
986 | if (request === requests) { |
---|
987 | prep(status === 'error' ? $tag(div, 'Error').html(settings.xhrError) : $(this).contents()); |
---|
988 | } |
---|
989 | }); |
---|
990 | } |
---|
991 | } |
---|
992 | |
---|
993 | // Navigates to the next page/image in a set. |
---|
994 | publicMethod.next = function () { |
---|
995 | if (!active && $related[1] && (settings.loop || $related[index + 1])) { |
---|
996 | index = getIndex(1); |
---|
997 | launch($related[index]); |
---|
998 | } |
---|
999 | }; |
---|
1000 | |
---|
1001 | publicMethod.prev = function () { |
---|
1002 | if (!active && $related[1] && (settings.loop || index)) { |
---|
1003 | index = getIndex(-1); |
---|
1004 | launch($related[index]); |
---|
1005 | } |
---|
1006 | }; |
---|
1007 | |
---|
1008 | // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close(); |
---|
1009 | publicMethod.close = function () { |
---|
1010 | if (open && !closing) { |
---|
1011 | |
---|
1012 | closing = true; |
---|
1013 | |
---|
1014 | open = false; |
---|
1015 | |
---|
1016 | trigger(event_cleanup, settings.onCleanup); |
---|
1017 | |
---|
1018 | $window.unbind('.' + prefix); |
---|
1019 | |
---|
1020 | $overlay.fadeTo(settings.fadeOut || 0, 0); |
---|
1021 | |
---|
1022 | $box.stop().fadeTo(settings.fadeOut || 0, 0, function () { |
---|
1023 | |
---|
1024 | $box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide(); |
---|
1025 | |
---|
1026 | trigger(event_purge); |
---|
1027 | |
---|
1028 | $loaded.empty().remove(); // Using empty first may prevent some IE7 issues. |
---|
1029 | |
---|
1030 | setTimeout(function () { |
---|
1031 | closing = false; |
---|
1032 | trigger(event_closed, settings.onClosed); |
---|
1033 | }, 1); |
---|
1034 | }); |
---|
1035 | } |
---|
1036 | }; |
---|
1037 | |
---|
1038 | // Removes changes Colorbox made to the document, but does not remove the plugin. |
---|
1039 | publicMethod.remove = function () { |
---|
1040 | if (!$box) { return; } |
---|
1041 | |
---|
1042 | $box.stop(); |
---|
1043 | $.colorbox.close(); |
---|
1044 | $box.stop().remove(); |
---|
1045 | $overlay.remove(); |
---|
1046 | closing = false; |
---|
1047 | $box = null; |
---|
1048 | $('.' + boxElement) |
---|
1049 | .removeData(colorbox) |
---|
1050 | .removeClass(boxElement); |
---|
1051 | |
---|
1052 | $(document).unbind('click.'+prefix); |
---|
1053 | }; |
---|
1054 | |
---|
1055 | // A method for fetching the current element Colorbox is referencing. |
---|
1056 | // returns a jQuery object. |
---|
1057 | publicMethod.element = function () { |
---|
1058 | return $(element); |
---|
1059 | }; |
---|
1060 | |
---|
1061 | publicMethod.settings = defaults; |
---|
1062 | |
---|
1063 | }(jQuery, document, window)); |
---|