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