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