vendor: 12,370 bytes, lines 1-532
1/*! Magnific Popup - v0.8.3 - 2013-05-09 2* http://dimsemenov.com/plugins/magnific-popup/ 3* Copyright (c) 2013 Dmitry Semenov; */ 4;(function($) { 5 6/*>>core*/ 7/** 8 * 9 * Magnific Popup Core JS file 10 * 11 */ 12 13 14/** 15 * Private static constants 16 */ 17var CLOSE_EVENT = 'Close', 18 BEFORE_APPEND_EVENT = 'BeforeAppend', 19 MARKUP_PARSE_EVENT = 'MarkupParse', 20 OPEN_EVENT = 'Open', 21 CHANGE_EVENT = 'Change', 22 NS = 'mfp', 23 EVENT_NS = '.' + NS, 24 READY_CLASS = 'mfp-ready', 25 REMOVING_CLASS = 'mfp-removing', 26 PREVENT_CLOSE_CLASS = 'mfp-prevent-close'; 27 28 29/** 30 * Private vars 31 */ 32var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this' 33 MagnificPopup = function(){}, 34 _prevStatus, 35 _window = $(window), 36 _body, 37 _document, 38 _prevContentType, 39 _wrapClasses, 40 _currPopupType; 41 42 43/** 44 * Private functions 45 */ 46var _mfpOn = function(name, f) { 47 mfp.ev.on(NS + name + EVENT_NS, f); 48 }, 49 _getEl = function(className, appendTo, html, raw) { 50 var el = document.createElement('div'); 51 el.className = 'mfp-'+className; 52 if(html) { 53 el.innerHTML = html; 54 } 55 if(!raw) { 56 el = $(el); 57 if(appendTo) { 58 el.appendTo(appendTo); 59 } 60 } else if(appendTo) { 61 appendTo.appendChild(el); 62 } 63 return el; 64 }, 65 _mfpTrigger = function(e, data) { 66 mfp.ev.triggerHandler(NS + e, data); 67 68 if(mfp.st.callbacks) { 69 // converts "mfpEventName" to "eventName" callback and triggers it if it's present 70 e = e.charAt(0).toLowerCase() + e.slice(1); 71 if(mfp.st.callbacks[e]) { 72 mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]); 73 } 74 } 75 }, 76 _setFocus = function() { 77 (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); 78 }, 79 _getCloseBtn = function(type) { 80 if(type !== _currPopupType || !mfp.currTemplate.closeBtn) { 81 mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) ); 82 _currPopupType = type; 83 } 84 return mfp.currTemplate.closeBtn; 85 }; 86 87 88 89/** 90 * Public functions 91 */ 92MagnificPopup.prototype = { 93 94 constructor: MagnificPopup, 95 96 /** 97 * Initializes Magnific Popup plugin. 98 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed 99 */ 100 init: function() { 101 var appVersion = navigator.appVersion; 102 mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1; 103 mfp.isAndroid = (/android/gi).test(appVersion); 104 mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); 105 106 // We disable fixed positioned lightbox on devices that don't handle it nicely. 107 // If you know a better way of detecting this - let me know. 108 mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); 109 _body = $(document.body); 110 _document = $(document); 111 112 mfp.popupsCache = {}; 113 }, 114 115 /** 116 * Opens popup 117 * @param data [description] 118 */ 119 open: function(data) { 120 121 if(mfp.isOpen) return; 122 123 var i; 124 125 mfp.types = []; 126 _wrapClasses = ''; 127 128 mfp.ev = data.el || _document; 129 130 if(data.isObj) { 131 mfp.index = data.index || 0; 132 } else { 133 mfp.index = 0; 134 var items = data.items, 135 item; 136 for(i = 0; i < items.length; i++) { 137 item = items[i]; 138 if(item.parsed) { 139 item = item.el[0]; 140 } 141 if(item === data.el[0]) { 142 mfp.index = i; 143 break; 144 } 145 } 146 } 147 148 149 if(data.key) { 150 if(!mfp.popupsCache[data.key]) { 151 mfp.popupsCache[data.key] = {}; 152 } 153 mfp.currTemplate = mfp.popupsCache[data.key]; 154 } else { 155 mfp.currTemplate = {}; 156 } 157 158 159 160 mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 161 mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; 162 163 mfp.items = data.items.length ? data.items : [data.items]; 164 165 // Building markup 166 // main containers are created only once 167 if(!mfp.bgOverlay) { 168 169 // Dark overlay 170 mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { 171 mfp.close(); 172 }); 173 174 mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) { 175 176 var target = e.target; 177 if($(target).hasClass(PREVENT_CLOSE_CLASS)) { 178 return; 179 } 180 181 if(mfp.st.closeOnContentClick) { 182 mfp.close(); 183 } else { 184 // close popup if click is not on a content, on close button, or content does not exist 185 if( !mfp.content || 186 $(target).hasClass('mfp-close') || 187 (mfp.preloader && e.target === mfp.preloader[0]) || 188 (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { 189 mfp.close(); 190 } 191 } 192 }); 193 194 mfp.container = _getEl('container', mfp.wrap); 195 } 196 197 mfp.contentContainer = _getEl('content'); 198 if(mfp.st.preloader) { 199 mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); 200 } 201 202 203 // Initializing modules 204 var modules = $.magnificPopup.modules; 205 for(i = 0; i < modules.length; i++) { 206 var n = modules[i]; 207 n = n.charAt(0).toUpperCase() + n.slice(1); 208 mfp['init'+n].call(mfp); 209 } 210 _mfpTrigger('BeforeOpen'); 211 212 213 // Close button 214 if(!mfp.st.closeBtnInside) { 215 mfp.wrap.append( _getCloseBtn() ); 216 } else { 217 _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { 218 values.close_replaceWith = _getCloseBtn(item.type); 219 }); 220 _wrapClasses += ' mfp-close-btn-in'; 221 } 222 223 if(mfp.st.alignTop) { 224 _wrapClasses += ' mfp-align-top'; 225 } 226 227 228 229 if(mfp.fixedContentPos) { 230 mfp.wrap.css({ 231 overflow: mfp.st.overflowY, 232 overflowX: 'hidden', 233 overflowY: mfp.st.overflowY 234 }); 235 } else { 236 mfp.wrap.css({ 237 top: _window.scrollTop(), 238 position: 'absolute' 239 }); 240 } 241 if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { 242 mfp.bgOverlay.css({ 243 height: _document.height(), 244 position: 'absolute' 245 }); 246 } 247 248 249 250 // Close on ESC key 251 _document.on('keyup' + EVENT_NS, function(e) { 252 if(e.keyCode === 27) { 253 mfp.close(); 254 } 255 }); 256 257 _window.on('resize' + EVENT_NS, function() { 258 mfp.updateSize(); 259 }); 260 261 262 if(!mfp.st.closeOnContentClick) { 263 _wrapClasses += ' mfp-auto-cursor'; 264 } 265 266 if(_wrapClasses) 267 mfp.wrap.addClass(_wrapClasses); 268 269 270 // this triggers recalculation of layout, so we get it once to not to trigger twice 271 var windowHeight = mfp.wH = _window.height(); 272 273 274 var bodyStyles = {}; 275 276 if( mfp.fixedContentPos && mfp.st.overflowY !== 'scroll' ) { 277 var s = mfp._getScrollbarSize(); 278 if(s) { 279 bodyStyles.paddingRight = s; 280 } 281 } 282 283 if(mfp.fixedContentPos) { 284 if(!mfp.isIE7) { 285 bodyStyles.overflow = 'hidden'; 286 } else { 287 // ie7 double-scroll bug 288 $('body, html').css('overflow', 'hidden'); 289 } 290 } 291 292 293 294 var classesToadd = mfp.st.mainClass; 295 if(mfp.isIE7) { 296 classesToadd += ' mfp-ie7'; 297 } 298 if(classesToadd) { 299 mfp._addClassToMFP( classesToadd ); 300 } 301 302 // add content 303 mfp.updateItemHTML(); 304 305 _mfpTrigger('BuildControls'); 306 307 308 // remove scrollbar, add padding e.t.c 309 _body.css(bodyStyles); 310 311 // add everything to DOM 312 mfp.bgOverlay.add(mfp.wrap).prependTo( document.body ); 313 314 315 316 // Save last focused element 317 mfp._lastFocusedEl = document.activeElement; 318 319 // Wait for next cycle to allow CSS transition 320 setTimeout(function() { 321 322 if(mfp.content) { 323 mfp._addClassToMFP(READY_CLASS); 324 _setFocus(); 325 } else { 326 // if content is not defined (not loaded e.t.c) we add class only for BG 327 mfp.bgOverlay.addClass(READY_CLASS); 328 } 329 330 // Trap the focus in popup 331 _document.on('focusin' + EVENT_NS, function (e) { 332 if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { 333 _setFocus(); 334 return false; 335 } 336 }); 337 338 }, 16); 339 340 mfp.isOpen = true; 341 mfp.updateSize(windowHeight); 342 _mfpTrigger(OPEN_EVENT); 343 }, 344 345 /** 346 * Closes the popup 347 */ 348 close: function() { 349 if(!mfp.isOpen) return; 350 351 mfp.isOpen = false; 352 // for CSS3 animation 353 if(mfp.st.removalDelay) { 354 mfp._addClassToMFP(REMOVING_CLASS); 355 setTimeout(function() { 356 mfp._close(); 357 }, mfp.st.removalDelay); 358 } else { 359 mfp._close(); 360 } 361 }, 362 363 /** 364 * Helper for close() function 365 */ 366 _close: function() { 367 _mfpTrigger(CLOSE_EVENT); 368 369 var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' '; 370 371 mfp.bgOverlay.detach(); 372 mfp.wrap.detach(); 373 mfp.container.empty(); 374 375 if(mfp.st.mainClass) { 376 classesToRemove += mfp.st.mainClass + ' '; 377 } 378 379 mfp._removeClassFromMFP(classesToRemove); 380 381 if(mfp.fixedContentPos) { 382 var bodyStyles = {paddingRight: 0}; 383 if(mfp.isIE7) { 384 $('body, html').css('overflow', 'auto'); 385 } else { 386 bodyStyles.overflow = 'visible'; 387 } 388 _body.css(bodyStyles); 389 } 390 391 _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS); 392 mfp.ev.off(EVENT_NS); 393 394 // clean up DOM elements that aren't removed 395 mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style'); 396 mfp.bgOverlay.attr('class', 'mfp-bg'); 397 mfp.container.attr('class', 'mfp-container'); 398 399 // remove close button from target element 400 if(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true ) { 401 if(mfp.currTemplate.closeBtn) 402 mfp.currTemplate.closeBtn.detach(); 403 } 404 405 406 if(mfp._lastFocusedEl) { 407 $(mfp._lastFocusedEl).focus(); // put tab focus back 408 } 409 mfp.content = null; 410 mfp.currTemplate = null; 411 mfp.prevHeight = 0; 412 }, 413 414 updateSize: function(winHeight) { 415 416 if(mfp.isIOS) { 417 // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2 418 var zoomLevel = document.documentElement.clientWidth / window.innerWidth; 419 var height = window.innerHeight * zoomLevel; 420 mfp.wrap.css('height', height); 421 mfp.wH = height; 422 } else { 423 mfp.wH = winHeight || _window.height(); 424 } 425 426 _mfpTrigger('Resize'); 427 428 }, 429 430 431 /** 432 * Set content of popup based on current index 433 */ 434 updateItemHTML: function() { 435 var item = mfp.items[mfp.index]; 436 437 // Detach and perform modifications 438 439 440 mfp.contentContainer.detach(); 441 442 if(mfp.content) 443 mfp.content.detach(); 444 445 if(!item.parsed) { 446 item = mfp.parseEl( mfp.index ); 447 } 448 449 mfp.currItem = item; 450 451 var type = item.type; 452 if(!mfp.currTemplate[type]) { 453 var markup = mfp.st[type] ? mfp.st[type].markup : false; 454 455 // allows to modify markup 456 _mfpTrigger('FirstMarkupParse', markup); 457 458 if(markup) { 459 mfp.currTemplate[type] = $(markup); 460 } else { 461 // if there is no markup found we just define that template is parsed 462 mfp.currTemplate[type] = true; 463 } 464 } 465 466 if(_prevContentType && _prevContentType !== item.type) { 467 mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); 468 } 469 470 var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); 471 mfp.appendContent(newContent, type); 472 473 item.preloaded = true; 474 475 _mfpTrigger(CHANGE_EVENT, item); 476 _prevContentType = item.type; 477 478 // Append container back after its content changed 479 mfp.container.prepend(mfp.contentContainer); 480 }, 481 482 483 /** 484 * Set HTML content of popup 485 */ 486 appendContent: function(newContent, type) { 487 mfp.content = newContent; 488 489 if(newContent) { 490 if(mfp.st.closeBtnInside && mfp.currTemplate[type] === true) { 491 // if there is no markup, we just append close button element inside 492 if(!mfp.content.find('.mfp-close').length) { 493 mfp.content.append(_getCloseBtn()); 494 } 495 } else { 496 mfp.content = newContent; 497 } 498 } else { 499 mfp.content = ''; 500 } 501 502 _mfpTrigger(BEFORE_APPEND_EVENT); 503 mfp.container.addClass('mfp-'+type+'-holder'); 504 505 mfp.contentContainer.append(mfp.content); 506 }, 507 508 509 510 511 /** 512 * Creates Magnific Popup data object based on given data 513 * @param {int} index Index of item to parse 514 */ 515 parseEl: function(index) { 516 var item = mfp.items[index], 517 type = item.type; 518 519 520 if(item.tagName) { 521 item = { el: $(item) }; 522 } else { 523 item = { data: item, src: item.src }; 524 } 525 526 if(item.el) { 527 var types = mfp.types; 528 529 // check for 'mfp-TYPE' class 530 for(var i = 0; i < types.length; i++) { 531 if( item.el.hasClass('mfp-'+types[i]) ) { 532 type = types[i];
533 break; 534 } 535 } 536 537 item.src = item.el.attr('data-mfp-src'); 538 if(!item.src) { 539 item.src = item.el.attr('href'); 540 } 541 } 542 543 item.type = type || mfp.st.type; 544 item.index = index; 545 item.parsed = true; 546 mfp.items[index] = item; 547 _mfpTrigger('ElementParse', item); 548 549 return mfp.items[index]; 550 }, 551 552 553 /** 554 * Initializes single popup or a group of popups 555 */ 556 addGroup: function(el, options) { 557 var eHandler = function(e) { 558 559 var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; 560 if( midClick || e.which !== 2 ) { 561 var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; 562 563 if(disableOn) { 564 if($.isFunction(disableOn)) { 565 if( !disableOn.call(mfp) ) { 566 return true; 567 } 568 } else { // else it's number 569 if( $(window).width() < disableOn ) { 570 return true; 571 } 572 } 573 } 574 575 e.preventDefault(); 576 options.el = $(this); 577 options.mainEl = el; 578 if(options.delegate) { 579 options.items = el.find(options.delegate); 580 } 581 mfp.open(options); 582 } 583 584 }; 585 586 if(!options) { 587 options = {}; 588 } 589 590 var eName = 'click.magnificPopup'; 591 if(options.items) { 592 options.isObj = true; 593 el.off(eName).on(eName, eHandler); 594 } else { 595 options.isObj = false; 596 if(options.delegate) { 597 el.off(eName).on(eName, options.delegate , eHandler); 598 } else { 599 options.items = el; 600 el.off(eName).on(eName, eHandler); 601 } 602 } 603 }, 604 605 606 /** 607 * Updates text on preloader 608 */ 609 updateStatus: function(status, text) { 610 611 if(mfp.preloader) { 612 if(_prevStatus !== status) { 613 mfp.container.removeClass('mfp-s-'+_prevStatus); 614 } 615 616 if(!text && status === 'loading') { 617 text = mfp.st.tLoading; 618 } 619 620 var data = { 621 status: status, 622 text: text 623 }; 624 // allows to modify status 625 _mfpTrigger('UpdateStatus', data); 626 627 status = data.status; 628 text = data.text; 629 630 mfp.preloader.html(text); 631 632 mfp.preloader.find('a').click(function(e) { 633 e.stopImmediatePropagation(); 634 }); 635 636 mfp.container.addClass('mfp-s-'+status); 637 _prevStatus = status; 638 } 639 }, 640 641 642 643 644 645 646 647 648 649 /* 650 "Private" helpers that aren't private at all 651 */ 652 _addClassToMFP: function(cName) { 653 mfp.bgOverlay.addClass(cName); 654 mfp.wrap.addClass(cName); 655 }, 656 _removeClassFromMFP: function(cName) { 657 this.bgOverlay.removeClass(cName); 658 mfp.wrap.removeClass(cName); 659 }, 660 _hasScrollBar: function(winHeight) { 661 if(document.body.clientHeight > (winHeight || _window.height()) ) { 662 return true; 663 } 664 return false; 665 }, 666 667 _parseMarkup: function(template, values, item) { 668 var arr; 669 if(item.data) { 670 values = $.extend(item.data, values); 671 } 672 _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); 673 674 $.each(values, function(key, value) { 675 if(value === undefined || value === false) { 676 return true; 677 } 678 arr = key.split('_'); 679 if(arr.length > 1) { 680 var el = template.find(EVENT_NS + '-'+arr[0]); 681 682 if(el.length > 0) { 683 var attr = arr[1]; 684 if(attr === 'replaceWith') { 685 if(el[0] !== value[0]) { 686 el.replaceWith(value); 687 } 688 } else if(attr === 'img') { 689 if(el.is('img')) { 690 el.attr('src', value); 691 } else { 692 el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' ); 693 } 694 } else { 695 el.attr(arr[1], value); 696 } 697 } 698 699 } else { 700 template.find(EVENT_NS + '-'+key).html(value); 701 } 702 }); 703 }, 704 705 _getScrollbarSize: function() { 706 // thx David 707 if(mfp.scrollbarSize === undefined) { 708 var scrollDiv = document.createElement("div"); 709 scrollDiv.id = "mfp-sbm"; 710 scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; 711 document.body.appendChild(scrollDiv); 712 mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; 713 document.body.removeChild(scrollDiv); 714 } 715 return mfp.scrollbarSize; 716 } 717 718}; /* MagnificPopup core prototype end */ 719 720 721 722 723/** 724 * Public static functions 725 */ 726$.magnificPopup = { 727 instance: null, 728 proto: MagnificPopup.prototype, 729 modules: [], 730 731 open: function(options, index) { 732 if(!$.magnificPopup.instance) { 733 mfp = new MagnificPopup(); 734 mfp.init(); 735 $.magnificPopup.instance = mfp; 736 } 737 738 if(!options) { 739 options = {}; 740 } 741 742 options.isObj = true; 743 options.index = index === undefined ? 0 : index; 744 return this.instance.open(options); 745 }, 746 747 close: function() { 748 return $.magnificPopup.instance.close(); 749 }, 750 751 registerModule: function(name, module) { 752 if(module.options) { 753 $.magnificPopup.defaults[name] = module.options; 754 } 755 $.extend(this.proto, module.proto); 756 this.modules.push(name); 757 }, 758 759 defaults: { 760 761 // Info about options is docs:
762 // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options 763 764 disableOn: 0, 765 766 key: null, 767 768 midClick: false, 769 770 mainClass: '', 771 772 preloader: true, 773 774 focus: '', // CSS selector of input to focus after popup is opened 775 776 closeOnContentClick: false, 777 778 closeBtnInside: true, 779 780 alignTop: false, 781 782 removalDelay: 0, 783 784 fixedContentPos: 'auto', 785 786 fixedBgPos: 'auto', 787 788 overflowY: 'auto', 789 790 closeMarkup: '<button title="%title%" type="button" class="mfp-close">×</button>', 791 792 tClose: 'Close (Esc)', 793 794 tLoading: 'Loading...' 795 796 } 797}; 798 799 800 801$.fn.magnificPopup = function(options) { 802 // Initialize Magnific Popup only when called at least once 803 if(!$.magnificPopup.instance) { 804 mfp = new MagnificPopup(); 805 mfp.init(); 806 $.magnificPopup.instance = mfp; 807 } 808 809 mfp.addGroup($(this), options); 810 return $(this); 811}; 812 813 814//Quick benchmark 815/* 816var start = performance.now(), 817 i, 818 rounds = 1000; 819 820for(i = 0; i < rounds; i++) { 821 822} 823console.log('Test #1:', performance.now() - start); 824 825start = performance.now(); 826for(i = 0; i < rounds; i++) { 827 828} 829console.log('Test #2:', performance.now() - start); 830*/ 831 832/*>>core*/ 833 834/*>>inline*/ 835 836var INLINE_NS = 'inline', 837 _hasPlaceholder; 838 839$.magnificPopup.registerModule(INLINE_NS, { 840 options: { 841 hiddenClass: NS+'-hide', 842 markup: '', 843 tNotFound: 'Content not found' 844 }, 845 proto: { 846 847 initInline: function() { 848 mfp.types.push(INLINE_NS); 849 _hasPlaceholder = false; 850 851 _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { 852 var item = mfp.currItem; 853 if(item.type === INLINE_NS) { 854 if(_hasPlaceholder) { 855 for(var i = 0; i < mfp.items.length; i++) { 856 item = mfp.items[i]; 857 if(item && item.inlinePlaceholder){ 858 item.inlinePlaceholder.after( item.inlineElement.addClass(mfp.st.inline.hiddenClass) ).detach(); 859 } 860 } 861 } 862 item.inlinePlaceholder = item.inlineElement = null; 863 } 864 }); 865 }, 866 867 getInline: function(item, template) { 868 mfp.updateStatus('ready'); 869 870 if(item.src) { 871 var inlineSt = mfp.st.inline; 872 // items.src can be String-CSS-selector or jQuery element 873 if(typeof item.src !== 'string') { 874 item.isElement = true; 875 } 876 877 if(!item.isElement && !item.inlinePlaceholder) { 878 item.inlinePlaceholder = _getEl(inlineSt.hiddenClass); 879 } 880 881 if(item.isElement) { 882 item.inlineElement = item.src; 883 } else if(!item.inlineElement) { 884 item.inlineElement = $(item.src); 885 if(!item.inlineElement.length) { 886 mfp.updateStatus('error', inlineSt.tNotFound); 887 item.inlineElement = $('<div>'); 888 } 889 } 890 891 if(item.inlinePlaceholder) { 892 _hasPlaceholder = true; 893 } 894 895 896 897 item.inlineElement.after(item.inlinePlaceholder).detach().removeClass(inlineSt.hiddenClass); 898 return item.inlineElement; 899 } else { 900 mfp._parseMarkup(template, {}, item); 901 return template; 902 } 903 } 904 } 905}); 906 907/*>>inline*/ 908 909/*>>ajax*/ 910var AJAX_NS = 'ajax', 911 _ajaxCur, 912 _removeAjaxCursor = function() { 913 if(_ajaxCur) { 914 _body.removeClass(_ajaxCur); 915 } 916 }; 917 918$.magnificPopup.registerModule(AJAX_NS, { 919 920 options: { 921 settings: null, 922 cursor: 'mfp-ajax-cur', 923 tError: '<a href="%url%">The content</a> could not be loaded.' 924 }, 925 926 proto: { 927 initAjax: function() { 928 mfp.types.push(AJAX_NS); 929 _ajaxCur = mfp.st.ajax.cursor; 930 931 _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, function() { 932 _removeAjaxCursor(); 933 if(mfp.req) { 934 mfp.req.abort(); 935 } 936 }); 937 }, 938 939 getAjax: function(item) { 940 941 if(_ajaxCur) 942 _body.addClass(_ajaxCur); 943 944 mfp.updateStatus('loading'); 945 946 var opts = $.extend({ 947 url: item.src, 948 success: function(data, textStatus, jqXHR) { 949 950 _mfpTrigger('ParseAjax', jqXHR); 951 952 mfp.appendContent( $(jqXHR.responseText), AJAX_NS ); 953 954 item.finished = true; 955 956 _removeAjaxCursor(); 957 958 _setFocus(); 959 960 setTimeout(function() { 961 mfp.wrap.addClass(READY_CLASS); 962 }, 16); 963 964 mfp.updateStatus('ready'); 965 966 }, 967 error: function() { 968 _removeAjaxCursor(); 969 item.finished = item.loadError = true; 970 mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); 971 } 972 }, mfp.st.ajax.settings); 973 974 mfp.req = $.ajax(opts); 975 976 return ''; 977 } 978 } 979}); 980 981 982 983 984 985 986 987/*>>ajax*/ 988 989/*>>image*/ 990var _imgInterval, 991 _getTitle = function(item) { 992 if(item.data && item.data.title !== undefined) 993 return item.data.title; 994
vendor: 9,959 bytes, lines 995-1413
995 var src = mfp.st.image.titleSrc; 996 997 if(src) { 998 if($.isFunction(src)) { 999 return src.call(mfp, item); 1000 } else if(item.el) { 1001 return item.el.attr(src) || ''; 1002 } 1003 } 1004 return ''; 1005 }; 1006 1007$.magnificPopup.registerModule('image', { 1008 1009 options: { 1010 markup: '<div class="mfp-figure">'+ 1011 '<div class="mfp-close"></div>'+ 1012 '<div class="mfp-img"></div>'+ 1013 '<div class="mfp-bottom-bar">'+ 1014 '<div class="mfp-title"></div>'+ 1015 '<div class="mfp-counter"></div>'+ 1016 '</div>'+ 1017 '</div>', 1018 cursor: 'mfp-zoom-out-cur', 1019 titleSrc: 'title', 1020 verticalFit: true, 1021 tError: '<a href="%url%">The image</a> could not be loaded.' 1022 }, 1023 1024 proto: { 1025 initImage: function() { 1026 var imgSt = mfp.st.image, 1027 ns = '.image'; 1028 1029 mfp.types.push('image'); 1030 1031 _mfpOn(OPEN_EVENT+ns, function() { 1032 if(mfp.currItem.type === 'image' && imgSt.cursor) { 1033 _body.addClass(imgSt.cursor); 1034 } 1035 }); 1036 1037 _mfpOn(CLOSE_EVENT+ns, function() { 1038 if(imgSt.cursor) { 1039 _body.removeClass(imgSt.cursor); 1040 } 1041 _window.off('resize' + EVENT_NS); 1042 }); 1043 1044 _mfpOn('Resize'+ns, function() { 1045 mfp.resizeImage(); 1046 }); 1047 }, 1048 resizeImage: function() { 1049 var item = mfp.currItem; 1050 if(!item.img) return; 1051 if(mfp.st.image.verticalFit) { 1052 item.img.css('max-height', mfp.wH + 'px'); 1053 } 1054 }, 1055 _onImageHasSize: function(item) { 1056 if(item.img) { 1057 1058 item.hasSize = true; 1059 1060 if(_imgInterval) { 1061 clearInterval(_imgInterval); 1062 } 1063 1064 item.isCheckingImgSize = false; 1065 1066 _mfpTrigger('ImageHasSize', item); 1067 1068 if(item.imgHidden) { 1069 if(mfp.content) 1070 mfp.content.removeClass('mfp-loading'); 1071 1072 item.imgHidden = false; 1073 } 1074 1075 } 1076 }, 1077 1078 /** 1079 * Function that loops until the image has size to display elements that rely on it asap 1080 */ 1081 findImageSize: function(item) { 1082 1083 var counter = 0, 1084 img = item.img[0], 1085 mfpSetInterval = function(delay) { 1086 1087 if(_imgInterval) { 1088 clearInterval(_imgInterval); 1089 } 1090 // decelerating interval that checks for size of an image 1091 _imgInterval = setInterval(function() { 1092 if(img.naturalWidth > 0) { 1093 mfp._onImageHasSize(item); 1094 return; 1095 } 1096 1097 if(counter > 200) { 1098 clearInterval(_imgInterval); 1099 } 1100 1101 counter++; 1102 if(counter === 3) { 1103 mfpSetInterval(10); 1104 } else if(counter === 40) { 1105 mfpSetInterval(50); 1106 } else if(counter === 100) { 1107 mfpSetInterval(500); 1108 } 1109 }, delay); 1110 }; 1111 1112 mfpSetInterval(1); 1113 }, 1114 1115 getImage: function(item, template) { 1116 1117 var guard = 0, 1118 1119 // image load complete handler 1120 onLoadComplete = function() { 1121 if(item) { 1122 if (item.img[0].complete) { 1123 item.img.off('.mfploader'); 1124 1125 if(item === mfp.currItem){ 1126 mfp._onImageHasSize(item); 1127 1128 mfp.updateStatus('ready'); 1129 } 1130 1131 item.hasSize = true; 1132 item.loaded = true; 1133 1134 } 1135 else { 1136 // if image complete check fails 200 times (20 sec), we assume that there was an error. 1137 guard++; 1138 if(guard < 200) { 1139 setTimeout(onLoadComplete,100); 1140 } else { 1141 onLoadError(); 1142 } 1143 } 1144 } 1145 }, 1146 1147 // image error handler 1148 onLoadError = function() { 1149 if(item) { 1150 item.img.off('.mfploader'); 1151 if(item === mfp.currItem){ 1152 mfp._onImageHasSize(item); 1153 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 1154 } 1155 1156 item.hasSize = true; 1157 item.loaded = true; 1158 item.loadError = true; 1159 } 1160 }, 1161 imgSt = mfp.st.image; 1162 1163 1164 var el = template.find('.mfp-img'); 1165 if(el.length) { 1166 var img = new Image(); 1167 img.className = 'mfp-img'; 1168 item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError); 1169 img.src = item.src; 1170 1171 // without clone() "error" event is not firing when IMG is replaced by new IMG 1172 // TODO: find a way to avoid such cloning 1173 if(el.is('img')) { 1174 item.img = item.img.clone(); 1175 } 1176 } 1177 1178 mfp._parseMarkup(template, { 1179 title: _getTitle(item), 1180 img_replaceWith: item.img 1181 }, item); 1182 1183 mfp.resizeImage(); 1184 1185 if(item.hasSize) { 1186 if(_imgInterval) clearInterval(_imgInterval); 1187 1188 if(item.loadError) { 1189 template.addClass('mfp-loading'); 1190 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 1191 } else { 1192 template.removeClass('mfp-loading'); 1193 mfp.updateStatus('ready'); 1194 } 1195 return template; 1196 } 1197 1198 mfp.updateStatus('loading'); 1199 item.loading = true; 1200 1201 if(!item.hasSize) { 1202 item.imgHidden = true; 1203 template.addClass('mfp-loading'); 1204 mfp.findImageSize(item); 1205 } 1206 1207 return template; 1208 } 1209 } 1210}); 1211 1212 1213 1214/*>>image*/ 1215 1216/*>>iframe*/ 1217 1218var IFRAME_NS = 'iframe', 1219 1220 // IE black screen bug fix 1221 toggleIframeInIE = function(show) { 1222 if(mfp.isIE7 && mfp.currItem && mfp.currItem.type === IFRAME_NS) { 1223 var el = mfp.content.find('iframe'); 1224 if(el.length) { 1225 el.css('display', show ? 'block' : 'none'); 1226 } 1227 } 1228 }; 1229 1230$.magnificPopup.registerModule(IFRAME_NS, { 1231 1232 options: { 1233 markup: '<div class="mfp-iframe-scaler">'+ 1234 '<div class="mfp-close"></div>'+ 1235 '<iframe class="mfp-iframe" frameborder="0" allowfullscreen></iframe>'+ 1236 '</div>', 1237 1238 srcAction: 'iframe_src', 1239 1240 // we don't care and support only one default type of URL by default 1241 patterns: { 1242 youtube: { 1243 index: 'youtube.com', 1244 id: 'v=', 1245 src: '//www.youtube.com/embed/%id%?autoplay=1' 1246 }, 1247 vimeo: { 1248 index: 'vimeo.com/', 1249 id: '/', 1250 src: '//player.vimeo.com/video/%id%?autoplay=1' 1251 }, 1252 gmaps: { 1253 index: '//maps.google.', 1254 src: '%id%&output=embed' 1255 } 1256 } 1257 }, 1258 1259 proto: { 1260 initIframe: function() { 1261 mfp.types.push(IFRAME_NS); 1262 toggleIframeInIE(true); 1263 _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { 1264 toggleIframeInIE(); 1265 }); 1266 }, 1267 1268 getIframe: function(item, template) { 1269 var embedSrc = item.src; 1270 var iframeSt = mfp.st.iframe; 1271 1272 $.each(iframeSt.patterns, function() { 1273 if(embedSrc.indexOf( this.index ) > -1) { 1274 if(this.id) { 1275 if(typeof this.id === 'string') { 1276 embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); 1277 } else { 1278 embedSrc = this.id.call( this, embedSrc ); 1279 } 1280 } 1281 embedSrc = this.src.replace('%id%', embedSrc ); 1282 return false; // break; 1283 } 1284 }); 1285 1286 var dataObj = {}; 1287 if(iframeSt.srcAction) { 1288 dataObj[iframeSt.srcAction] = embedSrc; 1289 } 1290 mfp._parseMarkup(template, dataObj, item); 1291 1292 mfp.updateStatus('ready'); 1293 1294 return template; 1295 } 1296 } 1297}); 1298 1299 1300 1301/*>>iframe*/ 1302 1303/*>>gallery*/ 1304/** 1305 * Get looped index depending on number of slides 1306 */ 1307var _getLoopedId = function(index) { 1308 var numSlides = mfp.items.length; 1309 if(index > numSlides - 1) { 1310 return index - numSlides; 1311 } else if(index < 0) { 1312 return numSlides + index; 1313 } 1314 return index; 1315 }, 1316 _replaceCurrTotal = function(text, curr, total) { 1317 return text.replace('%curr%', curr + 1).replace('%total%', total); 1318 }; 1319 1320$.magnificPopup.registerModule('gallery', { 1321 1322 options: { 1323 enabled: false, 1324 arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', 1325 preload: [0,2], 1326 navigateByImgClick: true, 1327 arrows: true, 1328 1329 tPrev: 'Previous (Left arrow key)', 1330 tNext: 'Next (Right arrow key)', 1331 tCounter: '%curr% of %total%' 1332 }, 1333 1334 proto: { 1335 initGallery: function() { 1336 1337 var gSt = mfp.st.gallery, 1338 ns = '.mfp-gallery', 1339 supportsFastClick = Boolean($.fn.mfpFastClick); 1340 1341 mfp.direction = true; // true - next, false - prev 1342 1343 if(!gSt || !gSt.enabled ) return false; 1344 1345 _wrapClasses += ' mfp-gallery'; 1346 1347 _mfpOn(OPEN_EVENT+ns, function() { 1348 1349 if(gSt.navigateByImgClick) { 1350 mfp.wrap.on('click'+ns, '.mfp-img', function() { 1351 mfp.next(); 1352 return false; 1353 }); 1354 } 1355 1356 _document.on('keydown'+ns, function(e) { 1357 if (e.keyCode === 37) { 1358 mfp.prev(); 1359 } else if (e.keyCode === 39) { 1360 mfp.next(); 1361 } 1362 }); 1363 }); 1364 1365 _mfpOn('UpdateStatus'+ns, function(e, data) { 1366 if(data.text) { 1367 data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); 1368 } 1369 }); 1370 1371 _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { 1372 var l = mfp.items.length; 1373 values.counter = l ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; 1374 }); 1375 1376 _mfpOn('BuildControls' + ns, function() { 1377 if(gSt.arrows && !mfp.arrowLeft) { 1378 var markup = gSt.arrowMarkup, 1379 arrowLeft = mfp.arrowLeft = $( markup.replace('%title%', gSt.tPrev).replace('%dir%', 'left') ).addClass(PREVENT_CLOSE_CLASS), 1380 arrowRight = mfp.arrowRight = $( markup.replace('%title%', gSt.tNext).replace('%dir%', 'right') ).addClass(PREVENT_CLOSE_CLASS); 1381 1382 var eName = supportsFastClick ? 'mfpFastClick' : 'click'; 1383 arrowLeft[eName](function() { 1384 mfp.prev(); 1385 }); 1386 arrowRight[eName](function() { 1387 mfp.next(); 1388 }); 1389 1390 // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) 1391 if(mfp.isIE7) { 1392 _getEl('b', arrowLeft[0], false, true); 1393 _getEl('a', arrowLeft[0], false, true); 1394 _getEl('b', arrowRight[0], false, true); 1395 _getEl('a', arrowRight[0], false, true); 1396 } 1397 1398 mfp.container.append(arrowLeft.add(arrowRight)); 1399 } 1400 }); 1401 1402 _mfpOn(CHANGE_EVENT+ns, function() { 1403 if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); 1404 1405 mfp._preloadTimeout = setTimeout(function() { 1406 mfp.preloadNearbyImages(); 1407 mfp._preloadTimeout = null; 1408 }, 16); 1409 }); 1410 1411 1412 _mfpOn(CLOSE_EVENT+ns, function() { 1413 _document.off(ns);
1414 mfp.wrap.off('click'+ns); 1415 1416 if(supportsFastClick) { 1417 mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); 1418 } 1419 mfp.arrowRight = mfp.arrowLeft = null; 1420 }); 1421 1422 }, 1423 next: function() { 1424 mfp.direction = true; 1425 mfp.index = _getLoopedId(mfp.index + 1); 1426 mfp.updateItemHTML(); 1427 }, 1428 prev: function() { 1429 mfp.direction = false; 1430 mfp.index = _getLoopedId(mfp.index - 1); 1431 mfp.updateItemHTML(); 1432 }, 1433 goTo: function(newIndex) { 1434 mfp.direction = (newIndex >= mfp.index); 1435 mfp.index = newIndex; 1436 mfp.updateItemHTML(); 1437 }, 1438 preloadNearbyImages: function() { 1439 var p = mfp.st.gallery.preload, 1440 preloadBefore = Math.min(p[0], mfp.items.length), 1441 preloadAfter = Math.min(p[1], mfp.items.length), 1442 i; 1443 1444 for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { 1445 mfp._preloadItem(mfp.index+i); 1446 } 1447 for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { 1448 mfp._preloadItem(mfp.index-i); 1449 } 1450 }, 1451 _preloadItem: function(index) { 1452 index = _getLoopedId(index); 1453 1454 if(mfp.items[index].preloaded) { 1455 return; 1456 } 1457 1458 var item = mfp.items[index]; 1459 if(!item.parsed) { 1460 item = mfp.parseEl( index ); 1461 } 1462 1463 _mfpTrigger('LazyLoad', item); 1464 1465 if(item.type === 'image') { 1466 item.img = $('<img class="mfp-img" />').on('load.mfploader', function() { 1467 item.hasSize = true; 1468 }).on('error.mfploader', function() { 1469 item.hasSize = true; 1470 item.loadError = true; 1471 }).attr('src', item.src); 1472 } 1473 1474 1475 item.preloaded = true; 1476 } 1477 } 1478}); 1479 1480/* 1481Touch Support that might be implemented some day 1482 1483addSwipeGesture: function() { 1484 var startX, 1485 moved, 1486 multipleTouches; 1487 1488 return; 1489 1490 var namespace = '.mfp', 1491 addEventNames = function(pref, down, move, up, cancel) { 1492 mfp._tStart = pref + down + namespace; 1493 mfp._tMove = pref + move + namespace; 1494 mfp._tEnd = pref + up + namespace; 1495 mfp._tCancel = pref + cancel + namespace; 1496 }; 1497 1498 if(window.navigator.msPointerEnabled) { 1499 addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); 1500 } else if('ontouchstart' in window) { 1501 addEventNames('touch', 'start', 'move', 'end', 'cancel'); 1502 } else { 1503 return; 1504 } 1505 _window.on(mfp._tStart, function(e) { 1506 var oE = e.originalEvent; 1507 multipleTouches = moved = false; 1508 startX = oE.pageX || oE.changedTouches[0].pageX; 1509 }).on(mfp._tMove, function(e) { 1510 if(e.originalEvent.touches.length > 1) { 1511 multipleTouches = e.originalEvent.touches.length; 1512 } else { 1513 //e.preventDefault(); 1514 moved = true; 1515 } 1516 }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { 1517 if(moved && !multipleTouches) { 1518 var oE = e.originalEvent, 1519 diff = startX - (oE.pageX || oE.changedTouches[0].pageX); 1520 1521 if(diff > 20) { 1522 mfp.next(); 1523 } else if(diff < -20) { 1524 mfp.prev(); 1525 } 1526 } 1527 }); 1528}, 1529*/ 1530 1531 1532/*>>gallery*/ 1533 1534/*>>retina*/ 1535 1536var RETINA_NS = 'retina'; 1537 1538$.magnificPopup.registerModule(RETINA_NS, { 1539 options: { 1540 replaceSrc: function(item) { 1541 return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); 1542 }, 1543 ratio: 1 // Function or number. Set to 1 to disable. 1544 }, 1545 proto: { 1546 initRetina: function() { 1547 if(window.devicePixelRatio > 1) { 1548 1549 var st = mfp.st.retina, 1550 ratio = st.ratio; 1551 1552 ratio = !isNaN(ratio) ? ratio : ratio(); 1553 1554 if(ratio > 1) { 1555 _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { 1556 item.img.css({ 1557 'max-width': item.img[0].naturalWidth / ratio, 1558 'width': '100%' 1559 }); 1560 }); 1561 _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { 1562 item.src = st.replaceSrc(item, ratio); 1563 }); 1564 } 1565 } 1566 1567 } 1568 } 1569}); 1570 1571/*>>retina*/ 1572 1573/*>>fastclick*/ 1574/** 1575 * FastClick event implementation. (removes 300ms delay on touch devices) 1576 * Based on https://developers.google.com/mobile/articles/fast_buttons 1577 * 1578 * You may use it outside the Magnific Popup by calling just: 1579 * 1580 * $('.your-el').mfpFastClick(function() { 1581 * console.log('Clicked!'); 1582 * }); 1583 * 1584 * To unbind: 1585 * $('.your-el').destroyMfpFastClick(); 1586 * 1587 * 1588 * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. 1589 * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick 1590 * 1591 */ 1592 1593(function() { 1594 var ghostClickDelay = 1000, 1595 supportsTouch = 'ontouchstart' in window, 1596 unbindTouchMove = function() { 1597 _window.off('touchmove'+ns+' touchend'+ns); 1598 }, 1599 eName = 'mfpFastClick', 1600 ns = '.'+eName; 1601 1602 1603 // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way 1604 $.fn.mfpFastClick = function(callback) { 1605 1606 return $(this).each(function() { 1607 1608 var elem = $(this), 1609 lock; 1610 1611 if( supportsTouch ) { 1612 1613 var timeout, 1614 startX, 1615 startY, 1616 pointerMoved, 1617 point, 1618 numPointers; 1619 1620 elem.on('touchstart' + ns, function(e) { 1621 pointerMoved = false; 1622 numPointers = 1; 1623 1624 point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; 1625 startX = point.clientX; 1626 startY = point.clientY; 1627 1628 _window.on('touchmove'+ns, function(e) { 1629 point = e.originalEvent ? e.originalEvent.touches : e.touches; 1630 numPointers = point.length; 1631 point = point[0]; 1632 if (Math.abs(point.clientX - startX) > 10 || 1633 Math.abs(point.clientY - startY) > 10) { 1634 pointerMoved = true; 1635 unbindTouchMove(); 1636 } 1637 }).on('touchend'+ns, function(e) { 1638 unbindTouchMove(); 1639 if(pointerMoved || numPointers > 1) { 1640 return; 1641 } 1642 lock = true; 1643 e.preventDefault(); 1644 clearTimeout(timeout); 1645 timeout = setTimeout(function() { 1646 lock = false; 1647 }, ghostClickDelay); 1648 callback(); 1649 });
1650 }); 1651 1652 } 1653 1654 elem.on('click' + ns, function() { 1655 if(!lock) { 1656 callback(); 1657 } 1658 }); 1659 }); 1660 }; 1661 1662 $.fn.destroyMfpFastClick = function() { 1663 $(this).off('touchstart' + ns + ' click' + ns); 1664 if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); 1665 }; 1666})(); 1667 1668/*>>fastclick*/ 1669})(window.jQuery || window.Zepto);
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.