File indexing completed on 2024-05-19 06:01:39
0001 /*! 0002 * fancyBox - jQuery Plugin 0003 * version: 2.1.4 (Thu, 10 Jan 2013) 0004 * @requires jQuery v1.6 or later 0005 * 0006 * Examples at http://fancyapps.com/fancybox/ 0007 * License: www.fancyapps.com/fancybox/#license 0008 * 0009 * Copyright 2012 Janis Skarnelis - janis@fancyapps.com 0010 * 0011 */ 0012 0013 (function (window, document, $, undefined) { 0014 "use strict"; 0015 0016 var W = $(window), 0017 D = $(document), 0018 F = $.fancybox = function () { 0019 F.open.apply( this, arguments ); 0020 }, 0021 IE = navigator.userAgent.match(/msie/), 0022 didUpdate = null, 0023 isTouch = document.createTouch !== undefined, 0024 0025 isQuery = function(obj) { 0026 return obj && obj.hasOwnProperty && obj instanceof $; 0027 }, 0028 isString = function(str) { 0029 return str && $.type(str) === "string"; 0030 }, 0031 isPercentage = function(str) { 0032 return isString(str) && str.indexOf('%') > 0; 0033 }, 0034 isScrollable = function(el) { 0035 return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); 0036 }, 0037 getScalar = function(orig, dim) { 0038 var value = parseInt(orig, 10) || 0; 0039 0040 if (dim && isPercentage(orig)) { 0041 value = F.getViewport()[ dim ] / 100 * value; 0042 } 0043 0044 return Math.ceil(value); 0045 }, 0046 getValue = function(value, dim) { 0047 return getScalar(value, dim) + 'px'; 0048 }; 0049 0050 $.extend(F, { 0051 // The current version of fancyBox 0052 version: '2.1.4', 0053 0054 defaults: { 0055 padding : 15, 0056 margin : 20, 0057 0058 width : 800, 0059 height : 600, 0060 minWidth : 100, 0061 minHeight : 100, 0062 maxWidth : 9999, 0063 maxHeight : 9999, 0064 0065 autoSize : true, 0066 autoHeight : false, 0067 autoWidth : false, 0068 0069 autoResize : true, 0070 autoCenter : !isTouch, 0071 fitToView : true, 0072 aspectRatio : false, 0073 topRatio : 0.5, 0074 leftRatio : 0.5, 0075 0076 scrolling : 'auto', // 'auto', 'yes' or 'no' 0077 wrapCSS : '', 0078 0079 arrows : true, 0080 closeBtn : true, 0081 closeClick : false, 0082 nextClick : false, 0083 mouseWheel : true, 0084 autoPlay : false, 0085 playSpeed : 3000, 0086 preload : 3, 0087 modal : false, 0088 loop : true, 0089 0090 ajax : { 0091 dataType : 'html', 0092 headers : { 'X-fancyBox': true } 0093 }, 0094 iframe : { 0095 scrolling : 'auto', 0096 preload : true 0097 }, 0098 swf : { 0099 wmode: 'transparent', 0100 allowfullscreen : 'true', 0101 allowscriptaccess : 'always' 0102 }, 0103 0104 keys : { 0105 next : { 0106 13 : 'left', // enter 0107 34 : 'up', // page down 0108 39 : 'left', // right arrow 0109 40 : 'up' // down arrow 0110 }, 0111 prev : { 0112 8 : 'right', // backspace 0113 33 : 'down', // page up 0114 37 : 'right', // left arrow 0115 38 : 'down' // up arrow 0116 }, 0117 close : [27], // escape key 0118 play : [32], // space - start/stop slideshow 0119 toggle : [70] // letter "f" - toggle fullscreen 0120 }, 0121 0122 direction : { 0123 next : 'left', 0124 prev : 'right' 0125 }, 0126 0127 scrollOutside : true, 0128 0129 // Override some properties 0130 index : 0, 0131 type : null, 0132 href : null, 0133 content : null, 0134 title : null, 0135 0136 // HTML templates 0137 tpl: { 0138 wrap : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>', 0139 image : '<img class="fancybox-image" src="{href}" alt="" />', 0140 iframe : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>', 0141 error : '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>', 0142 closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>', 0143 next : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>', 0144 prev : '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>' 0145 }, 0146 0147 // Properties for each animation type 0148 // Opening fancyBox 0149 openEffect : 'fade', // 'elastic', 'fade' or 'none' 0150 openSpeed : 250, 0151 openEasing : 'swing', 0152 openOpacity : true, 0153 openMethod : 'zoomIn', 0154 0155 // Closing fancyBox 0156 closeEffect : 'fade', // 'elastic', 'fade' or 'none' 0157 closeSpeed : 250, 0158 closeEasing : 'swing', 0159 closeOpacity : true, 0160 closeMethod : 'zoomOut', 0161 0162 // Changing next gallery item 0163 nextEffect : 'elastic', // 'elastic', 'fade' or 'none' 0164 nextSpeed : 250, 0165 nextEasing : 'swing', 0166 nextMethod : 'changeIn', 0167 0168 // Changing previous gallery item 0169 prevEffect : 'elastic', // 'elastic', 'fade' or 'none' 0170 prevSpeed : 250, 0171 prevEasing : 'swing', 0172 prevMethod : 'changeOut', 0173 0174 // Enable default helpers 0175 helpers : { 0176 overlay : true, 0177 title : true 0178 }, 0179 0180 // Callbacks 0181 onCancel : $.noop, // If canceling 0182 beforeLoad : $.noop, // Before loading 0183 afterLoad : $.noop, // After loading 0184 beforeShow : $.noop, // Before changing in current item 0185 afterShow : $.noop, // After opening 0186 beforeChange : $.noop, // Before changing gallery item 0187 beforeClose : $.noop, // Before closing 0188 afterClose : $.noop // After closing 0189 }, 0190 0191 //Current state 0192 group : {}, // Selected group 0193 opts : {}, // Group options 0194 previous : null, // Previous element 0195 coming : null, // Element being loaded 0196 current : null, // Currently loaded element 0197 isActive : false, // Is activated 0198 isOpen : false, // Is currently open 0199 isOpened : false, // Have been fully opened at least once 0200 0201 wrap : null, 0202 skin : null, 0203 outer : null, 0204 inner : null, 0205 0206 player : { 0207 timer : null, 0208 isActive : false 0209 }, 0210 0211 // Loaders 0212 ajaxLoad : null, 0213 imgPreload : null, 0214 0215 // Some collections 0216 transitions : {}, 0217 helpers : {}, 0218 0219 /* 0220 * Static methods 0221 */ 0222 0223 open: function (group, opts) { 0224 if (!group) { 0225 return; 0226 } 0227 0228 if (!$.isPlainObject(opts)) { 0229 opts = {}; 0230 } 0231 0232 // Close if already active 0233 if (false === F.close(true)) { 0234 return; 0235 } 0236 0237 // Normalize group 0238 if (!$.isArray(group)) { 0239 group = isQuery(group) ? $(group).get() : [group]; 0240 } 0241 0242 // Recheck if the type of each element is `object` and set content type (image, ajax, etc) 0243 $.each(group, function(i, element) { 0244 var obj = {}, 0245 href, 0246 title, 0247 content, 0248 type, 0249 rez, 0250 hrefParts, 0251 selector; 0252 0253 if ($.type(element) === "object") { 0254 // Check if is DOM element 0255 if (element.nodeType) { 0256 element = $(element); 0257 } 0258 0259 if (isQuery(element)) { 0260 obj = { 0261 href : element.data('fancybox-href') || element.attr('href'), 0262 title : element.data('fancybox-title') || element.attr('title'), 0263 isDom : true, 0264 element : element 0265 }; 0266 0267 if ($.metadata) { 0268 $.extend(true, obj, element.metadata()); 0269 } 0270 0271 } else { 0272 obj = element; 0273 } 0274 } 0275 0276 href = opts.href || obj.href || (isString(element) ? element : null); 0277 title = opts.title !== undefined ? opts.title : obj.title || ''; 0278 0279 content = opts.content || obj.content; 0280 type = content ? 'html' : (opts.type || obj.type); 0281 0282 if (!type && obj.isDom) { 0283 type = element.data('fancybox-type'); 0284 0285 if (!type) { 0286 rez = element.prop('class').match(/fancybox\.(\w+)/); 0287 type = rez ? rez[1] : null; 0288 } 0289 } 0290 0291 if (isString(href)) { 0292 // Try to guess the content type 0293 if (!type) { 0294 if (F.isImage(href)) { 0295 type = 'image'; 0296 0297 } else if (F.isSWF(href)) { 0298 type = 'swf'; 0299 0300 } else if (href.charAt(0) === '#') { 0301 type = 'inline'; 0302 0303 } else if (isString(element)) { 0304 type = 'html'; 0305 content = element; 0306 } 0307 } 0308 0309 // Split url into two pieces with source url and content selector, e.g, 0310 // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" 0311 if (type === 'ajax') { 0312 hrefParts = href.split(/\s+/, 2); 0313 href = hrefParts.shift(); 0314 selector = hrefParts.shift(); 0315 } 0316 } 0317 0318 if (!content) { 0319 if (type === 'inline') { 0320 if (href) { 0321 content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 0322 0323 } else if (obj.isDom) { 0324 content = element; 0325 } 0326 0327 } else if (type === 'html') { 0328 content = href; 0329 0330 } else if (!type && !href && obj.isDom) { 0331 type = 'inline'; 0332 content = element; 0333 } 0334 } 0335 0336 $.extend(obj, { 0337 href : href, 0338 type : type, 0339 content : content, 0340 title : title, 0341 selector : selector 0342 }); 0343 0344 group[ i ] = obj; 0345 }); 0346 0347 // Extend the defaults 0348 F.opts = $.extend(true, {}, F.defaults, opts); 0349 0350 // All options are merged recursive except keys 0351 if (opts.keys !== undefined) { 0352 F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; 0353 } 0354 0355 F.group = group; 0356 0357 return F._start(F.opts.index); 0358 }, 0359 0360 // Cancel image loading or abort ajax request 0361 cancel: function () { 0362 var coming = F.coming; 0363 0364 if (!coming || false === F.trigger('onCancel')) { 0365 return; 0366 } 0367 0368 F.hideLoading(); 0369 0370 if (F.ajaxLoad) { 0371 F.ajaxLoad.abort(); 0372 } 0373 0374 F.ajaxLoad = null; 0375 0376 if (F.imgPreload) { 0377 F.imgPreload.onload = F.imgPreload.onerror = null; 0378 } 0379 0380 if (coming.wrap) { 0381 coming.wrap.stop(true, true).trigger('onReset').remove(); 0382 } 0383 0384 F.coming = null; 0385 0386 // If the first item has been canceled, then clear everything 0387 if (!F.current) { 0388 F._afterZoomOut( coming ); 0389 } 0390 }, 0391 0392 // Start closing animation if is open; remove immediately if opening/closing 0393 close: function (event) { 0394 F.cancel(); 0395 0396 if (false === F.trigger('beforeClose')) { 0397 return; 0398 } 0399 0400 F.unbindEvents(); 0401 0402 if (!F.isActive) { 0403 return; 0404 } 0405 0406 if (!F.isOpen || event === true) { 0407 $('.fancybox-wrap').stop(true).trigger('onReset').remove(); 0408 0409 F._afterZoomOut(); 0410 0411 } else { 0412 F.isOpen = F.isOpened = false; 0413 F.isClosing = true; 0414 0415 $('.fancybox-item, .fancybox-nav').remove(); 0416 0417 F.wrap.stop(true, true).removeClass('fancybox-opened'); 0418 0419 F.transitions[ F.current.closeMethod ](); 0420 } 0421 }, 0422 0423 // Manage slideshow: 0424 // $.fancybox.play(); - toggle slideshow 0425 // $.fancybox.play( true ); - start 0426 // $.fancybox.play( false ); - stop 0427 play: function ( action ) { 0428 var clear = function () { 0429 clearTimeout(F.player.timer); 0430 }, 0431 set = function () { 0432 clear(); 0433 0434 if (F.current && F.player.isActive) { 0435 F.player.timer = setTimeout(F.next, F.current.playSpeed); 0436 } 0437 }, 0438 stop = function () { 0439 clear(); 0440 0441 $('body').unbind('.player'); 0442 0443 F.player.isActive = false; 0444 0445 F.trigger('onPlayEnd'); 0446 }, 0447 start = function () { 0448 if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { 0449 F.player.isActive = true; 0450 0451 $('body').bind({ 0452 'afterShow.player onUpdate.player' : set, 0453 'onCancel.player beforeClose.player' : stop, 0454 'beforeLoad.player' : clear 0455 }); 0456 0457 set(); 0458 0459 F.trigger('onPlayStart'); 0460 } 0461 }; 0462 0463 if (action === true || (!F.player.isActive && action !== false)) { 0464 start(); 0465 } else { 0466 stop(); 0467 } 0468 }, 0469 0470 // Navigate to next gallery item 0471 next: function ( direction ) { 0472 var current = F.current; 0473 0474 if (current) { 0475 if (!isString(direction)) { 0476 direction = current.direction.next; 0477 } 0478 0479 F.jumpto(current.index + 1, direction, 'next'); 0480 } 0481 }, 0482 0483 // Navigate to previous gallery item 0484 prev: function ( direction ) { 0485 var current = F.current; 0486 0487 if (current) { 0488 if (!isString(direction)) { 0489 direction = current.direction.prev; 0490 } 0491 0492 F.jumpto(current.index - 1, direction, 'prev'); 0493 } 0494 }, 0495 0496 // Navigate to gallery item by index 0497 jumpto: function ( index, direction, router ) { 0498 var current = F.current; 0499 0500 if (!current) { 0501 return; 0502 } 0503 0504 index = getScalar(index); 0505 0506 F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; 0507 F.router = router || 'jumpto'; 0508 0509 if (current.loop) { 0510 if (index < 0) { 0511 index = current.group.length + (index % current.group.length); 0512 } 0513 0514 index = index % current.group.length; 0515 } 0516 0517 if (current.group[ index ] !== undefined) { 0518 F.cancel(); 0519 0520 F._start(index); 0521 } 0522 }, 0523 0524 // Center inside viewport and toggle position type to fixed or absolute if needed 0525 reposition: function (e, onlyAbsolute) { 0526 var current = F.current, 0527 wrap = current ? current.wrap : null, 0528 pos; 0529 0530 if (wrap) { 0531 pos = F._getPosition(onlyAbsolute); 0532 0533 if (e && e.type === 'scroll') { 0534 delete pos.position; 0535 0536 wrap.stop(true, true).animate(pos, 200); 0537 0538 } else { 0539 wrap.css(pos); 0540 0541 current.pos = $.extend({}, current.dim, pos); 0542 } 0543 } 0544 }, 0545 0546 update: function (e) { 0547 var type = (e && e.type), 0548 anyway = !type || type === 'orientationchange'; 0549 0550 if (anyway) { 0551 clearTimeout(didUpdate); 0552 0553 didUpdate = null; 0554 } 0555 0556 if (!F.isOpen || didUpdate) { 0557 return; 0558 } 0559 0560 didUpdate = setTimeout(function() { 0561 var current = F.current; 0562 0563 if (!current || F.isClosing) { 0564 return; 0565 } 0566 0567 F.wrap.removeClass('fancybox-tmp'); 0568 0569 if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { 0570 F._setDimension(); 0571 } 0572 0573 if (!(type === 'scroll' && current.canShrink)) { 0574 F.reposition(e); 0575 } 0576 0577 F.trigger('onUpdate'); 0578 0579 didUpdate = null; 0580 0581 }, (anyway && !isTouch ? 0 : 300)); 0582 }, 0583 0584 // Shrink content to fit inside viewport or restore if resized 0585 toggle: function ( action ) { 0586 if (F.isOpen) { 0587 F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; 0588 0589 // Help browser to restore document dimensions 0590 if (isTouch) { 0591 F.wrap.removeAttr('style').addClass('fancybox-tmp'); 0592 0593 F.trigger('onUpdate'); 0594 } 0595 0596 F.update(); 0597 } 0598 }, 0599 0600 hideLoading: function () { 0601 D.unbind('.loading'); 0602 0603 $('#fancybox-loading').remove(); 0604 }, 0605 0606 showLoading: function () { 0607 var el, viewport; 0608 0609 F.hideLoading(); 0610 0611 el = $('<div id="fancybox-loading"><div></div></div>').click(F.cancel).appendTo('body'); 0612 0613 // If user will press the escape-button, the request will be canceled 0614 D.bind('keydown.loading', function(e) { 0615 if ((e.which || e.keyCode) === 27) { 0616 e.preventDefault(); 0617 0618 F.cancel(); 0619 } 0620 }); 0621 0622 if (!F.defaults.fixed) { 0623 viewport = F.getViewport(); 0624 0625 el.css({ 0626 position : 'absolute', 0627 top : (viewport.h * 0.5) + viewport.y, 0628 left : (viewport.w * 0.5) + viewport.x 0629 }); 0630 } 0631 }, 0632 0633 getViewport: function () { 0634 var locked = (F.current && F.current.locked) || false, 0635 rez = { 0636 x: W.scrollLeft(), 0637 y: W.scrollTop() 0638 }; 0639 0640 if (locked) { 0641 rez.w = locked[0].clientWidth; 0642 rez.h = locked[0].clientHeight; 0643 0644 } else { 0645 // See http://bugs.jquery.com/ticket/6724 0646 rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); 0647 rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); 0648 } 0649 0650 return rez; 0651 }, 0652 0653 // Unbind the keyboard / clicking actions 0654 unbindEvents: function () { 0655 if (F.wrap && isQuery(F.wrap)) { 0656 F.wrap.unbind('.fb'); 0657 } 0658 0659 D.unbind('.fb'); 0660 W.unbind('.fb'); 0661 }, 0662 0663 bindEvents: function () { 0664 var current = F.current, 0665 keys; 0666 0667 if (!current) { 0668 return; 0669 } 0670 0671 // Changing document height on iOS devices triggers a 'resize' event, 0672 // that can change document height... repeating infinitely 0673 W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); 0674 0675 keys = current.keys; 0676 0677 if (keys) { 0678 D.bind('keydown.fb', function (e) { 0679 var code = e.which || e.keyCode, 0680 target = e.target || e.srcElement; 0681 0682 // Skip esc key if loading, because showLoading will cancel preloading 0683 if (code === 27 && F.coming) { 0684 return false; 0685 } 0686 0687 // Ignore key combinations and key events within form elements 0688 if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { 0689 $.each(keys, function(i, val) { 0690 if (current.group.length > 1 && val[ code ] !== undefined) { 0691 F[ i ]( val[ code ] ); 0692 0693 e.preventDefault(); 0694 return false; 0695 } 0696 0697 if ($.inArray(code, val) > -1) { 0698 F[ i ] (); 0699 0700 e.preventDefault(); 0701 return false; 0702 } 0703 }); 0704 } 0705 }); 0706 } 0707 0708 if ($.fn.mousewheel && current.mouseWheel) { 0709 F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { 0710 var target = e.target || null, 0711 parent = $(target), 0712 canScroll = false; 0713 0714 while (parent.length) { 0715 if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { 0716 break; 0717 } 0718 0719 canScroll = isScrollable( parent[0] ); 0720 parent = $(parent).parent(); 0721 } 0722 0723 if (delta !== 0 && !canScroll) { 0724 if (F.group.length > 1 && !current.canShrink) { 0725 if (deltaY > 0 || deltaX > 0) { 0726 F.prev( deltaY > 0 ? 'down' : 'left' ); 0727 0728 } else if (deltaY < 0 || deltaX < 0) { 0729 F.next( deltaY < 0 ? 'up' : 'right' ); 0730 } 0731 0732 e.preventDefault(); 0733 } 0734 } 0735 }); 0736 } 0737 }, 0738 0739 trigger: function (event, o) { 0740 var ret, obj = o || F.coming || F.current; 0741 0742 if (!obj) { 0743 return; 0744 } 0745 0746 if ($.isFunction( obj[event] )) { 0747 ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); 0748 } 0749 0750 if (ret === false) { 0751 return false; 0752 } 0753 0754 if (obj.helpers) { 0755 $.each(obj.helpers, function (helper, opts) { 0756 if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { 0757 opts = $.extend(true, {}, F.helpers[helper].defaults, opts); 0758 0759 F.helpers[helper][event](opts, obj); 0760 } 0761 }); 0762 } 0763 0764 $.event.trigger(event + '.fb'); 0765 }, 0766 0767 isImage: function (str) { 0768 return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp)((\?|#).*)?$)/i); 0769 }, 0770 0771 isSWF: function (str) { 0772 return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); 0773 }, 0774 0775 _start: function (index) { 0776 var coming = {}, 0777 obj, 0778 href, 0779 type, 0780 margin, 0781 padding; 0782 0783 index = getScalar( index ); 0784 obj = F.group[ index ] || null; 0785 0786 if (!obj) { 0787 return false; 0788 } 0789 0790 coming = $.extend(true, {}, F.opts, obj); 0791 0792 // Convert margin and padding properties to array - top, right, bottom, left 0793 margin = coming.margin; 0794 padding = coming.padding; 0795 0796 if ($.type(margin) === 'number') { 0797 coming.margin = [margin, margin, margin, margin]; 0798 } 0799 0800 if ($.type(padding) === 'number') { 0801 coming.padding = [padding, padding, padding, padding]; 0802 } 0803 0804 // 'modal' propery is just a shortcut 0805 if (coming.modal) { 0806 $.extend(true, coming, { 0807 closeBtn : false, 0808 closeClick : false, 0809 nextClick : false, 0810 arrows : false, 0811 mouseWheel : false, 0812 keys : null, 0813 helpers: { 0814 overlay : { 0815 closeClick : false 0816 } 0817 } 0818 }); 0819 } 0820 0821 // 'autoSize' property is a shortcut, too 0822 if (coming.autoSize) { 0823 coming.autoWidth = coming.autoHeight = true; 0824 } 0825 0826 if (coming.width === 'auto') { 0827 coming.autoWidth = true; 0828 } 0829 0830 if (coming.height === 'auto') { 0831 coming.autoHeight = true; 0832 } 0833 0834 /* 0835 * Add reference to the group, so it`s possible to access from callbacks, example: 0836 * afterLoad : function() { 0837 * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); 0838 * } 0839 */ 0840 0841 coming.group = F.group; 0842 coming.index = index; 0843 0844 // Give a chance for callback or helpers to update coming item (type, title, etc) 0845 F.coming = coming; 0846 0847 if (false === F.trigger('beforeLoad')) { 0848 F.coming = null; 0849 0850 return; 0851 } 0852 0853 type = coming.type; 0854 href = coming.href; 0855 0856 if (!type) { 0857 F.coming = null; 0858 0859 //If we can not determine content type then drop silently or display next/prev item if looping through gallery 0860 if (F.current && F.router && F.router !== 'jumpto') { 0861 F.current.index = index; 0862 0863 return F[ F.router ]( F.direction ); 0864 } 0865 0866 return false; 0867 } 0868 0869 F.isActive = true; 0870 0871 if (type === 'image' || type === 'swf') { 0872 coming.autoHeight = coming.autoWidth = false; 0873 coming.scrolling = 'visible'; 0874 } 0875 0876 if (type === 'image') { 0877 coming.aspectRatio = true; 0878 } 0879 0880 if (type === 'iframe' && isTouch) { 0881 coming.scrolling = 'scroll'; 0882 } 0883 0884 // Build the neccessary markup 0885 coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); 0886 0887 $.extend(coming, { 0888 skin : $('.fancybox-skin', coming.wrap), 0889 outer : $('.fancybox-outer', coming.wrap), 0890 inner : $('.fancybox-inner', coming.wrap) 0891 }); 0892 0893 $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { 0894 coming.skin.css('padding' + v, getValue(coming.padding[ i ])); 0895 }); 0896 0897 F.trigger('onReady'); 0898 0899 // Check before try to load; 'inline' and 'html' types need content, others - href 0900 if (type === 'inline' || type === 'html') { 0901 if (!coming.content || !coming.content.length) { 0902 return F._error( 'content' ); 0903 } 0904 0905 } else if (!href) { 0906 return F._error( 'href' ); 0907 } 0908 0909 if (type === 'image') { 0910 F._loadImage(); 0911 0912 } else if (type === 'ajax') { 0913 F._loadAjax(); 0914 0915 } else if (type === 'iframe') { 0916 F._loadIframe(); 0917 0918 } else { 0919 F._afterLoad(); 0920 } 0921 }, 0922 0923 _error: function ( type ) { 0924 $.extend(F.coming, { 0925 type : 'html', 0926 autoWidth : true, 0927 autoHeight : true, 0928 minWidth : 0, 0929 minHeight : 0, 0930 scrolling : 'no', 0931 hasError : type, 0932 content : F.coming.tpl.error 0933 }); 0934 0935 F._afterLoad(); 0936 }, 0937 0938 _loadImage: function () { 0939 // Reset preload image so it is later possible to check "complete" property 0940 var img = F.imgPreload = new Image(); 0941 0942 img.onload = function () { 0943 this.onload = this.onerror = null; 0944 0945 F.coming.width = this.width; 0946 F.coming.height = this.height; 0947 0948 F._afterLoad(); 0949 }; 0950 0951 img.onerror = function () { 0952 this.onload = this.onerror = null; 0953 0954 F._error( 'image' ); 0955 }; 0956 0957 img.src = F.coming.href; 0958 0959 if (img.complete !== true) { 0960 F.showLoading(); 0961 } 0962 }, 0963 0964 _loadAjax: function () { 0965 var coming = F.coming; 0966 0967 F.showLoading(); 0968 0969 F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { 0970 url: coming.href, 0971 error: function (jqXHR, textStatus) { 0972 if (F.coming && textStatus !== 'abort') { 0973 F._error( 'ajax', jqXHR ); 0974 0975 } else { 0976 F.hideLoading(); 0977 } 0978 }, 0979 success: function (data, textStatus) { 0980 if (textStatus === 'success') { 0981 coming.content = data; 0982 0983 F._afterLoad(); 0984 } 0985 } 0986 })); 0987 }, 0988 0989 _loadIframe: function() { 0990 var coming = F.coming, 0991 iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) 0992 .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) 0993 .attr('src', coming.href); 0994 0995 // This helps IE 0996 $(coming.wrap).bind('onReset', function () { 0997 try { 0998 $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); 0999 } catch (e) {} 1000 }); 1001 1002 if (coming.iframe.preload) { 1003 F.showLoading(); 1004 1005 iframe.one('load', function() { 1006 $(this).data('ready', 1); 1007 1008 // iOS will lose scrolling if we resize 1009 if (!isTouch) { 1010 $(this).bind('load.fb', F.update); 1011 } 1012 1013 // Without this trick: 1014 // - iframe won't scroll on iOS devices 1015 // - IE7 sometimes displays empty iframe 1016 $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); 1017 1018 F._afterLoad(); 1019 }); 1020 } 1021 1022 coming.content = iframe.appendTo( coming.inner ); 1023 1024 if (!coming.iframe.preload) { 1025 F._afterLoad(); 1026 } 1027 }, 1028 1029 _preloadImages: function() { 1030 var group = F.group, 1031 current = F.current, 1032 len = group.length, 1033 cnt = current.preload ? Math.min(current.preload, len - 1) : 0, 1034 item, 1035 i; 1036 1037 for (i = 1; i <= cnt; i += 1) { 1038 item = group[ (current.index + i ) % len ]; 1039 1040 if (item.type === 'image' && item.href) { 1041 new Image().src = item.href; 1042 } 1043 } 1044 }, 1045 1046 _afterLoad: function () { 1047 var coming = F.coming, 1048 previous = F.current, 1049 placeholder = 'fancybox-placeholder', 1050 current, 1051 content, 1052 type, 1053 scrolling, 1054 href, 1055 embed; 1056 1057 F.hideLoading(); 1058 1059 if (!coming || F.isActive === false) { 1060 return; 1061 } 1062 1063 if (false === F.trigger('afterLoad', coming, previous)) { 1064 coming.wrap.stop(true).trigger('onReset').remove(); 1065 1066 F.coming = null; 1067 1068 return; 1069 } 1070 1071 if (previous) { 1072 F.trigger('beforeChange', previous); 1073 1074 previous.wrap.stop(true).removeClass('fancybox-opened') 1075 .find('.fancybox-item, .fancybox-nav') 1076 .remove(); 1077 } 1078 1079 F.unbindEvents(); 1080 1081 current = coming; 1082 content = coming.content; 1083 type = coming.type; 1084 scrolling = coming.scrolling; 1085 1086 $.extend(F, { 1087 wrap : current.wrap, 1088 skin : current.skin, 1089 outer : current.outer, 1090 inner : current.inner, 1091 current : current, 1092 previous : previous 1093 }); 1094 1095 href = current.href; 1096 1097 switch (type) { 1098 case 'inline': 1099 case 'ajax': 1100 case 'html': 1101 if (current.selector) { 1102 content = $('<div>').html(content).find(current.selector); 1103 1104 } else if (isQuery(content)) { 1105 if (!content.data(placeholder)) { 1106 content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() ); 1107 } 1108 1109 content = content.show().detach(); 1110 1111 current.wrap.bind('onReset', function () { 1112 if ($(this).find(content).length) { 1113 content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); 1114 } 1115 }); 1116 } 1117 break; 1118 1119 case 'image': 1120 content = current.tpl.image.replace('{href}', href); 1121 break; 1122 1123 case 'swf': 1124 content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>'; 1125 embed = ''; 1126 1127 $.each(current.swf, function(name, val) { 1128 content += '<param name="' + name + '" value="' + val + '"></param>'; 1129 embed += ' ' + name + '="' + val + '"'; 1130 }); 1131 1132 content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>'; 1133 break; 1134 } 1135 1136 if (!(isQuery(content) && content.parent().is(current.inner))) { 1137 current.inner.append( content ); 1138 } 1139 1140 // Give a chance for helpers or callbacks to update elements 1141 F.trigger('beforeShow'); 1142 1143 // Set scrolling before calculating dimensions 1144 current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); 1145 1146 // Set initial dimensions and start position 1147 F._setDimension(); 1148 1149 F.reposition(); 1150 1151 F.isOpen = false; 1152 F.coming = null; 1153 1154 F.bindEvents(); 1155 1156 if (!F.isOpened) { 1157 $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); 1158 1159 } else if (previous.prevMethod) { 1160 F.transitions[ previous.prevMethod ](); 1161 } 1162 1163 F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); 1164 1165 F._preloadImages(); 1166 }, 1167 1168 _setDimension: function () { 1169 var viewport = F.getViewport(), 1170 steps = 0, 1171 canShrink = false, 1172 canExpand = false, 1173 wrap = F.wrap, 1174 skin = F.skin, 1175 inner = F.inner, 1176 current = F.current, 1177 width = current.width, 1178 height = current.height, 1179 minWidth = current.minWidth, 1180 minHeight = current.minHeight, 1181 maxWidth = current.maxWidth, 1182 maxHeight = current.maxHeight, 1183 scrolling = current.scrolling, 1184 scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, 1185 margin = current.margin, 1186 wMargin = getScalar(margin[1] + margin[3]), 1187 hMargin = getScalar(margin[0] + margin[2]), 1188 wPadding, 1189 hPadding, 1190 wSpace, 1191 hSpace, 1192 origWidth, 1193 origHeight, 1194 origMaxWidth, 1195 origMaxHeight, 1196 ratio, 1197 width_, 1198 height_, 1199 maxWidth_, 1200 maxHeight_, 1201 iframe, 1202 body; 1203 1204 // Reset dimensions so we could re-check actual size 1205 wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); 1206 1207 wPadding = getScalar(skin.outerWidth(true) - skin.width()); 1208 hPadding = getScalar(skin.outerHeight(true) - skin.height()); 1209 1210 // Any space between content and viewport (margin, padding, border, title) 1211 wSpace = wMargin + wPadding; 1212 hSpace = hMargin + hPadding; 1213 1214 origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; 1215 origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; 1216 1217 if (current.type === 'iframe') { 1218 iframe = current.content; 1219 1220 if (current.autoHeight && iframe.data('ready') === 1) { 1221 try { 1222 if (iframe[0].contentWindow.document.location) { 1223 inner.width( origWidth ).height(9999); 1224 1225 body = iframe.contents().find('body'); 1226 1227 if (scrollOut) { 1228 body.css('overflow-x', 'hidden'); 1229 } 1230 1231 origHeight = body.height(); 1232 } 1233 1234 } catch (e) {} 1235 } 1236 1237 } else if (current.autoWidth || current.autoHeight) { 1238 inner.addClass( 'fancybox-tmp' ); 1239 1240 // Set width or height in case we need to calculate only one dimension 1241 if (!current.autoWidth) { 1242 inner.width( origWidth ); 1243 } 1244 1245 if (!current.autoHeight) { 1246 inner.height( origHeight ); 1247 } 1248 1249 if (current.autoWidth) { 1250 origWidth = inner.width(); 1251 } 1252 1253 if (current.autoHeight) { 1254 origHeight = inner.height(); 1255 } 1256 1257 inner.removeClass( 'fancybox-tmp' ); 1258 } 1259 1260 width = getScalar( origWidth ); 1261 height = getScalar( origHeight ); 1262 1263 ratio = origWidth / origHeight; 1264 1265 // Calculations for the content 1266 minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); 1267 maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); 1268 1269 minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); 1270 maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); 1271 1272 // These will be used to determine if wrap can fit in the viewport 1273 origMaxWidth = maxWidth; 1274 origMaxHeight = maxHeight; 1275 1276 if (current.fitToView) { 1277 maxWidth = Math.min(viewport.w - wSpace, maxWidth); 1278 maxHeight = Math.min(viewport.h - hSpace, maxHeight); 1279 } 1280 1281 maxWidth_ = viewport.w - wMargin; 1282 maxHeight_ = viewport.h - hMargin; 1283 1284 if (current.aspectRatio) { 1285 if (width > maxWidth) { 1286 width = maxWidth; 1287 height = getScalar(width / ratio); 1288 } 1289 1290 if (height > maxHeight) { 1291 height = maxHeight; 1292 width = getScalar(height * ratio); 1293 } 1294 1295 if (width < minWidth) { 1296 width = minWidth; 1297 height = getScalar(width / ratio); 1298 } 1299 1300 if (height < minHeight) { 1301 height = minHeight; 1302 width = getScalar(height * ratio); 1303 } 1304 1305 } else { 1306 width = Math.max(minWidth, Math.min(width, maxWidth)); 1307 1308 if (current.autoHeight && current.type !== 'iframe') { 1309 inner.width( width ); 1310 1311 height = inner.height(); 1312 } 1313 1314 height = Math.max(minHeight, Math.min(height, maxHeight)); 1315 } 1316 1317 // Try to fit inside viewport (including the title) 1318 if (current.fitToView) { 1319 inner.width( width ).height( height ); 1320 1321 wrap.width( width + wPadding ); 1322 1323 // Real wrap dimensions 1324 width_ = wrap.width(); 1325 height_ = wrap.height(); 1326 1327 if (current.aspectRatio) { 1328 while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { 1329 if (steps++ > 19) { 1330 break; 1331 } 1332 1333 height = Math.max(minHeight, Math.min(maxHeight, height - 10)); 1334 width = getScalar(height * ratio); 1335 1336 if (width < minWidth) { 1337 width = minWidth; 1338 height = getScalar(width / ratio); 1339 } 1340 1341 if (width > maxWidth) { 1342 width = maxWidth; 1343 height = getScalar(width / ratio); 1344 } 1345 1346 inner.width( width ).height( height ); 1347 1348 wrap.width( width + wPadding ); 1349 1350 width_ = wrap.width(); 1351 height_ = wrap.height(); 1352 } 1353 1354 } else { 1355 width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); 1356 height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); 1357 } 1358 } 1359 1360 if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { 1361 width += scrollOut; 1362 } 1363 1364 inner.width( width ).height( height ); 1365 1366 wrap.width( width + wPadding ); 1367 1368 width_ = wrap.width(); 1369 height_ = wrap.height(); 1370 1371 canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; 1372 canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); 1373 1374 $.extend(current, { 1375 dim : { 1376 width : getValue( width_ ), 1377 height : getValue( height_ ) 1378 }, 1379 origWidth : origWidth, 1380 origHeight : origHeight, 1381 canShrink : canShrink, 1382 canExpand : canExpand, 1383 wPadding : wPadding, 1384 hPadding : hPadding, 1385 wrapSpace : height_ - skin.outerHeight(true), 1386 skinSpace : skin.height() - height 1387 }); 1388 1389 if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { 1390 inner.height('auto'); 1391 } 1392 }, 1393 1394 _getPosition: function (onlyAbsolute) { 1395 var current = F.current, 1396 viewport = F.getViewport(), 1397 margin = current.margin, 1398 width = F.wrap.width() + margin[1] + margin[3], 1399 height = F.wrap.height() + margin[0] + margin[2], 1400 rez = { 1401 position: 'absolute', 1402 top : margin[0], 1403 left : margin[3] 1404 }; 1405 1406 if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { 1407 rez.position = 'fixed'; 1408 1409 } else if (!current.locked) { 1410 rez.top += viewport.y; 1411 rez.left += viewport.x; 1412 } 1413 1414 rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); 1415 rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); 1416 1417 return rez; 1418 }, 1419 1420 _afterZoomIn: function () { 1421 var current = F.current; 1422 1423 if (!current) { 1424 return; 1425 } 1426 1427 F.isOpen = F.isOpened = true; 1428 1429 F.wrap.css('overflow', 'visible').addClass('fancybox-opened'); 1430 1431 F.update(); 1432 1433 // Assign a click event 1434 if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { 1435 F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { 1436 if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { 1437 e.preventDefault(); 1438 1439 F[ current.closeClick ? 'close' : 'next' ](); 1440 } 1441 }); 1442 } 1443 1444 // Create a close button 1445 if (current.closeBtn) { 1446 $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { 1447 e.preventDefault(); 1448 1449 F.close(); 1450 }); 1451 } 1452 1453 // Create navigation arrows 1454 if (current.arrows && F.group.length > 1) { 1455 if (current.loop || current.index > 0) { 1456 $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); 1457 } 1458 1459 if (current.loop || current.index < F.group.length - 1) { 1460 $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); 1461 } 1462 } 1463 1464 F.trigger('afterShow'); 1465 1466 // Stop the slideshow if this is the last item 1467 if (!current.loop && current.index === current.group.length - 1) { 1468 F.play( false ); 1469 1470 } else if (F.opts.autoPlay && !F.player.isActive) { 1471 F.opts.autoPlay = false; 1472 1473 F.play(); 1474 } 1475 }, 1476 1477 _afterZoomOut: function ( obj ) { 1478 obj = obj || F.current; 1479 1480 $('.fancybox-wrap').trigger('onReset').remove(); 1481 1482 $.extend(F, { 1483 group : {}, 1484 opts : {}, 1485 router : false, 1486 current : null, 1487 isActive : false, 1488 isOpened : false, 1489 isOpen : false, 1490 isClosing : false, 1491 wrap : null, 1492 skin : null, 1493 outer : null, 1494 inner : null 1495 }); 1496 1497 F.trigger('afterClose', obj); 1498 } 1499 }); 1500 1501 /* 1502 * Default transitions 1503 */ 1504 1505 F.transitions = { 1506 getOrigPosition: function () { 1507 var current = F.current, 1508 element = current.element, 1509 orig = current.orig, 1510 pos = {}, 1511 width = 50, 1512 height = 50, 1513 hPadding = current.hPadding, 1514 wPadding = current.wPadding, 1515 viewport = F.getViewport(); 1516 1517 if (!orig && current.isDom && element.is(':visible')) { 1518 orig = element.find('img:first'); 1519 1520 if (!orig.length) { 1521 orig = element; 1522 } 1523 } 1524 1525 if (isQuery(orig)) { 1526 pos = orig.offset(); 1527 1528 if (orig.is('img')) { 1529 width = orig.outerWidth(); 1530 height = orig.outerHeight(); 1531 } 1532 1533 } else { 1534 pos.top = viewport.y + (viewport.h - height) * current.topRatio; 1535 pos.left = viewport.x + (viewport.w - width) * current.leftRatio; 1536 } 1537 1538 if (F.wrap.css('position') === 'fixed' || current.locked) { 1539 pos.top -= viewport.y; 1540 pos.left -= viewport.x; 1541 } 1542 1543 pos = { 1544 top : getValue(pos.top - hPadding * current.topRatio), 1545 left : getValue(pos.left - wPadding * current.leftRatio), 1546 width : getValue(width + wPadding), 1547 height : getValue(height + hPadding) 1548 }; 1549 1550 return pos; 1551 }, 1552 1553 step: function (now, fx) { 1554 var ratio, 1555 padding, 1556 value, 1557 prop = fx.prop, 1558 current = F.current, 1559 wrapSpace = current.wrapSpace, 1560 skinSpace = current.skinSpace; 1561 1562 if (prop === 'width' || prop === 'height') { 1563 ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); 1564 1565 if (F.isClosing) { 1566 ratio = 1 - ratio; 1567 } 1568 1569 padding = prop === 'width' ? current.wPadding : current.hPadding; 1570 value = now - padding; 1571 1572 F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); 1573 F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); 1574 } 1575 }, 1576 1577 zoomIn: function () { 1578 var current = F.current, 1579 startPos = current.pos, 1580 effect = current.openEffect, 1581 elastic = effect === 'elastic', 1582 endPos = $.extend({opacity : 1}, startPos); 1583 1584 // Remove "position" property that breaks older IE 1585 delete endPos.position; 1586 1587 if (elastic) { 1588 startPos = this.getOrigPosition(); 1589 1590 if (current.openOpacity) { 1591 startPos.opacity = 0.1; 1592 } 1593 1594 } else if (effect === 'fade') { 1595 startPos.opacity = 0.1; 1596 } 1597 1598 F.wrap.css(startPos).animate(endPos, { 1599 duration : effect === 'none' ? 0 : current.openSpeed, 1600 easing : current.openEasing, 1601 step : elastic ? this.step : null, 1602 complete : F._afterZoomIn 1603 }); 1604 }, 1605 1606 zoomOut: function () { 1607 var current = F.current, 1608 effect = current.closeEffect, 1609 elastic = effect === 'elastic', 1610 endPos = {opacity : 0.1}; 1611 1612 if (elastic) { 1613 endPos = this.getOrigPosition(); 1614 1615 if (current.closeOpacity) { 1616 endPos.opacity = 0.1; 1617 } 1618 } 1619 1620 F.wrap.animate(endPos, { 1621 duration : effect === 'none' ? 0 : current.closeSpeed, 1622 easing : current.closeEasing, 1623 step : elastic ? this.step : null, 1624 complete : F._afterZoomOut 1625 }); 1626 }, 1627 1628 changeIn: function () { 1629 var current = F.current, 1630 effect = current.nextEffect, 1631 startPos = current.pos, 1632 endPos = { opacity : 1 }, 1633 direction = F.direction, 1634 distance = 200, 1635 field; 1636 1637 startPos.opacity = 0.1; 1638 1639 if (effect === 'elastic') { 1640 field = direction === 'down' || direction === 'up' ? 'top' : 'left'; 1641 1642 if (direction === 'down' || direction === 'right') { 1643 startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); 1644 endPos[ field ] = '+=' + distance + 'px'; 1645 1646 } else { 1647 startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); 1648 endPos[ field ] = '-=' + distance + 'px'; 1649 } 1650 } 1651 1652 // Workaround for http://bugs.jquery.com/ticket/12273 1653 if (effect === 'none') { 1654 F._afterZoomIn(); 1655 1656 } else { 1657 F.wrap.css(startPos).animate(endPos, { 1658 duration : current.nextSpeed, 1659 easing : current.nextEasing, 1660 complete : F._afterZoomIn 1661 }); 1662 } 1663 }, 1664 1665 changeOut: function () { 1666 var previous = F.previous, 1667 effect = previous.prevEffect, 1668 endPos = { opacity : 0.1 }, 1669 direction = F.direction, 1670 distance = 200; 1671 1672 if (effect === 'elastic') { 1673 endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; 1674 } 1675 1676 previous.wrap.animate(endPos, { 1677 duration : effect === 'none' ? 0 : previous.prevSpeed, 1678 easing : previous.prevEasing, 1679 complete : function () { 1680 $(this).trigger('onReset').remove(); 1681 } 1682 }); 1683 } 1684 }; 1685 1686 /* 1687 * Overlay helper 1688 */ 1689 1690 F.helpers.overlay = { 1691 defaults : { 1692 closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay 1693 speedOut : 200, // duration of fadeOut animation 1694 showEarly : true, // indicates if should be opened immediately or wait until the content is ready 1695 css : {}, // custom CSS properties 1696 locked : !isTouch, // if true, the content will be locked into overlay 1697 fixed : true // if false, the overlay CSS position property will not be set to "fixed" 1698 }, 1699 1700 overlay : null, // current handle 1701 fixed : false, // indicates if the overlay has position "fixed" 1702 1703 // Public methods 1704 create : function(opts) { 1705 opts = $.extend({}, this.defaults, opts); 1706 1707 if (this.overlay) { 1708 this.close(); 1709 } 1710 1711 this.overlay = $('<div class="fancybox-overlay"></div>').appendTo( 'body' ); 1712 this.fixed = false; 1713 1714 if (opts.fixed && F.defaults.fixed) { 1715 this.overlay.addClass('fancybox-overlay-fixed'); 1716 1717 this.fixed = true; 1718 } 1719 }, 1720 1721 open : function(opts) { 1722 var that = this; 1723 1724 opts = $.extend({}, this.defaults, opts); 1725 1726 if (this.overlay) { 1727 this.overlay.unbind('.overlay').width('auto').height('auto'); 1728 1729 } else { 1730 this.create(opts); 1731 } 1732 1733 if (!this.fixed) { 1734 W.bind('resize.overlay', $.proxy( this.update, this) ); 1735 1736 this.update(); 1737 } 1738 1739 if (opts.closeClick) { 1740 this.overlay.bind('click.overlay', function(e) { 1741 if ($(e.target).hasClass('fancybox-overlay')) { 1742 if (F.isActive) { 1743 F.close(); 1744 } else { 1745 that.close(); 1746 } 1747 } 1748 }); 1749 } 1750 1751 this.overlay.css( opts.css ).show(); 1752 }, 1753 1754 close : function() { 1755 $('.fancybox-overlay').remove(); 1756 1757 W.unbind('resize.overlay'); 1758 1759 this.overlay = null; 1760 1761 if (this.margin !== false) { 1762 $('body').css('margin-right', this.margin); 1763 1764 this.margin = false; 1765 } 1766 1767 if (this.el) { 1768 this.el.removeClass('fancybox-lock'); 1769 } 1770 }, 1771 1772 // Private, callbacks 1773 1774 update : function () { 1775 var width = '100%', offsetWidth; 1776 1777 // Reset width/height so it will not mess 1778 this.overlay.width(width).height('100%'); 1779 1780 // jQuery does not return reliable result for IE 1781 if (IE) { 1782 offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); 1783 1784 if (D.width() > offsetWidth) { 1785 width = D.width(); 1786 } 1787 1788 } else if (D.width() > W.width()) { 1789 width = D.width(); 1790 } 1791 1792 this.overlay.width(width).height(D.height()); 1793 }, 1794 1795 // This is where we can manipulate DOM, because later it would cause iframes to reload 1796 onReady : function (opts, obj) { 1797 $('.fancybox-overlay').stop(true, true); 1798 1799 if (!this.overlay) { 1800 this.margin = D.height() > W.height() || $('body').css('overflow-y') === 'scroll' ? $('body').css('margin-right') : false; 1801 this.el = document.all && !document.querySelector ? $('html') : $('body'); 1802 1803 this.create(opts); 1804 } 1805 1806 if (opts.locked && this.fixed) { 1807 obj.locked = this.overlay.append( obj.wrap ); 1808 obj.fixed = false; 1809 } 1810 1811 if (opts.showEarly === true) { 1812 this.beforeShow.apply(this, arguments); 1813 } 1814 }, 1815 1816 beforeShow : function(opts, obj) { 1817 if (obj.locked) { 1818 this.el.addClass('fancybox-lock'); 1819 1820 if (this.margin !== false) { 1821 $('body').css('margin-right', getScalar( this.margin ) + obj.scrollbarWidth); 1822 } 1823 } 1824 1825 this.open(opts); 1826 }, 1827 1828 onUpdate : function() { 1829 if (!this.fixed) { 1830 this.update(); 1831 } 1832 }, 1833 1834 afterClose: function (opts) { 1835 // Remove overlay if exists and fancyBox is not opening 1836 // (e.g., it is not being open using afterClose callback) 1837 if (this.overlay && !F.isActive) { 1838 this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); 1839 } 1840 } 1841 }; 1842 1843 /* 1844 * Title helper 1845 */ 1846 1847 F.helpers.title = { 1848 defaults : { 1849 type : 'float', // 'float', 'inside', 'outside' or 'over', 1850 position : 'bottom' // 'top' or 'bottom' 1851 }, 1852 1853 beforeShow: function (opts) { 1854 var current = F.current, 1855 text = current.title, 1856 type = opts.type, 1857 title, 1858 target; 1859 1860 if ($.isFunction(text)) { 1861 text = text.call(current.element, current); 1862 } 1863 1864 if (!isString(text) || $.trim(text) === '') { 1865 return; 1866 } 1867 1868 title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">' + text + '</div>'); 1869 1870 switch (type) { 1871 case 'inside': 1872 target = F.skin; 1873 break; 1874 1875 case 'outside': 1876 target = F.wrap; 1877 break; 1878 1879 case 'over': 1880 target = F.inner; 1881 break; 1882 1883 default: // 'float' 1884 target = F.skin; 1885 1886 title.appendTo('body'); 1887 1888 if (IE) { 1889 title.width( title.width() ); 1890 } 1891 1892 title.wrapInner('<span class="child"></span>'); 1893 1894 //Increase bottom margin so this title will also fit into viewport 1895 F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); 1896 break; 1897 } 1898 1899 title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); 1900 } 1901 }; 1902 1903 // jQuery plugin initialization 1904 $.fn.fancybox = function (options) { 1905 var index, 1906 that = $(this), 1907 selector = this.selector || '', 1908 run = function(e) { 1909 var what = $(this).blur(), idx = index, relType, relVal; 1910 1911 if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { 1912 relType = options.groupAttr || 'data-fancybox-group'; 1913 relVal = what.attr(relType); 1914 1915 if (!relVal) { 1916 relType = 'rel'; 1917 relVal = what.get(0)[ relType ]; 1918 } 1919 1920 if (relVal && relVal !== '' && relVal !== 'nofollow') { 1921 what = selector.length ? $(selector) : that; 1922 what = what.filter('[' + relType + '="' + relVal + '"]'); 1923 idx = what.index(this); 1924 } 1925 1926 options.index = idx; 1927 1928 // Stop an event from bubbling if everything is fine 1929 if (F.open(what, options) !== false) { 1930 e.preventDefault(); 1931 } 1932 } 1933 }; 1934 1935 options = options || {}; 1936 index = options.index || 0; 1937 1938 if (!selector || options.live === false) { 1939 that.unbind('click.fb-start').bind('click.fb-start', run); 1940 1941 } else { 1942 D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); 1943 } 1944 1945 this.filter('[data-fancybox-start=1]').trigger('click'); 1946 1947 return this; 1948 }; 1949 1950 // Tests that need a body at doc ready 1951 D.ready(function() { 1952 if ( $.scrollbarWidth === undefined ) { 1953 // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth 1954 $.scrollbarWidth = function() { 1955 var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'), 1956 child = parent.children(), 1957 width = child.innerWidth() - child.height( 99 ).innerWidth(); 1958 1959 parent.remove(); 1960 1961 return width; 1962 }; 1963 } 1964 1965 if ( $.support.fixedPosition === undefined ) { 1966 $.support.fixedPosition = (function() { 1967 var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'), 1968 fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); 1969 1970 elem.remove(); 1971 1972 return fixed; 1973 }()); 1974 } 1975 1976 $.extend(F.defaults, { 1977 scrollbarWidth : $.scrollbarWidth(), 1978 fixed : $.support.fixedPosition, 1979 parent : $('body') 1980 }); 1981 }); 1982 1983 }(window, document, jQuery));