vendor: 37,823 bytes, lines 1-1711
1/*! Magnific Popup - v1.0.0 - 2015-01-03 2* //dimsemenov.com/plugins/magnific-popup/ 3* Copyright (c) 2015 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, //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.isIE7 = appVersion.indexOf("MSIE 7.") !== -1; 140 mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1; 141 mfp.isLowIE = mfp.isIE7 || mfp.isIE8; 142 mfp.isAndroid = (/android/gi).test(appVersion); 143 mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); 144 mfp.supportsTransition = supportsTransitions(); 145 146 // We disable fixed positioned lightbox on devices that don't handle it nicely. 147 // If you know a better way of detecting this - let me know. 148 mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); 149 _document = $(document); 150 151 mfp.popupsCache = {}; 152 }, 153 154 /** 155 * Opens popup 156 * @param data [description] 157 */ 158 open: function(data) { 159 160 var i; 161 162 if(data.isObj === false) { 163 // convert jQuery collection to array to avoid conflicts later 164 mfp.items = data.items.toArray(); 165 166 mfp.index = 0; 167 var items = data.items, 168 item; 169 for(i = 0; i < items.length; i++) { 170 item = items[i]; 171 if(item.parsed) { 172 item = item.el[0]; 173 } 174 if(item === data.el[0]) { 175 mfp.index = i; 176 break; 177 } 178 } 179 } else { 180 mfp.items = $.isArray(data.items) ? data.items : [data.items]; 181 mfp.index = data.index || 0; 182 } 183 184 // if popup is already opened - we just update the content 185 if(mfp.isOpen) { 186 mfp.updateItemHTML(); 187 return; 188 } 189 190 mfp.types = []; 191 _wrapClasses = ''; 192 if(data.mainEl && data.mainEl.length) { 193 mfp.ev = data.mainEl.eq(0); 194 } else { 195 mfp.ev = _document; 196 } 197 198 if(data.key) { 199 if(!mfp.popupsCache[data.key]) { 200 mfp.popupsCache[data.key] = {}; 201 } 202 mfp.currTemplate = mfp.popupsCache[data.key]; 203 } else { 204 mfp.currTemplate = {}; 205 } 206 207 208 209 mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 210 mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; 211 212 if(mfp.st.modal) { 213 mfp.st.closeOnContentClick = false; 214 mfp.st.closeOnBgClick = false; 215 mfp.st.showCloseBtn = false; 216 mfp.st.enableEscapeKey = false; 217 } 218 219 220 // Building markup 221 // main containers are created only once 222 if(!mfp.bgOverlay) { 223 224 // Dark overlay 225 mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { 226 mfp.close(); 227 }); 228 229 mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) { 230 if(mfp._checkIfClose(e.target)) { 231 mfp.close(); 232 } 233 }); 234 235 mfp.container = _getEl('container', mfp.wrap); 236 } 237 238 mfp.contentContainer = _getEl('content'); 239 if(mfp.st.preloader) { 240 mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); 241 } 242 243 244 // Initializing modules 245 var modules = $.magnificPopup.modules; 246 for(i = 0; i < modules.length; i++) { 247 var n = modules[i]; 248 n = n.charAt(0).toUpperCase() + n.slice(1); 249 mfp['init'+n].call(mfp); 250 } 251 _mfpTrigger('BeforeOpen'); 252 253 254 if(mfp.st.showCloseBtn) { 255 // Close button 256 if(!mfp.st.closeBtnInside) { 257 mfp.wrap.append( _getCloseBtn() ); 258 } else { 259 _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { 260 values.close_replaceWith = _getCloseBtn(item.type); 261 }); 262 _wrapClasses += ' mfp-close-btn-in'; 263 } 264 } 265 266 if(mfp.st.alignTop) { 267 _wrapClasses += ' mfp-align-top'; 268 } 269 270 271 272 if(mfp.fixedContentPos) { 273 mfp.wrap.css({ 274 overflow: mfp.st.overflowY, 275 overflowX: 'hidden', 276 overflowY: mfp.st.overflowY 277 }); 278 } else { 279 mfp.wrap.css({ 280 top: _window.scrollTop(), 281 position: 'absolute' 282 }); 283 } 284 if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { 285 mfp.bgOverlay.css({ 286 height: _document.height(), 287 position: 'absolute' 288 }); 289 } 290 291 292 293 if(mfp.st.enableEscapeKey) { 294 // Close on ESC key 295 _document.on('keyup' + EVENT_NS, function(e) { 296 if(e.keyCode === 27) { 297 mfp.close(); 298 } 299 }); 300 } 301 302 _window.on('resize' + EVENT_NS, function() { 303 mfp.updateSize(); 304 }); 305 306 307 if(!mfp.st.closeOnContentClick) { 308 _wrapClasses += ' mfp-auto-cursor'; 309 } 310 311 if(_wrapClasses) 312 mfp.wrap.addClass(_wrapClasses); 313 314 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._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 //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 504 505 506 507 if(!mfp.currTemplate[type]) { 508 var markup = mfp.st[type] ? mfp.st[type].markup : false; 509 510 // allows to modify markup 511 _mfpTrigger('FirstMarkupParse', markup); 512 513 if(markup) { 514 mfp.currTemplate[type] = $(markup); 515 } else { 516 // if there is no markup found we just define that template is parsed 517 mfp.currTemplate[type] = true; 518 } 519 } 520 521 if(_prevContentType && _prevContentType !== item.type) { 522 mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); 523 } 524 525 var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); 526 mfp.appendContent(newContent, type); 527 528 item.preloaded = true; 529 530 _mfpTrigger(CHANGE_EVENT, item); 531 _prevContentType = item.type; 532 533 // Append container back after its content changed 534 mfp.container.prepend(mfp.contentContainer); 535 536 _mfpTrigger('AfterChange'); 537 }, 538 539 540 /** 541 * Set HTML content of popup 542 */ 543 appendContent: function(newContent, type) { 544 mfp.content = newContent; 545 546 if(newContent) { 547 if(mfp.st.showCloseBtn && mfp.st.closeBtnInside && 548 mfp.currTemplate[type] === true) { 549 // if there is no markup, we just append close button element inside 550 if(!mfp.content.find('.mfp-close').length) { 551 mfp.content.append(_getCloseBtn()); 552 } 553 } else { 554 mfp.content = newContent; 555 } 556 } else { 557 mfp.content = ''; 558 } 559 560 _mfpTrigger(BEFORE_APPEND_EVENT); 561 mfp.container.addClass('mfp-'+type+'-holder'); 562 563 mfp.contentContainer.append(mfp.content); 564 }, 565 566 567 568 569 /** 570 * Creates Magnific Popup data object based on given data 571 * @param {int} index Index of item to parse 572 */ 573 parseEl: function(index) { 574 var item = mfp.items[index], 575 type; 576 577 if(item.tagName) { 578 item = { el: $(item) }; 579 } else { 580 type = item.type; 581 item = { data: item, src: item.src }; 582 } 583 584 if(item.el) { 585 var types = mfp.types; 586 587 // check for 'mfp-TYPE' class 588 for(var i = 0; i < types.length; i++) { 589 if( item.el.hasClass('mfp-'+types[i]) ) { 590 type = types[i]; 591 break; 592 } 593 } 594 595 item.src = item.el.attr('data-mfp-src'); 596 if(!item.src) { 597 item.src = item.el.attr('href'); 598 } 599 } 600 601 item.type = type || mfp.st.type || 'inline'; 602 item.index = index; 603 item.parsed = true; 604 mfp.items[index] = item; 605 _mfpTrigger('ElementParse', item); 606 607 return mfp.items[index]; 608 }, 609 610 611 /** 612 * Initializes single popup or a group of popups 613 */ 614 addGroup: function(el, options) { 615 var eHandler = function(e) { 616 e.mfpEl = this; 617 mfp._openClick(e, el, options); 618 }; 619 620 if(!options) { 621 options = {}; 622 } 623 624 var eName = 'click.magnificPopup'; 625 options.mainEl = el; 626 627 if(options.items) { 628 options.isObj = true; 629 el.off(eName).on(eName, eHandler); 630 } else { 631 options.isObj = false; 632 if(options.delegate) { 633 el.off(eName).on(eName, options.delegate , eHandler); 634 } else { 635 options.items = el; 636 el.off(eName).on(eName, eHandler); 637 } 638 } 639 }, 640 _openClick: function(e, el, options) { 641 var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; 642 643 644 if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) { 645 return; 646 } 647 648 var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; 649 650 if(disableOn) { 651 if($.isFunction(disableOn)) { 652 if( !disableOn.call(mfp) ) { 653 return true; 654 } 655 } else { // else it's number 656 if( _window.width() < disableOn ) { 657 return true; 658 } 659 } 660 } 661 662 if(e.type) { 663 e.preventDefault(); 664 665 // This will prevent popup from closing if element is inside and popup is already opened 666 if(mfp.isOpen) { 667 e.stopPropagation(); 668 } 669 } 670 671 672 options.el = $(e.mfpEl); 673 if(options.delegate) { 674 options.items = el.find(options.delegate); 675 } 676 mfp.open(options); 677 }, 678 679 680 /** 681 * Updates text on preloader 682 */ 683 updateStatus: function(status, text) { 684 685 if(mfp.preloader) { 686 if(_prevStatus !== status) { 687 mfp.container.removeClass('mfp-s-'+_prevStatus); 688 } 689 690 if(!text && status === 'loading') { 691 text = mfp.st.tLoading; 692 } 693 694 var data = { 695 status: status, 696 text: text 697 }; 698 // allows to modify status 699 _mfpTrigger('UpdateStatus', data); 700 701 status = data.status; 702 text = data.text; 703 704 mfp.preloader.html(text); 705 706 mfp.preloader.find('a').on('click', function(e) { 707 e.stopImmediatePropagation(); 708 }); 709 710 mfp.container.addClass('mfp-s-'+status); 711 _prevStatus = status; 712 } 713 }, 714 715 716 /* 717 "Private" helpers that aren't private at all 718 */ 719 // Check to close popup or not 720 // "target" is an element that was clicked 721 _checkIfClose: function(target) { 722 723 if($(target).hasClass(PREVENT_CLOSE_CLASS)) { 724 return; 725 } 726 727 var closeOnContent = mfp.st.closeOnContentClick; 728 var closeOnBg = mfp.st.closeOnBgClick; 729 730 if(closeOnContent && closeOnBg) { 731 return true; 732 } else { 733 734 // We close the popup if click is on close button or on preloader. Or if there is no content. 735 if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) { 736 return true; 737 } 738 739 // if click is outside the content 740 if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { 741 if(closeOnBg) { 742 // last check, if the clicked element is in DOM, (in case it's removed onclick) 743 if( $.contains(document, target) ) { 744 return true; 745 } 746 } 747 } else if(closeOnContent) { 748 return true; 749 } 750 751 } 752 return false; 753 }, 754 _addClassToMFP: function(cName) { 755 mfp.bgOverlay.addClass(cName); 756 mfp.wrap.addClass(cName); 757 }, 758 _removeClassFromMFP: function(cName) { 759 this.bgOverlay.removeClass(cName); 760 mfp.wrap.removeClass(cName); 761 }, 762 _hasScrollBar: function(winHeight) { 763 return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) ); 764 }, 765 _setFocus: function() { 766 (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); 767 }, 768 _onFocusIn: function(e) { 769 if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { 770 mfp._setFocus(); 771 return false; 772 } 773 }, 774 _parseMarkup: function(template, values, item) { 775 var arr; 776 if(item.data) { 777 values = $.extend(item.data, values); 778 } 779 _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); 780 781 $.each(values, function(key, value) { 782 if(value === undefined || value === false) { 783 return true; 784 } 785 arr = key.split('_'); 786 if(arr.length > 1) { 787 var el = template.find(EVENT_NS + '-'+arr[0]); 788 789 if(el.length > 0) { 790 var attr = arr[1]; 791 if(attr === 'replaceWith') { 792 if(el[0] !== value[0]) { 793 el.replaceWith(value); 794 } 795 } else if(attr === 'img') { 796 if(el.is('img')) { 797 el.attr('src', value); 798 } else { 799 el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' ); 800 } 801 } else { 802 el.attr(arr[1], value); 803 } 804 } 805 806 } else { 807 template.find(EVENT_NS + '-'+key).html(value); 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 847 options.isObj = true; 848 options.index = index || 0; 849 return this.instance.open(options); 850 }, 851 852 close: function() { 853 return $.magnificPopup.instance && $.magnificPopup.instance.close(); 854 }, 855 856 registerModule: function(name, module) { 857 if(module.options) { 858 $.magnificPopup.defaults[name] = module.options; 859 } 860 $.extend(this.proto, module.proto); 861 this.modules.push(name); 862 }, 863 864 defaults: { 865 866 // Info about options is in docs: 867 // //dimsemenov.com/plugins/magnific-popup/documentation.html#options 868 869 disableOn: 0, 870 871 key: null, 872 873 midClick: false, 874 875 mainClass: '', 876 877 preloader: true, 878 879 focus: '', // CSS selector of input to focus after popup is opened 880 881 closeOnContentClick: false, 882 883 closeOnBgClick: true, 884 885 closeBtnInside: true, 886 887 showCloseBtn: true, 888 889 enableEscapeKey: true, 890 891 modal: false, 892 893 alignTop: false, 894 895 removalDelay: 0, 896 897 prependTo: null, 898 899 fixedContentPos: 'auto', 900 901 fixedBgPos: 'auto', 902 903 overflowY: 'auto', 904 905 closeMarkup: '<button title="%title%" type="button" class="mfp-close">×</button>', 906 907 tClose: 'Close (Esc)', 908 909 tLoading: 'Loading...' 910 911 } 912}; 913 914 915 916$.fn.magnificPopup = function(options) { 917 _checkInstance(); 918 919 var jqEl = $(this); 920 921 // We call some API method of first param is a string 922 if (typeof options === "string" ) { 923 924 if(options === 'open') { 925 var items, 926 itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup, 927 index = parseInt(arguments[1], 10) || 0; 928 929 if(itemOpts.items) { 930 items = itemOpts.items[index]; 931 } else { 932 items = jqEl; 933 if(itemOpts.delegate) { 934 items = items.find(itemOpts.delegate); 935 } 936 items = items.eq( index ); 937 } 938 mfp._openClick({mfpEl:items}, jqEl, itemOpts); 939 } else { 940 if(mfp.isOpen) 941 mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1)); 942 } 943 944 } else { 945 // clone options obj 946 options = $.extend(true, {}, options); 947 948 /* 949 * As Zepto doesn't support .data() method for objects 950 * and it works only in normal browsers 951 * we assign "options" object directly to the DOM element. FTW! 952 */ 953 if(_isJQ) { 954 jqEl.data('magnificPopup', options); 955 } else { 956 jqEl[0].magnificPopup = options; 957 } 958 959 mfp.addGroup(jqEl, options); 960 961 } 962 return jqEl; 963}; 964 965 966/*>>core*/ 967 968/*>>inline*/ 969 970var INLINE_NS = 'inline', 971 _hiddenClass, 972 _inlinePlaceholder, 973 _lastInlineElement, 974 _putInlineElementsBack = function() { 975 if(_lastInlineElement) { 976 _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach(); 977 _lastInlineElement = null; 978 } 979 }; 980 981$.magnificPopup.registerModule(INLINE_NS, { 982 options: { 983 hiddenClass: 'hide', // will be appended with `mfp-` prefix 984 markup: '', 985 tNotFound: 'Content not found' 986 }, 987 proto: { 988 989 initInline: function() { 990 mfp.types.push(INLINE_NS); 991 992 _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { 993 _putInlineElementsBack(); 994 }); 995 }, 996 997 getInline: function(item, template) { 998 999 _putInlineElementsBack(); 1000 1001 if(item.src) { 1002 var inlineSt = mfp.st.inline, 1003 el = $(item.src); 1004 1005 if(el.length) { 1006 1007 // If target element has parent - we replace it with placeholder and put it back after popup is closed 1008 var parent = el[0].parentNode; 1009 if(parent && parent.tagName) { 1010 if(!_inlinePlaceholder) { 1011 _hiddenClass = inlineSt.hiddenClass; 1012 _inlinePlaceholder = _getEl(_hiddenClass); 1013 _hiddenClass = 'mfp-'+_hiddenClass; 1014 } 1015 // replace target inline element with placeholder 1016 _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass); 1017 } 1018 1019 mfp.updateStatus('ready'); 1020 } else { 1021 mfp.updateStatus('error', inlineSt.tNotFound); 1022 el = $('<div>'); 1023 } 1024 1025 item.inlineElement = el; 1026 return el; 1027 } 1028 1029 mfp.updateStatus('ready'); 1030 mfp._parseMarkup(template, {}, item); 1031 return template; 1032 } 1033 } 1034}); 1035 1036/*>>inline*/ 1037 1038/*>>ajax*/ 1039var AJAX_NS = 'ajax', 1040 _ajaxCur, 1041 _removeAjaxCursor = function() { 1042 if(_ajaxCur) { 1043 $(document.body).removeClass(_ajaxCur); 1044 } 1045 }, 1046 _destroyAjaxRequest = function() { 1047 _removeAjaxCursor(); 1048 if(mfp.req) { 1049 mfp.req.abort(); 1050 } 1051 }; 1052 1053$.magnificPopup.registerModule(AJAX_NS, { 1054 1055 options: { 1056 settings: null, 1057 cursor: 'mfp-ajax-cur', 1058 tError: '<a href="%url%">The content</a> could not be loaded.' 1059 }, 1060 1061 proto: { 1062 initAjax: function() { 1063 mfp.types.push(AJAX_NS); 1064 _ajaxCur = mfp.st.ajax.cursor; 1065 1066 _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest); 1067 _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest); 1068 }, 1069 getAjax: function(item) { 1070 1071 if(_ajaxCur) { 1072 $(document.body).addClass(_ajaxCur); 1073 } 1074 1075 mfp.updateStatus('loading'); 1076 1077 var opts = $.extend({ 1078 url: item.src, 1079 success: function(data, textStatus, jqXHR) { 1080 var temp = { 1081 data:data, 1082 xhr:jqXHR 1083 }; 1084 1085 _mfpTrigger('ParseAjax', temp); 1086 1087 mfp.appendContent( $(temp.data), AJAX_NS ); 1088 1089 item.finished = true; 1090 1091 _removeAjaxCursor(); 1092 1093 mfp._setFocus(); 1094 1095 setTimeout(function() { 1096 mfp.wrap.addClass(READY_CLASS); 1097 }, 16); 1098 1099 mfp.updateStatus('ready'); 1100 1101 _mfpTrigger('AjaxContentAdded'); 1102 }, 1103 error: function() { 1104 _removeAjaxCursor(); 1105 item.finished = item.loadError = true; 1106 mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); 1107 } 1108 }, mfp.st.ajax.settings); 1109 1110 mfp.req = $.ajax(opts); 1111 1112 return ''; 1113 } 1114 } 1115}); 1116 1117 1118 1119 1120 1121 1122 1123/*>>ajax*/ 1124 1125/*>>image*/ 1126var _imgInterval, 1127 _getTitle = function(item) { 1128 if(item.data && item.data.title !== undefined) 1129 return item.data.title; 1130 1131 var src = mfp.st.image.titleSrc; 1132 1133 if(src) { 1134 if($.isFunction(src)) { 1135 return src.call(mfp, item); 1136 } else if(item.el) { 1137 return item.el.attr(src) || ''; 1138 } 1139 } 1140 return ''; 1141 }; 1142 1143$.magnificPopup.registerModule('image', { 1144 1145 options: { 1146 markup: '<div class="mfp-figure">'+ 1147 '<div class="mfp-close"></div>'+ 1148 '<figure>'+ 1149 '<div class="mfp-img"></div>'+ 1150 '<figcaption>'+ 1151 '<div class="mfp-bottom-bar">'+ 1152 '<div class="mfp-title"></div>'+ 1153 '<div class="mfp-counter"></div>'+ 1154 '</div>'+ 1155 '</figcaption>'+ 1156 '</figure>'+ 1157 '</div>', 1158 cursor: 'mfp-zoom-out-cur', 1159 titleSrc: 'title', 1160 verticalFit: true, 1161 tError: '<a href="%url%">The image</a> could not be loaded.' 1162 }, 1163 1164 proto: { 1165 initImage: function() { 1166 var imgSt = mfp.st.image, 1167 ns = '.image'; 1168 1169 mfp.types.push('image'); 1170 1171 _mfpOn(OPEN_EVENT+ns, function() { 1172 if(mfp.currItem.type === 'image' && imgSt.cursor) { 1173 $(document.body).addClass(imgSt.cursor); 1174 } 1175 }); 1176 1177 _mfpOn(CLOSE_EVENT+ns, function() { 1178 if(imgSt.cursor) { 1179 $(document.body).removeClass(imgSt.cursor); 1180 } 1181 _window.off('resize' + EVENT_NS); 1182 }); 1183 1184 _mfpOn('Resize'+ns, mfp.resizeImage); 1185 if(mfp.isLowIE) { 1186 _mfpOn('AfterChange', mfp.resizeImage); 1187 } 1188 }, 1189 resizeImage: function() { 1190 var item = mfp.currItem; 1191 if(!item || !item.img) return; 1192 1193 if(mfp.st.image.verticalFit) { 1194 var decr = 0; 1195 // fix box-sizing in ie7/8 1196 if(mfp.isLowIE) { 1197 decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10); 1198 } 1199 item.img.css('max-height', mfp.wH-decr); 1200 } 1201 }, 1202 _onImageHasSize: function(item) { 1203 if(item.img) { 1204 1205 item.hasSize = true; 1206 1207 if(_imgInterval) { 1208 clearInterval(_imgInterval); 1209 } 1210 1211 item.isCheckingImgSize = false; 1212 1213 _mfpTrigger('ImageHasSize', item); 1214 1215 if(item.imgHidden) { 1216 if(mfp.content) 1217 mfp.content.removeClass('mfp-loading'); 1218 1219 item.imgHidden = false; 1220 } 1221 1222 } 1223 }, 1224 1225 /** 1226 * Function that loops until the image has size to display elements that rely on it asap 1227 */ 1228 findImageSize: function(item) { 1229 1230 var counter = 0, 1231 img = item.img[0], 1232 mfpSetInterval = function(delay) { 1233 1234 if(_imgInterval) { 1235 clearInterval(_imgInterval); 1236 } 1237 // decelerating interval that checks for size of an image 1238 _imgInterval = setInterval(function() { 1239 if(img.naturalWidth > 0) { 1240 mfp._onImageHasSize(item); 1241 return; 1242 } 1243 1244 if(counter > 200) { 1245 clearInterval(_imgInterval); 1246 } 1247 1248 counter++; 1249 if(counter === 3) { 1250 mfpSetInterval(10); 1251 } else if(counter === 40) { 1252 mfpSetInterval(50); 1253 } else if(counter === 100) { 1254 mfpSetInterval(500); 1255 } 1256 }, delay); 1257 }; 1258 1259 mfpSetInterval(1); 1260 }, 1261 1262 getImage: function(item, template) { 1263 1264 var guard = 0, 1265 1266 // image load complete handler 1267 onLoadComplete = function() { 1268 if(item) { 1269 if (item.img[0].complete) { 1270 item.img.off('.mfploader'); 1271 1272 if(item === mfp.currItem){ 1273 mfp._onImageHasSize(item); 1274 1275 mfp.updateStatus('ready'); 1276 } 1277 1278 item.hasSize = true; 1279 item.loaded = true; 1280 1281 _mfpTrigger('ImageLoadComplete'); 1282 1283 } 1284 else { 1285 // if image complete check fails 200 times (20 sec), we assume that there was an error. 1286 guard++; 1287 if(guard < 200) { 1288 setTimeout(onLoadComplete,100); 1289 } else { 1290 onLoadError(); 1291 } 1292 } 1293 } 1294 }, 1295 1296 // image error handler 1297 onLoadError = function() { 1298 if(item) { 1299 item.img.off('.mfploader'); 1300 if(item === mfp.currItem){ 1301 mfp._onImageHasSize(item); 1302 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); 1303 } 1304 1305 item.hasSize = true; 1306 item.loaded = true; 1307 item.loadError = true; 1308 } 1309 }, 1310 imgSt = mfp.st.image; 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 1372 1373/*>>image*/ 1374 1375/*>>zoom*/ 1376var hasMozTransform, 1377 getHasMozTransform = function() { 1378 if(hasMozTransform === undefined) { 1379 hasMozTransform = document.createElement('p').style.MozTransform !== undefined; 1380 } 1381 return hasMozTransform; 1382 }; 1383 1384$.magnificPopup.registerModule('zoom', { 1385 1386 options: { 1387 enabled: false, 1388 easing: 'ease-in-out', 1389 duration: 300, 1390 opener: function(element) { 1391 return element.is('img') ? element : element.find('img'); 1392 } 1393 }, 1394 1395 proto: { 1396 1397 initZoom: function() { 1398 var zoomSt = mfp.st.zoom, 1399 ns = '.zoom', 1400 image; 1401 1402 if(!zoomSt.enabled || !mfp.supportsTransition) { 1403 return; 1404 } 1405 1406 var duration = zoomSt.duration, 1407 getElToAnimate = function(image) { 1408 var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'), 1409 transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing, 1410 cssObj = { 1411 position: 'fixed', 1412 zIndex: 9999, 1413 left: 0, 1414 top: 0, 1415 '-webkit-backface-visibility': 'hidden' 1416 }, 1417 t = 'transition'; 1418 1419 cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition; 1420 1421 newImg.css(cssObj); 1422 return newImg; 1423 }, 1424 showMainContent = function() { 1425 mfp.content.css('visibility', 'visible'); 1426 }, 1427 openTimeout, 1428 animatedImg; 1429 1430 _mfpOn('BuildControls'+ns, function() { 1431 if(mfp._allowZoom()) { 1432 1433 clearTimeout(openTimeout); 1434 mfp.content.css('visibility', 'hidden'); 1435 1436 // Basically, all code below does is clones existing image, puts in on top of the current one and animated it 1437 1438 image = mfp._getItemToZoom(); 1439 1440 if(!image) { 1441 showMainContent(); 1442 return; 1443 } 1444 1445 animatedImg = getElToAnimate(image); 1446 1447 animatedImg.css( mfp._getOffset() ); 1448 1449 mfp.wrap.append(animatedImg); 1450 1451 openTimeout = setTimeout(function() { 1452 animatedImg.css( mfp._getOffset( true ) ); 1453 openTimeout = setTimeout(function() { 1454 1455 showMainContent(); 1456 1457 setTimeout(function() { 1458 animatedImg.remove(); 1459 image = animatedImg = null; 1460 _mfpTrigger('ZoomAnimationEnded'); 1461 }, 16); // avoid blink when switching images 1462 1463 }, duration); // this timeout equals animation duration 1464 1465 }, 16); // by adding this timeout we avoid short glitch at the beginning of animation 1466 1467 1468 // Lots of timeouts... 1469 } 1470 }); 1471 _mfpOn(BEFORE_CLOSE_EVENT+ns, function() { 1472 if(mfp._allowZoom()) { 1473 1474 clearTimeout(openTimeout); 1475 1476 mfp.st.removalDelay = duration; 1477 1478 if(!image) { 1479 image = mfp._getItemToZoom(); 1480 if(!image) { 1481 return; 1482 } 1483 animatedImg = getElToAnimate(image); 1484 } 1485 1486 1487 animatedImg.css( mfp._getOffset(true) ); 1488 mfp.wrap.append(animatedImg); 1489 mfp.content.css('visibility', 'hidden'); 1490 1491 setTimeout(function() { 1492 animatedImg.css( mfp._getOffset() ); 1493 }, 16); 1494 } 1495 1496 }); 1497 1498 _mfpOn(CLOSE_EVENT+ns, function() { 1499 if(mfp._allowZoom()) { 1500 showMainContent(); 1501 if(animatedImg) { 1502 animatedImg.remove(); 1503 } 1504 image = null; 1505 } 1506 }); 1507 }, 1508 1509 _allowZoom: function() { 1510 return mfp.currItem.type === 'image'; 1511 }, 1512 1513 _getItemToZoom: function() { 1514 if(mfp.currItem.hasSize) { 1515 return mfp.currItem.img; 1516 } else { 1517 return false; 1518 } 1519 }, 1520 1521 // Get element postion relative to viewport 1522 _getOffset: function(isLarge) { 1523 var el; 1524 if(isLarge) { 1525 el = mfp.currItem.img; 1526 } else { 1527 el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem); 1528 } 1529 1530 var offset = el.offset(); 1531 var paddingTop = parseInt(el.css('padding-top'),10); 1532 var paddingBottom = parseInt(el.css('padding-bottom'),10); 1533 offset.top -= ( $(window).scrollTop() - paddingTop ); 1534 1535 1536 /* 1537 1538 Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa. 1539 1540 */ 1541 var obj = { 1542 width: el.width(), 1543 // fix Zepto height+padding issue 1544 height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop 1545 }; 1546 1547 // I hate to do this, but there is no another option 1548 if( getHasMozTransform() ) { 1549 obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)'; 1550 } else { 1551 obj.left = offset.left; 1552 obj.top = offset.top; 1553 } 1554 return obj; 1555 } 1556 1557 } 1558}); 1559 1560 1561 1562/*>>zoom*/ 1563 1564/*>>iframe*/ 1565 1566var IFRAME_NS = 'iframe', 1567 _emptyPage = '//about:blank', 1568 1569 _fixIframeBugs = function(isShowing) { 1570 if(mfp.currTemplate[IFRAME_NS]) { 1571 var el = mfp.currTemplate[IFRAME_NS].find('iframe'); 1572 if(el.length) { 1573 // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug 1574 if(!isShowing) { 1575 el[0].src = _emptyPage; 1576 } 1577 1578 // IE8 black screen bug fix 1579 if(mfp.isIE8) { 1580 el.css('display', isShowing ? 'block' : 'none'); 1581 } 1582 } 1583 } 1584 }; 1585 1586$.magnificPopup.registerModule(IFRAME_NS, { 1587 1588 options: { 1589 markup: '<div class="mfp-iframe-scaler">'+ 1590 '<div class="mfp-close"></div>'+ 1591 '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+ 1592 '</div>', 1593 1594 srcAction: 'iframe_src', 1595 1596 // we don't care and support only one default type of URL by default 1597 patterns: { 1598 youtube: { 1599 index: 'youtube.com', 1600 id: 'v=', 1601 src: '//www.youtube.com/embed/%id%?autoplay=1' 1602 }, 1603 vimeo: { 1604 index: 'vimeo.com/', 1605 id: '/', 1606 src: '//player.vimeo.com/video/%id%?autoplay=1' 1607 }, 1608 gmaps: { 1609 index: '//maps.google.', 1610 src: '%id%&output=embed' 1611 } 1612 } 1613 }, 1614 1615 proto: { 1616 initIframe: function() { 1617 mfp.types.push(IFRAME_NS); 1618 1619 _mfpOn('BeforeChange', function(e, prevType, newType) { 1620 if(prevType !== newType) { 1621 if(prevType === IFRAME_NS) { 1622 _fixIframeBugs(); // iframe if removed 1623 } else if(newType === IFRAME_NS) { 1624 _fixIframeBugs(true); // iframe is showing 1625 } 1626 }// else { 1627 // iframe source is switched, don't do anything 1628 //} 1629 }); 1630 1631 _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { 1632 _fixIframeBugs(); 1633 }); 1634 }, 1635 1636 getIframe: function(item, template) { 1637 var embedSrc = item.src; 1638 var iframeSt = mfp.st.iframe; 1639 1640 $.each(iframeSt.patterns, function() { 1641 if(embedSrc.indexOf( this.index ) > -1) { 1642 if(this.id) { 1643 if(typeof this.id === 'string') { 1644 embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); 1645 } else { 1646 embedSrc = this.id.call( this, embedSrc ); 1647 } 1648 } 1649 embedSrc = this.src.replace('%id%', embedSrc ); 1650 return false; // break; 1651 } 1652 }); 1653 1654 var dataObj = {}; 1655 if(iframeSt.srcAction) { 1656 dataObj[iframeSt.srcAction] = embedSrc; 1657 } 1658 mfp._parseMarkup(template, dataObj, item); 1659 1660 mfp.updateStatus('ready'); 1661 1662 return template; 1663 } 1664 } 1665}); 1666 1667 1668 1669/*>>iframe*/ 1670 1671/*>>gallery*/ 1672/** 1673 * Get looped index depending on number of slides 1674 */ 1675var _getLoopedId = function(index) { 1676 var numSlides = mfp.items.length; 1677 if(index > numSlides - 1) { 1678 return index - numSlides; 1679 } else if(index < 0) { 1680 return numSlides + index; 1681 } 1682 return index; 1683 }, 1684 _replaceCurrTotal = function(text, curr, total) { 1685 return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); 1686 }; 1687 1688$.magnificPopup.registerModule('gallery', { 1689 1690 options: { 1691 enabled: false, 1692 arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', 1693 preload: [0,2], 1694 navigateByImgClick: true, 1695 arrows: true, 1696 1697 tPrev: 'Previous (Left arrow key)', 1698 tNext: 'Next (Right arrow key)', 1699 tCounter: '%curr% of %total%' 1700 }, 1701 1702 proto: { 1703 initGallery: function() { 1704 1705 var gSt = mfp.st.gallery, 1706 ns = '.mfp-gallery', 1707 supportsFastClick = Boolean($.fn.mfpFastClick); 1708 1709 mfp.direction = true; // true - next, false - prev 1710 1711 if(!gSt || !gSt.enabled ) return false;
1712 1713 _wrapClasses += ' mfp-gallery'; 1714 1715 _mfpOn(OPEN_EVENT+ns, function() { 1716 1717 if(gSt.navigateByImgClick) { 1718 mfp.wrap.on('click'+ns, '.mfp-img', function() { 1719 if(mfp.items.length > 1) { 1720 mfp.next(); 1721 return false; 1722 } 1723 }); 1724 } 1725 1726 _document.on('keydown'+ns, function(e) { 1727 if (e.keyCode === 37) { 1728 mfp.prev(); 1729 } else if (e.keyCode === 39) { 1730 mfp.next(); 1731 } 1732 }); 1733 }); 1734 1735 _mfpOn('UpdateStatus'+ns, function(e, data) { 1736 if(data.text) { 1737 data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); 1738 } 1739 }); 1740 1741 _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { 1742 var l = mfp.items.length; 1743 values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; 1744 }); 1745 1746 _mfpOn('BuildControls' + ns, function() { 1747 if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { 1748 var markup = gSt.arrowMarkup, 1749 arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS), 1750 arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS); 1751 1752 var eName = supportsFastClick ? 'mfpFastClick' : 'click'; 1753 arrowLeft[eName](function() { 1754 mfp.prev(); 1755 }); 1756 arrowRight[eName](function() { 1757 mfp.next(); 1758 }); 1759 1760 // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) 1761 if(mfp.isIE7) { 1762 _getEl('b', arrowLeft[0], false, true); 1763 _getEl('a', arrowLeft[0], false, true); 1764 _getEl('b', arrowRight[0], false, true); 1765 _getEl('a', arrowRight[0], false, true); 1766 } 1767 1768 mfp.container.append(arrowLeft.add(arrowRight)); 1769 } 1770 }); 1771 1772 _mfpOn(CHANGE_EVENT+ns, function() { 1773 if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); 1774 1775 mfp._preloadTimeout = setTimeout(function() { 1776 mfp.preloadNearbyImages(); 1777 mfp._preloadTimeout = null; 1778 }, 16); 1779 }); 1780 1781 1782 _mfpOn(CLOSE_EVENT+ns, function() { 1783 _document.off(ns); 1784 mfp.wrap.off('click'+ns); 1785 1786 if(mfp.arrowLeft && supportsFastClick) { 1787 mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); 1788 } 1789 mfp.arrowRight = mfp.arrowLeft = null; 1790 }); 1791 1792 }, 1793 next: function() { 1794 mfp.direction = true; 1795 mfp.index = _getLoopedId(mfp.index + 1); 1796 mfp.updateItemHTML(); 1797 }, 1798 prev: function() { 1799 mfp.direction = false; 1800 mfp.index = _getLoopedId(mfp.index - 1); 1801 mfp.updateItemHTML(); 1802 }, 1803 goTo: function(newIndex) { 1804 mfp.direction = (newIndex >= mfp.index); 1805 mfp.index = newIndex; 1806 mfp.updateItemHTML(); 1807 }, 1808 preloadNearbyImages: function() { 1809 var p = mfp.st.gallery.preload, 1810 preloadBefore = Math.min(p[0], mfp.items.length), 1811 preloadAfter = Math.min(p[1], mfp.items.length), 1812 i; 1813 1814 for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { 1815 mfp._preloadItem(mfp.index+i); 1816 } 1817 for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { 1818 mfp._preloadItem(mfp.index-i); 1819 } 1820 }, 1821 _preloadItem: function(index) { 1822 index = _getLoopedId(index); 1823 1824 if(mfp.items[index].preloaded) { 1825 return; 1826 } 1827 1828 var item = mfp.items[index]; 1829 if(!item.parsed) { 1830 item = mfp.parseEl( index ); 1831 } 1832 1833 _mfpTrigger('LazyLoad', item); 1834 1835 if(item.type === 'image') { 1836 item.img = $('<img class="mfp-img" />').on('load.mfploader', function() { 1837 item.hasSize = true; 1838 }).on('error.mfploader', function() { 1839 item.hasSize = true; 1840 item.loadError = true; 1841 _mfpTrigger('LazyLoadError', item); 1842 }).attr('src', item.src); 1843 } 1844 1845 1846 item.preloaded = true; 1847 } 1848 } 1849}); 1850 1851/* 1852Touch Support that might be implemented some day 1853 1854addSwipeGesture: function() { 1855 var startX, 1856 moved, 1857 multipleTouches; 1858 1859 return; 1860 1861 var namespace = '.mfp', 1862 addEventNames = function(pref, down, move, up, cancel) { 1863 mfp._tStart = pref + down + namespace; 1864 mfp._tMove = pref + move + namespace; 1865 mfp._tEnd = pref + up + namespace; 1866 mfp._tCancel = pref + cancel + namespace; 1867 }; 1868 1869 if(window.navigator.msPointerEnabled) { 1870 addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); 1871 } else if('ontouchstart' in window) { 1872 addEventNames('touch', 'start', 'move', 'end', 'cancel'); 1873 } else { 1874 return; 1875 } 1876 _window.on(mfp._tStart, function(e) { 1877 var oE = e.originalEvent; 1878 multipleTouches = moved = false;
1879 startX = oE.pageX || oE.changedTouches[0].pageX; 1880 }).on(mfp._tMove, function(e) { 1881 if(e.originalEvent.touches.length > 1) { 1882 multipleTouches = e.originalEvent.touches.length; 1883 } else { 1884 //e.preventDefault(); 1885 moved = true; 1886 } 1887 }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { 1888 if(moved && !multipleTouches) { 1889 var oE = e.originalEvent, 1890 diff = startX - (oE.pageX || oE.changedTouches[0].pageX); 1891 1892 if(diff > 20) { 1893 mfp.next(); 1894 } else if(diff < -20) { 1895 mfp.prev(); 1896 } 1897 } 1898 }); 1899}, 1900*/ 1901 1902 1903/*>>gallery*/ 1904 1905/*>>retina*/ 1906 1907var RETINA_NS = 'retina'; 1908 1909$.magnificPopup.registerModule(RETINA_NS, { 1910 options: { 1911 replaceSrc: function(item) { 1912 return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); 1913 }, 1914 ratio: 1 // Function or number. Set to 1 to disable. 1915 }, 1916 proto: { 1917 initRetina: function() { 1918 if(window.devicePixelRatio > 1) { 1919 1920 var st = mfp.st.retina, 1921 ratio = st.ratio; 1922 1923 ratio = !isNaN(ratio) ? ratio : ratio(); 1924 1925 if(ratio > 1) { 1926 _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { 1927 item.img.css({ 1928 'max-width': item.img[0].naturalWidth / ratio, 1929 'width': '100%' 1930 }); 1931 }); 1932 _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { 1933 item.src = st.replaceSrc(item, ratio); 1934 }); 1935 } 1936 } 1937 1938 } 1939 } 1940}); 1941 1942/*>>retina*/ 1943 1944/*>>fastclick*/ 1945/** 1946 * FastClick event implementation. (removes 300ms delay on touch devices) 1947 * Based on //developers.google.com/mobile/articles/fast_buttons 1948 * 1949 * You may use it outside the Magnific Popup by calling just: 1950 * 1951 * $('.your-el').mfpFastClick(function() { 1952 * console.log('Clicked!'); 1953 * }); 1954 * 1955 * To unbind: 1956 * $('.your-el').destroyMfpFastClick(); 1957 * 1958 * 1959 * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. 1960 * If you need something more advanced, use plugin by FT Labs //github.com/ftlabs/fastclick 1961 * 1962 */ 1963 1964(function() { 1965 var ghostClickDelay = 1000, 1966 supportsTouch = 'ontouchstart' in window, 1967 unbindTouchMove = function() { 1968 _window.off('touchmove'+ns+' touchend'+ns); 1969 }, 1970 eName = 'mfpFastClick', 1971 ns = '.'+eName; 1972 1973 1974 // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way 1975 $.fn.mfpFastClick = function(callback) { 1976 1977 return $(this).each(function() { 1978 1979 var elem = $(this), 1980 lock; 1981 1982 if( supportsTouch ) { 1983 1984 var timeout, 1985 startX, 1986 startY, 1987 pointerMoved, 1988 point, 1989 numPointers; 1990 1991 elem.on('touchstart' + ns, function(e) { 1992 pointerMoved = false; 1993 numPointers = 1; 1994 1995 point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; 1996 startX = point.clientX; 1997 startY = point.clientY; 1998 1999 _window.on('touchmove'+ns, function(e) { 2000 point = e.originalEvent ? e.originalEvent.touches : e.touches; 2001 numPointers = point.length; 2002 point = point[0]; 2003 if (Math.abs(point.clientX - startX) > 10 || 2004 Math.abs(point.clientY - startY) > 10) { 2005 pointerMoved = true; 2006 unbindTouchMove(); 2007 } 2008 }).on('touchend'+ns, function(e) { 2009 unbindTouchMove(); 2010 if(pointerMoved || numPointers > 1) { 2011 return; 2012 } 2013 lock = true; 2014 e.preventDefault(); 2015 clearTimeout(timeout); 2016 timeout = setTimeout(function() { 2017 lock = false; 2018 }, ghostClickDelay); 2019 callback(); 2020 }); 2021 }); 2022 2023 } 2024 2025 elem.on('click' + ns, function() { 2026 if(!lock) { 2027 callback(); 2028 } 2029 }); 2030 }); 2031 }; 2032 2033 $.fn.destroyMfpFastClick = function() { 2034 $(this).off('touchstart' + ns + ' click' + ns); 2035 if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); 2036 }; 2037})(); 2038 2039/*>>fastclick*/ 2040 _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.