PageSourceSearch

https://www.morinaga.com.tw/assets/js/jquery.magnific-popup.js

js morinaga.com.tw collected 2026-10-06 12:54:49 UTC 45,732 bytes, 2,042 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.