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