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