JAVASCRIPT   67

jquery magnific popup jss

Guest on 29th July 2022 01:36:58 PM

  1. /*! Magnific Popup - v1.0.0 - 2015-01-03
  2. * http://dimsemenov.com/plugins/magnific-popup/
  3. * Copyright (c) 2015 Dmitry Semenov; */
  4. ;(function (factory) {
  5. if (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.  */
  28. var 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 */
  46. var 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.  */
  60. var _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.  */
  129. MagnificPopup.prototype = {
  130.  
  131.         constructor: MagnificPopup,
  132.  
  133.         /**
  134.          * Initializes Magnific Popup plugin.
  135.          * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
  136.          */
  137.         init: function() {
  138.                 var appVersion = navigator.appVersion;
  139.                 mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1;
  140.                 mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1;
  141.                 mfp.isLowIE = mfp.isIE7 || mfp.isIE8;
  142.                 mfp.isAndroid = (/android/gi).test(appVersion);
  143.                 mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
  144.                 mfp.supportsTransition = supportsTransitions();
  145.  
  146.                 // We disable fixed positioned lightbox on devices that don't handle it nicely.
  147.                 // If you know a better way of detecting this - let me know.
  148.                 mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
  149.                 _document = $(document);
  150.  
  151.                 mfp.popupsCache = {};
  152.         },
  153.  
  154.         /**
  155.          * Opens popup
  156.          * @param  data [description]
  157.          */
  158.         open: function(data) {
  159.  
  160.                 var i;
  161.  
  162.                 if(data.isObj === false) {
  163.                         // convert jQuery collection to array to avoid conflicts later
  164.                         mfp.items = data.items.toArray();
  165.  
  166.                         mfp.index = 0;
  167.                         var items = data.items,
  168.                                 item;
  169.                         for(i = 0; i < items.length; i++) {
  170.                                 item = items[i];
  171.                                 if(item.parsed) {
  172.                                         item = item.el[0];
  173.                                 }
  174.                                 if(item === data.el[0]) {
  175.                                         mfp.index = i;
  176.                                         break;
  177.                                 }
  178.                         }
  179.                 } else {
  180.                         mfp.items = $.isArray(data.items) ? data.items : [data.items];
  181.                         mfp.index = data.index || 0;
  182.                 }
  183.  
  184.                 // if popup is already opened - we just update the content
  185.                 if(mfp.isOpen) {
  186.                         mfp.updateItemHTML();
  187.                         return;
  188.                 }
  189.                
  190.                 mfp.types = [];
  191.                 _wrapClasses = '';
  192.                 if(data.mainEl && data.mainEl.length) {
  193.                         mfp.ev = data.mainEl.eq(0);
  194.                 } else {
  195.                         mfp.ev = _document;
  196.                 }
  197.  
  198.                 if(data.key) {
  199.                         if(!mfp.popupsCache[data.key]) {
  200.                                 mfp.popupsCache[data.key] = {};
  201.                         }
  202.                         mfp.currTemplate = mfp.popupsCache[data.key];
  203.                 } else {
  204.                         mfp.currTemplate = {};
  205.                 }
  206.  
  207.  
  208.  
  209.                 mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
  210.                 mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;
  211.  
  212.                 if(mfp.st.modal) {
  213.                         mfp.st.closeOnContentClick = false;
  214.                         mfp.st.closeOnBgClick = false;
  215.                         mfp.st.showCloseBtn = false;
  216.                         mfp.st.enableEscapeKey = false;
  217.                 }
  218.                
  219.  
  220.                 // Building markup
  221.                 // main containers are created only once
  222.                 if(!mfp.bgOverlay) {
  223.  
  224.                         // Dark overlay
  225.                         mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
  226.                                 mfp.close();
  227.                         });
  228.  
  229.                         mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
  230.                                 if(mfp._checkIfClose(e.target)) {
  231.                                         mfp.close();
  232.                                 }
  233.                         });
  234.  
  235.                         mfp.container = _getEl('container', mfp.wrap);
  236.                 }
  237.  
  238.                 mfp.contentContainer = _getEl('content');
  239.                 if(mfp.st.preloader) {
  240.                         mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
  241.                 }
  242.  
  243.  
  244.                 // Initializing modules
  245.                 var modules = $.magnificPopup.modules;
  246.                 for(i = 0; i < modules.length; i++) {
  247.                         var n = modules[i];
  248.                         n = n.charAt(0).toUpperCase() + n.slice(1);
  249.                         mfp['init'+n].call(mfp);
  250.                 }
  251.                 _mfpTrigger('BeforeOpen');
  252.  
  253.  
  254.                 if(mfp.st.showCloseBtn) {
  255.                         // Close button
  256.                         if(!mfp.st.closeBtnInside) {
  257.                                 mfp.wrap.append( _getCloseBtn() );
  258.                         } else {
  259.                                 _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
  260.                                         values.close_replaceWith = _getCloseBtn(item.type);
  261.                                 });
  262.                                 _wrapClasses += ' mfp-close-btn-in';
  263.                         }
  264.                 }
  265.  
  266.                 if(mfp.st.alignTop) {
  267.                         _wrapClasses += ' mfp-align-top';
  268.                 }
  269.  
  270.        
  271.  
  272.                 if(mfp.fixedContentPos) {
  273.                         mfp.wrap.css({
  274.                                 overflow: mfp.st.overflowY,
  275.                                 overflowX: 'hidden',
  276.                                 overflowY: mfp.st.overflowY
  277.                         });
  278.                 } else {
  279.                         mfp.wrap.css({
  280.                                 top: _window.scrollTop(),
  281.                                 position: 'absolute'
  282.                         });
  283.                 }
  284.                 if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
  285.                         mfp.bgOverlay.css({
  286.                                 height: _document.height(),
  287.                                 position: 'absolute'
  288.                         });
  289.                 }
  290.  
  291.                
  292.  
  293.                 if(mfp.st.enableEscapeKey) {
  294.                         // Close on ESC key
  295.                         _document.on('keyup' + EVENT_NS, function(e) {
  296.                                 if(e.keyCode === 27) {
  297.                                         mfp.close();
  298.                                 }
  299.                         });
  300.                 }
  301.  
  302.                 _window.on('resize' + EVENT_NS, function() {
  303.                         mfp.updateSize();
  304.                 });
  305.  
  306.  
  307.                 if(!mfp.st.closeOnContentClick) {
  308.                         _wrapClasses += ' mfp-auto-cursor';
  309.                 }
  310.                
  311.                 if(_wrapClasses)
  312.                         mfp.wrap.addClass(_wrapClasses);
  313.  
  314.  
  315.                 // 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 ) ) {
  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">&times;</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. /*
  969. var start = performance.now(),
  970.         i,
  971.         rounds = 1000;
  972.  
  973. for(i = 0; i < rounds; i++) {
  974.  
  975. }
  976. console.log('Test #1:', performance.now() - start);
  977.  
  978. start = performance.now();
  979. for(i = 0; i < rounds; i++) {
  980.  
  981. }
  982. console.log('Test #2:', performance.now() - start);
  983. */
  984.  
  985.  
  986. /*>>core*/
  987.  
  988. /*>>inline*/
  989.  
  990. var 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*/
  1059. var 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*/
  1146. var _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*/
  1396. var 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.  
  1586. var 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.                         vimeo: {
  1624.                                 index: 'vimeo.com/',
  1625.                                 id: '/',
  1626.                                 src: '//player.vimeo.com/video/%id%?autoplay=1'
  1627.                         },
  1628.                         gmaps: {
  1629.                                 index: '//maps.google.',
  1630.                                 src: '%id%&output=embed'
  1631.                         }
  1632.                 }
  1633.         },
  1634.  
  1635.         proto: {
  1636.                 initIframe: function() {
  1637.                         mfp.types.push(IFRAME_NS);
  1638.  
  1639.                         _mfpOn('BeforeChange', function(e, prevType, newType) {
  1640.                                 if(prevType !== newType) {
  1641.                                         if(prevType === IFRAME_NS) {
  1642.                                                 _fixIframeBugs(); // iframe if removed
  1643.                                         } else if(newType === IFRAME_NS) {
  1644.                                                 _fixIframeBugs(true); // iframe is showing
  1645.                                         }
  1646.                                 }// else {
  1647.                                         // iframe source is switched, don't do anything
  1648.                                 //}
  1649.                         });
  1650.  
  1651.                         _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
  1652.                                 _fixIframeBugs();
  1653.                         });
  1654.                 },
  1655.  
  1656.                 getIframe: function(item, template) {
  1657.                         var embedSrc = item.src;
  1658.                         var iframeSt = mfp.st.iframe;
  1659.                                
  1660.                         $.each(iframeSt.patterns, function() {
  1661.                                 if(embedSrc.indexOf( this.index ) > -1) {
  1662.                                         if(this.id) {
  1663.                                                 if(typeof this.id === 'string') {
  1664.                                                         embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
  1665.                                                 } else {
  1666.                                                         embedSrc = this.id.call( this, embedSrc );
  1667.                                                 }
  1668.                                         }
  1669.                                         embedSrc = this.src.replace('%id%', embedSrc );
  1670.                                         return false; // break;
  1671.                                 }
  1672.                         });
  1673.                        
  1674.                         var dataObj = {};
  1675.                         if(iframeSt.srcAction) {
  1676.                                 dataObj[iframeSt.srcAction] = embedSrc;
  1677.                         }
  1678.                         mfp._parseMarkup(template, dataObj, item);
  1679.  
  1680.                         mfp.updateStatus('ready');
  1681.  
  1682.                         return template;
  1683.                 }
  1684.         }
  1685. });
  1686.  
  1687.  
  1688.  
  1689. /*>>iframe*/
  1690.  
  1691. /*>>gallery*/
  1692. /**
  1693.  * Get looped index depending on number of slides
  1694.  */
  1695. var _getLoopedId = function(index) {
  1696.                 var numSlides = mfp.items.length;
  1697.                 if(index > numSlides - 1) {
  1698.                         return index - numSlides;
  1699.                 } else  if(index < 0) {
  1700.                         return numSlides + index;
  1701.                 }
  1702.                 return index;
  1703.         },
  1704.         _replaceCurrTotal = function(text, curr, total) {
  1705.                 return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
  1706.         };
  1707.  
  1708. $.magnificPopup.registerModule('gallery', {
  1709.  
  1710.         options: {
  1711.                 enabled: false,
  1712.                 arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
  1713.                 preload: [0,2],
  1714.                 navigateByImgClick: true,
  1715.                 arrows: true,
  1716.  
  1717.                 tPrev: 'Previous (Left arrow key)',
  1718.                 tNext: 'Next (Right arrow key)',
  1719.                 tCounter: '%curr% of %total%'
  1720.         },
  1721.  
  1722.         proto: {
  1723.                 initGallery: function() {
  1724.  
  1725.                         var gSt = mfp.st.gallery,
  1726.                                 ns = '.mfp-gallery',
  1727.                                 supportsFastClick = Boolean($.fn.mfpFastClick);
  1728.  
  1729.                         mfp.direction = true; // true - next, false - prev
  1730.                        
  1731.                         if(!gSt || !gSt.enabled ) return false;
  1732.  
  1733.                         _wrapClasses += ' mfp-gallery';
  1734.  
  1735.                         _mfpOn(OPEN_EVENT+ns, function() {
  1736.  
  1737.                                 if(gSt.navigateByImgClick) {
  1738.                                         mfp.wrap.on('click'+ns, '.mfp-img', function() {
  1739.                                                 if(mfp.items.length > 1) {
  1740.                                                         mfp.next();
  1741.                                                         return false;
  1742.                                                 }
  1743.                                         });
  1744.                                 }
  1745.  
  1746.                                 _document.on('keydown'+ns, function(e) {
  1747.                                         if (e.keyCode === 37) {
  1748.                                                 mfp.prev();
  1749.                                         } else if (e.keyCode === 39) {
  1750.                                                 mfp.next();
  1751.                                         }
  1752.                                 });
  1753.                         });
  1754.  
  1755.                         _mfpOn('UpdateStatus'+ns, function(e, data) {
  1756.                                 if(data.text) {
  1757.                                         data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
  1758.                                 }
  1759.                         });
  1760.  
  1761.                         _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
  1762.                                 var l = mfp.items.length;
  1763.                                 values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
  1764.                         });
  1765.  
  1766.                         _mfpOn('BuildControls' + ns, function() {
  1767.                                 if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
  1768.                                         var markup = gSt.arrowMarkup,
  1769.                                                 arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),                      
  1770.                                                 arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);
  1771.  
  1772.                                         var eName = supportsFastClick ? 'mfpFastClick' : 'click';
  1773.                                         arrowLeft[eName](function() {
  1774.                                                 mfp.prev();
  1775.                                         });                    
  1776.                                         arrowRight[eName](function() {
  1777.                                                 mfp.next();
  1778.                                         });    
  1779.  
  1780.                                         // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b)
  1781.                                         if(mfp.isIE7) {
  1782.                                                 _getEl('b', arrowLeft[0], false, true);
  1783.                                                 _getEl('a', arrowLeft[0], false, true);
  1784.                                                 _getEl('b', arrowRight[0], false, true);
  1785.                                                 _getEl('a', arrowRight[0], false, true);
  1786.                                         }
  1787.  
  1788.                                         mfp.container.append(arrowLeft.add(arrowRight));
  1789.                                 }
  1790.                         });
  1791.  
  1792.                         _mfpOn(CHANGE_EVENT+ns, function() {
  1793.                                 if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);
  1794.  
  1795.                                 mfp._preloadTimeout = setTimeout(function() {
  1796.                                         mfp.preloadNearbyImages();
  1797.                                         mfp._preloadTimeout = null;
  1798.                                 }, 16);        
  1799.                         });
  1800.  
  1801.  
  1802.                         _mfpOn(CLOSE_EVENT+ns, function() {
  1803.                                 _document.off(ns);
  1804.                                 mfp.wrap.off('click'+ns);
  1805.                        
  1806.                                 if(mfp.arrowLeft && supportsFastClick) {
  1807.                                         mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick();
  1808.                                 }
  1809.                                 mfp.arrowRight = mfp.arrowLeft = null;
  1810.                         });
  1811.  
  1812.                 },
  1813.                 next: function() {
  1814.                         mfp.direction = true;
  1815.                         mfp.index = _getLoopedId(mfp.index + 1);
  1816.                         mfp.updateItemHTML();
  1817.                 },
  1818.                 prev: function() {
  1819.                         mfp.direction = false;
  1820.                         mfp.index = _getLoopedId(mfp.index - 1);
  1821.                         mfp.updateItemHTML();
  1822.                 },
  1823.                 goTo: function(newIndex) {
  1824.                         mfp.direction = (newIndex >= mfp.index);
  1825.                         mfp.index = newIndex;
  1826.                         mfp.updateItemHTML();
  1827.                 },
  1828.                 preloadNearbyImages: function() {
  1829.                         var p = mfp.st.gallery.preload,
  1830.                                 preloadBefore = Math.min(p[0], mfp.items.length),
  1831.                                 preloadAfter = Math.min(p[1], mfp.items.length),
  1832.                                 i;
  1833.  
  1834.                         for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
  1835.                                 mfp._preloadItem(mfp.index+i);
  1836.                         }
  1837.                         for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
  1838.                                 mfp._preloadItem(mfp.index-i);
  1839.                         }
  1840.                 },
  1841.                 _preloadItem: function(index) {
  1842.                         index = _getLoopedId(index);
  1843.  
  1844.                         if(mfp.items[index].preloaded) {
  1845.                                 return;
  1846.                         }
  1847.  
  1848.                         var item = mfp.items[index];
  1849.                         if(!item.parsed) {
  1850.                                 item = mfp.parseEl( index );
  1851.                         }
  1852.  
  1853.                         _mfpTrigger('LazyLoad', item);
  1854.  
  1855.                         if(item.type === 'image') {
  1856.                                 item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
  1857.                                         item.hasSize = true;
  1858.                                 }).on('error.mfploader', function() {
  1859.                                         item.hasSize = true;
  1860.                                         item.loadError = true;
  1861.                                         _mfpTrigger('LazyLoadError', item);
  1862.                                 }).attr('src', item.src);
  1863.                         }
  1864.  
  1865.  
  1866.                         item.preloaded = true;
  1867.                 }
  1868.         }
  1869. });
  1870.  
  1871. /*
  1872. Touch Support that might be implemented some day
  1873.  
  1874. addSwipeGesture: function() {
  1875.         var startX,
  1876.                 moved,
  1877.                 multipleTouches;
  1878.  
  1879.                 return;
  1880.  
  1881.         var namespace = '.mfp',
  1882.                 addEventNames = function(pref, down, move, up, cancel) {
  1883.                         mfp._tStart = pref + down + namespace;
  1884.                         mfp._tMove = pref + move + namespace;
  1885.                         mfp._tEnd = pref + up + namespace;
  1886.                         mfp._tCancel = pref + cancel + namespace;
  1887.                 };
  1888.  
  1889.         if(window.navigator.msPointerEnabled) {
  1890.                 addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
  1891.         } else if('ontouchstart' in window) {
  1892.                 addEventNames('touch', 'start', 'move', 'end', 'cancel');
  1893.         } else {
  1894.                 return;
  1895.         }
  1896.         _window.on(mfp._tStart, function(e) {
  1897.                 var oE = e.originalEvent;
  1898.                 multipleTouches = moved = false;
  1899.                 startX = oE.pageX || oE.changedTouches[0].pageX;
  1900.         }).on(mfp._tMove, function(e) {
  1901.                 if(e.originalEvent.touches.length > 1) {
  1902.                         multipleTouches = e.originalEvent.touches.length;
  1903.                 } else {
  1904.                         //e.preventDefault();
  1905.                         moved = true;
  1906.                 }
  1907.         }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) {
  1908.                 if(moved && !multipleTouches) {
  1909.                         var oE = e.originalEvent,
  1910.                                 diff = startX - (oE.pageX || oE.changedTouches[0].pageX);
  1911.  
  1912.                         if(diff > 20) {
  1913.                                 mfp.next();
  1914.                         } else if(diff < -20) {
  1915.                                 mfp.prev();
  1916.                         }
  1917.                 }
  1918.         });
  1919. },
  1920. */
  1921.  
  1922.  
  1923. /*>>gallery*/
  1924.  
  1925. /*>>retina*/
  1926.  
  1927. var RETINA_NS = 'retina';
  1928.  
  1929. $.magnificPopup.registerModule(RETINA_NS, {
  1930.         options: {
  1931.                 replaceSrc: function(item) {
  1932.                         return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
  1933.                 },
  1934.                 ratio: 1 // Function or number.  Set to 1 to disable.
  1935.         },
  1936.         proto: {
  1937.                 initRetina: function() {
  1938.                         if(window.devicePixelRatio > 1) {
  1939.  
  1940.                                 var st = mfp.st.retina,
  1941.                                         ratio = st.ratio;
  1942.  
  1943.                                 ratio = !isNaN(ratio) ? ratio : ratio();
  1944.  
  1945.                                 if(ratio > 1) {
  1946.                                         _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
  1947.                                                 item.img.css({
  1948.                                                         'max-width': item.img[0].naturalWidth / ratio,
  1949.                                                         'width': '100%'
  1950.                                                 });
  1951.                                         });
  1952.                                         _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
  1953.                                                 item.src = st.replaceSrc(item, ratio);
  1954.                                         });
  1955.                                 }
  1956.                         }
  1957.  
  1958.                 }
  1959.         }
  1960. });
  1961.  
  1962. /*>>retina*/
  1963.  
  1964. /*>>fastclick*/
  1965. /**
  1966.  * FastClick event implementation. (removes 300ms delay on touch devices)
  1967.  * Based on https://developers.google.com/mobile/articles/fast_buttons
  1968.  *
  1969.  * You may use it outside the Magnific Popup by calling just:
  1970.  *
  1971.  * $('.your-el').mfpFastClick(function() {
  1972.  *     console.log('Clicked!');
  1973.  * });
  1974.  *
  1975.  * To unbind:
  1976.  * $('.your-el').destroyMfpFastClick();
  1977.  *
  1978.  *
  1979.  * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound.
  1980.  * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick
  1981.  *
  1982.  */
  1983.  
  1984. (function() {
  1985.         var ghostClickDelay = 1000,
  1986.                 supportsTouch = 'ontouchstart' in window,
  1987.                 unbindTouchMove = function() {
  1988.                         _window.off('touchmove'+ns+' touchend'+ns);
  1989.                 },
  1990.                 eName = 'mfpFastClick',
  1991.                 ns = '.'+eName;
  1992.  
  1993.  
  1994.         // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way
  1995.         $.fn.mfpFastClick = function(callback) {
  1996.  
  1997.                 return $(this).each(function() {
  1998.  
  1999.                         var elem = $(this),
  2000.                                 lock;
  2001.  
  2002.                         if( supportsTouch ) {
  2003.  
  2004.                                 var timeout,
  2005.                                         startX,
  2006.                                         startY,
  2007.                                         pointerMoved,
  2008.                                         point,
  2009.                                         numPointers;
  2010.  
  2011.                                 elem.on('touchstart' + ns, function(e) {
  2012.                                         pointerMoved = false;
  2013.                                         numPointers = 1;
  2014.  
  2015.                                         point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0];
  2016.                                         startX = point.clientX;
  2017.                                         startY = point.clientY;
  2018.  
  2019.                                         _window.on('touchmove'+ns, function(e) {
  2020.                                                 point = e.originalEvent ? e.originalEvent.touches : e.touches;
  2021.                                                 numPointers = point.length;
  2022.                                                 point = point[0];
  2023.                                                 if (Math.abs(point.clientX - startX) > 10 ||
  2024.                                                         Math.abs(point.clientY - startY) > 10) {
  2025.                                                         pointerMoved = true;
  2026.                                                         unbindTouchMove();
  2027.                                                 }
  2028.                                         }).on('touchend'+ns, function(e) {
  2029.                                                 unbindTouchMove();
  2030.                                                 if(pointerMoved || numPointers > 1) {
  2031.                                                         return;
  2032.                                                 }
  2033.                                                 lock = true;
  2034.                                                 e.preventDefault();
  2035.                                                 clearTimeout(timeout);
  2036.                                                 timeout = setTimeout(function() {
  2037.                                                         lock = false;
  2038.                                                 }, ghostClickDelay);
  2039.                                                 callback();
  2040.                                         });
  2041.                                 });
  2042.  
  2043.                         }
  2044.  
  2045.                         elem.on('click' + ns, function() {
  2046.                                 if(!lock) {
  2047.                                         callback();
  2048.                                 }
  2049.                         });
  2050.                 });
  2051.         };
  2052.  
  2053.         $.fn.destroyMfpFastClick = function() {
  2054.                 $(this).off('touchstart' + ns + ' click' + ns);
  2055.                 if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns);
  2056.         };
  2057. })();
  2058.  
  2059. /*>>fastclick*/
  2060.  _checkInstance(); }));

Raw Paste


Login or Register to edit or fork this paste. It's free.