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