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