vendor: 7,522 bytes, lines 1-284
1/*! 2 * fancyBox - jQuery Plugin 3 * version: 2.1.5 (Fri, 14 Jun 2013) 4 * @requires jQuery v1.6 or later 5 * 6 * Examples at http://fancyapps.com/fancybox/ 7 * License: www.fancyapps.com/fancybox/#license 8 * 9 * Copyright 2012 Janis Skarnelis - [email protected] 10 * 11 * Dual licensed under the MIT and GPL licenses: 12 * http://www.opensource.org/licenses/mit-license.php 13 * http://www.gnu.org/licenses/gpl.html 14 * 15 */ 16 17(function (window, document, $, undefined) { 18 "use strict"; 19 20 var H = $("html"), 21 W = $(window), 22 D = $(document), 23 F = $.fancybox = function () { 24 F.open.apply( this, arguments ); 25 }, 26 IE = navigator.userAgent.match(/msie/i), 27 didUpdate = null, 28 isTouch = document.createTouch !== undefined, 29 30 isQuery = function(obj) { 31 return obj && obj.hasOwnProperty && obj instanceof $; 32 }, 33 isString = function(str) { 34 return str && $.type(str) === "string"; 35 }, 36 isPercentage = function(str) { 37 return isString(str) && str.indexOf('%') > 0; 38 }, 39 isScrollable = function(el) { 40 return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); 41 }, 42 getScalar = function(orig, dim) { 43 var value = parseInt(orig, 10) || 0; 44 45 if (dim && isPercentage(orig)) { 46 value = F.getViewport()[ dim ] / 100 * value; 47 } 48 49 return Math.ceil(value); 50 }, 51 getValue = function(value, dim) { 52 return getScalar(value, dim) + 'px'; 53 }; 54 55 $.extend(F, { 56 // The current version of fancyBox 57 version: '2.1.5', 58 59 defaults: { 60 padding : 15, 61 margin : 20, 62 63 width : 800, 64 height : 600, 65 minWidth : 100, 66 minHeight : 50, 67 maxWidth : 9999, 68 maxHeight : 9999, 69 pixelRatio: 1, // Set to 2 for retina display support 70 71 autoSize : true, 72 autoHeight : false, 73 autoWidth : false, 74 75 autoResize : true, 76 autoCenter : !isTouch, 77 fitToView : true, 78 aspectRatio : false, 79 topRatio : 0.5, 80 leftRatio : 0.5, 81 82 scrolling : 'auto', // 'auto', 'yes' or 'no' 83 wrapCSS : '', 84 85 arrows : true, 86 closeBtn : true, 87 closeClick : false, 88 nextClick : false, 89 mouseWheel : true, 90 autoPlay : false, 91 playSpeed : 3000, 92 preload : 3, 93 modal : false, 94 loop : true, 95 96 ajax : { 97 dataType : 'html', 98 headers : { 'X-fancyBox': true } 99 }, 100 iframe : { 101 scrolling : 'auto', 102 preload : true 103 }, 104 swf : { 105 wmode: 'transparent', 106 allowfullscreen : 'true', 107 allowscriptaccess : 'always' 108 }, 109 110 keys : { 111 next : { 112 13 : 'left', // enter 113 34 : 'up', // page down 114 39 : 'left', // right arrow 115 40 : 'up' // down arrow 116 }, 117 prev : { 118 8 : 'right', // backspace 119 33 : 'down', // page up 120 37 : 'right', // left arrow 121 38 : 'down' // up arrow 122 }, 123 close : [27], // escape key 124 play : [32], // space - start/stop slideshow 125 toggle : [70] // letter "f" - toggle fullscreen 126 }, 127 128 direction : { 129 next : 'left', 130 prev : 'right' 131 }, 132 133 scrollOutside : true, 134 135 // Override some properties 136 index : 0, 137 type : null, 138 href : null, 139 content : null, 140 title : null, 141 142 // HTML templates 143 tpl: { 144 wrap : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>', 145 image : '<img class="fancybox-image" src="{href}" alt="" />', 146 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>', 147 error : '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>', 148 closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>', 149 next : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>', 150 prev : '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>' 151 }, 152 153 // Properties for each animation type 154 // Opening fancyBox 155 openEffect : 'fade', // 'elastic', 'fade' or 'none' 156 openSpeed : 250, 157 openEasing : 'swing', 158 openOpacity : true, 159 openMethod : 'zoomIn', 160 161 // Closing fancyBox 162 closeEffect : 'fade', // 'elastic', 'fade' or 'none' 163 closeSpeed : 250, 164 closeEasing : 'swing', 165 closeOpacity : true, 166 closeMethod : 'zoomOut', 167 168 // Changing next gallery item 169 nextEffect : 'elastic', // 'elastic', 'fade' or 'none' 170 nextSpeed : 250, 171 nextEasing : 'swing', 172 nextMethod : 'changeIn', 173 174 // Changing previous gallery item 175 prevEffect : 'elastic', // 'elastic', 'fade' or 'none' 176 prevSpeed : 250, 177 prevEasing : 'swing', 178 prevMethod : 'changeOut', 179 180 // Enable default helpers 181 helpers : { 182 overlay : true, 183 title : true 184 }, 185 186 // Callbacks 187 onCancel : $.noop, // If canceling 188 beforeLoad : $.noop, // Before loading 189 afterLoad : $.noop, // After loading 190 beforeShow : $.noop, // Before changing in current item 191 afterShow : $.noop, // After opening 192 beforeChange : $.noop, // Before changing gallery item 193 beforeClose : $.noop, // Before closing 194 afterClose : $.noop // After closing 195 }, 196 197 //Current state 198 group : {}, // Selected group 199 opts : {}, // Group options 200 previous : null, // Previous element 201 coming : null, // Element being loaded 202 current : null, // Currently loaded element 203 isActive : false, // Is activated 204 isOpen : false, // Is currently open 205 isOpened : false, // Have been fully opened at least once 206 207 wrap : null, 208 skin : null, 209 outer : null, 210 inner : null, 211 212 player : { 213 timer : null, 214 isActive : false 215 }, 216 217 // Loaders 218 ajaxLoad : null, 219 imgPreload : null, 220 221 // Some collections 222 transitions : {}, 223 helpers : {}, 224 225 /* 226 * Static methods 227 */ 228 229 open: function (group, opts) { 230 if (!group) { 231 return; 232 } 233 234 if (!$.isPlainObject(opts)) { 235 opts = {}; 236 } 237 238 // Close if already active 239 if (false === F.close(true)) { 240 return; 241 } 242 243 // Normalize group 244 if (!$.isArray(group)) { 245 group = isQuery(group) ? $(group).get() : [group]; 246 } 247 248 // Recheck if the type of each element is `object` and set content type (image, ajax, etc) 249 $.each(group, function(i, element) { 250 var obj = {}, 251 href, 252 title, 253 content, 254 type, 255 rez, 256 hrefParts, 257 selector; 258 259 if ($.type(element) === "object") { 260 // Check if is DOM element 261 if (element.nodeType) { 262 element = $(element); 263 } 264 265 if (isQuery(element)) { 266 obj = { 267 href : element.data('fancybox-href') || element.attr('href'), 268 title : element.data('fancybox-title') || element.attr('title'), 269 isDom : true, 270 element : element 271 }; 272 273 if ($.metadata) { 274 $.extend(true, obj, element.metadata()); 275 } 276 277 } else { 278 obj = element; 279 } 280 } 281 282 href = opts.href || obj.href || (isString(element) ? element : null); 283 title = opts.title !== undefined ? opts.title : obj.title || ''; 284
vendor: 40,063 bytes, lines 285-1896
285 content = opts.content || obj.content; 286 type = content ? 'html' : (opts.type || obj.type); 287 288 if (!type && obj.isDom) { 289 type = element.data('fancybox-type'); 290 291 if (!type) { 292 rez = element.prop('class').match(/fancybox\.(\w+)/); 293 type = rez ? rez[1] : null; 294 } 295 } 296 297 if (isString(href)) { 298 // Try to guess the content type 299 if (!type) { 300 if (F.isImage(href)) { 301 type = 'image'; 302 303 } else if (F.isSWF(href)) { 304 type = 'swf'; 305 306 } else if (href.charAt(0) === '#') { 307 type = 'inline'; 308 309 } else if (isString(element)) { 310 type = 'html'; 311 content = element; 312 } 313 } 314 315 // Split url into two pieces with source url and content selector, e.g, 316 // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" 317 if (type === 'ajax') { 318 hrefParts = href.split(/\s+/, 2); 319 href = hrefParts.shift(); 320 selector = hrefParts.shift(); 321 } 322 } 323 324 if (!content) { 325 if (type === 'inline') { 326 if (href) { 327 content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 328 329 } else if (obj.isDom) { 330 content = element; 331 } 332 333 } else if (type === 'html') { 334 content = href; 335 336 } else if (!type && !href && obj.isDom) { 337 type = 'inline'; 338 content = element; 339 } 340 } 341 342 $.extend(obj, { 343 href : href, 344 type : type, 345 content : content, 346 title : title, 347 selector : selector 348 }); 349 350 group[ i ] = obj; 351 }); 352 353 // Extend the defaults 354 F.opts = $.extend(true, {}, F.defaults, opts); 355 356 // All options are merged recursive except keys 357 if (opts.keys !== undefined) { 358 F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; 359 } 360 361 F.group = group; 362 363 return F._start(F.opts.index); 364 }, 365 366 // Cancel image loading or abort ajax request 367 cancel: function () { 368 var coming = F.coming; 369 370 if (!coming || false === F.trigger('onCancel')) { 371 return; 372 } 373 374 F.hideLoading(); 375 376 if (F.ajaxLoad) { 377 F.ajaxLoad.abort(); 378 } 379 380 F.ajaxLoad = null; 381 382 if (F.imgPreload) { 383 F.imgPreload.onload = F.imgPreload.onerror = null; 384 } 385 386 if (coming.wrap) { 387 coming.wrap.stop(true, true).trigger('onReset').remove(); 388 } 389 390 F.coming = null; 391 392 // If the first item has been canceled, then clear everything 393 if (!F.current) { 394 F._afterZoomOut( coming ); 395 } 396 }, 397 398 // Start closing animation if is open; remove immediately if opening/closing 399 close: function (event) { 400 F.cancel(); 401 402 if (false === F.trigger('beforeClose')) { 403 return; 404 } 405 406 F.unbindEvents(); 407 408 if (!F.isActive) { 409 return; 410 } 411 412 if (!F.isOpen || event === true) { 413 $('.fancybox-wrap').stop(true).trigger('onReset').remove(); 414 415 F._afterZoomOut(); 416 417 } else { 418 F.isOpen = F.isOpened = false; 419 F.isClosing = true; 420 421 $('.fancybox-item, .fancybox-nav').remove(); 422 423 F.wrap.stop(true, true).removeClass('fancybox-opened'); 424 425 F.transitions[ F.current.closeMethod ](); 426 } 427 }, 428 429 // Manage slideshow: 430 // $.fancybox.play(); - toggle slideshow 431 // $.fancybox.play( true ); - start 432 // $.fancybox.play( false ); - stop 433 play: function ( action ) { 434 var clear = function () { 435 clearTimeout(F.player.timer); 436 }, 437 set = function () { 438 clear(); 439 440 if (F.current && F.player.isActive) { 441 F.player.timer = setTimeout(F.next, F.current.playSpeed); 442 } 443 }, 444 stop = function () { 445 clear(); 446 447 D.unbind('.player'); 448 449 F.player.isActive = false; 450 451 F.trigger('onPlayEnd'); 452 }, 453 start = function () { 454 if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { 455 F.player.isActive = true; 456 457 D.bind({ 458 'onCancel.player beforeClose.player' : stop, 459 'onUpdate.player' : set, 460 'beforeLoad.player' : clear 461 }); 462 463 set(); 464 465 F.trigger('onPlayStart'); 466 } 467 }; 468 469 if (action === true || (!F.player.isActive && action !== false)) { 470 start(); 471 } else { 472 stop(); 473 } 474 }, 475 476 // Navigate to next gallery item 477 next: function ( direction ) { 478 var current = F.current; 479 480 if (current) { 481 if (!isString(direction)) { 482 direction = current.direction.next; 483 } 484 485 F.jumpto(current.index + 1, direction, 'next'); 486 } 487 }, 488 489 // Navigate to previous gallery item 490 prev: function ( direction ) { 491 var current = F.current; 492 493 if (current) { 494 if (!isString(direction)) { 495 direction = current.direction.prev; 496 } 497 498 F.jumpto(current.index - 1, direction, 'prev'); 499 } 500 }, 501 502 // Navigate to gallery item by index 503 jumpto: function ( index, direction, router ) { 504 var current = F.current; 505 506 if (!current) { 507 return; 508 } 509 510 index = getScalar(index); 511 512 F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; 513 F.router = router || 'jumpto'; 514 515 if (current.loop) { 516 if (index < 0) { 517 index = current.group.length + (index % current.group.length); 518 } 519 520 index = index % current.group.length; 521 } 522 523 if (current.group[ index ] !== undefined) { 524 F.cancel(); 525 526 F._start(index); 527 } 528 }, 529 530 // Center inside viewport and toggle position type to fixed or absolute if needed 531 reposition: function (e, onlyAbsolute) { 532 var current = F.current, 533 wrap = current ? current.wrap : null, 534 pos; 535 536 if (wrap) { 537 pos = F._getPosition(onlyAbsolute); 538 539 if (e && e.type === 'scroll') { 540 delete pos.position; 541 542 wrap.stop(true, true).animate(pos, 200); 543 544 } else { 545 wrap.css(pos); 546 547 current.pos = $.extend({}, current.dim, pos); 548 } 549 } 550 }, 551 552 update: function (e) { 553 var type = (e && e.type), 554 anyway = !type || type === 'orientationchange'; 555 556 if (anyway) { 557 clearTimeout(didUpdate); 558 559 didUpdate = null; 560 } 561 562 if (!F.isOpen || didUpdate) { 563 return; 564 } 565 566 didUpdate = setTimeout(function() { 567 var current = F.current; 568 569 if (!current || F.isClosing) { 570 return; 571 } 572 573 F.wrap.removeClass('fancybox-tmp'); 574 575 if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { 576 F._setDimension(); 577 } 578 579 if (!(type === 'scroll' && current.canShrink)) { 580 F.reposition(e); 581 } 582 583 F.trigger('onUpdate'); 584 585 didUpdate = null; 586 587 }, (anyway && !isTouch ? 0 : 300)); 588 }, 589 590 // Shrink content to fit inside viewport or restore if resized 591 toggle: function ( action ) { 592 if (F.isOpen) { 593 F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; 594 595 // Help browser to restore document dimensions 596 if (isTouch) { 597 F.wrap.removeAttr('style').addClass('fancybox-tmp'); 598 599 F.trigger('onUpdate'); 600 } 601 602 F.update(); 603 } 604 }, 605 606 hideLoading: function () { 607 D.unbind('.loading'); 608 609 $('#fancybox-loading').remove(); 610 }, 611 612 showLoading: function () { 613 var el, viewport; 614 615 F.hideLoading(); 616 617 el = $('<div id="fancybox-loading"><div></div></div>').click(F.cancel).appendTo('body'); 618 619 // If user will press the escape-button, the request will be canceled 620 D.bind('keydown.loading', function(e) { 621 if ((e.which || e.keyCode) === 27) { 622 e.preventDefault(); 623 624 F.cancel(); 625 } 626 }); 627 628 if (!F.defaults.fixed) { 629 viewport = F.getViewport(); 630 631 el.css({ 632 position : 'absolute', 633 top : (viewport.h * 0.5) + viewport.y, 634 left : (viewport.w * 0.5) + viewport.x 635 }); 636 } 637 }, 638 639 getViewport: function () { 640 var locked = (F.current && F.current.locked) || false, 641 rez = { 642 x: W.scrollLeft(), 643 y: W.scrollTop() 644 }; 645 646 if (locked) { 647 rez.w = locked[0].clientWidth; 648 rez.h = locked[0].clientHeight; 649 650 } else { 651 // See http://bugs.jquery.com/ticket/6724 652 rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); 653 rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); 654 } 655 656 return rez; 657 }, 658 659 // Unbind the keyboard / clicking actions 660 unbindEvents: function () { 661 if (F.wrap && isQuery(F.wrap)) { 662 F.wrap.unbind('.fb'); 663 } 664 665 D.unbind('.fb'); 666 W.unbind('.fb'); 667 }, 668 669 bindEvents: function () { 670 var current = F.current, 671 keys; 672 673 if (!current) { 674 return; 675 } 676 677 // Changing document height on iOS devices triggers a 'resize' event, 678 // that can change document height... repeating infinitely 679 W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); 680 681 keys = current.keys; 682 683 if (keys) { 684 D.bind('keydown.fb', function (e) { 685 var code = e.which || e.keyCode, 686 target = e.target || e.srcElement; 687 688 // Skip esc key if loading, because showLoading will cancel preloading 689 if (code === 27 && F.coming) { 690 return false; 691 } 692 693 // Ignore key combinations and key events within form elements 694 if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { 695 $.each(keys, function(i, val) { 696 if (current.group.length > 1 && val[ code ] !== undefined) { 697 F[ i ]( val[ code ] ); 698 699 e.preventDefault(); 700 return false; 701 } 702 703 if ($.inArray(code, val) > -1) { 704 F[ i ] (); 705 706 e.preventDefault(); 707 return false; 708 } 709 }); 710 } 711 }); 712 } 713 714 if ($.fn.mousewheel && current.mouseWheel) { 715 F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { 716 var target = e.target || null, 717 parent = $(target), 718 canScroll = false; 719 720 while (parent.length) { 721 if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { 722 break; 723 } 724 725 canScroll = isScrollable( parent[0] ); 726 parent = $(parent).parent(); 727 } 728 729 if (delta !== 0 && !canScroll) { 730 if (F.group.length > 1 && !current.canShrink) { 731 if (deltaY > 0 || deltaX > 0) { 732 F.prev( deltaY > 0 ? 'down' : 'left' ); 733 734 } else if (deltaY < 0 || deltaX < 0) { 735 F.next( deltaY < 0 ? 'up' : 'right' ); 736 } 737 738 e.preventDefault(); 739 } 740 } 741 }); 742 } 743 }, 744 745 trigger: function (event, o) { 746 var ret, obj = o || F.coming || F.current; 747 748 if (!obj) { 749 return; 750 } 751 752 if ($.isFunction( obj[event] )) { 753 ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); 754 } 755 756 if (ret === false) { 757 return false; 758 } 759 760 if (obj.helpers) { 761 $.each(obj.helpers, function (helper, opts) { 762 if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { 763 F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj); 764 } 765 }); 766 } 767 768 D.trigger(event); 769 }, 770 771 isImage: function (str) { 772 return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); 773 }, 774 775 isSWF: function (str) { 776 return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); 777 }, 778 779 _start: function (index) { 780 var coming = {}, 781 obj, 782 href, 783 type, 784 margin, 785 padding; 786 787 index = getScalar( index ); 788 obj = F.group[ index ] || null; 789 790 if (!obj) { 791 return false; 792 } 793 794 coming = $.extend(true, {}, F.opts, obj); 795 796 // Convert margin and padding properties to array - top, right, bottom, left 797 margin = coming.margin; 798 padding = coming.padding; 799 800 if ($.type(margin) === 'number') { 801 coming.margin = [margin, margin, margin, margin]; 802 } 803 804 if ($.type(padding) === 'number') { 805 coming.padding = [padding, padding, padding, padding]; 806 } 807 808 // 'modal' propery is just a shortcut 809 if (coming.modal) { 810 $.extend(true, coming, { 811 closeBtn : false, 812 closeClick : false, 813 nextClick : false, 814 arrows : false, 815 mouseWheel : false, 816 keys : null, 817 helpers: { 818 overlay : { 819 closeClick : false 820 } 821 } 822 }); 823 } 824 825 // 'autoSize' property is a shortcut, too 826 if (coming.autoSize) { 827 coming.autoWidth = coming.autoHeight = true; 828 } 829 830 if (coming.width === 'auto') { 831 coming.autoWidth = true; 832 } 833 834 if (coming.height === 'auto') { 835 coming.autoHeight = true; 836 } 837 838 /* 839 * Add reference to the group, so it`s possible to access from callbacks, example: 840 * afterLoad : function() { 841 * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); 842 * } 843 */ 844 845 coming.group = F.group; 846 coming.index = index; 847 848 // Give a chance for callback or helpers to update coming item (type, title, etc) 849 F.coming = coming; 850 851 if (false === F.trigger('beforeLoad')) { 852 F.coming = null; 853 854 return; 855 } 856 857 type = coming.type; 858 href = coming.href; 859 860 if (!type) { 861 F.coming = null; 862 863 //If we can not determine content type then drop silently or display next/prev item if looping through gallery 864 if (F.current && F.router && F.router !== 'jumpto') { 865 F.current.index = index; 866 867 return F[ F.router ]( F.direction ); 868 } 869 870 return false; 871 } 872 873 F.isActive = true; 874 875 if (type === 'image' || type === 'swf') { 876 coming.autoHeight = coming.autoWidth = false; 877 coming.scrolling = 'visible'; 878 } 879 880 if (type === 'image') { 881 coming.aspectRatio = true; 882 } 883 884 if (type === 'iframe' && isTouch) { 885 coming.scrolling = 'scroll'; 886 } 887 888 // Build the neccessary markup 889 coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); 890 891 $.extend(coming, { 892 skin : $('.fancybox-skin', coming.wrap), 893 outer : $('.fancybox-outer', coming.wrap), 894 inner : $('.fancybox-inner', coming.wrap) 895 }); 896 897 $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { 898 coming.skin.css('padding' + v, getValue(coming.padding[ i ])); 899 }); 900 901 F.trigger('onReady'); 902 903 // Check before try to load; 'inline' and 'html' types need content, others - href 904 if (type === 'inline' || type === 'html') { 905 if (!coming.content || !coming.content.length) { 906 return F._error( 'content' ); 907 } 908 909 } else if (!href) { 910 return F._error( 'href' ); 911 } 912 913 if (type === 'image') { 914 F._loadImage(); 915 916 } else if (type === 'ajax') { 917 F._loadAjax(); 918 919 } else if (type === 'iframe') { 920 F._loadIframe(); 921 922 } else { 923 F._afterLoad(); 924 } 925 }, 926 927 _error: function ( type ) { 928 $.extend(F.coming, { 929 type : 'html', 930 autoWidth : true, 931 autoHeight : true, 932 minWidth : 0, 933 minHeight : 0, 934 scrolling : 'no', 935 hasError : type, 936 content : F.coming.tpl.error 937 }); 938 939 F._afterLoad(); 940 }, 941 942 _loadImage: function () { 943 // Reset preload image so it is later possible to check "complete" property 944 var img = F.imgPreload = new Image(); 945 946 img.onload = function () { 947 this.onload = this.onerror = null; 948 949 F.coming.width = this.width / F.opts.pixelRatio; 950 F.coming.height = this.height / F.opts.pixelRatio; 951 952 F._afterLoad(); 953 }; 954 955 img.onerror = function () { 956 this.onload = this.onerror = null; 957 958 F._error( 'image' ); 959 }; 960 961 img.src = F.coming.href; 962 963 if (img.complete !== true) { 964 F.showLoading(); 965 } 966 }, 967 968 _loadAjax: function () { 969 var coming = F.coming; 970 971 F.showLoading(); 972 973 F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { 974 url: coming.href, 975 error: function (jqXHR, textStatus) { 976 if (F.coming && textStatus !== 'abort') { 977 F._error( 'ajax', jqXHR ); 978 979 } else { 980 F.hideLoading(); 981 } 982 }, 983 success: function (data, textStatus) { 984 if (textStatus === 'success') { 985 coming.content = data; 986 987 F._afterLoad(); 988 } 989 } 990 })); 991 }, 992 993 _loadIframe: function() { 994 var coming = F.coming, 995 iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) 996 .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) 997 .attr('src', coming.href); 998 999 // This helps IE 1000 $(coming.wrap).bind('onReset', function () { 1001 try { 1002 $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); 1003 } catch (e) {} 1004 }); 1005 1006 if (coming.iframe.preload) { 1007 F.showLoading(); 1008 1009 iframe.one('load', function() { 1010 $(this).data('ready', 1); 1011 1012 // iOS will lose scrolling if we resize 1013 if (!isTouch) { 1014 $(this).bind('load.fb', F.update); 1015 } 1016 1017 // Without this trick: 1018 // - iframe won't scroll on iOS devices 1019 // - IE7 sometimes displays empty iframe 1020 $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); 1021 1022 F._afterLoad(); 1023 }); 1024 } 1025 1026 coming.content = iframe.appendTo( coming.inner ); 1027 1028 if (!coming.iframe.preload) { 1029 F._afterLoad(); 1030 } 1031 }, 1032 1033 _preloadImages: function() { 1034 var group = F.group, 1035 current = F.current, 1036 len = group.length, 1037 cnt = current.preload ? Math.min(current.preload, len - 1) : 0, 1038 item, 1039 i; 1040 1041 for (i = 1; i <= cnt; i += 1) { 1042 item = group[ (current.index + i ) % len ]; 1043 1044 if (item.type === 'image' && item.href) { 1045 new Image().src = item.href; 1046 } 1047 } 1048 }, 1049 1050 _afterLoad: function () { 1051 var coming = F.coming, 1052 previous = F.current, 1053 placeholder = 'fancybox-placeholder', 1054 current, 1055 content, 1056 type, 1057 scrolling, 1058 href, 1059 embed; 1060 1061 F.hideLoading(); 1062 1063 if (!coming || F.isActive === false) { 1064 return; 1065 } 1066 1067 if (false === F.trigger('afterLoad', coming, previous)) { 1068 coming.wrap.stop(true).trigger('onReset').remove(); 1069 1070 F.coming = null; 1071 1072 return; 1073 } 1074 1075 if (previous) { 1076 F.trigger('beforeChange', previous); 1077 1078 previous.wrap.stop(true).removeClass('fancybox-opened') 1079 .find('.fancybox-item, .fancybox-nav') 1080 .remove(); 1081 } 1082 1083 F.unbindEvents(); 1084 1085 current = coming; 1086 content = coming.content; 1087 type = coming.type; 1088 scrolling = coming.scrolling; 1089 1090 $.extend(F, { 1091 wrap : current.wrap, 1092 skin : current.skin, 1093 outer : current.outer, 1094 inner : current.inner, 1095 current : current, 1096 previous : previous 1097 }); 1098 1099 href = current.href; 1100 1101 switch (type) { 1102 case 'inline': 1103 case 'ajax': 1104 case 'html': 1105 if (current.selector) { 1106 content = $('<div>').html(content).find(current.selector); 1107 1108 } else if (isQuery(content)) { 1109 if (!content.data(placeholder)) { 1110 content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() ); 1111 } 1112 1113 content = content.show().detach(); 1114 1115 current.wrap.bind('onReset', function () { 1116 if ($(this).find(content).length) { 1117 content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); 1118 } 1119 }); 1120 } 1121 break; 1122 1123 case 'image': 1124 content = current.tpl.image.replace('{href}', href); 1125 break; 1126 1127 case 'swf': 1128 content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>'; 1129 embed = ''; 1130 1131 $.each(current.swf, function(name, val) { 1132 content += '<param name="' + name + '" value="' + val + '"></param>'; 1133 embed += ' ' + name + '="' + val + '"'; 1134 }); 1135 1136 content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>'; 1137 break; 1138 } 1139 1140 if (!(isQuery(content) && content.parent().is(current.inner))) { 1141 current.inner.append( content ); 1142 } 1143 1144 // Give a chance for helpers or callbacks to update elements 1145 F.trigger('beforeShow'); 1146 1147 // Set scrolling before calculating dimensions 1148 current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); 1149 1150 // Set initial dimensions and start position 1151 F._setDimension(); 1152 1153 F.reposition(); 1154 1155 F.isOpen = false; 1156 F.coming = null; 1157 1158 F.bindEvents(); 1159 1160 if (!F.isOpened) { 1161 $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); 1162 1163 } else if (previous.prevMethod) { 1164 F.transitions[ previous.prevMethod ](); 1165 } 1166 1167 F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); 1168 1169 F._preloadImages(); 1170 }, 1171 1172 _setDimension: function () { 1173 var viewport = F.getViewport(), 1174 steps = 0, 1175 canShrink = false, 1176 canExpand = false, 1177 wrap = F.wrap, 1178 skin = F.skin, 1179 inner = F.inner, 1180 current = F.current, 1181 width = current.width, 1182 height = current.height, 1183 minWidth = current.minWidth, 1184 minHeight = current.minHeight, 1185 maxWidth = current.maxWidth, 1186 maxHeight = current.maxHeight, 1187 scrolling = current.scrolling, 1188 scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, 1189 margin = current.margin, 1190 wMargin = getScalar(margin[1] + margin[3]), 1191 hMargin = getScalar(margin[0] + margin[2]), 1192 wPadding, 1193 hPadding, 1194 wSpace, 1195 hSpace, 1196 origWidth, 1197 origHeight, 1198 origMaxWidth, 1199 origMaxHeight, 1200 ratio, 1201 width_, 1202 height_, 1203 maxWidth_, 1204 maxHeight_, 1205 iframe, 1206 body; 1207 1208 // Reset dimensions so we could re-check actual size 1209 wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); 1210 1211 wPadding = getScalar(skin.outerWidth(true) - skin.width()); 1212 hPadding = getScalar(skin.outerHeight(true) - skin.height()); 1213 1214 // Any space between content and viewport (margin, padding, border, title) 1215 wSpace = wMargin + wPadding; 1216 hSpace = hMargin + hPadding; 1217 1218 origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; 1219 origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; 1220 1221 if (current.type === 'iframe') { 1222 iframe = current.content; 1223 1224 if (current.autoHeight && iframe.data('ready') === 1) { 1225 try { 1226 if (iframe[0].contentWindow.document.location) { 1227 inner.width( origWidth ).height(9999); 1228 1229 body = iframe.contents().find('body'); 1230 1231 if (scrollOut) { 1232 body.css('overflow-x', 'hidden'); 1233 } 1234 1235 origHeight = body.outerHeight(true); 1236 } 1237 1238 } catch (e) {} 1239 } 1240 1241 } else if (current.autoWidth || current.autoHeight) { 1242 inner.addClass( 'fancybox-tmp' ); 1243 1244 // Set width or height in case we need to calculate only one dimension 1245 if (!current.autoWidth) { 1246 inner.width( origWidth ); 1247 } 1248 1249 if (!current.autoHeight) { 1250 inner.height( origHeight ); 1251 } 1252 1253 if (current.autoWidth) { 1254 origWidth = inner.width(); 1255 } 1256 1257 if (current.autoHeight) { 1258 origHeight = inner.height(); 1259 } 1260 1261 inner.removeClass( 'fancybox-tmp' ); 1262 } 1263 1264 width = getScalar( origWidth ); 1265 height = getScalar( origHeight ); 1266 1267 ratio = origWidth / origHeight; 1268 1269 // Calculations for the content 1270 minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); 1271 maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); 1272 1273 minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); 1274 maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); 1275 1276 // These will be used to determine if wrap can fit in the viewport 1277 origMaxWidth = maxWidth; 1278 origMaxHeight = maxHeight; 1279 1280 if (current.fitToView) { 1281 maxWidth = Math.min(viewport.w - wSpace, maxWidth); 1282 maxHeight = Math.min(viewport.h - hSpace, maxHeight); 1283 } 1284 1285 maxWidth_ = viewport.w - wMargin; 1286 maxHeight_ = viewport.h - hMargin; 1287 1288 if (current.aspectRatio) { 1289 if (width > maxWidth) { 1290 width = maxWidth; 1291 height = getScalar(width / ratio); 1292 } 1293 1294 if (height > maxHeight) { 1295 height = maxHeight; 1296 width = getScalar(height * ratio); 1297 } 1298 1299 if (width < minWidth) { 1300 width = minWidth; 1301 height = getScalar(width / ratio); 1302 } 1303 1304 if (height < minHeight) { 1305 height = minHeight; 1306 width = getScalar(height * ratio); 1307 } 1308 1309 } else { 1310 width = Math.max(minWidth, Math.min(width, maxWidth)); 1311 1312 if (current.autoHeight && current.type !== 'iframe') { 1313 inner.width( width ); 1314 1315 height = inner.height(); 1316 } 1317 1318 height = Math.max(minHeight, Math.min(height, maxHeight)); 1319 } 1320 1321 // Try to fit inside viewport (including the title) 1322 if (current.fitToView) { 1323 inner.width( width ).height( height ); 1324 1325 wrap.width( width + wPadding ); 1326 1327 // Real wrap dimensions 1328 width_ = wrap.width(); 1329 height_ = wrap.height(); 1330 1331 if (current.aspectRatio) { 1332 while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { 1333 if (steps++ > 19) { 1334 break; 1335 } 1336 1337 height = Math.max(minHeight, Math.min(maxHeight, height - 10)); 1338 width = getScalar(height * ratio); 1339 1340 if (width < minWidth) { 1341 width = minWidth; 1342 height = getScalar(width / ratio); 1343 } 1344 1345 if (width > maxWidth) { 1346 width = maxWidth; 1347 height = getScalar(width / ratio); 1348 } 1349 1350 inner.width( width ).height( height ); 1351 1352 wrap.width( width + wPadding ); 1353 1354 width_ = wrap.width(); 1355 height_ = wrap.height(); 1356 } 1357 1358 } else { 1359 width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); 1360 height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); 1361 } 1362 } 1363 1364 if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { 1365 width += scrollOut; 1366 } 1367 1368 inner.width( width ).height( height ); 1369 1370 wrap.width( width + wPadding ); 1371 1372 width_ = wrap.width(); 1373 height_ = wrap.height(); 1374 1375 canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; 1376 canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); 1377 1378 $.extend(current, { 1379 dim : { 1380 width : getValue( width_ ), 1381 height : getValue( height_ ) 1382 }, 1383 origWidth : origWidth, 1384 origHeight : origHeight, 1385 canShrink : canShrink, 1386 canExpand : canExpand, 1387 wPadding : wPadding, 1388 hPadding : hPadding, 1389 wrapSpace : height_ - skin.outerHeight(true), 1390 skinSpace : skin.height() - height 1391 }); 1392 1393 if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { 1394 inner.height('auto'); 1395 } 1396 }, 1397 1398 _getPosition: function (onlyAbsolute) { 1399 var current = F.current, 1400 viewport = F.getViewport(), 1401 margin = current.margin, 1402 width = F.wrap.width() + margin[1] + margin[3], 1403 height = F.wrap.height() + margin[0] + margin[2], 1404 rez = { 1405 position: 'absolute', 1406 top : margin[0], 1407 left : margin[3] 1408 }; 1409 1410 if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { 1411 rez.position = 'fixed'; 1412 1413 } else if (!current.locked) { 1414 rez.top += viewport.y; 1415 rez.left += viewport.x; 1416 } 1417 1418 rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); 1419 rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); 1420 1421 return rez; 1422 }, 1423 1424 _afterZoomIn: function () { 1425 var current = F.current; 1426 1427 if (!current) { 1428 return; 1429 } 1430 1431 F.isOpen = F.isOpened = true; 1432 1433 F.wrap.css('overflow', 'visible').addClass('fancybox-opened'); 1434 1435 F.update(); 1436 1437 // Assign a click event 1438 if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { 1439 F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { 1440 if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { 1441 e.preventDefault(); 1442 1443 F[ current.closeClick ? 'close' : 'next' ](); 1444 } 1445 }); 1446 } 1447 1448 // Create a close button 1449 if (current.closeBtn) { 1450 $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { 1451 e.preventDefault(); 1452 1453 F.close(); 1454 }); 1455 } 1456 1457 // Create navigation arrows 1458 if (current.arrows && F.group.length > 1) { 1459 if (current.loop || current.index > 0) { 1460 $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); 1461 } 1462 1463 if (current.loop || current.index < F.group.length - 1) { 1464 $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); 1465 } 1466 } 1467 1468 F.trigger('afterShow'); 1469 1470 // Stop the slideshow if this is the last item 1471 if (!current.loop && current.index === current.group.length - 1) { 1472 F.play( false ); 1473 1474 } else if (F.opts.autoPlay && !F.player.isActive) { 1475 F.opts.autoPlay = false; 1476 1477 F.play(); 1478 } 1479 }, 1480 1481 _afterZoomOut: function ( obj ) { 1482 obj = obj || F.current; 1483 1484 $('.fancybox-wrap').trigger('onReset').remove(); 1485 1486 $.extend(F, { 1487 group : {}, 1488 opts : {}, 1489 router : false, 1490 current : null, 1491 isActive : false, 1492 isOpened : false, 1493 isOpen : false, 1494 isClosing : false, 1495 wrap : null, 1496 skin : null, 1497 outer : null, 1498 inner : null 1499 }); 1500 1501 F.trigger('afterClose', obj); 1502 } 1503 }); 1504 1505 /* 1506 * Default transitions 1507 */ 1508 1509 F.transitions = { 1510 getOrigPosition: function () { 1511 var current = F.current, 1512 element = current.element, 1513 orig = current.orig, 1514 pos = {}, 1515 width = 50, 1516 height = 50, 1517 hPadding = current.hPadding, 1518 wPadding = current.wPadding, 1519 viewport = F.getViewport(); 1520 1521 if (!orig && current.isDom && element.is(':visible')) { 1522 orig = element.find('img:first'); 1523 1524 if (!orig.length) { 1525 orig = element; 1526 } 1527 } 1528 1529 if (isQuery(orig)) { 1530 pos = orig.offset(); 1531 1532 if (orig.is('img')) { 1533 width = orig.outerWidth(); 1534 height = orig.outerHeight(); 1535 } 1536 1537 } else { 1538 pos.top = viewport.y + (viewport.h - height) * current.topRatio; 1539 pos.left = viewport.x + (viewport.w - width) * current.leftRatio; 1540 } 1541 1542 if (F.wrap.css('position') === 'fixed' || current.locked) { 1543 pos.top -= viewport.y; 1544 pos.left -= viewport.x; 1545 } 1546 1547 pos = { 1548 top : getValue(pos.top - hPadding * current.topRatio), 1549 left : getValue(pos.left - wPadding * current.leftRatio), 1550 width : getValue(width + wPadding), 1551 height : getValue(height + hPadding) 1552 }; 1553 1554 return pos; 1555 }, 1556 1557 step: function (now, fx) { 1558 var ratio, 1559 padding, 1560 value, 1561 prop = fx.prop, 1562 current = F.current, 1563 wrapSpace = current.wrapSpace, 1564 skinSpace = current.skinSpace; 1565 1566 if (prop === 'width' || prop === 'height') { 1567 ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); 1568 1569 if (F.isClosing) { 1570 ratio = 1 - ratio; 1571 } 1572 1573 padding = prop === 'width' ? current.wPadding : current.hPadding; 1574 value = now - padding; 1575 1576 F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); 1577 F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); 1578 } 1579 }, 1580 1581 zoomIn: function () { 1582 var current = F.current, 1583 startPos = current.pos, 1584 effect = current.openEffect, 1585 elastic = effect === 'elastic', 1586 endPos = $.extend({opacity : 1}, startPos); 1587 1588 // Remove "position" property that breaks older IE 1589 delete endPos.position; 1590 1591 if (elastic) { 1592 startPos = this.getOrigPosition(); 1593 1594 if (current.openOpacity) { 1595 startPos.opacity = 0.1; 1596 } 1597 1598 } else if (effect === 'fade') { 1599 startPos.opacity = 0.1; 1600 } 1601 1602 F.wrap.css(startPos).animate(endPos, { 1603 duration : effect === 'none' ? 0 : current.openSpeed, 1604 easing : current.openEasing, 1605 step : elastic ? this.step : null, 1606 complete : F._afterZoomIn 1607 }); 1608 }, 1609 1610 zoomOut: function () { 1611 var current = F.current, 1612 effect = current.closeEffect, 1613 elastic = effect === 'elastic', 1614 endPos = {opacity : 0.1}; 1615 1616 if (elastic) { 1617 endPos = this.getOrigPosition(); 1618 1619 if (current.closeOpacity) { 1620 endPos.opacity = 0.1; 1621 } 1622 } 1623 1624 F.wrap.animate(endPos, { 1625 duration : effect === 'none' ? 0 : current.closeSpeed, 1626 easing : current.closeEasing, 1627 step : elastic ? this.step : null, 1628 complete : F._afterZoomOut 1629 }); 1630 }, 1631 1632 changeIn: function () { 1633 var current = F.current, 1634 effect = current.nextEffect, 1635 startPos = current.pos, 1636 endPos = { opacity : 1 }, 1637 direction = F.direction, 1638 distance = 200, 1639 field; 1640 1641 startPos.opacity = 0.1; 1642 1643 if (effect === 'elastic') { 1644 field = direction === 'down' || direction === 'up' ? 'top' : 'left'; 1645 1646 if (direction === 'down' || direction === 'right') { 1647 startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); 1648 endPos[ field ] = '+=' + distance + 'px'; 1649 1650 } else { 1651 startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); 1652 endPos[ field ] = '-=' + distance + 'px'; 1653 } 1654 } 1655 1656 // Workaround for http://bugs.jquery.com/ticket/12273 1657 if (effect === 'none') { 1658 F._afterZoomIn(); 1659 1660 } else { 1661 F.wrap.css(startPos).animate(endPos, { 1662 duration : current.nextSpeed, 1663 easing : current.nextEasing, 1664 complete : F._afterZoomIn 1665 }); 1666 } 1667 }, 1668 1669 changeOut: function () { 1670 var previous = F.previous, 1671 effect = previous.prevEffect, 1672 endPos = { opacity : 0.1 }, 1673 direction = F.direction, 1674 distance = 200; 1675 1676 if (effect === 'elastic') { 1677 endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; 1678 } 1679 1680 previous.wrap.animate(endPos, { 1681 duration : effect === 'none' ? 0 : previous.prevSpeed, 1682 easing : previous.prevEasing, 1683 complete : function () { 1684 $(this).trigger('onReset').remove(); 1685 } 1686 }); 1687 } 1688 }; 1689 1690 /* 1691 * Overlay helper 1692 */ 1693 1694 F.helpers.overlay = { 1695 defaults : { 1696 closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay 1697 speedOut : 200, // duration of fadeOut animation 1698 showEarly : true, // indicates if should be opened immediately or wait until the content is ready 1699 css : {}, // custom CSS properties 1700 locked : !isTouch, // if true, the content will be locked into overlay 1701 fixed : true // if false, the overlay CSS position property will not be set to "fixed" 1702 }, 1703 1704 overlay : null, // current handle 1705 fixed : false, // indicates if the overlay has position "fixed" 1706 el : $('html'), // element that contains "the lock" 1707 1708 // Public methods 1709 create : function(opts) { 1710 opts = $.extend({}, this.defaults, opts); 1711 1712 if (this.overlay) { 1713 this.close(); 1714 } 1715 1716 this.overlay = $('<div class="fancybox-overlay"></div>').appendTo( F.coming ? F.coming.parent : opts.parent ); 1717 this.fixed = false; 1718 1719 if (opts.fixed && F.defaults.fixed) { 1720 this.overlay.addClass('fancybox-overlay-fixed'); 1721 1722 this.fixed = true; 1723 } 1724 }, 1725 1726 open : function(opts) { 1727 var that = this; 1728 1729 opts = $.extend({}, this.defaults, opts); 1730 1731 if (this.overlay) { 1732 this.overlay.unbind('.overlay').width('auto').height('auto'); 1733 1734 } else { 1735 this.create(opts); 1736 } 1737 1738 if (!this.fixed) { 1739 W.bind('resize.overlay', $.proxy( this.update, this) ); 1740 1741 this.update(); 1742 } 1743 1744 if (opts.closeClick) { 1745 this.overlay.bind('click.overlay', function(e) { 1746 if ($(e.target).hasClass('fancybox-overlay')) { 1747 if (F.isActive) { 1748 F.close(); 1749 } else { 1750 that.close(); 1751 } 1752 1753 return false; 1754 } 1755 }); 1756 } 1757 1758 this.overlay.css( opts.css ).show(); 1759 }, 1760 1761 close : function() { 1762 var scrollV, scrollH; 1763 1764 W.unbind('resize.overlay'); 1765 1766 if (this.el.hasClass('fancybox-lock')) { 1767 $('.fancybox-margin').removeClass('fancybox-margin'); 1768 1769 scrollV = W.scrollTop(); 1770 scrollH = W.scrollLeft(); 1771 1772 this.el.removeClass('fancybox-lock'); 1773 1774 W.scrollTop( scrollV ).scrollLeft( scrollH ); 1775 } 1776 1777 $('.fancybox-overlay').remove().hide(); 1778 1779 $.extend(this, { 1780 overlay : null, 1781 fixed : false 1782 }); 1783 }, 1784 1785 // Private, callbacks 1786 1787 update : function () { 1788 var width = '100%', offsetWidth; 1789 1790 // Reset width/height so it will not mess 1791 this.overlay.width(width).height('100%'); 1792 1793 // jQuery does not return reliable result for IE 1794 if (IE) { 1795 offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); 1796 1797 if (D.width() > offsetWidth) { 1798 width = D.width(); 1799 } 1800 1801 } else if (D.width() > W.width()) { 1802 width = D.width(); 1803 } 1804 1805 this.overlay.width(width).height(D.height()); 1806 }, 1807 1808 // This is where we can manipulate DOM, because later it would cause iframes to reload 1809 onReady : function (opts, obj) { 1810 var overlay = this.overlay; 1811 1812 $('.fancybox-overlay').stop(true, true); 1813 1814 if (!overlay) { 1815 this.create(opts); 1816 } 1817 1818 if (opts.locked && this.fixed && obj.fixed) { 1819 if (!overlay) { 1820 this.margin = D.height() > W.height() ? $('html').css('margin-right').replace("px", "") : false; 1821 } 1822 1823 obj.locked = this.overlay.append( obj.wrap ); 1824 obj.fixed = false; 1825 } 1826 1827 if (opts.showEarly === true) { 1828 this.beforeShow.apply(this, arguments); 1829 } 1830 }, 1831 1832 beforeShow : function(opts, obj) { 1833 var scrollV, scrollH; 1834 1835 if (obj.locked) { 1836 if (this.margin !== false) { 1837 $('*').filter(function(){ 1838 return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") ); 1839 }).addClass('fancybox-margin'); 1840 1841 this.el.addClass('fancybox-margin'); 1842 } 1843 1844 scrollV = W.scrollTop(); 1845 scrollH = W.scrollLeft(); 1846 1847 this.el.addClass('fancybox-lock'); 1848 1849 W.scrollTop( scrollV ).scrollLeft( scrollH ); 1850 } 1851 1852 this.open(opts); 1853 }, 1854 1855 onUpdate : function() { 1856 if (!this.fixed) { 1857 this.update(); 1858 } 1859 }, 1860 1861 afterClose: function (opts) { 1862 // Remove overlay if exists and fancyBox is not opening 1863 // (e.g., it is not being open using afterClose callback) 1864 //if (this.overlay && !F.isActive) { 1865 if (this.overlay && !F.coming) { 1866 this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); 1867 } 1868 } 1869 }; 1870 1871 /* 1872 * Title helper 1873 */ 1874 1875 F.helpers.title = { 1876 defaults : { 1877 type : 'float', // 'float', 'inside', 'outside' or 'over', 1878 position : 'bottom' // 'top' or 'bottom' 1879 }, 1880 1881 beforeShow: function (opts) { 1882 var current = F.current, 1883 text = current.title, 1884 type = opts.type, 1885 title, 1886 target; 1887 1888 if ($.isFunction(text)) { 1889 text = text.call(current.element, current); 1890 } 1891 1892 if (!isString(text) || $.trim(text) === '') { 1893 return; 1894 } 1895 1896 title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">
vendor: 3,289 bytes, lines 1896-2024
1896' + text + '</div>'); 1897 1898 switch (type) { 1899 case 'inside': 1900 target = F.skin; 1901 break; 1902 1903 case 'outside': 1904 target = F.wrap; 1905 break; 1906 1907 case 'over': 1908 target = F.inner; 1909 break; 1910 1911 default: // 'float' 1912 target = F.skin; 1913 1914 title.appendTo('body'); 1915 1916 if (IE) { 1917 title.width( title.width() ); 1918 } 1919 1920 title.wrapInner('<span class="child"></span>'); 1921 1922 //Increase bottom margin so this title will also fit into viewport 1923 F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); 1924 break; 1925 } 1926 1927 title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); 1928 } 1929 }; 1930 1931 // jQuery plugin initialization 1932 $.fn.fancybox = function (options) { 1933 var index, 1934 that = $(this), 1935 selector = this.selector || '', 1936 run = function(e) { 1937 var what = $(this).blur(), idx = index, relType, relVal; 1938 1939 if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { 1940 relType = options.groupAttr || 'data-fancybox-group'; 1941 relVal = what.attr(relType); 1942 1943 if (!relVal) { 1944 relType = 'rel'; 1945 relVal = what.get(0)[ relType ]; 1946 } 1947 1948 if (relVal && relVal !== '' && relVal !== 'nofollow') { 1949 what = selector.length ? $(selector) : that; 1950 what = what.filter('[' + relType + '="' + relVal + '"]'); 1951 idx = what.index(this); 1952 } 1953 1954 options.index = idx; 1955 1956 // Stop an event from bubbling if everything is fine 1957 if (F.open(what, options) !== false) { 1958 e.preventDefault(); 1959 } 1960 } 1961 }; 1962 1963 options = options || {}; 1964 index = options.index || 0; 1965 1966 if (!selector || options.live === false) { 1967 that.unbind('click.fb-start').bind('click.fb-start', run); 1968 1969 } else { 1970 D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); 1971 } 1972 1973 this.filter('[data-fancybox-start=1]').trigger('click'); 1974 1975 return this; 1976 }; 1977 1978 // Tests that need a body at doc ready 1979 D.ready(function() { 1980 var w1, w2; 1981 1982 if ( $.scrollbarWidth === undefined ) { 1983 // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth 1984 $.scrollbarWidth = function() { 1985 var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'), 1986 child = parent.children(), 1987 width = child.innerWidth() - child.height( 99 ).innerWidth(); 1988 1989 parent.remove(); 1990 1991 return width; 1992 }; 1993 } 1994 1995 if ( $.support.fixedPosition === undefined ) { 1996 $.support.fixedPosition = (function() { 1997 var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'), 1998 fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); 1999 2000 elem.remove(); 2001 2002 return fixed; 2003 }()); 2004 } 2005 2006 $.extend(F.defaults, { 2007 scrollbarWidth : $.scrollbarWidth(), 2008 fixed : $.support.fixedPosition, 2009 parent : $('body') 2010 }); 2011 2012 //Get real width of page scroll-bar 2013 w1 = $(window).width(); 2014 2015 H.addClass('fancybox-lock-test'); 2016 2017 w2 = $(window).width(); 2018 2019 H.removeClass('fancybox-lock-test'); 2020 2021 $("<style type='text/css'>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head"); 2022 }); 2023 2024}(window, document, jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.