1/*! 2 * fancyBox - jQuery Plugin 3 * version: 2.0.3 (29/11/2011) 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 2011 Janis Skarnelis - [email protected] 10 * 11 */ 12(function (window, document, $) { 13 var W = $(window), 14 D = $(document), 15 F = $.fancybox = function () { 16 F.open.apply(this, arguments); 17 }, 18 didResize = false, 19 resizeTimer = null; 20 21 $.extend(F, { 22 // The current version of fancyBox 23 version: '2.0.3', 24 25 defaults: { 26 padding: 15, 27 margin: 20, 28 29 width: 800, 30 height: 600, 31 minWidth: 200, 32 minHeight: 200, 33 maxWidth: 9999, 34 maxHeight: 9999, 35 36 autoSize: true, 37 fitToView: true, 38 aspectRatio: false, 39 topRatio: 0.5, 40 41 fixed: !$.browser.msie || $.browser.version > 6, 42 scrolling: 'auto', // 'auto', 'yes' or 'no' 43 wrapCSS: 'fancybox-default', 44 45 arrows: true, 46 closeBtn: true, 47 closeClick: false, 48 nextClick: false, 49 mouseWheel: true, 50 autoPlay: false, 51 playSpeed: 3000, 52 53 modal: false, 54 loop: true, 55 ajax: {}, 56 keys: { 57 next: [13, 32, 34, 39, 40], // enter, space, page down, right arrow, down arrow 58 prev: [8, 33, 37, 38], // backspace, page up, left arrow, up arrow 59 close: [27] // escape key 60 }, 61 62 // Override some properties 63 index: 0, 64 type: null, 65 href: null, 66 content: null, 67 title: null, 68 69 // HTML templates 70 tpl: { 71 wrap: '<div class="fancybox-wrap"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div>', 72 image: '<img class="fancybox-image" src="{href}" alt="" />', 73 iframe: '<iframe class="fancybox-iframe" name="fancybox-frame{rnd}" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="{scrolling}" src="{href}"></iframe>', 74 swf: '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="wmode" value="transparent" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="{href}" /><embed src="{href}" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="100%" height="100%" wmode="transparent"></embed></object>', 75 error: '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>', 76 closeBtn: '<div title="Close" class="fancybox-item fancybox-close"></div>', 77 next: '<a title="Next" class="fancybox-item fancybox-next"><span></span></a>', 78 prev: '<a title="Previous" class="fancybox-item fancybox-prev"><span></span></a>' 79 }, 80 81 // Properties for each animation type 82 // Opening fancyBox 83 openEffect: 'elastic', // 'elastic', 'fade' or 'none' 84 openSpeed: 500, 85 openEasing: 'swing', 86 openOpacity: true, 87 openMethod: 'zoomIn', 88 89 // Closing fancyBox 90 closeEffect: 'fade', // 'elastic', 'fade' or 'none' 91 closeSpeed: 500, 92 closeEasing: 'swing', 93 closeOpacity: true, 94 closeMethod: 'zoomOut', 95 96 // Changing next gallery item 97 nextEffect: 'elastic', // 'elastic', 'fade' or 'none' 98 nextSpeed: 300, 99 nextEasing: 'swing', 100 nextMethod: 'changeIn', 101 102 // Changing previous gallery item 103 prevEffect: 'elastic', // 'elastic', 'fade' or 'none' 104 prevSpeed: 300, 105 prevEasing: 'swing', 106 prevMethod: 'changeOut', 107 108 // Enabled helpers 109 helpers: { 110 overlay: { 111 speedIn: 0, 112 speedOut: 0, 113 opacity: 0.85, 114 css: { 115 cursor: 'pointer', 116 'background-color': 'rgba(0, 0, 0, 0.85)' //Browsers who don`t support rgba will fall back to default color value defined at CSS file 117 }, 118 closeClick: true 119 }, 120 title: { 121 type: 'float' // 'float', 'inside', 'outside' or 'over' 122 } 123 }, 124 125 // Callbacks 126 onCancel: $.noop, // If canceling 127 beforeLoad: $.noop, // Before loading 128 afterLoad: $.noop, // After loading 129 beforeShow: $.noop, // Before changing in current item 130 afterShow: $.noop, // After opening 131 beforeClose: $.noop, // Before closing 132 afterClose: $.noop // After closing 133 }, 134 135 //Current state 136 group: {}, // Selected group 137 opts: {}, // Group options 138 coming: null, // Element being loaded 139 current: null, // Currently loaded element 140 isOpen: false, // Is currently open 141 isOpened: false, // Have been fully opened at least once 142 wrap: null, 143 outer: null, 144 inner: null, 145 146 player: { 147 timer: null, 148 isActive: false 149 }, 150 151 // Loaders 152 ajaxLoad: null, 153 imgPreload: null, 154 155 // Some collections 156 transitions: {}, 157 helpers: {}, 158 159 /* 160 * Static methods 161 */ 162 163 open: function (group, opts) { 164 // Normalize group 165 if (!$.isArray(group)) { 166 group = [group]; 167 } 168 169 if (!group.length) { 170 return; 171 } 172 173 //Kill existing instances 174 F.close(true); 175 176 //extend the defaults 177 F.opts = $.extend(true, {}, F.defaults, opts); 178 F.group = group; 179 180 F._start(F.opts.index || 0); 181 }, 182 183 cancel: function () { 184 if (F.coming && false === F.trigger('onCancel')) { 185 return; 186 } 187 188 F.coming = null; 189 190 F.hideLoading(); 191 192 if (F.ajaxLoad) { 193 F.ajaxLoad.abort(); 194 } 195 196 F.ajaxLoad = null; 197 198 if (F.imgPreload) { 199 F.imgPreload.onload = F.imgPreload.onabort = F.imgPreload.onerror = null; 200 } 201 }, 202 203 close: function (a) { 204 F.cancel(); 205 206 if (!F.current || false === F.trigger('beforeClose')) { 207 return; 208 } 209 210 F.unbindEvents(); 211 212 //If forced or is still opening then remove immediately 213 if (!F.isOpen || (a && a[0] === true)) { 214 $(".fancybox-wrap").stop().trigger('onReset').remove(); 215 216 F._afterZoomOut(); 217 218 } else { 219 F.isOpen = F.isOpened = false; 220 221 $(".fancybox-item").remove(); 222 223 F.wrap.stop(true).removeClass('fancybox-opened'); 224 F.inner.css('overflow', 'hidden'); 225 226 F.transitions[F.current.closeMethod](); 227 } 228 }, 229 230 play: function (a) { 231 var clear = function () { 232 clearTimeout(F.player.timer); 233 }, 234 set = function () { 235 clear(); 236 237 if (F.current && F.player.isActive) { 238 F.player.timer = setTimeout(F.next, F.current.playSpeed); 239 } 240 }, 241 stop = function () { 242 clear(); 243 244 $('body').unbind('.player'); 245 246 F.player.isActive = false; 247 248 F.trigger('onPlayEnd'); 249 }, 250 start = function () { 251 if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { 252 F.player.isActive = true; 253 254 set(); 255 256 $('body').bind({ 257 'onCancel.player afterShow.player onUpdate.player': set, 258 'beforeClose.player': stop, 259 'beforeLoad.player': clear 260 }); 261 262 F.trigger('onPlayStart'); 263 } 264 }; 265 266 if (F.player.isActive || (a && a[0] === false)) { 267 stop(); 268 } else { 269 start(); 270 } 271 }, 272 273 next: function () { 274 if (F.current) { 275 F.jumpto(F.current.index + 1); 276 } 277 }, 278 279 prev: function () { 280 if (F.current) { 281 F.jumpto(F.current.index - 1); 282 } 283 }, 284 285 jumpto: function (index) { 286 if (!F.current) { 287 return; 288 } 289 290 index = parseInt(index, 10); 291 292 if (F.group.length > 1 && F.current.loop) { 293 if (index >= F.group.length) { 294 index = 0; 295 296 } else if (index < 0) { 297 index = F.group.length - 1; 298 } 299 } 300 301 if (typeof F.group[index] !== 'undefined') { 302 F.cancel(); 303 304 F._start(index); 305 } 306 }, 307 308 reposition: function (a) { 309 if (F.isOpen) { 310 F.wrap.css(F._getPosition(a)); 311 } 312 }, 313 314 update: function () { 315 if (F.isOpen) { 316 // It's a very bad idea to attach handlers to the window scroll event, run this code after a delay 317 if (!didResize) { 318 resizeTimer = setInterval(function () { 319 if (didResize) { 320 didResize = false; 321 322 clearTimeout(resizeTimer); 323 324 if (F.current) { 325 if (F.current.autoSize) { 326 F.inner.height('auto'); 327 F.current.height = F.inner.height(); 328 } 329 330 F._setDimension(); 331 332 if (F.current.canGrow) { 333 F.inner.height('auto'); 334 } 335 336 F.reposition(); 337 338 F.trigger('onUpdate'); 339 } 340 } 341 }, 100); 342 } 343 344 didResize = true; 345 } 346 }, 347 348 toggle: function () { 349 if (F.isOpen) { 350 F.current.fitToView = !F.current.fitToView; 351 352 F.update(); 353 } 354 }, 355 356 hideLoading: function () { 357 $("#fancybox-loading").remove(); 358 }, 359 360 showLoading: function () { 361 F.hideLoading(); 362 363 $('<div id="fancybox-loading"></div>').click(F.cancel).appendTo('body'); 364 }, 365 366 getViewport: function () { 367 return { 368 x: W.scrollLeft(), 369 y: W.scrollTop(), 370 w: W.width(), 371 h: W.height() 372 }; 373 }, 374 375 // Unbind the keyboard / clicking actions 376 unbindEvents: function () { 377 if (F.wrap) { 378 F.wrap.unbind('.fb'); 379 } 380 381 D.unbind('.fb'); 382 W.unbind('.fb'); 383 }, 384 385 bindEvents: function () { 386 var current = F.current, 387 keys = current.keys; 388 389 if (!current) { 390 return; 391 } 392 393 W.bind('resize.fb, orientationchange.fb', F.update); 394 395 if (keys) { 396 D.bind('keydown.fb', function (e) { 397 // Ignore key events within form elements 398 if ($.inArray(e.target.tagName.toLowerCase(), ['input', 'textarea', 'select', 'button']) > -1) { 399 return; 400 } 401 402 if ($.inArray(e.keyCode, keys.close) > -1) { 403 F.close(); 404 e.preventDefault(); 405 406 } else if ($.inArray(e.keyCode, keys.next) > -1) { 407 F.next(); 408 e.preventDefault(); 409 410 } else if ($.inArray(e.keyCode, keys.prev) > -1) { 411 F.prev(); 412 e.preventDefault(); 413 } 414 }); 415 } 416 417 if ($.fn.mousewheel && current.mouseWheel && F.group.length > 1) { 418 F.wrap.bind('mousewheel.fb', function (e, delta) { 419 if ($(e.target).get(0).clientHeight === 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) { 420 e.preventDefault(); 421 422 F[delta > 0 ? 'prev' : 'next'](); 423 } 424 }); 425 } 426 }, 427 428 trigger: function (event) { 429 var ret, obj = $.inArray(event, ['onCancel', 'beforeLoad', 'afterLoad']) > -1 ? 'coming' : 'current'; 430 431 if (!F[obj]) { 432 return; 433 } 434 435 if ($.isFunction(F[obj][event])) { 436 ret = F[obj][event].apply(F[obj], Array.prototype.slice.call(arguments, 1)); 437 } 438 439 if (ret === false) { 440 return false; 441 } 442 443 if (F[obj].helpers) { 444 $.each(F[obj].helpers, function (helper, opts) { 445 if (opts && typeof F.helpers[helper] !== 'undefined' && $.isFunction(F.helpers[helper][event])) { 446 F.helpers[helper][event](opts); 447 } 448 }); 449 } 450 451 $.event.trigger(event + '.fb'); 452 }, 453 454 isImage: function (str) { 455 return str && str.match(/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i); 456 }, 457 458 isSWF: function (str) { 459 return str && str.match(/\.(swf)(.*)?$/i); 460 }, 461 462 _start: function (index) { 463 var element = F.group[index] || null, 464 isDom, 465 href, 466 type, 467 rez, 468 coming = $.extend(true, {}, F.opts, ($.isPlainObject(element) ? element : {}), { 469 index: index, 470 element: element 471 }); 472 473 // Convert margin property to array - top, right, bottom, left 474 if (typeof coming.margin === 'number') { 475 coming.margin = [coming.margin, coming.margin, coming.margin, coming.margin]; 476 } 477 478 // 'modal' propery is just a shortcut 479 if (coming.modal) { 480 $.extend(true, coming, { 481 closeBtn: false, 482 closeClick: false, 483 nextClick: false,
484 arrows: false, 485 mouseWheel: false, 486 keys: null, 487 helpers: { 488 overlay: { 489 css: { 490 cursor: 'auto' 491 }, 492 closeClick: false 493 } 494 } 495 }); 496 } 497 498 //Give a chance for callback or helpers to update coming item (type, title, etc) 499 F.coming = coming; 500 501 if (false === F.trigger('beforeLoad')) { 502 F.coming = null; 503 return; 504 } 505 506 if (typeof element === 'object' && (element.nodeType || element instanceof $)) { 507 isDom = true; 508 coming.href = $(element).attr('href') || coming.href; 509 coming.title = $(element).attr('title') || coming.title; 510 511 if ($.metadata) { 512 $.extend(coming, $(element).metadata()); 513 } 514 } 515 516 type = coming.type; 517 href = coming.href; 518 519 ///Check if content type is set, if not, try to get 520 if (!type) { 521 if (isDom) { 522 rez = $(element).data('fancybox-type'); 523 524 if (!rez && element.className) { 525 rez = element.className.match(/fancybox\.(\w+)/); 526 rez = rez ? rez[1] : false; 527 } 528 } 529 530 if (rez) { 531 type = rez; 532 533 } else if (href) { 534 if (F.isImage(href)) { 535 type = 'image'; 536 537 } else if (F.isSWF(href)) { 538 type = 'swf'; 539 540 } else if (href.match(/^#/)) { 541 type = 'inline'; 542 } 543 } 544 545 // ...if not - display element itself 546 if (!type) { 547 type = isDom ? 'inline' : 'html'; 548 } 549 550 coming.type = type; 551 } 552 553 // Check before try to load; 'inline' and 'html' types need content, others - href 554 if (type === 'inline' || type === 'html') { 555 if (!coming.content) { 556 coming.content = type === 'inline' && href ? $(href) : element; 557 } 558 559 if (!coming.content.length) { 560 type = null; 561 } 562 563 } else { 564 coming.href = href || element; 565 566 if (!coming.href) { 567 type = null; 568 } 569 } 570 571 /* 572 Add reference to the group, so it`s possible to access from callbacks, example: 573 574 afterLoad : function() { 575 this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); 576 } 577 578 */ 579 580 coming.group = F.group; 581 582 if (type === 'image') { 583 F._loadImage(); 584 585 } else if (type === 'ajax') { 586 F._loadAjax(); 587 588 } else if (type) { 589 F._afterLoad(); 590 591 } else { 592 F._error(); 593 } 594 }, 595 596 _error: function () { 597 F.coming.type = 'html'; 598 F.coming.minHeight = 0; 599 F.coming.autoSize = true; 600 F.coming.content = F.coming.tpl.error; 601 602 F._afterLoad(); 603 }, 604 605 _loadImage: function () { 606 // Reset preload image so it is later possible to check "complete" property 607 F.imgPreload = new Image(); 608 609 F.imgPreload.onload = function () { 610 this.onload = this.onerror = null; 611 612 F.coming.width = this.width; 613 F.coming.height = this.height; 614 615 F._afterLoad(); 616 }; 617 618 F.imgPreload.onerror = function () { 619 this.onload = this.onerror = null; 620 621 F._error(); 622 }; 623 624 F.imgPreload.src = F.coming.href; 625 626 if (!F.imgPreload.complete) { 627 F.showLoading(); 628 } 629 }, 630 631 _loadAjax: function () { 632 F.showLoading(); 633 634 F.ajaxLoad = $.ajax($.extend({}, F.coming.ajax, { 635 url: F.coming.href, 636 error: function (jqXHR, textStatus, errorThrown) { 637 if (textStatus !== 'abort') { 638 F.coming.content = errorThrown; 639 640 F._error(); 641 642 } else { 643 F.hideLoading(); 644 } 645 }, 646 success: function (data, textStatus, jqXHR) { 647 if (textStatus === 'success') { 648 F.coming.content = data; 649 650 F._afterLoad(); 651 } 652 } 653 })); 654 }, 655 656 _afterLoad: function () { 657 F.hideLoading(); 658 659 if (!F.coming || false === F.trigger('afterLoad', F.current)) { 660 F.coming = false; 661 662 return; 663 } 664 665 if (F.isOpened) { 666 $(".fancybox-item").remove(); 667 668 F.wrap.stop(true).removeClass('fancybox-opened'); 669 F.inner.css('overflow', 'hidden'); 670 671 F.transitions[F.current.prevMethod](); 672 673 } else { 674 $(".fancybox-wrap").stop().trigger('onReset').remove(); 675 676 F.trigger('afterClose'); 677 } 678 679 F.unbindEvents(); 680 681 F.isOpen = false; 682 F.current = F.coming; 683 F.coming = false; 684 685 //Build the neccessary markup 686 F.wrap = $(F.current.tpl.wrap).addClass('fancybox-tmp ' + F.current.wrapCSS).appendTo('body'); 687 F.outer = $('.fancybox-outer', F.wrap).css('padding', F.current.padding + 'px'); 688 F.inner = $('.fancybox-inner', F.wrap); 689 690 F._setContent(); 691 692 //Give a chance for helpers or callbacks to update elements 693 F.trigger('beforeShow'); 694 695 //Set initial dimensions and hide
696 F._setDimension(); 697 698 F.wrap.hide().removeClass('fancybox-tmp'); 699 700 F.bindEvents(); 701 702 F.transitions[ F.isOpened ? F.current.nextMethod : F.current.openMethod ](); 703 }, 704 705 _setContent: function () { 706 var content, loadingBay, current = F.current, 707 type = current.type; 708 709 switch (type) { 710 case 'inline': 711 case 'ajax': 712 case 'html': 713 if (type === 'inline') { 714 content = current.content.show().detach(); 715 716 if (content.parent().hasClass('fancybox-inner')) { 717 content.parents('.fancybox-wrap').trigger('onReset').remove(); 718 } 719 720 $(F.wrap).bind('onReset', function () { 721 content.appendTo('body').hide(); 722 }); 723 724 } else { 725 content = current.content; 726 } 727 728 if (current.autoSize) { 729 loadingBay = $('<div class="fancybox-tmp"></div>').appendTo($("body")).append(content); 730 731 current.width = loadingBay.outerWidth(); 732 current.height = loadingBay.outerHeight(true); 733 734 content = loadingBay.contents().detach(); 735 736 loadingBay.remove(); 737 } 738 739 break; 740 741 case 'image': 742 content = current.tpl.image.replace('{href}', current.href); 743 744 current.aspectRatio = true; 745 break; 746 747 case 'swf': 748 content = current.tpl.swf.replace(/\{width\}/g, current.width).replace(/\{height\}/g, current.height).replace(/\{href\}/g, current.href); 749 break; 750 751 case 'iframe': 752 content = current.tpl.iframe.replace('{href}', current.href).replace('{scrolling}', current.scrolling).replace('{rnd}', new Date().getTime()); 753 break; 754 } 755 756 if ($.inArray(type, ['image', 'swf', 'iframe']) > -1) { 757 current.autoSize = false; 758 current.scrolling = false; 759 } 760 761 F.inner.append(content); 762 }, 763 764 _setDimension: function () { 765 var current = F.current, 766 viewport = F.getViewport(), 767 margin = current.margin, 768 padding2 = current.padding * 2, 769 width = current.width + padding2, 770 height = current.height + padding2, 771 ratio = current.width / current.height, 772 773 maxWidth = current.maxWidth, 774 maxHeight = current.maxHeight, 775 minWidth = current.minWidth, 776 minHeight = current.minHeight, 777 height_, 778 space; 779 780 viewport.w -= (margin[1] + margin[3]); 781 viewport.h -= (margin[0] + margin[2]); 782 783 if (width.toString().indexOf('%') > -1) { 784 width = ((viewport.w * parseFloat(width)) / 100); 785 } 786 787 if (height.toString().indexOf('%') > -1) { 788 height = ((viewport.h * parseFloat(height)) / 100); 789 } 790 791 if (current.fitToView) { 792 maxWidth = Math.min(viewport.w, maxWidth); 793 maxHeight = Math.min(viewport.h, maxHeight); 794 } 795 796 maxWidth = Math.max(minWidth, maxWidth); 797 maxHeight = Math.max(minHeight, maxHeight); 798 799 if (current.aspectRatio) { 800 if (width > maxWidth) { 801 width = maxWidth; 802 height = ((width - padding2) / ratio) + padding2; 803 } 804 805 if (height > maxHeight) { 806 height = maxHeight; 807 width = ((height - padding2) * ratio) + padding2; 808 } 809 810 if (width < minWidth) { 811 width = minWidth; 812 height = ((width - padding2) / ratio) + padding2; 813 } 814 815 if (height < minHeight) { 816 height = minHeight; 817 width = ((height - padding2) * ratio) + padding2; 818 } 819 820 } else { 821 width = Math.max(minWidth, Math.min(width, maxWidth)); 822 height = Math.max(minHeight, Math.min(height, maxHeight)); 823 } 824 825 width = Math.round(width); 826 height = Math.round(height); 827 828 //Reset dimensions 829 $(F.wrap.add(F.outer).add(F.inner)).width('auto').height('auto'); 830 831 F.inner.width(width - padding2).height(height - padding2); 832 F.wrap.width(width); 833 834 height_ = F.wrap.height(); // Real wrap height 835 836 //Fit wrapper inside 837 if (width > maxWidth || height_ > maxHeight) { 838 while ((width > maxWidth || height_ > maxHeight) && width > minWidth && height_ > minHeight) { 839 height = height - 10; 840 841 if (current.aspectRatio) { 842 width = Math.round(((height - padding2) * ratio) + padding2); 843 844 if (width < minWidth) { 845 width = minWidth; 846 height = ((width - padding2) / ratio) + padding2; 847 } 848 849 } else { 850 width = width - 10; 851 } 852 853 F.inner.width(width - padding2).height(height - padding2); 854 F.wrap.width(width); 855 856 height_ = F.wrap.height(); 857 } 858 } 859 860 current.dim = { 861 width: width, 862 height: height_ 863 }; 864
865 current.canGrow = current.autoSize && height > minHeight && height < maxHeight; 866 current.canShrink = false; 867 current.canExpand = false; 868 869 if ((width - padding2) < current.width || (height - padding2) < current.height) { 870 current.canExpand = true; 871 872 } else if ((width > viewport.w || height_ > viewport.h) && width > minWidth && height > minHeight) { 873 current.canShrink = true; 874 } 875 876 space = height_ - padding2; 877 878 F.innerSpace = space - F.inner.height(); 879 F.outerSpace = space - F.outer.height(); 880 }, 881 882 _getPosition: function (a) { 883 var viewport = F.getViewport(), 884 margin = F.current.margin, 885 width = F.wrap.width() + margin[1] + margin[3], 886 height = F.wrap.height() + margin[0] + margin[2], 887 rez = { 888 position: 'absolute', 889 top: margin[0] + viewport.y, 890 left: margin[3] + viewport.x 891 }; 892 893 if (F.current.fixed && (!a || a[0] === false) && height <= viewport.h && width <= viewport.w) { 894 rez = { 895 position: 'fixed', 896 top: margin[0], 897 left: margin[3] 898 }; 899 } 900 901 rez.top = Math.ceil(Math.max(rez.top, rez.top + ((viewport.h - height) * F.current.topRatio))) + 'px';
902 rez.left = Math.ceil(Math.max(rez.left, rez.left + ((viewport.w - width) * 0.5))) + 'px'; 903 904 return rez; 905 }, 906 907 _afterZoomIn: function () { 908 var current = F.current; 909 910 F.isOpen = F.isOpened = true; 911 912 F.wrap.addClass('fancybox-opened').css('overflow', 'visible'); 913 914 F.update(); 915 916 F.inner.css('overflow', current.scrolling === 'auto' ? 'auto' : (current.scrolling === 'yes' ? 'scroll' : 'hidden')); 917 918 //Assign a click event 919 if (current.closeClick || current.nextClick) { 920 F.inner.bind('click.fb', current.nextClick ? F.next : F.close); 921 } 922 923 //Create a close button 924 if (current.closeBtn) { 925 $(F.current.tpl.closeBtn).appendTo(F.wrap).bind('click.fb', F.close); 926 } 927 928 //Create navigation arrows 929 if (current.arrows && F.group.length > 1) { 930 if (current.loop || current.index > 0) { 931 $(current.tpl.prev).appendTo(F.wrap).bind('click.fb', F.prev); 932 } 933 934 if (current.loop || current.index < F.group.length - 1) { 935 $(current.tpl.next).appendTo(F.wrap).bind('click.fb', F.next); 936 } 937 } 938 939 F.trigger('afterShow'); 940 941 if (F.opts.autoPlay && !F.player.isActive) { 942 F.opts.autoPlay = false; 943 944 F.play(); 945 } 946 }, 947 948 _afterZoomOut: function () { 949 F.trigger('afterClose'); 950 951 F.wrap.trigger('onReset').remove(); 952 953 $.extend(F, { 954 group: {}, 955 opts: {}, 956 current: null, 957 isOpened: false, 958 isOpen: false, 959 wrap: null, 960 outer: null, 961 inner: null 962 }); 963 } 964 }); 965 966 /* 967 * Default transitions 968 */ 969 970 F.transitions = { 971 getOrigPosition: function () { 972 var element = F.current.element, 973 pos = {}, 974 width = 50, 975 height = 50, 976 image, viewport; 977 978 if (element && element.nodeName && $(element).is(':visible')) { 979 image = $(element).find('img:first'); 980 981 if (image.length) { 982 pos = image.offset(); 983 width = image.outerWidth(); 984 height = image.outerHeight(); 985 986 } else { 987 pos = $(element).offset(); 988 } 989 990 } else { 991 viewport = F.getViewport(); 992 pos.top = viewport.y + (viewport.h - height) * 0.5; 993 pos.left = viewport.x + (viewport.w - width) * 0.5; 994 } 995 996 pos = { 997 top: Math.ceil(pos.top) + 'px', 998 left: Math.ceil(pos.left) + 'px', 999 width: Math.ceil(width) + 'px', 1000 height: Math.ceil(height) + 'px' 1001 }; 1002 1003 return pos; 1004 }, 1005 1006 step: function (now, fx) { 1007 var ratio, innerValue, outerValue; 1008 1009 if (fx.prop === 'width' || fx.prop === 'height') { 1010 innerValue = outerValue = Math.ceil(now - (F.current.padding * 2)); 1011 1012 if (fx.prop === 'height') { 1013 ratio = (now - fx.start) / (fx.end - fx.start); 1014 1015 if (fx.start > fx.end) { 1016 ratio = 1 - ratio; 1017 } 1018 1019 innerValue -= F.innerSpace * ratio; 1020 outerValue -= F.outerSpace * ratio; 1021 } 1022 1023 F.inner[fx.prop](innerValue); 1024 F.outer[fx.prop](outerValue); 1025 } 1026 }, 1027 1028 zoomIn: function () { 1029 var current = F.current, 1030 startPos, 1031 endPos, 1032 dim = current.dim; 1033 1034 if (current.openEffect === 'elastic') { 1035 endPos = $.extend({}, dim, F._getPosition(true)); 1036 1037 //Remove "position" property 1038 delete endPos.position; 1039 1040 startPos = this.getOrigPosition(); 1041 1042 if (current.openOpacity) { 1043 startPos.opacity = 0; 1044 endPos.opacity = 1; 1045 } 1046 1047 F.wrap.css(startPos).show().animate(endPos, { 1048 duration: current.openSpeed, 1049 easing: current.openEasing, 1050 step: this.step, 1051 complete: F._afterZoomIn 1052 }); 1053 1054 } else { 1055 F.wrap.css($.extend({}, dim, F._getPosition())); 1056 1057 if (current.openEffect === 'fade') { 1058 F.wrap.fadeIn(current.openSpeed, F._afterZoomIn); 1059 1060 } else { 1061 F.wrap.show(); 1062 F._afterZoomIn(); 1063 } 1064 } 1065 }, 1066 1067 zoomOut: function () { 1068 var current = F.current, 1069 endPos; 1070 1071 if (current.closeEffect === 'elastic') { 1072 if (F.wrap.css('position') === 'fixed') { 1073 F.wrap.css(F._getPosition(true)); 1074 } 1075 1076 endPos = this.getOrigPosition(); 1077 1078 if (current.closeOpacity) { 1079 endPos.opacity = 0; 1080 } 1081 1082 F.wrap.animate(endPos, { 1083 duration: current.closeSpeed, 1084 easing: current.closeEasing, 1085 step: this.step, 1086 complete: F._afterZoomOut 1087 }); 1088 1089 } else { 1090 F.wrap.fadeOut(current.closeEffect === 'fade' ? current.closeSpeed : 0, F._afterZoomOut); 1091 } 1092 }, 1093 1094 changeIn: function () { 1095 var current = F.current, 1096 startPos; 1097 1098 if (F.current.nextEffect === 'elastic') { 1099 startPos = F._getPosition(true); 1100 startPos.opacity = 0; 1101 startPos.top = (parseInt(startPos.top, 10) - 200) + 'px'; 1102 1103 F.wrap.css(startPos).show().animate({ 1104 opacity: 1, 1105 top: '+=200px' 1106 }, { 1107 duration: current.nextSpeed, 1108 complete: F._afterZoomIn 1109 }); 1110 1111 } else { 1112 F.wrap.css(F._getPosition()); 1113 1114 if (current.nextEffect === 'fade') { 1115 F.wrap.hide().fadeIn(current.nextSpeed, F._afterZoomIn); 1116 1117 } else { 1118 F.wrap.show(); 1119 F._afterZoomIn(); 1120 } 1121 } 1122 }, 1123 1124 changeOut: function () { 1125 function cleanUp() { 1126 $(this).trigger('onReset').remove(); 1127 } 1128 1129 F.wrap.removeClass('fancybox-opened'); 1130 1131 if (F.current.prevEffect === 'elastic') { 1132 F.wrap.animate({ 1133 'opacity': 0, 1134 top: '+=200px' 1135 }, { 1136 duration: F.current.prevSpeed, 1137 complete: cleanUp 1138 }); 1139 1140 } else { 1141 F.wrap.fadeOut(F.current.prevEffect === 'fade' ? F.current.prevSpeed : 0, cleanUp); 1142 } 1143 } 1144 }; 1145 1146 /* 1147 * Overlay helper 1148 */ 1149
1150 F.helpers.overlay = { 1151 overlay: null, 1152 1153 update: function () { 1154 var width, scrollWidth, offsetWidth; 1155 1156 //Reset width/height so it will not mess 1157 this.overlay.width(0).height(0); 1158 1159 if ($.browser.msie) { 1160 scrollWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); 1161 offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); 1162 1163 width = scrollWidth < offsetWidth ? W.width() : scrollWidth; 1164 1165 } else { 1166 width = D.width(); 1167 } 1168 1169 this.overlay.width(width).height(D.height()); 1170 }, 1171 1172 beforeShow: function (opts) { 1173 if (this.overlay) { 1174 return; 1175 } 1176 1177 this.overlay = $('<div id="fancybox-overlay"></div>').css(opts.css || { 1178 background: 'black' 1179 }).appendTo('body'); 1180 1181 this.update(); 1182 1183 if (opts.closeClick) { 1184 this.overlay.bind('click.fb', F.close); 1185 } 1186 1187 W.bind("resize.fb", $.proxy(this.update, this)); 1188 1189 this.overlay.fadeTo(opts.speedIn || "fast", opts.opacity || 1); 1190 }, 1191 1192 onUpdate: function () { 1193 //Update as content may change document dimensions 1194 this.update(); 1195 }, 1196 1197 afterClose: function (opts) { 1198 if (this.overlay) { 1199 this.overlay.fadeOut(opts.speedOut || "fast", function () { 1200 $(this).remove(); 1201 }); 1202 } 1203 1204 this.overlay = null; 1205 } 1206 }; 1207 1208 /* 1209 * Title helper 1210 */ 1211 1212 F.helpers.title = { 1213 beforeShow: function (opts) { 1214 var title, text = F.current.title; 1215 1216 if (text) { 1217 title = $('<div class="fancybox-title fancybox-title-' + opts.type + '-wrap">' + text + '</div>').appendTo('body'); 1218 1219 if (opts.type === 'float') { 1220 //This helps for some browsers 1221 title.width(title.width()); 1222 1223 title.wrapInner('<span class="child"></span>'); 1224 1225 //Increase bottom margin so this title will also fit into viewport 1226 F.current.margin[2] += Math.abs(parseInt(title.css('margin-bottom'), 10)); 1227 } 1228 1229 title.appendTo(opts.type === 'over' ? F.inner : (opts.type === 'outside' ? F.wrap : F.outer)); 1230 } 1231 } 1232 }; 1233 1234 // jQuery plugin initialization 1235 $.fn.fancybox = function (options) { 1236 var opts = options || {}, 1237 selector = this.selector || ''; 1238 1239 function run(e) { 1240 var group = [], relType = false, relVal = $(this).data('fancybox-group'); 1241 1242 e.preventDefault(); 1243 1244 // Check if element has 'data-fancybox-group' attribute, if not - use 'rel' 1245 if (typeof relVal !== 'undefined') { 1246 relType = relVal ? 'data-fancybox-group' : false; 1247 1248 } else if (this.rel && this.rel !== '' && this.rel !== 'nofollow') { 1249 relVal = this.rel; 1250 relType = 'rel'; 1251 } 1252 1253 if (relType) { 1254 group = selector.length ? $(selector).filter('[' + relType + '="' + relVal + '"]') : $('[' + relType + '="' + relVal + '"]'); 1255 } 1256 1257 if (group.length) { 1258 opts.index = group.index(this); 1259 1260 F.open(group.get(), opts); 1261 1262 } else { 1263 F.open(this, opts); 1264 } 1265 1266 return false; 1267 } 1268 1269 if (selector) { 1270 D.undelegate(selector, 'click.fb-start').delegate(selector, 'click.fb-start', run); 1271 1272 } else { 1273 $(this).unbind('click.fb-start').bind('click.fb-start', run); 1274 } 1275 1276 return this; 1277 }; 1278 1279}(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.