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