shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

jquery.magnific-popup.js (43589B)


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