PageSourceSearch

https://comozooconservatory.org/wp-content/themes/comozooconservatory/js/scripts.js?ver=1748895544

js comozooconservatory.org collected 2026-09-24 17:37:40 UTC 194,954 bytes, 5,940 lines download raw bytes

vendor: 37,723 bytes, lines 1-1693
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) { 
5if (typeof define === 'function' && define.amd) { 
6 // AMD. Register as an anonymous module. 
7 define(['jquery'], factory); 
8 } else if (typeof exports === 'object') { 
9 // Node/CommonJS 
10 factory(require('jquery')); 
11 } else { 
12 // Browser globals 
13 factory(window.jQuery || window.Zepto); 
14 } 
15 }(function($) { 
16
17/*>>core*/
18/**
19 * 
20 * Magnific Popup Core JS file
21 * 
22 */
23
24
25/**
26 * Private static constants
27 */
28var CLOSE_EVENT = 'Close',
29	BEFORE_CLOSE_EVENT = 'BeforeClose',
30	AFTER_CLOSE_EVENT = 'AfterClose',
31	BEFORE_APPEND_EVENT = 'BeforeAppend',
32	MARKUP_PARSE_EVENT = 'MarkupParse',
33	OPEN_EVENT = 'Open',
34	CHANGE_EVENT = 'Change',
35	NS = 'mfp',
36	EVENT_NS = '.' + NS,
37	READY_CLASS = 'mfp-ready',
38	REMOVING_CLASS = 'mfp-removing',
39	PREVENT_CLOSE_CLASS = 'mfp-prevent-close';
40
41
42/**
43 * Private vars 
44 */
45/*jshint -W079 */
46var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
47	MagnificPopup = function(){},
48	_isJQ = !!(window.jQuery),
49	_prevStatus,
50	_window = $(window),
51	_document,
52	_prevContentType,
53	_wrapClasses,
54	_currPopupType;
55
56
57/**
58 * Private functions
59 */
60var _mfpOn = function(name, f) {
61		mfp.ev.on(NS + name + EVENT_NS, f);
62	},
63	_getEl = function(className, appendTo, html, raw) {
64		var el = document.createElement('div');
65		el.className = 'mfp-'+className;
66		if(html) {
67			el.innerHTML = html;
68		}
69		if(!raw) {
70			el = $(el);
71			if(appendTo) {
72				el.appendTo(appendTo);
73			}
74		} else if(appendTo) {
75			appendTo.appendChild(el);
76		}
77		return el;
78	},
79	_mfpTrigger = function(e, data) {
80		mfp.ev.triggerHandler(NS + e, data);
81
82		if(mfp.st.callbacks) {
83			// converts "mfpEventName" to "eventName" callback and triggers it if it's present
84			e = e.charAt(0).toLowerCase() + e.slice(1);
85			if(mfp.st.callbacks[e]) {
86				mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
87			}
88		}
89	},
90	_getCloseBtn = function(type) {
91		if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
92			mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
93			_currPopupType = type;
94		}
95		return mfp.currTemplate.closeBtn;
96	},
97	// Initialize Magnific Popup only when called at least once
98	_checkInstance = function() {
99		if(!$.magnificPopup.instance) {
100			/*jshint -W020 */
101			mfp = new MagnificPopup();
102			mfp.init();
103			$.magnificPopup.instance = mfp;
104		}
105	},
106	// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
107	supportsTransitions = function() {
108		var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
109			v = ['ms','O','Moz','Webkit']; // 'v' for vendor
110
111		if( s['transition'] !== undefined ) {
112			return true; 
113		}
114			
115		while( v.length ) {
116			if( v.pop() + 'Transition' in s ) {
117				return true;
118			}
119		}
120				
121		return false;
122	};
123
124
125
126/**
127 * Public functions
128 */
129MagnificPopup.prototype = {
130
131	constructor: MagnificPopup,
132
133	/**
134	 * Initializes Magnific Popup plugin. 
135	 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
136	 */
137	init: function() {
138		var appVersion = navigator.appVersion;
139		mfp.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
962var 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*/
1031var 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*/
1112var _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*/
1360var 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
1549var 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 */
1658var _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
1824var 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(); }));
1861// MagnificPopup
1862// -------------------------------------------------------------
1863jQuery(document).ready(function ($) {
1864  $('.video-popup').magnificPopup({
1865    type: 'iframe',
1866  });
1867
1868  $('.iframe-popup a').magnificPopup({
1869    type: 'iframe',
1870  });
1871
1872  $('.photo-popup').magnificPopup({
1873    type: 'image',
1874  });
1875
1876  $('.youtube-video').magnificPopup({
1877    type: 'iframe',
1878    iframe: {
1879      patterns: {
1880        youtube: {
1881          index: 'youtube.com/',
1882          id: 'v=',
1883          src: '//www.youtube.com/embed/%id%?rel=0&autoplay=1',
1884        },
1885      },
1886    },
1887  });
1888});
1889
vendor: 12,075 bytes, lines 1890-2330
1890/*!
1891 * imagesLoaded PACKAGED v5.0.0
1892 * JavaScript is all like "You images are done yet or what?"
1893 * MIT License
1894 */
1895
1896/**
1897 * EvEmitter v2.1.1
1898 * Lil' event emitter
1899 * MIT License
1900 */
1901
1902( function( global, factory ) {
1903  // universal module definition
1904  if ( typeof module == 'object' && module.exports ) {
1905    // CommonJS - Browserify, Webpack
1906    module.exports = factory();
1907  } else {
1908    // Browser globals
1909    global.EvEmitter = factory();
1910  }
1911
1912}( typeof window != 'undefined' ? window : this, function() {
1913
1914function EvEmitter() {}
1915
1916let proto = EvEmitter.prototype;
1917
1918proto.on = function( eventName, listener ) {
1919  if ( !eventName || !listener ) return this;
1920
1921  // set events hash
1922  let events = this._events = this._events || {};
1923  // set listeners array
1924  let listeners = events[ eventName ] = events[ eventName ] || [];
1925  // only add once
1926  if ( !listeners.includes( listener ) ) {
1927    listeners.push( listener );
1928  }
1929
1930  return this;
1931};
1932
1933proto.once = function( eventName, listener ) {
1934  if ( !eventName || !listener ) return this;
1935
1936  // add event
1937  this.on( eventName, listener );
1938  // set once flag
1939  // set onceEvents hash
1940  let onceEvents = this._onceEvents = this._onceEvents || {};
1941  // set onceListeners object
1942  let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
1943  // set flag
1944  onceListeners[ listener ] = true;
1945
1946  return this;
1947};
1948
1949proto.off = function( eventName, listener ) {
1950  let listeners = this._events && this._events[ eventName ];
1951  if ( !listeners || !listeners.length ) return this;
1952
1953  let index = listeners.indexOf( listener );
1954  if ( index != -1 ) {
1955    listeners.splice( index, 1 );
1956  }
1957
1958  return this;
1959};
1960
1961proto.emitEvent = function( eventName, args ) {
1962  let listeners = this._events && this._events[ eventName ];
1963  if ( !listeners || !listeners.length ) return this;
1964
1965  // copy over to avoid interference if .off() in listener
1966  listeners = listeners.slice( 0 );
1967  args = args || [];
1968  // once stuff
1969  let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
1970
1971  for ( let listener of listeners ) {
1972    let isOnce = onceListeners && onceListeners[ listener ];
1973    if ( isOnce ) {
1974      // remove listener
1975      // remove before trigger to prevent recursion
1976      this.off( eventName, listener );
1977      // unset once flag
1978      delete onceListeners[ listener ];
1979    }
1980    // trigger listener
1981    listener.apply( this, args );
1982  }
1983
1984  return this;
1985};
1986
1987proto.allOff = function() {
1988  delete this._events;
1989  delete this._onceEvents;
1990  return this;
1991};
1992
1993return EvEmitter;
1994
1995} ) );
1996/*!
1997 * imagesLoaded v5.0.0
1998 * JavaScript is all like "You images are done yet or what?"
1999 * MIT License
2000 */
2001
2002( function( window, factory ) {
2003  // universal module definition
2004  if ( typeof module == 'object' && module.exports ) {
2005    // CommonJS
2006    module.exports = factory( window, require('ev-emitter') );
2007  } else {
2008    // browser global
2009    window.imagesLoaded = factory( window, window.EvEmitter );
2010  }
2011
2012} )( typeof window !== 'undefined' ? window : this,
2013    function factory( window, EvEmitter ) {
2014
2015let $ = window.jQuery;
2016let console = window.console;
2017
2018// -------------------------- helpers -------------------------- //
2019
2020// turn element or nodeList into an array
2021function makeArray( obj ) {
2022  // use object if already an array
2023  if ( Array.isArray( obj ) ) return obj;
2024
2025  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
2026  // convert nodeList to array
2027  if ( isArrayLike ) return [ ...obj ];
2028
2029  // array of single index
2030  return [ obj ];
2031}
2032
2033// -------------------------- imagesLoaded -------------------------- //
2034
2035/**
2036 * @param {[Array, Element, NodeList, String]} elem
2037 * @param {[Object, Function]} options - if function, use as callback
2038 * @param {Function} onAlways - callback function
2039 * @returns {ImagesLoaded}
2040 */
2041function ImagesLoaded( elem, options, onAlways ) {
2042  // coerce ImagesLoaded() without new, to be new ImagesLoaded()
2043  if ( !( this instanceof ImagesLoaded ) ) {
2044    return new ImagesLoaded( elem, options, onAlways );
2045  }
2046  // use elem as selector string
2047  let queryElem = elem;
2048  if ( typeof elem == 'string' ) {
2049    queryElem = document.querySelectorAll( elem );
2050  }
2051  // bail if bad element
2052  if ( !queryElem ) {
2053    console.error(`Bad element for imagesLoaded ${queryElem || elem}`);
2054    return;
2055  }
2056
2057  this.elements = makeArray( queryElem );
2058  this.options = {};
2059  // shift arguments if no options set
2060  if ( typeof options == 'function' ) {
2061    onAlways = options;
2062  } else {
2063    Object.assign( this.options, options );
2064  }
2065
2066  if ( onAlways ) this.on( 'always', onAlways );
2067
2068  this.getImages();
2069  // add jQuery Deferred object
2070  if ( $ ) this.jqDeferred = new $.Deferred();
2071
2072  // HACK check async to allow time to bind listeners
2073  setTimeout( this.check.bind( this ) );
2074}
2075
2076ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
2077
2078ImagesLoaded.prototype.getImages = function() {
2079  this.images = [];
2080
2081  // filter & find items if we have an item selector
2082  this.elements.forEach( this.addElementImages, this );
2083};
2084
2085const elementNodeTypes = [ 1, 9, 11 ];
2086
2087/**
2088 * @param {Node} elem
2089 */
2090ImagesLoaded.prototype.addElementImages = function( elem ) {
2091  // filter siblings
2092  if ( elem.nodeName === 'IMG' ) {
2093    this.addImage( elem );
2094  }
2095  // get background image on element
2096  if ( this.options.background === true ) {
2097    this.addElementBackgroundImages( elem );
2098  }
2099
2100  // find children
2101  // no non-element nodes, #143
2102  let { nodeType } = elem;
2103  if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;
2104
2105  let childImgs = elem.querySelectorAll('img');
2106  // concat childElems to filterFound array
2107  for ( let img of childImgs ) {
2108    this.addImage( img );
2109  }
2110
2111  // get child background images
2112  if ( typeof this.options.background == 'string' ) {
2113    let children = elem.querySelectorAll( this.options.background );
2114    for ( let child of children ) {
2115      this.addElementBackgroundImages( child );
2116    }
2117  }
2118};
2119
2120const reURL = /url\((['"])?(.*?)\1\)/gi;
2121
2122ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
2123  let style = getComputedStyle( elem );
2124  // Firefox returns null if in a hidden iframe https://bugzil.la/548397
2125  if ( !style ) return;
2126
2127  // get url inside url("...")
2128  let matches = reURL.exec( style.backgroundImage );
2129  while ( matches !== null ) {
2130    let url = matches && matches[2];
2131    if ( url ) {
2132      this.addBackground( url, elem );
2133    }
2134    matches = reURL.exec( style.backgroundImage );
2135  }
2136};
2137
2138/**
2139 * @param {Image} img
2140 */
2141ImagesLoaded.prototype.addImage = function( img ) {
2142  let loadingImage = new LoadingImage( img );
2143  this.images.push( loadingImage );
2144};
2145
2146ImagesLoaded.prototype.addBackground = function( url, elem ) {
2147  let background = new Background( url, elem );
2148  this.images.push( background );
2149};
2150
2151ImagesLoaded.prototype.check = function() {
2152  this.progressedCount = 0;
2153  this.hasAnyBroken = false;
2154  // complete if no images
2155  if ( !this.images.length ) {
2156    this.complete();
2157    return;
2158  }
2159
2160  /* eslint-disable-next-line func-style */
2161  let onProgress = ( image, elem, message ) => {
2162    // HACK - Chrome triggers event before object properties have changed. #83
2163    setTimeout( () => {
2164      this.progress( image, elem, message );
2165    } );
2166  };
2167
2168  this.images.forEach( function( loadingImage ) {
2169    loadingImage.once( 'progress', onProgress );
2170    loadingImage.check();
2171  } );
2172};
2173
2174ImagesLoaded.prototype.progress = function( image, elem, message ) {
2175  this.progressedCount++;
2176  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
2177  // progress event
2178  this.emitEvent( 'progress', [ this, image, elem ] );
2179  if ( this.jqDeferred && this.jqDeferred.notify ) {
2180    this.jqDeferred.notify( this, image );
2181  }
2182  // check if completed
2183  if ( this.progressedCount === this.images.length ) {
2184    this.complete();
2185  }
2186
2187  if ( this.options.debug && console ) {
2188    console.log( `progress: ${message}`, image, elem );
2189  }
2190};
2191
2192ImagesLoaded.prototype.complete = function() {
2193  let eventName = this.hasAnyBroken ? 'fail' : 'done';
2194  this.isComplete = true;
2195  this.emitEvent( eventName, [ this ] );
2196  this.emitEvent( 'always', [ this ] );
2197  if ( this.jqDeferred ) {
2198    let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
2199    this.jqDeferred[ jqMethod ]( this );
2200  }
2201};
2202
2203// --------------------------  -------------------------- //
2204
2205function LoadingImage( img ) {
2206  this.img = img;
2207}
2208
2209LoadingImage.prototype = Object.create( EvEmitter.prototype );
2210
2211LoadingImage.prototype.check = function() {
2212  // If complete is true and browser supports natural sizes,
2213  // try to check for image status manually.
2214  let isComplete = this.getIsImageComplete();
2215  if ( isComplete ) {
2216    // report based on naturalWidth
2217    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
2218    return;
2219  }
2220
2221  // If none of the checks above matched, simulate loading on detached element.
2222  this.proxyImage = new Image();
2223  // add crossOrigin attribute. #204
2224  if ( this.img.crossOrigin ) {
2225    this.proxyImage.crossOrigin = this.img.crossOrigin;
2226  }
2227  this.proxyImage.addEventListener( 'load', this );
2228  this.proxyImage.addEventListener( 'error', this );
2229  // bind to image as well for Firefox. #191
2230  this.img.addEventListener( 'load', this );
2231  this.img.addEventListener( 'error', this );
2232  this.proxyImage.src = this.img.currentSrc || this.img.src;
2233};
2234
2235LoadingImage.prototype.getIsImageComplete = function() {
2236  // check for non-zero, non-undefined naturalWidth
2237  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
2238  return this.img.complete && this.img.naturalWidth;
2239};
2240
2241LoadingImage.prototype.confirm = function( isLoaded, message ) {
2242  this.isLoaded = isLoaded;
2243  let { parentNode } = this.img;
2244  // emit progress with parent <picture> or self <img>
2245  let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;
2246  this.emitEvent( 'progress', [ this, elem, message ] );
2247};
2248
2249// ----- events ----- //
2250
2251// trigger specified handler for event type
2252LoadingImage.prototype.handleEvent = function( event ) {
2253  let method = 'on' + event.type;
2254  if ( this[ method ] ) {
2255    this[ method ]( event );
2256  }
2257};
2258
2259LoadingImage.prototype.onload = function() {
2260  this.confirm( true, 'onload' );
2261  this.unbindEvents();
2262};
2263
2264LoadingImage.prototype.onerror = function() {
2265  this.confirm( false, 'onerror' );
2266  this.unbindEvents();
2267};
2268
2269LoadingImage.prototype.unbindEvents = function() {
2270  this.proxyImage.removeEventListener( 'load', this );
2271  this.proxyImage.removeEventListener( 'error', this );
2272  this.img.removeEventListener( 'load', this );
2273  this.img.removeEventListener( 'error', this );
2274};
2275
2276// -------------------------- Background -------------------------- //
2277
2278function Background( url, element ) {
2279  this.url = url;
2280  this.element = element;
2281  this.img = new Image();
2282}
2283
2284// inherit LoadingImage prototype
2285Background.prototype = Object.create( LoadingImage.prototype );
2286
2287Background.prototype.check = function() {
2288  this.img.addEventListener( 'load', this );
2289  this.img.addEventListener( 'error', this );
2290  this.img.src = this.url;
2291  // check if image is already complete
2292  let isComplete = this.getIsImageComplete();
2293  if ( isComplete ) {
2294    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
2295    this.unbindEvents();
2296  }
2297};
2298
2299Background.prototype.unbindEvents = function() {
2300  this.img.removeEventListener( 'load', this );
2301  this.img.removeEventListener( 'error', this );
2302};
2303
2304Background.prototype.confirm = function( isLoaded, message ) {
2305  this.isLoaded = isLoaded;
2306  this.emitEvent( 'progress', [ this, this.element, message ] );
2307};
2308
2309// -------------------------- jQuery -------------------------- //
2310
2311ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
2312  jQuery = jQuery || window.jQuery;
2313  if ( !jQuery ) return;
2314
2315  // set local variable
2316  $ = jQuery;
2317  // $().imagesLoaded()
2318  $.fn.imagesLoaded = function( options, onAlways ) {
2319    let instance = new ImagesLoaded( this, options, onAlways );
2320    return instance.jqDeferred.promise( $( this ) );
2321  };
2322};
2323// try making plugin
2324ImagesLoaded.makeJQueryPlugin();
2325
2326// --------------------------  -------------------------- //
2327
2328return ImagesLoaded;
2329
2330} );
2331
2332// ImagesLoaded
2333// ------------------------------------------------------------
2334
vendor: 95,083 bytes, lines 2335-5741
2335/*!
2336 * Flickity PACKAGED v3.0.0
2337 * Touch, responsive, flickable carousels
2338 *
2339 * Licensed GPLv3 for open source use
2340 * or Flickity Commercial License for commercial use
2341 *
2342 * https://flickity.metafizzy.co
2343 * Copyright 2015-2022 Metafizzy
2344 */
2345
2346/**
2347 * Bridget makes jQuery widgets
2348 * v3.0.1
2349 * MIT license
2350 */
2351
2352( function( window, factory ) {
2353  // module definition
2354 if ( typeof module == 'object' && module.exports ) {
2355   // CommonJS
2356   module.exports = factory(
2357       window,
2358       require('jquery'),
2359   );
2360 } else {
2361   // browser global
2362   window.jQueryBridget = factory(
2363       window,
2364       window.jQuery,
2365   );
2366 }
2367
2368}( window, function factory( window, jQuery ) {
2369
2370// ----- utils ----- //
2371
2372// helper function for logging errors
2373// $.error breaks jQuery chaining
2374let console = window.console;
2375let logError = typeof console == 'undefined' ? function() {} :
2376  function( message ) {
2377    console.error( message );
2378  };
2379
2380// ----- jQueryBridget ----- //
2381
2382function jQueryBridget( namespace, PluginClass, $ ) {
2383  $ = $ || jQuery || window.jQuery;
2384  if ( !$ ) {
2385    return;
2386  }
2387
2388  // add option method -> $().plugin('option', {...})
2389  if ( !PluginClass.prototype.option ) {
2390    // option setter
2391    PluginClass.prototype.option = function( opts ) {
2392      if ( !opts ) return;
2393
2394      this.options = Object.assign( this.options || {}, opts );
2395    };
2396  }
2397
2398  // make jQuery plugin
2399  $.fn[ namespace ] = function( arg0, ...args ) {
2400    if ( typeof arg0 == 'string' ) {
2401      // method call $().plugin( 'methodName', { options } )
2402      return methodCall( this, arg0, args );
2403    }
2404    // just $().plugin({ options })
2405    plainCall( this, arg0 );
2406    return this;
2407  };
2408
2409  // $().plugin('methodName')
2410  function methodCall( $elems, methodName, args ) {
2411    let returnValue;
2412    let pluginMethodStr = `$().${namespace}("${methodName}")`;
2413
2414    $elems.each( function( i, elem ) {
2415      // get instance
2416      let instance = $.data( elem, namespace );
2417      if ( !instance ) {
2418        logError( `${namespace} not initialized.` +
2419          ` Cannot call method ${pluginMethodStr}` );
2420        return;
2421      }
2422
2423      let method = instance[ methodName ];
2424      if ( !method || methodName.charAt( 0 ) == '_' ) {
2425        logError(`${pluginMethodStr} is not a valid method`);
2426        return;
2427      }
2428
2429      // apply method, get return value
2430      let value = method.apply( instance, args );
2431      // set return value if value is returned, use only first value
2432      returnValue = returnValue === undefined ? value : returnValue;
2433    } );
2434
2435    return returnValue !== undefined ? returnValue : $elems;
2436  }
2437
2438  function plainCall( $elems, options ) {
2439    $elems.each( function( i, elem ) {
2440      let instance = $.data( elem, namespace );
2441      if ( instance ) {
2442        // set options & init
2443        instance.option( options );
2444        instance._init();
2445      } else {
2446        // initialize new instance
2447        instance = new PluginClass( elem, options );
2448        $.data( elem, namespace, instance );
2449      }
2450    } );
2451  }
2452
2453}
2454
2455// -----  ----- //
2456
2457return jQueryBridget;
2458
2459} ) );
2460/**
2461 * EvEmitter v2.1.1
2462 * Lil' event emitter
2463 * MIT License
2464 */
2465
2466( function( global, factory ) {
2467  // universal module definition
2468  if ( typeof module == 'object' && module.exports ) {
2469    // CommonJS - Browserify, Webpack
2470    module.exports = factory();
2471  } else {
2472    // Browser globals
2473    global.EvEmitter = factory();
2474  }
2475
2476}( typeof window != 'undefined' ? window : this, function() {
2477
2478function EvEmitter() {}
2479
2480let proto = EvEmitter.prototype;
2481
2482proto.on = function( eventName, listener ) {
2483  if ( !eventName || !listener ) return this;
2484
2485  // set events hash
2486  let events = this._events = this._events || {};
2487  // set listeners array
2488  let listeners = events[ eventName ] = events[ eventName ] || [];
2489  // only add once
2490  if ( !listeners.includes( listener ) ) {
2491    listeners.push( listener );
2492  }
2493
2494  return this;
2495};
2496
2497proto.once = function( eventName, listener ) {
2498  if ( !eventName || !listener ) return this;
2499
2500  // add event
2501  this.on( eventName, listener );
2502  // set once flag
2503  // set onceEvents hash
2504  let onceEvents = this._onceEvents = this._onceEvents || {};
2505  // set onceListeners object
2506  let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
2507  // set flag
2508  onceListeners[ listener ] = true;
2509
2510  return this;
2511};
2512
2513proto.off = function( eventName, listener ) {
2514  let listeners = this._events && this._events[ eventName ];
2515  if ( !listeners || !listeners.length ) return this;
2516
2517  let index = listeners.indexOf( listener );
2518  if ( index != -1 ) {
2519    listeners.splice( index, 1 );
2520  }
2521
2522  return this;
2523};
2524
2525proto.emitEvent = function( eventName, args ) {
2526  let listeners = this._events && this._events[ eventName ];
2527  if ( !listeners || !listeners.length ) return this;
2528
2529  // copy over to avoid interference if .off() in listener
2530  listeners = listeners.slice( 0 );
2531  args = args || [];
2532  // once stuff
2533  let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
2534
2535  for ( let listener of listeners ) {
2536    let isOnce = onceListeners && onceListeners[ listener ];
2537    if ( isOnce ) {
2538      // remove listener
2539      // remove before trigger to prevent recursion
2540      this.off( eventName, listener );
2541      // unset once flag
2542      delete onceListeners[ listener ];
2543    }
2544    // trigger listener
2545    listener.apply( this, args );
2546  }
2547
2548  return this;
2549};
2550
2551proto.allOff = function() {
2552  delete this._events;
2553  delete this._onceEvents;
2554  return this;
2555};
2556
2557return EvEmitter;
2558
2559} ) );
2560/*!
2561 * Infinite Scroll v2.0.4
2562 * measure size of elements
2563 * MIT license
2564 */
2565
2566( function( window, factory ) {
2567  if ( typeof module == 'object' && module.exports ) {
2568    // CommonJS
2569    module.exports = factory();
2570  } else {
2571    // browser global
2572    window.getSize = factory();
2573  }
2574
2575} )( window, function factory() {
2576
2577// -------------------------- helpers -------------------------- //
2578
2579// get a number from a string, not a percentage
2580function getStyleSize( value ) {
2581  let num = parseFloat( value );
2582  // not a percent like '100%', and a number
2583  let isValid = value.indexOf('%') == -1 && !isNaN( num );
2584  return isValid && num;
2585}
2586
2587// -------------------------- measurements -------------------------- //
2588
2589let measurements = [
2590  'paddingLeft',
2591  'paddingRight',
2592  'paddingTop',
2593  'paddingBottom',
2594  'marginLeft',
2595  'marginRight',
2596  'marginTop',
2597  'marginBottom',
2598  'borderLeftWidth',
2599  'borderRightWidth',
2600  'borderTopWidth',
2601  'borderBottomWidth',
2602];
2603
2604let measurementsLength = measurements.length;
2605
2606function getZeroSize() {
2607  let size = {
2608    width: 0,
2609    height: 0,
2610    innerWidth: 0,
2611    innerHeight: 0,
2612    outerWidth: 0,
2613    outerHeight: 0,
2614  };
2615  measurements.forEach( ( measurement ) => {
2616    size[ measurement ] = 0;
2617  } );
2618  return size;
2619}
2620
2621// -------------------------- getSize -------------------------- //
2622
2623function getSize( elem ) {
2624  // use querySeletor if elem is string
2625  if ( typeof elem == 'string' ) elem = document.querySelector( elem );
2626
2627  // do not proceed on non-objects
2628  let isElement = elem && typeof elem == 'object' && elem.nodeType;
2629  if ( !isElement ) return;
2630
2631  let style = getComputedStyle( elem );
2632
2633  // if hidden, everything is 0
2634  if ( style.display == 'none' ) return getZeroSize();
2635
2636  let size = {};
2637  size.width = elem.offsetWidth;
2638  size.height = elem.offsetHeight;
2639
2640  let isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
2641
2642  // get all measurements
2643  measurements.forEach( ( measurement ) => {
2644    let value = style[ measurement ];
2645    let num = parseFloat( value );
2646    // any 'auto', 'medium' value will be 0
2647    size[ measurement ] = !isNaN( num ) ? num : 0;
2648  } );
2649
2650  let paddingWidth = size.paddingLeft + size.paddingRight;
2651  let paddingHeight = size.paddingTop + size.paddingBottom;
2652  let marginWidth = size.marginLeft + size.marginRight;
2653  let marginHeight = size.marginTop + size.marginBottom;
2654  let borderWidth = size.borderLeftWidth + size.borderRightWidth;
2655  let borderHeight = size.borderTopWidth + size.borderBottomWidth;
2656
2657  // overwrite width and height if we can get it from style
2658  let styleWidth = getStyleSize( style.width );
2659  if ( styleWidth !== false ) {
2660    size.width = styleWidth +
2661      // add padding and border unless it's already including it
2662      ( isBorderBox ? 0 : paddingWidth + borderWidth );
2663  }
2664
2665  let styleHeight = getStyleSize( style.height );
2666  if ( styleHeight !== false ) {
2667    size.height = styleHeight +
2668      // add padding and border unless it's already including it
2669      ( isBorderBox ? 0 : paddingHeight + borderHeight );
2670  }
2671
2672  size.innerWidth = size.width - ( paddingWidth + borderWidth );
2673  size.innerHeight = size.height - ( paddingHeight + borderHeight );
2674
2675  size.outerWidth = size.width + marginWidth;
2676  size.outerHeight = size.height + marginHeight;
2677
2678  return size;
2679}
2680
2681return getSize;
2682
2683} );
2684/**
2685 * Fizzy UI utils v3.0.0
2686 * MIT license
2687 */
2688
2689( function( global, factory ) {
2690  // universal module definition
2691  if ( typeof module == 'object' && module.exports ) {
2692    // CommonJS
2693    module.exports = factory( global );
2694  } else {
2695    // browser global
2696    global.fizzyUIUtils = factory( global );
2697  }
2698
2699}( this, function factory( global ) {
2700
2701let utils = {};
2702
2703// ----- extend ----- //
2704
2705// extends objects
2706utils.extend = function( a, b ) {
2707  return Object.assign( a, b );
2708};
2709
2710// ----- modulo ----- //
2711
2712utils.modulo = function( num, div ) {
2713  return ( ( num % div ) + div ) % div;
2714};
2715
2716// ----- makeArray ----- //
2717
2718// turn element or nodeList into an array
2719utils.makeArray = function( obj ) {
2720  // use object if already an array
2721  if ( Array.isArray( obj ) ) return obj;
2722
2723  // return empty array if undefined or null. #6
2724  if ( obj === null || obj === undefined ) return [];
2725
2726  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
2727  // convert nodeList to array
2728  if ( isArrayLike ) return [ ...obj ];
2729
2730  // array of single index
2731  return [ obj ];
2732};
2733
2734// ----- removeFrom ----- //
2735
2736utils.removeFrom = function( ary, obj ) {
2737  let index = ary.indexOf( obj );
2738  if ( index != -1 ) {
2739    ary.splice( index, 1 );
2740  }
2741};
2742
2743// ----- getParent ----- //
2744
2745utils.getParent = function( elem, selector ) {
2746  while ( elem.parentNode && elem != document.body ) {
2747    elem = elem.parentNode;
2748    if ( elem.matches( selector ) ) return elem;
2749  }
2750};
2751
2752// ----- getQueryElement ----- //
2753
2754// use element as selector string
2755utils.getQueryElement = function( elem ) {
2756  if ( typeof elem == 'string' ) {
2757    return document.querySelector( elem );
2758  }
2759  return elem;
2760};
2761
2762// ----- handleEvent ----- //
2763
2764// enable .ontype to trigger from .addEventListener( elem, 'type' )
2765utils.handleEvent = function( event ) {
2766  let method = 'on' + event.type;
2767  if ( this[ method ] ) {
2768    this[ method ]( event );
2769  }
2770};
2771
2772// ----- filterFindElements ----- //
2773
2774utils.filterFindElements = function( elems, selector ) {
2775  // make array of elems
2776  elems = utils.makeArray( elems );
2777
2778  return elems
2779    // check that elem is an actual element
2780    .filter( ( elem ) => elem instanceof HTMLElement )
2781    .reduce( ( ffElems, elem ) => {
2782      // add elem if no selector
2783      if ( !selector ) {
2784        ffElems.push( elem );
2785        return ffElems;
2786      }
2787      // filter & find items if we have a selector
2788      // filter
2789      if ( elem.matches( selector ) ) {
2790        ffElems.push( elem );
2791      }
2792      // find children
2793      let childElems = elem.querySelectorAll( selector );
2794      // concat childElems to filterFound array
2795      ffElems = ffElems.concat( ...childElems );
2796      return ffElems;
2797    }, [] );
2798};
2799
2800// ----- debounceMethod ----- //
2801
2802utils.debounceMethod = function( _class, methodName, threshold ) {
2803  threshold = threshold || 100;
2804  // original method
2805  let method = _class.prototype[ methodName ];
2806  let timeoutName = methodName + 'Timeout';
2807
2808  _class.prototype[ methodName ] = function() {
2809    clearTimeout( this[ timeoutName ] );
2810
2811    let args = arguments;
2812    this[ timeoutName ] = setTimeout( () => {
2813      method.apply( this, args );
2814      delete this[ timeoutName ];
2815    }, threshold );
2816  };
2817};
2818
2819// ----- docReady ----- //
2820
2821utils.docReady = function( onDocReady ) {
2822  let readyState = document.readyState;
2823  if ( readyState == 'complete' || readyState == 'interactive' ) {
2824    // do async to allow for other scripts to run. metafizzy/flickity#441
2825    setTimeout( onDocReady );
2826  } else {
2827    document.addEventListener( 'DOMContentLoaded', onDocReady );
2828  }
2829};
2830
2831// ----- htmlInit ----- //
2832
2833// http://bit.ly/3oYLusc
2834utils.toDashed = function( str ) {
2835  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
2836    return $1 + '-' + $2;
2837  } ).toLowerCase();
2838};
2839
2840let console = global.console;
2841
2842// allow user to initialize classes via [data-namespace] or .js-namespace class
2843// htmlInit( Widget, 'widgetName' )
2844// options are parsed from data-namespace-options
2845utils.htmlInit = function( WidgetClass, namespace ) {
2846  utils.docReady( function() {
2847    let dashedNamespace = utils.toDashed( namespace );
2848    let dataAttr = 'data-' + dashedNamespace;
2849    let dataAttrElems = document.querySelectorAll( `[${dataAttr}]` );
2850    let jQuery = global.jQuery;
2851
2852    [ ...dataAttrElems ].forEach( ( elem ) => {
2853      let attr = elem.getAttribute( dataAttr );
2854      let options;
2855      try {
2856        options = attr && JSON.parse( attr );
2857      } catch ( error ) {
2858        // log error, do not initialize
2859        if ( console ) {
2860          console.error( `Error parsing ${dataAttr} on ${elem.className}: ${error}` );
2861        }
2862        return;
2863      }
2864      // initialize
2865      let instance = new WidgetClass( elem, options );
2866      // make available via $().data('namespace')
2867      if ( jQuery ) {
2868        jQuery.data( elem, namespace, instance );
2869      }
2870    } );
2871
2872  } );
2873};
2874
2875// -----  ----- //
2876
2877return utils;
2878
2879} ) );
2880/*!
2881 * Unidragger v3.0.0
2882 * Draggable base class
2883 * MIT license
2884 */
2885
2886( function( window, factory ) {
2887  // universal module definition
2888  if ( typeof module == 'object' && module.exports ) {
2889    // CommonJS
2890    module.exports = factory(
2891        window,
2892        require('ev-emitter'),
2893    );
2894  } else {
2895    // browser global
2896    window.Unidragger = factory(
2897        window,
2898        window.EvEmitter,
2899    );
2900  }
2901
2902}( typeof window != 'undefined' ? window : this, function factory( window, EvEmitter ) {
2903
2904function Unidragger() {}
2905
2906// inherit EvEmitter
2907let proto = Unidragger.prototype = Object.create( EvEmitter.prototype );
2908
2909// ----- bind start ----- //
2910
2911// trigger handler methods for events
2912proto.handleEvent = function( event ) {
2913  let method = 'on' + event.type;
2914  if ( this[ method ] ) {
2915    this[ method ]( event );
2916  }
2917};
2918
2919let startEvent, activeEvents;
2920if ( 'ontouchstart' in window ) {
2921  // HACK prefer Touch Events as you can preventDefault on touchstart to
2922  // disable scroll in iOS & mobile Chrome metafizzy/flickity#1177
2923  startEvent = 'touchstart';
2924  activeEvents = [ 'touchmove', 'touchend', 'touchcancel' ];
2925} else if ( window.PointerEvent ) {
2926  // Pointer Events
2927  startEvent = 'pointerdown';
2928  activeEvents = [ 'pointermove', 'pointerup', 'pointercancel' ];
2929} else {
2930  // mouse events
2931  startEvent = 'mousedown';
2932  activeEvents = [ 'mousemove', 'mouseup' ];
2933}
2934
2935// prototype so it can be overwriteable by Flickity
2936proto.touchActionValue = 'none';
2937
2938proto.bindHandles = function() {
2939  this._bindHandles( 'addEventListener', this.touchActionValue );
2940};
2941
2942proto.unbindHandles = function() {
2943  this._bindHandles( 'removeEventListener', '' );
2944};
2945
2946/**
2947 * Add or remove start event
2948 * @param {String} bindMethod - addEventListener or removeEventListener
2949 * @param {String} touchAction - value for touch-action CSS property
2950 */
2951proto._bindHandles = function( bindMethod, touchAction ) {
2952  this.handles.forEach( ( handle ) => {
2953    handle[ bindMethod ]( startEvent, this );
2954    handle[ bindMethod ]( 'click', this );
2955    // touch-action: none to override browser touch gestures. metafizzy/flickity#540
2956    if ( window.PointerEvent ) handle.style.touchAction = touchAction;
2957  } );
2958};
2959
2960proto.bindActivePointerEvents = function() {
2961  activeEvents.forEach( ( eventName ) => {
2962    window.addEventListener( eventName, this );
2963  } );
2964};
2965
2966proto.unbindActivePointerEvents = function() {
2967  activeEvents.forEach( ( eventName ) => {
2968    window.removeEventListener( eventName, this );
2969  } );
2970};
2971
2972// ----- event handler helpers ----- //
2973
2974// trigger method with matching pointer
2975proto.withPointer = function( methodName, event ) {
2976  if ( event.pointerId == this.pointerIdentifier ) {
2977    this[ methodName ]( event, event );
2978  }
2979};
2980
2981// trigger method with matching touch
2982proto.withTouch = function( methodName, event ) {
2983  let touch;
2984  for ( let changedTouch of event.changedTouches ) {
2985    if ( changedTouch.identifier == this.pointerIdentifier ) {
2986      touch = changedTouch;
2987    }
2988  }
2989  if ( touch ) this[ methodName ]( event, touch );
2990};
2991
2992// ----- start event ----- //
2993
2994proto.onmousedown = function( event ) {
2995  this.pointerDown( event, event );
2996};
2997
2998proto.ontouchstart = function( event ) {
2999  this.pointerDown( event, event.changedTouches[0] );
3000};
3001
3002proto.onpointerdown = function( event ) {
3003  this.pointerDown( event, event );
3004};
3005
3006// nodes that have text fields
3007const cursorNodes = [ 'TEXTAREA', 'INPUT', 'SELECT', 'OPTION' ];
3008// input types that do not have text fields
3009const clickTypes = [ 'radio', 'checkbox', 'button', 'submit', 'image', 'file' ];
3010
3011/**
3012 * any time you set `event, pointer` it refers to:
3013 * @param {Event} event
3014 * @param {Event | Touch} pointer
3015 */
3016proto.pointerDown = function( event, pointer ) {
3017  // dismiss multi-touch taps, right clicks, and clicks on text fields
3018  let isCursorNode = cursorNodes.includes( event.target.nodeName );
3019  let isClickType = clickTypes.includes( event.target.type );
3020  let isOkayElement = !isCursorNode || isClickType;
3021  let isOkay = !this.isPointerDown && !event.button && isOkayElement;
3022  if ( !isOkay ) return;
3023
3024  this.isPointerDown = true;
3025  // save pointer identifier to match up touch events
3026  this.pointerIdentifier = pointer.pointerId !== undefined ?
3027    // pointerId for pointer events, touch.indentifier for touch events
3028    pointer.pointerId : pointer.identifier;
3029  // track position for move
3030  this.pointerDownPointer = {
3031    pageX: pointer.pageX,
3032    pageY: pointer.pageY,
3033  };
3034
3035  this.bindActivePointerEvents();
3036  this.emitEvent( 'pointerDown', [ event, pointer ] );
3037};
3038
3039// ----- move ----- //
3040
3041proto.onmousemove = function( event ) {
3042  this.pointerMove( event, event );
3043};
3044
3045proto.onpointermove = function( event ) {
3046  this.withPointer( 'pointerMove', event );
3047};
3048
3049proto.ontouchmove = function( event ) {
3050  this.withTouch( 'pointerMove', event );
3051};
3052
3053proto.pointerMove = function( event, pointer ) {
3054  let moveVector = {
3055    x: pointer.pageX - this.pointerDownPointer.pageX,
3056    y: pointer.pageY - this.pointerDownPointer.pageY,
3057  };
3058  this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] );
3059  // start drag if pointer has moved far enough to start drag
3060  let isDragStarting = !this.isDragging && this.hasDragStarted( moveVector );
3061  if ( isDragStarting ) this.dragStart( event, pointer );
3062  if ( this.isDragging ) this.dragMove( event, pointer, moveVector );
3063};
3064
3065// condition if pointer has moved far enough to start drag
3066proto.hasDragStarted = function( moveVector ) {
3067  return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3;
3068};
3069
3070// ----- drag ----- //
3071
3072proto.dragStart = function( event, pointer ) {
3073  this.isDragging = true;
3074  this.isPreventingClicks = true; // set flag to prevent clicks
3075  this.emitEvent( 'dragStart', [ event, pointer ] );
3076};
3077
3078proto.dragMove = function( event, pointer, moveVector ) {
3079  this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );
3080};
3081
3082// ----- end ----- //
3083
3084proto.onmouseup = function( event ) {
3085  this.pointerUp( event, event );
3086};
3087
3088proto.onpointerup = function( event ) {
3089  this.withPointer( 'pointerUp', event );
3090};
3091
3092proto.ontouchend = function( event ) {
3093  this.withTouch( 'pointerUp', event );
3094};
3095
3096proto.pointerUp = function( event, pointer ) {
3097  this.pointerDone();
3098  this.emitEvent( 'pointerUp', [ event, pointer ] );
3099
3100  if ( this.isDragging ) {
3101    this.dragEnd( event, pointer );
3102  } else {
3103    // pointer didn't move enough for drag to start
3104    this.staticClick( event, pointer );
3105  }
3106};
3107
3108proto.dragEnd = function( event, pointer ) {
3109  this.isDragging = false; // reset flag
3110  // re-enable clicking async
3111  setTimeout( () => delete this.isPreventingClicks );
3112
3113  this.emitEvent( 'dragEnd', [ event, pointer ] );
3114};
3115
3116// triggered on pointer up & pointer cancel
3117proto.pointerDone = function() {
3118  this.isPointerDown = false;
3119  delete this.pointerIdentifier;
3120  this.unbindActivePointerEvents();
3121  this.emitEvent('pointerDone');
3122};
3123
3124// ----- cancel ----- //
3125
3126proto.onpointercancel = function( event ) {
3127  this.withPointer( 'pointerCancel', event );
3128};
3129
3130proto.ontouchcancel = function( event ) {
3131  this.withTouch( 'pointerCancel', event );
3132};
3133
3134proto.pointerCancel = function( event, pointer ) {
3135  this.pointerDone();
3136  this.emitEvent( 'pointerCancel', [ event, pointer ] );
3137};
3138
3139// ----- click ----- //
3140
3141// handle all clicks and prevent clicks when dragging
3142proto.onclick = function( event ) {
3143  if ( this.isPreventingClicks ) event.preventDefault();
3144};
3145
3146// triggered after pointer down & up with no/tiny movement
3147proto.staticClick = function( event, pointer ) {
3148  // ignore emulated mouse up clicks
3149  let isMouseup = event.type == 'mouseup';
3150  if ( isMouseup && this.isIgnoringMouseUp ) return;
3151
3152  this.emitEvent( 'staticClick', [ event, pointer ] );
3153
3154  // set flag for emulated clicks 300ms after touchend
3155  if ( isMouseup ) {
3156    this.isIgnoringMouseUp = true;
3157    // reset flag after 400ms
3158    setTimeout( () => {
3159      delete this.isIgnoringMouseUp;
3160    }, 400 );
3161  }
3162};
3163
3164// -----  ----- //
3165
3166return Unidragger;
3167
3168} ) );
3169/*!
3170 * imagesLoaded v5.0.0
3171 * JavaScript is all like "You images are done yet or what?"
3172 * MIT License
3173 */
3174
3175( function( window, factory ) {
3176  // universal module definition
3177  if ( typeof module == 'object' && module.exports ) {
3178    // CommonJS
3179    module.exports = factory( window, require('ev-emitter') );
3180  } else {
3181    // browser global
3182    window.imagesLoaded = factory( window, window.EvEmitter );
3183  }
3184
3185} )( typeof window !== 'undefined' ? window : this,
3186    function factory( window, EvEmitter ) {
3187
3188let $ = window.jQuery;
3189let console = window.console;
3190
3191// -------------------------- helpers -------------------------- //
3192
3193// turn element or nodeList into an array
3194function makeArray( obj ) {
3195  // use object if already an array
3196  if ( Array.isArray( obj ) ) return obj;
3197
3198  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
3199  // convert nodeList to array
3200  if ( isArrayLike ) return [ ...obj ];
3201
3202  // array of single index
3203  return [ obj ];
3204}
3205
3206// -------------------------- imagesLoaded -------------------------- //
3207
3208/**
3209 * @param {[Array, Element, NodeList, String]} elem
3210 * @param {[Object, Function]} options - if function, use as callback
3211 * @param {Function} onAlways - callback function
3212 * @returns {ImagesLoaded}
3213 */
3214function ImagesLoaded( elem, options, onAlways ) {
3215  // coerce ImagesLoaded() without new, to be new ImagesLoaded()
3216  if ( !( this instanceof ImagesLoaded ) ) {
3217    return new ImagesLoaded( elem, options, onAlways );
3218  }
3219  // use elem as selector string
3220  let queryElem = elem;
3221  if ( typeof elem == 'string' ) {
3222    queryElem = document.querySelectorAll( elem );
3223  }
3224  // bail if bad element
3225  if ( !queryElem ) {
3226    console.error(`Bad element for imagesLoaded ${queryElem || elem}`);
3227    return;
3228  }
3229
3230  this.elements = makeArray( queryElem );
3231  this.options = {};
3232  // shift arguments if no options set
3233  if ( typeof options == 'function' ) {
3234    onAlways = options;
3235  } else {
3236    Object.assign( this.options, options );
3237  }
3238
3239  if ( onAlways ) this.on( 'always', onAlways );
3240
3241  this.getImages();
3242  // add jQuery Deferred object
3243  if ( $ ) this.jqDeferred = new $.Deferred();
3244
3245  // HACK check async to allow time to bind listeners
3246  setTimeout( this.check.bind( this ) );
3247}
3248
3249ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
3250
3251ImagesLoaded.prototype.getImages = function() {
3252  this.images = [];
3253
3254  // filter & find items if we have an item selector
3255  this.elements.forEach( this.addElementImages, this );
3256};
3257
3258const elementNodeTypes = [ 1, 9, 11 ];
3259
3260/**
3261 * @param {Node} elem
3262 */
3263ImagesLoaded.prototype.addElementImages = function( elem ) {
3264  // filter siblings
3265  if ( elem.nodeName === 'IMG' ) {
3266    this.addImage( elem );
3267  }
3268  // get background image on element
3269  if ( this.options.background === true ) {
3270    this.addElementBackgroundImages( elem );
3271  }
3272
3273  // find children
3274  // no non-element nodes, #143
3275  let { nodeType } = elem;
3276  if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;
3277
3278  let childImgs = elem.querySelectorAll('img');
3279  // concat childElems to filterFound array
3280  for ( let img of childImgs ) {
3281    this.addImage( img );
3282  }
3283
3284  // get child background images
3285  if ( typeof this.options.background == 'string' ) {
3286    let children = elem.querySelectorAll( this.options.background );
3287    for ( let child of children ) {
3288      this.addElementBackgroundImages( child );
3289    }
3290  }
3291};
3292
3293const reURL = /url\((['"])?(.*?)\1\)/gi;
3294
3295ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
3296  let style = getComputedStyle( elem );
3297  // Firefox returns null if in a hidden iframe https://bugzil.la/548397
3298  if ( !style ) return;
3299
3300  // get url inside url("...")
3301  let matches = reURL.exec( style.backgroundImage );
3302  while ( matches !== null ) {
3303    let url = matches && matches[2];
3304    if ( url ) {
3305      this.addBackground( url, elem );
3306    }
3307    matches = reURL.exec( style.backgroundImage );
3308  }
3309};
3310
3311/**
3312 * @param {Image} img
3313 */
3314ImagesLoaded.prototype.addImage = function( img ) {
3315  let loadingImage = new LoadingImage( img );
3316  this.images.push( loadingImage );
3317};
3318
3319ImagesLoaded.prototype.addBackground = function( url, elem ) {
3320  let background = new Background( url, elem );
3321  this.images.push( background );
3322};
3323
3324ImagesLoaded.prototype.check = function() {
3325  this.progressedCount = 0;
3326  this.hasAnyBroken = false;
3327  // complete if no images
3328  if ( !this.images.length ) {
3329    this.complete();
3330    return;
3331  }
3332
3333  /* eslint-disable-next-line func-style */
3334  let onProgress = ( image, elem, message ) => {
3335    // HACK - Chrome triggers event before object properties have changed. #83
3336    setTimeout( () => {
3337      this.progress( image, elem, message );
3338    } );
3339  };
3340
3341  this.images.forEach( function( loadingImage ) {
3342    loadingImage.once( 'progress', onProgress );
3343    loadingImage.check();
3344  } );
3345};
3346
3347ImagesLoaded.prototype.progress = function( image, elem, message ) {
3348  this.progressedCount++;
3349  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
3350  // progress event
3351  this.emitEvent( 'progress', [ this, image, elem ] );
3352  if ( this.jqDeferred && this.jqDeferred.notify ) {
3353    this.jqDeferred.notify( this, image );
3354  }
3355  // check if completed
3356  if ( this.progressedCount === this.images.length ) {
3357    this.complete();
3358  }
3359
3360  if ( this.options.debug && console ) {
3361    console.log( `progress: ${message}`, image, elem );
3362  }
3363};
3364
3365ImagesLoaded.prototype.complete = function() {
3366  let eventName = this.hasAnyBroken ? 'fail' : 'done';
3367  this.isComplete = true;
3368  this.emitEvent( eventName, [ this ] );
3369  this.emitEvent( 'always', [ this ] );
3370  if ( this.jqDeferred ) {
3371    let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
3372    this.jqDeferred[ jqMethod ]( this );
3373  }
3374};
3375
3376// --------------------------  -------------------------- //
3377
3378function LoadingImage( img ) {
3379  this.img = img;
3380}
3381
3382LoadingImage.prototype = Object.create( EvEmitter.prototype );
3383
3384LoadingImage.prototype.check = function() {
3385  // If complete is true and browser supports natural sizes,
3386  // try to check for image status manually.
3387  let isComplete = this.getIsImageComplete();
3388  if ( isComplete ) {
3389    // report based on naturalWidth
3390    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
3391    return;
3392  }
3393
3394  // If none of the checks above matched, simulate loading on detached element.
3395  this.proxyImage = new Image();
3396  // add crossOrigin attribute. #204
3397  if ( this.img.crossOrigin ) {
3398    this.proxyImage.crossOrigin = this.img.crossOrigin;
3399  }
3400  this.proxyImage.addEventListener( 'load', this );
3401  this.proxyImage.addEventListener( 'error', this );
3402  // bind to image as well for Firefox. #191
3403  this.img.addEventListener( 'load', this );
3404  this.img.addEventListener( 'error', this );
3405  this.proxyImage.src = this.img.currentSrc || this.img.src;
3406};
3407
3408LoadingImage.prototype.getIsImageComplete = function() {
3409  // check for non-zero, non-undefined naturalWidth
3410  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
3411  return this.img.complete && this.img.naturalWidth;
3412};
3413
3414LoadingImage.prototype.confirm = function( isLoaded, message ) {
3415  this.isLoaded = isLoaded;
3416  let { parentNode } = this.img;
3417  // emit progress with parent <picture> or self <img>
3418  let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;
3419  this.emitEvent( 'progress', [ this, elem, message ] );
3420};
3421
3422// ----- events ----- //
3423
3424// trigger specified handler for event type
3425LoadingImage.prototype.handleEvent = function( event ) {
3426  let method = 'on' + event.type;
3427  if ( this[ method ] ) {
3428    this[ method ]( event );
3429  }
3430};
3431
3432LoadingImage.prototype.onload = function() {
3433  this.confirm( true, 'onload' );
3434  this.unbindEvents();
3435};
3436
3437LoadingImage.prototype.onerror = function() {
3438  this.confirm( false, 'onerror' );
3439  this.unbindEvents();
3440};
3441
3442LoadingImage.prototype.unbindEvents = function() {
3443  this.proxyImage.removeEventListener( 'load', this );
3444  this.proxyImage.removeEventListener( 'error', this );
3445  this.img.removeEventListener( 'load', this );
3446  this.img.removeEventListener( 'error', this );
3447};
3448
3449// -------------------------- Background -------------------------- //
3450
3451function Background( url, element ) {
3452  this.url = url;
3453  this.element = element;
3454  this.img = new Image();
3455}
3456
3457// inherit LoadingImage prototype
3458Background.prototype = Object.create( LoadingImage.prototype );
3459
3460Background.prototype.check = function() {
3461  this.img.addEventListener( 'load', this );
3462  this.img.addEventListener( 'error', this );
3463  this.img.src = this.url;
3464  // check if image is already complete
3465  let isComplete = this.getIsImageComplete();
3466  if ( isComplete ) {
3467    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
3468    this.unbindEvents();
3469  }
3470};
3471
3472Background.prototype.unbindEvents = function() {
3473  this.img.removeEventListener( 'load', this );
3474  this.img.removeEventListener( 'error', this );
3475};
3476
3477Background.prototype.confirm = function( isLoaded, message ) {
3478  this.isLoaded = isLoaded;
3479  this.emitEvent( 'progress', [ this, this.element, message ] );
3480};
3481
3482// -------------------------- jQuery -------------------------- //
3483
3484ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
3485  jQuery = jQuery || window.jQuery;
3486  if ( !jQuery ) return;
3487
3488  // set local variable
3489  $ = jQuery;
3490  // $().imagesLoaded()
3491  $.fn.imagesLoaded = function( options, onAlways ) {
3492    let instance = new ImagesLoaded( this, options, onAlways );
3493    return instance.jqDeferred.promise( $( this ) );
3494  };
3495};
3496// try making plugin
3497ImagesLoaded.makeJQueryPlugin();
3498
3499// --------------------------  -------------------------- //
3500
3501return ImagesLoaded;
3502
3503} );
3504// Flickity.Cell
3505( function( window, factory ) {
3506  // universal module definition
3507  if ( typeof module == 'object' && module.exports ) {
3508    // CommonJS
3509    module.exports = factory( require('get-size') );
3510  } else {
3511    // browser global
3512    window.Flickity = window.Flickity || {};
3513    window.Flickity.Cell = factory( window.getSize );
3514  }
3515
3516}( typeof window != 'undefined' ? window : this, function factory( getSize ) {
3517
3518const cellClassName = 'flickity-cell';
3519
3520function Cell( elem ) {
3521  this.element = elem;
3522  this.element.classList.add( cellClassName );
3523
3524  this.x = 0;
3525  this.unselect();
3526}
3527
3528let proto = Cell.prototype;
3529
3530proto.destroy = function() {
3531  // reset style
3532  this.unselect();
3533  this.element.classList.remove( cellClassName );
3534  this.element.style.transform = '';
3535  this.element.removeAttribute('aria-hidden');
3536};
3537
3538proto.getSize = function() {
3539  this.size = getSize( this.element );
3540};
3541
3542proto.select = function() {
3543  this.element.classList.add('is-selected');
3544  this.element.removeAttribute('aria-hidden');
3545};
3546
3547proto.unselect = function() {
3548  this.element.classList.remove('is-selected');
3549  this.element.setAttribute( 'aria-hidden', 'true' );
3550};
3551
3552proto.remove = function() {
3553  this.element.remove();
3554};
3555
3556return Cell;
3557
3558} ) );
3559// slide
3560( function( window, factory ) {
3561  // universal module definition
3562  if ( typeof module == 'object' && module.exports ) {
3563    // CommonJS
3564    module.exports = factory();
3565  } else {
3566    // browser global
3567    window.Flickity = window.Flickity || {};
3568    window.Flickity.Slide = factory();
3569  }
3570
3571}( typeof window != 'undefined' ? window : this, function factory() {
3572
3573function Slide( beginMargin, endMargin, cellAlign ) {
3574  this.beginMargin = beginMargin;
3575  this.endMargin = endMargin;
3576  this.cellAlign = cellAlign;
3577  this.cells = [];
3578  this.outerWidth = 0;
3579  this.height = 0;
3580}
3581
3582let proto = Slide.prototype;
3583
3584proto.addCell = function( cell ) {
3585  this.cells.push( cell );
3586  this.outerWidth += cell.size.outerWidth;
3587  this.height = Math.max( cell.size.outerHeight, this.height );
3588  // first cell stuff
3589  if ( this.cells.length === 1 ) {
3590    this.x = cell.x; // x comes from first cell
3591    this.firstMargin = cell.size[ this.beginMargin ];
3592  }
3593};
3594
3595proto.updateTarget = function() {
3596  let lastCell = this.getLastCell();
3597  let lastMargin = lastCell ? lastCell.size[ this.endMargin ] : 0;
3598  let slideWidth = this.outerWidth - ( this.firstMargin + lastMargin );
3599  this.target = this.x + this.firstMargin + slideWidth * this.cellAlign;
3600};
3601
3602proto.getLastCell = function() {
3603  return this.cells[ this.cells.length - 1 ];
3604};
3605
3606proto.select = function() {
3607  this.cells.forEach( ( cell ) => cell.select() );
3608};
3609
3610proto.unselect = function() {
3611  this.cells.forEach( ( cell ) => cell.unselect() );
3612};
3613
3614proto.getCellElements = function() {
3615  return this.cells.map( ( cell ) => cell.element );
3616};
3617
3618return Slide;
3619
3620} ) );
3621// animate
3622( function( window, factory ) {
3623  // universal module definition
3624  if ( typeof module == 'object' && module.exports ) {
3625    // CommonJS
3626    module.exports = factory( require('fizzy-ui-utils') );
3627  } else {
3628    // browser global
3629    window.Flickity = window.Flickity || {};
3630    window.Flickity.animatePrototype = factory( window.fizzyUIUtils );
3631  }
3632
3633}( typeof window != 'undefined' ? window : this, function factory( utils ) {
3634
3635// -------------------------- animate -------------------------- //
3636
3637let proto = {};
3638
3639proto.startAnimation = function() {
3640  if ( this.isAnimating ) return;
3641
3642  this.isAnimating = true;
3643  this.restingFrames = 0;
3644  this.animate();
3645};
3646
3647proto.animate = function() {
3648  this.applyDragForce();
3649  this.applySelectedAttraction();
3650
3651  let previousX = this.x;
3652
3653  this.integratePhysics();
3654  this.positionSlider();
3655  this.settle( previousX );
3656  // animate next frame
3657  if ( this.isAnimating ) requestAnimationFrame( () => this.animate() );
3658};
3659
3660proto.positionSlider = function() {
3661  let x = this.x;
3662  // wrap position around
3663  if ( this.isWrapping ) {
3664    x = utils.modulo( x, this.slideableWidth ) - this.slideableWidth;
3665    this.shiftWrapCells( x );
3666  }
3667
3668  this.setTranslateX( x, this.isAnimating );
3669  this.dispatchScrollEvent();
3670};
3671
3672proto.setTranslateX = function( x, is3d ) {
3673  x += this.cursorPosition;
3674  // reverse if right-to-left and using transform
3675  if ( this.options.rightToLeft ) x = -x;
3676  let translateX = this.getPositionValue( x );
3677  // use 3D transforms for hardware acceleration on iOS
3678  // but use 2D when settled, for better font-rendering
3679  this.slider.style.transform = is3d ?
3680    `translate3d(${translateX},0,0)` : `translateX(${translateX})`;
3681};
3682
3683proto.dispatchScrollEvent = function() {
3684  let firstSlide = this.slides[0];
3685  if ( !firstSlide ) return;
3686
3687  let positionX = -this.x - firstSlide.target;
3688  let progress = positionX / this.slidesWidth;
3689  this.dispatchEvent( 'scroll', null, [ progress, positionX ] );
3690};
3691
3692proto.positionSliderAtSelected = function() {
3693  if ( !this.cells.length ) return;
3694
3695  this.x = -this.selectedSlide.target;
3696  this.velocity = 0; // stop wobble
3697  this.positionSlider();
3698};
3699
3700proto.getPositionValue = function( position ) {
3701  if ( this.options.percentPosition ) {
3702    // percent position, round to 2 digits, like 12.34%
3703    return ( Math.round( ( position / this.size.innerWidth ) * 10000 ) * 0.01 ) + '%';
3704  } else {
3705    // pixel positioning
3706    return Math.round( position ) + 'px';
3707  }
3708};
3709
3710proto.settle = function( previousX ) {
3711  // keep track of frames where x hasn't moved
3712  let isResting = !this.isPointerDown &&
3713      Math.round( this.x * 100 ) === Math.round( previousX * 100 );
3714  if ( isResting ) this.restingFrames++;
3715  // stop animating if resting for 3 or more frames
3716  if ( this.restingFrames > 2 ) {
3717    this.isAnimating = false;
3718    delete this.isFreeScrolling;
3719    // render position with translateX when settled
3720    this.positionSlider();
3721    this.dispatchEvent( 'settle', null, [ this.selectedIndex ] );
3722  }
3723};
3724
3725proto.shiftWrapCells = function( x ) {
3726  // shift before cells
3727  let beforeGap = this.cursorPosition + x;
3728  this._shiftCells( this.beforeShiftCells, beforeGap, -1 );
3729  // shift after cells
3730  let afterGap = this.size.innerWidth - ( x + this.slideableWidth + this.cursorPosition );
3731  this._shiftCells( this.afterShiftCells, afterGap, 1 );
3732};
3733
3734proto._shiftCells = function( cells, gap, shift ) {
3735  cells.forEach( ( cell ) => {
3736    let cellShift = gap > 0 ? shift : 0;
3737    this._wrapShiftCell( cell, cellShift );
3738    gap -= cell.size.outerWidth;
3739  } );
3740};
3741
3742proto._unshiftCells = function( cells ) {
3743  if ( !cells || !cells.length ) return;
3744
3745  cells.forEach( ( cell ) => this._wrapShiftCell( cell, 0 ) );
3746};
3747
3748// @param {Integer} shift - 0, 1, or -1
3749proto._wrapShiftCell = function( cell, shift ) {
3750  this._renderCellPosition( cell, cell.x + this.slideableWidth * shift );
3751};
3752
3753// -------------------------- physics -------------------------- //
3754
3755proto.integratePhysics = function() {
3756  this.x += this.velocity;
3757  this.velocity *= this.getFrictionFactor();
3758};
3759
3760proto.applyForce = function( force ) {
3761  this.velocity += force;
3762};
3763
3764proto.getFrictionFactor = function() {
3765  return 1 - this.options[ this.isFreeScrolling ? 'freeScrollFriction' : 'friction' ];
3766};
3767
3768proto.getRestingPosition = function() {
3769  // my thanks to Steven Wittens, who simplified this math greatly
3770  return this.x + this.velocity / ( 1 - this.getFrictionFactor() );
3771};
3772
3773proto.applyDragForce = function() {
3774  if ( !this.isDraggable || !this.isPointerDown ) return;
3775
3776  // change the position to drag position by applying force
3777  let dragVelocity = this.dragX - this.x;
3778  let dragForce = dragVelocity - this.velocity;
3779  this.applyForce( dragForce );
3780};
3781
3782proto.applySelectedAttraction = function() {
3783  // do not attract if pointer down or no slides
3784  let dragDown = this.isDraggable && this.isPointerDown;
3785  if ( dragDown || this.isFreeScrolling || !this.slides.length ) return;
3786
3787  let distance = this.selectedSlide.target * -1 - this.x;
3788  let force = distance * this.options.selectedAttraction;
3789  this.applyForce( force );
3790};
3791
3792return proto;
3793
3794} ) );
3795// Flickity main
3796/* eslint-disable max-params */
3797( function( window, factory ) {
3798  // universal module definition
3799  if ( typeof module == 'object' && module.exports ) {
3800    // CommonJS
3801    module.exports = factory(
3802        window,
3803        require('ev-emitter'),
3804        require('get-size'),
3805        require('fizzy-ui-utils'),
3806        require('./cell'),
3807        require('./slide'),
3808        require('./animate'),
3809    );
3810  } else {
3811    // browser global
3812    let _Flickity = window.Flickity;
3813
3814    window.Flickity = factory(
3815        window,
3816        window.EvEmitter,
3817        window.getSize,
3818        window.fizzyUIUtils,
3819        _Flickity.Cell,
3820        _Flickity.Slide,
3821        _Flickity.animatePrototype,
3822    );
3823  }
3824
3825}( typeof window != 'undefined' ? window : this,
3826    function factory( window, EvEmitter, getSize, utils, Cell, Slide, animatePrototype ) {
3827/* eslint-enable max-params */
3828
3829// vars
3830const { getComputedStyle, console } = window;
3831let { jQuery } = window;
3832
3833// -------------------------- Flickity -------------------------- //
3834
3835// globally unique identifiers
3836let GUID = 0;
3837// internal store of all Flickity intances
3838let instances = {};
3839
3840function Flickity( element, options ) {
3841  let queryElement = utils.getQueryElement( element );
3842  if ( !queryElement ) {
3843    if ( console ) console.error(`Bad element for Flickity: ${queryElement || element}`);
3844    return;
3845  }
3846  this.element = queryElement;
3847  // do not initialize twice on same element
3848  if ( this.element.flickityGUID ) {
3849    let instance = instances[ this.element.flickityGUID ];
3850    if ( instance ) instance.option( options );
3851    return instance;
3852  }
3853
3854  // add jQuery
3855  if ( jQuery ) {
3856    this.$element = jQuery( this.element );
3857  }
3858  // options
3859  this.options = { ...this.constructor.defaults };
3860  this.option( options );
3861
3862  // kick things off
3863  this._create();
3864}
3865
3866Flickity.defaults = {
3867  accessibility: true,
3868  // adaptiveHeight: false,
3869  cellAlign: 'center',
3870  // cellSelector: undefined,
3871  // contain: false,
3872  freeScrollFriction: 0.075, // friction when free-scrolling
3873  friction: 0.28, // friction when selecting
3874  namespaceJQueryEvents: true,
3875  // initialIndex: 0,
3876  percentPosition: true,
3877  resize: true,
3878  selectedAttraction: 0.025,
3879  setGallerySize: true,
3880  // watchCSS: false,
3881  // wrapAround: false
3882};
3883
3884// hash of methods triggered on _create()
3885Flickity.create = {};
3886
3887let proto = Flickity.prototype;
3888// inherit EventEmitter
3889Object.assign( proto, EvEmitter.prototype );
3890
3891proto._create = function() {
3892  let { resize, watchCSS, rightToLeft } = this.options;
3893  // add id for Flickity.data
3894  let id = this.guid = ++GUID;
3895  this.element.flickityGUID = id; // expando
3896  instances[ id ] = this; // associate via id
3897  // initial properties
3898  this.selectedIndex = 0;
3899  // how many frames slider has been in same position
3900  this.restingFrames = 0;
3901  // initial physics properties
3902  this.x = 0;
3903  this.velocity = 0;
3904  this.beginMargin = rightToLeft ? 'marginRight' : 'marginLeft';
3905  this.endMargin = rightToLeft ? 'marginLeft' : 'marginRight';
3906  // create viewport & slider
3907  this.viewport = document.createElement('div');
3908  this.viewport.className = 'flickity-viewport';
3909  this._createSlider();
3910  // used for keyboard navigation
3911  this.focusableElems = [ this.element ];
3912
3913  if ( resize || watchCSS ) {
3914    window.addEventListener( 'resize', this );
3915  }
3916
3917  // add listeners from on option
3918  for ( let eventName in this.options.on ) {
3919    let listener = this.options.on[ eventName ];
3920    this.on( eventName, listener );
3921  }
3922
3923  for ( let method in Flickity.create ) {
3924    Flickity.create[ method ].call( this );
3925  }
3926
3927  if ( watchCSS ) {
3928    this.watchCSS();
3929  } else {
3930    this.activate();
3931  }
3932};
3933
3934/**
3935 * set options
3936 * @param {Object} opts - options to extend
3937 */
3938proto.option = function( opts ) {
3939  Object.assign( this.options, opts );
3940};
3941
3942proto.activate = function() {
3943  if ( this.isActive ) return;
3944
3945  this.isActive = true;
3946  this.element.classList.add('flickity-enabled');
3947  if ( this.options.rightToLeft ) {
3948    this.element.classList.add('flickity-rtl');
3949  }
3950
3951  this.getSize();
3952  // move initial cell elements so they can be loaded as cells
3953  let cellElems = this._filterFindCellElements( this.element.children );
3954  this.slider.append( ...cellElems );
3955  this.viewport.append( this.slider );
3956  this.element.append( this.viewport );
3957  // get cells from children
3958  this.reloadCells();
3959
3960  if ( this.options.accessibility ) {
3961    // allow element to focusable
3962    this.element.tabIndex = 0;
3963    // listen for key presses
3964    this.element.addEventListener( 'keydown', this );
3965  }
3966
3967  this.emitEvent('activate');
3968  this.selectInitialIndex();
3969  // flag for initial activation, for using initialIndex
3970  this.isInitActivated = true;
3971  // ready event. #493
3972  this.dispatchEvent('ready');
3973};
3974
3975// slider positions the cells
3976proto._createSlider = function() {
3977  // slider element does all the positioning
3978  let slider = document.createElement('div');
3979  slider.className = 'flickity-slider';
3980  this.slider = slider;
3981};
3982
3983proto._filterFindCellElements = function( elems ) {
3984  return utils.filterFindElements( elems, this.options.cellSelector );
3985};
3986
3987// goes through all children
3988proto.reloadCells = function() {
3989  // collection of item elements
3990  this.cells = this._makeCells( this.slider.children );
3991  this.positionCells();
3992  this._updateWrapShiftCells();
3993  this.setGallerySize();
3994};
3995
3996/**
3997 * turn elements into Flickity.Cells
3998 * @param {[Array, NodeList, HTMLElement]} elems - elements to make into cells
3999 * @returns {Array} items - collection of new Flickity Cells
4000 */
4001proto._makeCells = function( elems ) {
4002  let cellElems = this._filterFindCellElements( elems );
4003
4004  // create new Cells for collection
4005  return cellElems.map( ( cellElem ) => new Cell( cellElem ) );
4006};
4007
4008proto.getLastCell = function() {
4009  return this.cells[ this.cells.length - 1 ];
4010};
4011
4012proto.getLastSlide = function() {
4013  return this.slides[ this.slides.length - 1 ];
4014};
4015
4016// positions all cells
4017proto.positionCells = function() {
4018  // size all cells
4019  this._sizeCells( this.cells );
4020  // position all cells
4021  this._positionCells( 0 );
4022};
4023
4024/**
4025 * position certain cells
4026 * @param {Integer} index - which cell to start with
4027 */
4028proto._positionCells = function( index ) {
4029  index = index || 0;
4030  // also measure maxCellHeight
4031  // start 0 if positioning all cells
4032  this.maxCellHeight = index ? this.maxCellHeight || 0 : 0;
4033  let cellX = 0;
4034  // get cellX
4035  if ( index > 0 ) {
4036    let startCell = this.cells[ index - 1 ];
4037    cellX = startCell.x + startCell.size.outerWidth;
4038  }
4039
4040  this.cells.slice( index ).forEach( ( cell ) => {
4041    cell.x = cellX;
4042    this._renderCellPosition( cell, cellX );
4043    cellX += cell.size.outerWidth;
4044    this.maxCellHeight = Math.max( cell.size.outerHeight, this.maxCellHeight );
4045  } );
4046  // keep track of cellX for wrap-around
4047  this.slideableWidth = cellX;
4048  // slides
4049  this.updateSlides();
4050  // contain slides target
4051  this._containSlides();
4052  // update slidesWidth
4053  this.slidesWidth = this.cells.length ?
4054    this.getLastSlide().target - this.slides[0].target : 0;
4055};
4056
4057proto._renderCellPosition = function( cell, x ) {
4058  // render position of cell with in slider
4059  let sideOffset = this.options.rightToLeft ? -1 : 1;
4060  let renderX = x * sideOffset;
4061  if ( this.options.percentPosition ) renderX *= this.size.innerWidth / cell.size.width;
4062  let positionValue = this.getPositionValue( renderX );
4063  cell.element.style.transform = `translateX( ${positionValue} )`;
4064};
4065
4066/**
4067 * cell.getSize() on multiple cells
4068 * @param {Array} cells - cells to size
4069 */
4070proto._sizeCells = function( cells ) {
4071  cells.forEach( ( cell ) => cell.getSize() );
4072};
4073
4074// --------------------------  -------------------------- //
4075
4076proto.updateSlides = function() {
4077  this.slides = [];
4078  if ( !this.cells.length ) return;
4079
4080  let { beginMargin, endMargin } = this;
4081  let slide = new Slide( beginMargin, endMargin, this.cellAlign );
4082  this.slides.push( slide );
4083
4084  let canCellFit = this._getCanCellFit();
4085
4086  this.cells.forEach( ( cell, i ) => {
4087    // just add cell if first cell in slide
4088    if ( !slide.cells.length ) {
4089      slide.addCell( cell );
4090      return;
4091    }
4092
4093    let slideWidth = ( slide.outerWidth - slide.firstMargin ) +
4094      ( cell.size.outerWidth - cell.size[ endMargin ] );
4095
4096    if ( canCellFit( i, slideWidth ) ) {
4097      slide.addCell( cell );
4098    } else {
4099      // doesn't fit, new slide
4100      slide.updateTarget();
4101
4102      slide = new Slide( beginMargin, endMargin, this.cellAlign );
4103      this.slides.push( slide );
4104      slide.addCell( cell );
4105    }
4106  } );
4107  // last slide
4108  slide.updateTarget();
4109  // update .selectedSlide
4110  this.updateSelectedSlide();
4111};
4112
4113proto._getCanCellFit = function() {
4114  let { groupCells } = this.options;
4115  if ( !groupCells ) return () => false;
4116
4117  if ( typeof groupCells == 'number' ) {
4118    // group by number. 3 -> [0,1,2], [3,4,5], ...
4119    let number = parseInt( groupCells, 10 );
4120    return ( i ) => ( i % number ) !== 0;
4121  }
4122  // default, group by width of slide
4123  let percent = 1;
4124  // parse '75%
4125  let percentMatch = typeof groupCells == 'string' && groupCells.match( /^(\d+)%$/ );
4126  if ( percentMatch ) percent = parseInt( percentMatch[1], 10 ) / 100;
4127  let groupWidth = ( this.size.innerWidth + 1 ) * percent;
4128  return ( i, slideWidth ) => slideWidth <= groupWidth;
4129};
4130
4131// alias _init for jQuery plugin .flickity()
4132proto._init =
4133proto.reposition = function() {
4134  this.positionCells();
4135  this.positionSliderAtSelected();
4136};
4137
4138proto.getSize = function() {
4139  this.size = getSize( this.element );
4140  this.setCellAlign();
4141  this.cursorPosition = this.size.innerWidth * this.cellAlign;
4142};
4143
4144let cellAlignShorthands = {
4145  left: 0,
4146  center: 0.5,
4147  right: 1,
4148};
4149
4150proto.setCellAlign = function() {
4151  let { cellAlign, rightToLeft } = this.options;
4152  let shorthand = cellAlignShorthands[ cellAlign ];
4153  this.cellAlign = shorthand !== undefined ? shorthand : cellAlign;
4154  if ( rightToLeft ) this.cellAlign = 1 - this.cellAlign;
4155};
4156
4157proto.setGallerySize = function() {
4158  if ( !this.options.setGallerySize ) return;
4159
4160  let height = this.options.adaptiveHeight && this.selectedSlide ?
4161    this.selectedSlide.height : this.maxCellHeight;
4162  this.viewport.style.height = `${height}px`;
4163};
4164
4165proto._updateWrapShiftCells = function() {
4166  // update isWrapping
4167  this.isWrapping = this.getIsWrapping();
4168  // only for wrap-around
4169  if ( !this.isWrapping ) return;
4170
4171  // unshift previous cells
4172  this._unshiftCells( this.beforeShiftCells );
4173  this._unshiftCells( this.afterShiftCells );
4174  // get before cells
4175  // initial gap
4176  let beforeGapX = this.cursorPosition;
4177  let lastIndex = this.cells.length - 1;
4178  this.beforeShiftCells = this._getGapCells( beforeGapX, lastIndex, -1 );
4179  // get after cells
4180  // ending gap between last cell and end of gallery viewport
4181  let afterGapX = this.size.innerWidth - this.cursorPosition;
4182  // start cloning at first cell, working forwards
4183  this.afterShiftCells = this._getGapCells( afterGapX, 0, 1 );
4184};
4185
4186proto.getIsWrapping = function() {
4187  let { wrapAround } = this.options;
4188  if ( !wrapAround || this.slides.length < 2 ) return false;
4189
4190  if ( wrapAround !== 'fill' ) return true;
4191  // check that slides can fit
4192
4193  let gapWidth = this.slideableWidth - this.size.innerWidth;
4194  if ( gapWidth > this.size.innerWidth ) return true; // gap * 2x big, all good
4195  // check that content width - shifting cell is bigger than viewport width
4196  for ( let cell of this.cells ) {
4197    if ( cell.size.outerWidth > gapWidth ) return false;
4198  }
4199  return true;
4200};
4201
4202proto._getGapCells = function( gapX, cellIndex, increment ) {
4203  // keep adding cells until the cover the initial gap
4204  let cells = [];
4205  while ( gapX > 0 ) {
4206    let cell = this.cells[ cellIndex ];
4207    if ( !cell ) break;
4208
4209    cells.push( cell );
4210    cellIndex += increment;
4211    gapX -= cell.size.outerWidth;
4212  }
4213  return cells;
4214};
4215
4216// ----- contain & wrap ----- //
4217
4218// contain cell targets so no excess sliding
4219proto._containSlides = function() {
4220  let isContaining = this.options.contain && !this.isWrapping &&
4221      this.cells.length;
4222  if ( !isContaining ) return;
4223
4224  let contentWidth = this.slideableWidth - this.getLastCell().size[ this.endMargin ];
4225  // content is less than gallery size
4226  let isContentSmaller = contentWidth < this.size.innerWidth;
4227  if ( isContentSmaller ) {
4228    // all cells fit inside gallery
4229    this.slides.forEach( ( slide ) => {
4230      slide.target = contentWidth * this.cellAlign;
4231    } );
4232  } else {
4233    // contain to bounds
4234    let beginBound = this.cursorPosition + this.cells[0].size[ this.beginMargin ];
4235    let endBound = contentWidth - this.size.innerWidth * ( 1 - this.cellAlign );
4236    this.slides.forEach( ( slide ) => {
4237      slide.target = Math.max( slide.target, beginBound );
4238      slide.target = Math.min( slide.target, endBound );
4239    } );
4240  }
4241};
4242
4243// ----- events ----- //
4244
4245/**
4246 * emits events via eventEmitter and jQuery events
4247 * @param {String} type - name of event
4248 * @param {Event} event - original event
4249 * @param {Array} args - extra arguments
4250 */
4251proto.dispatchEvent = function( type, event, args ) {
4252  let emitArgs = event ? [ event ].concat( args ) : args;
4253  this.emitEvent( type, emitArgs );
4254
4255  if ( jQuery && this.$element ) {
4256    // default trigger with type if no event
4257    type += this.options.namespaceJQueryEvents ? '.flickity' : '';
4258    let $event = type;
4259    if ( event ) {
4260      // create jQuery event
4261      let jQEvent = new jQuery.Event( event );
4262      jQEvent.type = type;
4263      $event = jQEvent;
4264    }
4265    this.$element.trigger( $event, args );
4266  }
4267};
4268
4269const unidraggerEvents = [
4270  'dragStart',
4271  'dragMove',
4272  'dragEnd',
4273  'pointerDown',
4274  'pointerMove',
4275  'pointerEnd',
4276  'staticClick',
4277];
4278
4279let _emitEvent = proto.emitEvent;
4280proto.emitEvent = function( eventName, args ) {
4281  if ( eventName === 'staticClick' ) {
4282    // add cellElem and cellIndex args to staticClick
4283    let clickedCell = this.getParentCell( args[0].target );
4284    let cellElem = clickedCell && clickedCell.element;
4285    let cellIndex = clickedCell && this.cells.indexOf( clickedCell );
4286    args = args.concat( cellElem, cellIndex );
4287  }
4288  // do regular thing
4289  _emitEvent.call( this, eventName, args );
4290  // duck-punch in jQuery events for Unidragger events
4291  let isUnidraggerEvent = unidraggerEvents.includes( eventName );
4292  if ( !isUnidraggerEvent || !jQuery || !this.$element ) return;
4293
4294  eventName += this.options.namespaceJQueryEvents ? '.flickity' : '';
4295  let event = args.shift( 0 );
4296  let jQEvent = new jQuery.Event( event );
4297  jQEvent.type = eventName;
4298  this.$element.trigger( jQEvent, args );
4299};
4300
4301// -------------------------- select -------------------------- //
4302
4303/**
4304 * @param {Integer} index - index of the slide
4305 * @param {Boolean} isWrap - will wrap-around to last/first if at the end
4306 * @param {Boolean} isInstant - will immediately set position at selected cell
4307 */
4308proto.select = function( index, isWrap, isInstant ) {
4309  if ( !this.isActive ) return;
4310
4311  index = parseInt( index, 10 );
4312  this._wrapSelect( index );
4313
4314  if ( this.isWrapping || isWrap ) {
4315    index = utils.modulo( index, this.slides.length );
4316  }
4317  // bail if invalid index
4318  if ( !this.slides[ index ] ) return;
4319
4320  let prevIndex = this.selectedIndex;
4321  this.selectedIndex = index;
4322  this.updateSelectedSlide();
4323  if ( isInstant ) {
4324    this.positionSliderAtSelected();
4325  } else {
4326    this.startAnimation();
4327  }
4328  if ( this.options.adaptiveHeight ) {
4329    this.setGallerySize();
4330  }
4331  // events
4332  this.dispatchEvent( 'select', null, [ index ] );
4333  // change event if new index
4334  if ( index !== prevIndex ) {
4335    this.dispatchEvent( 'change', null, [ index ] );
4336  }
4337};
4338
4339// wraps position for wrapAround, to move to closest slide. #113
4340proto._wrapSelect = function( index ) {
4341  if ( !this.isWrapping ) return;
4342
4343  const { selectedIndex, slideableWidth, slides: { length } } = this;
4344  // shift index for wrap, do not wrap dragSelect
4345  if ( !this.isDragSelect ) {
4346    let wrapIndex = utils.modulo( index, length );
4347    // go to shortest
4348    let delta = Math.abs( wrapIndex - selectedIndex );
4349    let backWrapDelta = Math.abs( ( wrapIndex + length ) - selectedIndex );
4350    let forewardWrapDelta = Math.abs( ( wrapIndex - length ) - selectedIndex );
4351    if ( backWrapDelta < delta ) {
4352      index += length;
4353    } else if ( forewardWrapDelta < delta ) {
4354      index -= length;
4355    }
4356  }
4357
4358  // wrap position so slider is within normal area
4359  if ( index < 0 ) {
4360    this.x -= slideableWidth;
4361  } else if ( index >= length ) {
4362    this.x += slideableWidth;
4363  }
4364};
4365
4366proto.previous = function( isWrap, isInstant ) {
4367  this.select( this.selectedIndex - 1, isWrap, isInstant );
4368};
4369
4370proto.next = function( isWrap, isInstant ) {
4371  this.select( this.selectedIndex + 1, isWrap, isInstant );
4372};
4373
4374proto.updateSelectedSlide = function() {
4375  let slide = this.slides[ this.selectedIndex ];
4376  // selectedIndex could be outside of slides, if triggered before resize()
4377  if ( !slide ) return;
4378
4379  // unselect previous selected slide
4380  this.unselectSelectedSlide();
4381  // update new selected slide
4382  this.selectedSlide = slide;
4383  slide.select();
4384  this.selectedCells = slide.cells;
4385  this.selectedElements = slide.getCellElements();
4386  // HACK: selectedCell & selectedElement is first cell in slide, backwards compatibility
4387  this.selectedCell = slide.cells[0];
4388  this.selectedElement = this.selectedElements[0];
4389};
4390
4391proto.unselectSelectedSlide = function() {
4392  if ( this.selectedSlide ) this.selectedSlide.unselect();
4393};
4394
4395proto.selectInitialIndex = function() {
4396  let initialIndex = this.options.initialIndex;
4397  // already activated, select previous selectedIndex
4398  if ( this.isInitActivated ) {
4399    this.select( this.selectedIndex, false, true );
4400    return;
4401  }
4402  // select with selector string
4403  if ( initialIndex && typeof initialIndex == 'string' ) {
4404    let cell = this.queryCell( initialIndex );
4405    if ( cell ) {
4406      this.selectCell( initialIndex, false, true );
4407      return;
4408    }
4409  }
4410
4411  let index = 0;
4412  // select with number
4413  if ( initialIndex && this.slides[ initialIndex ] ) {
4414    index = initialIndex;
4415  }
4416  // select instantly
4417  this.select( index, false, true );
4418};
4419
4420/**
4421 * select slide from number or cell element
4422 * @param {[Element, Number]} value - zero-based index or element to select
4423 * @param {Boolean} isWrap - enables wrapping around for extra index
4424 * @param {Boolean} isInstant - disables slide animation
4425 */
4426proto.selectCell = function( value, isWrap, isInstant ) {
4427  // get cell
4428  let cell = this.queryCell( value );
4429  if ( !cell ) return;
4430
4431  let index = this.getCellSlideIndex( cell );
4432  this.select( index, isWrap, isInstant );
4433};
4434
4435proto.getCellSlideIndex = function( cell ) {
4436  // get index of slide that has cell
4437  let cellSlide = this.slides.find( ( slide ) => slide.cells.includes( cell ) );
4438  return this.slides.indexOf( cellSlide );
4439};
4440
4441// -------------------------- get cells -------------------------- //
4442
4443/**
4444 * get Flickity.Cell, given an Element
4445 * @param {Element} elem - matching cell element
4446 * @returns {Flickity.Cell} cell - matching cell
4447 */
4448proto.getCell = function( elem ) {
4449  // loop through cells to get the one that matches
4450  for ( let cell of this.cells ) {
4451    if ( cell.element === elem ) return cell;
4452  }
4453};
4454
4455/**
4456 * get collection of Flickity.Cells, given Elements
4457 * @param {[Element, Array, NodeList]} elems - multiple elements
4458 * @returns {Array} cells - Flickity.Cells
4459 */
4460proto.getCells = function( elems ) {
4461  elems = utils.makeArray( elems );
4462  return elems.map( ( elem ) => this.getCell( elem ) ).filter( Boolean );
4463};
4464
4465/**
4466 * get cell elements
4467 * @returns {Array} cellElems
4468 */
4469proto.getCellElements = function() {
4470  return this.cells.map( ( cell ) => cell.element );
4471};
4472
4473/**
4474 * get parent cell from an element
4475 * @param {Element} elem - child element
4476 * @returns {Flickit.Cell} cell - parent cell
4477 */
4478proto.getParentCell = function( elem ) {
4479  // first check if elem is cell
4480  let cell = this.getCell( elem );
4481  if ( cell ) return cell;
4482
4483  // try to get parent cell elem
4484  let closest = elem.closest('.flickity-slider > *');
4485  return this.getCell( closest );
4486};
4487
4488/**
4489 * get cells adjacent to a slide
4490 * @param {Integer} adjCount - number of adjacent slides
4491 * @param {Integer} index - index of slide to start
4492 * @returns {Array} cells - array of Flickity.Cells
4493 */
4494proto.getAdjacentCellElements = function( adjCount, index ) {
4495  if ( !adjCount ) return this.selectedSlide.getCellElements();
4496
4497  index = index === undefined ? this.selectedIndex : index;
4498
4499  let len = this.slides.length;
4500  if ( 1 + ( adjCount * 2 ) >= len ) {
4501    return this.getCellElements(); // get all
4502  }
4503
4504  let cellElems = [];
4505  for ( let i = index - adjCount; i <= index + adjCount; i++ ) {
4506    let slideIndex = this.isWrapping ? utils.modulo( i, len ) : i;
4507    let slide = this.slides[ slideIndex ];
4508    if ( slide ) {
4509      cellElems = cellElems.concat( slide.getCellElements() );
4510    }
4511  }
4512  return cellElems;
4513};
4514
4515/**
4516 * select slide from number or cell element
4517 * @param {[Element, String, Number]} selector - element, selector string, or index
4518 * @returns {Flickity.Cell} - matching cell
4519 */
4520proto.queryCell = function( selector ) {
4521  if ( typeof selector == 'number' ) {
4522    // use number as index
4523    return this.cells[ selector ];
4524  }
4525  // do not select invalid selectors from hash: #123, #/. #791
4526  let isSelectorString = typeof selector == 'string' && !selector.match( /^[#.]?[\d/]/ );
4527  if ( isSelectorString ) {
4528    // use string as selector, get element
4529    selector = this.element.querySelector( selector );
4530  }
4531  // get cell from element
4532  return this.getCell( selector );
4533};
4534
4535// -------------------------- events -------------------------- //
4536
4537proto.uiChange = function() {
4538  this.emitEvent('uiChange');
4539};
4540
4541// ----- resize ----- //
4542
4543proto.onresize = function() {
4544  this.watchCSS();
4545  this.resize();
4546};
4547
4548utils.debounceMethod( Flickity, 'onresize', 150 );
4549
4550proto.resize = function() {
4551  // #1177 disable resize behavior when animating or dragging for iOS 15
4552  if ( !this.isActive || this.isAnimating || this.isDragging ) return;
4553  this.getSize();
4554  // wrap values
4555  if ( this.isWrapping ) {
4556    this.x = utils.modulo( this.x, this.slideableWidth );
4557  }
4558  this.positionCells();
4559  this._updateWrapShiftCells();
4560  this.setGallerySize();
4561  this.emitEvent('resize');
4562  // update selected index for group slides, instant
4563  // TODO: position can be lost between groups of various numbers
4564  let selectedElement = this.selectedElements && this.selectedElements[0];
4565  this.selectCell( selectedElement, false, true );
4566};
4567
4568// watches the :after property, activates/deactivates
4569proto.watchCSS = function() {
4570  if ( !this.options.watchCSS ) return;
4571
4572  let afterContent = getComputedStyle( this.element, ':after' ).content;
4573  // activate if :after { content: 'flickity' }
4574  if ( afterContent.includes('flickity') ) {
4575    this.activate();
4576  } else {
4577    this.deactivate();
4578  }
4579};
4580
4581// ----- keydown ----- //
4582
4583// go previous/next if left/right keys pressed
4584proto.onkeydown = function( event ) {
4585  let { activeElement } = document;
4586  let handler = Flickity.keyboardHandlers[ event.key ];
4587  // only work if element is in focus
4588  if ( !this.options.accessibility || !activeElement || !handler ) return;
4589
4590  let isFocused = this.focusableElems.some( ( elem ) => activeElement === elem );
4591  if ( isFocused ) handler.call( this );
4592};
4593
4594Flickity.keyboardHandlers = {
4595  ArrowLeft: function() {
4596    this.uiChange();
4597    let leftMethod = this.options.rightToLeft ? 'next' : 'previous';
4598    this[ leftMethod ]();
4599  },
4600  ArrowRight: function() {
4601    this.uiChange();
4602    let rightMethod = this.options.rightToLeft ? 'previous' : 'next';
4603    this[ rightMethod ]();
4604  },
4605};
4606
4607// ----- focus ----- //
4608
4609proto.focus = function() {
4610  this.element.focus({ preventScroll: true });
4611};
4612
4613// -------------------------- destroy -------------------------- //
4614
4615// deactivate all Flickity functionality, but keep stuff available
4616proto.deactivate = function() {
4617  if ( !this.isActive ) return;
4618
4619  this.element.classList.remove('flickity-enabled');
4620  this.element.classList.remove('flickity-rtl');
4621  this.unselectSelectedSlide();
4622  // destroy cells
4623  this.cells.forEach( ( cell ) => cell.destroy() );
4624  this.viewport.remove();
4625  // move child elements back into element
4626  this.element.append( ...this.slider.children );
4627  if ( this.options.accessibility ) {
4628    this.element.removeAttribute('tabIndex');
4629    this.element.removeEventListener( 'keydown', this );
4630  }
4631  // set flags
4632  this.isActive = false;
4633  this.emitEvent('deactivate');
4634};
4635
4636proto.destroy = function() {
4637  this.deactivate();
4638  window.removeEventListener( 'resize', this );
4639  this.allOff();
4640  this.emitEvent('destroy');
4641  if ( jQuery && this.$element ) {
4642    jQuery.removeData( this.element, 'flickity' );
4643  }
4644  delete this.element.flickityGUID;
4645  delete instances[ this.guid ];
4646};
4647
4648// -------------------------- prototype -------------------------- //
4649
4650Object.assign( proto, animatePrototype );
4651
4652// -------------------------- extras -------------------------- //
4653
4654/**
4655 * get Flickity instance from element
4656 * @param {[Element, String]} elem - element or selector string
4657 * @returns {Flickity} - Flickity instance
4658 */
4659Flickity.data = function( elem ) {
4660  elem = utils.getQueryElement( elem );
4661  if ( elem ) return instances[ elem.flickityGUID ];
4662};
4663
4664utils.htmlInit( Flickity, 'flickity' );
4665
4666let { jQueryBridget } = window;
4667if ( jQuery && jQueryBridget ) {
4668  jQueryBridget( 'flickity', Flickity, jQuery );
4669}
4670
4671// set internal jQuery, for Webpack + jQuery v3, #478
4672Flickity.setJQuery = function( jq ) {
4673  jQuery = jq;
4674};
4675
4676Flickity.Cell = Cell;
4677Flickity.Slide = Slide;
4678
4679return Flickity;
4680
4681} ) );
4682// drag
4683( function( window, factory ) {
4684  // universal module definition
4685  if ( typeof module == 'object' && module.exports ) {
4686    // CommonJS
4687    module.exports = factory(
4688        window,
4689        require('./core'),
4690        require('unidragger'),
4691        require('fizzy-ui-utils'),
4692    );
4693  } else {
4694    // browser global
4695    window.Flickity = factory(
4696        window,
4697        window.Flickity,
4698        window.Unidragger,
4699        window.fizzyUIUtils,
4700    );
4701  }
4702
4703}( typeof window != 'undefined' ? window : this,
4704    function factory( window, Flickity, Unidragger, utils ) {
4705
4706// ----- defaults ----- //
4707
4708Object.assign( Flickity.defaults, {
4709  draggable: '>1',
4710  dragThreshold: 3,
4711} );
4712
4713// -------------------------- drag prototype -------------------------- //
4714
4715let proto = Flickity.prototype;
4716Object.assign( proto, Unidragger.prototype ); // inherit Unidragger
4717proto.touchActionValue = '';
4718
4719// --------------------------  -------------------------- //
4720
4721Flickity.create.drag = function() {
4722  this.on( 'activate', this.onActivateDrag );
4723  this.on( 'uiChange', this._uiChangeDrag );
4724  this.on( 'deactivate', this.onDeactivateDrag );
4725  this.on( 'cellChange', this.updateDraggable );
4726  this.on( 'pointerDown', this.handlePointerDown );
4727  this.on( 'pointerUp', this.handlePointerUp );
4728  this.on( 'pointerDown', this.handlePointerDone );
4729  this.on( 'dragStart', this.handleDragStart );
4730  this.on( 'dragMove', this.handleDragMove );
4731  this.on( 'dragEnd', this.handleDragEnd );
4732  this.on( 'staticClick', this.handleStaticClick );
4733  // TODO updateDraggable on resize? if groupCells & slides change
4734};
4735
4736proto.onActivateDrag = function() {
4737  this.handles = [ this.viewport ];
4738  this.bindHandles();
4739  this.updateDraggable();
4740};
4741
4742proto.onDeactivateDrag = function() {
4743  this.unbindHandles();
4744  this.element.classList.remove('is-draggable');
4745};
4746
4747proto.updateDraggable = function() {
4748  // disable dragging if less than 2 slides. #278
4749  if ( this.options.draggable === '>1' ) {
4750    this.isDraggable = this.slides.length > 1;
4751  } else {
4752    this.isDraggable = this.options.draggable;
4753  }
4754  this.element.classList.toggle( 'is-draggable', this.isDraggable );
4755};
4756
4757proto._uiChangeDrag = function() {
4758  delete this.isFreeScrolling;
4759};
4760
4761// -------------------------- pointer events -------------------------- //
4762
4763proto.handlePointerDown = function( event ) {
4764  if ( !this.isDraggable ) {
4765    // proceed for staticClick
4766    this.bindActivePointerEvents( event );
4767    return;
4768  }
4769
4770  let isTouchStart = event.type === 'touchstart';
4771  let isTouchPointer = event.pointerType === 'touch';
4772  let isFocusNode = event.target.matches('input, textarea, select');
4773  if ( !isTouchStart && !isTouchPointer && !isFocusNode ) event.preventDefault();
4774  if ( !isFocusNode ) this.focus();
4775  // blur
4776  if ( document.activeElement !== this.element ) document.activeElement.blur();
4777  // stop if it was moving
4778  this.dragX = this.x;
4779  this.viewport.classList.add('is-pointer-down');
4780  // track scrolling
4781  this.pointerDownScroll = getScrollPosition();
4782  window.addEventListener( 'scroll', this );
4783  this.bindActivePointerEvents( event );
4784};
4785
4786// ----- move ----- //
4787
4788proto.hasDragStarted = function( moveVector ) {
4789  return Math.abs( moveVector.x ) > this.options.dragThreshold;
4790};
4791
4792// ----- up ----- //
4793
4794proto.handlePointerUp = function() {
4795  delete this.isTouchScrolling;
4796  this.viewport.classList.remove('is-pointer-down');
4797};
4798
4799proto.handlePointerDone = function() {
4800  window.removeEventListener( 'scroll', this );
4801  delete this.pointerDownScroll;
4802};
4803
4804// -------------------------- dragging -------------------------- //
4805
4806proto.handleDragStart = function() {
4807  if ( !this.isDraggable ) return;
4808
4809  this.dragStartPosition = this.x;
4810  this.startAnimation();
4811  window.removeEventListener( 'scroll', this );
4812};
4813
4814proto.handleDragMove = function( event, pointer, moveVector ) {
4815  if ( !this.isDraggable ) return;
4816
4817  event.preventDefault();
4818
4819  this.previousDragX = this.dragX;
4820  // reverse if right-to-left
4821  let direction = this.options.rightToLeft ? -1 : 1;
4822  // wrap around move. #589
4823  if ( this.isWrapping ) moveVector.x %= this.slideableWidth;
4824  let dragX = this.dragStartPosition + moveVector.x * direction;
4825
4826  if ( !this.isWrapping ) {
4827    // slow drag
4828    let originBound = Math.max( -this.slides[0].target, this.dragStartPosition );
4829    dragX = dragX > originBound ? ( dragX + originBound ) * 0.5 : dragX;
4830    let endBound = Math.min( -this.getLastSlide().target, this.dragStartPosition );
4831    dragX = dragX < endBound ? ( dragX + endBound ) * 0.5 : dragX;
4832  }
4833
4834  this.dragX = dragX;
4835  this.dragMoveTime = new Date();
4836};
4837
4838proto.handleDragEnd = function() {
4839  if ( !this.isDraggable ) return;
4840
4841  let { freeScroll } = this.options;
4842  if ( freeScroll ) this.isFreeScrolling = true;
4843  // set selectedIndex based on where flick will end up
4844  let index = this.dragEndRestingSelect();
4845
4846  if ( freeScroll && !this.isWrapping ) {
4847    // if free-scroll & not wrap around
4848    // do not free-scroll if going outside of bounding slides
4849    // so bounding slides can attract slider, and keep it in bounds
4850    let restingX = this.getRestingPosition();
4851    this.isFreeScrolling = -restingX > this.slides[0].target &&
4852      -restingX < this.getLastSlide().target;
4853  } else if ( !freeScroll && index === this.selectedIndex ) {
4854    // boost selection if selected index has not changed
4855    index += this.dragEndBoostSelect();
4856  }
4857  delete this.previousDragX;
4858  // apply selection
4859  // HACK, set flag so dragging stays in correct direction
4860  this.isDragSelect = this.isWrapping;
4861  this.select( index );
4862  delete this.isDragSelect;
4863};
4864
4865proto.dragEndRestingSelect = function() {
4866  let restingX = this.getRestingPosition();
4867  // how far away from selected slide
4868  let distance = Math.abs( this.getSlideDistance( -restingX, this.selectedIndex ) );
4869  // get closet resting going up and going down
4870  let positiveResting = this._getClosestResting( restingX, distance, 1 );
4871  let negativeResting = this._getClosestResting( restingX, distance, -1 );
4872  // use closer resting for wrap-around
4873  return positiveResting.distance < negativeResting.distance ?
4874    positiveResting.index : negativeResting.index;
4875};
4876
4877/**
4878 * given resting X and distance to selected cell
4879 * get the distance and index of the closest cell
4880 * @param {Number} restingX - estimated post-flick resting position
4881 * @param {Number} distance - distance to selected cell
4882 * @param {Integer} increment - +1 or -1, going up or down
4883 * @returns {Object} - { distance: {Number}, index: {Integer} }
4884 */
4885proto._getClosestResting = function( restingX, distance, increment ) {
4886  let index = this.selectedIndex;
4887  let minDistance = Infinity;
4888  let condition = this.options.contain && !this.isWrapping ?
4889    // if containing, keep going if distance is equal to minDistance
4890    ( dist, minDist ) => dist <= minDist :
4891    ( dist, minDist ) => dist < minDist;
4892
4893  while ( condition( distance, minDistance ) ) {
4894    // measure distance to next cell
4895    index += increment;
4896    minDistance = distance;
4897    distance = this.getSlideDistance( -restingX, index );
4898    if ( distance === null ) break;
4899
4900    distance = Math.abs( distance );
4901  }
4902  return {
4903    distance: minDistance,
4904    // selected was previous index
4905    index: index - increment,
4906  };
4907};
4908
4909/**
4910 * measure distance between x and a slide target
4911 * @param {Number} x - horizontal position
4912 * @param {Integer} index - slide index
4913 * @returns {Number} - slide distance
4914 */
4915proto.getSlideDistance = function( x, index ) {
4916  let len = this.slides.length;
4917  // wrap around if at least 2 slides
4918  let isWrapAround = this.options.wrapAround && len > 1;
4919  let slideIndex = isWrapAround ? utils.modulo( index, len ) : index;
4920  let slide = this.slides[ slideIndex ];
4921  if ( !slide ) return null;
4922
4923  // add distance for wrap-around slides
4924  let wrap = isWrapAround ? this.slideableWidth * Math.floor( index/len ) : 0;
4925  return x - ( slide.target + wrap );
4926};
4927
4928proto.dragEndBoostSelect = function() {
4929  // do not boost if no previousDragX or dragMoveTime
4930  if ( this.previousDragX === undefined || !this.dragMoveTime ||
4931    // or if drag was held for 100 ms
4932    new Date() - this.dragMoveTime > 100 ) {
4933    return 0;
4934  }
4935
4936  let distance = this.getSlideDistance( -this.dragX, this.selectedIndex );
4937  let delta = this.previousDragX - this.dragX;
4938  if ( distance > 0 && delta > 0 ) {
4939    // boost to next if moving towards the right, and positive velocity
4940    return 1;
4941  } else if ( distance < 0 && delta < 0 ) {
4942    // boost to previous if moving towards the left, and negative velocity
4943    return -1;
4944  }
4945  return 0;
4946};
4947
4948// ----- scroll ----- //
4949
4950proto.onscroll = function() {
4951  let scroll = getScrollPosition();
4952  let scrollMoveX = this.pointerDownScroll.x - scroll.x;
4953  let scrollMoveY = this.pointerDownScroll.y - scroll.y;
4954  // cancel click/tap if scroll is too much
4955  if ( Math.abs( scrollMoveX ) > 3 || Math.abs( scrollMoveY ) > 3 ) {
4956    this.pointerDone();
4957  }
4958};
4959
4960// ----- utils ----- //
4961
4962function getScrollPosition() {
4963  return {
4964    x: window.pageXOffset,
4965    y: window.pageYOffset,
4966  };
4967}
4968
4969// -----  ----- //
4970
4971return Flickity;
4972
4973} ) );
4974// prev/next buttons
4975( function( window, factory ) {
4976  // universal module definition
4977  if ( typeof module == 'object' && module.exports ) {
4978    // CommonJS
4979    module.exports = factory( require('./core') );
4980  } else {
4981    // browser global
4982    factory( window.Flickity );
4983  }
4984
4985}( typeof window != 'undefined' ? window : this, function factory( Flickity ) {
4986
4987const svgURI = 'http://www.w3.org/2000/svg';
4988
4989// -------------------------- PrevNextButton -------------------------- //
4990
4991function PrevNextButton( increment, direction, arrowShape ) {
4992  this.increment = increment;
4993  this.direction = direction;
4994  this.isPrevious = increment === 'previous';
4995  this.isLeft = direction === 'left';
4996  this._create( arrowShape );
4997}
4998
4999PrevNextButton.prototype._create = function( arrowShape ) {
5000  // properties
5001  let element = this.element = document.createElement('button');
5002  element.className = `flickity-button flickity-prev-next-button ${this.increment}`;
5003  let label = this.isPrevious ? 'Previous' : 'Next';
5004  // prevent button from submitting form https://stackoverflow.com/a/10836076/182183
5005  element.setAttribute( 'type', 'button' );
5006  element.setAttribute( 'aria-label', label );
5007  // init as disabled
5008  this.disable();
5009  // create arrow
5010  let svg = this.createSVG( label, arrowShape );
5011  element.append( svg );
5012};
5013
5014PrevNextButton.prototype.createSVG = function( label, arrowShape ) {
5015  let svg = document.createElementNS( svgURI, 'svg' );
5016  svg.setAttribute( 'class', 'flickity-button-icon' );
5017  svg.setAttribute( 'viewBox', '0 0 100 100' );
5018  // add title #1189
5019  let title = document.createElementNS( svgURI, 'title' );
5020  title.append( label );
5021  // add path
5022  let path = document.createElementNS( svgURI, 'path' );
5023  let pathMovements = getArrowMovements( arrowShape );
5024  path.setAttribute( 'd', pathMovements );
5025  path.setAttribute( 'class', 'arrow' );
5026  // rotate arrow
5027  if ( !this.isLeft ) {
5028    path.setAttribute( 'transform', 'translate(100, 100) rotate(180)' );
5029  }
5030  svg.append( title, path );
5031  return svg;
5032};
5033
5034// get SVG path movmement
5035function getArrowMovements( shape ) {
5036  // use shape as movement if string
5037  if ( typeof shape == 'string' ) return shape;
5038
5039  let { x0, x1, x2, x3, y1, y2 } = shape;
5040
5041  // create movement string
5042  return `M ${x0}, 50
5043    L ${x1}, ${y1 + 50}
5044    L ${x2}, ${y2 + 50}
5045    L ${x3}, 50
5046    L ${x2}, ${50 - y2}
5047    L ${x1}, ${50 - y1}
5048    Z`;
5049}
5050
5051// -----  ----- //
5052
5053PrevNextButton.prototype.enable = function() {
5054  this.element.removeAttribute('disabled');
5055};
5056
5057PrevNextButton.prototype.disable = function() {
5058  this.element.setAttribute( 'disabled', true );
5059};
5060
5061// -------------------------- Flickity prototype -------------------------- //
5062
5063Object.assign( Flickity.defaults, {
5064  prevNextButtons: true,
5065  arrowShape: {
5066    x0: 10,
5067    x1: 60, y1: 50,
5068    x2: 70, y2: 40,
5069    x3: 30,
5070  },
5071} );
5072
5073Flickity.create.prevNextButtons = function() {
5074  if ( !this.options.prevNextButtons ) return;
5075
5076  let { rightToLeft, arrowShape } = this.options;
5077  let prevDirection = rightToLeft ? 'right' : 'left';
5078  let nextDirection = rightToLeft ? 'left' : 'right';
5079  this.prevButton = new PrevNextButton( 'previous', prevDirection, arrowShape );
5080  this.nextButton = new PrevNextButton( 'next', nextDirection, arrowShape );
5081  this.focusableElems.push( this.prevButton.element );
5082  this.focusableElems.push( this.nextButton.element );
5083
5084  this.handlePrevButtonClick = () => {
5085    this.uiChange();
5086    this.previous();
5087  };
5088
5089  this.handleNextButtonClick = () => {
5090    this.uiChange();
5091    this.next();
5092  };
5093
5094  this.on( 'activate', this.activatePrevNextButtons );
5095  this.on( 'select', this.updatePrevNextButtons );
5096};
5097
5098let proto = Flickity.prototype;
5099
5100proto.updatePrevNextButtons = function() {
5101  let lastIndex = this.slides.length ? this.slides.length - 1 : 0;
5102  this.updatePrevNextButton( this.prevButton, 0 );
5103  this.updatePrevNextButton( this.nextButton, lastIndex );
5104};
5105
5106proto.updatePrevNextButton = function( button, disabledIndex ) {
5107  // enable is wrapAround and at least 2 slides
5108  if ( this.isWrapping && this.slides.length > 1 ) {
5109    button.enable();
5110    return;
5111  }
5112
5113  let isEnabled = this.selectedIndex !== disabledIndex;
5114  button[ isEnabled ? 'enable' : 'disable' ]();
5115  // if disabling button that is focused,
5116  // shift focus to element to maintain keyboard accessibility
5117  let isDisabledFocused = !isEnabled && document.activeElement === button.element;
5118  if ( isDisabledFocused ) this.focus();
5119};
5120
5121proto.activatePrevNextButtons = function() {
5122  this.prevButton.element.addEventListener( 'click', this.handlePrevButtonClick );
5123  this.nextButton.element.addEventListener( 'click', this.handleNextButtonClick );
5124  this.element.append( this.prevButton.element, this.nextButton.element );
5125  this.on( 'deactivate', this.deactivatePrevNextButtons );
5126};
5127
5128proto.deactivatePrevNextButtons = function() {
5129  this.prevButton.element.remove();
5130  this.nextButton.element.remove();
5131  this.prevButton.element.removeEventListener( 'click', this.handlePrevButtonClick );
5132  this.nextButton.element.removeEventListener( 'click', this.handleNextButtonClick );
5133  this.off( 'deactivate', this.deactivatePrevNextButtons );
5134};
5135
5136// --------------------------  -------------------------- //
5137
5138Flickity.PrevNextButton = PrevNextButton;
5139
5140return Flickity;
5141
5142} ) );
5143// page dots
5144( function( window, factory ) {
5145  // universal module definition
5146  if ( typeof module == 'object' && module.exports ) {
5147    // CommonJS
5148    module.exports = factory(
5149        require('./core'),
5150        require('fizzy-ui-utils'),
5151    );
5152  } else {
5153    // browser global
5154    factory(
5155        window.Flickity,
5156        window.fizzyUIUtils,
5157    );
5158  }
5159
5160}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
5161
5162// -------------------------- PageDots -------------------------- //
5163
5164function PageDots() {
5165  // create holder element
5166  this.holder = document.createElement('div');
5167  this.holder.className = 'flickity-page-dots';
5168  // create dots, array of elements
5169  this.dots = [];
5170}
5171
5172PageDots.prototype.setDots = function( slidesLength ) {
5173  // get difference between number of slides and number of dots
5174  let delta = slidesLength - this.dots.length;
5175  if ( delta > 0 ) {
5176    this.addDots( delta );
5177  } else if ( delta < 0 ) {
5178    this.removeDots( -delta );
5179  }
5180};
5181
5182PageDots.prototype.addDots = function( count ) {
5183  let newDots = new Array( count ).fill()
5184    .map( ( item, i ) => {
5185      let dot = document.createElement('button');
5186      dot.setAttribute( 'type', 'button' );
5187      let num = i + 1 + this.dots.length;
5188      dot.className = 'flickity-page-dot';
5189      dot.textContent = `View slide ${num}`;
5190      return dot;
5191    } );
5192
5193  this.holder.append( ...newDots );
5194  this.dots = this.dots.concat( newDots );
5195};
5196
5197PageDots.prototype.removeDots = function( count ) {
5198  // remove from this.dots collection
5199  let removeDots = this.dots.splice( this.dots.length - count, count );
5200  // remove from DOM
5201  removeDots.forEach( ( dot ) => dot.remove() );
5202};
5203
5204PageDots.prototype.updateSelected = function( index ) {
5205  // remove selected class on previous
5206  if ( this.selectedDot ) {
5207    this.selectedDot.classList.remove('is-selected');
5208    this.selectedDot.removeAttribute('aria-current');
5209  }
5210  // don't proceed if no dots
5211  if ( !this.dots.length ) return;
5212
5213  this.selectedDot = this.dots[ index ];
5214  this.selectedDot.classList.add('is-selected');
5215  this.selectedDot.setAttribute( 'aria-current', 'step' );
5216};
5217
5218Flickity.PageDots = PageDots;
5219
5220// -------------------------- Flickity -------------------------- //
5221
5222Object.assign( Flickity.defaults, {
5223  pageDots: true,
5224} );
5225
5226Flickity.create.pageDots = function() {
5227  if ( !this.options.pageDots ) return;
5228
5229  this.pageDots = new PageDots();
5230  this.handlePageDotsClick = this.onPageDotsClick.bind( this );
5231  // events
5232  this.on( 'activate', this.activatePageDots );
5233  this.on( 'select', this.updateSelectedPageDots );
5234  this.on( 'cellChange', this.updatePageDots );
5235  this.on( 'resize', this.updatePageDots );
5236  this.on( 'deactivate', this.deactivatePageDots );
5237};
5238
5239let proto = Flickity.prototype;
5240
5241proto.activatePageDots = function() {
5242  this.pageDots.setDots( this.slides.length );
5243  this.focusableElems.push( ...this.pageDots.dots );
5244  this.pageDots.holder.addEventListener( 'click', this.handlePageDotsClick );
5245  this.element.append( this.pageDots.holder );
5246};
5247
5248proto.onPageDotsClick = function( event ) {
5249  let index = this.pageDots.dots.indexOf( event.target );
5250  if ( index === -1 ) return; // only dot clicks
5251
5252  this.uiChange();
5253  this.select( index );
5254};
5255
5256proto.updateSelectedPageDots = function() {
5257  this.pageDots.updateSelected( this.selectedIndex );
5258};
5259
5260proto.updatePageDots = function() {
5261  this.pageDots.dots.forEach( ( dot ) => {
5262    utils.removeFrom( this.focusableElems, dot );
5263  } );
5264  this.pageDots.setDots( this.slides.length );
5265  this.focusableElems.push( ...this.pageDots.dots );
5266};
5267
5268proto.deactivatePageDots = function() {
5269  this.pageDots.holder.remove();
5270  this.pageDots.holder.removeEventListener( 'click', this.handlePageDotsClick );
5271};
5272
5273// -----  ----- //
5274
5275Flickity.PageDots = PageDots;
5276
5277return Flickity;
5278
5279} ) );
5280// player & autoPlay
5281( function( window, factory ) {
5282  // universal module definition
5283  if ( typeof module == 'object' && module.exports ) {
5284    // CommonJS
5285    module.exports = factory( require('./core') );
5286  } else {
5287    // browser global
5288    factory( window.Flickity );
5289  }
5290
5291}( typeof window != 'undefined' ? window : this, function factory( Flickity ) {
5292
5293// -------------------------- Player -------------------------- //
5294
5295function Player( autoPlay, onTick ) {
5296  this.autoPlay = autoPlay;
5297  this.onTick = onTick;
5298  this.state = 'stopped';
5299  // visibility change event handler
5300  this.onVisibilityChange = this.visibilityChange.bind( this );
5301  this.onVisibilityPlay = this.visibilityPlay.bind( this );
5302}
5303
5304// start play
5305Player.prototype.play = function() {
5306  if ( this.state === 'playing' ) return;
5307
5308  // do not play if page is hidden, start playing when page is visible
5309  let isPageHidden = document.hidden;
5310  if ( isPageHidden ) {
5311    document.addEventListener( 'visibilitychange', this.onVisibilityPlay );
5312    return;
5313  }
5314
5315  this.state = 'playing';
5316  // listen to visibility change
5317  document.addEventListener( 'visibilitychange', this.onVisibilityChange );
5318  // start ticking
5319  this.tick();
5320};
5321
5322Player.prototype.tick = function() {
5323  // do not tick if not playing
5324  if ( this.state !== 'playing' ) return;
5325
5326  // default to 3 seconds
5327  let time = typeof this.autoPlay == 'number' ? this.autoPlay : 3000;
5328  // HACK: reset ticks if stopped and started within interval
5329  this.clear();
5330  this.timeout = setTimeout( () => {
5331    this.onTick();
5332    this.tick();
5333  }, time );
5334};
5335
5336Player.prototype.stop = function() {
5337  this.state = 'stopped';
5338  this.clear();
5339  // remove visibility change event
5340  document.removeEventListener( 'visibilitychange', this.onVisibilityChange );
5341};
5342
5343Player.prototype.clear = function() {
5344  clearTimeout( this.timeout );
5345};
5346
5347Player.prototype.pause = function() {
5348  if ( this.state === 'playing' ) {
5349    this.state = 'paused';
5350    this.clear();
5351  }
5352};
5353
5354Player.prototype.unpause = function() {
5355  // re-start play if paused
5356  if ( this.state === 'paused' ) this.play();
5357};
5358
5359// pause if page visibility is hidden, unpause if visible
5360Player.prototype.visibilityChange = function() {
5361  let isPageHidden = document.hidden;
5362  this[ isPageHidden ? 'pause' : 'unpause' ]();
5363};
5364
5365Player.prototype.visibilityPlay = function() {
5366  this.play();
5367  document.removeEventListener( 'visibilitychange', this.onVisibilityPlay );
5368};
5369
5370// -------------------------- Flickity -------------------------- //
5371
5372Object.assign( Flickity.defaults, {
5373  pauseAutoPlayOnHover: true,
5374} );
5375
5376Flickity.create.player = function() {
5377  this.player = new Player( this.options.autoPlay, () => {
5378    this.next( true );
5379  } );
5380
5381  this.on( 'activate', this.activatePlayer );
5382  this.on( 'uiChange', this.stopPlayer );
5383  this.on( 'pointerDown', this.stopPlayer );
5384  this.on( 'deactivate', this.deactivatePlayer );
5385};
5386
5387let proto = Flickity.prototype;
5388
5389proto.activatePlayer = function() {
5390  if ( !this.options.autoPlay ) return;
5391
5392  this.player.play();
5393  this.element.addEventListener( 'mouseenter', this );
5394};
5395
5396// Player API, don't hate the ... thanks I know where the door is
5397
5398proto.playPlayer = function() {
5399  this.player.play();
5400};
5401
5402proto.stopPlayer = function() {
5403  this.player.stop();
5404};
5405
5406proto.pausePlayer = function() {
5407  this.player.pause();
5408};
5409
5410proto.unpausePlayer = function() {
5411  this.player.unpause();
5412};
5413
5414proto.deactivatePlayer = function() {
5415  this.player.stop();
5416  this.element.removeEventListener( 'mouseenter', this );
5417};
5418
5419// ----- mouseenter/leave ----- //
5420
5421// pause auto-play on hover
5422proto.onmouseenter = function() {
5423  if ( !this.options.pauseAutoPlayOnHover ) return;
5424
5425  this.player.pause();
5426  this.element.addEventListener( 'mouseleave', this );
5427};
5428
5429// resume auto-play on hover off
5430proto.onmouseleave = function() {
5431  this.player.unpause();
5432  this.element.removeEventListener( 'mouseleave', this );
5433};
5434
5435// -----  ----- //
5436
5437Flickity.Player = Player;
5438
5439return Flickity;
5440
5441} ) );
5442// add, remove cell
5443( function( window, factory ) {
5444  // universal module definition
5445  if ( typeof module == 'object' && module.exports ) {
5446    // CommonJS
5447    module.exports = factory(
5448        require('./core'),
5449        require('fizzy-ui-utils'),
5450    );
5451  } else {
5452    // browser global
5453    factory(
5454        window.Flickity,
5455        window.fizzyUIUtils,
5456    );
5457  }
5458
5459}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
5460
5461// append cells to a document fragment
5462function getCellsFragment( cells ) {
5463  let fragment = document.createDocumentFragment();
5464  cells.forEach( ( cell ) => fragment.appendChild( cell.element ) );
5465  return fragment;
5466}
5467
5468// -------------------------- add/remove cell prototype -------------------------- //
5469
5470let proto = Flickity.prototype;
5471
5472/**
5473 * Insert, prepend, or append cells
5474 * @param {[Element, Array, NodeList]} elems - Elements to insert
5475 * @param {Integer} index - Zero-based number to insert
5476 */
5477proto.insert = function( elems, index ) {
5478  let cells = this._makeCells( elems );
5479  if ( !cells || !cells.length ) return;
5480
5481  let len = this.cells.length;
5482  // default to append
5483  index = index === undefined ? len : index;
5484  // add cells with document fragment
5485  let fragment = getCellsFragment( cells );
5486  // append to slider
5487  let isAppend = index === len;
5488  if ( isAppend ) {
5489    this.slider.appendChild( fragment );
5490  } else {
5491    let insertCellElement = this.cells[ index ].element;
5492    this.slider.insertBefore( fragment, insertCellElement );
5493  }
5494  // add to this.cells
5495  if ( index === 0 ) {
5496    // prepend, add to start
5497    this.cells = cells.concat( this.cells );
5498  } else if ( isAppend ) {
5499    // append, add to end
5500    this.cells = this.cells.concat( cells );
5501  } else {
5502    // insert in this.cells
5503    let endCells = this.cells.splice( index, len - index );
5504    this.cells = this.cells.concat( cells ).concat( endCells );
5505  }
5506
5507  this._sizeCells( cells );
5508  this.cellChange( index );
5509  this.positionSliderAtSelected();
5510};
5511
5512proto.append = function( elems ) {
5513  this.insert( elems, this.cells.length );
5514};
5515
5516proto.prepend = function( elems ) {
5517  this.insert( elems, 0 );
5518};
5519
5520/**
5521 * Remove cells
5522 * @param {[Element, Array, NodeList]} elems - ELements to remove
5523 */
5524proto.remove = function( elems ) {
5525  let cells = this.getCells( elems );
5526  if ( !cells || !cells.length ) return;
5527
5528  let minCellIndex = this.cells.length - 1;
5529  // remove cells from collection & DOM
5530  cells.forEach( ( cell ) => {
5531    cell.remove();
5532    let index = this.cells.indexOf( cell );
5533    minCellIndex = Math.min( index, minCellIndex );
5534    utils.removeFrom( this.cells, cell );
5535  } );
5536
5537  this.cellChange( minCellIndex );
5538  this.positionSliderAtSelected();
5539};
5540
5541/**
5542 * logic to be run after a cell's size changes
5543 * @param {Element} elem - cell's element
5544 */
5545proto.cellSizeChange = function( elem ) {
5546  let cell = this.getCell( elem );
5547  if ( !cell ) return;
5548
5549  cell.getSize();
5550
5551  let index = this.cells.indexOf( cell );
5552  this.cellChange( index );
5553  // do not position slider after lazy load
5554};
5555
5556/**
5557 * logic any time a cell is changed: added, removed, or size changed
5558 * @param {Integer} changedCellIndex - index of the changed cell, optional
5559 */
5560proto.cellChange = function( changedCellIndex ) {
5561  let prevSelectedElem = this.selectedElement;
5562  this._positionCells( changedCellIndex );
5563  this._updateWrapShiftCells();
5564  this.setGallerySize();
5565  // update selectedIndex, try to maintain position & select previous selected element
5566  let cell = this.getCell( prevSelectedElem );
5567  if ( cell ) this.selectedIndex = this.getCellSlideIndex( cell );
5568  this.selectedIndex = Math.min( this.slides.length - 1, this.selectedIndex );
5569
5570  this.emitEvent( 'cellChange', [ changedCellIndex ] );
5571  // position slider
5572  this.select( this.selectedIndex );
5573};
5574
5575// -----  ----- //
5576
5577return Flickity;
5578
5579} ) );
5580// lazyload
5581( function( window, factory ) {
5582  // universal module definition
5583  if ( typeof module == 'object' && module.exports ) {
5584    // CommonJS
5585    module.exports = factory(
5586        require('./core'),
5587        require('fizzy-ui-utils'),
5588    );
5589  } else {
5590    // browser global
5591    factory(
5592        window.Flickity,
5593        window.fizzyUIUtils,
5594    );
5595  }
5596
5597}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
5598
5599const lazyAttr = 'data-flickity-lazyload';
5600const lazySrcAttr = `${lazyAttr}-src`;
5601const lazySrcsetAttr = `${lazyAttr}-srcset`;
5602const imgSelector = `img[${lazyAttr}], img[${lazySrcAttr}], ` +
5603  `img[${lazySrcsetAttr}], source[${lazySrcsetAttr}]`;
5604
5605Flickity.create.lazyLoad = function() {
5606  this.on( 'select', this.lazyLoad );
5607
5608  this.handleLazyLoadComplete = this.onLazyLoadComplete.bind( this );
5609};
5610
5611let proto = Flickity.prototype;
5612
5613proto.lazyLoad = function() {
5614  let { lazyLoad } = this.options;
5615  if ( !lazyLoad ) return;
5616
5617  // get adjacent cells, use lazyLoad option for adjacent count
5618  let adjCount = typeof lazyLoad == 'number' ? lazyLoad : 0;
5619  // lazy load images
5620  this.getAdjacentCellElements( adjCount )
5621    .map( getCellLazyImages )
5622    .flat()
5623    .forEach( ( img ) => new LazyLoader( img, this.handleLazyLoadComplete ) );
5624};
5625
5626function getCellLazyImages( cellElem ) {
5627  // check if cell element is lazy image
5628  if ( cellElem.matches('img') ) {
5629    let cellAttr = cellElem.getAttribute( lazyAttr );
5630    let cellSrcAttr = cellElem.getAttribute( lazySrcAttr );
5631    let cellSrcsetAttr = cellElem.getAttribute( lazySrcsetAttr );
5632    if ( cellAttr || cellSrcAttr || cellSrcsetAttr ) {
5633      return cellElem;
5634    }
5635  }
5636  // select lazy images in cell
5637  return [ ...cellElem.querySelectorAll( imgSelector ) ];
5638}
5639
5640proto.onLazyLoadComplete = function( img, event ) {
5641  let cell = this.getParentCell( img );
5642  let cellElem = cell && cell.element;
5643  this.cellSizeChange( cellElem );
5644
5645  this.dispatchEvent( 'lazyLoad', event, cellElem );
5646};
5647
5648// -------------------------- LazyLoader -------------------------- //
5649
5650/**
5651 * class to handle loading images
5652 * @param {Image} img - Image element
5653 * @param {Function} onComplete - callback function
5654 */
5655function LazyLoader( img, onComplete ) {
5656  this.img = img;
5657  this.onComplete = onComplete;
5658  this.load();
5659}
5660
5661LazyLoader.prototype.handleEvent = utils.handleEvent;
5662
5663LazyLoader.prototype.load = function() {
5664  this.img.addEventListener( 'load', this );
5665  this.img.addEventListener( 'error', this );
5666  // get src & srcset
5667  let src = this.img.getAttribute( lazyAttr ) ||
5668    this.img.getAttribute( lazySrcAttr );
5669  let srcset = this.img.getAttribute( lazySrcsetAttr );
5670  // set src & serset
5671  this.img.src = src;
5672  if ( srcset ) this.img.setAttribute( 'srcset', srcset );
5673  // remove attr
5674  this.img.removeAttribute( lazyAttr );
5675  this.img.removeAttribute( lazySrcAttr );
5676  this.img.removeAttribute( lazySrcsetAttr );
5677};
5678
5679LazyLoader.prototype.onload = function( event ) {
5680  this.complete( event, 'flickity-lazyloaded' );
5681};
5682
5683LazyLoader.prototype.onerror = function( event ) {
5684  this.complete( event, 'flickity-lazyerror' );
5685};
5686
5687LazyLoader.prototype.complete = function( event, className ) {
5688  // unbind events
5689  this.img.removeEventListener( 'load', this );
5690  this.img.removeEventListener( 'error', this );
5691  let mediaElem = this.img.parentNode.matches('picture') ? this.img.parentNode : this.img;
5692  mediaElem.classList.add( className );
5693
5694  this.onComplete( this.img, event );
5695};
5696
5697// -----  ----- //
5698
5699Flickity.LazyLoader = LazyLoader;
5700
5701return Flickity;
5702
5703} ) );
5704// imagesloaded
5705( function( window, factory ) {
5706  // universal module definition
5707  if ( typeof module == 'object' && module.exports ) {
5708    // CommonJS
5709    module.exports = factory(
5710        require('./core'),
5711        require('imagesloaded'),
5712    );
5713  } else {
5714    // browser global
5715    factory(
5716        window.Flickity,
5717        window.imagesLoaded,
5718    );
5719  }
5720
5721}( typeof window != 'undefined' ? window : this,
5722    function factory( Flickity, imagesLoaded ) {
5723
5724Flickity.create.imagesLoaded = function() {
5725  this.on( 'activate', this.imagesLoaded );
5726};
5727
5728Flickity.prototype.imagesLoaded = function() {
5729  if ( !this.options.imagesLoaded ) return;
5730
5731  let onImagesLoadedProgress = ( instance, image ) => {
5732    let cell = this.getParentCell( image.img );
5733    this.cellSizeChange( cell && cell.element );
5734    if ( !this.options.freeScroll ) this.positionSliderAtSelected();
5735  };
5736  imagesLoaded( this.slider ).on( 'progress', onImagesLoadedProgress );
5737};
5738
5739return Flickity;
5740
5741} ) );
5742
5743// Flickity
5744// -------------------------------------------------------------
5745
5746// Homepage - testimonial-gallery
5747// -------------------------------------------------------------
5748// jQuery(document).ready(function($){
5749// 	$('.home .tribe-events-day-time-slot').flickity({
5750// 		wrapAround: true,
5751// 		contain: true,
5752// 		autoPlay: 5500,
5753// 		prevNextButtons: false,
5754// 		pageDots: true,
5755// 		imagesLoaded: true,
5756// 		cellAlign: 'left'
5757// 	});
5758// });
5759
5760// -------------------------------------------------------------
5761// -------------------------------------------------------------
5762// -------------------------------------------------------------
5763// Have you seen a IE mobile device? There is issues that this mmenu has with IE
5764// -------------------------------------------------------------
5765// -------------------------------------------------------------
5766// -------------------------------------------------------------
5767// if (document.documentElement.clientWidth < 769) {
vendor: 37,528 bytes, lines 5768-5769
5768/*! For license information please see mmenu.js.LICENSE.txt */
5769(()=>{"use strict";const e={hooks:{},navbar:{add:!0,title:"Menu",titleLink:"parent"},slidingSubmenus:!0},t={classNames:{divider:"Divider",nolistview:"NoListview",nopanel:"NoPanel",panel:"Panel",selected:"Selected",vertical:"Vertical"},language:null,panelNodetype:["ul","ol","div"],screenReader:{closeSubmenu:"Close submenu",openSubmenu:"Open submenu",toggleSubmenu:"Toggle submenu"}},n=(e,t)=>{"object"!=s(e)&&(e={}),"object"!=s(t)&&(t={});for(let i in t)t.hasOwnProperty(i)&&(void 0===e[i]?e[i]=t[i]:"object"==s(e[i])&&n(e[i],t[i]));return e},s=e=>({}.toString.call(e).match(/\s([a-zA-Z]+)/)[1].toLowerCase()),i=()=>"mm-"+a++;let a=0;const o=e=>"mm-clone-"==e.slice(0,9)?e:`mm-clone-${e}`,r=e=>"mm-clone-"==e.slice(0,9)?e.slice(9):e,l={},m=(e,t)=>{void 0===l[t]&&(l[t]={}),n(l[t],e)},c=e=>{const t=e.split("."),n=document.createElement(t.shift());return n.classList.add(...t),n},d=(e,t)=>t.length?[].slice.call(e.querySelectorAll(t)):[],h=(e,t)=>{const n=Array.prototype.slice.call(e.children);return t?n.filter((e=>e.matches(t))):n},p=(e,t)=>{let n=[],s=e.parentElement;for(;s;)n.push(s),s=s.parentElement;return t?n.filter((e=>e.matches(t))):n},u=e=>e.filter((e=>!e.matches(".mm-hidden"))),f=e=>{let t=[];return u(e).forEach((e=>{t.push(...h(e,"a.mm-listitem__text"))})),t.filter((e=>!e.matches(".mm-btn--next")))},b=(e,t,n)=>{e.matches("."+t)&&e.classList.add(n)};let v={};const g=(e,t,n)=>{"number"==typeof e&&(e="(min-width: "+e+"px)"),v[e]=v[e]||[],v[e].push({yes:t,no:n})},L=(e,t)=>{var n=t.matches?"yes":"no";for(let t=0;t<v[e].length;t++)v[e][t][n]()};var _,E,w,P=function(e,t,n){if(!t.has(e))throw new TypeError("attempted to set private field on non-instance");return t.set(e,n),n},y=function(e,t){if(!t.has(e))throw new TypeError("attempted to get private field on non-instance");return t.get(e)};m({"Close submenu":"Untermenü schließen",Menu:"Menü","Open submenu":"Untermenü öffnen","Toggle submenu":"Untermenü wechseln"},"de"),m({"Close submenu":"بستن زیرمنو",Menu:"منو","Open submenu":"بازکردن زیرمنو","Toggle submenu":"سوییچ زیرمنو"},"fa"),m({"Close submenu":"Submenu sluiten",Menu:"Menu","Open submenu":"Submenu openen","Toggle submenu":"Submenu wisselen"},"nl"),m({"Close submenu":"Fechar submenu",Menu:"Menu","Open submenu":"Abrir submenu","Toggle submenu":"Alternar submenu"},"pt_br"),m({"Close submenu":"Закрыть подменю",Menu:"Меню","Open submenu":"Открыть подменю","Toggle submenu":"Переключить подменю"},"ru"),m({"Close submenu":"Zatvoriť submenu",Menu:"Menu","Open submenu":"Otvoriť submenu","Toggle submenu":"Prepnúť submenu"},"sk"),m({"Close submenu":"Закрити підменю",Menu:"Меню","Open submenu":"Відкрити підменю","Toggle submenu":"Перемкнути підменю"},"uk");class S{constructor(s,i,a){return _.set(this,void 0),E.set(this,void 0),w.set(this,void 0),this.opts=n(i,e),this.conf=n(a,t),this._api=["i18n","bind","openPanel","closePanel","setSelected"],this.node={},this.hook={},this.node.menu="string"==typeof s?document.querySelector(s):s,"function"==typeof this._deprecatedWarnings&&this._deprecatedWarnings(),this.trigger("init:before"),this._initObservers(),this._initAddons(),this._initHooks(),this._initAPI(),this._initMenu(),this._initPanels(),this._initOpened(),(()=>{for(let e in v){let t=window.matchMedia(e);L(e,t),t.onchange=n=>{L(e,t)}}})(),this.trigger("init:after"),this}openPanel(e,t=!0,n=!0){if(!e)return;e=e.closest(".mm-panel"),this.trigger("openPanel:before",[e,{animation:t,setfocus:n}]);const s=e.closest(".mm-listitem--vertical");if(s){s.classList.add("mm-listitem--opened");const e=s.closest(".mm-panel");this.openPanel(e)}else{const n=h(this.node.pnls,".mm-panel--opened")[0];e.matches(".mm-panel--parent")&&n&&n.classList.add("mm-panel--highest");const s=["mm-panel--opened","mm-panel--parent"],i=[];t?s.push("mm-panel--noanimation"):i.push("mm-panel--noanimation"),h(this.node.pnls,".mm-panel").forEach((t=>{t.classList.add(...i),t.classList.remove(...s),t!==n&&t.classList.remove("mm-panel--highest"),t===e?t.removeAttribute("inert"):t.setAttribute("inert","true")})),e.classList.add("mm-panel--opened");let a=d(this.node.pnls,`#${e.dataset.mmParent}`)[0];for(;a;)a=a.closest(".mm-panel"),a.classList.add("mm-panel--parent"),a=d(this.node.pnls,`#${a.dataset.mmParent}`)[0]}this.trigger("openPanel:after",[e,{animation:t,setfocus:n}])}closePanel(e,t=!0,n=!0){if(e&&(e.matches(".mm-panel--opened")||e.parentElement.matches(".mm-listitem--opened"))){if(this.trigger("closePanel:before",[e]),e.parentElement.matches(".mm-listitem--vertical"))e.parentElement.classList.remove("mm-listitem--opened");else if(e.dataset.mmParent){const s=d(this.node.pnls,`#${e.dataset.mmParent}`)[0];this.openPanel(s,t,n)}else{const s=h(this.node.pnls,".mm-panel--parent").pop();if(s&&s!==e)this.openPanel(s,t,n);else{const s=h(this.node.pnls,".mm-panel")[0];s&&s!==e&&this.openPanel(s,t,n)}}this.trigger("closePanel:after",[e])}}togglePanel(e){let t="openPanel";(e.parentElement.matches(".mm-listitem--opened")||e.matches(".mm-panel--opened"))&&(t="closePanel"),this[t](e)}setSelected(e){this.trigger("setSelected:before",[e]),d(this.node.menu,".mm-listitem--selected").forEach((e=>{e.classList.remove("mm-listitem--selected")})),e.classList.add("mm-listitem--selected"),this.trigger("setSelected:after",[e])}bind(e,t){this.hook[e]=this.hook[e]||[],this.hook[e].push(t)}trigger(e,t){if(this.hook[e])for(var n=0,s=this.hook[e].length;n<s;n++)this.hook[e][n].apply(this,t)}_initObservers(){P(this,_,new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach((e=>{e.matches(this.conf.panelNodetype.join(", "))&&this._initListview(e)}))}))}))),P(this,E,new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach((e=>{this._initListitem(e)}))}))}))),P(this,w,new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach((e=>{(null==e?void 0:e.matches(this.conf.panelNodetype.join(", ")))&&this._initSubPanel(e)}))}))})))}_initAPI(){const e=this;this.API={},this._api.forEach((t=>{this.API[t]=function(){return e[t].apply(e,arguments)}})),this.node.menu.mmApi=this.API}_initHooks(){for(let e in this.opts.hooks)this.bind(e,this.opts.hooks[e])}_initAddons(){this.trigger("initAddons:before");for(let e in S.addons)S.addons[e].call(this);this.trigger("initAddons:after")}_initMenu(){this.trigger("initMenu:before"),this.node.wrpr=this.node.wrpr||this.node.menu.parentElement,this.node.wrpr.classList.add("mm-wrapper"),this.node.menu.classList.add("mm-menu"),this.node.menu.id=this.node.menu.id||i(),this.node.menu.setAttribute("aria-label",this.i18n(this.opts.navbar.title||"Menu")),this.node.menu.setAttribute("aria-modal","true"),this.node.menu.setAttribute("role","dialog");const e=h(this.node.menu).filter((e=>e.matches(this.conf.panelNodetype.join(", "))));this.node.pnls=c("div.mm-panels"),this.node.menu.append(this.node.pnls),e.forEach((e=>{this._initPanel(e)})),this.trigger("initMenu:after")}_initPanels(){this.trigger("initPanels:before"),this.node.menu.addEventListener("click",(e=>{var t,n;const s=(null===(n=null===(t=e.target)||void 0===t?void 0:t.closest("a[href]"))||void 0===n?void 0:n.getAttribute("href"))||"";if("#"===s.slice(0,1))try{const t=d(this.node.menu,s)[0];t&&(e.preventDefault(),this.togglePanel(t))}catch(e){}}),{capture:!0}),this.trigger("initPanels:after")}_initPanel(e){var t;if(!e.matches(".mm-panel")&&(b(e,this.conf.classNames.panel,"mm-panel"),b(e,this.conf.classNames.nopanel,"mm-nopanel"),!e.matches(".mm-nopanel"))){if(this.trigger("initPanel:before",[e]),e.id=e.id||i(),e.matches("ul, ol")){const t=c("div");t.id=e.id,e.removeAttribute("id"),[].slice.call(e.classList).filter((e=>"mm-"===e.slice(0,3))).forEach((n=>{t.classList.add(n),e.classList.remove(n)})),Object.keys(e.dataset).filter((e=>"mm"===e.slice(0,2))).forEach((n=>{t.dataset[n]=e.dataset[n],delete e.dataset[n]})),e.before(t),t.append(e),e=t}return e.classList.add("mm-panel"),(null===(t=e.parentElement)||void 0===t?void 0:t.matches(".mm-listitem--vertical"))||this.node.pnls.append(e),this._initNavbar(e),h(e,"ul, ol").forEach((e=>{this._initListview(e)})),y(this,_).observe(e,{childList:!0}),this.trigger("initPanel:after",[e]),e}}_initNavbar(e){if(h(e,".mm-navbar").length)return;let t=null,n=null;if(e.dataset.mmParent)for(t=d(this.node.pnls,`#${e.dataset.mmParent}`)[0],n=t.closest(".mm-panel");n.closest(".mm-listitem--vertical");)n=n.parentElement.closest(".mm-panel");if(null==t?void 0:t.matches(".mm-listitem--vertical"))return;this.trigger("initNavbar:before",[e]);const s=c("div.mm-navbar");if(this.opts.navbar.add||s.classList.add("mm-hidden"),n){const e=c("a.mm-btn.mm-btn--prev.mm-navbar__btn");e.href=`#${n.id}`,e.setAttribute("aria-label",this.i18n(this.conf.screenReader.closeSubmenu)),s.append(e)}let i=null;t?i=h(t,".mm-listitem__text")[0]:n&&(i=d(n,'a[href="#'+e.id+'"]')[0]);const a=c("a.mm-navbar__title");switch(a.tabIndex=-1,a.setAttribute("aria-hidden","true"),this.opts.navbar.titleLink){case"anchor":i&&(a.href=i.getAttribute("href"));break;case"parent":n&&(a.href=`#${n.id}`)}const o=c("span");var r;o.innerHTML=e.dataset.mmTitle||((r=i)?[].slice.call(r.childNodes).filter((e=>e.nodeType===Node.TEXT_NODE)).map((e=>e.nodeValue.trim())).join(" "):"")||this.i18n(this.opts.navbar.title||"Menu"),e.prepend(s),s.append(a),a.append(o),this.trigger("initNavbar:after",[e])}_initListview(e){["htmlulistelement","htmlolistelement"].includes(s(e))&&(e.matches(".mm-listview")||(b(e,this.conf.classNames.nolistview,"mm-nolistview"),e.matches(".mm-nolistview")||(this.trigger("initListview:before",[e]),e.classList.add("mm-listview"),h(e).forEach((e=>{this._initListitem(e)})),y(this,E).observe(e,{childList:!0}),this.trigger("initListview:after",[e]))))}_initListitem(e){["htmllielement"].includes(s(e))&&(e.matches(".mm-listitem")||(b(e,this.conf.classNames.divider,"mm-divider"),e.matches(".mm-divider")||(this.trigger("initListitem:before",[e]),e.classList.add("mm-listitem"),b(e,this.conf.classNames.selected,"mm-listitem--selected"),h(e,"a, span").forEach((e=>{e.classList.add("mm-listitem__text")})),h(e,this.conf.panelNodetype.join(", ")).forEach((e=>{this._initSubPanel(e)})),y(this,w).observe(e,{childList:!0}),this.trigger("initListitem:after",[e]))))}_initSubPanel(e){if(e.matches(".mm-panel"))return;const t=e.parentElement;(e.matches("."+this.conf.classNames.vertical)||!this.opts.slidingSubmenus)&&t.classList.add("mm-listitem--vertical"),t.id=t.id||i(),e.id=e.id||i(),t.dataset.mmChild=e.id,e.dataset.mmParent=t.id;let n=h(t,".mm-btn")[0];n||(n=c("a.mm-btn.mm-btn--next.mm-listitem__btn"),h(t,"a, span").forEach((e=>{e.matches("span")?(n.classList.add("mm-listitem__text"),n.innerHTML=e.innerHTML,t.insertBefore(n,e.nextElementSibling),e.remove()):t.insertBefore(n,e.nextElementSibling)})),n.setAttribute("aria-label",this.i18n(this.conf.screenReader[t.matches(".mm-listitem--vertical")?"toggleSubmenu":"openSubmenu"]))),n.href=`#${e.id}`,this._initPanel(e)}_initOpened(){this.trigger("initOpened:before");const e=d(this.node.pnls,".mm-listitem--selected").pop();let t=h(this.node.pnls,".mm-panel")[0];e&&(this.setSelected(e),t=e.closest(".mm-panel")),this.openPanel(t,!1,!1),this.trigger("initOpened:after")}i18n(e){return((e,t)=>"string"==typeof t&&void 0!==l[t]&&l[t][e]||e)(e,this.conf.language)}static i18n(e={},t=""){if(!e||!t)return l;m(e,t)}}_=new WeakMap,E=new WeakMap,w=new WeakMap,S.addons={},S.node={},S.vars={};const M={use:!0,position:"left"},k={clone:!1,menu:{insertMethod:"append",insertSelector:"body"},page:{nodetype:"div",selector:null,noSelector:[]},screenReader:{closeMenu:"Close menu",openMenu:"Open menu"}},T=["left","left-front","right","right-front","top","bottom"];S.prototype.open=function(){this.node.menu.matches(".mm-menu--opened")||(this.trigger("open:before"),this.node.wrpr.classList.add("mm-wrapper--opened",`mm-wrapper--position-${this.opts.offCanvas.position}`),this.node.menu.classList.add("mm-menu--opened"),this.node.menu.removeAttribute("inert"),S.node.blck.removeAttribute("inert"),S.node.page.setAttribute("inert","true"),this.node.open=document.activeElement,this.trigger("open:after"))},S.prototype.close=function(){var e;this.node.menu.matches(".mm-menu--opened")&&(this.trigger("close:before"),this.node.wrpr.classList.remove("mm-wrapper--opened",`mm-wrapper--position-${this.opts.offCanvas.position}`),this.node.menu.classList.remove("mm-menu--opened"),this.node.menu.setAttribute("inert","true"),S.node.blck.setAttribute("inert","true"),S.node.page.removeAttribute("inert"),null===(e=this.node.open||document.querySelector(`[href="#${this.node.menu.id}"]`)||null)||void 0===e||e.focus(),document.body.scrollLeft=0,document.documentElement.scrollLeft=0,this.trigger("close:after"))},S.prototype.setPage=function(e){const t=this.conf.offCanvas;if(!e){let n="string"==typeof t.page.selector?d(document.body,t.page.selector):h(document.body,t.page.nodetype);if(n=n.filter((e=>!e.matches(".mm-menu, .mm-wrapper__blocker"))),t.page.noSelector.length&&(n=n.filter((e=>!e.matches(t.page.noSelector.join(", "))))),n.length>1){let e=c("div");n[0].before(e),n.forEach((t=>{e.append(t)})),n=[e]}e=n[0]}this.trigger("setPage:before",[e]),e.classList.add("mm-page","mm-slideout"),e.id=e.id||i(),S.node.blck.setAttribute("href",`#${e.id}`),S.node.page=e,this.trigger("setPage:after",[e])};const x={fix:!0},A="ontouchstart"in window||!!navigator.msMaxTouchPoints||!1,C=["light","dark","white","black","light-contrast","dark-contrast","white-contrast","black-contrast"];S.prototype.theme=function(e=null){const t=this.opts.theme;if(!e)return t;C.includes(e)&&(this.node.menu.classList.remove(`mm-menu--theme-${t}`),this.node.menu.classList.add(`mm-menu--theme-${e}`),this.opts.theme=e)};const N={close:!1,open:!1},$={add:!1},O={use:!1,top:[],bottom:[],position:"left",type:"default"},H={add:!1,blockPanel:!0,visible:3},q={breadcrumbs:{separator:"/",removeFirst:!1}};function I(){this.opts.navbars=this.opts.navbars||[],this.conf.navbars=this.conf.navbars||{},n(this.conf.navbars,q);let e=this.opts.navbars;if(void 0!==e&&(e instanceof Array||(e=[e]),e.length)){var t={};e.forEach((e=>{if(!(e=function(e){return"boolean"==typeof e&&e&&(e={}),"object"!=typeof e&&(e={}),void 0===e.content&&(e.content=["prev","title"]),e.content instanceof Array||(e.content=[e.content]),void 0===e.use&&(e.use=!0),e}(e)).use)return;const n=c("div.mm-navbar");let{position:s}=e;"bottom"!==s&&(s="top"),t[s]||(t[s]=c("div.mm-navbars.mm-navbars--"+s)),t[s].append(n);for(let t=0,s=e.content.length;t<s;t++){const s=e.content[t];if("string"==typeof s){const e=I.navbarContents[s];if("function"==typeof e)e.call(this,n);else{let e=c("span");e.innerHTML=s;const t=h(e);1==t.length&&(e=t[0]),n.append(e)}}else n.append(s)}if("string"==typeof e.type){const t=I.navbarTypes[e.type];"function"==typeof t&&t.call(this,n)}let i=()=>{n.classList.remove("mm-hidden")};"boolean"==typeof e.use?this.bind("initMenu:after",i):g(e.use,i,(()=>{n.classList.add("mm-hidden")}))})),this.bind("initMenu:after",(()=>{for(let e in t)this.node.pnls["bottom"==e?"after":"before"](t[e])}))}}I.navbarContents={breadcrumbs:function(e){var t=c("div.mm-navbar__breadcrumbs");e.append(t),this.bind("initNavbar:after",(e=>{if(!e.querySelector(".mm-navbar__breadcrumbs")){h(e,".mm-navbar")[0].classList.add("mm-hidden");for(var t=[],n=c("span.mm-navbar__breadcrumbs"),s=e,i=!0;s;){if(!(s=s.closest(".mm-panel")).parentElement.matches(".mm-listitem--vertical")){let e=d(s,".mm-navbar__title span")[0];if(e){let n=e.textContent;n.length&&t.unshift(i?`<span>${n}</span>`:`<a \n                                    href="#${s.id}" \n                                    title="${this.i18n(this.conf.screenReader.openSubmenu)}"\n                                    >${n}</a>`)}i=!1}s=d(this.node.pnls,`#${s.dataset.mmParent}`)[0]}this.conf.navbars.breadcrumbs.removeFirst&&t.shift(),n.innerHTML=t.join('<span class="mm-separator">'+this.conf.navbars.breadcrumbs.separator+"</span>"),h(e,".mm-navbar")[0].append(n)}})),this.bind("openPanel:before",(e=>{var n=e.querySelector(".mm-navbar__breadcrumbs");t.innerHTML=n?n.innerHTML:""}))},close:function(e){const t=c("a.mm-btn.mm-btn--close.mm-navbar__btn");t.setAttribute("aria-label",this.i18n(this.conf.offCanvas.screenReader.closeMenu)),e.append(t),this.bind("setPage:after",(e=>{t.href=`#${e.id}`}))},prev:function(e){let t=c("a.mm-btn.mm-hidden");e.append(t),this.bind("initNavbar:after",(e=>{h(e,".mm-navbar")[0].classList.add("mm-hidden")})),this.bind("openPanel:before",(e=>{if(e.parentElement.matches(".mm-listitem--vertical"))return;t.classList.add("mm-hidden");const n=e.querySelector(".mm-navbar__btn.mm-btn--prev");if(n){const e=n.cloneNode(!0);t.after(e),t.remove(),t=e}}))},searchfield:function(e){let t=c("div.mm-navbar__searchfield");t.id=i(),e.append(t),this.opts.searchfield=this.opts.searchfield||{},this.opts.searchfield.add=!0,this.opts.searchfield.addTo=`#${t.id}`},title:function(e){let t=c("a.mm-navbar__title");e.append(t),this.bind("openPanel:before",(e=>{if(e.parentElement.matches(".mm-listitem--vertical"))return;const n=e.querySelector(".mm-navbar__title");if(n){const e=n.cloneNode(!0);t.after(e),t.remove(),t=e}}))}},I.navbarTypes={tabs:function(e){function t(n){const s=h(e,`.mm-navbar__tab[href="#${n.id}"]`)[0];if(s)s.classList.add("mm-navbar__tab--selected"),s.ariaExpanded="true";else{const e=d(this.node.pnls,`#${n.dataset.mmParent}`)[0];e&&t.call(this,e.closest(".mm-panel"))}}e.classList.add("mm-navbar--tabs"),e.closest(".mm-navbars").classList.add("mm-navbars--has-tabs"),h(e,"a").forEach((e=>{e.classList.add("mm-navbar__tab")})),this.bind("openPanel:before",(n=>{h(e,"a").forEach((e=>{e.classList.remove("mm-navbar__tab--selected"),e.ariaExpanded="false"})),t.call(this,n)})),this.bind("initPanels:after",(()=>{e.addEventListener("click",(e=>{var t,n,s;const i=null===(n=null===(t=e.target)||void 0===t?void 0:t.closest(".mm-navbar__tab"))||void 0===n?void 0:n.getAttribute("href");try{null===(s=d(this.node.pnls,`${i}.mm-panel`)[0])||void 0===s||s.classList.add("mm-panel--noanimation")}catch(e){}}),{capture:!0})}))}};const j={scroll:!1,update:!1},B={scrollOffset:0,updateOffset:50},R={add:!1,addTo:"panels",noResults:"No results found.",placeholder:"Search",search:!0,searchIn:"panels",splash:"",title:"Search"},D={cancel:!0,clear:!0,form:{},input:{},panel:{},submit:!1};m({cancel:"abbrechen","Cancel searching":"Suche abbrechen","Clear searchfield":"Suchfeld löschen","No results found.":"Keine Ergebnisse gefunden.",Search:"Suche"},"de"),m({cancel:"انصراف","Cancel searching":"لغو جستجو","Clear searchfield":"پاک کردن فیلد جستجو","No results found.":"نتیجه‌ای یافت نشد.",Search:"جستجو"},"fa"),m({cancel:"annuleren","Cancel searching":"Zoeken annuleren","Clear searchfield":"Zoekveld leeg maken","No results found.":"Geen resultaten gevonden.",Search:"Zoeken"},"nl"),m({cancel:"cancelar","Cancel searching":"Cancelar pesquisa","Clear searchfield":"Limpar campo de pesquisa","No results found.":"Nenhum resultado encontrado.",Search:"Buscar"},"pt_br"),m({cancel:"отменить","Cancel searching":"Отменить поиск","Clear searchfield":"Очистить поле поиска","No results found.":"Ничего не найдено.",Search:"Найти"},"ru"),m({cancel:"zrušiť","Cancel searching":"Zrušiť vyhľadávanie","Clear searchfield":"Vymazať pole vyhľadávania","No results found.":"Neboli nájdené žiadne výsledky.",Search:"Vyhľadávanie"},"sk"),m({cancel:"скасувати","Cancel searching":"Скасувати пошук","Clear searchfield":"Очистити поле пошуку","No results found.":"Нічого не знайдено.",Search:"Пошук"},"uk");const F=function(){const e=this.opts.searchfield,t=this.conf.searchfield;let n=h(this.node.pnls,".mm-panel--search")[0];return n||(n=c("div.mm-panel--search"),K(n,t.panel),e.title.length&&(n.dataset.mmTitle=this.i18n(e.title)),n.append(c("ul")),this._initPanel(n),n)},Z=function(e){const t=this.opts.searchfield;if(e.matches(t.addTo)){const t=e.matches(".mm-panel--search");if(!d(e,".mm-searchfield").length){const n=W.call(this,t);t&&n.classList.add("mm-searchfield--cancelable"),e.prepend(n),z.call(this,n)}}if(t.splash.length&&e.matches(".mm-panel--search")&&!d(e,".mm-panel__splash").length){const n=c("div.mm-panel__splash");n.innerHTML=t.splash,e.append(n)}if(t.noResults.length&&!d(e,".mm-panel__noresults").length){const n=c("div.mm-panel__noresults");n.innerHTML=this.i18n(t.noResults),e.append(n)}},W=function(e=!1){const t=this.opts.searchfield,n=this.conf.searchfield,s=c("form.mm-searchfield");K(s,n.form);const i=c("div.mm-searchfield__input");s.append(i);const a=c("input");if(i.append(a),a.type="text",a.autocomplete="off",a.placeholder=this.i18n(t.placeholder),a.setAttribute("aria-label",this.i18n(t.placeholder)),K(a,n.input),n.submit){const e=c("button.mm-btnreset.mm-btn.mm-btn--next.mm-searchfield__btn");e.type="submit",i.append(e)}else if(n.clear){const e=c("button.mm-btnreset.mm-btn.mm-btn--close.mm-searchfield__btn");e.type="reset",e.setAttribute("aria-label",this.i18n("Clear searchfield")),i.append(e),s.addEventListener("reset",(()=>{window.requestAnimationFrame((()=>{a.dispatchEvent(new Event("input"))}))}))}if(n.cancel&&e){const e=c("a.mm-searchfield__cancel");e.href="#",e.setAttribute("aria-label",this.i18n("Cancel searching")),e.textContent=this.i18n("cancel"),s.append(e),e.addEventListener("click",(e=>{e.preventDefault(),this.closePanel(h(this.node.pnls,".mm-panel--search")[0],!1)}))}return s},z=function(e){const t=this.opts.searchfield,n=e.closest(".mm-panel")||d(this.node.pnls,".mm-panel--search")[0],s=d(e,"input")[0];let i=n.matches(".mm-panel--search")?h(this.node.pnls,t.searchIn):[n];i=i.filter((e=>!e.matches(".mm-panel--search")));const a=()=>{const a=s.value.toLowerCase().trim();if(a.length?e.classList.add("mm-searchfield--searching"):e.classList.remove("mm-searchfield--searching"),!t.search)return;const o=[];if(i.forEach((e=>{e.scrollTop=0,o.push(...d(e,".mm-listitem"))})),a.length){this.trigger("search:before"),n.classList.add("mm-panel--searching"),o.forEach((e=>{const t=h(e,".mm-listitem__text")[0];var n;(!t||(n=t,[].slice.call(n.childNodes).filter((e=>!e.ariaHidden)).map((e=>e.textContent)).join(" ")).toLowerCase().indexOf(a)>-1)&&(e.dataset.mmSearchresult=a)}));let e=0;e=n.matches(".mm-panel--search")?V(n,a,i):Y(a,i),n.classList[0==e?"add":"remove"]("mm-panel--noresults"),this.trigger("search:after")}else this.trigger("clear:before"),n.classList.remove("mm-panel--searching","mm-panel--noresults"),n.matches(".mm-panel--search")?(U(n),t.splash||this.closePanel(n,!1,!1)):G(i),this.trigger("clear:after")};s.addEventListener("input",a),a()},V=(e,t,n)=>{const s=d(e,".mm-listview")[0];s.innerHTML="";let i=0;return n.forEach((e=>{const n=d(e,`[data-mm-searchresult="${t}"]`);if(i+=n.length,n.length){const t=d(e,".mm-navbar__title")[0];if(t){const e=c("li.mm-divider");e.innerHTML=t.innerHTML,s.append(e)}n.forEach((e=>{const t=e.cloneNode(!0);s.append(t)}))}})),d(s,".mm-panel").forEach((e=>{e.remove()})),["id","data-mm-parent","data-mm-child"].forEach((e=>{d(s,`[${e}]`).forEach((t=>{t.removeAttribute(e)}))})),d(s,".mm-listitem--opened").forEach((e=>{e.classList.remove("mm-listitem--opened")})),i},U=e=>{d(e,".mm-listview")[0].innerHTML=""},Y=(e,t)=>{let n=0;return t.forEach((t=>{const s=d(t,`[data-mm-searchresult="${e}"]`);n+=s.length,s.length&&s.forEach((t=>{const n=((e,t)=>{let n=[],s=e.previousElementSibling;for(;s;)t&&!s.matches(t)||n.push(s),s=s.previousElementSibling;return n})(t,".mm-divider")[0];n&&(n.dataset.mmSearchresult=e)})),d(t,".mm-listitem, .mm-divider").forEach((t=>{t.classList.add("mm-hidden"),t.dataset.mmSearchresult===e&&[t,...p(t,".mm-listitem")].forEach((e=>{e.classList.remove("mm-hidden")}))}))})),n},G=e=>{e.forEach((e=>{d(e,".mm-listitem, .mm-divider").forEach((e=>{e.classList.remove("mm-hidden")}))}))},K=(e,t)=>{t&&Object.keys(t).forEach((n=>{e[n]=t[n]}))},X={add:!1,addTo:"panels"},J={current:!0,hover:!1,parent:!1},Q={collapsed:{use:!1},expanded:{use:!1,initial:"open"}};S.addons={offcanvas:function(){this.opts.offCanvas=this.opts.offCanvas||{},this.conf.offCanvas=this.conf.offCanvas||{};const e=n(this.opts.offCanvas,M),t=n(this.conf.offCanvas,k);e.use&&(T.includes(e.position)||(e.position=T[0]),this._api.push("open","close","setPage","position"),t.clone&&(this.node.menu=this.node.menu.cloneNode(!0),this.node.menu.id&&(this.node.menu.id=o(this.node.menu.id)),d(this.node.menu,"[id]").forEach((e=>{e.id=o(e.id)}))),this.bind("initMenu:before",(()=>{this.node.wrpr=document.querySelector(t.menu.insertSelector),this.node.wrpr[t.menu.insertMethod](this.node.menu)})),S.node.blck||this.bind("initMenu:before",(()=>{const e=c("a.mm-wrapper__blocker.mm-blocker.mm-slideout");e.id=i(),e.setAttribute("aria-label",this.i18n(t.screenReader.closeMenu)),e.setAttribute("inert","true"),document.querySelector(t.menu.insertSelector).append(e),S.node.blck=e})),this.bind("initMenu:after",(()=>{this.setPage(S.node.page),this.node.menu.classList.add("mm-menu--offcanvas"),this.node.menu.setAttribute("inert","true"),T.includes(e.position)&&(this.node.wrpr.classList.add(`mm-wrapper--position-${e.position}`),this.node.menu.classList.add(`mm-menu--position-${e.position}`));let t=window.location.hash;if(t){let e=r(this.node.menu.id);e&&e==t.slice(1)&&setTimeout((()=>{this.open()}),1e3)}})),document.addEventListener("click",(e=>{var t;switch(null===(t=e.target.closest("a"))||void 0===t?void 0:t.getAttribute("href")){case`#${r(this.node.menu.id)}`:e.preventDefault(),this.open();break;case`#${r(S.node.page.id)}`:e.preventDefault(),this.close()}})),document.addEventListener("keyup",(e=>{"Escape"==e.key&&this.close()})))},scrollBugFix:function(){if(!A||!this.opts.offCanvas.use)return;if(this.opts.scrollBugFix=this.opts.scrollBugFix||{},!n(this.opts.scrollBugFix,x).fix)return;const e=(e=>{let t="",n=null;return e.addEventListener("touchstart",(e=>{1===e.touches.length&&(t="",n=e.touches[0].pageY)})),e.addEventListener("touchend",(e=>{0===e.touches.length&&(t="",n=null)})),e.addEventListener("touchmove",(e=>{if(t="",n&&1===e.touches.length){const s=e.changedTouches[0].pageY;s>n?t="down":s<n&&(t="up"),n=s}})),{get:()=>t}})(this.node.menu);this.node.menu.addEventListener("scroll",(e=>{e.preventDefault(),e.stopPropagation()}),{passive:!1}),this.node.menu.addEventListener("touchmove",(t=>{let n=t.target.closest(".mm-panel, .mm-iconbar__top, .mm-iconbar__bottom");n&&n.closest(".mm-listitem--vertical")&&(n=p(n,".mm-panel").pop()),n?(n.scrollHeight===n.offsetHeight||0==n.scrollTop&&"down"==e.get()||n.scrollHeight==n.scrollTop+n.offsetHeight&&"up"==e.get())&&t.stopPropagation():t.stopPropagation()}),{passive:!1}),this.bind("open:after",(()=>{var e=h(this.node.pnls,".mm-panel--opened")[0];e&&(e.scrollTop=0)})),window.addEventListener("orientationchange",(e=>{var t=h(this.node.pnls,".mm-panel--opened")[0];t&&(t.scrollTop=0,t.style["-webkit-overflow-scrolling"]="auto",t.style["-webkit-overflow-scrolling"]="touch")}))},theme:function(){this.opts.theme=this.opts.theme||"light";const e=this.opts.theme;C.includes(e)||(this.opts.theme=C[0]),this._api.push("theme"),this.bind("initMenu:after",(()=>{this.theme(this.opts.theme)}))},backButton:function(){if(this.opts.backButton=this.opts.backButton||{},!this.opts.offCanvas.use)return;const e=n(this.opts.backButton,N),t=`#${this.node.menu.id}`;if(e.close){let e=[];const n=()=>{e=[t],h(this.node.pnls,".mm-panel--opened, .mm-panel--parent").forEach((t=>{e.push("#"+t.id)}))};this.bind("open:after",(()=>{history.pushState(null,"",location.pathname+location.search+t)})),this.bind("open:after",n),this.bind("openPanel:after",n),this.bind("close:after",(()=>{e=[],history.back(),history.pushState(null,"",location.pathname+location.search)})),window.addEventListener("popstate",(()=>{if(this.node.menu.matches(".mm-menu--opened")&&e.length){e=e.slice(0,-1);const n=e[e.length-1];n==t?this.close():(this.openPanel(this.node.menu.querySelector(n)),history.pushState(null,"",location.pathname+location.search+t))}}))}e.open&&window.addEventListener("popstate",(e=>{this.node.menu.matches(".mm-menu--opened")||location.hash!=t||this.open()}))},counters:function(){if(this.opts.counters=this.opts.counters||{},!n(this.opts.counters,$).add)return;const e=e=>{const t=this.node.pnls.querySelector(`#${e.dataset.mmParent}`);if(!t)return;const n=t.querySelector(".mm-counter");if(!n)return;const s=[];h(e,".mm-listview").forEach((e=>{s.push(...h(e,".mm-listitem"))})),n.innerHTML=u(s).length.toString()},t=new MutationObserver((t=>{t.forEach((t=>{"class"==t.attributeName&&e(t.target.closest(".mm-panel"))}))}));this.bind("initListview:after",(t=>{const n=t.closest(".mm-panel"),s=this.node.pnls.querySelector(`#${n.dataset.mmParent}`);if(!s)return;const i=h(s,".mm-btn")[0];if(i){if(!h(i,".mm-counter").length){const e=c("span.mm-counter");e.setAttribute("aria-hidden","true"),i.prepend(e)}e(n)}})),this.bind("initListitem:after",(e=>{const n=e.closest(".mm-panel");n&&this.node.pnls.querySelector(`#${n.dataset.mmParent}`)&&t.observe(e,{attributes:!0})}))},iconbar:function(){this.opts.iconbar=this.opts.iconbar||{};const e=n(this.opts.iconbar,O);if(!e.use)return;let t;if(["top","bottom"].forEach(((n,i)=>{let a=e[n];"array"!=s(a)&&(a=[a]);const o=c("div.mm-iconbar__"+n);for(let e=0,t=a.length;e<t;e++)"string"==typeof a[e]?o.innerHTML+=a[e]:o.append(a[e]);o.children.length&&(t||(t=c("div.mm-iconbar")),t.append(o))})),t){this.bind("initMenu:after",(()=>{this.node.menu.prepend(t)}));let n="mm-menu--iconbar-"+e.position,s=()=>{this.node.menu.classList.add(n)},i=()=>{this.node.menu.classList.remove(n)};if("boolean"==typeof e.use?this.bind("initMenu:after",s):g(e.use,s,i),"tabs"==e.type){t.classList.add("mm-iconbar--tabs"),t.addEventListener("click",(e=>{const t=e.target.closest(".mm-iconbar__tab");if(t)if(t.matches(".mm-iconbar__tab--selected"))e.stopImmediatePropagation();else try{const n=d(this.node.menu,`${t.getAttribute("href")}.mm-panel`)[0];n&&(e.preventDefault(),e.stopImmediatePropagation(),this.openPanel(n,!1))}catch(e){}}));const e=n=>{d(t,"a").forEach((e=>{e.classList.remove("mm-iconbar__tab--selected")}));const s=d(t,'[href="#'+n.id+'"]')[0];if(s)s.classList.add("mm-iconbar__tab--selected");else{const t=d(this.node.pnls,`#${n.dataset.mmParent}`)[0];t&&e(t.closest(".mm-panel"))}};this.bind("openPanel:before",e)}}},iconPanels:function(){this.opts.iconPanels=this.opts.iconPanels||{};const e=n(this.opts.iconPanels,H);let t=!1;if("first"==e.visible&&(t=!0,e.visible=1),e.visible=Math.min(3,Math.max(1,e.visible)),e.visible++,e.add){this.bind("initMenu:after",(()=>{this.node.menu.classList.add("mm-menu--iconpanel")}));const n=["mm-panel--iconpanel-0","mm-panel--iconpanel-1","mm-panel--iconpanel-2","mm-panel--iconpanel-3"];t?this.bind("initMenu:after",(()=>{var e;null===(e=h(this.node.pnls,".mm-panel")[0])||void 0===e||e.classList.add("mm-panel--iconpanel-first")})):this.bind("openPanel:after",(t=>{if(t.closest(".mm-listitem--vertical"))return;let s=h(this.node.pnls,".mm-panel");s=s.filter((e=>e.matches(".mm-panel--parent"))),s.push(t),s=s.slice(-e.visible),s.forEach(((e,t)=>{e.classList.remove("mm-panel--iconpanel-first",...n),e.classList.add(`mm-panel--iconpanel-${t}`)}))}))}},navbars:I,pageScroll:function(){this.opts.pageScroll=this.opts.pageScroll||{},this.conf.pageScroll=this.conf.pageScroll||{};const e=n(this.opts.pageScroll,j),t=n(this.conf.pageScroll,B);var s;function i(){s&&window.scrollTo({top:s.getBoundingClientRect().top+document.scrollingElement.scrollTop-t.scrollOffset,behavior:"smooth"}),s=null}function a(e){try{if("#"==e.slice(0,1))return d(S.node.page,e)[0]}catch(e){}return null}if(this.opts.offCanvas.use&&e.scroll&&(this.bind("close:after",(()=>{i()})),this.node.menu.addEventListener("click",(e=>{var t,n;const o=(null===(n=null===(t=e.target)||void 0===t?void 0:t.closest("a[href]"))||void 0===n?void 0:n.getAttribute("href"))||"";(s=a(o))&&(e.preventDefault(),this.node.menu.matches(".mm-menu--sidebar-expanded")&&this.node.wrpr.matches(".mm-wrapper--sidebar-expanded")?i():this.close())}))),e.update){let e=[];this.bind("initListview:after",(t=>{const n=h(t,".mm-listitem");f(n).forEach((t=>{const n=a(t.getAttribute("href"));n&&e.unshift(n)}))}));let n=-1;window.addEventListener("scroll",(s=>{const i=window.scrollY;for(var a=0;a<e.length;a++)if(e[a].offsetTop<i+t.updateOffset){if(n!==a){n=a;let t=h(this.node.pnls,".mm-panel--opened")[0],s=d(t,".mm-listitem"),i=f(s);i=i.filter((t=>t.matches('[href="#'+e[a].id+'"]'))),i.length&&this.setSelected(i[0].parentElement)}break}}),{passive:!0})}},searchfield:function(){this.opts.searchfield=this.opts.searchfield||{},this.conf.searchfield=this.conf.searchfield||{};const e=n(this.opts.searchfield,R);if(n(this.conf.searchfield,D),e.add){switch(e.addTo){case"panels":e.addTo=".mm-panel";break;case"searchpanel":e.addTo=".mm-panel--search"}"panels"===e.searchIn&&(e.searchIn=".mm-panel"),this.bind("initPanel:after",(t=>{t.matches(e.addTo)&&!t.closest(".mm-listitem--vertical")&&Z.call(this,t)})),this.bind("initMenu:after",(()=>{const t=F.call(this);Z.call(this,t),d(this.node.menu,e.addTo).forEach((n=>{if(!n.matches(".mm-panel")){const s=W.call(this,!0);n.append(s);const i=d(s,"input")[0];e.splash.length?(i.addEventListener("focusin",(()=>{this.openPanel(t,!1,!1)})),this.bind("openPanel:after",(e=>{e.matches(".mm-panel--search")?s.classList.add("mm-searchfield--cancelable"):s.classList.remove("mm-searchfield--cancelable")}))):(this.bind("search:after",(()=>{this.openPanel(t,!1,!1)})),i.addEventListener("focusout",(()=>{i.value.length||this.closePanel(t,!1)}))),z.call(this,s)}}))})),this.bind("close:before",(()=>{d(this.node.menu,".mm-searchfield input").forEach((e=>{e.blur()}))}))}},sectionIndexer:function(){this.opts.sectionIndexer=this.opts.sectionIndexer||{},n(this.opts.sectionIndexer,X).add&&this.bind("initPanels:after",(()=>{if(!this.node.indx){let e="";"abcdefghijklmnopqrstuvwxyz".split("").forEach((t=>{e+='<a href="#">'+t+"</a>"}));let t=c("div.mm-sectionindexer");t.innerHTML=e,this.node.pnls.prepend(t),this.node.indx=t,this.node.indx.addEventListener("click",(e=>{e.target.matches("a")&&e.preventDefault()}));let n=e=>{if(!e.target.matches("a"))return;const t=e.target.textContent,n=h(this.node.pnls,".mm-panel--opened")[0];let s=-1,i=n.scrollTop;n.scrollTop=0,d(n,".mm-divider").filter((e=>!e.matches(".mm-hidden"))).forEach((e=>{s<0&&t==e.textContent.trim().slice(0,1).toLowerCase()&&(s=e.offsetTop)})),n.scrollTop=s>-1?s:i};A?(this.node.indx.addEventListener("touchstart",n),this.node.indx.addEventListener("touchmove",n)):this.node.indx.addEventListener("mouseover",n)}this.bind("openPanel:before",(e=>{const t=d(e,".mm-divider").filter((e=>!e.matches(".mm-hidden"))).length;this.node.indx.classList[t?"add":"remove"]("mm-sectionindexer--active")}))}))},setSelected:function(){this.opts.setSelected=this.opts.setSelected||{};const e=n(this.opts.setSelected,J);if("detect"==e.current){const e=t=>{t=t.split("?")[0].split("#")[0];const n=this.node.menu.querySelector('a[href="'+t+'"], a[href="'+t+'/"]');if(n)this.setSelected(n.parentElement);else{const n=t.split("/").slice(0,-1);n.length&&e(n.join("/"))}};this.bind("initMenu:after",(()=>{e.call(this,window.location.href)}))}else e.current||this.bind("initListview:after",(e=>{h(e,".mm-listitem--selected").forEach((e=>{e.classList.remove("mm-listitem--selected")}))}));e.hover&&this.bind("initMenu:after",(()=>{this.node.menu.classList.add("mm-menu--selected-hover")})),e.parent&&(this.bind("openPanel:after",(e=>{d(this.node.pnls,".mm-listitem--selected-parent").forEach((e=>{e.classList.remove("mm-listitem--selected-parent")}));let t=e;for(;t;){let e=d(this.node.pnls,`#${t.dataset.mmParent}`)[0];t=null==e?void 0:e.closest(".mm-panel"),e&&!e.matches(".mm-listitem--vertical")&&e.classList.add("mm-listitem--selected-parent")}})),this.bind("initMenu:after",(()=>{this.node.menu.classList.add("mm-menu--selected-parent")})))},sidebar:function(){if(!this.opts.offCanvas.use)return;this.opts.sidebar=this.opts.sidebar||{};const e=n(this.opts.sidebar,Q);if(e.collapsed.use){this.bind("initMenu:after",(()=>{this.node.menu.classList.add("mm-menu--sidebar-collapsed")}));let t=()=>{this.node.wrpr.classList.add("mm-wrapper--sidebar-collapsed")},n=()=>{this.node.wrpr.classList.remove("mm-wrapper--sidebar-collapsed")};"boolean"==typeof e.collapsed.use?this.bind("initMenu:after",t):g(e.collapsed.use,t,n)}if(e.expanded.use){this.bind("initMenu:after",(()=>{this.node.menu.classList.add("mm-menu--sidebar-expanded")}));let t=!1,n=()=>{t=!0,this.node.wrpr.classList.add("mm-wrapper--sidebar-expanded"),this.node.menu.removeAttribute("aria-modal"),this.open(),S.node.page.removeAttribute("inert")},s=()=>{t=!1,this.node.wrpr.classList.remove("mm-wrapper--sidebar-expanded"),this.node.menu.setAttribute("aria-modal","true"),this.close()};"boolean"==typeof e.expanded.use?this.bind("initMenu:after",n):g(e.expanded.use,n,s),this.bind("close:after",(()=>{t&&window.sessionStorage.setItem("mmenuExpandedState","closed")})),this.bind("open:after",(()=>{t&&(window.sessionStorage.setItem("mmenuExpandedState","open"),S.node.page.removeAttribute("inert"))}));let i=e.expanded.initial;const a=window.sessionStorage.getItem("mmenuExpandedState");switch(a){case"open":case"closed":i=a}"closed"===i&&this.bind("init:after",(()=>{this.close()}))}}},window&&(window.Mmenu=S)})();
5769
5770// MMENU
5771// -------------------------------------------------------------
5772jQuery(document).ready(function ($) {
5773  new Mmenu('#sidebar', {
5774    offCanvas: {
5775      position: 'left',
5776    },
5777    theme: 'light',
5778  });
5779});
5780// }
5781
5782// Sticky Header
5783// -------------------------------------------------------------
5784jQuery(document).ready(function ($) {
5785  if ($('body.page-id-2 .sticky-header').length >= 1) {
5786    $(window).scroll(function () {
5787      var header = $(document).scrollTop();
5788      var headerHeight = $('.site-header').height();
5789      if (header > headerHeight) {
5790        $('.site-header').height(headerHeight);
5791        $('.sticky-header').addClass('sticky');
5792        $('.sticky-header').fadeIn();
5793      } else {
5794        $('.site-header').css('height', 'auto');
5795        $('.sticky-header').removeClass('sticky');
5796      }
5797    });
5798  } else {
5799    $('.sticky-header').addClass('sticky');
5800  }
5801});
5802
5803// https://tympanus.net/codrops/2013/03/19/thumbnail-grid-with-expanding-preview/
5804jQuery(document).ready(function ($) {
5805  // Get Viewport Dimensions -- NEW
5806  // -------------------------------------------------------------
5807  function updateViewportDimensions() {
5808    var viewportwidth;
5809    var viewportheight;
5810    // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
5811    if (typeof window.innerWidth != 'undefined') {
5812      (viewportwidth = window.innerWidth), (viewportheight = window.innerHeight);
5813    }
5814    // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
5815    else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0) {
5816      (viewportwidth = document.documentElement.clientWidth), (viewportheight = document.documentElement.clientHeight);
5817    }
5818    // older versions of IE
5819    else {
5820      (viewportwidth = document.getElementsByTagName('body')[0].clientWidth), (viewportheight = document.getElementsByTagName('body')[0].clientHeight);
5821    }
5822    return {
5823      width: viewportwidth,
5824      height: viewportheight,
5825    };
5826  }
5827  var viewport = updateViewportDimensions();
5828
5829  // Throttle Resize-triggered Events
5830  // source: http://stackoverflow.com/questions/2854407/javascript-jquery-window-resize-how-to-fire-after-the-resize-is-completed
5831  // -------------------------------------------------------------
5832  var waitForFinalEvent = (function () {
5833    var timers = {};
5834    return function (callback, ms, uniqueId) {
5835      if (!uniqueId) {
5836        uniqueId = "Don't call this twice without a uniqueId";
5837      }
5838      if (timers[uniqueId]) {
5839        clearTimeout(timers[uniqueId]);
5840      }
5841      timers[uniqueId] = setTimeout(callback, ms);
5842    };
5843  })();
5844  var timeToWaitForLast = 100;
5845
5846  gallerfy();
5847  var curPicPos = 0;
5848
5849  $('.comogallery article > .gallery-header > a').click(function () {
5850    var galleryheaderHeight = $('.comogallery .gallery-header').height();
5851    var gallerycontentMarginTop = parseInt($('.comogallery .gallery-content').css('margin-top'));
5852    var gallerycontentHeight = -1;
5853
5854    $('.comogallery .gallery-content').each(function () {
5855      gallerycontentHeight = gallerycontentHeight > $(this).height() ? gallerycontentHeight : $(this).height();
5856    });
5857
5858    var resultitemHeight = galleryheaderHeight + gallerycontentHeight + gallerycontentMarginTop;
5859    $('.comogallery article').removeClass('open').css('height', 'auto');
5860    $(this).parent().parent().addClass('open').css('height', resultitemHeight);
5861    $('.comogallery article .gallery-content').css('height', gallerycontentHeight);
5862    curPicPos = $(this).parent().attr('data-pos');
5863    $(window).scrollTop(curPicPos);
5864    e.preventDefault();
5865  });
5866
5867  $(window).resize(function () {
5868    var galleryheaderHeight = $('.comogallery .gallery-header').height();
5869    var gallerycontentMarginTop = parseInt($('.comogallery .gallery-content').css('margin-top'));
5870    var gallerycontentHeight = -1;
5871
5872    $('.comogallery .gallery-content').each(function () {
5873      gallerycontentHeight = gallerycontentHeight > $(this).height() ? gallerycontentHeight : $(this).height();
5874    });
5875
5876    var resultitemHeight = galleryheaderHeight + gallerycontentHeight + gallerycontentMarginTop;
5877    viewport = updateViewportDimensions();
5878    $('.comogallery article.open').css('height', resultitemHeight);
5879    $('.comogallery article .gallery-content').css('height', gallerycontentHeight);
5880  });
5881
5882  $('.comogallery article')
5883    .find('.detailNext')
5884    .click(function () {
5885      var galleryheaderHeight = $('.comogallery .gallery-header').height();
5886      var gallerycontentMarginTop = parseInt($('.comogallery .gallery-content').css('margin-top'));
5887      var gallerycontentHeight = -1;
5888
5889      $('.comogallery .gallery-content').each(function () {
5890        gallerycontentHeight = gallerycontentHeight > $(this).height() ? gallerycontentHeight : $(this).height();
5891      });
5892
5893      var resultitemHeight = galleryheaderHeight + gallerycontentHeight + gallerycontentMarginTop;
5894      $(this).parent().parent().parent().parent().next().css('height', resultitemHeight).addClass('open').prev().removeClass('open').css('height', 'auto');
5895      curPicPos = $(this).parent().parent().parent().parent().next().find('.gallery-header').attr('data-pos');
5896      $(window).scrollTop(curPicPos);
5897      return false;
5898    });
5899
5900  $('.comogallery article')
5901    .find('.detailPrev')
5902    .click(function () {
5903      var galleryheaderHeight = $('.comogallery .gallery-header').height();
5904      var gallerycontentMarginTop = parseInt($('.comogallery .gallery-content').css('margin-top'));
5905      var gallerycontentHeight = -1;
5906
5907      $('.comogallery .gallery-content').each(function () {
5908        gallerycontentHeight = gallerycontentHeight > $(this).height() ? gallerycontentHeight : $(this).height();
5909      });
5910
5911      var resultitemHeight = galleryheaderHeight + gallerycontentHeight + gallerycontentMarginTop;
5912      $(this).parent().parent().parent().parent().prev().css('height', resultitemHeight).addClass('open').next().removeClass('open').css('height', 'auto');
5913      curPicPos = $(this).parent().parent().parent().parent().prev().find('.gallery-header').attr('data-pos');
5914      $(window).scrollTop(curPicPos);
5915      return false;
5916    });
5917
5918  $('.comogallery article')
5919    .find('.detailClose')
5920    .click(function () {
5921      $('.comogallery article').removeClass('open').css('height', 'auto');
5922      return false;
5923    });
5924
5925  function gallerfy() {
5926    $('.comogallery .gallery-header').each(function () {
5927      $(this).attr('data-pos', parseInt($(this).offset().top) - 65);
5928    });
5929  }
5930});
5931
5932// Homepage - get day
5933// -------------------------------------------------------------
5934jQuery(document).ready(function ($) {
5935  var today = moment().format('ddd');
5936
5937  if ($('body.page-id-2 .bp-contact-card').length >= 1) {
5938    $('.bp-opening-hours').addClass(today);
5939  }
5940});

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.