vendor: 43,945 bytes, lines 1-1946
1/*! Magnific Popup - v1.2.0 - 2024-06-08 2* http://dimsemenov.com/plugins/magnific-popup/ 3* Copyright (c) 2024 Dmytro Semenov; */ 4;(function (factory) { 5if (typeof define === 'function' && define.amd) { 6 // AMD. Register as an anonymous module. 7 define(['jquery'], factory); 8 } else if (typeof exports === 'object') { 9 // Node/CommonJS 10 factory(require('jquery')); 11 } else { 12 // Browser globals 13 factory(window.jQuery || window.Zepto); 14 } 15 }(function($) { 16 17/*>>core*/ 18/** 19 * 20 * Magnific Popup Core JS file 21 * 22 */ 23 24 25/** 26 * Private static constants 27 */ 28var CLOSE_EVENT = 'Close', 29 BEFORE_CLOSE_EVENT = 'BeforeClose', 30 AFTER_CLOSE_EVENT = 'AfterClose', 31 BEFORE_APPEND_EVENT = 'BeforeAppend', 32 MARKUP_PARSE_EVENT = 'MarkupParse', 33 OPEN_EVENT = 'Open', 34 CHANGE_EVENT = 'Change', 35 NS = 'mfp', 36 EVENT_NS = '.' + NS, 37 READY_CLASS = 'mfp-ready', 38 REMOVING_CLASS = 'mfp-removing', 39 PREVENT_CLOSE_CLASS = 'mfp-prevent-close'; 40 41 42/** 43 * Private vars 44 */ 45/*jshint -W079 */ 46var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this' 47 MagnificPopup = function(){}, 48 _isJQ = !!(window.jQuery), 49 _prevStatus, 50 _window = $(window), 51 _document, 52 _prevContentType, 53 _wrapClasses, 54 _currPopupType; 55 56 57/** 58 * Private functions 59 */ 60var _mfpOn = function(name, f) { 61 mfp.ev.on(NS + name + EVENT_NS, f); 62 }, 63 _getEl = function(className, appendTo, html, raw) { 64 var el = document.createElement('div'); 65 el.className = 'mfp-'+className; 66 if(html) { 67 el.innerHTML = html; 68 } 69 if(!raw) { 70 el = $(el); 71 if(appendTo) { 72 el.appendTo(appendTo); 73 } 74 } else if(appendTo) { 75 appendTo.appendChild(el); 76 } 77 return el; 78 }, 79 _mfpTrigger = function(e, data) { 80 mfp.ev.triggerHandler(NS + e, data); 81 82 if(mfp.st.callbacks) { 83 // converts "mfpEventName" to "eventName" callback and triggers it if it's present 84 e = e.charAt(0).toLowerCase() + e.slice(1); 85 if(mfp.st.callbacks[e]) { 86 mfp.st.callbacks[e].apply(mfp, Array.isArray(data) ? data : [data]); 87 } 88 } 89 }, 90 _getCloseBtn = function(type) { 91 if(type !== _currPopupType || !mfp.currTemplate.closeBtn) { 92 mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace(/%title%/g, mfp.st.tClose ) ); 93 _currPopupType = type; 94 } 95 return mfp.currTemplate.closeBtn; 96 }, 97 // Initialize Magnific Popup only when called at least once 98 _checkInstance = function() { 99 if(!$.magnificPopup.instance) { 100 /*jshint -W020 */ 101 mfp = new MagnificPopup(); 102 mfp.init(); 103 $.magnificPopup.instance = mfp; 104 } 105 }, 106 // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr 107 supportsTransitions = function() { 108 var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist 109 v = ['ms','O','Moz','Webkit']; // 'v' for vendor 110 111 if( s['transition'] !== undefined ) { 112 return true; 113 } 114 115 while( v.length ) { 116 if( v.pop() + 'Transition' in s ) { 117 return true; 118 } 119 } 120 121 return false; 122 }; 123 124 125 126/** 127 * Public functions 128 */ 129MagnificPopup.prototype = { 130 131 constructor: MagnificPopup, 132 133 /** 134 * Initializes Magnific Popup plugin. 135 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed 136 */ 137 init: function() { 138 var appVersion = navigator.appVersion; 139 mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener; 140 mfp.isAndroid = (/android/gi).test(appVersion); 141 mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); 142 mfp.supportsTransition = supportsTransitions(); 143 144 // We disable fixed positioned lightbox on devices that don't handle it nicely. 145 // If you know a better way of detecting this - let me know. 146 mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); 147 _document = $(document); 148 149 mfp.popupsCache = {}; 150 }, 151 152 /** 153 * Opens popup 154 * @param data [description] 155 */ 156 open: function(data) { 157 158 var i; 159 160 if(data.isObj === false) { 161 // convert jQuery collection to array to avoid conflicts later 162 mfp.items = data.items.toArray(); 163 164 mfp.index = 0; 165 var items = data.items, 166 item; 167 for(i = 0; i < items.length; i++) { 168 item = items[i]; 169 if(item.parsed) { 170 item = item.el[0]; 171 } 172 if(item === data.el[0]) { 173 mfp.index = i; 174 break; 175 } 176 } 177 } else { 178 mfp.items = Array.isArray(data.items) ? data.items : [data.items]; 179 mfp.index = data.index || 0; 180 } 181 182 // if popup is already opened - we just update the content 183 if(mfp.isOpen) { 184 mfp.updateItemHTML(); 185 return; 186 } 187 188 mfp.types = []; 189 _wrapClasses = ''; 190 if(data.mainEl && data.mainEl.length) { 191 mfp.ev = data.mainEl.eq(0); 192 } else { 193 mfp.ev = _document; 194 } 195 196 if(data.key) { 197 if(!mfp.popupsCache[data.key]) { 198 mfp.popupsCache[data.key] = {}; 199 } 200 mfp.currTemplate = mfp.popupsCache[data.key]; 201 } else { 202 mfp.currTemplate = {}; 203 } 204 205 206 207 mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 208 mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; 209 210 if(mfp.st.modal) { 211 mfp.st.closeOnContentClick = false; 212 mfp.st.closeOnBgClick = false; 213 mfp.st.showCloseBtn = false; 214 mfp.st.enableEscapeKey = false; 215 } 216 217 218 // Building markup 219 // main containers are created only once 220 if(!mfp.bgOverlay) { 221 222 // Dark overlay 223 mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { 224 mfp.close(); 225 }); 226 227 mfp.wrap = _getEl('wrap') 228 .attr('tabindex', -1) 229 .attr('role', 'dialog') 230 .attr('aria-modal', true) 231 .attr('aria-label', 'Popup Image') 232 .on('click'+EVENT_NS, function(e) { 233 if(mfp._checkIfClose(e.target)) { 234 mfp.close(); 235 } 236 }); 237 238 mfp.container = _getEl('container', mfp.wrap); 239 } 240 241 mfp.contentContainer = _getEl('content'); 242 if(mfp.st.preloader) { 243 mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); 244 } 245 246 247 // Initializing modules 248 var modules = $.magnificPopup.modules; 249 for(i = 0; i < modules.length; i++) { 250 var n = modules[i]; 251 n = n.charAt(0).toUpperCase() + n.slice(1); 252 mfp['init'+n].call(mfp); 253 } 254 _mfpTrigger('BeforeOpen'); 255 256 257 if(mfp.st.showCloseBtn) { 258 // Close button 259 if(!mfp.st.closeBtnInside) { 260 mfp.wrap.append( _getCloseBtn() ); 261 } else { 262 _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { 263 values.close_replaceWith = _getCloseBtn(item.type); 264 }); 265 _wrapClasses += ' mfp-close-btn-in'; 266 } 267 } 268 269 if(mfp.st.alignTop) { 270 _wrapClasses += ' mfp-align-top'; 271 } 272 273 274 275 if(mfp.fixedContentPos) { 276 mfp.wrap.css({ 277 overflow: mfp.st.overflowY, 278 overflowX: 'hidden', 279 overflowY: mfp.st.overflowY 280 }); 281 } else { 282 mfp.wrap.css({ 283 top: _window.scrollTop(), 284 position: 'absolute' 285 }); 286 } 287 if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { 288 mfp.bgOverlay.css({ 289 height: _document.height(), 290 position: 'absolute' 291 }); 292 } 293 294 295 296 if(mfp.st.enableEscapeKey) { 297 // Close on ESC key 298 _document.on('keyup' + EVENT_NS, function(e) { 299 if(e.keyCode === 27) { 300 mfp.close(); 301 } 302 }); 303 } 304 305 _window.on('resize' + EVENT_NS, function() { 306 mfp.updateSize(); 307 }); 308 309 310 if(!mfp.st.closeOnContentClick) { 311 _wrapClasses += ' mfp-auto-cursor'; 312 } 313 314 if(_wrapClasses) 315 mfp.wrap.addClass(_wrapClasses); 316 317 318 // this triggers recalculation of layout, so we get it once to not to trigger twice 319 var windowHeight = mfp.wH = _window.height(); 320 321 322 var windowStyles = {}; 323 324 if( mfp.fixedContentPos ) { 325 if(mfp._hasScrollBar(windowHeight)){ 326 var s = mfp._getScrollbarSize(); 327 if(s) { 328 windowStyles.marginRight = s; 329 } 330 } 331 } 332 333 if(mfp.fixedContentPos) { 334 if(!mfp.isIE7) { 335 windowStyles.overflow = 'hidden'; 336 } else { 337 // ie7 double-scroll bug 338 $('body, html').css('overflow', 'hidden'); 339 } 340 } 341 342 343 344 var classesToadd = mfp.st.mainClass; 345 if(mfp.isIE7) { 346 classesToadd += ' mfp-ie7'; 347 } 348 if(classesToadd) { 349 mfp._addClassToMFP( classesToadd ); 350 } 351 352 // add content 353 mfp.updateItemHTML(); 354 355 _mfpTrigger('BuildControls'); 356 357 // remove scrollbar, add margin e.t.c 358 $('html').css(windowStyles); 359 360 // add everything to DOM 361 mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) ); 362 363 // Save last focused element 364 mfp._lastFocusedEl = document.activeElement; 365 366 // Wait for next cycle to allow CSS transition 367 setTimeout(function() { 368 369 if(mfp.content) { 370 mfp._addClassToMFP(READY_CLASS); 371 mfp._setFocus(); 372 } else { 373 // if content is not defined (not loaded e.t.c) we add class only for BG 374 mfp.bgOverlay.addClass(READY_CLASS); 375 } 376 377 // Trap the focus in popup 378 _document.on('focusin' + EVENT_NS, mfp._onFocusIn); 379 380 }, 16); 381 382 mfp.isOpen = true; 383 mfp.updateSize(windowHeight); 384 _mfpTrigger(OPEN_EVENT); 385 386 return data; 387 }, 388 389 /** 390 * Closes the popup 391 */ 392 close: function() { 393 if(!mfp.isOpen) return; 394 _mfpTrigger(BEFORE_CLOSE_EVENT); 395 396 mfp.isOpen = false; 397 // for CSS3 animation 398 if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) { 399 mfp._addClassToMFP(REMOVING_CLASS); 400 setTimeout(function() { 401 mfp._close(); 402 }, mfp.st.removalDelay); 403 } else { 404 mfp._close(); 405 } 406 }, 407 408 /** 409 * Helper for close() function 410 */ 411 _close: function() { 412 _mfpTrigger(CLOSE_EVENT); 413 414 var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' '; 415 416 mfp.bgOverlay.detach(); 417 mfp.wrap.detach(); 418 mfp.container.empty(); 419 420 if(mfp.st.mainClass) { 421 classesToRemove += mfp.st.mainClass + ' '; 422 } 423 424 mfp._removeClassFromMFP(classesToRemove); 425 426 if(mfp.fixedContentPos) { 427 var windowStyles = {marginRight: ''}; 428 if(mfp.isIE7) { 429 $('body, html').css('overflow', ''); 430 } else { 431 windowStyles.overflow = ''; 432 } 433 $('html').css(windowStyles); 434 } 435 436 _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS); 437 mfp.ev.off(EVENT_NS); 438 439 // clean up DOM elements that aren't removed 440 mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style'); 441 mfp.bgOverlay.attr('class', 'mfp-bg'); 442 mfp.container.attr('class', 'mfp-container'); 443 444 // remove close button from target element 445 if(mfp.st.showCloseBtn && 446 (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) { 447 if(mfp.currTemplate.closeBtn) 448 mfp.currTemplate.closeBtn.detach(); 449 } 450 451 452 if(mfp.st.autoFocusLast && mfp._lastFocusedEl) { 453 $(mfp._lastFocusedEl).trigger('focus'); // put tab focus back 454 } 455 mfp.currItem = null; 456 mfp.content = null; 457 mfp.currTemplate = null; 458 mfp.prevHeight = 0; 459 460 _mfpTrigger(AFTER_CLOSE_EVENT); 461 }, 462 463 updateSize: function(winHeight) { 464 465 if(mfp.isIOS) { 466 // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2 467 var zoomLevel = document.documentElement.clientWidth / window.innerWidth; 468 var height = window.innerHeight * zoomLevel; 469 mfp.wrap.css('height', height); 470 mfp.wH = height; 471 } else { 472 mfp.wH = winHeight || _window.height(); 473 } 474 // Fixes #84: popup incorrectly positioned with position:relative on body 475 if(!mfp.fixedContentPos) { 476 mfp.wrap.css('height', mfp.wH); 477 } 478 479 _mfpTrigger('Resize'); 480 481 }, 482 483 /** 484 * Set content of popup based on current index 485 */ 486 updateItemHTML: function() { 487 var item = mfp.items[mfp.index]; 488 489 // Detach and perform modifications 490 mfp.contentContainer.detach(); 491 492 if(mfp.content) 493 mfp.content.detach(); 494 495 if(!item.parsed) { 496 item = mfp.parseEl( mfp.index ); 497 } 498 499 var type = item.type; 500 501 _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]); 502 // BeforeChange event works like so: 503 // _mfpOn('BeforeChange', function(e, prevType, newType) { }); 504 505 mfp.currItem = item; 506 507 if(!mfp.currTemplate[type]) { 508 var markup = mfp.st[type] ? mfp.st[type].markup : false; 509 510 // allows to modify markup 511 _mfpTrigger('FirstMarkupParse', markup); 512 513 if(markup) { 514 mfp.currTemplate[type] = $(markup); 515 } else { 516 // if there is no markup found we just define that template is parsed 517 mfp.currTemplate[type] = true; 518 } 519 } 520 521 if(_prevContentType && _prevContentType !== item.type) { 522 mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); 523 } 524 525 var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); 526 mfp.appendContent(newContent, type); 527 528 item.preloaded = true; 529 530 _mfpTrigger(CHANGE_EVENT, item); 531 _prevContentType = item.type; 532 533 // Append container back after its content changed 534 mfp.container.prepend(mfp.contentContainer); 535 536 _mfpTrigger('AfterChange'); 537 }, 538 539 540 /** 541 * Set HTML content of popup 542 */ 543 appendContent: function(newContent, type) { 544 mfp.content = newContent; 545 546 if(newContent) { 547 if(mfp.st.showCloseBtn && mfp.st.closeBtnInside && 548 mfp.currTemplate[type] === true) { 549 // if there is no markup, we just append close button element inside 550 if(!mfp.content.find('.mfp-close').length) { 551 mfp.content.append(_getCloseBtn()); 552 } 553 } else { 554 mfp.content = newContent; 555 } 556 } else { 557 mfp.content = ''; 558 } 559 560 _mfpTrigger(BEFORE_APPEND_EVENT); 561 mfp.container.addClass('mfp-'+type+'-holder'); 562 563 mfp.contentContainer.append(mfp.content); 564 }, 565 566 567 /** 568 * Creates Magnific Popup data object based on given data 569 * @param {int} index Index of item to parse 570 */ 571 parseEl: function(index) { 572 var item = mfp.items[index], 573 type; 574 575 if(item.tagName) { 576 item = { el: $(item) }; 577 } else { 578 type = item.type; 579 item = { data: item, src: item.src }; 580 } 581 582 if(item.el) { 583 var types = mfp.types; 584 585 // check for 'mfp-TYPE' class 586 for(var i = 0; i < types.length; i++) { 587 if( item.el.hasClass('mfp-'+types[i]) ) { 588 type = types[i]; 589 break; 590 } 591 } 592 593 item.src = item.el.attr('data-mfp-src'); 594 if(!item.src) { 595 item.src = item.el.attr('href'); 596 } 597 } 598 599 item.type = type || mfp.st.type || 'inline'; 600 item.index = index; 601 item.parsed = true; 602 mfp.items[index] = item; 603 _mfpTrigger('ElementParse', item); 604 605 return mfp.items[index]; 606 }, 607 608 609 /** 610 * Initializes single popup or a group of popups 611 */ 612 addGroup: function(el, options) { 613 var eHandler = function(e) { 614 e.mfpEl = this; 615 mfp._openClick(e, el, options); 616 }; 617 618 if(!options) { 619 options = {}; 620 } 621 622 var eName = 'click.magnificPopup'; 623 options.mainEl = el; 624 625 if(options.items) { 626 options.isObj = true; 627 el.off(eName).on(eName, eHandler); 628 } else { 629 options.isObj = false; 630 if(options.delegate) { 631 el.off(eName).on(eName, options.delegate , eHandler); 632 } else { 633 options.items = el; 634 el.off(eName).on(eName, eHandler); 635 } 636 } 637 }, 638 _openClick: function(e, el, options) { 639 var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; 640 641 642 if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) { 643 return; 644 } 645 646 var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; 647 648 if(disableOn) { 649 if(typeof disableOn === "function") { 650 if( !disableOn.call(mfp) ) { 651 return true; 652 } 653 } else { // else it's number 654 if( _window.width() < disableOn ) { 655 return true; 656 } 657 } 658 } 659 660 if(e.type) { 661 e.preventDefault(); 662 663 // This will prevent popup from closing if element is inside and popup is already opened 664 if(mfp.isOpen) { 665 e.stopPropagation(); 666 } 667 } 668 669 options.el = $(e.mfpEl); 670 if(options.delegate) { 671 options.items = el.find(options.delegate); 672 } 673 mfp.open(options); 674 }, 675 676 677 /** 678 * Updates text on preloader 679 */ 680 updateStatus: function(status, text) { 681 682 if(mfp.preloader) { 683 if(_prevStatus !== status) { 684 mfp.container.removeClass('mfp-s-'+_prevStatus); 685 } 686 687 if(!text && status === 'loading') { 688 text = mfp.st.tLoading; 689 } 690 691 var data = { 692 status: status, 693 text: text 694 }; 695 // allows to modify status 696 _mfpTrigger('UpdateStatus', data); 697 698 status = data.status; 699 text = data.text; 700 701 if (mfp.st.allowHTMLInStatusIndicator) { 702 mfp.preloader.html(text); 703 } else { 704 mfp.preloader.text(text); 705 } 706 707 mfp.preloader.find('a').on('click', function(e) { 708 e.stopImmediatePropagation(); 709 }); 710 711 mfp.container.addClass('mfp-s-'+status); 712 _prevStatus = status; 713 } 714 }, 715 716 717 /* 718 "Private" helpers that aren't private at all 719 */ 720 // Check to close popup or not 721 // "target" is an element that was clicked 722 _checkIfClose: function(target) { 723 724 if($(target).closest('.' + PREVENT_CLOSE_CLASS).length) { 725 return; 726 } 727 728 var closeOnContent = mfp.st.closeOnContentClick; 729 var closeOnBg = mfp.st.closeOnBgClick; 730 731 if(closeOnContent && closeOnBg) { 732 return true; 733 } else { 734 735 // We close the popup if click is on close button or on preloader. Or if there is no content. 736 if(!mfp.content || $(target).closest('.mfp-close').length || (mfp.preloader && target === mfp.preloader[0]) ) { 737 return true; 738 } 739 740 // if click is outside the content 741 if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { 742 if(closeOnBg) { 743 // last check, if the clicked element is in DOM, (in case it's removed onclick) 744 if( $.contains(document, target) ) { 745 return true; 746 } 747 } 748 } else if(closeOnContent) { 749 return true; 750 } 751 752 } 753 return false; 754 }, 755 _addClassToMFP: function(cName) { 756 mfp.bgOverlay.addClass(cName); 757 mfp.wrap.addClass(cName); 758 }, 759 _removeClassFromMFP: function(cName) { 760 this.bgOverlay.removeClass(cName); 761 mfp.wrap.removeClass(cName); 762 }, 763 _hasScrollBar: function(winHeight) { 764 return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) ); 765 }, 766 _setFocus: function() { 767 (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).trigger('focus'); 768 }, 769 _onFocusIn: function(e) { 770 if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { 771 mfp._setFocus(); 772 return false; 773 } 774 }, 775 _parseMarkup: function(template, values, item) { 776 var arr; 777 if(item.data) { 778 values = $.extend(item.data, values); 779 } 780 _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); 781 782 $.each(values, function(key, value) { 783 if(value === undefined || value === false) { 784 return true; 785 } 786 arr = key.split('_'); 787 if(arr.length > 1) { 788 var el = template.find(EVENT_NS + '-'+arr[0]); 789 790 if(el.length > 0) { 791 var attr = arr[1]; 792 if(attr === 'replaceWith') { 793 if(el[0] !== value[0]) { 794 el.replaceWith(value); 795 } 796 } else if(attr === 'img') { 797 if(el.is('img')) { 798 el.attr('src', value); 799 } else { 800 el.replaceWith( $('<img>').attr('src', value).attr('class', el.attr('class')) ); 801 } 802 } else { 803 el.attr(arr[1], value); 804 } 805 } 806 807 } else { 808 if (mfp.st.allowHTMLInTemplate) { 809 template.find(EVENT_NS + '-'+key).html(value); 810 } else { 811 template.find(EVENT_NS + '-'+key).text(value); 812 } 813 } 814 }); 815 }, 816 817 _getScrollbarSize: function() { 818 // thx David 819 if(mfp.scrollbarSize === undefined) { 820 var scrollDiv = document.createElement("div"); 821 scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; 822 document.body.appendChild(scrollDiv); 823 mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; 824 document.body.removeChild(scrollDiv); 825 } 826 return mfp.scrollbarSize; 827 } 828 829}; /* MagnificPopup core prototype end */ 830 831 832 833 834/** 835 * Public static functions 836 */ 837$.magnificPopup = { 838 instance: null, 839 proto: MagnificPopup.prototype, 840 modules: [], 841 842 open: function(options, index) { 843 _checkInstance(); 844 845 if(!options) { 846 options = {}; 847 } else { 848 options = $.extend(true, {}, options); 849 } 850 851 options.isObj = true; 852 options.index = index || 0; 853 return this.instance.open(options); 854 }, 855 856 close: function() { 857 return $.magnificPopup.instance && $.magnificPopup.instance.close(); 858 }, 859 860 registerModule: function(name, module) { 861 if(module.options) { 862 $.magnificPopup.defaults[name] = module.options; 863 } 864 $.extend(this.proto, module.proto); 865 this.modules.push(name); 866 }, 867 868 defaults: { 869 870 // Info about options is in docs: 871 // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options 872 873 disableOn: 0, 874 875 key: null, 876 877 midClick: false, 878 879 mainClass: '', 880 881 preloader: true, 882 883 focus: '', // CSS selector of input to focus after popup is opened 884 885 closeOnContentClick: false, 886 887 closeOnBgClick: true, 888 889 closeBtnInside: true, 890 891 showCloseBtn: true, 892 893 enableEscapeKey: true, 894 895 modal: false, 896 897 alignTop: false, 898 899 removalDelay: 0, 900 901 prependTo: null, 902 903 fixedContentPos: 'auto', 904 905 fixedBgPos: 'auto', 906 907 overflowY: 'auto', 908 909 closeMarkup: '<button title="%title%" type="button" class="mfp-close" aria-label="%title%"><span aria-hidden="true">×</span></button>', 910 911 tClose: 'Close (Esc)', 912 913 tLoading: 'Loading...', 914 915 autoFocusLast: true, 916 917 allowHTMLInStatusIndicator: false, 918 919 allowHTMLInTemplate: false 920 921 } 922}; 923 924 925 926$.fn.magnificPopup = function(options) { 927 _checkInstance(); 928 929 var jqEl = $(this); 930 931 // We call some API method of first param is a string 932 if (typeof options === "string" ) { 933 934 if(options === 'open') { 935 var items, 936 itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup, 937 index = parseInt(arguments[1], 10) || 0; 938 939 if(itemOpts.items) { 940 items = itemOpts.items[index]; 941 } else { 942 items = jqEl; 943 if(itemOpts.delegate) { 944 items = items.find(itemOpts.delegate); 945 } 946 items = items.eq( index ); 947 } 948 mfp._openClick({mfpEl:items}, jqEl, itemOpts); 949 } else { 950 if(mfp.isOpen) 951 mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1)); 952 } 953 954 } else { 955 // clone options obj 956 options = $.extend(true, {}, options); 957 958 /* 959 * As Zepto doesn't support .data() method for objects 960 * and it works only in normal browsers 961 * we assign "options" object directly to the DOM element. FTW! 962 */ 963 if(_isJQ) { 964 jqEl.data('magnificPopup', options); 965 } else { 966 jqEl[0].magnificPopup = options; 967 } 968 969 mfp.addGroup(jqEl, options); 970 971 } 972 return jqEl; 973}; 974 975/*>>core*/ 976 977/*>>inline*/ 978 979var INLINE_NS = 'inline', 980 _hiddenClass, 981 _inlinePlaceholder, 982 _lastInlineElement, 983 _putInlineElementsBack = function() { 984 if(_lastInlineElement) { 985 _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach(); 986 _lastInlineElement = null; 987 } 988 }; 989 990$.magnificPopup.registerModule(INLINE_NS, { 991 options: { 992 hiddenClass: 'hide', // will be appended with `mfp-` prefix 993 markup: '', 994 tNotFound: 'Content not found' 995 }, 996 proto: { 997 998 initInline: function() { 999 mfp.types.push(INLINE_NS); 1000 1001 _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { 1002 _putInlineElementsBack(); 1003 }); 1004 }, 1005 1006 getInline: function(item, template) { 1007 1008 _putInlineElementsBack(); 1009 1010 if(item.src) { 1011 var inlineSt = mfp.st.inline, 1012 el = $(item.src); 1013 1014 if(el.length) { 1015 1016 // If target element has parent - we replace it with placeholder and put it back after popup is closed 1017 var parent = el[0].parentNode; 1018 if(parent && parent.tagName) { 1019 if(!_inlinePlaceholder) { 1020 _hiddenClass = inlineSt.hiddenClass; 1021 _inlinePlaceholder = _getEl(_hiddenClass); 1022 _hiddenClass = 'mfp-'+_hiddenClass; 1023 } 1024 // replace target inline element with placeholder 1025 _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass); 1026 } 1027 1028 mfp.updateStatus('ready'); 1029 } else { 1030 mfp.updateStatus('error', inlineSt.tNotFound); 1031 el = $('<div>'); 1032 } 1033 1034 item.inlineElement = el; 1035 return el; 1036 } 1037 1038 mfp.updateStatus('ready'); 1039 mfp._parseMarkup(template, {}, item); 1040 return template; 1041 } 1042 } 1043}); 1044 1045/*>>inline*/ 1046 1047/*>>ajax*/ 1048var AJAX_NS = 'ajax', 1049 _ajaxCur, 1050 _removeAjaxCursor = function() { 1051 if(_ajaxCur) { 1052 $(document.body).removeClass(_ajaxCur); 1053 } 1054 }, 1055 _destroyAjaxRequest = function() { 1056 _removeAjaxCursor(); 1057 if(mfp.req) { 1058 mfp.req.abort(); 1059 } 1060 }; 1061 1062$.magnificPopup.registerModule(AJAX_NS, { 1063 1064 options: { 1065 settings: null, 1066 cursor: 'mfp-ajax-cur', 1067 tError: 'The content could not be loaded.' 1068 }, 1069 1070 proto: { 1071 initAjax: function() { 1072 mfp.types.push(AJAX_NS); 1073 _ajaxCur = mfp.st.ajax.cursor; 1074 1075 _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest); 1076 _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest); 1077 }, 1078 getAjax: function(item) { 1079 1080 if(_ajaxCur) { 1081 $(document.body).addClass(_ajaxCur); 1082 } 1083 1084 mfp.updateStatus('loading'); 1085 1086 var opts = $.extend({ 1087 url: item.src, 1088 success: function(data, textStatus, jqXHR) { 1089 var temp = { 1090 data:data, 1091 xhr:jqXHR 1092 }; 1093 1094 _mfpTrigger('ParseAjax', temp); 1095 1096 mfp.appendContent( $(temp.data), AJAX_NS ); 1097 1098 item.finished = true; 1099 1100 _removeAjaxCursor(); 1101 1102 mfp._setFocus(); 1103 1104 setTimeout(function() { 1105 mfp.wrap.addClass(READY_CLASS); 1106 }, 16); 1107 1108 mfp.updateStatus('ready'); 1109 1110 _mfpTrigger('AjaxContentAdded'); 1111 }, 1112 error: function() { 1113 _removeAjaxCursor(); 1114 item.finished = item.loadError = true; 1115 mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); 1116 } 1117 }, mfp.st.ajax.settings); 1118 1119 mfp.req = $.ajax(opts); 1120 1121 return ''; 1122 } 1123 } 1124}); 1125 1126/*>>ajax*/ 1127 1128/*>>image*/ 1129var _imgInterval, 1130 _getTitle = function(item) { 1131 if(item.data && item.data.title !== undefined) 1132 return item.data.title; 1133 1134 var src = mfp.st.image.titleSrc; 1135 1136 if(src) { 1137 if(typeof src === "function") { 1138 return src.call(mfp, item); 1139 } else if(item.el) { 1140 return item.el.attr(src) || ''; 1141 } 1142 } 1143 return ''; 1144 }; 1145 1146$.magnificPopup.registerModule('image', { 1147 1148 options: { 1149 markup: '<div class="mfp-figure">'+ 1150 '<div class="mfp-close"></div>'+ 1151 '<figure>'+ 1152 '<div class="mfp-img"></div>'+ 1153 '<figcaption>'+ 1154 '<div class="mfp-bottom-bar">'+ 1155 '<div class="mfp-title"></div>'+ 1156 '<div class="mfp-counter"></div>'+ 1157 '</div>'+ 1158 '</figcaption>'+ 1159 '</figure>'+ 1160 '</div>', 1161 cursor: 'mfp-zoom-out-cur', 1162 titleSrc: 'title', 1163 verticalFit: true, 1164 tError: 'The image could not be loaded.' 1165 }, 1166 1167 proto: { 1168 initImage: function() { 1169 var imgSt = mfp.st.image, 1170 ns = '.image'; 1171 1172 mfp.types.push('image'); 1173 1174 _mfpOn(OPEN_EVENT+ns, function() { 1175 if(mfp.currItem.type === 'image' && imgSt.cursor) { 1176 $(document.body).addClass(imgSt.cursor); 1177 } 1178 }); 1179 1180 _mfpOn(CLOSE_EVENT+ns, function() { 1181 if(imgSt.cursor) { 1182 $(document.body).removeClass(imgSt.cursor); 1183 } 1184 _window.off('resize' + EVENT_NS); 1185 }); 1186 1187 _mfpOn('Resize'+ns, mfp.resizeImage); 1188 if(mfp.isLowIE) { 1189 _mfpOn('AfterChange', mfp.resizeImage); 1190 } 1191 }, 1192 resizeImage: function() { 1193 var item = mfp.currItem; 1194 if(!item || !item.img) return; 1195 1196 if(mfp.st.image.verticalFit) { 1197 var decr = 0; 1198 // fix box-sizing in ie7/8 1199 if(mfp.isLowIE) { 1200 decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10); 1201 } 1202 item.img.css('max-height', mfp.wH-decr); 1203 } 1204 }, 1205 _onImageHasSize: function(item) { 1206 if(item.img) { 1207 1208 item.hasSize = true; 1209 1210 if(_imgInterval) { 1211 clearInterval(_imgInterval); 1212 } 1213 1214 item.isCheckingImgSize = false; 1215 1216 _mfpTrigger('ImageHasSize', item); 1217 1218 if(item.imgHidden) { 1219 if(mfp.content) 1220 mfp.content.removeClass('mfp-loading'); 1221 1222 item.imgHidden = false; 1223 } 1224 1225 } 1226 }, 1227 1228 /** 1229 * Function that loops until the image has size to display elements that rely on it asap 1230 */ 1231 findImageSize: function(item) { 1232 1233 var counter = 0, 1234 img = item.img[0], 1235 mfpSetInterval = function(delay) { 1236 1237 if(_imgInterval) { 1238 clearInterval(_imgInterval); 1239 } 1240 // decelerating interval that checks for size of an image 1241 _imgInterval = setInterval(function() { 1242 if(img.naturalWidth > 0) { 1243 mfp._onImageHasSize(item); 1244 return; 1245 } 1246 1247 if(counter > 200) { 1248 clearInterval(_imgInterval); 1249 } 1250 1251 counter++; 1252 if(counter === 3) { 1253 mfpSetInterval(10); 1254 } else if(counter === 40) { 1255 mfpSetInterval(50); 1256 } else if(counter === 100) { 1257 mfpSetInterval(500); 1258 } 1259 }, delay); 1260 }; 1261 1262 mfpSetInterval(1); 1263 }, 1264 1265 getImage: function(item, template) { 1266 1267 var guard = 0, 1268 1269 imgSt = mfp.st.image, 1270 1271 // image error handler 1272 onLoadError = function() { 1273 if(item) { 1274 item.img.off('.mfploader'); 1275 if(item === mfp.currItem){ 1276 mfp._onImageHasSize(item); 1277 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 1278 } 1279 1280 item.hasSize = true; 1281 item.loaded = true; 1282 item.loadError = true; 1283 } 1284 }, 1285 1286 // image load complete handler 1287 onLoadComplete = function() { 1288 if(item) { 1289 if (item.img[0].complete) { 1290 item.img.off('.mfploader'); 1291 1292 if(item === mfp.currItem){ 1293 mfp._onImageHasSize(item); 1294 1295 mfp.updateStatus('ready'); 1296 } 1297 1298 item.hasSize = true; 1299 item.loaded = true; 1300 1301 _mfpTrigger('ImageLoadComplete'); 1302 1303 } 1304 else { 1305 // if image complete check fails 200 times (20 sec), we assume that there was an error. 1306 guard++; 1307 if(guard < 200) { 1308 setTimeout(onLoadComplete,100); 1309 } else { 1310 onLoadError(); 1311 } 1312 } 1313 } 1314 }; 1315 1316 1317 1318 var el = template.find('.mfp-img'); 1319 if(el.length) { 1320 var img = document.createElement('img'); 1321 img.className = 'mfp-img'; 1322 if(item.el && item.el.find('img').length) { 1323 img.alt = item.el.find('img').attr('alt'); 1324 } 1325 item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError); 1326 img.src = item.src; 1327 1328 // without clone() "error" event is not firing when IMG is replaced by new IMG 1329 // TODO: find a way to avoid such cloning 1330 if(el.is('img')) { 1331 item.img = item.img.clone(); 1332 } 1333 1334 img = item.img[0]; 1335 if(img.naturalWidth > 0) { 1336 item.hasSize = true; 1337 } else if(!img.width) { 1338 item.hasSize = false; 1339 } 1340 } 1341 1342 mfp._parseMarkup(template, { 1343 title: _getTitle(item), 1344 img_replaceWith: item.img 1345 }, item); 1346 1347 mfp.resizeImage(); 1348 1349 if(item.hasSize) { 1350 if(_imgInterval) clearInterval(_imgInterval); 1351 1352 if(item.loadError) { 1353 template.addClass('mfp-loading'); 1354 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 1355 } else { 1356 template.removeClass('mfp-loading'); 1357 mfp.updateStatus('ready'); 1358 } 1359 return template; 1360 } 1361 1362 mfp.updateStatus('loading'); 1363 item.loading = true; 1364 1365 if(!item.hasSize) { 1366 item.imgHidden = true; 1367 template.addClass('mfp-loading'); 1368 mfp.findImageSize(item); 1369 } 1370 1371 return template; 1372 } 1373 } 1374}); 1375 1376/*>>image*/ 1377 1378/*>>zoom*/ 1379var hasMozTransform, 1380 getHasMozTransform = function() { 1381 if(hasMozTransform === undefined) { 1382 hasMozTransform = document.createElement('p').style.MozTransform !== undefined; 1383 } 1384 return hasMozTransform; 1385 }; 1386 1387$.magnificPopup.registerModule('zoom', { 1388 1389 options: { 1390 enabled: false, 1391 easing: 'ease-in-out', 1392 duration: 300, 1393 opener: function(element) { 1394 return element.is('img') ? element : element.find('img'); 1395 } 1396 }, 1397 1398 proto: { 1399 1400 initZoom: function() { 1401 var zoomSt = mfp.st.zoom, 1402 ns = '.zoom', 1403 image; 1404 1405 if(!zoomSt.enabled || !mfp.supportsTransition) { 1406 return; 1407 } 1408 1409 var duration = zoomSt.duration, 1410 getElToAnimate = function(image) { 1411 var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'), 1412 transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing, 1413 cssObj = { 1414 position: 'fixed', 1415 zIndex: 9999, 1416 left: 0, 1417 top: 0, 1418 '-webkit-backface-visibility': 'hidden' 1419 }, 1420 t = 'transition'; 1421 1422 cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition; 1423 1424 newImg.css(cssObj); 1425 return newImg; 1426 }, 1427 showMainContent = function() { 1428 mfp.content.css('visibility', 'visible'); 1429 }, 1430 openTimeout, 1431 animatedImg; 1432 1433 _mfpOn('BuildControls'+ns, function() { 1434 if(mfp._allowZoom()) { 1435 1436 clearTimeout(openTimeout); 1437 mfp.content.css('visibility', 'hidden'); 1438 1439 // Basically, all code below does is clones existing image, puts in on top of the current one and animated it 1440 1441 image = mfp._getItemToZoom(); 1442 1443 if(!image) { 1444 showMainContent(); 1445 return; 1446 } 1447 1448 animatedImg = getElToAnimate(image); 1449 1450 animatedImg.css( mfp._getOffset() ); 1451 1452 mfp.wrap.append(animatedImg); 1453 1454 openTimeout = setTimeout(function() { 1455 animatedImg.css( mfp._getOffset( true ) ); 1456 openTimeout = setTimeout(function() { 1457 1458 showMainContent(); 1459 1460 setTimeout(function() { 1461 animatedImg.remove(); 1462 image = animatedImg = null; 1463 _mfpTrigger('ZoomAnimationEnded'); 1464 }, 16); // avoid blink when switching images 1465 1466 }, duration); // this timeout equals animation duration 1467 1468 }, 16); // by adding this timeout we avoid short glitch at the beginning of animation 1469 1470 1471 // Lots of timeouts... 1472 } 1473 }); 1474 _mfpOn(BEFORE_CLOSE_EVENT+ns, function() { 1475 if(mfp._allowZoom()) { 1476 1477 clearTimeout(openTimeout); 1478 1479 mfp.st.removalDelay = duration; 1480 1481 if(!image) { 1482 image = mfp._getItemToZoom(); 1483 if(!image) { 1484 return; 1485 } 1486 animatedImg = getElToAnimate(image); 1487 } 1488 1489 animatedImg.css( mfp._getOffset(true) ); 1490 mfp.wrap.append(animatedImg); 1491 mfp.content.css('visibility', 'hidden'); 1492 1493 setTimeout(function() { 1494 animatedImg.css( mfp._getOffset() ); 1495 }, 16); 1496 } 1497 1498 }); 1499 1500 _mfpOn(CLOSE_EVENT+ns, function() { 1501 if(mfp._allowZoom()) { 1502 showMainContent(); 1503 if(animatedImg) { 1504 animatedImg.remove(); 1505 } 1506 image = null; 1507 } 1508 }); 1509 }, 1510 1511 _allowZoom: function() { 1512 return mfp.currItem.type === 'image'; 1513 }, 1514 1515 _getItemToZoom: function() { 1516 if(mfp.currItem.hasSize) { 1517 return mfp.currItem.img; 1518 } else { 1519 return false; 1520 } 1521 }, 1522 1523 // Get element postion relative to viewport 1524 _getOffset: function(isLarge) { 1525 var el; 1526 if(isLarge) { 1527 el = mfp.currItem.img; 1528 } else { 1529 el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem); 1530 } 1531 1532 var offset = el.offset(); 1533 var paddingTop = parseInt(el.css('padding-top'),10); 1534 var paddingBottom = parseInt(el.css('padding-bottom'),10); 1535 offset.top -= ( $(window).scrollTop() - paddingTop ); 1536 1537 1538 /* 1539 1540 Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa. 1541 1542 */ 1543 var obj = { 1544 width: el.width(), 1545 // fix Zepto height+padding issue 1546 height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop 1547 }; 1548 1549 // I hate to do this, but there is no another option 1550 if( getHasMozTransform() ) { 1551 obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)'; 1552 } else { 1553 obj.left = offset.left; 1554 obj.top = offset.top; 1555 } 1556 return obj; 1557 } 1558 1559 } 1560}); 1561 1562 1563 1564/*>>zoom*/ 1565 1566/*>>iframe*/ 1567 1568var IFRAME_NS = 'iframe', 1569 _emptyPage = '//about:blank', 1570 1571 _fixIframeBugs = function(isShowing) { 1572 if(mfp.currTemplate[IFRAME_NS]) { 1573 var el = mfp.currTemplate[IFRAME_NS].find('iframe'); 1574 if(el.length) { 1575 // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug 1576 if(!isShowing) { 1577 el[0].src = _emptyPage; 1578 } 1579 1580 // IE8 black screen bug fix 1581 if(mfp.isIE8) { 1582 el.css('display', isShowing ? 'block' : 'none'); 1583 } 1584 } 1585 } 1586 }; 1587 1588$.magnificPopup.registerModule(IFRAME_NS, { 1589 1590 options: { 1591 markup: '<div class="mfp-iframe-scaler">'+ 1592 '<div class="mfp-close"></div>'+ 1593 '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+ 1594 '</div>', 1595 1596 srcAction: 'iframe_src', 1597 1598 // we don't care and support only one default type of URL by default 1599 patterns: { 1600 youtube: { 1601 index: 'youtube.com', 1602 id: 'v=', 1603 src: '//www.youtube.com/embed/%id%?autoplay=1' 1604 }, 1605 youtu_be: { 1606 index: 'youtu.be', 1607 id: '/', 1608 src: '//www.youtube.com/embed/%id%?autoplay=1', 1609 }, 1610 youtube_nocookie: { 1611 index: 'youtube-nocookie.com', 1612 id: '/', 1613 src: '//www.youtube-nocookie.com/embed/%id%?autoplay=1', 1614 }, 1615 vimeo: { 1616 index: 'vimeo.com/', 1617 id: '/', 1618 src: '//player.vimeo.com/video/%id%?autoplay=1' 1619 }, 1620 gmaps: { 1621 index: '//maps.google.', 1622 src: '%id%&output=embed' 1623 } 1624 } 1625 }, 1626 1627 proto: { 1628 initIframe: function() { 1629 mfp.types.push(IFRAME_NS); 1630 1631 _mfpOn('BeforeChange', function(e, prevType, newType) { 1632 if(prevType !== newType) { 1633 if(prevType === IFRAME_NS) { 1634 _fixIframeBugs(); // iframe if removed 1635 } else if(newType === IFRAME_NS) { 1636 _fixIframeBugs(true); // iframe is showing 1637 } 1638 }// else { 1639 // iframe source is switched, don't do anything 1640 //} 1641 }); 1642 1643 _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { 1644 _fixIframeBugs(); 1645 }); 1646 }, 1647 1648 getIframe: function(item, template) { 1649 var embedSrc = item.src; 1650 var iframeSt = mfp.st.iframe; 1651 1652 $.each(iframeSt.patterns, function() { 1653 if(embedSrc.indexOf( this.index ) > -1) { 1654 if(this.id) { 1655 if(typeof this.id === 'string') { 1656 embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); 1657 } else { 1658 embedSrc = this.id.call( this, embedSrc ); 1659 } 1660 } 1661 embedSrc = this.src.replace('%id%', embedSrc ); 1662 return false; // break; 1663 } 1664 }); 1665 1666 var dataObj = {}; 1667 if(iframeSt.srcAction) { 1668 dataObj[iframeSt.srcAction] = embedSrc; 1669 } 1670 1671 mfp._parseMarkup(template, dataObj, item); 1672 1673 mfp.updateStatus('ready'); 1674 1675 return template; 1676 } 1677 } 1678}); 1679 1680 1681 1682/*>>iframe*/ 1683 1684/*>>gallery*/ 1685/** 1686 * Get looped index depending on number of slides 1687 */ 1688var _getLoopedId = function(index) { 1689 var numSlides = mfp.items.length; 1690 if(index > numSlides - 1) { 1691 return index - numSlides; 1692 } else if(index < 0) { 1693 return numSlides + index; 1694 } 1695 return index; 1696 }, 1697 _replaceCurrTotal = function(text, curr, total) { 1698 return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); 1699 }; 1700 1701$.magnificPopup.registerModule('gallery', { 1702 1703 options: { 1704 enabled: false, 1705 arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', 1706 preload: [0,2], 1707 navigateByImgClick: true, 1708 arrows: true, 1709 1710 tPrev: 'Previous (Left arrow key)', 1711 tNext: 'Next (Right arrow key)', 1712 tCounter: '%curr% of %total%', 1713 1714 langDir: null, 1715 loop: true, 1716 }, 1717 1718 proto: { 1719 initGallery: function() { 1720 1721 var gSt = mfp.st.gallery, 1722 ns = '.mfp-gallery'; 1723 1724 mfp.direction = true; // true - next, false - prev 1725 1726 if(!gSt || !gSt.enabled ) return false; 1727 1728 if (!gSt.langDir) { 1729 gSt.langDir = document.dir || 'ltr'; 1730 } 1731 1732 _wrapClasses += ' mfp-gallery'; 1733 1734 _mfpOn(OPEN_EVENT+ns, function() { 1735 1736 if(gSt.navigateByImgClick) { 1737 mfp.wrap.on('click'+ns, '.mfp-img', function() { 1738 if(mfp.items.length > 1) { 1739 mfp.next(); 1740 return false; 1741 } 1742 }); 1743 } 1744 1745 _document.on('keydown'+ns, function(e) { 1746 if (e.keyCode === 37) { 1747 if (gSt.langDir === 'rtl') mfp.next(); 1748 else mfp.prev(); 1749 } else if (e.keyCode === 39) { 1750 if (gSt.langDir === 'rtl') mfp.prev(); 1751 else mfp.next(); 1752 } 1753 }); 1754 1755 mfp.updateGalleryButtons(); 1756 1757 }); 1758 1759 _mfpOn('UpdateStatus'+ns, function(/*e, data*/) { 1760 mfp.updateGalleryButtons(); 1761 }); 1762 1763 _mfpOn('UpdateStatus'+ns, function(e, data) { 1764 if(data.text) { 1765 data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); 1766 } 1767 }); 1768 1769 _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { 1770 var l = mfp.items.length; 1771 values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; 1772 }); 1773 1774 _mfpOn('BuildControls' + ns, function() { 1775 if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { 1776 1777 var arrowLeftDesc, arrowRightDesc, arrowLeftAction, arrowRightAction; 1778 1779 if (gSt.langDir === 'rtl') { 1780 arrowLeftDesc = gSt.tNext; 1781 arrowRightDesc = gSt.tPrev; 1782 arrowLeftAction = 'next'; 1783 arrowRightAction = 'prev'; 1784 } else { 1785 arrowLeftDesc = gSt.tPrev; 1786 arrowRightDesc = gSt.tNext; 1787 arrowLeftAction = 'prev'; 1788 arrowRightAction = 'next'; 1789 } 1790 1791 var markup = gSt.arrowMarkup, 1792 arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, arrowLeftDesc) 1793 .replace(/%action%/gi, arrowLeftAction) 1794 .replace(/%dir%/gi, 'left') ) 1795 .attr('aria-label', arrowLeftDesc) 1796 .addClass(PREVENT_CLOSE_CLASS), 1797 arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, arrowRightDesc) 1798 .replace(/%action%/gi, arrowRightAction) 1799 .replace(/%dir%/gi, 'right') ) 1800 .attr('aria-label', arrowRightDesc) 1801 .addClass(PREVENT_CLOSE_CLASS); 1802 1803 if (gSt.langDir === 'rtl') { 1804 mfp.arrowNext = arrowLeft; 1805 mfp.arrowPrev = arrowRight; 1806 } else { 1807 mfp.arrowNext = arrowRight; 1808 mfp.arrowPrev = arrowLeft; 1809 } 1810 1811 arrowLeft.on('click', function() { 1812 if (gSt.langDir === 'rtl') mfp.next(); 1813 else mfp.prev(); 1814 }); 1815 arrowRight.on('click', function() { 1816 if (gSt.langDir === 'rtl') mfp.prev(); 1817 else mfp.next(); 1818 }); 1819 1820 mfp.container.append(arrowLeft.add(arrowRight)); 1821 mfp.container 1822 .attr('role', 'region') 1823 .attr('aria-label', 'carousel'); 1824 } 1825 }); 1826 1827 _mfpOn(CHANGE_EVENT+ns, function() { 1828 if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); 1829 1830 mfp._preloadTimeout = setTimeout(function() { 1831 mfp.preloadNearbyImages(); 1832 mfp._preloadTimeout = null; 1833 }, 16); 1834 }); 1835 1836 1837 _mfpOn(CLOSE_EVENT+ns, function() { 1838 _document.off(ns); 1839 mfp.wrap.off('click'+ns); 1840 mfp.arrowRight = mfp.arrowLeft = null; 1841 }); 1842 1843 }, 1844 next: function() { 1845 var newIndex = _getLoopedId(mfp.index + 1); 1846 if (!mfp.st.gallery.loop && newIndex === 0 ) return false; 1847 mfp.direction = true; 1848 mfp.index = newIndex; 1849 mfp.updateItemHTML(); 1850 }, 1851 prev: function() { 1852 var newIndex = mfp.index - 1; 1853 if (!mfp.st.gallery.loop && newIndex < 0) return false; 1854 mfp.direction = false; 1855 mfp.index = _getLoopedId(newIndex); 1856 mfp.updateItemHTML(); 1857 }, 1858 goTo: function(newIndex) { 1859 mfp.direction = (newIndex >= mfp.index); 1860 mfp.index = newIndex; 1861 mfp.updateItemHTML(); 1862 }, 1863 preloadNearbyImages: function() { 1864 var p = mfp.st.gallery.preload, 1865 preloadBefore = Math.min(p[0], mfp.items.length), 1866 preloadAfter = Math.min(p[1], mfp.items.length), 1867 i; 1868 1869 for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { 1870 mfp._preloadItem(mfp.index+i); 1871 } 1872 for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { 1873 mfp._preloadItem(mfp.index-i); 1874 } 1875 }, 1876 _preloadItem: function(index) { 1877 index = _getLoopedId(index); 1878 1879 if(mfp.items[index].preloaded) { 1880 return; 1881 } 1882 1883 var item = mfp.items[index]; 1884 if(!item.parsed) { 1885 item = mfp.parseEl( index ); 1886 } 1887 1888 _mfpTrigger('LazyLoad', item); 1889 1890 if(item.type === 'image') { 1891 item.img = $('<img class="mfp-img" />').on('load.mfploader', function() { 1892 item.hasSize = true; 1893 }).on('error.mfploader', function() { 1894 item.hasSize = true; 1895 item.loadError = true; 1896 _mfpTrigger('LazyLoadError', item); 1897 }).attr('src', item.src); 1898 } 1899 1900 1901 item.preloaded = true; 1902 }, 1903 1904 /** 1905 * Show/hide the gallery prev/next buttons if we're at the start/end, if looping is turned off 1906 * Added by Joloco for Veg 1907 */ 1908 updateGalleryButtons: function() { 1909 1910 if ( !mfp.st.gallery.loop && typeof mfp.arrowPrev === 'object' && mfp.arrowPrev !== null) { 1911 1912 if (mfp.index === 0) mfp.arrowPrev.hide(); 1913 else mfp.arrowPrev.show(); 1914 1915 if (mfp.index === (mfp.items.length - 1)) mfp.arrowNext.hide(); 1916 else mfp.arrowNext.show(); 1917 1918 } 1919 1920 }, 1921 1922 } 1923 1924}); 1925 1926 1927/*>>gallery*/ 1928 1929/*>>retina*/ 1930 1931var RETINA_NS = 'retina'; 1932 1933$.magnificPopup.registerModule(RETINA_NS, { 1934 options: { 1935 replaceSrc: function(item) { 1936 return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); 1937 }, 1938 ratio: 1 // Function or number. Set to 1 to disable. 1939 }, 1940 proto: { 1941 initRetina: function() { 1942 if(window.devicePixelRatio > 1) { 1943 1944 var st = mfp.st.retina, 1945 ratio = st.ratio; 1946
1947 ratio = !isNaN(ratio) ? ratio : ratio(); 1948 1949 if(ratio > 1) { 1950 _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { 1951 item.img.css({ 1952 'max-width': item.img[0].naturalWidth / ratio, 1953 'width': '100%' 1954 }); 1955 }); 1956 _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { 1957 item.src = st.replaceSrc(item, ratio); 1958 }); 1959 } 1960 } 1961 1962 } 1963 } 1964}); 1965 1966/*>>retina*/ 1967 _checkInstance(); }));
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.