/*! Magnific Popup - v0.9.9 - 2013-12-27
 * http://dimsemenov.com/plugins/magnific-popup/
 * Copyright (c) 2013 Dmitry Semenov; */
;(function($) {

	/*>>core*/
	/**
	 *
	 * Magnific Popup Core JS file
	 *
	 */


	/**
	 * Private static constants
	 */
	var CLOSE_EVENT = 'Close',
		BEFORE_CLOSE_EVENT = 'BeforeClose',
		AFTER_CLOSE_EVENT = 'AfterClose',
		BEFORE_APPEND_EVENT = 'BeforeAppend',
		MARKUP_PARSE_EVENT = 'MarkupParse',
		OPEN_EVENT = 'Open',
		CHANGE_EVENT = 'Change',
		NS = 'mfp',
		EVENT_NS = '.' + NS,
		READY_CLASS = 'mfp-ready',
		REMOVING_CLASS = 'mfp-removing',
		PREVENT_CLOSE_CLASS = 'mfp-prevent-close';


	/**
	 * Private vars
	 */
	var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
		MagnificPopup = function(){},
		_isJQ = !!(window.jQuery),
		_prevStatus,
		_window = $(window),
		_body,
		_document,
		_prevContentType,
		_wrapClasses,
		_currPopupType;


	/**
	 * Private functions
	 */
	var _mfpOn = function(name, f) {
			mfp.ev.on(NS + name + EVENT_NS, f);
		},
		_getEl = function(className, appendTo, html, raw) {
			var el = document.createElement('div');
			el.className = 'mfp-'+className;
			if(html) {
				el.innerHTML = html;
			}
			if(!raw) {
				el = $(el);
				if(appendTo) {
					el.appendTo(appendTo);
				}
			} else if(appendTo) {
				appendTo.appendChild(el);
			}
			return el;
		},
		_mfpTrigger = function(e, data) {
			mfp.ev.triggerHandler(NS + e, data);

			if(mfp.st.callbacks) {
				// converts "mfpEventName" to "eventName" callback and triggers it if it's present
				e = e.charAt(0).toLowerCase() + e.slice(1);
				if(mfp.st.callbacks[e]) {
					mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
				}
			}
		},
		_getCloseBtn = function(type) {
			if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
				mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
				_currPopupType = type;
			}
			return mfp.currTemplate.closeBtn;
		},
	// Initialize Magnific Popup only when called at least once
		_checkInstance = function() {
			if(!$.magnificPopup.instance) {
				mfp = new MagnificPopup();
				mfp.init();
				$.magnificPopup.instance = mfp;
			}
		},
	// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
		supportsTransitions = function() {
			var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
				v = ['ms','O','Moz','Webkit']; // 'v' for vendor

			if( s['transition'] !== undefined ) {
				return true;
			}

			while( v.length ) {
				if( v.pop() + 'Transition' in s ) {
					return true;
				}
			}

			return false;
		};



	/**
	 * Public functions
	 */
	MagnificPopup.prototype = {

		constructor: MagnificPopup,

		/**
		 * Initializes Magnific Popup plugin.
		 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
		 */
		init: function() {
			var appVersion = navigator.appVersion;
			mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1;
			mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1;
			mfp.isLowIE = mfp.isIE7 || mfp.isIE8;
			mfp.isAndroid = (/android/gi).test(appVersion);
			mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
			mfp.supportsTransition = supportsTransitions();

			// We disable fixed positioned lightbox on devices that don't handle it nicely.
			// If you know a better way of detecting this - let me know.
			mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
			_document = $(document);

			mfp.popupsCache = {};
		},

		/**
		 * Opens popup
		 * @param  data [description]
		 */
		open: function(data) {

			if(!_body) {
				_body = $(document.body);
			}

			var i;

			if(data.isObj === false) {
				// convert jQuery collection to array to avoid conflicts later
				mfp.items = data.items.toArray();

				mfp.index = 0;
				var items = data.items,
					item;
				for(i = 0; i < items.length; i++) {
					item = items[i];
					if(item.parsed) {
						item = item.el[0];
					}
					if(item === data.el[0]) {
						mfp.index = i;
						break;
					}
				}
			} else {
				mfp.items = $.isArray(data.items) ? data.items : [data.items];
				mfp.index = data.index || 0;
			}

			// if popup is already opened - we just update the content
			if(mfp.isOpen) {
				mfp.updateItemHTML();
				return;
			}

			mfp.types = [];
			_wrapClasses = '';
			if(data.mainEl && data.mainEl.length) {
				mfp.ev = data.mainEl.eq(0);
			} else {
				mfp.ev = _document;
			}

			if(data.key) {
				if(!mfp.popupsCache[data.key]) {
					mfp.popupsCache[data.key] = {};
				}
				mfp.currTemplate = mfp.popupsCache[data.key];
			} else {
				mfp.currTemplate = {};
			}



			mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
			mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;

			if(mfp.st.modal) {
				mfp.st.closeOnContentClick = false;
				mfp.st.closeOnBgClick = false;
				mfp.st.showCloseBtn = false;
				mfp.st.enableEscapeKey = false;
			}


			// Building markup
			// main containers are created only once
			if(!mfp.bgOverlay) {

				// Dark overlay
				mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
					mfp.close();
				});

				mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
					if(mfp._checkIfClose(e.target)) {
						mfp.close();
					}
				});

				mfp.container = _getEl('container', mfp.wrap);
			}

			mfp.contentContainer = _getEl('content');
			if(mfp.st.preloader) {
				mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
			}


			// Initializing modules
			var modules = $.magnificPopup.modules;
			for(i = 0; i < modules.length; i++) {
				var n = modules[i];
				n = n.charAt(0).toUpperCase() + n.slice(1);
				mfp['init'+n].call(mfp);
			}
			_mfpTrigger('BeforeOpen');


			if(mfp.st.showCloseBtn) {
				// Close button
				if(!mfp.st.closeBtnInside) {
					mfp.wrap.append( _getCloseBtn() );
				} else {
					_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
						values.close_replaceWith = _getCloseBtn(item.type);
					});
					_wrapClasses += ' mfp-close-btn-in';
				}
			}

			if(mfp.st.alignTop) {
				_wrapClasses += ' mfp-align-top';
			}



			if(mfp.fixedContentPos) {
				mfp.wrap.css({
					overflow: mfp.st.overflowY,
					overflowX: 'hidden',
					overflowY: mfp.st.overflowY
				});
			} else {
				mfp.wrap.css({
					top: _window.scrollTop(),
					position: 'absolute'
				});
			}
			if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
				mfp.bgOverlay.css({
					height: _document.height(),
					position: 'absolute'
				});
			}



			if(mfp.st.enableEscapeKey) {
				// Close on ESC key
				_document.on('keyup' + EVENT_NS, function(e) {
					if(e.keyCode === 27) {
						mfp.close();
					}
				});
			}

			_window.on('resize' + EVENT_NS, function() {
				mfp.updateSize();
			});


			if(!mfp.st.closeOnContentClick) {
				_wrapClasses += ' mfp-auto-cursor';
			}

			if(_wrapClasses)
				mfp.wrap.addClass(_wrapClasses);


			// this triggers recalculation of layout, so we get it once to not to trigger twice
			var windowHeight = mfp.wH = _window.height();


			var windowStyles = {};

			if( mfp.fixedContentPos ) {
				if(mfp._hasScrollBar(windowHeight)){
					var s = mfp._getScrollbarSize();
					if(s) {
						windowStyles.marginRight = s;
					}
				}
			}

			if(mfp.fixedContentPos) {
				if(!mfp.isIE7) {
					windowStyles.overflow = 'hidden';
				} else {
					// ie7 double-scroll bug
					$('body, html').css('overflow', 'hidden');
				}
			}



			var classesToadd = mfp.st.mainClass;
			if(mfp.isIE7) {
				classesToadd += ' mfp-ie7';
			}
			if(classesToadd) {
				mfp._addClassToMFP( classesToadd );
			}

			// add content
			mfp.updateItemHTML();

			_mfpTrigger('BuildControls');

			// remove scrollbar, add margin e.t.c
			$('html').css(windowStyles);

			// add everything to DOM
			mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || _body );

			// Save last focused element
			mfp._lastFocusedEl = document.activeElement;

			// Wait for next cycle to allow CSS transition
			setTimeout(function() {

				if(mfp.content) {
					mfp._addClassToMFP(READY_CLASS);
					mfp._setFocus();
				} else {
					// if content is not defined (not loaded e.t.c) we add class only for BG
					mfp.bgOverlay.addClass(READY_CLASS);
				}

				// Trap the focus in popup
				_document.on('focusin' + EVENT_NS, mfp._onFocusIn);

			}, 16);

			mfp.isOpen = true;
			mfp.updateSize(windowHeight);
			_mfpTrigger(OPEN_EVENT);

			return data;
		},

		/**
		 * Closes the popup
		 */
		close: function() {
			if(!mfp.isOpen) return;
			_mfpTrigger(BEFORE_CLOSE_EVENT);

			mfp.isOpen = false;
			// for CSS3 animation
			if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
				mfp._addClassToMFP(REMOVING_CLASS);
				setTimeout(function() {
					mfp._close();
				}, mfp.st.removalDelay);
			} else {
				mfp._close();
			}
		},

		/**
		 * Helper for close() function
		 */
		_close: function() {
			_mfpTrigger(CLOSE_EVENT);

			var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';

			mfp.bgOverlay.detach();
			mfp.wrap.detach();
			mfp.container.empty();

			if(mfp.st.mainClass) {
				classesToRemove += mfp.st.mainClass + ' ';
			}

			mfp._removeClassFromMFP(classesToRemove);

			if(mfp.fixedContentPos) {
				var windowStyles = {marginRight: ''};
				if(mfp.isIE7) {
					$('body, html').css('overflow', '');
				} else {
					windowStyles.overflow = '';
				}
				$('html').css(windowStyles);
			}

			_document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
			mfp.ev.off(EVENT_NS);

			// clean up DOM elements that aren't removed
			mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
			mfp.bgOverlay.attr('class', 'mfp-bg');
			mfp.container.attr('class', 'mfp-container');

			// remove close button from target element
			if(mfp.st.showCloseBtn &&
				(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
				if(mfp.currTemplate.closeBtn)
					mfp.currTemplate.closeBtn.detach();
			}


			if(mfp._lastFocusedEl) {
				$(mfp._lastFocusedEl).focus(); // put tab focus back
			}
			mfp.currItem = null;
			mfp.content = null;
			mfp.currTemplate = null;
			mfp.prevHeight = 0;

			_mfpTrigger(AFTER_CLOSE_EVENT);
		},

		updateSize: function(winHeight) {

			if(mfp.isIOS) {
				// fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
				var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
				var height = window.innerHeight * zoomLevel;
				mfp.wrap.css('height', height);
				mfp.wH = height;
			} else {
				mfp.wH = winHeight || _window.height();
			}
			// Fixes #84: popup incorrectly positioned with position:relative on body
			if(!mfp.fixedContentPos) {
				mfp.wrap.css('height', mfp.wH);
			}

			_mfpTrigger('Resize');

		},

		/**
		 * Set content of popup based on current index
		 */
		updateItemHTML: function() {
			var item = mfp.items[mfp.index];

			// Detach and perform modifications
			mfp.contentContainer.detach();

			if(mfp.content)
				mfp.content.detach();

			if(!item.parsed) {
				item = mfp.parseEl( mfp.index );
			}

			var type = item.type;

			_mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
			// BeforeChange event works like so:
			// _mfpOn('BeforeChange', function(e, prevType, newType) { });

			mfp.currItem = item;





			if(!mfp.currTemplate[type]) {
				var markup = mfp.st[type] ? mfp.st[type].markup : false;

				// allows to modify markup
				_mfpTrigger('FirstMarkupParse', markup);

				if(markup) {
					mfp.currTemplate[type] = $(markup);
				} else {
					// if there is no markup found we just define that template is parsed
					mfp.currTemplate[type] = true;
				}
			}

			if(_prevContentType && _prevContentType !== item.type) {
				mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
			}

			var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
			mfp.appendContent(newContent, type);

			item.preloaded = true;

			_mfpTrigger(CHANGE_EVENT, item);
			_prevContentType = item.type;

			// Append container back after its content changed
			mfp.container.prepend(mfp.contentContainer);

			_mfpTrigger('AfterChange');
		},


		/**
		 * Set HTML content of popup
		 */
		appendContent: function(newContent, type) {
			mfp.content = newContent;

			if(newContent) {
				if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
					mfp.currTemplate[type] === true) {
					// if there is no markup, we just append close button element inside
					if(!mfp.content.find('.mfp-close').length) {
						mfp.content.append(_getCloseBtn());
					}
				} else {
					mfp.content = newContent;
				}
			} else {
				mfp.content = '';
			}

			_mfpTrigger(BEFORE_APPEND_EVENT);
			mfp.container.addClass('mfp-'+type+'-holder');

			mfp.contentContainer.append(mfp.content);
		},




		/**
		 * Creates Magnific Popup data object based on given data
		 * @param  {int} index Index of item to parse
		 */
		parseEl: function(index) {
			var item = mfp.items[index],
				type;

			if(item.tagName) {
				item = { el: $(item) };
			} else {
				type = item.type;
				item = { data: item, src: item.src };
			}

			if(item.el) {
				var types = mfp.types;

				// check for 'mfp-TYPE' class
				for(var i = 0; i < types.length; i++) {
					if( item.el.hasClass('mfp-'+types[i]) ) {
						type = types[i];
						break;
					}
				}

				item.src = item.el.attr('data-mfp-src');
				if(!item.src) {
					item.src = item.el.attr('href');
				}
			}

			item.type = type || mfp.st.type || 'inline';
			item.index = index;
			item.parsed = true;
			mfp.items[index] = item;
			_mfpTrigger('ElementParse', item);

			return mfp.items[index];
		},


		/**
		 * Initializes single popup or a group of popups
		 */
		addGroup: function(el, options) {
			var eHandler = function(e) {
				e.mfpEl = this;
				mfp._openClick(e, el, options);
			};

			if(!options) {
				options = {};
			}

			var eName = 'click.magnificPopup';
			options.mainEl = el;

			if(options.items) {
				options.isObj = true;
				el.off(eName).on(eName, eHandler);
			} else {
				options.isObj = false;
				if(options.delegate) {
					el.off(eName).on(eName, options.delegate , eHandler);
				} else {
					options.items = el;
					el.off(eName).on(eName, eHandler);
				}
			}
		},
		_openClick: function(e, el, options) {
			var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;


			if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) {
				return;
			}

			var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;

			if(disableOn) {
				if($.isFunction(disableOn)) {
					if( !disableOn.call(mfp) ) {
						return true;
					}
				} else { // else it's number
					if( _window.width() < disableOn ) {
						return true;
					}
				}
			}

			if(e.type) {
				e.preventDefault();

				// This will prevent popup from closing if element is inside and popup is already opened
				if(mfp.isOpen) {
					e.stopPropagation();
				}
			}


			options.el = $(e.mfpEl);
			if(options.delegate) {
				options.items = el.find(options.delegate);
			}
			mfp.open(options);
		},


		/**
		 * Updates text on preloader
		 */
		updateStatus: function(status, text) {

			if(mfp.preloader) {
				if(_prevStatus !== status) {
					mfp.container.removeClass('mfp-s-'+_prevStatus);
				}

				if(!text && status === 'loading') {
					text = mfp.st.tLoading;
				}

				var data = {
					status: status,
					text: text
				};
				// allows to modify status
				_mfpTrigger('UpdateStatus', data);

				status = data.status;
				text = data.text;

				mfp.preloader.html(text);

				mfp.preloader.find('a').on('click', function(e) {
					e.stopImmediatePropagation();
				});

				mfp.container.addClass('mfp-s-'+status);
				_prevStatus = status;
			}
		},


		/*
		 "Private" helpers that aren't private at all
		 */
		// Check to close popup or not
		// "target" is an element that was clicked
		_checkIfClose: function(target) {

			if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
				return;
			}

			var closeOnContent = mfp.st.closeOnContentClick;
			var closeOnBg = mfp.st.closeOnBgClick;

			if(closeOnContent && closeOnBg) {
				return true;
			} else {

				// We close the popup if click is on close button or on preloader. Or if there is no content.
				if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
					return true;
				}

				// if click is outside the content
				if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
					if(closeOnBg) {
						// last check, if the clicked element is in DOM, (in case it's removed onclick)
						if( $.contains(document, target) ) {
							return true;
						}
					}
				} else if(closeOnContent) {
					return true;
				}

			}
			return false;
		},
		_addClassToMFP: function(cName) {
			mfp.bgOverlay.addClass(cName);
			mfp.wrap.addClass(cName);
		},
		_removeClassFromMFP: function(cName) {
			this.bgOverlay.removeClass(cName);
			mfp.wrap.removeClass(cName);
		},
		_hasScrollBar: function(winHeight) {
			return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
		},
		_setFocus: function() {
			(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
		},
		_onFocusIn: function(e) {
			if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
				mfp._setFocus();
				return false;
			}
		},
		_parseMarkup: function(template, values, item) {
			var arr;
			if(item.data) {
				values = $.extend(item.data, values);
			}
			_mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );

			$.each(values, function(key, value) {
				if(value === undefined || value === false) {
					return true;
				}
				arr = key.split('_');
				if(arr.length > 1) {
					var el = template.find(EVENT_NS + '-'+arr[0]);

					if(el.length > 0) {
						var attr = arr[1];
						if(attr === 'replaceWith') {
							if(el[0] !== value[0]) {
								el.replaceWith(value);
							}
						} else if(attr === 'img') {
							if(el.is('img')) {
								el.attr('src', value);
							} else {
								el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' );
							}
						} else {
							el.attr(arr[1], value);
						}
					}

				} else {
					template.find(EVENT_NS + '-'+key).html(value);
				}
			});
		},

		_getScrollbarSize: function() {
			// thx David
			if(mfp.scrollbarSize === undefined) {
				var scrollDiv = document.createElement("div");
				scrollDiv.id = "mfp-sbm";
				scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
				document.body.appendChild(scrollDiv);
				mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
				document.body.removeChild(scrollDiv);
			}
			return mfp.scrollbarSize;
		}

	}; /* MagnificPopup core prototype end */




	/**
	 * Public static functions
	 */
	$.magnificPopup = {
		instance: null,
		proto: MagnificPopup.prototype,
		modules: [],

		open: function(options, index) {
			_checkInstance();

			if(!options) {
				options = {};
			} else {
				options = $.extend(true, {}, options);
			}


			options.isObj = true;
			options.index = index || 0;
			return this.instance.open(options);
		},

		close: function() {
			return $.magnificPopup.instance && $.magnificPopup.instance.close();
		},

		registerModule: function(name, module) {
			if(module.options) {
				$.magnificPopup.defaults[name] = module.options;
			}
			$.extend(this.proto, module.proto);
			this.modules.push(name);
		},

		defaults: {

			// Info about options is in docs:
			// http://dimsemenov.com/plugins/magnific-popup/documentation.html#options

			disableOn: 0,

			key: null,

			midClick: false,

			mainClass: '',

			preloader: true,

			focus: '', // CSS selector of input to focus after popup is opened

			closeOnContentClick: false,

			closeOnBgClick: true,

			closeBtnInside: true,

			showCloseBtn: true,

			enableEscapeKey: true,

			modal: false,

			alignTop: false,

			removalDelay: 0,

			prependTo: null,

			fixedContentPos: 'auto',

			fixedBgPos: 'auto',

			overflowY: 'auto',

			closeMarkup: '<button title="%title%" type="button" class="mfp-close">&times;</button>',

			tClose: 'Close (Esc)',

			tLoading: 'Loading...'

		}
	};



	$.fn.magnificPopup = function(options) {
		_checkInstance();

		var jqEl = $(this);

		// We call some API method of first param is a string
		if (typeof options === "string" ) {

			if(options === 'open') {
				var items,
					itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
					index = parseInt(arguments[1], 10) || 0;

				if(itemOpts.items) {
					items = itemOpts.items[index];
				} else {
					items = jqEl;
					if(itemOpts.delegate) {
						items = items.find(itemOpts.delegate);
					}
					items = items.eq( index );
				}
				mfp._openClick({mfpEl:items}, jqEl, itemOpts);
			} else {
				if(mfp.isOpen)
					mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
			}

		} else {
			// clone options obj
			options = $.extend(true, {}, options);

			/*
			 * As Zepto doesn't support .data() method for objects
			 * and it works only in normal browsers
			 * we assign "options" object directly to the DOM element. FTW!
			 */
			if(_isJQ) {
				jqEl.data('magnificPopup', options);
			} else {
				jqEl[0].magnificPopup = options;
			}

			mfp.addGroup(jqEl, options);

		}
		return jqEl;
	};


//Quick benchmark
	/*
	 var start = performance.now(),
	 i,
	 rounds = 1000;

	 for(i = 0; i < rounds; i++) {

	 }
	 console.log('Test #1:', performance.now() - start);

	 start = performance.now();
	 for(i = 0; i < rounds; i++) {

	 }
	 console.log('Test #2:', performance.now() - start);
	 */


	/*>>core*/

	/*>>inline*/

	var INLINE_NS = 'inline',
		_hiddenClass,
		_inlinePlaceholder,
		_lastInlineElement,
		_putInlineElementsBack = function() {
			if(_lastInlineElement) {
				_inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
				_lastInlineElement = null;
			}
		};

	$.magnificPopup.registerModule(INLINE_NS, {
		options: {
			hiddenClass: 'hide', // will be appended with `mfp-` prefix
			markup: '',
			tNotFound: 'Content not found'
		},
		proto: {

			initInline: function() {
				mfp.types.push(INLINE_NS);

				_mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
					_putInlineElementsBack();
				});
			},

			getInline: function(item, template) {

				_putInlineElementsBack();

				if(item.src) {
					var inlineSt = mfp.st.inline,
						el = $(item.src);

					if(el.length) {

						// If target element has parent - we replace it with placeholder and put it back after popup is closed
						var parent = el[0].parentNode;
						if(parent && parent.tagName) {
							if(!_inlinePlaceholder) {
								_hiddenClass = inlineSt.hiddenClass;
								_inlinePlaceholder = _getEl(_hiddenClass);
								_hiddenClass = 'mfp-'+_hiddenClass;
							}
							// replace target inline element with placeholder
							_lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
						}

						mfp.updateStatus('ready');
					} else {
						mfp.updateStatus('error', inlineSt.tNotFound);
						el = $('<div>');
					}

					item.inlineElement = el;
					return el;
				}

				mfp.updateStatus('ready');
				mfp._parseMarkup(template, {}, item);
				return template;
			}
		}
	});

	/*>>inline*/

	/*>>ajax*/
	var AJAX_NS = 'ajax',
		_ajaxCur,
		_removeAjaxCursor = function() {
			if(_ajaxCur) {
				_body.removeClass(_ajaxCur);
			}
		},
		_destroyAjaxRequest = function() {
			_removeAjaxCursor();
			if(mfp.req) {
				mfp.req.abort();
			}
		};

	$.magnificPopup.registerModule(AJAX_NS, {

		options: {
			settings: null,
			cursor: 'mfp-ajax-cur',
			tError: '<a href="%url%">The content</a> could not be loaded.'
		},

		proto: {
			initAjax: function() {
				mfp.types.push(AJAX_NS);
				_ajaxCur = mfp.st.ajax.cursor;

				_mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
				_mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
			},
			getAjax: function(item) {

				if(_ajaxCur)
					_body.addClass(_ajaxCur);

				mfp.updateStatus('loading');

				var opts = $.extend({
					url: item.src,
					success: function(data, textStatus, jqXHR) {
						var temp = {
							data:data,
							xhr:jqXHR
						};

						_mfpTrigger('ParseAjax', temp);

						mfp.appendContent( $(temp.data), AJAX_NS );

						item.finished = true;

						_removeAjaxCursor();

						mfp._setFocus();

						setTimeout(function() {
							mfp.wrap.addClass(READY_CLASS);
						}, 16);

						mfp.updateStatus('ready');

						_mfpTrigger('AjaxContentAdded');
					},
					error: function() {
						_removeAjaxCursor();
						item.finished = item.loadError = true;
						mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
					}
				}, mfp.st.ajax.settings);

				mfp.req = $.ajax(opts);

				return '';
			}
		}
	});







	/*>>ajax*/

	/*>>image*/
	var _imgInterval,
		_getTitle = function(item) {
			if(item.data && item.data.title !== undefined)
				return item.data.title;

			var src = mfp.st.image.titleSrc;

			if(src) {
				if($.isFunction(src)) {
					return src.call(mfp, item);
				} else if(item.el) {
					return item.el.attr(src) || '';
				}
			}
			return '';
		};

	$.magnificPopup.registerModule('image', {

		options: {
			markup: '<div class="mfp-figure">'+
				'<div class="mfp-close"></div>'+
				'<figure>'+
				'<div class="mfp-img"></div>'+
				'<figcaption>'+
				'<div class="mfp-bottom-bar">'+
				'<div class="mfp-title"></div>'+
				'<div class="mfp-counter"></div>'+
				'</div>'+
				'</figcaption>'+
				'</figure>'+
				'</div>',
			cursor: 'mfp-zoom-out-cur',
			titleSrc: 'title',
			verticalFit: true,
			tError: '<a href="%url%">The image</a> could not be loaded.'
		},

		proto: {
			initImage: function() {
				var imgSt = mfp.st.image,
					ns = '.image';

				mfp.types.push('image');

				_mfpOn(OPEN_EVENT+ns, function() {
					if(mfp.currItem.type === 'image' && imgSt.cursor) {
						_body.addClass(imgSt.cursor);
					}
				});

				_mfpOn(CLOSE_EVENT+ns, function() {
					if(imgSt.cursor) {
						_body.removeClass(imgSt.cursor);
					}
					_window.off('resize' + EVENT_NS);
				});

				_mfpOn('Resize'+ns, mfp.resizeImage);
				if(mfp.isLowIE) {
					_mfpOn('AfterChange', mfp.resizeImage);
				}
			},
			resizeImage: function() {
				var item = mfp.currItem;
				if(!item || !item.img) return;

				if(mfp.st.image.verticalFit) {
					var decr = 0;
					// fix box-sizing in ie7/8
					if(mfp.isLowIE) {
						decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
					}
					item.img.css('max-height', mfp.wH-decr);
				}
			},
			_onImageHasSize: function(item) {
				if(item.img) {

					item.hasSize = true;

					if(_imgInterval) {
						clearInterval(_imgInterval);
					}

					item.isCheckingImgSize = false;

					_mfpTrigger('ImageHasSize', item);

					if(item.imgHidden) {
						if(mfp.content)
							mfp.content.removeClass('mfp-loading');

						item.imgHidden = false;
					}

				}
			},

			/**
			 * Function that loops until the image has size to display elements that rely on it asap
			 */
			findImageSize: function(item) {

				var counter = 0,
					img = item.img[0],
					mfpSetInterval = function(delay) {

						if(_imgInterval) {
							clearInterval(_imgInterval);
						}
						// decelerating interval that checks for size of an image
						_imgInterval = setInterval(function() {
							if(img.naturalWidth > 0) {
								mfp._onImageHasSize(item);
								return;
							}

							if(counter > 200) {
								clearInterval(_imgInterval);
							}

							counter++;
							if(counter === 3) {
								mfpSetInterval(10);
							} else if(counter === 40) {
								mfpSetInterval(50);
							} else if(counter === 100) {
								mfpSetInterval(500);
							}
						}, delay);
					};

				mfpSetInterval(1);
			},

			getImage: function(item, template) {

				var guard = 0,

				// image load complete handler
					onLoadComplete = function() {
						if(item) {
							if (item.img[0].complete) {
								item.img.off('.mfploader');

								if(item === mfp.currItem){
									mfp._onImageHasSize(item);

									mfp.updateStatus('ready');
								}

								item.hasSize = true;
								item.loaded = true;

								_mfpTrigger('ImageLoadComplete');

							}
							else {
								// if image complete check fails 200 times (20 sec), we assume that there was an error.
								guard++;
								if(guard < 200) {
									setTimeout(onLoadComplete,100);
								} else {
									onLoadError();
								}
							}
						}
					},

				// image error handler
					onLoadError = function() {
						if(item) {
							item.img.off('.mfploader');
							if(item === mfp.currItem){
								mfp._onImageHasSize(item);
								mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
							}

							item.hasSize = true;
							item.loaded = true;
							item.loadError = true;
						}
					},
					imgSt = mfp.st.image;


				var el = template.find('.mfp-img');
				if(el.length) {
					var img = document.createElement('img');
					img.className = 'mfp-img';
					item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
					img.src = item.src;

					// without clone() "error" event is not firing when IMG is replaced by new IMG
					// TODO: find a way to avoid such cloning
					if(el.is('img')) {
						item.img = item.img.clone();
					}

					img = item.img[0];
					if(img.naturalWidth > 0) {
						item.hasSize = true;
					} else if(!img.width) {
						item.hasSize = false;
					}
				}

				mfp._parseMarkup(template, {
					title: _getTitle(item),
					img_replaceWith: item.img
				}, item);

				mfp.resizeImage();

				if(item.hasSize) {
					if(_imgInterval) clearInterval(_imgInterval);

					if(item.loadError) {
						template.addClass('mfp-loading');
						mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
					} else {
						template.removeClass('mfp-loading');
						mfp.updateStatus('ready');
					}
					return template;
				}

				mfp.updateStatus('loading');
				item.loading = true;

				if(!item.hasSize) {
					item.imgHidden = true;
					template.addClass('mfp-loading');
					mfp.findImageSize(item);
				}

				return template;
			}
		}
	});



	/*>>image*/

	/*>>zoom*/
	var hasMozTransform,
		getHasMozTransform = function() {
			if(hasMozTransform === undefined) {
				hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
			}
			return hasMozTransform;
		};

	$.magnificPopup.registerModule('zoom', {

		options: {
			enabled: false,
			easing: 'ease-in-out',
			duration: 300,
			opener: function(element) {
				return element.is('img') ? element : element.find('img');
			}
		},

		proto: {

			initZoom: function() {
				var zoomSt = mfp.st.zoom,
					ns = '.zoom',
					image;

				if(!zoomSt.enabled || !mfp.supportsTransition) {
					return;
				}

				var duration = zoomSt.duration,
					getElToAnimate = function(image) {
						var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
							transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
							cssObj = {
								position: 'fixed',
								zIndex: 9999,
								left: 0,
								top: 0,
								'-webkit-backface-visibility': 'hidden'
							},
							t = 'transition';

						cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;

						newImg.css(cssObj);
						return newImg;
					},
					showMainContent = function() {
						mfp.content.css('visibility', 'visible');
					},
					openTimeout,
					animatedImg;

				_mfpOn('BuildControls'+ns, function() {
					if(mfp._allowZoom()) {

						clearTimeout(openTimeout);
						mfp.content.css('visibility', 'hidden');

						// Basically, all code below does is clones existing image, puts in on top of the current one and animated it

						image = mfp._getItemToZoom();

						if(!image) {
							showMainContent();
							return;
						}

						animatedImg = getElToAnimate(image);

						animatedImg.css( mfp._getOffset() );

						mfp.wrap.append(animatedImg);

						openTimeout = setTimeout(function() {
							animatedImg.css( mfp._getOffset( true ) );
							openTimeout = setTimeout(function() {

								showMainContent();

								setTimeout(function() {
									animatedImg.remove();
									image = animatedImg = null;
									_mfpTrigger('ZoomAnimationEnded');
								}, 16); // avoid blink when switching images

							}, duration); // this timeout equals animation duration

						}, 16); // by adding this timeout we avoid short glitch at the beginning of animation


						// Lots of timeouts...
					}
				});
				_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
					if(mfp._allowZoom()) {

						clearTimeout(openTimeout);

						mfp.st.removalDelay = duration;

						if(!image) {
							image = mfp._getItemToZoom();
							if(!image) {
								return;
							}
							animatedImg = getElToAnimate(image);
						}


						animatedImg.css( mfp._getOffset(true) );
						mfp.wrap.append(animatedImg);
						mfp.content.css('visibility', 'hidden');

						setTimeout(function() {
							animatedImg.css( mfp._getOffset() );
						}, 16);
					}

				});

				_mfpOn(CLOSE_EVENT+ns, function() {
					if(mfp._allowZoom()) {
						showMainContent();
						if(animatedImg) {
							animatedImg.remove();
						}
						image = null;
					}
				});
			},

			_allowZoom: function() {
				return mfp.currItem.type === 'image';
			},

			_getItemToZoom: function() {
				if(mfp.currItem.hasSize) {
					return mfp.currItem.img;
				} else {
					return false;
				}
			},

			// Get element postion relative to viewport
			_getOffset: function(isLarge) {
				var el;
				if(isLarge) {
					el = mfp.currItem.img;
				} else {
					el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
				}

				var offset = el.offset();
				var paddingTop = parseInt(el.css('padding-top'),10);
				var paddingBottom = parseInt(el.css('padding-bottom'),10);
				offset.top -= ( $(window).scrollTop() - paddingTop );


				/*

				 Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.

				 */
				var obj = {
					width: el.width(),
					// fix Zepto height+padding issue
					height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
				};

				// I hate to do this, but there is no another option
				if( getHasMozTransform() ) {
					obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
				} else {
					obj.left = offset.left;
					obj.top = offset.top;
				}
				return obj;
			}

		}
	});



	/*>>zoom*/

	/*>>iframe*/

	var IFRAME_NS = 'iframe',
		_emptyPage = '//about:blank',

		_fixIframeBugs = function(isShowing) {
			if(mfp.currTemplate[IFRAME_NS]) {
				var el = mfp.currTemplate[IFRAME_NS].find('iframe');
				if(el.length) {
					// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
					if(!isShowing) {
						el[0].src = _emptyPage;
					}

					// IE8 black screen bug fix
					if(mfp.isIE8) {
						el.css('display', isShowing ? 'block' : 'none');
					}
				}
			}
		};

	$.magnificPopup.registerModule(IFRAME_NS, {

		options: {
			markup: '<div class="mfp-iframe-scaler">'+
				'<div class="mfp-close"></div>'+
				'<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
				'</div>',

			srcAction: 'iframe_src',

			// we don't care and support only one default type of URL by default
			patterns: {
				youtube: {
					index: 'youtube.com',
					id: 'v=',
					src: '//www.youtube.com/embed/%id%?autoplay=1'
				},
				vimeo: {
					index: 'vimeo.com/',
					id: '/',
					src: '//player.vimeo.com/video/%id%?autoplay=1'
				},
				gmaps: {
					index: '//maps.google.',
					src: '%id%&output=embed'
				}
			}
		},

		proto: {
			initIframe: function() {
				mfp.types.push(IFRAME_NS);

				_mfpOn('BeforeChange', function(e, prevType, newType) {
					if(prevType !== newType) {
						if(prevType === IFRAME_NS) {
							_fixIframeBugs(); // iframe if removed
						} else if(newType === IFRAME_NS) {
							_fixIframeBugs(true); // iframe is showing
						}
					}// else {
					// iframe source is switched, don't do anything
					//}
				});

				_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
					_fixIframeBugs();
				});
			},

			getIframe: function(item, template) {
				var embedSrc = item.src;
				var iframeSt = mfp.st.iframe;

				$.each(iframeSt.patterns, function() {
					if(embedSrc.indexOf( this.index ) > -1) {
						if(this.id) {
							if(typeof this.id === 'string') {
								embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
							} else {
								embedSrc = this.id.call( this, embedSrc );
							}
						}
						embedSrc = this.src.replace('%id%', embedSrc );
						return false; // break;
					}
				});

				var dataObj = {};
				if(iframeSt.srcAction) {
					dataObj[iframeSt.srcAction] = embedSrc;
				}
				mfp._parseMarkup(template, dataObj, item);

				mfp.updateStatus('ready');

				return template;
			}
		}
	});



	/*>>iframe*/

	/*>>gallery*/
	/**
	 * Get looped index depending on number of slides
	 */
	var _getLoopedId = function(index) {
			var numSlides = mfp.items.length;
			if(index > numSlides - 1) {
				return index - numSlides;
			} else  if(index < 0) {
				return numSlides + index;
			}
			return index;
		},
		_replaceCurrTotal = function(text, curr, total) {
			return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
		};

	$.magnificPopup.registerModule('gallery', {

		options: {
			enabled: false,
			arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
			preload: [0,2],
			navigateByImgClick: true,
			arrows: true,

			tPrev: 'Previous (Left arrow key)',
			tNext: 'Next (Right arrow key)',
			tCounter: '%curr% of %total%'
		},

		proto: {
			initGallery: function() {

				var gSt = mfp.st.gallery,
					ns = '.mfp-gallery',
					supportsFastClick = Boolean($.fn.mfpFastClick);

				mfp.direction = true; // true - next, false - prev

				if(!gSt || !gSt.enabled ) return false;

				_wrapClasses += ' mfp-gallery';

				_mfpOn(OPEN_EVENT+ns, function() {

					if(gSt.navigateByImgClick) {
						mfp.wrap.on('click'+ns, '.mfp-img', function() {
							if(mfp.items.length > 1) {
								mfp.next();
								return false;
							}
						});
					}

					_document.on('keydown'+ns, function(e) {
						if (e.keyCode === 37) {
							mfp.prev();
						} else if (e.keyCode === 39) {
							mfp.next();
						}
					});
				});

				_mfpOn('UpdateStatus'+ns, function(e, data) {
					if(data.text) {
						data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
					}
				});

				_mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
					var l = mfp.items.length;
					values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
				});

				_mfpOn('BuildControls' + ns, function() {
					if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
						var markup = gSt.arrowMarkup,
							arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
							arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);

						var eName = supportsFastClick ? 'mfpFastClick' : 'click';
						arrowLeft[eName](function() {
							mfp.prev();
						});
						arrowRight[eName](function() {
							mfp.next();
						});

						// Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b)
						if(mfp.isIE7) {
							_getEl('b', arrowLeft[0], false, true);
							_getEl('a', arrowLeft[0], false, true);
							_getEl('b', arrowRight[0], false, true);
							_getEl('a', arrowRight[0], false, true);
						}

						mfp.container.append(arrowLeft.add(arrowRight));
					}
				});

				_mfpOn(CHANGE_EVENT+ns, function() {
					if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);

					mfp._preloadTimeout = setTimeout(function() {
						mfp.preloadNearbyImages();
						mfp._preloadTimeout = null;
					}, 16);
				});


				_mfpOn(CLOSE_EVENT+ns, function() {
					_document.off(ns);
					mfp.wrap.off('click'+ns);

					if(mfp.arrowLeft && supportsFastClick) {
						mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick();
					}
					mfp.arrowRight = mfp.arrowLeft = null;
				});

			},
			next: function() {
				mfp.direction = true;
				mfp.index = _getLoopedId(mfp.index + 1);
				mfp.updateItemHTML();
			},
			prev: function() {
				mfp.direction = false;
				mfp.index = _getLoopedId(mfp.index - 1);
				mfp.updateItemHTML();
			},
			goTo: function(newIndex) {
				mfp.direction = (newIndex >= mfp.index);
				mfp.index = newIndex;
				mfp.updateItemHTML();
			},
			preloadNearbyImages: function() {
				var p = mfp.st.gallery.preload,
					preloadBefore = Math.min(p[0], mfp.items.length),
					preloadAfter = Math.min(p[1], mfp.items.length),
					i;

				for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
					mfp._preloadItem(mfp.index+i);
				}
				for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
					mfp._preloadItem(mfp.index-i);
				}
			},
			_preloadItem: function(index) {
				index = _getLoopedId(index);

				if(mfp.items[index].preloaded) {
					return;
				}

				var item = mfp.items[index];
				if(!item.parsed) {
					item = mfp.parseEl( index );
				}

				_mfpTrigger('LazyLoad', item);

				if(item.type === 'image') {
					item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
						item.hasSize = true;
					}).on('error.mfploader', function() {
						item.hasSize = true;
						item.loadError = true;
						_mfpTrigger('LazyLoadError', item);
					}).attr('src', item.src);
				}


				item.preloaded = true;
			}
		}
	});

	/*
	 Touch Support that might be implemented some day

	 addSwipeGesture: function() {
	 var startX,
	 moved,
	 multipleTouches;

	 return;

	 var namespace = '.mfp',
	 addEventNames = function(pref, down, move, up, cancel) {
	 mfp._tStart = pref + down + namespace;
	 mfp._tMove = pref + move + namespace;
	 mfp._tEnd = pref + up + namespace;
	 mfp._tCancel = pref + cancel + namespace;
	 };

	 if(window.navigator.msPointerEnabled) {
	 addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
	 } else if('ontouchstart' in window) {
	 addEventNames('touch', 'start', 'move', 'end', 'cancel');
	 } else {
	 return;
	 }
	 _window.on(mfp._tStart, function(e) {
	 var oE = e.originalEvent;
	 multipleTouches = moved = false;
	 startX = oE.pageX || oE.changedTouches[0].pageX;
	 }).on(mfp._tMove, function(e) {
	 if(e.originalEvent.touches.length > 1) {
	 multipleTouches = e.originalEvent.touches.length;
	 } else {
	 //e.preventDefault();
	 moved = true;
	 }
	 }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) {
	 if(moved && !multipleTouches) {
	 var oE = e.originalEvent,
	 diff = startX - (oE.pageX || oE.changedTouches[0].pageX);

	 if(diff > 20) {
	 mfp.next();
	 } else if(diff < -20) {
	 mfp.prev();
	 }
	 }
	 });
	 },
	 */


	/*>>gallery*/

	/*>>retina*/

	var RETINA_NS = 'retina';

	$.magnificPopup.registerModule(RETINA_NS, {
		options: {
			replaceSrc: function(item) {
				return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
			},
			ratio: 1 // Function or number.  Set to 1 to disable.
		},
		proto: {
			initRetina: function() {
				if(window.devicePixelRatio > 1) {

					var st = mfp.st.retina,
						ratio = st.ratio;

					ratio = !isNaN(ratio) ? ratio : ratio();

					if(ratio > 1) {
						_mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
							item.img.css({
								'max-width': item.img[0].naturalWidth / ratio,
								'width': '100%'
							});
						});
						_mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
							item.src = st.replaceSrc(item, ratio);
						});
					}
				}

			}
		}
	});

	/*>>retina*/

	/*>>fastclick*/
	/**
	 * FastClick event implementation. (removes 300ms delay on touch devices)
	 * Based on https://developers.google.com/mobile/articles/fast_buttons
	 *
	 * You may use it outside the Magnific Popup by calling just:
	 *
	 * $('.your-el').mfpFastClick(function() {
 *     console.log('Clicked!');
 * });
	 *
	 * To unbind:
	 * $('.your-el').destroyMfpFastClick();
	 *
	 *
	 * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound.
	 * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick
	 *
	 */

	(function() {
		var ghostClickDelay = 1000,
			supportsTouch = 'ontouchstart' in window,
			unbindTouchMove = function() {
				_window.off('touchmove'+ns+' touchend'+ns);
			},
			eName = 'mfpFastClick',
			ns = '.'+eName;


		// As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way
		$.fn.mfpFastClick = function(callback) {

			return $(this).each(function() {

				var elem = $(this),
					lock;

				if( supportsTouch ) {

					var timeout,
						startX,
						startY,
						pointerMoved,
						point,
						numPointers;

					elem.on('touchstart' + ns, function(e) {
						pointerMoved = false;
						numPointers = 1;

						point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0];
						startX = point.clientX;
						startY = point.clientY;

						_window.on('touchmove'+ns, function(e) {
							point = e.originalEvent ? e.originalEvent.touches : e.touches;
							numPointers = point.length;
							point = point[0];
							if (Math.abs(point.clientX - startX) > 10 ||
								Math.abs(point.clientY - startY) > 10) {
								pointerMoved = true;
								unbindTouchMove();
							}
						}).on('touchend'+ns, function(e) {
							unbindTouchMove();
							if(pointerMoved || numPointers > 1) {
								return;
							}
							lock = true;
							e.preventDefault();
							clearTimeout(timeout);
							timeout = setTimeout(function() {
								lock = false;
							}, ghostClickDelay);
							callback();
						});
					});

				}

				elem.on('click' + ns, function() {
					if(!lock) {
						callback();
					}
				});
			});
		};

		$.fn.destroyMfpFastClick = function() {
			$(this).off('touchstart' + ns + ' click' + ns);
			if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns);
		};
	})();

	/*>>fastclick*/
	_checkInstance(); })(window.jQuery || window.Zepto);
/*jslint browser: true, indent: 4, regexp: true, white:true */
/**
 * Cookie class
 * Handles all operations on cookies
 *
 * @author Johan Arensman
 */
(function (global) {
	'use strict';

	/**
	 * Creates a new cookie instance with the given name.
	 * @param {string} name
	 * @param {Object|string} [newValue] (new) value for this cookie or object literal with options.
	 * @constructor
	 */
	function Cookie(name, newValue) {
		if (name !== undefined) {
			this.name = name;

			if (newValue !== undefined) {
				if (typeof newValue === 'object') {
					this.set(newValue);
				} else {
					this.setValue(newValue);
				}
			} else {
				this.read();
			}
		}
	}

	/**
	 * Return the names of all cookies
	 * return {array} An array with all cookie names.
	 */
	function names() {
		return document.cookie.replace(/((?:^|\s*;)[^=]+)(?=;|$)|^\s*|\s*(?:=[^;]*)?(?:\1|$)/g, "")
			.split(/\s*(?:=[^;]*)?;\s*/);
	}

	/**
	 * Returns an object literal with cookie names and Cookie instances for all cookies.
	 * @returns {Object}
	 */
	function all() {
		var keys = names(),
			i = 0, l, cookies = {};
		for (l = keys.length; i < l; i++) {
			cookies[keys[i]] = new Cookie(keys[i]);
		}
		return cookies;
	}

	Cookie.names = names;
	Cookie.all = all;

	Cookie.prototype = {
		'name': undefined,
		'value': undefined,
		'domain': undefined,
		'path': undefined,
		'expires': undefined,
		'max-age': undefined,
		'secure': undefined,

		'names': names,
		'all': all,

		/**
		 * Sets the value of this cookie
		 * @param {*} value
		 * @returns {Cookie}
		 */
		setValue: function (value) {
			this.value = window.encodeURIComponent(value);
			return this;
		},

		/**
		 * Set the expiration date by days
		 * @param {Number} days
		 * @returns {Cookie}
		 */
		setDays: function (days) {
			var date;
			if (days) {
				date = new Date();
				date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
				this.expires = date;
			}
			return this;
		},

		/**
		 * Set any valid cookie property either using an object with key/value pairs or a property with a value.
		 * @param {string|Object} option The name of the option or the object containing key/value pairs.
		 * @param {*} [value] The value of the option
		 * @returns {Cookie}
		 */
		set: function (option, value) {
			var setter = typeof option === 'string' ? 'set' + (option.charAt(0).toUpperCase() + option.substring(1)) : false,
				key;

			if (typeof this[setter] === 'function') {
				return this[setter](value);
			}

			if (this.hasOwnProperty(option)) {
				this[option] = value;
			} else {
				for (key in option) {
					if (option.hasOwnProperty(key) && this.hasOwnProperty(key)) {
						this.set(key, option[key]);
					}
				}
			}
			return this;
		},

		/**
		 * Reads the value of this cookie
		 * @returns {string|*}
		 */
		read: function () {
			if (typeof this.name !== 'string') {
				throw new TypeError("No name was set for the cookie.");
			}
			this.value = document.cookie.replace(new RegExp('(?:(?:^|.*;\s*)'
				+ this.name + '\s*=\s*([^;]*).*$)|^.*$', 'g'), '$1');
			return window.decodeURIComponent(this.value);
		},

		/**
		 * Write / save the cookie
		 * @param {string|Object} [value]
		 * @returns {Cookie}
		 */
		write: function (value) {
			var maxAge = window.parseInt(this['max-age']),
				cookie;

			if (value !== undefined) {
				this.setValue(value);
			}

			if (typeof this.name !== 'string') {
				throw new TypeError("No name was set for the cookie.");
			}

			cookie = [this.name + '=' + this.value];

			if (this.expires) {
				if (!this.expires instanceof Date) {
					throw new TypeError("Expires property must be an instance of Date.");
				}
				cookie.push('expires=' + this.expires.toUTCString());
			}

			if (maxAge) {
				cookie.push('max-age=' + maxAge);
			}

			if (this.path) {
				cookie.push('path=' + this.path);
			}

			document.cookie = cookie.join('; ');
			return this;
		},

		/**
		 * Remove the cookie
		 * @returns {Cookie}
		 */
		remove: function () {
			this.setDays(-1);
			return this.write('');
		},

		/**
		 * Returns the string value of the cookie
		 * @returns {string}
		 */
		toString: function () {
			return String(this.value);
		}
	};

	window[global] = Cookie;
}('Cookie'));

/*jslint browser: true, indent: 4, white:true */

/**
 * Create an internationalisation object automatically set to the language used on this document.
 * @author Johan Arensman
 */
var i18n = (function (language) {
	'use strict';
	var catalogs = {},
		defaultLanguage = language ? language.toLowerCase() : 'en',
		cache = {};

	/**
	 * Returns the catalog value for the given dot separated key.
	 * @param {string} key Dot separated path to the requested string without the language key.
	 * @param {string} [language] Optional override for the language to find.
	 * @returns {*} The result matching the given key or false when it's not found.
	 */
	function translate(key, language) {
		var value = catalogs,
			path, part;

		if (cache.hasOwnProperty(key)) {
			return cache[key];
		}

		path = key.split('.');
		path.unshift(language || defaultLanguage);

		do {
			part = path.shift();
			value = value.hasOwnProperty(part) ? value[part] : false;
		} while (value && path.length);

		cache[key] = value;
		return value;
	}

	/**
	 * Loads a formatted object as translations used in the application
	 * @param {object} translations
	 */
	function loadTranslations(translations) {
		catalogs = translations;
	}

	return {
		'get': translate,
		'loadTranslations': loadTranslations
	};
}(document.documentElement.getAttribute('lang') || 'en'));

﻿﻿$(document).ready(function () {

    $.fn.trackTrace = function () {
        var tracktraceData = [],
            that = this,
            url,
            isBusy = false,
            countriesRendered = false,
            formClicked = false,
            startForm = $('form#tracktrace'),
            activeCode = false,
            postalLoad = false,
            formKeys = {
                barcode: startForm.find('input#barcode').attr('name'),
                country: 'tracktrace-country',
                postal: startForm.find('input#postalcode').attr('name'),
                foreign: startForm.find('input#foreign').attr('name'),
                link: startForm.attr('action')
            },
            countries = [];



        function initCountries() {
            var trackTraceExists = $('article.track-trace');

            if (countries.length == 0 && trackTraceExists.length > 0) {
                $(document).ajaxStart(function() {
                    trackTraceExists.addClass('loading');
                });
                $(document).ajaxStop(function() {
                    trackTraceExists.removeClass('loading');
                    $(that).trigger('updateSize.killerApp');
                    $(document).on('unbind', 'ajaxStart');
                });

                $.ajax({
                    dataType: 'json',
                    url: $('article.track-trace').data('countries'),
                    async: true,
                    success: function (data) {
                        if (data != null) {
                            var firstOption;
                            $.each(data, function (key, value) {
                                countries.push(value);
                            });

                            countries.sort(predicate(
                                'selected', 'frequent', 'value'));
                        }
                        renderCountries();
                    }
                });

                $.each(countries, function (key, val) {
                    if (val.postal && val.selected == 'asc') {
                        var postalCode = $('form#tracktrace').find('div.postal-code');
                        postalCode.removeClass('hidden');
                    }
                });
            }

            function predicate() {
                var fields = [],
                  n_fields = arguments.length,
                  field, name, reverse, cmp;

                var default_cmp = function (a, b) {
                    if (a === b) return 0;
                    return a < b ? -1 : 1;
                },
                  getCmpFunc = function (primer, reverse) {
                      var dfc = default_cmp,
                        // closer in scope
                        cmp = default_cmp;
                      if (primer) {
                          cmp = function (a, b) {
                              return dfc(primer(a), primer(b));
                          };
                      }
                      if (reverse) {
                          return function (a, b) {
                              return -1 * cmp(a, b);
                          };
                      }
                      return cmp;
                  };

                // preprocess sorting options
                for (var i = 0; i < n_fields; i++) {
                    field = arguments[i];
                    if (typeof field === 'string') {
                        name = field;
                        cmp = default_cmp;
                    } else {
                        name = field.name;
                        cmp = getCmpFunc(field.primer, field.reverse);
                    }
                    fields.push({
                        name: name,
                        cmp: cmp
                    });
                }

                // final comparison function
                return function (A, B) {
                    var a, b, name, result;
                    for (var i = 0; i < n_fields; i++) {
                        result = 0;
                        field = fields[i];
                        name = field.name;

                        result = field.cmp(A[name], B[name]);
                        if (result !== 0) break;
                    }
                    return result;
                };
            }
        }

        if ($('.killerapp-open-wrapper').has($('article.track-trace')).length > 0) {
            formClicked = true;
            initCountries();
        }

        $('form#tracktrace').on('submit', function () {
            url = changeCodeUrl($(this).attr('action'), $(this));
            var countrySelect = $('select#tracktrace-country');
            var countryCode = countrySelect.find('option:selected').data('countrycode');
            var barcode = $('input#barcode').val();
            var postalcode = $('input#postalcode').val();
            if (countryCode == '') {
                countryCode = 'EN';
            }
            document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
                detail: {
                    name: "funnel_interaction",
                    funnel: {
                        "name": "killer widget - track en trace",
                        "technology": "killerwidget",
                        "type": "application",
                        "step": "laatste",
                        "step_name": "succes killerwidget"
                    },
                    optins: [
                        {
                            "category": "barcode",
                            "answer": barcode
                        },
                        {
                            "category": "postalcode",
                            "answer": postalcode
                        },
                        {
                            "category": "country",
                            "answer": countryCode
                        }
                    ]
                }
            })
            );
            if (activeCode.formMethod == 'Get (url)') {
                if (activeCode != false) {
                    url = changeCodeUrl(activeCode.link, $(this));
                } else {
                    url = changeCodeUrl($(this).attr('action'), $(this));
                }
                var newUrl = url.split('{1}').join($('input#barcode').val()).split('{2}').join($('input#postalcode').val()).split('{3}').join($('select#tracktrace-country').val()).split('{4}').join(countryCode);
                if (newUrl != '') {
                    window.open(newUrl, '_blank');
                }
                return false;
            }
            if (activeCode == false) {
                url = changeCodeUrl($(this).attr('action'), $(this));
                var newUrl = url.split('{1}').join($('input#barcode').val()).split('{2}').join($('input#postalcode').val()).split('{3}').join($('select#tracktrace-country').val()).split('{4}').join(countryCode);
                if (newUrl != '') {
                    window.open(newUrl, '_blank');
                }
                return false;
            }
        });

        $(this).on('click open.killerApp', function (key, value) {
            var form = $('form#tracktrace');

            if (!formClicked && !countriesRendered) {
                formClicked = true;
                if (form.find('.tracktrace-country').length) {
                    initCountries();
                }
            }

            // Get data service URL
            var url = $(this).data('url');

            // Resolving data.
            if (tracktraceData.length < 1) {
                $.ajax({
                    dataType: 'json',
                    url: url,
                    async: true,
                    success: function (data) {
                        tracktraceData = data;
                    }
                });
            }
        });
        if (typeof ($(this).find('input#postalcode')) !== 'undefined') {
            var button = $('form#tracktrace').find('div.submit-buttons button');
            var postalField = $(this).find('input#postalcode');
            var barcodeField = $(this).find('input#barcode');
            $(postalField).on('keyup change', function () {
                if (postalField.val().length > 0 && barcodeField.val().length > 0) {
                    button.attr('disabled', false);
                } else {
                    button.attr('disabled', true);
                }
            });
        }

        if (typeof ($(this).find('input#barcode')) !== 'undefined') {
            var barcodeField = $(this).find('input#barcode');
            $(barcodeField).on('keyup change', function () {
                var button = $('form#tracktrace').find('div.submit-buttons button');
                var postalCode = $('form#tracktrace').find('div.postal-code');
                if (postalCode.css('display') == 'block') {
                    if (barcodeField.val().length > 0 && postalCode.find('input#postalcode').val().length > 0) {
                        button.attr('disabled', false);
                    } else {
                        button.attr('disabled', true);
                    }
                } else {
                    if (barcodeField.val().length > 0) {
                        button.attr('disabled', false);
                    } else {
                        button.attr('disabled', true);
                    }
                }

                if (!isBusy) {
                    isBusy = true;
                    var code = matchPrefix($(this).val());
                    if (code !== false) {
                        activeCode = code;
                        setBarcodeValues(code);
                    } else {
                        activeCode = false;
                        resetFormKeys();
                    }

                } else {
                    todo = $(this).val();
                }
            });
        }

        function matchPrefix(barcode) {
            for (var keyword in tracktraceData) {
                var data = tracktraceData[keyword];
                if (data.title != null) {
                    var patterns = getRegexTypes(data.regextype, data.prefix);
                    for (var pattern in patterns) {
                        for (var i = 0; i < patterns.length; i++) {
                            if (barcode.match(patterns[i])) {
                                isBusy = false;
                                return tracktraceData[keyword];
                            }
                        }
                    }
                }
            }
            isBusy = false;
            return false;
        }

        function setBarcodeValues(code) {
            var form = $('form#tracktrace');
            if (code.formMethod == 'Get (url)') {
                //code.link = changeCodeUrl(code.link, form);
                url = code.link;
            } else if (code.formMethod == 'Post') {
                form.attr('method', 'POST');
                if (code.barcodeKey != '') { form.find('input#barcode').attr('name', code.barcodeKey); }
                if (code.countryKey != '') { form.find('select#tracktrace-country').attr('name', code.countryKey); }
                if (code.postalKey != '') { form.find('input#postalcode').attr('name', code.postalKey); }
                if (code.foreignKey != '') { form.find('input#foreign').attr('name', code.foreignKey); }
                if (code.link != '') { form.attr('action', code.link); }
            }
        } 1

        function changeCodeUrl(url, form) {
            if (form.find('div.form-row.postal-code').hasClass('hidden') || form.find('input#postalcode').val() == '') {
                var postal = url.split("?");
                var postal = postal[postal.length - 1].split('&');
                if (postal.length < 2) {
                    url = url.replace('/{2}', '');
                }
                else if (postal.length > 1) {
                    for (var i = 0; i < postal.length; i++) {
                        if (postal[i].indexOf('{2}') > -1) {
                            url = url.replace('&' + postal[i], '');
                            url = url.replace(postal[i], '');
                        }
                    }
                }
            }
            if (form.find('select#tracktrace-country').val() == '') {
                var country = url.split("?");
                var country = country[country.length - 1].split('&');
                if (country.length < 2) {
                    url = url.replace('/{3}', '');
                }
                else if (country.length > 1) {
                    for (var i = 0; i < postal.length; i++) {
                        if (postal[i].indexOf('{3}') > -1) {
                            url = url.replace('&' + postal[i], '');
                            url = url.replace(postal[i], '');
                        }
                    }
                }
            }
            return url;
        }

        function resetFormKeys() {
            var form = $('form#tracktrace');
            form.attr('method', 'GET');
            form.find('input#barcode').attr('name', formKeys.barcode);
            form.find('select#tracktrace-country').attr('name', formKeys.country);
            form.find('input#postalcode').attr('name', formKeys.postal);
            form.find('input#foreign').attr('name', formKeys.foreign);
            form.attr('action', formKeys.link);

            return true;
        }


        function getRegexTypes(regexType, prefix) {
            var ret = [];

            if (regexType == "3S" || regexType == "2S") {
                ret.push(new RegExp('\\b' + prefix + '+[a-zA-Z]{1,6}[0-9]{2,10}\\b', 'gi'));
            }
            if (regexType == "KG") {
                ret.push(new RegExp('\\b' + prefix + '+[0-9]{1,9}\\b', 'gi'));
                ret.push(new RegExp('\\b' + prefix + '+[a-zA-Z]{1,6}[0-9]{2,10}\\b', 'gi'));
            }
            if (regexType == "Brieven internationaal" || regexType == "Pakketten internationaal") {
                ret.push(new RegExp('\\b' + prefix + '+[0-9]{5,9}[a-zA-Z]{2,3}\\b', 'gi'));
            }

            if (regexType == "Alleen code prefix") {
                ret.push(new RegExp('\\b' + prefix + '[a-zA-Z0-9]{1,20}\\b', 'gi'));
            }
            1
            if (ret.length == 0) {
                ret.push(new RegExp('\\b' + prefix + '+[a-zA-Z0-9]{1,11}\\b', 'gi'));
            }


            return ret;
        }

        function renderCountries() {
            var options = [];

            var select = $('<select>', {
                'class': 'inputselect',
                'name': formKeys.country,
                'id': 'tracktrace-country'
            }).on('change', function () {
                var inputPostal = $('div.form-row.postal-code');
                var button = $('form#tracktrace').find('div.submit-buttons button');
                var postalCode = $('form#tracktrace').find('div.postal-code');
                if ($(this.options[this.selectedIndex]).attr('data-postal') == 'true') {
                    if (postalCode.find('input#postalcode').val().length > 0) {
                        button.attr('disabled', false);
                    } else {
                        button.attr('disabled', true);
                    }
                    inputPostal.removeClass('hidden');
                } else {
                    var barcodeField = $('form#tracktrace').find('input#barcode');
                    if (barcodeField.val().length > 0) {
                        button.attr('disabled', false);
                    } else {
                        button.attr('disabled', true);
                    }
                    inputPostal.addClass('hidden');
                }
            });

            select.append($.map(countries, function (country) {
                if (country.key == "separator") {
                    return option = $('<option>', {
                        'value': "",
                        'text': "",
                        'disabled': true,
                        'class': 'separator'
                    });
                }
                return option = $('<option>', {
                    'value': country.key,
                    'text': country.value,
                    'data-postal': country.postal,
                    'data-countrycode': country.countryCode,
                    'selected': function () {
                        if (country.selected == "asc") {
                            postalLoad = country.postal;
                            return true;
                        }
                    }
                });
            }));

            $('.tracktrace-country').append(select);
            countriesRendered = true;
            if (postalLoad) {
                var postalCode = $('form#tracktrace').find('div.postal-code');
                postalCode.removeClass('hidden');
                $(that).trigger('updateSize.killerApp');
            }

        }
    };

    $('article.track-trace').trackTrace();

    // Deprecated funciton for 3s code.
    $('#link-tracktrace').on('click', function () {
        // Modify Url when one of theses prefixes are used.
        var catchForeign = ['3S', 'KG', '2S'];

        // Get prefix of code.
        var prefix = $('#barcode').val().substring(0, 2);

        // If prefix is in array.
        var used = $.inArray(prefix.toUpperCase(), catchForeign) > -1;

        // Get current url.
        currentUrl = $(this).attr('href').toLowerCase().replace("barcode", "b").replace("postalcode", "p");

        // Get foreign value.
        var foreign = $('input[name="i"]:checked').val();

        // Get postalcode value.
        var postalCode = $('#postalcode').val();

        // If postalcode is not empty and foreign is false.
        if (postalCode != "" && foreign == 'False') {
            currentUrl = currentUrl.replace("p=", "p=" + postalCode);
        }

        // When search value is used with 3s, kg or 2s prefix
        if (used) {
            if (foreign == '') {
                foreign = 'False';
            }
            currentUrl += '&i=' + foreign;
            if (foreign == 'True') {
                currentUrl = currentUrl.replace("&p=", "");
            }
        }
        window.open(currentUrl);
        return false;
    });

      $('.track-trace').one('keyup', ':input:visible:first', function () {
          document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
              detail: {
                  name: "funnel_interaction",
                  funnel: {
                      "name": "killer widget - track en trace",      
                      "technology": "killerwidget",
                      "type": "application",
                      "step": "10",
                      "step_name": "start killerwidget"
                  }
              }
          })
          );
      });

});

/*jslint browser: true, plusplus: true, regexp: true, indent: 4, white:true */
/*global Modernizr, jQuery, i18n */

jQuery(function ($) {
	'use strict';

    /**
	 * Generic killer app
	 * @param {object} [options]
	 * @returns {jQuery}
	 */
	$.fn.killerApp = function (options) {
		var $html = $(document.documentElement),
			desktopWidth = 1000,
			killerApps = $(this),
			settings = $.extend({}, {
				onActivate: $.noop,
				onDeactivate: $.noop
			}, options),
			activeApp;

		window.addEventListener('resize', setAppLocation);

		function setAppLocation() {
			var width = window.innerWidth;
			var container = $('.banner-tt');
			if (width > desktopWidth) {
				container.prependTo($('.killerapp-banner'));
			} else {
				// Only switch if container is still in desktop mode
				// otherwise the switch is done from mobile to mobile which is
				// unnecessary(and caused keyboard errors on android)
				if (container.parent('.killerapp-banner').length) {
					container.prependTo($('.killerapp-banner-loose'));
				}
			}
		}
		setAppLocation();

		return killerApps
			.each(function () {
				var element = $(this),
					form = element.find('form'),
					collapsed = true;

				element
					.on('open.killerApp', function () {
						if (collapsed) {
							element.addClass('opening').removeClass('collapsed');
							killerApps.not(element).trigger('close.killerApp');
							form.show();
							collapsed = false;
							activeApp = element;
							if (!element.hasClass('is-ratescalculator')) {
								settings.onActivate();
							}
						}
					})
					.on('close.killerApp', function () {
						if (!collapsed) {
							if (!element.hasClass('is-ratescalculator')) {
								element.addClass('collapsed closing');
							} else {
								element.addClass('closing');
							}
							form.hide();
							collapsed = true;
							activeApp = null;
							settings.onDeactivate();
						}
					});

				// header is a 'open':
				element.find('header').on('click', function () {
					element.trigger('open.killerApp');
				});

				// make sure initially open killer app is initialized
				if (!element.is('.collapsed')) {
					element.trigger('open.killerApp');
					checkInputText($(this).find('form'));
				}

				element.find('header').on('click', function () {
					// Focus at the first empty input text field. 
					checkInputText($(this).next('form'));
				});
			});
	};

	// Set focus to first empty input field.
	var checkInputText = function (form) {
		var ret = "";
		form.find('input[type=text]').each(function (key, value) {
			if ($(this).val() == "" && ret == "") {
				ret = this;
			}
		});
		if (ret == "") {
			ret = form.find('input[type=text]').last();
		}
		$(ret).focus();
	};
});

/*jslint browser: true, plusplus: true, regexp: true, indent: 4, white:true */
/*global Modernizr, jQuery, i18n */

jQuery(function ($) {
    'use strict';

    /**
	 * Generic killer app
	 * @param {object} [options]
	 * @returns {jQuery}
	 */
    $.fn.killerAppOld = function (options) {
        var $html = $(document.documentElement),
            desktopWidth = 1000,
			killerApps = $(this),
			settings = $.extend({}, {
			    onActivate: $.noop,
			    onDeactivate: $.noop
			}, options),
			activeAppClick = false,
			activeApp;

        $html
			// check if the active app should be deactivated:
			.on('click touchend', function () {
			    if (activeApp && !activeAppClick) {
			        activeApp.trigger('close.killerApp');
			        activeApp = null;
			    }
			    activeAppClick = false;
			});

        window.addEventListener('resize', setAppLocation);

        function setAppLocation() {
            var width = window.innerWidth;
            var container = $('.banner-tt');
            if (width > desktopWidth) {
                container.prependTo($('.killerapp-banner'));
            } else {
                // Only switch if container is still in desktop mode
                // otherwise the switch is done from mobile to mobile which is
                // unnecessary(and caused keyboard errors on android)
                if (container.parent('.killerapp-banner').length) {
                    container.prependTo($('.killerapp-banner-loose'));
                }
            }
        }	
        setAppLocation();

        return killerApps
			.each(function () {
			    var element = $(this),
					form = element.find('form'),
					$result = element.find('.result-container'),
					collapsed = true,
					originalHeight;

			    // undo the CSS height: 0;
			    form.css('height', 'auto');
			    // store the height
			    originalHeight = form.height();
			    // set the height back to 0
			    if (!element.closest('.killerapp-open-wrapper').length || element.hasClass('is-ratescalculator')) {
			        form.height(0);
			    } else {
			        // we don't need any handlers for opening/closing
			        return;
			    }

			    function toggleForm() {
			        originalHeight = form.css({
			        	height : 'auto',
			        	visibility : 'hidden'
			        }).height();
			        form
			        	.stop()
			        	.css({
				        	height : collapsed ? 0 : originalHeight,
				        	visibility : ''
				        })
			        	.animate({ height: collapsed ? originalHeight : 0 }, 200, function () {
				            element.removeClass('opening closing');
				        });
			    }

			    element
					.on('click touchend', function () {
					    activeAppClick = (activeApp && activeApp.is(element));
					})
					.on('toggle.killerApp', function () {
					    element.trigger(collapsed ? 'open.killerApp' : 'close.killerApp');
					})
					// Resize the fixed height form when a conditionally displayed element changes
					.on('updateSize.killerApp change.conditionalDisplay', function () {
					    var currentHeight = form.height();
					    originalHeight = form.css('height', 'auto').height();
					    form.height(currentHeight);
					    if (!collapsed) {
					        form.animate({ height: originalHeight }, 200);
					    }
					})
					.on('open.killerApp', function () {
					    if (collapsed) {
					        element.addClass('opening').removeClass('collapsed');
					        killerApps.not(element).trigger('close.killerApp');
					        toggleForm();
					        collapsed = false;
					        activeApp = element;
					        if (!element.hasClass('is-ratescalculator')) {
					            settings.onActivate();
					        }
					    }
					})
					.on('close.killerApp', function () {
					    if (!collapsed) {
					        if (!element.hasClass('is-ratescalculator')) {
					            element.addClass('collapsed closing');
					        } else {
					            element.addClass('closing');
					        }
					        toggleForm();
					        collapsed = true;
					        activeApp = null;
					        settings.onDeactivate();
					    }
					});


			    // form clicks always open:
			    form.on('click', function () {
			        if (collapsed) {
			            element.trigger('open.killerApp');
			        }
			    });
			    // header is a 'toggle':
			    element.find('header').on('click', function () {
			        element.trigger('toggle.killerApp');
			    });
			});
    };

    /**
	 * The rates calculator killer app
	 * Works on top of the base killerApp plugin
	 * @returns {jQuery}
	 */
    $.fn.ratesCalculator = function () {
        return $(this).each(function () {
            var app = $(this),
				dataUrl = app.data('data-source'),
				form = app.find('form'),
				json = null,
				renderTypes = {},
				conditions = {},
				variables = {},
				questionIndex = 0,
				isOpen = false,
				currentWeightsList;


            /**
			 * Saves the provided state variable with the given value
			 * @param {string} variable
			 * @param {*} value
			 * @returns {*} The given value
			 */
            function set(variable, value) {
                variables[variable] = value;
                return value;
            }

            /**
			 * Retrieves the variable from the state and returns it. Returns the defaultValue when it doesn't exist.
			 * @param {string} variable
			 * @param {*} [defaultValue]
			 * @returns {*}
			 */
            function get(variable, defaultValue) {
                if (variables.hasOwnProperty(variable)) {
                    return variables[variable];
                }
                return defaultValue;
            }

            /**
			 * Renders an array of questions
			 * @param {Array} questions The questions definition Array
			 * @param {Array} [values] Predefined set of question values
			 */
            function render(questions, values) {
                // lookup array for the next questions (siblings, not children):
                var nextQuestions = questions.slice();
                form.stop();

                $.each(questions, function (i, question) {
                    var type = question.type || '?',
						value = values ? $(values).filter(function (i, value) {
						    return value.name === question.id;
						}) : question.value,
						failed, row, tooltip, label;

                    if (value && value.length && typeof value.get === 'function') {
                        value = value.get(0).value;
                    }
                    // Remove this question from the upcoming questions list:
                    nextQuestions.shift();
                    question.nextQuestions = nextQuestions.slice();

                    if (renderTypes[type]) {
                        if (question.hasOwnProperty('conditions')) {
                            failed = $.grep(question.conditions, function (condition) {
                                if (conditions.hasOwnProperty(condition.type)) {
                                    return conditions[condition.type].apply(question, condition['arguments']);
                                }
                                return false;
                            }, true);

                            if (failed.length) {
                                // one or more conditions have failed, don't render:
                                return;
                            }
                        }

                        row = renderTypes[type](question, String(value));

                        if (row) {
                            row.addClass('form-row');
                            if (questionIndex === 0) {
                                row.addClass('first');
                            }
                            questionIndex++;

                            // a value has changed in this row:
                            row.on('questionChange.killerApp', function (event, data) {
                                var children = row.nextAll('.form-row');

                                if (data && data['export']) {
                                    $.each(data['export'], function (i, variable) {
                                        // when the export has no value, the value of the data is used:
                                        set(variable.key, variable.value !== undefined ? variable.value : data.value);
                                    });
                                }

                                // destroy any tooltips:
                                children.find('.tooltip').qtip('destroy', true);
                                // remove the elements:
                                children.remove();
                                // and update the index:
                                questionIndex = row.prevAll('.form-row').length + 1;
                            });

                            form.append(row);

                            // Initialize the tooltip:
                            if (question.info) {
                                tooltip = $('<div>', {
                                    'class': 'tooltip',
                                    'html': question.info
                                });
                                label = row.find('.label').first();

                                if (label.length) {
                                    if (label.hasClass('inline')) {
                                        label.after(tooltip);
                                    } else {
                                        label.append(tooltip);
                                    }
                                } else {
                                    // append the tooltip:
                                    row.append(tooltip);
                                }
                                window.initializeQTips(row);
                            }

                            row.trigger('questionRender.killerApp');
                        }
                    }
                });
                app.trigger('updateSize.killerApp');
            }

            /**
			 * Returns the currently selected regions based on the selected type and country
			 * @returns {Array}
			 */
            function getSelectedCountryRegions() {
                var listName = get('regionList'),
					countryId = get('country'),
					country;

                if (listName && countryId) {
                    country = $.grep(json.countries, function (country) {
                        return country.id === countryId;
                    })[0];
                    return country[listName];
                }

                return [];
            }

            /**
			 * Condition which tests if the currently selected weight has the given price key
			 * @param {string} priceKey
			 * @returns {bool}
			 */
            conditions.weightHasPriceKey = function (priceKey) {
                var currentWeightId = window.parseInt(get('currentWeight')),
					currentWeight;

                if (currentWeightId && currentWeightsList && currentWeightsList.hasOwnProperty('weights')) {
                    // fetch the currently selected weight:
                    currentWeight = $.grep(currentWeightsList.weights, function (weight) {
                        return window.parseInt(weight.value) === currentWeightId;
                    });

                    if (currentWeight.length) {
                        // return whether the selected weight has the price key:
                        return currentWeight[0].hasOwnProperty(priceKey);
                    }
                }
                return false;
            };

            /**
			 * Returns a radio input type
			 * @param {object} question
			 * @param {*} [value]
			 * @returns {jQuery}
			 */
            renderTypes.radio = function (question, value, typePackage) {
                //TODO check for flexible solution
                var container = $('<fieldset>', { 'class': 'radio' }),
					label = question.label ? $('<span>', {
					    'class': 'label',
					    'text': question.label,
					    'for': question.options[0].id || question.id + '-0'
					}) : 0,
					fields = $('<span>', { 'class': 'field' }),
					checkedField = null;

                // Force the value of checked (even when we don't have a value, to avoid remembering from a previous state)
                $.map(question.options, function (option) {
                    option.checked = String(option.value) === value;
                    return option;
                });

                // render the options
                $.each(question.options, function (i, option) {
                    var id = option.id || question.id + '-' + i,
						input = $('<input>', {
						    'class': 'input',
						    'type': 'radio',
						    'name': question.id,
						    'id': id,
						    'value': option.value,
						    'checked': option.checked
						});

                    if (option.checked) {
                        checkedField = input;
                    }

                    input.on('change', function () {
                        var children = option.children || question.children || question.nextQuestions;
                        // trigger a change (to remove all next rows)
                        container.trigger('questionChange.killerApp', option);
                        // render my children:
                        if (children) {
                            render(children);
                        }
                    });

                    if (typePackage) {
                        fields.append($('<span>', {
                            'class': 'field-half'
                        }).append(input).append(
							$('<label>', {
							    'class': ('inline label package package-' + i),
							    'for': id,
							    'text': option.label || '?'
							})).on('click', function () {
							    input.prop('checked', true).trigger('change');
							})
						);
                    } else {
                        fields.append(input).append(
							$('<label>', {
							    'class': 'inline label',
							    'for': id,
							    'text': option.label || '?'
							}).on('click', function () {
							    input.prop('checked', true).trigger('change');
							})
						);
                    }
                });

                if (label) {
                    container.append(label)
                }
                container.append(fields);

                if (checkedField) {
                    window.setTimeout(function () {
                        checkedField.trigger('change');
                    }, 50);
                }

                return container;
            };

            /**
			 * Returns an illustrated radio input type
			 * @param {object} question
			 * @param {*} [value]
			 * @returns {jQuery}
			 */
            renderTypes.package = function (question, value) {
                return renderTypes.radio(question, value, true);
            };

            /**
			 * Returns a select input type
			 * @param {object} question
			 * @param {*} [value]
			 * @returns {jQuery}
			 */
            renderTypes.select = function (question, value) {
                var container = $('<div>', { 'class': 'select' }),
					label = $('<label>', {
					    'class': 'label',
					    'text': question.label,
					    'for': question.id
					}),
					fields = $('<span>', { 'class': 'field' }),
					select = $('<select>', {
					    'class': 'inputselect',
					    'name': question.id,
					    'id': question.id
					}),
					hasSelectedOptions = false;

                if (question.placeholder) {
                    if (question.type != 'country') {
                        select.append($('<option>', {
                            'value': '',
                            'text': question.placeholder
                        }));
                    }
                }

                select.append($.map(question.options, function (option) {
                    return $('<option>', {
                        'value': option.value,
                        'text': option.label,
                        'class': option.class,
                        'disabled': option.disabled,
                        'selected': (function () {
                            if (option.select == "asc") {
                                hasSelectedOptions = true;
                                return true;
                            }
                            return false;
                        }())
                    });
                })).appendTo(fields);

                select.on('change', function () {
                    var currentValue = select.val(),
						option = $(question.options).filter(function () {
						    return this.value === currentValue;
						}).get(0),
						children = option && option.children ? option.children : question.children || question.nextQuestions;

                    // trigger a change which (re)renders all children
                    question.value = currentValue;
                    container.trigger('questionChange.killerApp', question);
                    // render my children:
                    if (children) {
                        render(children);
                    }
                });

                // When a <select> is rendered with a value, immediately trigger a change when rendered:
                if (hasSelectedOptions) {
                    container.on('questionRender.killerApp', function () {
                        container.find('.input, .inputselect').trigger('change');
                    });
                }

                return container.append(label, fields);
            };

            /**
			 * Returns a (single) checkbox input
			 * @param {object} question
			 * @param {*} [value]
			 * @returns {jQuery}
			 */
            renderTypes.checkbox = function (question, value) {
                var container = $('<div>', { 'class': 'checkbox' }),
					label = $('<label>', {
					    'class': 'inline label',
					    'text': question.label,
					    'for': question.id
					}),
					input = $('<input>', {
					    'class': 'input',
					    'type': 'checkbox',
					    'name': question.id,
					    'id': question.id,
					    'value': value || question.value,
					    'checked': question.checked
					});

                input.on('change', function () {
                    var checked = input.prop('checked'),
					// find the option that matches our checked state:
						option = $(question.options).filter(function () {
						    return (this.checked === 'true' || this.checked === true) === checked;
						}).get(0),
						children = option && option.children ? option.children : question.children || question.nextQuestions;

                    container.trigger('questionChange.killerApp', option);
                    // render the children of the option
                    if (children) {
                        render(children);
                    }
                });

                return container.append(input, label);
            };

            /**
			 * Outputs the HTML in the text property of the question.
			 * @param {object} question
			 * @returns {jQuery}
			 */
            renderTypes.html = function (question) {
                return $('<div>', {
                    'class': 'html',
                    'html': question.text
                });
            };

            /**
			 * Returns a 'select' renderType with countries and populates the 'country' variable.
			 * @param {object} question
			 * @param {*} [value]
			 * @returns {jQuery}
			 */
            renderTypes.country = function (question, value) {

                json.countries.sort(predicate(
                    'selected', 'frequent', 'name'));

                var first = false;
                question.options = $.map(json.countries, function (country) {
                    if (country.id == "separator") {
                        return {
                            'value': "",
                            'label': "",
                            'disabled': true,
                            'class': 'separator'
                        } 
                    } else {
                        return {
                            'label': country.name,
                            'value': country.id,
                            'disabled': false,
                            'select': country.selected
                        };
                    }
                });
                return renderTypes.select(question, value);
            };

            function predicate() {
                var fields = [],
                  n_fields = arguments.length,
                  field, name, reverse, cmp;

                var default_cmp = function (a, b) {
                    if (a === b) return 0;
                    return a < b ? -1 : 1;
                },
                  getCmpFunc = function (primer, reverse) {
                      var dfc = default_cmp,
                        // closer in scope
                        cmp = default_cmp;
                      if (primer) {
                          cmp = function (a, b) {
                              return dfc(primer(a), primer(b));
                          };
                      }
                      if (reverse) {
                          return function (a, b) {
                              return -1 * cmp(a, b);
                          };
                      }
                      return cmp;
                  };

                // preprocess sorting options
                for (var i = 0; i < n_fields; i++) {
                    field = arguments[i];
                    if (typeof field === 'string') {
                        name = field;
                        cmp = default_cmp;
                    } else {
                        name = field.name;
                        cmp = getCmpFunc(field.primer, field.reverse);
                    }
                    fields.push({
                        name: name,
                        cmp: cmp
                    });
                }

                // final comparison function
                return function (A, B) {
                    var a, b, name, result;
                    for (var i = 0; i < n_fields; i++) {
                        result = 0;
                        field = fields[i];
                        name = field.name;

                        result = field.cmp(A[name], B[name]);
                        if (result !== 0) break;
                    }
                    return result;
                };
            }

            /**
			 * Weight select, retrieves the correct list and returns a 'select' renderType.
			 * @param {object} question
			 * @param {*} [value]
			 * @returns {jQuery|bool}
			 */
            renderTypes.weight = function (question, value) {
                var listName = get('regionList'),
					countryRegions = getSelectedCountryRegions(),
					weightList, rates;

                if (countryRegions.length) {
                    weightList = json[listName];

                    // find the first correct entry in the weight list based on the regions of the country:
                    rates = $.grep(weightList, function (weight) {
                        return $.inArray(weight.id, countryRegions) !== -1;
                    })[0];

                    // make the current rates available to other questions
                    currentWeightsList = rates;

                    if (rates) {
                        // reformat the weights to an option array
                        question.options = $.map(rates.weights, function (option) {
                            return {
                                'label': option.label,
                                'value': option.value
                            };
                        });

                        return renderTypes.select(question, value);
                    }

                    return false;
                }
                window.alert('No region list set! Unable to determine what type of mail is sent (post/package).');
                return false;
            };

            /**
			 * Region based HTML output, chooses the correct text based on the country and returns a 'html' renderType.
			 * @param {object} question
			 * @returns {jQuery}
			 * @see renderTypes.html()
			 */
            renderTypes.regionExitHtml = function (question) {
                var regions = getSelectedCountryRegions(),
					textKey = 'default',
					key;

                for (key in question.texts) {
                    if (question.texts.hasOwnProperty(key) && $.inArray(key, regions) !== -1) {
                        textKey = key;
                    }
                }

                question.text = $('<div>').html(question.texts[textKey] || '').text();
                return renderTypes.html(question);
            };


            //START NEW KILLER-APP
            renderTypes.resultsButton = function (question) {
                var $element = $('<div>', {
                    'class': 'html submit-buttons'
                }).append($('<p>').append($('<button>', {
                    'class': 'button',
                    'html': question.label
                })));

                // observeer de button op clicks
                $element.on('click', function (event) {

                    event.preventDefault();
                    renderChannels();
                    showPromos();
                });
                // na click doe je ding, verbergen enzo, tonenn uitgangen.
                return $element;
            };

            function returnToForm() {
                $('.rates-calculator').removeClass('result').find('.result-row.price-display').each(function () {
                    $(this).remove();
                });
                $('.rates-calculator').find('.result-row.promo').each(function () {
                    $(this).remove();
                });
            }

            //show nieuwe 'uitgangen'
            function renderChannels() {
                var regionList = get('regionList'),
					countryRegions = getSelectedCountryRegions(),
					weightList = json[regionList],
					currentWeightId = parseInt(get('currentWeight')),
					weights,
					priceList,
					priceKey = get('priceKey'),
					isRegistered = priceKey === 'registered',
					currentWeight,
                    weightResults,
					channelsList,
                    parameterList,
					currencySign = json.currency[0].currencySign;
                weights = $.grep(weightList, function (weight) {
                    return $.inArray(weight.id, countryRegions) !== -1;
                });

                priceList = $.grep(currentWeightsList.weights, function (weight) {
                    return window.parseInt(weight.value) === currentWeight;
                })[0];
 
                var results = [];
                for (var i = 0; i < weights.length; i++) {
                    var tempWeights = weights[i];
                    for (var z = 0; z < tempWeights.weights.length; z++) {
                        if (tempWeights.weights[z].value == currentWeightId) {
                            results.push(tempWeights.weights[z]);
                        }
                    }
                }

                var channelsLists = [];
                for (var i = 0; i < results.length; i++) {
                    channelsList = $.grep(results[i].channels, function (list) {
                        var registeredList = [];
                        if ((typeof list.registered) == "object") {
                            for (var registeredType in list.registered) {
                                if (list.registered[registeredType] == "true") {
                                    registeredList.push(true);
                                } else if (list.registered[registeredType] == "false") {
                                    registeredList.push(false);
                                }
                            }
                        } else {
                            if (list.registered == "true") {
                                registeredList.push(true);
                            } else if (list.registered == "false") {
                                registeredList.push(false);
                            }
                        }
                        return $.inArray(isRegistered, registeredList) !== -1;
                    });
                    channelsLists = $.merge(channelsLists, channelsList);
                }

                var embeddedChannelList = [];
                for (var i = 0; i < channelsLists.length; i++) {
                    if (channelsLists[i].root) {
                        for (var channel = 0; channel < channelsLists[i].root.channels.length; channel++) {
                            embeddedChannelList.push(channelsLists[i].root.channels[channel]);
                        }
                    }
                }

                function getRegions(country, type)
                {
                    for (var c in json.countries) {
                        if (json.countries[c].name == country) {
                            if (type == 'post') {
                                return json.countries[c]['post-regions'];
                            } else {
                                return json.countries[c]['package-regions'];
                            }
                        }
                    }
                }

                channelsList = embeddedChannelList;

                if (channelsList.length) {
                    //channelsList = channelsList[0].root.channels;
                    $('.rates-calculator').addClass('result');

                    var types = ['Brief', 'Pakket', 'Postzegel'];
                    var typeValues = ['Letters', 'Parcels', 'LetterStampCode'];
                    var paramKeys = ['catalogue', 'productCode', 'weightClass', 'countryIsoCode'];
                    var formType = $('input[name=post-package]:checked').val();
                    var weight, country, countryVal, registered, regions;
                    if (formType == 1) {
                        weight = $('#package-weight option:selected').text();
                        country = $('#package-country').val();
                        countryVal = $('#package-country option:selected').text();
                        registered = $('#package-registered').is(':checked');
                        regions = getRegions(countryVal, 'package');
                    } else {
                        weight = $('#post-weight option:selected').text();
                        countryVal = $('#post-country option:selected').text();
                        country = $('#post-country').val();
                        registered = $('#post-registered').is(':checked');
                        regions = getRegions(countryVal, 'post');
                    }

                    var tmpRegions = [];
                    for (var i = 0; i < regions.length; i++) {
                        tmpRegions.push(regions[i].toLowerCase());
                    }
                    regions = tmpRegions;

                    $.each(channelsList, function (i, channel) {
                        var param = (channel.href.indexOf('?params') > -1) ? true : false;
                        var stamp = (channel.href.indexOf('?stamp') > -1) ? true : false;
                        if ((param || stamp) && json.parameterValues.parameter != null) {
                            var typeValue = typeValues[formType];
                            var tridionType = types[formType];
                            var replacement = "?params"
                            if (stamp) {
                                typeValue = typeValues[2];
                                tridionType = types[2];
                                replacement = "?stamp"
                            }
                            parameterList = json.parameterValues.parameter;
                            for (i = 0; i < parameterList.length; i++) {
                                if (parameterList[i].type == tridionType && parameterList[i].weight_key == weight && (parameterList[i].region == "" || regions.indexOf(parameterList[i].region.toLowerCase()) > -1) && (parameterList[i].tab == "" || parameterList[i].tab == channel.tab)) {
                                    var product_code = parameterList[i].product_code;
                                    var weight_class = parameterList[i].weight;
                                    if (registered && parameterList[i].product_code_registered != '') {
                                        product_code = parameterList[i].product_code_registered;
                                    }
                                    if (registered && parameterList[i].weight_registered != '') {
                                        weight_class = parameterList[i].weight_registered;
                                    }
                                    var url = '?catalogue=' + typeValue
                                            + '&productCode=' + product_code
                                            + '&weightClass=' + weight_class
                                            + '&countryIsoCode=' + country;
                                    channel.href = channel.href.replace(replacement, url);
                                }
                            }
                        }

                        // bouw exit html
                        var $channel = $('<div>', {
                            'class': 'result-row price-display'
                        }).append($('<a>', {
                            'class': 'wrapper',
                            'href': channel.href
                        }).append($('<h4>', {
                            'html': channel.title
                        })).append($('<span>', {
                            'class': 'price',
                            'html': currencySign + channel[priceKey]
                        })).append($('<p>', {
                            'html': channel.info
                        })));
                        if (channel.promoted == "true") {
                            $channel.addClass('promoted');
                        }
                        if (channel.popup == "true") {
                            $channel.find("a").attr('target', '_blank');
                        }
                        if (channel[priceKey] != '-') {
                            $('.rates-calculator').find('.result-container').append($channel);
                        }

                    });
                }
                //backbutton
                $('#js-killer-app-previous').on('click', function () {
                    returnToForm();
                });
            }

            //show 'vaste elementen'
            function showPromos() {

                var regionList = get('regionList'),
					countryRegions = getSelectedCountryRegions(),
					weightList = json[regionList],
					weights,
					promosList;
                weights = $.grep(weightList, function (weight) {
                    return $.inArray(weight.id, countryRegions) !== -1;
                })[0];

                promosList = weights.rootPromos.promos;
                // bouw exit html
                var $promo = $('.rates-calculator').find('.result-container').append($('<div>', {
                    'class': 'result-row promo'
                }));

                $.each(promosList, function (i, promo) {
                    // bouw exit html
                    var $block = $('<div>');

                    if (promo.title) {
                        $block.append($('<h4>', {
                            'html': promo.title
                        })).addClass('extra');
                    }

                    $block.append($('<p>').append($('<a>', {
                        'href': promo.href,
                        'html': promo.text
                    })));
                    if (promo.popup == "true") {
                        $block.find("a").attr('target', '_blank');
                    }
                    $promo.find('.promo').append($block);
                });
            }

            //END NEW KILLER-APP

            /**
			 * Handles the 'open' event, loads the JSON and renders the initial questions
			 */
            app.on('open.killerApp', function () {
                var values = form.serializeArray();

                form.empty();
                form.trigger('reset');
                questionIndex = 0;
                if (json === null) {
                    app.addClass('loading');
                    $.ajax({
                        dataType: 'json',
                        url: dataUrl,
                        success: function (data) {
                            if (data.questions !== undefined) {
                                json = data;
                                app.removeClass('loading');
                                render(json.questions, values);
                            }
                        },
                        error: function () {
                            app.removeClass('loading');
                            render([
								{
								    'type': 'html',
								    'text': i18n.get('killer-apps.load-error')
								}
                            ], values);
                        }
                    });
                } else {
                    if (json.questions !== undefined) {
                        render(json.questions, values);
                    }
                }
                isOpen = true;
            });

            /**
			 * Handles the 'close' event, cleans the generated questions.
			 */
            app.on('close.killerApp', function () {
                if (isOpen) {
                    // Fixes a bug which causes inputs to retain their value...
                    form.find('input[type=radio]').prop('checked', false).empty();
                    form.empty();
                    questionIndex = 0;
                    render(json.questions);
                    isOpen = false;
                    app.trigger('updateSize.killerApp');
                    returnToForm();
                }
            });

            /**
			 * When the app is created the first question is rendered but since we want to render each question
			 * dynamically we need to copy the value of the first question.
			 */
            form.on('click', '.form-row:first-child label', function () {
                var label = $(this),
					placeholderInput = $('#' + label.attr('for')),
					placeholderInputType = placeholderInput.attr('type').toLowerCase();

                if ($.inArray(placeholderInputType, ['radio', 'checkbox']) >= 0) {
                    placeholderInput.prop('checked', true);
                }
            });

            /**
			 * When the form is submitted using a button with an 'action' data attribute
			 * the form action is updated and the form is submitted.
			 * Example button: <button type="submit" data-action="http://www.google.com/">Submit form to Google</button>
			 */
            form.on('click', 'button[data-action]', function () {
                form.attr('action', $(this).data('action'));
            });
        });
    };

    // immediately invoke the rates calculator killer app:
    $('.rates-calculator.killer-app-old').ratesCalculator();

    $('div.killer-apps-old article.column').each(function (key, value) {
        $(this).click(function () {
            // Get form in killerapp.
            var form = $(this).find('form');

            // Default focus is false
            var isFocus = false;

            // Get killerapp height
            var height = Number(form.css('height').replace('px', ''));

            // If form height is bigger then 80.
            if (height > 80) {
                isFocus = true;
            }

            if (isFocus == false) {
                // Focus at the first empty input text field. 
                checkInputText(form);

                // Select first
                var checked = isChecked(form);
                if (!checked) {
                    checkFirstRadio(form);
                }
            }
        });
    });

    var focusZipcodesearch = function () {
        if ($('section.tab-content').length) {
            var form = $('section.tab-content').find('form');
            checkInputText(form);
        }
    };

    // Set focus to first empty input field.
    var checkInputText = function (form) {
        var ret = "";
        form.find('input[type=text]').each(function (key, value) {
            if ($(this).val() == "" && ret == "") {
                ret = this;
            }
        });
        if (ret == "") {
            ret = form.find('input[type=text]').last();
        }
        $(ret).focus();
    };

    // If radio button is checked.
    var isChecked = function (form) {
        var ret = false;
        form.find('input[type=radio]').each(function (key, value) {
            var checked = $(this).is(':checked');
            if (checked) {
                ret = true;
            }
        });
        return ret;
    };

    // Check first radio button.
    var checkFirstRadio = function (form) {
        var excludeIds = ['post-package-0'];
        var radio = form.find('input[type=radio]').first();

        var used = $.inArray(radio.attr('id'), excludeIds) > -1;
        if (used) {
            radio.prop('checked', true);
        }
    };

    focusZipcodesearch();
});

/*jslint browser: true, plusplus: true, regexp: true, indent: 4, white:true */
/*global jQuery, Modernizr */
/**
 * This purpose of this file is to implement a accordion
 *
 * This functionality is provided via a jQuery plugin.
 *
 * Example - basic accordion
 *
 * html:
 * 	<div class="accordion">
 * 		<h3 class="accordion-header" data-panel-ref="1">Title 1</h3>
 * 		<div class="accordion-panel" data-panel-id="1">
 * 			Hello world 1
 * 		</div>
 * 		<h3 class="accordion-header" data-panel-ref="2">Title 2</h3>
 * 		<div class="accordion-panel" data-panel-id="2">
 * 			Hello world 2
 * 		</div>
 * 		<h3 class="accordion-header" data-panel-ref="3">Title 3</h3>
 * 		<div class="accordion-panel" data-panel-id="3">
 * 			Hello world 3
 * 		</div>
 * 	</div>
 *
 * javascript:
 * 	$('.selector').accordion();
 *
 */
(function ($) {
	'use strict';

	var defaultOptions = {
		panelButtonSelector: '',
		panelContentSelector: '',

		/**
		 * Data attribute of panel button
		 * @param {String} panelButtonDataAttribute
		 */
		panelButtonDataAttribute: 'data-panel-ref',

		/**
		 * Data attribute of panel content
		 * @param {String} panelContentDataAttribute
		 */
		panelContentDataAttribute: 'data-panel-id',

		/**
		 * Css selector of active element
		 * @param {String} activeClassname
		 */
		activeClassname: 'active',

		/**
		 * Name of the function to execute
		 * @param {String} togglePanel
		 */
		panelButtonAction : 'togglePanel'
	};

	var Accordion = function( options ){
		var openPanelId;
		$.extend(this, defaultOptions, options);

		this.bindElements();

		if ( this.openPanelId ){
			openPanelId = this.openPanelId;
			this.openPanelId = null;
			this.openPanel( openPanelId );
		}
	};

	$.extend( Accordion.prototype, {
		bindElements : function(){
			var $accordionElement = this.$element;

			this.$panelContentElements = $accordionElement.find(this.panelContentSelector + '[' + this.panelContentDataAttribute + ']');
			this.$panelButtonsElements = $accordionElement.find(this.panelButtonSelector + '[' + this.panelButtonDataAttribute + ']');

			this.$panelButtonsElements.on('click touchend', $.proxy(function(e){
				var $buttonElement = $(e.delegateTarget),
					panelId = $buttonElement.attr(this.panelButtonDataAttribute);

				this[ this.panelButtonAction ](panelId);

				if (e.target.tagName === 'a' || e.type === 'touchend'){
					e.preventDefault();
				}
			}, this));
		},

		/**
		 * Open the corresponding panel and then remove the active classes from the $panelContentElements
		 * and $panelContentElements using a filter function to make use of the already matched elements in
		 * the DOM. The :not selector is used to select everything except the current panelId.
		 *
		 * After removal of the active classes, the active class is added to the current $panelContentElements
		 * and $panelButtonsElements using the toggleClass function that determines if the class should be
		 * added or removed depending on the class presence
		 */
		togglePanel : function( panelId ){
			var $panelContentElements = this.$panelContentElements,
				$panelButtonsElements = this.$panelButtonsElements;

			this.closePanels( panelId );

			$panelButtonsElements.filter('[' + this.panelButtonDataAttribute + '="'+ panelId +'"]').toggleClass(this.activeClassname);
			$panelContentElements.filter('[' + this.panelContentDataAttribute + '="'+ panelId +'"]').toggleClass(this.activeClassname);

			this.checkOpenPanelChange();
		},

		openPanel : function( panelId ){
			var $panelContentElements = this.$panelContentElements,
				$panelButtonsElements = this.$panelButtonsElements;

			this.closePanels( panelId );

			$panelButtonsElements
				// mark button as active
				.filter('[' + this.panelButtonDataAttribute + '="'+ panelId +'"]')
				.addClass(this.activeClassname)

				// make sure that radio buttons inside panel button selector are checked
				.find('input[type="radio"]').prop('checked', true);

			// show content bound to panel button
			$panelContentElements.filter('[' + this.panelContentDataAttribute + '="'+ panelId +'"]').addClass(this.activeClassname);

			this.checkOpenPanelChange();
		},

		closePanels : function( excludedPanelId ){
			var $panelContentElements = this.$panelContentElements,
				$panelButtonsElements = this.$panelButtonsElements;

			if ( excludedPanelId != undefined ){
				$panelButtonsElements = $panelButtonsElements.filter(':not([' + this.panelButtonDataAttribute + '="'+ excludedPanelId +'"])');
				$panelContentElements = $panelContentElements.filter(':not([' + this.panelContentDataAttribute + '="'+ excludedPanelId +'"])');

			}

			$panelButtonsElements.removeClass(this.activeClassname);
			$panelContentElements.removeClass(this.activeClassname);
		},

		checkOpenPanelChange : function(){
			var openPanel = this.$panelContentElements.filter('.' + this.activeClassname),
				openPanelId = openPanel.attr(this.panelContentDataAttribute);

			if ( this.openPanelId != openPanelId ){
				this.openPanelId = openPanelId;
				this.$element.trigger('openpanelchange', [openPanelId]);
			}

			if ( this.openPanelId ){
				this.$element.addClass(this.activeClassname);
			} else {
				this.$element.removeClass(this.activeClassname);
			}
		}
	} );

	$.fn.extend({
		accordion: function(options){
			options = $.extend({}, options || {});

			return this.each(function(){
				var $element = $(this),
					accordionInstance = $element.data('accordionInstance');

				if ( !accordionInstance ){
					options.$element = $element;
					accordionInstance = new Accordion(options);
					$element.data('accordionInstance', accordionInstance);
				} else {
					$.each( options, function( option, value ){
						switch(option){
							case 'openPanelId':
								accordionInstance.openPanel( value )
								break;

							case 'togglePanel':
								accordionInstance.togglePanel( value )
								break;
						}
					} );
				}
			});
		}
	})
})(jQuery);

!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Flagship=e():t.Flagship=e()}(window,(function(){return function(t){var e={};function n(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(i,r,function(e){return t[e]}.bind(null,r));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=19)}([function(t,e,n){"use strict";var i=n(8),r=Object.prototype.toString;function o(t){return"[object Array]"===r.call(t)}function a(t){return void 0===t}function s(t){return null!==t&&"object"==typeof t}function u(t){if("[object Object]"!==r.call(t))return!1;var e=Object.getPrototypeOf(t);return null===e||e===Object.prototype}function c(t){return"[object Function]"===r.call(t)}function f(t,e){if(null!=t)if("object"!=typeof t&&(t=[t]),o(t))for(var n=0,i=t.length;n<i;n++)e.call(null,t[n],n,t);else for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.call(null,t[r],r,t)}t.exports={isArray:o,isArrayBuffer:function(t){return"[object ArrayBuffer]"===r.call(t)},isBuffer:function(t){return null!==t&&!a(t)&&null!==t.constructor&&!a(t.constructor)&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)},isFormData:function(t){return"undefined"!=typeof FormData&&t instanceof FormData},isArrayBufferView:function(t){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&t.buffer instanceof ArrayBuffer},isString:function(t){return"string"==typeof t},isNumber:function(t){return"number"==typeof t},isObject:s,isPlainObject:u,isUndefined:a,isDate:function(t){return"[object Date]"===r.call(t)},isFile:function(t){return"[object File]"===r.call(t)},isBlob:function(t){return"[object Blob]"===r.call(t)},isFunction:c,isStream:function(t){return s(t)&&c(t.pipe)},isURLSearchParams:function(t){return"undefined"!=typeof URLSearchParams&&t instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)},forEach:f,merge:function t(){var e={};function n(n,i){u(e[i])&&u(n)?e[i]=t(e[i],n):u(n)?e[i]=t({},n):o(n)?e[i]=n.slice():e[i]=n}for(var i=0,r=arguments.length;i<r;i++)f(arguments[i],n);return e},extend:function(t,e,n){return f(e,(function(e,r){t[r]=n&&"function"==typeof e?i(e,n):e})),t},trim:function(t){return t.replace(/^\s*/,"").replace(/\s*$/,"")},stripBOM:function(t){return 65279===t.charCodeAt(0)&&(t=t.slice(1)),t}}},function(t,e,n){"use strict";(function(t){var i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var r=n(5),o=n(38),a=n(40),s=n(4),u=n(41),c=(n(42),{postFlagshipApi:function(t,e){var n=t.panic,o=t.config,s=t.log,u=t.endpoint,c=t.callback,f=t.params;void 0===e&&(e={headers:{}});var l={},d={};!function(t,e){t.flagshipApi&&t.flagshipApi.includes("/v2/")&&!t.apiKey&&e.fatal('initialization - flagshipApi v2 detected but required setting "apiKey" is missing !')}(o,s);var h=!o.flagshipApi.includes("/v1/"),p=u.includes(o.flagshipApi)?u:o.flagshipApi+u,g=p.includes("/campaigns");d["x-sdk-client"]="js",d["x-sdk-version"]=a.version,o.apiKey&&h&&g&&(d["x-api-key"]=o.apiKey);var v=r.default.CancelToken.source(),m=function(){return r.default.post(p,i(i({},f),l),i(i({},e),{cancelToken:v.token,headers:i(i({},e.headers),d),timeout:g?1e3*o.timeout:void 0})).then((function(t){return n.checkPanicMode(t.data),t}))};return c?c(m,v,o):m()},checkPollingIntervalValue:function(e){switch(typeof e){case"number":return t&&t.env,e>=s.internalConfig.pollingIntervalMinValue?"ok":"underLimit";case"object":return"notSupported";case"undefined":default:return"notSupported"}},checkVisitorContext:function(t,e){var n={};return Object.entries(t).forEach((function(t){var i=t[0],r=t[1];"object"!=typeof r||Array.isArray(r)?Array.isArray(r)?e.warn('Context key "'+i+'" is an array which is not supported. This key will be ignored...'):null==r?e.warn('Context key "'+i+'" is null or undefined which is not supported. This key will be ignored...'):n[i]=r:e.warn('Context key "'+i+'" is an object (json) which is not supported. This key will be ignored...')})),n},logIgnoredAttributesFromObject:function(t,e,n){void 0===n&&(n="");var i=!1;Object.entries(t).forEach((function(t){var r=t[0],o=t[1];i=!0,e.warn('Unknown key "'+r+'" detected (with value="'+o+'"). This key has been ignored... - '+n)})),i||e.debug("No unknown key detected :) - "+n)},checkTimeout:function(t){return"number"==typeof t&&t>0?t:s.default.timeout},checkConfig:function(t,e){var n={},r={},o=[];Object.entries(s.default).forEach((function(t){var e=t[0];return o.push(e)}));var a=Object.keys(u.default);return Object.keys(t).forEach((function(e){var i=t[e];if(o.includes(e))if(null==i)n[e]=s.default[e];else switch(e){case"timeout":n[e]=c.checkTimeout(i);break;default:n[e]=i}else a.includes(e)||(r[e]=i)})),e&&(n.apiKey=e),{cleanConfig:i({},n),ignoredConfig:i({},r)}},checkDecisionApiResponseFormat:function(t,e){return t.data&&t.data.campaigns?t.data:(e.warn("Unknow Decision Api response received or error happened"),null)},checkBucketingApiResponse:function(t,e){var n={id:{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}},type:{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}},variationGroups:{presence:{message:"is missing"},type:{type:"array",message:"is not a array"}}},i=!0,r="",a=o.validate(t,{campaigns:{presence:{message:"is missing"},type:{type:"array",message:"is not a array"}},lastModifiedDate:{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}}});return a?(i=!1,r+=c.generateValidateError(a)):t.campaigns.forEach((function(t,e){var a=o.validate(t,n);a&&(i=!1,r+=c.generateValidateError(a,e))})),i?t:(e.error(r),null)},generateValidateError:function(t,e){var n="";return n+="number"==typeof e?"Element at index="+e+":\n":"Element:\n",Object.keys(t).forEach((function(e){n+='- "'+e+'" '+t[e].map((function(n,i){return i===t[e].length-1?""+n:n+" and "}))+".\n"})),n+="\n"},validateDecisionApiData:function(t,e){var n={id:{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}},variationGroupId:{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}},"variation.id":{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}},"variation.modifications.type":{presence:{message:"is missing"},type:{type:"string",message:"is not a string"}},"variation.modifications.value":{presence:{message:"is missing"}}},i={},r="Decision Api data does not have correct format:\n";return t&&Array.isArray(t)?(t.forEach((function(t,e){var a=o.validate(t,n);a&&(i[e]=a,r+=c.generateValidateError(a,e))})),0===Object.keys(i).length?t:(e.error(r),null)):(Array.isArray(t)||null===t||e.error('validateDecisionApiData - received unexpected decision api data of type "'+typeof t+'"'),null)},isUsingFlagshipApi:function(t,e){switch(t){case"v1":return e.flagshipApi.includes(s.internalConfig.apiV1);case"v2":return e.flagshipApi.includes(s.internalConfig.apiV2);default:return!1}},generatePanicDecisionApiResponse:function(t){return{visitorId:t,campaigns:[],panic:!0}},generateReadyListenerOutput:function(t){return{withError:!!t,error:t}}});e.default=c}).call(this,n(7))},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(6);e.default=i.default},function(t,e,n){"use strict";var i,r="object"==typeof Reflect?Reflect:null,o=r&&"function"==typeof r.apply?r.apply:function(t,e,n){return Function.prototype.apply.call(t,e,n)};i=r&&"function"==typeof r.ownKeys?r.ownKeys:Object.getOwnPropertySymbols?function(t){return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t))}:function(t){return Object.getOwnPropertyNames(t)};var a=Number.isNaN||function(t){return t!=t};function s(){s.init.call(this)}t.exports=s,t.exports.once=function(t,e){return new Promise((function(n,i){function r(){void 0!==o&&t.removeListener("error",o),n([].slice.call(arguments))}var o;"error"!==e&&(o=function(n){t.removeListener(e,r),i(n)},t.once("error",o)),t.once(e,r)}))},s.EventEmitter=s,s.prototype._events=void 0,s.prototype._eventsCount=0,s.prototype._maxListeners=void 0;var u=10;function c(t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t)}function f(t){return void 0===t._maxListeners?s.defaultMaxListeners:t._maxListeners}function l(t,e,n,i){var r,o,a,s;if(c(n),void 0===(o=t._events)?(o=t._events=Object.create(null),t._eventsCount=0):(void 0!==o.newListener&&(t.emit("newListener",e,n.listener?n.listener:n),o=t._events),a=o[e]),void 0===a)a=o[e]=n,++t._eventsCount;else if("function"==typeof a?a=o[e]=i?[n,a]:[a,n]:i?a.unshift(n):a.push(n),(r=f(t))>0&&a.length>r&&!a.warned){a.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(e)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=t,u.type=e,u.count=a.length,s=u,console&&console.warn&&console.warn(s)}return t}function d(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function h(t,e,n){var i={fired:!1,wrapFn:void 0,target:t,type:e,listener:n},r=d.bind(i);return r.listener=n,i.wrapFn=r,r}function p(t,e,n){var i=t._events;if(void 0===i)return[];var r=i[e];return void 0===r?[]:"function"==typeof r?n?[r.listener||r]:[r]:n?function(t){for(var e=new Array(t.length),n=0;n<e.length;++n)e[n]=t[n].listener||t[n];return e}(r):v(r,r.length)}function g(t){var e=this._events;if(void 0!==e){var n=e[t];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function v(t,e){for(var n=new Array(e),i=0;i<e;++i)n[i]=t[i];return n}Object.defineProperty(s,"defaultMaxListeners",{enumerable:!0,get:function(){return u},set:function(t){if("number"!=typeof t||t<0||a(t))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+t+".");u=t}}),s.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},s.prototype.setMaxListeners=function(t){if("number"!=typeof t||t<0||a(t))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+t+".");return this._maxListeners=t,this},s.prototype.getMaxListeners=function(){return f(this)},s.prototype.emit=function(t){for(var e=[],n=1;n<arguments.length;n++)e.push(arguments[n]);var i="error"===t,r=this._events;if(void 0!==r)i=i&&void 0===r.error;else if(!i)return!1;if(i){var a;if(e.length>0&&(a=e[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var u=r[t];if(void 0===u)return!1;if("function"==typeof u)o(u,this,e);else{var c=u.length,f=v(u,c);for(n=0;n<c;++n)o(f[n],this,e)}return!0},s.prototype.addListener=function(t,e){return l(this,t,e,!1)},s.prototype.on=s.prototype.addListener,s.prototype.prependListener=function(t,e){return l(this,t,e,!0)},s.prototype.once=function(t,e){return c(e),this.on(t,h(this,t,e)),this},s.prototype.prependOnceListener=function(t,e){return c(e),this.prependListener(t,h(this,t,e)),this},s.prototype.removeListener=function(t,e){var n,i,r,o,a;if(c(e),void 0===(i=this._events))return this;if(void 0===(n=i[t]))return this;if(n===e||n.listener===e)0==--this._eventsCount?this._events=Object.create(null):(delete i[t],i.removeListener&&this.emit("removeListener",t,n.listener||e));else if("function"!=typeof n){for(r=-1,o=n.length-1;o>=0;o--)if(n[o]===e||n[o].listener===e){a=n[o].listener,r=o;break}if(r<0)return this;0===r?n.shift():function(t,e){for(;e+1<t.length;e++)t[e]=t[e+1];t.pop()}(n,r),1===n.length&&(i[t]=n[0]),void 0!==i.removeListener&&this.emit("removeListener",t,a||e)}return this},s.prototype.off=s.prototype.removeListener,s.prototype.removeAllListeners=function(t){var e,n,i;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[t]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[t]),this;if(0===arguments.length){var r,o=Object.keys(n);for(i=0;i<o.length;++i)"removeListener"!==(r=o[i])&&this.removeAllListeners(r);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(e=n[t]))this.removeListener(t,e);else if(void 0!==e)for(i=e.length-1;i>=0;i--)this.removeListener(t,e[i]);return this},s.prototype.listeners=function(t){return p(this,t,!0)},s.prototype.rawListeners=function(t){return p(this,t,!1)},s.listenerCount=function(t,e){return"function"==typeof t.listenerCount?t.listenerCount(e):g.call(t,e)},s.prototype.listenerCount=g,s.prototype.eventNames=function(){return this._eventsCount>0?i(this._events):[]}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.internalConfig=void 0;e.internalConfig={campaignNormalEndpoint:"@API_URL@@ENV_ID@/campaigns?mode=normal",bucketingEndpoint:"https://cdn.flagship.io/@ENV_ID@/bucketing.json",apiV1:"https://decision-api.flagship.io/v1/",apiV2:"https://decision.flagship.io/v2/",pollingIntervalMinValue:1},e.default={fetchNow:!0,activateNow:!1,enableConsoleLogs:!1,enableClientCache:!0,decisionMode:"API",nodeEnv:"production",flagshipApi:"https://decision-api.flagship.io/v1/",pollingInterval:null,apiKey:null,timeout:2,initialBucketing:null,initialModifications:null,internal:{react:null,reactNative:{httpCallback:null}}}},function(t,e,n){t.exports=n(21)},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i={getLogger:function(t,e){void 0===e&&(e="Flagship SDK");var n=t.enableConsoleLogs,i=t.nodeEnv,r=function(){return"["+(new Date).toISOString().slice(11,-5)+"]"};return{warn:function(t){return n?console.warn(r()+" - "+e+" - "+t):null},error:function(t){return n?console.error(r()+" - "+e+" - "+t):null},info:function(t){return n?console.log(r()+" - "+e+" - "+t):null},fatal:function(t){return n?console.error(r()+" - FATAL - "+e+" - "+t):null},debug:function(t){return i&&"production"!==i&&n?console.log(r()+" - DEBUG - "+e+" - "+t):null}}}};e.FlagshipCommon={createVisitorId:function(){var t=new Date,e=Math.floor(89999*Math.random()+1e4),n=function(t){return 1===t.toString().length?"0"+t:t};return""+t.getFullYear()+n(t.getMonth()+1)+n(t.getDate())+n(t.getHours())+n(t.getMinutes())+e}},e.default=i},function(t,e){var n,i,r=t.exports={};function o(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(t){if(n===setTimeout)return setTimeout(t,0);if((n===o||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:o}catch(t){n=o}try{i="function"==typeof clearTimeout?clearTimeout:a}catch(t){i=a}}();var u,c=[],f=!1,l=-1;function d(){f&&u&&(f=!1,u.length?c=u.concat(c):l=-1,c.length&&h())}function h(){if(!f){var t=s(d);f=!0;for(var e=c.length;e;){for(u=c,c=[];++l<e;)u&&u[l].run();l=-1,e=c.length}u=null,f=!1,function(t){if(i===clearTimeout)return clearTimeout(t);if((i===a||!i)&&clearTimeout)return i=clearTimeout,clearTimeout(t);try{i(t)}catch(e){try{return i.call(null,t)}catch(e){return i.call(this,t)}}}(t)}}function p(t,e){this.fun=t,this.array=e}function g(){}r.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];c.push(new p(t,e)),1!==c.length||f||s(h)},p.prototype.run=function(){this.fun.apply(null,this.array)},r.title="browser",r.browser=!0,r.env={},r.argv=[],r.version="",r.versions={},r.on=g,r.addListener=g,r.once=g,r.off=g,r.removeListener=g,r.removeAllListeners=g,r.emit=g,r.prependListener=g,r.prependOnceListener=g,r.listeners=function(t){return[]},r.binding=function(t){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(t){throw new Error("process.chdir is not supported")},r.umask=function(){return 0}},function(t,e,n){"use strict";t.exports=function(t,e){return function(){for(var n=new Array(arguments.length),i=0;i<n.length;i++)n[i]=arguments[i];return t.apply(e,n)}}},function(t,e,n){"use strict";var i=n(0);function r(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}t.exports=function(t,e,n){if(!e)return t;var o;if(n)o=n(e);else if(i.isURLSearchParams(e))o=e.toString();else{var a=[];i.forEach(e,(function(t,e){null!=t&&(i.isArray(t)?e+="[]":t=[t],i.forEach(t,(function(t){i.isDate(t)?t=t.toISOString():i.isObject(t)&&(t=JSON.stringify(t)),a.push(r(e)+"="+r(t))})))})),o=a.join("&")}if(o){var s=t.indexOf("#");-1!==s&&(t=t.slice(0,s)),t+=(-1===t.indexOf("?")?"?":"&")+o}return t}},function(t,e,n){"use strict";t.exports=function(t){return!(!t||!t.__CANCEL__)}},function(t,e,n){"use strict";(function(e){var i=n(0),r=n(26),o={"Content-Type":"application/x-www-form-urlencoded"};function a(t,e){!i.isUndefined(t)&&i.isUndefined(t["Content-Type"])&&(t["Content-Type"]=e)}var s,u={adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==e&&"[object process]"===Object.prototype.toString.call(e))&&(s=n(12)),s),transformRequest:[function(t,e){return r(e,"Accept"),r(e,"Content-Type"),i.isFormData(t)||i.isArrayBuffer(t)||i.isBuffer(t)||i.isStream(t)||i.isFile(t)||i.isBlob(t)?t:i.isArrayBufferView(t)?t.buffer:i.isURLSearchParams(t)?(a(e,"application/x-www-form-urlencoded;charset=utf-8"),t.toString()):i.isObject(t)?(a(e,"application/json;charset=utf-8"),JSON.stringify(t)):t}],transformResponse:[function(t){if("string"==typeof t)try{t=JSON.parse(t)}catch(t){}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(t){return t>=200&&t<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},i.forEach(["delete","get","head"],(function(t){u.headers[t]={}})),i.forEach(["post","put","patch"],(function(t){u.headers[t]=i.merge(o)})),t.exports=u}).call(this,n(7))},function(t,e,n){"use strict";var i=n(0),r=n(27),o=n(29),a=n(9),s=n(30),u=n(33),c=n(34),f=n(13);t.exports=function(t){return new Promise((function(e,n){var l=t.data,d=t.headers;i.isFormData(l)&&delete d["Content-Type"];var h=new XMLHttpRequest;if(t.auth){var p=t.auth.username||"",g=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";d.Authorization="Basic "+btoa(p+":"+g)}var v=s(t.baseURL,t.url);if(h.open(t.method.toUpperCase(),a(v,t.params,t.paramsSerializer),!0),h.timeout=t.timeout,h.onreadystatechange=function(){if(h&&4===h.readyState&&(0!==h.status||h.responseURL&&0===h.responseURL.indexOf("file:"))){var i="getAllResponseHeaders"in h?u(h.getAllResponseHeaders()):null,o={data:t.responseType&&"text"!==t.responseType?h.response:h.responseText,status:h.status,statusText:h.statusText,headers:i,config:t,request:h};r(e,n,o),h=null}},h.onabort=function(){h&&(n(f("Request aborted",t,"ECONNABORTED",h)),h=null)},h.onerror=function(){n(f("Network Error",t,null,h)),h=null},h.ontimeout=function(){var e="timeout of "+t.timeout+"ms exceeded";t.timeoutErrorMessage&&(e=t.timeoutErrorMessage),n(f(e,t,"ECONNABORTED",h)),h=null},i.isStandardBrowserEnv()){var m=(t.withCredentials||c(v))&&t.xsrfCookieName?o.read(t.xsrfCookieName):void 0;m&&(d[t.xsrfHeaderName]=m)}if("setRequestHeader"in h&&i.forEach(d,(function(t,e){void 0===l&&"content-type"===e.toLowerCase()?delete d[e]:h.setRequestHeader(e,t)})),i.isUndefined(t.withCredentials)||(h.withCredentials=!!t.withCredentials),t.responseType)try{h.responseType=t.responseType}catch(e){if("json"!==t.responseType)throw e}"function"==typeof t.onDownloadProgress&&h.addEventListener("progress",t.onDownloadProgress),"function"==typeof t.onUploadProgress&&h.upload&&h.upload.addEventListener("progress",t.onUploadProgress),t.cancelToken&&t.cancelToken.promise.then((function(t){h&&(h.abort(),n(t),h=null)})),l||(l=null),h.send(l)}))}},function(t,e,n){"use strict";var i=n(28);t.exports=function(t,e,n,r,o){var a=new Error(t);return i(a,e,n,r,o)}},function(t,e,n){"use strict";var i=n(0);t.exports=function(t,e){e=e||{};var n={},r=["url","method","data"],o=["headers","auth","proxy","params"],a=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],s=["validateStatus"];function u(t,e){return i.isPlainObject(t)&&i.isPlainObject(e)?i.merge(t,e):i.isPlainObject(e)?i.merge({},e):i.isArray(e)?e.slice():e}function c(r){i.isUndefined(e[r])?i.isUndefined(t[r])||(n[r]=u(void 0,t[r])):n[r]=u(t[r],e[r])}i.forEach(r,(function(t){i.isUndefined(e[t])||(n[t]=u(void 0,e[t]))})),i.forEach(o,c),i.forEach(a,(function(r){i.isUndefined(e[r])?i.isUndefined(t[r])||(n[r]=u(void 0,t[r])):n[r]=u(void 0,e[r])})),i.forEach(s,(function(i){i in e?n[i]=u(t[i],e[i]):i in t&&(n[i]=u(void 0,t[i]))}));var f=r.concat(o).concat(a).concat(s),l=Object.keys(t).concat(Object.keys(e)).filter((function(t){return-1===f.indexOf(t)}));return i.forEach(l,c),n}},function(t,e,n){"use strict";function i(t){this.message=t}i.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},i.prototype.__CANCEL__=!0,t.exports=i},function(t,e){t.exports=function(){throw new Error("define cannot be used indirect")}},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){"use strict";(function(t){
/*!
 * The buffer module from node.js, for the browser.
 *
 * @author   Feross Aboukhadijeh <http://feross.org>
 * @license  MIT
 */
var i=n(47),r=n(48),o=n(49);function a(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(t,e){if(a()<e)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e)).__proto__=u.prototype:(null===t&&(t=new u(e)),t.length=e),t}function u(t,e,n){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(t,e,n);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return l(this,t)}return c(this,t,e,n)}function c(t,e,n,i){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?function(t,e,n,i){if(e.byteLength,n<0||e.byteLength<n)throw new RangeError("'offset' is out of bounds");if(e.byteLength<n+(i||0))throw new RangeError("'length' is out of bounds");e=void 0===n&&void 0===i?new Uint8Array(e):void 0===i?new Uint8Array(e,n):new Uint8Array(e,n,i);u.TYPED_ARRAY_SUPPORT?(t=e).__proto__=u.prototype:t=d(t,e);return t}(t,e,n,i):"string"==typeof e?function(t,e,n){"string"==typeof n&&""!==n||(n="utf8");if(!u.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var i=0|p(e,n),r=(t=s(t,i)).write(e,n);r!==i&&(t=t.slice(0,r));return t}(t,e,n):function(t,e){if(u.isBuffer(e)){var n=0|h(e.length);return 0===(t=s(t,n)).length||e.copy(t,0,0,n),t}if(e){if("undefined"!=typeof ArrayBuffer&&e.buffer instanceof ArrayBuffer||"length"in e)return"number"!=typeof e.length||(i=e.length)!=i?s(t,0):d(t,e);if("Buffer"===e.type&&o(e.data))return d(t,e.data)}var i;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(t,e)}function f(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function l(t,e){if(f(e),t=s(t,e<0?0:0|h(e)),!u.TYPED_ARRAY_SUPPORT)for(var n=0;n<e;++n)t[n]=0;return t}function d(t,e){var n=e.length<0?0:0|h(e.length);t=s(t,n);for(var i=0;i<n;i+=1)t[i]=255&e[i];return t}function h(t){if(t>=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|t}function p(t,e){if(u.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var i=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return V(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return F(t).length;default:if(i)return V(t).length;e=(""+e).toLowerCase(),i=!0}}function g(t,e,n){var i=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return S(this,e,n);case"utf8":case"utf-8":return M(this,e,n);case"ascii":return C(this,e,n);case"latin1":case"binary":return P(this,e,n);case"base64":return k(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,n);default:if(i)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),i=!0}}function v(t,e,n){var i=t[e];t[e]=t[n],t[n]=i}function m(t,e,n,i,r){if(0===t.length)return-1;if("string"==typeof n?(i=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=r?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(r)return-1;n=t.length-1}else if(n<0){if(!r)return-1;n=0}if("string"==typeof e&&(e=u.from(e,i)),u.isBuffer(e))return 0===e.length?-1:y(t,e,n,i,r);if("number"==typeof e)return e&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?r?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):y(t,[e],n,i,r);throw new TypeError("val must be string, number or Buffer")}function y(t,e,n,i,r){var o,a=1,s=t.length,u=e.length;if(void 0!==i&&("ucs2"===(i=String(i).toLowerCase())||"ucs-2"===i||"utf16le"===i||"utf-16le"===i)){if(t.length<2||e.length<2)return-1;a=2,s/=2,u/=2,n/=2}function c(t,e){return 1===a?t[e]:t.readUInt16BE(e*a)}if(r){var f=-1;for(o=n;o<s;o++)if(c(t,o)===c(e,-1===f?0:o-f)){if(-1===f&&(f=o),o-f+1===u)return f*a}else-1!==f&&(o-=o-f),f=-1}else for(n+u>s&&(n=s-u),o=n;o>=0;o--){for(var l=!0,d=0;d<u;d++)if(c(t,o+d)!==c(e,d)){l=!1;break}if(l)return o}return-1}function b(t,e,n,i){n=Number(n)||0;var r=t.length-n;i?(i=Number(i))>r&&(i=r):i=r;var o=e.length;if(o%2!=0)throw new TypeError("Invalid hex string");i>o/2&&(i=o/2);for(var a=0;a<i;++a){var s=parseInt(e.substr(2*a,2),16);if(isNaN(s))return a;t[n+a]=s}return a}function w(t,e,n,i){return z(V(e,t.length-n),t,n,i)}function A(t,e,n,i){return z(function(t){for(var e=[],n=0;n<t.length;++n)e.push(255&t.charCodeAt(n));return e}(e),t,n,i)}function E(t,e,n,i){return A(t,e,n,i)}function I(t,e,n,i){return z(F(e),t,n,i)}function x(t,e,n,i){return z(function(t,e){for(var n,i,r,o=[],a=0;a<t.length&&!((e-=2)<0);++a)n=t.charCodeAt(a),i=n>>8,r=n%256,o.push(r),o.push(i);return o}(e,t.length-n),t,n,i)}function k(t,e,n){return 0===e&&n===t.length?i.fromByteArray(t):i.fromByteArray(t.slice(e,n))}function M(t,e,n){n=Math.min(t.length,n);for(var i=[],r=e;r<n;){var o,a,s,u,c=t[r],f=null,l=c>239?4:c>223?3:c>191?2:1;if(r+l<=n)switch(l){case 1:c<128&&(f=c);break;case 2:128==(192&(o=t[r+1]))&&(u=(31&c)<<6|63&o)>127&&(f=u);break;case 3:o=t[r+1],a=t[r+2],128==(192&o)&&128==(192&a)&&(u=(15&c)<<12|(63&o)<<6|63&a)>2047&&(u<55296||u>57343)&&(f=u);break;case 4:o=t[r+1],a=t[r+2],s=t[r+3],128==(192&o)&&128==(192&a)&&128==(192&s)&&(u=(15&c)<<18|(63&o)<<12|(63&a)<<6|63&s)>65535&&u<1114112&&(f=u)}null===f?(f=65533,l=1):f>65535&&(f-=65536,i.push(f>>>10&1023|55296),f=56320|1023&f),i.push(f),r+=l}return function(t){var e=t.length;if(e<=4096)return String.fromCharCode.apply(String,t);var n="",i=0;for(;i<e;)n+=String.fromCharCode.apply(String,t.slice(i,i+=4096));return n}(i)}e.Buffer=u,e.SlowBuffer=function(t){+t!=t&&(t=0);return u.alloc(+t)},e.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==t.TYPED_ARRAY_SUPPORT?t.TYPED_ARRAY_SUPPORT:function(){try{var t=new Uint8Array(1);return t.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===t.foo()&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(t){return!1}}(),e.kMaxLength=a(),u.poolSize=8192,u._augment=function(t){return t.__proto__=u.prototype,t},u.from=function(t,e,n){return c(null,t,e,n)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(t,e,n){return function(t,e,n,i){return f(e),e<=0?s(t,e):void 0!==n?"string"==typeof i?s(t,e).fill(n,i):s(t,e).fill(n):s(t,e)}(null,t,e,n)},u.allocUnsafe=function(t){return l(null,t)},u.allocUnsafeSlow=function(t){return l(null,t)},u.isBuffer=function(t){return!(null==t||!t._isBuffer)},u.compare=function(t,e){if(!u.isBuffer(t)||!u.isBuffer(e))throw new TypeError("Arguments must be Buffers");if(t===e)return 0;for(var n=t.length,i=e.length,r=0,o=Math.min(n,i);r<o;++r)if(t[r]!==e[r]){n=t[r],i=e[r];break}return n<i?-1:i<n?1:0},u.isEncoding=function(t){switch(String(t).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(t,e){if(!o(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return u.alloc(0);var n;if(void 0===e)for(e=0,n=0;n<t.length;++n)e+=t[n].length;var i=u.allocUnsafe(e),r=0;for(n=0;n<t.length;++n){var a=t[n];if(!u.isBuffer(a))throw new TypeError('"list" argument must be an Array of Buffers');a.copy(i,r),r+=a.length}return i},u.byteLength=p,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var t=this.length;if(t%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var e=0;e<t;e+=2)v(this,e,e+1);return this},u.prototype.swap32=function(){var t=this.length;if(t%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var e=0;e<t;e+=4)v(this,e,e+3),v(this,e+1,e+2);return this},u.prototype.swap64=function(){var t=this.length;if(t%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var e=0;e<t;e+=8)v(this,e,e+7),v(this,e+1,e+6),v(this,e+2,e+5),v(this,e+3,e+4);return this},u.prototype.toString=function(){var t=0|this.length;return 0===t?"":0===arguments.length?M(this,0,t):g.apply(this,arguments)},u.prototype.equals=function(t){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===u.compare(this,t)},u.prototype.inspect=function(){var t="",n=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(t+=" ... ")),"<Buffer "+t+">"},u.prototype.compare=function(t,e,n,i,r){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===i&&(i=0),void 0===r&&(r=this.length),e<0||n>t.length||i<0||r>this.length)throw new RangeError("out of range index");if(i>=r&&e>=n)return 0;if(i>=r)return-1;if(e>=n)return 1;if(this===t)return 0;for(var o=(r>>>=0)-(i>>>=0),a=(n>>>=0)-(e>>>=0),s=Math.min(o,a),c=this.slice(i,r),f=t.slice(e,n),l=0;l<s;++l)if(c[l]!==f[l]){o=c[l],a=f[l];break}return o<a?-1:a<o?1:0},u.prototype.includes=function(t,e,n){return-1!==this.indexOf(t,e,n)},u.prototype.indexOf=function(t,e,n){return m(this,t,e,n,!0)},u.prototype.lastIndexOf=function(t,e,n){return m(this,t,e,n,!1)},u.prototype.write=function(t,e,n,i){if(void 0===e)i="utf8",n=this.length,e=0;else if(void 0===n&&"string"==typeof e)i=e,n=this.length,e=0;else{if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e|=0,isFinite(n)?(n|=0,void 0===i&&(i="utf8")):(i=n,n=void 0)}var r=this.length-e;if((void 0===n||n>r)&&(n=r),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");i||(i="utf8");for(var o=!1;;)switch(i){case"hex":return b(this,t,e,n);case"utf8":case"utf-8":return w(this,t,e,n);case"ascii":return A(this,t,e,n);case"latin1":case"binary":return E(this,t,e,n);case"base64":return I(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,t,e,n);default:if(o)throw new TypeError("Unknown encoding: "+i);i=(""+i).toLowerCase(),o=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function C(t,e,n){var i="";n=Math.min(t.length,n);for(var r=e;r<n;++r)i+=String.fromCharCode(127&t[r]);return i}function P(t,e,n){var i="";n=Math.min(t.length,n);for(var r=e;r<n;++r)i+=String.fromCharCode(t[r]);return i}function S(t,e,n){var i=t.length;(!e||e<0)&&(e=0),(!n||n<0||n>i)&&(n=i);for(var r="",o=e;o<n;++o)r+=U(t[o]);return r}function _(t,e,n){for(var i=t.slice(e,n),r="",o=0;o<i.length;o+=2)r+=String.fromCharCode(i[o]+256*i[o+1]);return r}function O(t,e,n){if(t%1!=0||t<0)throw new RangeError("offset is not uint");if(t+e>n)throw new RangeError("Trying to access beyond buffer length")}function T(t,e,n,i,r,o){if(!u.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>r||e<o)throw new RangeError('"value" argument is out of bounds');if(n+i>t.length)throw new RangeError("Index out of range")}function R(t,e,n,i){e<0&&(e=65535+e+1);for(var r=0,o=Math.min(t.length-n,2);r<o;++r)t[n+r]=(e&255<<8*(i?r:1-r))>>>8*(i?r:1-r)}function j(t,e,n,i){e<0&&(e=4294967295+e+1);for(var r=0,o=Math.min(t.length-n,4);r<o;++r)t[n+r]=e>>>8*(i?r:3-r)&255}function L(t,e,n,i,r,o){if(n+i>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function N(t,e,n,i,o){return o||L(t,0,n,4),r.write(t,e,n,i,23,4),n+4}function D(t,e,n,i,o){return o||L(t,0,n,8),r.write(t,e,n,i,52,8),n+8}u.prototype.slice=function(t,e){var n,i=this.length;if((t=~~t)<0?(t+=i)<0&&(t=0):t>i&&(t=i),(e=void 0===e?i:~~e)<0?(e+=i)<0&&(e=0):e>i&&(e=i),e<t&&(e=t),u.TYPED_ARRAY_SUPPORT)(n=this.subarray(t,e)).__proto__=u.prototype;else{var r=e-t;n=new u(r,void 0);for(var o=0;o<r;++o)n[o]=this[o+t]}return n},u.prototype.readUIntLE=function(t,e,n){t|=0,e|=0,n||O(t,e,this.length);for(var i=this[t],r=1,o=0;++o<e&&(r*=256);)i+=this[t+o]*r;return i},u.prototype.readUIntBE=function(t,e,n){t|=0,e|=0,n||O(t,e,this.length);for(var i=this[t+--e],r=1;e>0&&(r*=256);)i+=this[t+--e]*r;return i},u.prototype.readUInt8=function(t,e){return e||O(t,1,this.length),this[t]},u.prototype.readUInt16LE=function(t,e){return e||O(t,2,this.length),this[t]|this[t+1]<<8},u.prototype.readUInt16BE=function(t,e){return e||O(t,2,this.length),this[t]<<8|this[t+1]},u.prototype.readUInt32LE=function(t,e){return e||O(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},u.prototype.readUInt32BE=function(t,e){return e||O(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},u.prototype.readIntLE=function(t,e,n){t|=0,e|=0,n||O(t,e,this.length);for(var i=this[t],r=1,o=0;++o<e&&(r*=256);)i+=this[t+o]*r;return i>=(r*=128)&&(i-=Math.pow(2,8*e)),i},u.prototype.readIntBE=function(t,e,n){t|=0,e|=0,n||O(t,e,this.length);for(var i=e,r=1,o=this[t+--i];i>0&&(r*=256);)o+=this[t+--i]*r;return o>=(r*=128)&&(o-=Math.pow(2,8*e)),o},u.prototype.readInt8=function(t,e){return e||O(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},u.prototype.readInt16LE=function(t,e){e||O(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(t,e){e||O(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(t,e){return e||O(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},u.prototype.readInt32BE=function(t,e){return e||O(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},u.prototype.readFloatLE=function(t,e){return e||O(t,4,this.length),r.read(this,t,!0,23,4)},u.prototype.readFloatBE=function(t,e){return e||O(t,4,this.length),r.read(this,t,!1,23,4)},u.prototype.readDoubleLE=function(t,e){return e||O(t,8,this.length),r.read(this,t,!0,52,8)},u.prototype.readDoubleBE=function(t,e){return e||O(t,8,this.length),r.read(this,t,!1,52,8)},u.prototype.writeUIntLE=function(t,e,n,i){(t=+t,e|=0,n|=0,i)||T(this,t,e,n,Math.pow(2,8*n)-1,0);var r=1,o=0;for(this[e]=255&t;++o<n&&(r*=256);)this[e+o]=t/r&255;return e+n},u.prototype.writeUIntBE=function(t,e,n,i){(t=+t,e|=0,n|=0,i)||T(this,t,e,n,Math.pow(2,8*n)-1,0);var r=n-1,o=1;for(this[e+r]=255&t;--r>=0&&(o*=256);)this[e+r]=t/o&255;return e+n},u.prototype.writeUInt8=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,1,255,0),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},u.prototype.writeUInt16LE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):R(this,t,e,!0),e+2},u.prototype.writeUInt16BE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):R(this,t,e,!1),e+2},u.prototype.writeUInt32LE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):j(this,t,e,!0),e+4},u.prototype.writeUInt32BE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):j(this,t,e,!1),e+4},u.prototype.writeIntLE=function(t,e,n,i){if(t=+t,e|=0,!i){var r=Math.pow(2,8*n-1);T(this,t,e,n,r-1,-r)}var o=0,a=1,s=0;for(this[e]=255&t;++o<n&&(a*=256);)t<0&&0===s&&0!==this[e+o-1]&&(s=1),this[e+o]=(t/a>>0)-s&255;return e+n},u.prototype.writeIntBE=function(t,e,n,i){if(t=+t,e|=0,!i){var r=Math.pow(2,8*n-1);T(this,t,e,n,r-1,-r)}var o=n-1,a=1,s=0;for(this[e+o]=255&t;--o>=0&&(a*=256);)t<0&&0===s&&0!==this[e+o+1]&&(s=1),this[e+o]=(t/a>>0)-s&255;return e+n},u.prototype.writeInt8=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,1,127,-128),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},u.prototype.writeInt16LE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):R(this,t,e,!0),e+2},u.prototype.writeInt16BE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):R(this,t,e,!1),e+2},u.prototype.writeInt32LE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):j(this,t,e,!0),e+4},u.prototype.writeInt32BE=function(t,e,n){return t=+t,e|=0,n||T(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):j(this,t,e,!1),e+4},u.prototype.writeFloatLE=function(t,e,n){return N(this,t,e,!0,n)},u.prototype.writeFloatBE=function(t,e,n){return N(this,t,e,!1,n)},u.prototype.writeDoubleLE=function(t,e,n){return D(this,t,e,!0,n)},u.prototype.writeDoubleBE=function(t,e,n){return D(this,t,e,!1,n)},u.prototype.copy=function(t,e,n,i){if(n||(n=0),i||0===i||(i=this.length),e>=t.length&&(e=t.length),e||(e=0),i>0&&i<n&&(i=n),i===n)return 0;if(0===t.length||0===this.length)return 0;if(e<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length),t.length-e<i-n&&(i=t.length-e+n);var r,o=i-n;if(this===t&&n<e&&e<i)for(r=o-1;r>=0;--r)t[r+e]=this[r+n];else if(o<1e3||!u.TYPED_ARRAY_SUPPORT)for(r=0;r<o;++r)t[r+e]=this[r+n];else Uint8Array.prototype.set.call(t,this.subarray(n,n+o),e);return o},u.prototype.fill=function(t,e,n,i){if("string"==typeof t){if("string"==typeof e?(i=e,e=0,n=this.length):"string"==typeof n&&(i=n,n=this.length),1===t.length){var r=t.charCodeAt(0);r<256&&(t=r)}if(void 0!==i&&"string"!=typeof i)throw new TypeError("encoding must be a string");if("string"==typeof i&&!u.isEncoding(i))throw new TypeError("Unknown encoding: "+i)}else"number"==typeof t&&(t&=255);if(e<0||this.length<e||this.length<n)throw new RangeError("Out of range index");if(n<=e)return this;var o;if(e>>>=0,n=void 0===n?this.length:n>>>0,t||(t=0),"number"==typeof t)for(o=e;o<n;++o)this[o]=t;else{var a=u.isBuffer(t)?t:V(new u(t,i).toString()),s=a.length;for(o=0;o<n-e;++o)this[o+e]=a[o%s]}return this};var B=/[^+\/0-9A-Za-z-_]/g;function U(t){return t<16?"0"+t.toString(16):t.toString(16)}function V(t,e){var n;e=e||1/0;for(var i=t.length,r=null,o=[],a=0;a<i;++a){if((n=t.charCodeAt(a))>55295&&n<57344){if(!r){if(n>56319){(e-=3)>-1&&o.push(239,191,189);continue}if(a+1===i){(e-=3)>-1&&o.push(239,191,189);continue}r=n;continue}if(n<56320){(e-=3)>-1&&o.push(239,191,189),r=n;continue}n=65536+(r-55296<<10|n-56320)}else r&&(e-=3)>-1&&o.push(239,191,189);if(r=null,n<128){if((e-=1)<0)break;o.push(n)}else if(n<2048){if((e-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function F(t){return i.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(B,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function z(t,e,n,i){for(var r=0;r<i&&!(r+n>=e.length||r>=t.length);++r)e[r+n]=t[r];return r}}).call(this,n(17))},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(20);var r={start:function(t,e,n){return"object"!=typeof e||null===e||Array.isArray(e)?new i.default(t,e,n):function(t,e){return new i.default(t,void 0,e)}(t,e)}};e.default=r},function(t,e,n){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),o=n(4),a=n(1),s=n(2),u=n(43),c=n(44),f=n(50),l=n(51),d=n(52),h=function(){function t(t,e,n){void 0===n&&(n={});var c=a.default.checkConfig(n,e),h=c.cleanConfig,p=c.ignoredConfig;this.config=i(i({},o.default),h),this.log=s.default.getLogger(this.config),this.eventEmitter=new r.EventEmitter,this.bucket=null,this.panic=new f.default(this.config),this.envId=t,this.cacheManager=null,this.config.enableClientCache&&l.default.isClient()&&(this.cacheManager=d.default),e?this.config&&this.config.apiKey&&a.default.isUsingFlagshipApi("v1",this.config)&&(this.config.flagshipApi=o.internalConfig.apiV2,this.log.debug("apiKey detected, forcing the use of Flagship api V2")):this.log.warn('WARNING: "start" function signature will change in the next major release. "start(envId, settings)" will be "start(envId, apiKey, settings)", please make this change ASAP!'),h&&this.log.debug("Custom flagship SDK config attribute(s) detected"),"Bucketing"===this.config.decisionMode&&(this.bucket=new u.default(this.envId,this.config,this.panic),this.config.fetchNow&&this.startBucketingPolling()),a.default.logIgnoredAttributesFromObject(p,this.log,"custom flagship SDK config"),n.timeout&&n.timeout!==this.config.timeout&&this.log.warn('"timeout" setting is incorrect (value specified =>"'+n.timeout+'"). The default value (='+this.config.timeout+" seconds) has been set instead.")}return t.prototype.newVisitor=function(t,e,n){var r=this;void 0===t&&(t=null),void 0===n&&(n={});var o=i(i({},{isAuthenticated:null}),n).isAuthenticated,s=new c.default(this.envId,t,this.panic,this.config,{bucket:this.bucket,context:e,isAuthenticated:o,cacheManager:this.cacheManager}),u={API:{newVisitorInfo:'new visitor (id="'+s.id+'") calling decision API for initialization (waiting to be ready...)',modificationSuccess:'new visitor (id="'+s.id+'") decision API finished (ready !)',modificationFailed:function(t){return'new visitor (id="'+s.id+'") decision API failed during initialization with error "'+t+'"'}},Bucketing:{newVisitorInfo:'new visitor (id="'+s.id+'") waiting for existing bucketing data (waiting to be ready...)',modificationSuccess:'new visitor (id="'+s.id+'") (ready !)'}};this.log.info('Creating new visitor (id="'+s.id+'")');var f=!1;return this.config.fetchNow||this.config.activateNow?(this.log.info(u[this.config.decisionMode].newVisitorInfo),s.getAllModifications(this.config.activateNow,{force:!0}).then((function(){var t=function(){r.log.info(u[r.config.decisionMode].modificationSuccess),s.callEventEndpoint(),s.emit("ready",a.default.generateReadyListenerOutput())},e=function(e){f||(f=!0,e?t():s.synchronizeModifications(r.config.activateNow).then((function(){return t()})))};"Bucketing"===r.config.decisionMode&&r.config.fetchNow&&!r.bucket.data?(r.eventEmitter.once("bucketPollingSuccess",(function(){return e(!1)})),r.eventEmitter.once("bucketPollingFailed",(function(){return e(!0)}))):t()})).catch((function(t){"Bucketing"!==r.config.decisionMode&&r.log.fatal(u[r.config.decisionMode].modificationFailed(t)),s.emit("ready",a.default.generateReadyListenerOutput(t))}))):s.once("newListener",(function(t,e){"ready"===t&&e(a.default.generateReadyListenerOutput())})),s},t.prototype.updateVisitor=function(t,e){var n={context:t.context,isAuthenticated:t.isAuthenticated},r=i(i({},n),e),o=r.context,s=r.isAuthenticated;this.log.debug('updateVisitor - updating visitor (id="'+t.id+'")');var u=new c.default(this.envId,t.id,this.panic,this.config,{bucket:this.bucket,previousVisitorInstance:t,context:o,isAuthenticated:s,cacheManager:this.cacheManager});return l.default.deepCompare(t.context,o)&&null!==u.fetchedModifications||!this.config.fetchNow&&!this.config.activateNow?u.once("newListener",(function(t,e){"ready"===t&&e(a.default.generateReadyListenerOutput())})):(this.log.debug('updateVisitor - visitor(id="'+t.id+'") does not have modifications or context has changed + (fetchNow='+this.config.fetchNow+" OR/AND activateNow="+this.config.activateNow+") detected, trigger a synchronize..."),u.synchronizeModifications(this.config.activateNow).then((function(){u.emit("ready",a.default.generateReadyListenerOutput())})).catch((function(t){u.emit("ready",a.default.generateReadyListenerOutput(t))}))),u},t.prototype.startBucketingPolling=function(){var t=this;return null===this.bucket||this.bucket.isPollingRunning?null!==this.bucket&&this.bucket.isPollingRunning?(this.log.warn('startBucketingPolling - bucket already polling with interval set to "'+this.config.pollingInterval+'" second(s).'),{success:!1,reason:'startBucketingPolling - bucket already polling with interval set to "'+this.config.pollingInterval+'" second(s).'}):(this.log.error('startBucketingPolling - bucket not initialized, make sure "decisionMode" is set to "Bucketing"'),{success:!1,reason:'startBucketingPolling - bucket not initialized, make sure "decisionMode" is set to "Bucketing"'}):(this.bucket.startPolling(),this.bucket.on("launched",(function(e){var n=e.status;t.eventEmitter.emit("bucketPollingSuccess",{status:n,payload:t.bucket.data})})),this.bucket.on("error",(function(e){t.eventEmitter.emit("bucketPollingFailed",e)})),{success:!0})},t.prototype.stopBucketingPolling=function(){return null!==this.bucket&&this.bucket.isPollingRunning?(this.bucket.stopPolling(),this.log.info("stopBucketingPolling - bucketing is stopped"),{success:!0}):(this.log.info("stopBucketingPolling - bucketing is already stopped"),{success:!1,reason:"stopBucketingPolling - bucketing is already stopped"})},t}();e.default=h},function(t,e,n){"use strict";var i=n(0),r=n(8),o=n(22),a=n(14);function s(t){var e=new o(t),n=r(o.prototype.request,e);return i.extend(n,o.prototype,e),i.extend(n,e),n}var u=s(n(11));u.Axios=o,u.create=function(t){return s(a(u.defaults,t))},u.Cancel=n(15),u.CancelToken=n(35),u.isCancel=n(10),u.all=function(t){return Promise.all(t)},u.spread=n(36),u.isAxiosError=n(37),t.exports=u,t.exports.default=u},function(t,e,n){"use strict";var i=n(0),r=n(9),o=n(23),a=n(24),s=n(14);function u(t){this.defaults=t,this.interceptors={request:new o,response:new o}}u.prototype.request=function(t){"string"==typeof t?(t=arguments[1]||{}).url=arguments[0]:t=t||{},(t=s(this.defaults,t)).method?t.method=t.method.toLowerCase():this.defaults.method?t.method=this.defaults.method.toLowerCase():t.method="get";var e=[a,void 0],n=Promise.resolve(t);for(this.interceptors.request.forEach((function(t){e.unshift(t.fulfilled,t.rejected)})),this.interceptors.response.forEach((function(t){e.push(t.fulfilled,t.rejected)}));e.length;)n=n.then(e.shift(),e.shift());return n},u.prototype.getUri=function(t){return t=s(this.defaults,t),r(t.url,t.params,t.paramsSerializer).replace(/^\?/,"")},i.forEach(["delete","get","head","options"],(function(t){u.prototype[t]=function(e,n){return this.request(s(n||{},{method:t,url:e,data:(n||{}).data}))}})),i.forEach(["post","put","patch"],(function(t){u.prototype[t]=function(e,n,i){return this.request(s(i||{},{method:t,url:e,data:n}))}})),t.exports=u},function(t,e,n){"use strict";var i=n(0);function r(){this.handlers=[]}r.prototype.use=function(t,e){return this.handlers.push({fulfilled:t,rejected:e}),this.handlers.length-1},r.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)},r.prototype.forEach=function(t){i.forEach(this.handlers,(function(e){null!==e&&t(e)}))},t.exports=r},function(t,e,n){"use strict";var i=n(0),r=n(25),o=n(10),a=n(11);function s(t){t.cancelToken&&t.cancelToken.throwIfRequested()}t.exports=function(t){return s(t),t.headers=t.headers||{},t.data=r(t.data,t.headers,t.transformRequest),t.headers=i.merge(t.headers.common||{},t.headers[t.method]||{},t.headers),i.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete t.headers[e]})),(t.adapter||a.adapter)(t).then((function(e){return s(t),e.data=r(e.data,e.headers,t.transformResponse),e}),(function(e){return o(e)||(s(t),e&&e.response&&(e.response.data=r(e.response.data,e.response.headers,t.transformResponse))),Promise.reject(e)}))}},function(t,e,n){"use strict";var i=n(0);t.exports=function(t,e,n){return i.forEach(n,(function(n){t=n(t,e)})),t}},function(t,e,n){"use strict";var i=n(0);t.exports=function(t,e){i.forEach(t,(function(n,i){i!==e&&i.toUpperCase()===e.toUpperCase()&&(t[e]=n,delete t[i])}))}},function(t,e,n){"use strict";var i=n(13);t.exports=function(t,e,n){var r=n.config.validateStatus;n.status&&r&&!r(n.status)?e(i("Request failed with status code "+n.status,n.config,null,n.request,n)):t(n)}},function(t,e,n){"use strict";t.exports=function(t,e,n,i,r){return t.config=e,n&&(t.code=n),t.request=i,t.response=r,t.isAxiosError=!0,t.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},t}},function(t,e,n){"use strict";var i=n(0);t.exports=i.isStandardBrowserEnv()?{write:function(t,e,n,r,o,a){var s=[];s.push(t+"="+encodeURIComponent(e)),i.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),i.isString(r)&&s.push("path="+r),i.isString(o)&&s.push("domain="+o),!0===a&&s.push("secure"),document.cookie=s.join("; ")},read:function(t){var e=document.cookie.match(new RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove:function(t){this.write(t,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},function(t,e,n){"use strict";var i=n(31),r=n(32);t.exports=function(t,e){return t&&!i(e)?r(t,e):e}},function(t,e,n){"use strict";t.exports=function(t){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(t)}},function(t,e,n){"use strict";t.exports=function(t,e){return e?t.replace(/\/+$/,"")+"/"+e.replace(/^\/+/,""):t}},function(t,e,n){"use strict";var i=n(0),r=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];t.exports=function(t){var e,n,o,a={};return t?(i.forEach(t.split("\n"),(function(t){if(o=t.indexOf(":"),e=i.trim(t.substr(0,o)).toLowerCase(),n=i.trim(t.substr(o+1)),e){if(a[e]&&r.indexOf(e)>=0)return;a[e]="set-cookie"===e?(a[e]?a[e]:[]).concat([n]):a[e]?a[e]+", "+n:n}})),a):a}},function(t,e,n){"use strict";var i=n(0);t.exports=i.isStandardBrowserEnv()?function(){var t,e=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function r(t){var i=t;return e&&(n.setAttribute("href",i),i=n.href),n.setAttribute("href",i),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return t=r(window.location.href),function(e){var n=i.isString(e)?r(e):e;return n.protocol===t.protocol&&n.host===t.host}}():function(){return!0}},function(t,e,n){"use strict";var i=n(15);function r(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");var e;this.promise=new Promise((function(t){e=t}));var n=this;t((function(t){n.reason||(n.reason=new i(t),e(n.reason))}))}r.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},r.source=function(){var t;return{token:new r((function(e){t=e})),cancel:t}},t.exports=r},function(t,e,n){"use strict";t.exports=function(t){return function(e){return t.apply(null,e)}}},function(t,e,n){"use strict";t.exports=function(t){return"object"==typeof t&&!0===t.isAxiosError}},function(t,e,n){(function(t){
/*!
 * validate.js 0.13.1
 *
 * (c) 2013-2019 Nicklas Ansman, 2013 Wrapp
 * Validate.js may be freely distributed under the MIT license.
 * For all details and documentation:
 * http://validatejs.org/
 */
(function(t,e,i){"use strict";var r=function(t,e,n){n=o.extend({},o.options,n);var i=o.runValidations(t,e,n);if(i.some((function(t){return o.isPromise(t.error)})))throw new Error("Use validate.async if you want support for promises");return r.processValidationResults(i,n)},o=r;o.extend=function(t){return[].slice.call(arguments,1).forEach((function(e){for(var n in e)t[n]=e[n]})),t},o.extend(r,{version:{major:0,minor:13,patch:1,metadata:null,toString:function(){var t=o.format("%{major}.%{minor}.%{patch}",o.version);return o.isEmpty(o.version.metadata)||(t+="+"+o.version.metadata),t}},Promise:"undefined"!=typeof Promise?Promise:null,EMPTY_STRING_REGEXP:/^\s*$/,runValidations:function(t,e,n){var i,r,a,s,u,c,f,l=[];for(i in(o.isDomElement(t)||o.isJqueryElement(t))&&(t=o.collectFormValues(t)),e)for(r in a=o.getDeepObjectValue(t,i),s=o.result(e[i],a,t,i,n,e)){if(!(u=o.validators[r]))throw f=o.format("Unknown validator %{name}",{name:r}),new Error(f);c=s[r],(c=o.result(c,a,t,i,n,e))&&l.push({attribute:i,value:a,validator:r,globalOptions:n,attributes:t,options:c,error:u.call(u,a,c,i,t,n)})}return l},processValidationResults:function(t,e){t=o.pruneEmptyErrors(t,e),t=o.expandMultipleErrors(t,e),t=o.convertErrorMessages(t,e);var n=e.format||"grouped";if("function"!=typeof o.formatters[n])throw new Error(o.format("Unknown format %{format}",e));return t=o.formatters[n](t),o.isEmpty(t)?void 0:t},async:function(t,e,n){var i=(n=o.extend({},o.async.options,n)).wrapErrors||function(t){return t};!1!==n.cleanAttributes&&(t=o.cleanAttributes(t,e));var r=o.runValidations(t,e,n);return new o.Promise((function(a,s){o.waitForResults(r).then((function(){var u=o.processValidationResults(r,n);u?s(new i(u,n,t,e)):a(t)}),(function(t){s(t)}))}))},single:function(t,e,n){return n=o.extend({},o.single.options,n,{format:"flat",fullMessages:!1}),o({single:t},{single:e},n)},waitForResults:function(t){return t.reduce((function(t,e){return o.isPromise(e.error)?t.then((function(){return e.error.then((function(t){e.error=t||null}))})):t}),new o.Promise((function(t){t()})))},result:function(t){var e=[].slice.call(arguments,1);return"function"==typeof t&&(t=t.apply(null,e)),t},isNumber:function(t){return"number"==typeof t&&!isNaN(t)},isFunction:function(t){return"function"==typeof t},isInteger:function(t){return o.isNumber(t)&&t%1==0},isBoolean:function(t){return"boolean"==typeof t},isObject:function(t){return t===Object(t)},isDate:function(t){return t instanceof Date},isDefined:function(t){return null!=t},isPromise:function(t){return!!t&&o.isFunction(t.then)},isJqueryElement:function(t){return t&&o.isString(t.jquery)},isDomElement:function(t){return!!t&&(!(!t.querySelectorAll||!t.querySelector)&&(!(!o.isObject(document)||t!==document)||("object"==typeof HTMLElement?t instanceof HTMLElement:t&&"object"==typeof t&&null!==t&&1===t.nodeType&&"string"==typeof t.nodeName)))},isEmpty:function(t){var e;if(!o.isDefined(t))return!0;if(o.isFunction(t))return!1;if(o.isString(t))return o.EMPTY_STRING_REGEXP.test(t);if(o.isArray(t))return 0===t.length;if(o.isDate(t))return!1;if(o.isObject(t)){for(e in t)return!1;return!0}return!1},format:o.extend((function(t,e){return o.isString(t)?t.replace(o.format.FORMAT_REGEXP,(function(t,n,i){return"%"===n?"%{"+i+"}":String(e[i])})):t}),{FORMAT_REGEXP:/(%?)%\{([^\}]+)\}/g}),prettify:function(t){return o.isNumber(t)?100*t%1==0?""+t:parseFloat(Math.round(100*t)/100).toFixed(2):o.isArray(t)?t.map((function(t){return o.prettify(t)})).join(", "):o.isObject(t)?o.isDefined(t.toString)?t.toString():JSON.stringify(t):(t=""+t).replace(/([^\s])\.([^\s])/g,"$1 $2").replace(/\\+/g,"").replace(/[_-]/g," ").replace(/([a-z])([A-Z])/g,(function(t,e,n){return e+" "+n.toLowerCase()})).toLowerCase()},stringifyValue:function(t,e){return(e&&e.prettify||o.prettify)(t)},isString:function(t){return"string"==typeof t},isArray:function(t){return"[object Array]"==={}.toString.call(t)},isHash:function(t){return o.isObject(t)&&!o.isArray(t)&&!o.isFunction(t)},contains:function(t,e){return!!o.isDefined(t)&&(o.isArray(t)?-1!==t.indexOf(e):e in t)},unique:function(t){return o.isArray(t)?t.filter((function(t,e,n){return n.indexOf(t)==e})):t},forEachKeyInKeypath:function(t,e,n){if(o.isString(e)){var i,r="",a=!1;for(i=0;i<e.length;++i)switch(e[i]){case".":a?(a=!1,r+="."):(t=n(t,r,!1),r="");break;case"\\":a?(a=!1,r+="\\"):a=!0;break;default:a=!1,r+=e[i]}return n(t,r,!0)}},getDeepObjectValue:function(t,e){if(o.isObject(t))return o.forEachKeyInKeypath(t,e,(function(t,e){if(o.isObject(t))return t[e]}))},collectFormValues:function(t,e){var n,i,r,a,s,u,c={};if(o.isJqueryElement(t)&&(t=t[0]),!t)return c;for(e=e||{},a=t.querySelectorAll("input[name], textarea[name]"),n=0;n<a.length;++n)if(r=a.item(n),!o.isDefined(r.getAttribute("data-ignored"))){var f=r.name.replace(/\./g,"\\\\.");u=o.sanitizeFormValue(r.value,e),"number"===r.type?u=u?+u:null:"checkbox"===r.type?r.attributes.value?r.checked||(u=c[f]||null):u=r.checked:"radio"===r.type&&(r.checked||(u=c[f]||null)),c[f]=u}for(a=t.querySelectorAll("select[name]"),n=0;n<a.length;++n)if(r=a.item(n),!o.isDefined(r.getAttribute("data-ignored"))){if(r.multiple)for(i in u=[],r.options)(s=r.options[i])&&s.selected&&u.push(o.sanitizeFormValue(s.value,e));else{var l=void 0!==r.options[r.selectedIndex]?r.options[r.selectedIndex].value:"";u=o.sanitizeFormValue(l,e)}c[r.name]=u}return c},sanitizeFormValue:function(t,e){return e.trim&&o.isString(t)&&(t=t.trim()),!1!==e.nullify&&""===t?null:t},capitalize:function(t){return o.isString(t)?t[0].toUpperCase()+t.slice(1):t},pruneEmptyErrors:function(t){return t.filter((function(t){return!o.isEmpty(t.error)}))},expandMultipleErrors:function(t){var e=[];return t.forEach((function(t){o.isArray(t.error)?t.error.forEach((function(n){e.push(o.extend({},t,{error:n}))})):e.push(t)})),e},convertErrorMessages:function(t,e){var n=[],i=(e=e||{}).prettify||o.prettify;return t.forEach((function(t){var r=o.result(t.error,t.value,t.attribute,t.options,t.attributes,t.globalOptions);o.isString(r)?("^"===r[0]?r=r.slice(1):!1!==e.fullMessages&&(r=o.capitalize(i(t.attribute))+" "+r),r=r.replace(/\\\^/g,"^"),r=o.format(r,{value:o.stringifyValue(t.value,e)}),n.push(o.extend({},t,{error:r}))):n.push(t)})),n},groupErrorsByAttribute:function(t){var e={};return t.forEach((function(t){var n=e[t.attribute];n?n.push(t):e[t.attribute]=[t]})),e},flattenErrorsToArray:function(t){return t.map((function(t){return t.error})).filter((function(t,e,n){return n.indexOf(t)===e}))},cleanAttributes:function(t,e){function n(t,e,n){return o.isObject(t[e])?t[e]:t[e]=!!n||{}}return o.isObject(e)&&o.isObject(t)?function t(e,n){if(!o.isObject(e))return e;var i,r,a=o.extend({},e);for(r in e)i=n[r],o.isObject(i)?a[r]=t(a[r],i):i||delete a[r];return a}(t,e=function(t){var e,i={};for(e in t)t[e]&&o.forEachKeyInKeypath(i,e,n);return i}(e)):{}},exposeModule:function(t,e,n,i,r){n?(i&&i.exports&&(n=i.exports=t),n.validate=t):(e.validate=t,t.isFunction(r)&&r.amd&&r([],(function(){return t})))},warn:function(t){"undefined"!=typeof console&&console.warn&&console.warn("[validate.js] "+t)},error:function(t){"undefined"!=typeof console&&console.error&&console.error("[validate.js] "+t)}}),r.validators={presence:function(t,e){if(!1!==(e=o.extend({},this.options,e)).allowEmpty?!o.isDefined(t):o.isEmpty(t))return e.message||this.message||"can't be blank"},length:function(t,e,n){if(o.isDefined(t)){var i,r=(e=o.extend({},this.options,e)).is,a=e.maximum,s=e.minimum,u=[],c=(t=(e.tokenizer||function(t){return t})(t)).length;return o.isNumber(c)?(o.isNumber(r)&&c!==r&&(i=e.wrongLength||this.wrongLength||"is the wrong length (should be %{count} characters)",u.push(o.format(i,{count:r}))),o.isNumber(s)&&c<s&&(i=e.tooShort||this.tooShort||"is too short (minimum is %{count} characters)",u.push(o.format(i,{count:s}))),o.isNumber(a)&&c>a&&(i=e.tooLong||this.tooLong||"is too long (maximum is %{count} characters)",u.push(o.format(i,{count:a}))),u.length>0?e.message||u:void 0):e.message||this.notValid||"has an incorrect length"}},numericality:function(t,e,n,i,r){if(o.isDefined(t)){var a,s,u=[],c={greaterThan:function(t,e){return t>e},greaterThanOrEqualTo:function(t,e){return t>=e},equalTo:function(t,e){return t===e},lessThan:function(t,e){return t<e},lessThanOrEqualTo:function(t,e){return t<=e},divisibleBy:function(t,e){return t%e==0}},f=(e=o.extend({},this.options,e)).prettify||r&&r.prettify||o.prettify;if(o.isString(t)&&e.strict){var l="^-?(0|[1-9]\\d*)";if(e.onlyInteger||(l+="(\\.\\d+)?"),l+="$",!new RegExp(l).test(t))return e.message||e.notValid||this.notValid||this.message||"must be a valid number"}if(!0!==e.noStrings&&o.isString(t)&&!o.isEmpty(t)&&(t=+t),!o.isNumber(t))return e.message||e.notValid||this.notValid||this.message||"is not a number";if(e.onlyInteger&&!o.isInteger(t))return e.message||e.notInteger||this.notInteger||this.message||"must be an integer";for(a in c)if(s=e[a],o.isNumber(s)&&!c[a](t,s)){var d="not"+o.capitalize(a),h=e[d]||this[d]||this.message||"must be %{type} %{count}";u.push(o.format(h,{count:s,type:f(a)}))}return e.odd&&t%2!=1&&u.push(e.notOdd||this.notOdd||this.message||"must be odd"),e.even&&t%2!=0&&u.push(e.notEven||this.notEven||this.message||"must be even"),u.length?e.message||u:void 0}},datetime:o.extend((function(t,e){if(!o.isFunction(this.parse)||!o.isFunction(this.format))throw new Error("Both the parse and format functions needs to be set to use the datetime/date validator");if(o.isDefined(t)){var n,i=[],r=(e=o.extend({},this.options,e)).earliest?this.parse(e.earliest,e):NaN,a=e.latest?this.parse(e.latest,e):NaN;return t=this.parse(t,e),isNaN(t)||e.dateOnly&&t%864e5!=0?(n=e.notValid||e.message||this.notValid||"must be a valid date",o.format(n,{value:arguments[0]})):(!isNaN(r)&&t<r&&(n=e.tooEarly||e.message||this.tooEarly||"must be no earlier than %{date}",n=o.format(n,{value:this.format(t,e),date:this.format(r,e)}),i.push(n)),!isNaN(a)&&t>a&&(n=e.tooLate||e.message||this.tooLate||"must be no later than %{date}",n=o.format(n,{date:this.format(a,e),value:this.format(t,e)}),i.push(n)),i.length?o.unique(i):void 0)}}),{parse:null,format:null}),date:function(t,e){return e=o.extend({},e,{dateOnly:!0}),o.validators.datetime.call(o.validators.datetime,t,e)},format:function(t,e){(o.isString(e)||e instanceof RegExp)&&(e={pattern:e});var n,i=(e=o.extend({},this.options,e)).message||this.message||"is invalid",r=e.pattern;if(o.isDefined(t))return o.isString(t)?(o.isString(r)&&(r=new RegExp(e.pattern,e.flags)),(n=r.exec(t))&&n[0].length==t.length?void 0:i):i},inclusion:function(t,e){if(o.isDefined(t)&&(o.isArray(e)&&(e={within:e}),e=o.extend({},this.options,e),!o.contains(e.within,t))){var n=e.message||this.message||"^%{value} is not included in the list";return o.format(n,{value:t})}},exclusion:function(t,e){if(o.isDefined(t)&&(o.isArray(e)&&(e={within:e}),e=o.extend({},this.options,e),o.contains(e.within,t))){var n=e.message||this.message||"^%{value} is restricted";return o.isString(e.within[t])&&(t=e.within[t]),o.format(n,{value:t})}},email:o.extend((function(t,e){var n=(e=o.extend({},this.options,e)).message||this.message||"is not a valid email";if(o.isDefined(t))return o.isString(t)&&this.PATTERN.exec(t)?void 0:n}),{PATTERN:/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i}),equality:function(t,e,n,i,r){if(o.isDefined(t)){o.isString(e)&&(e={attribute:e});var a=(e=o.extend({},this.options,e)).message||this.message||"is not equal to %{attribute}";if(o.isEmpty(e.attribute)||!o.isString(e.attribute))throw new Error("The attribute must be a non empty string");var s=o.getDeepObjectValue(i,e.attribute),u=e.comparator||function(t,e){return t===e},c=e.prettify||r&&r.prettify||o.prettify;return u(t,s,e,n,i)?void 0:o.format(a,{attribute:c(e.attribute)})}},url:function(t,e){if(o.isDefined(t)){var n=(e=o.extend({},this.options,e)).message||this.message||"is not a valid url",i=e.schemes||this.schemes||["http","https"],r=e.allowLocal||this.allowLocal||!1,a=e.allowDataUrl||this.allowDataUrl||!1;if(!o.isString(t))return n;var s="^(?:(?:"+i.join("|")+")://)(?:\\S+(?::\\S*)?@)?(?:",u="(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))";if(r?u+="?":s+="(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})",s+="(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*"+u+")(?::\\d{2,5})?(?:[/?#]\\S*)?$",a){s="(?:"+s+")|(?:^data:(?:\\w+\\/[-+.\\w]+(?:;[\\w=]+)*)?(?:;base64)?,[A-Za-z0-9-_.!~\\*'();\\/?:@&=+$,%]*$)"}return new RegExp(s,"i").exec(t)?void 0:n}},type:o.extend((function(t,e,n,i,r){if(o.isString(e)&&(e={type:e}),o.isDefined(t)){var a,s=o.extend({},this.options,e),u=s.type;if(!o.isDefined(u))throw new Error("No type was specified");if(a=o.isFunction(u)?u:this.types[u],!o.isFunction(a))throw new Error("validate.validators.type.types."+u+" must be a function.");if(!a(t,s,n,i,r)){var c=e.message||this.messages[u]||this.message||s.message||(o.isFunction(u)?"must be of the correct type":"must be of type %{type}");return o.isFunction(c)&&(c=c(t,e,n,i,r)),o.format(c,{attribute:o.prettify(n),type:u})}}}),{types:{object:function(t){return o.isObject(t)&&!o.isArray(t)},array:o.isArray,integer:o.isInteger,number:o.isNumber,string:o.isString,date:o.isDate,boolean:o.isBoolean},messages:{}})},r.formatters={detailed:function(t){return t},flat:o.flattenErrorsToArray,grouped:function(t){var e;for(e in t=o.groupErrorsByAttribute(t))t[e]=o.flattenErrorsToArray(t[e]);return t},constraint:function(t){var e;for(e in t=o.groupErrorsByAttribute(t))t[e]=t[e].map((function(t){return t.validator})).sort();return t}},r.exposeModule(r,this,t,e,n(16))}).call(this,e,t,n(16))}).call(this,n(39)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t){t.exports=JSON.parse('{"name":"@flagship.io/js-sdk","version":"2.2.5","description":"Flagship JS SDK","main":"dist/index.node.js","browser":"dist/index.browser.js","react-native":"dist/index.reactNative.js","files":["dist","public","CONTRIBUTING.md","README.md","package.json"],"types":"dist/index.d.ts","engines":{"npm":">=3","node":">=6"},"scripts":{"test":"jest --verbose","test:coverage":"jest --coverage","test:badges":"npm run test:coverage && jest-coverage-badges && cp ./coverage/badge-lines.svg ./badges/ && cp ./coverage/badge-functions.svg ./badges/","test:react-sample":"cd ./examples/react-app && npm test","eslint":"eslint --version && eslint --quiet .ts,.js","release":"np","version":"npm run build","publish":"npm run test:badges && npm run update:react-app && npm run update:api-server && git add . && git commit -m\\"Post publish update\\" && git push && npm run publish:react","publish:react":"cd ./examples/react-app && npm run deploy:github","update:react-app":"cd ./examples/react-app && npm install @flagship.io/js-sdk@latest --save && cd ../../","update:api-server":"cd ./examples/api-server && npm install @flagship.io/js-sdk@latest --save && cd ../../","update:fsLog":"npm install @flagship.io/js-sdk-logs@latest --save","contributors:add":"all-contributors add","contributors:generate":"all-contributors generate","stats:dev":"rm -rf dist && webpack --env=stats","stats:prod":"webpack --profile --json --env=prod > stats.json && webpack-bundle-analyzer ./stats.json","build":"rm -rf dist && webpack --env=prod && ./cleanDts.sh"},"repository":{"type":"git","url":"git+https://github.com/abtasty/flagship-js-sdk"},"license":"Apache-2.0","bugs":{"url":"https://github.com/abtasty/flagship-js-sdk/issues","email":"emilien.domenge-heritier@abtasty.com"},"contributors":[{"name":"Emilien Domenge-Heritier","email":"emilien.domenge-heritier@abtasty.com","url":"https://domenge.fr"},{"name":"Guillaume Jacquart","email":"guillaume.jacquart@abtasty.com"},{"name":"Yanis Tam","email":"yanis@abtasty.com"}],"keywords":["flagship","abtasty","node","sdk"],"homepage":"https://github.com/abtasty/flagship-js-sdk","devDependencies":{"@babel/core":"^7.7.2","@babel/preset-env":"^7.7.1","@babel/preset-typescript":"^7.7.2","@types/jest":"^24.0.22","@types/node":"^12.12.7","@typescript-eslint/eslint-plugin":"^2.8.0","@typescript-eslint/parser":"^2.8.0","all-contributors-cli":"^6.16.1","babel-jest":"^24.9.0","babel-loader":"^8.0.6","dts-bundle-generator":"^4.3.0","eslint":"^6.1.0","eslint-config-airbnb-base":"^14.0.0","eslint-config-prettier":"^6.11.0","eslint-loader":"^3.0.3","eslint-plugin-import":"^2.18.2","eslint-plugin-prettier":"^3.1.4","jest":"^24.9.0","jest-coverage-badges":"^1.1.2","jest-localstorage-mock":"^2.4.3","jest-mock-axios":"^3.1.2","np":"^6.2.3","prettier":"2.0.4","source-map-loader":"^0.2.4","supertest":"^4.0.2","ts-loader":"^7.0.5","typescript":"^3.7.2","webpack":"4.41.0","webpack-bundle-analyzer":"^3.8.0","webpack-cli":"^3.3.10","webpack-merge":"^4.2.2","webpack-node-externals":"^1.7.2"},"dependencies":{"@flagship.io/js-sdk-logs":"^0.1.4","axios":"^0.21.1","events":"^3.1.0","react-native-murmurhash":"^1.1.0","validate.js":"^0.13.1"},"jest":{"setupFiles":["jest-localstorage-mock"],"testEnvironment":"node","coverageReporters":["json-summary","text","lcov"],"collectCoverage":true,"transform":{"^.+\\\\.[t|j]sx?$":"babel-jest"},"coveragePathIgnorePatterns":["<rootDir>/test/","/node_modules/"],"testPathIgnorePatterns":["<rootDir>/src/config/","<rootDir>/examples/"]}}')},function(t,e,n){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var r=i(i({},{enableErrorLayout:!1,enableSafeMode:!1}),{});e.default=r},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.demoPollingInterval=void 0,e.demoPollingInterval=.005},function(t,e,n){"use strict";var i,r=this&&this.__extends||(i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)},function(t,e){function n(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}),o=this&&this.__assign||function(){return(o=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)},a=this&&this.__rest||function(t,e){var n={};for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&e.indexOf(i)<0&&(n[i]=t[i]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(i=Object.getOwnPropertySymbols(t);r<i.length;r++)e.indexOf(i[r])<0&&Object.prototype.propertyIsEnumerable.call(t,i[r])&&(n[i[r]]=t[i[r]])}return n};Object.defineProperty(e,"__esModule",{value:!0});var s=n(5),u=n(3),c=n(4),f=n(2),l=n(1),d=function(t){function e(e,n,i,r){var o=t.call(this)||this;return o.panic=i,o.config=n,o.log=f.default.getLogger(o.config,"Flagship SDK - Bucketing"),o.envId=e,o.data=n.initialBucketing&&l.default.checkBucketingApiResponse(n.initialBucketing,o.log)||null,o.isPollingRunning=!1,o.lastModifiedDate=o.data&&o.data.lastModifiedDate||null,o.on("launched",(function(){"ok"===l.default.checkPollingIntervalValue(o.config.pollingInterval)&&o.isPollingRunning&&(o.log.debug("startPolling - polling finished successfully. Next polling in "+o.config.pollingInterval+" minute(s)"),setTimeout((function(){o.isPollingRunning?o.pollingMechanism():o.log.debug('on("launched") listener - bucketing stop detected.')}),1e3*o.config.pollingInterval))})),o.on("error",(function(t){"ok"===l.default.checkPollingIntervalValue(o.config.pollingInterval)&&o.isPollingRunning&&(o.log.error('startPolling - polling failed with error "'+t+'". Next polling in '+o.config.pollingInterval+" minute(s)"),setTimeout((function(){o.pollingMechanism()}),60*o.config.pollingInterval*1e3))})),o}return r(e,t),e.validateStatus=function(t){return t<400},e.prototype.callApi=function(){var t=this,n={headers:{"If-Modified-Since":null!==this.lastModifiedDate?this.lastModifiedDate:""},validateStatus:e.validateStatus},i=c.internalConfig.bucketingEndpoint.replace("@ENV_ID@",this.envId);return s.default.get(i,n).then((function(e){var n=e.data,r=e.status,s=a(e,["data","status"]);return t.panic.checkPanicMode(n),t.panic.enabled||(304===r?t.log.info("callApi - current bucketing up to date (api status=304)"):200===r?(s.headers["last-modified"]?t.lastModifiedDate=s.headers["last-modified"]:t.log.warn('callApi - http GET request (url="'+i+'") did not return attribute "last-modified"'),t.log.info("callApi - current bucketing updated"),t.data=o(o({},n),{lastModifiedDate:t.lastModifiedDate})):t.log.error('callApi - unexpected status (="'+r+'") received. This polling will be ignored.')),t.emit("launched",{status:r}),n})).catch((function(e){t.log.fatal("An error occurred while fetching using bucketing..."),t.emit("error",e)}))},e.prototype.stopPolling=function(){this.isPollingRunning=!1},e.prototype.pollingMechanism=function(){switch(l.default.checkPollingIntervalValue(this.config.pollingInterval)){case"ok":this.isPollingRunning=!0,this.log.debug("startPolling - starting a new polling..."),this.callApi();break;case"notSupported":this.isPollingRunning=!1,this.log.error('startPolling - The "pollingInterval" setting has value="'+this.config.pollingInterval+'" and type="'+typeof this.config.pollingInterval+'" which is not supported. The setting will be ignored and the bucketing api will be called only once for initialization.)'),this.callApi();break;case"underLimit":default:this.isPollingRunning=!1,this.log.error('startPolling - The "pollingInterval" setting is below the limit ('+c.internalConfig.pollingIntervalMinValue+" second). The setting will be ignored and the bucketing api will be called only once for initialization."),this.callApi()}},e.prototype.startPolling=function(){this.isPollingRunning?this.log.warn("startPolling - already running"):(null===this.data&&this.log.debug("startPolling - initializing bucket"),this.pollingMechanism())},e}(u.EventEmitter);e.default=d},function(t,e,n){"use strict";var i,r=this&&this.__extends||(i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)},function(t,e){function n(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}),o=this&&this.__assign||function(){return(o=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)},a=this&&this.__awaiter||function(t,e,n,i){return new(n||(n=Promise))((function(r,o){function a(t){try{u(i.next(t))}catch(t){o(t)}}function s(t){try{u(i.throw(t))}catch(t){o(t)}}function u(t){var e;t.done?r(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(a,s)}u((i=i.apply(t,e||[])).next())}))},s=this&&this.__generator||function(t,e){var n,i,r,o,a={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(o){return function(s){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,i=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(r=a.trys,(r=r.length>0&&r[r.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]<r[3])){a.label=o[1];break}if(6===o[0]&&a.label<r[1]){a.label=r[1],r=o;break}if(r&&a.label<r[2]){a.label=r[2],a.ops.push(o);break}r[2]&&a.ops.pop(),a.trys.pop();continue}o=e.call(t,a)}catch(t){o=[6,t],i=0}finally{n=r=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,s])}}},u=this&&this.__spreadArrays||function(){for(var t=0,e=0,n=arguments.length;e<n;e++)t+=arguments[e].length;var i=Array(t),r=0;for(e=0;e<n;e++)for(var o=arguments[e],a=0,s=o.length;a<s;a++,r++)i[r]=o[a];return i};Object.defineProperty(e,"__esModule",{value:!0});var c=n(6),f=n(5),l=n(3),d=n(1),h=n(2),p=n(45),g=function(t){function e(n,i,r,a,s){void 0===s&&(s={});var u=t.call(this)||this,c=o(o({},{bucket:null,context:{},isAuthenticated:!1,previousVisitorInstance:null,cacheManager:null}),Object.keys(s).reduce((function(t,e){var n;return void 0===s[e]||null===s[e]?t:o(o({},t),((n={})[e]=s[e],n))}),{})),f=c.bucket,l=c.context,g=c.previousVisitorInstance,v=c.isAuthenticated,m=c.cacheManager;u.cacheManager=m,u.panic=r,u.config=a,u.isAuthenticated=v;var y=h.default.getLogger(u.config,"Flagship SDK - visitorId:*initiliazing*"),b=u.checkIfCanConsiderCacheData(i,u.getCache({customLog:y}));return u.setVisitorId(i||(null==b?void 0:b.id)||e.createVisitorId()),u.anonymousId=(null==b?void 0:b.anonymousId)||null,b&&(u.isAuthenticated&&!u.anonymousId?u.log.warn('detected "isAuthenticated=true" but the SDK found an inconsistency from cache. It seems the visitor only had an unauthenticate experience and never has been authenticate before. As a result, the visitor will still be considered anonymous.'):!u.isAuthenticated&&u.anonymousId&&(u.log.info('detected "isAuthenticated=false" + previous authenticate experience for this visitor. From there, the SDK will consider its previous unauthenticate experience.'),u.unauthenticate())),i||b||u.log.info('no id specified during visitor creation. The SDK has automatically created one: "'+u.id+'"'),u.envId=n,u.context=d.default.checkVisitorContext(l,u.log),u.isAllModificationsFetched=!!g&&g.isAllModificationsFetched,u.bucket=null,g?(u.fetchedModifications=g?g.fetchedModifications:null,u.modificationsInternalStatus=g?g.modificationsInternalStatus:null):a.initialModifications?u.saveModificationsInCache(a.initialModifications):(u.fetchedModifications=null,u.modificationsInternalStatus=null),"Bucketing"===u.config.decisionMode&&(u.bucket=new p.default(u.envId,u.id,u.context,u.config,f)),u.updateCache(),u}return r(e,t),e.prototype.setVisitorId=function(t){this.id=t,this.log=h.default.getLogger(this.config,"Flagship SDK - visitorId:"+this.id)},e.prototype.checkIfCanConsiderCacheData=function(t,e){return e?t&&(this.isAuthenticated||t!==e.anonymousId)?t===e.id?e:null:e:null},e.prototype.getCache=function(t){void 0===t&&(t={});var e={customLog:this.log},n=o(o({},e),t).customLog;return this.cacheManager?this.cacheManager.loadVisitorProfile(this.id):(n.debug("getCache - no cache manager found."),null)},e.prototype.updateCache=function(){var t={id:this.id,anonymousId:this.anonymousId,context:this.context,campaigns:this.fetchedModifications};if(this.cacheManager)return this.cacheManager.saveVisitorProfile(this.id,t);this.log.debug("updateCache - no cache manager found.")},e.createVisitorId=function(){return c.FlagshipCommon.createVisitorId()},e.prototype.authenticate=function(t){var e,n=this;if(!t)return e="authenticate - no id specified. You must provide the visitor id which identifies your authenticated user.",this.log.error(e),new Promise((function(t,n){return n(e)}));if("string"!=typeof t)return e="authenticate - Received incorrect argument type: '"+typeof t+"'.The expected id must be type of 'string'.",this.log.error(e),new Promise((function(t,n){return n(e)}));this.anonymousId=this.id,this.setVisitorId(t),this.isAuthenticated=!0,this.updateCache();var i=this.config,r=i.fetchNow,o=i.activateNow,a="authenticate - visitor passed from anonymous (id="+this.anonymousId+") to authenticated (id="+this.id+").";return r||o?this.synchronizeModifications().then((function(){return n.log.info(a)})):(this.log.info(a+' Make sure to manually call "synchronize()" function in order to get the last visitor\'s modifications.'),new Promise((function(t){return t()})))},e.prototype.unauthenticate=function(t){var e,n=this;if(!this.anonymousId)return e="unauthenticate - Your visitor never has been authenticated.",this.log.error(e),new Promise((function(t,n){return n(e)}));var i=this.id;this.setVisitorId(t||this.anonymousId),this.anonymousId=null,this.isAuthenticated=!1,this.updateCache();var r=this.config,o=r.fetchNow,a=r.activateNow,s="unauthenticate - visitor passed from authenticated (id="+i+") to anonymous (id="+this.id+").";return o||a?this.synchronizeModifications().then((function(){return n.log.info(s)})):(this.log.info(s+' Make sure to manually call "synchronize()" function in order to get the last visitor\'s modifications.'),new Promise((function(t){return t()})))},e.prototype.activateCampaign=function(t,e,n){var i=this;return new Promise((function(r,o){d.default.postFlagshipApi({panic:i.panic,config:i.config,log:i.log,endpoint:i.config.flagshipApi+"activate",params:{vid:i.id,aid:i.anonymousId,cid:i.envId,caid:e,vaid:t}}).then((function(e){var o='VariationId "'+t+'" successfully activate with status code:'+e.status;n&&n.success&&(o=n.success+' with status code "'+e.status+'"'),i.log.debug(o),r({status:200})})).catch((function(e){var r='Trigger activate of variationId "'+t+'" failed with error "'+e+'"';n&&n.fail&&(r=n.fail+' failed with error "'+e+'"'),i.log.fatal(r),o(e)}))}))},e.prototype.activateModifications=function(t){if(!this.panic.shouldRunSafeMode("activateModifications")){var e=t.reduce((function(t,e){var n=e.key;return u(t,[{key:n,defaultValue:"",activate:!0}])}),[]);if(this.fetchedModifications){var n=this.extractDesiredModifications(this.fetchedModifications,e).detailsModifications;this.triggerActivateIfNeeded(n)}}},e.prototype.triggerActivateIfNeeded=function(t,e){var n=this;void 0===t&&(t=null),void 0===e&&(e=!1);var i=[],r=this.modificationsInternalStatus,o=[];if(this.isVisitorCacheExist()){Object.entries(t||r).forEach((function(t){var i=t[0],u=t[1];return a(n,void 0,void 0,(function(){var t,a,c;return s(this,(function(s){var f;return t=!!u.isActivateNeeded||e,f={vgId:u.variationGroupId[0],vId:u.variationId[0],archived:r[i].activated},a=!(0===f.archived.variationGroupId.length&&0===f.archived.variationId.length||(f.archived.variationGroupId[0]!==f.vgId||f.archived.variationId[0]!==f.vId?(n.log.debug('triggerActivateIfNeeded - detecting a new variation (id="'+f.vId+'") (variationGroupId="'+f.vgId+'") which activates the same key as another older variation'),1):(n.log.debug('triggerActivateIfNeeded - variation (vgId="'+f.vgId+'") already activated'),0))),t&&!a&&(c=!1,o.forEach((function(t,e){var n=t.vId,r=t.vgId;n===u.variationId[0]&&r===u.variationGroupId[0]&&(o[e].keys.push(i),c=!0)})),c||o.push({vgId:u.variationGroupId[0],vId:u.variationId[0],campaignId:u.campaignId[0],keys:[i]})),[2]}))}))}));var u=function(t,e){var i=t.keys,r=t.vgId,o=t.vId;void 0===e&&(e=!1),i.forEach((function(t){e?(n.modificationsInternalStatus[t].activated.variationId.shift(),n.modificationsInternalStatus[t].activated.variationGroupId.shift()):(n.modificationsInternalStatus[t].activated.variationId.unshift(o),n.modificationsInternalStatus[t].activated.variationGroupId.unshift(r))}))};o.forEach((function(t){var e=t.vId,r=t.vgId,o=t.keys,a=t.campaignId;i.push(a),u({vId:e,vgId:r,keys:o}),n.activateCampaign(e,r,{success:'Modification key(s) "'+o.toString()+'" successfully activate.',fail:'Trigger activate of modification key(s) "'+o.toString()+'" failed.'}).catch((function(){u({vId:e,vgId:r,keys:o},!0)}))}));var c=this.checkCampaignsActivatedMultipleTimes(t,e),f=c.activateKey,l=c.activateCampaign;Object.entries(f).forEach((function(t){var e=t[0],i=t[1];i>1&&(n.log.warn('Key "'+e+'" has been activated '+i+" times because it was in conflict in further campaigns (debug logs for more details)"),n.log.debug("Here the details:"+Object.entries(l).map((function(t){var n=t[0],i=t[1],r=i.directActivate;return i.indirectActivate.includes(e)?'\n- because key "'+e+'" is also include inside campaign id="'+n+'" where key(s) "'+r.map((function(t){return t+" "}))+'" is/are also requested.':null}))))}))}},e.prototype.isVisitorCacheExist=function(){return!(!this.fetchedModifications||!this.modificationsInternalStatus)||(this.log.debug('checkCampaignsActivatedMultipleTimes: Error "this.fetchedModifications" or/and "this.modificationsInternalStatus" is empty'),!1)},e.prototype.checkCampaignsActivatedMultipleTimes=function(t,e){var n=this;void 0===t&&(t=null),void 0===e&&(e=!1);var i,r={activateCampaign:{},activateKey:{}};if(!this.isVisitorCacheExist())return r;if(t)i=Object.entries(t).filter((function(t){return!0===t[1].isActivateNeeded}));else{if(!e)return r;i=Object.entries(this.modificationsInternalStatus)}var o=function(t,e){if(n.fetchedModifications){var i=n.fetchedModifications.filter((function(e){return e.id===t}));if(1===i.length)return Object.keys(i[0].variation.modifications.value).filter((function(t){return t!==e}));n.log.debug('extractModificationIndirectKeysFromCampaign - detected more than one campaign with same id "'+i[0].id+'"')}return[]};i.forEach((function(t){var e=t[0],n=t[1];r.activateCampaign[n.campaignId[0]]?r.activateCampaign[n.campaignId[0]].directActivate.push(e):r.activateCampaign[n.campaignId[0]]={directActivate:[e],indirectActivate:o(n.campaignId[0],e)}})),Object.keys(r.activateCampaign).forEach((function(t){Object.values(r.activateCampaign[t].directActivate).forEach((function(e){r.activateCampaign[t].indirectActivate.includes(e)&&r.activateCampaign[t].indirectActivate.splice(r.activateCampaign[t].indirectActivate.indexOf(e),1)}))}));return i.forEach((function(t){var e=t[0];r.activateKey[e]=function(t){return Object.values(r.activateCampaign).reduce((function(e,n){var i=n.directActivate;return e+n.indirectActivate.filter((function(e){return e===t})).length+i.filter((function(e){return e===t})).length}),0)}(e)})),r},e.prototype.getModificationsInternalStatus=function(){var t=e.analyseModifications(this.fetchedModifications).detailsModifications,n=this.modificationsInternalStatus;return Object.keys(t).reduce((function(e,i){var r,a,s=t[i],u=s.value,c=s.type,f=s.campaignId,l=s.variationGroupId,d=s.variationId;return n&&n[i]?o(o({},e),((r={})[i]=o(o({},n[i]),{value:u,type:c,campaignId:f,variationId:d,variationGroupId:l}),r)):o(o({},e),((a={})[i]={value:u,type:c,campaignId:f,variationId:d,variationGroupId:l,activated:{variationId:[],variationGroupId:[]}},a))}),{})},e.analyseModifications=function(t,e,n){void 0===t&&(t=[]),void 0===e&&(e=!1);var i={},r={};return t.forEach((function(t){return Object.entries(t.variation.modifications.value).forEach((function(o){var a=o[0],s=o[1];r[a]?(i[a].value.push(s),i[a].type.push(t.variation.modifications.type),i[a].campaignId.push(t.id),i[a].variationId.push(t.variation.id),i[a].variationGroupId.push(t.variationGroupId)):(r[a]=s,i[a]={value:[s],type:[t.variation.modifications.type],campaignId:[t.id],variationId:[t.variation.id],variationGroupId:[t.variationGroupId],isRequested:!1,isActivateNeeded:!!e},n&&n.some((function(t){t.key===a&&(i[a].isRequested=!0,!e&&t.activate&&(i[a].isActivateNeeded=t.activate))})))})),null})),{detailsModifications:i,mergedModifications:r}},e.prototype.extractDesiredModifications=function(t,n,i){var r=this;void 0===i&&(i=null);var o={},a=e.analyseModifications(t,!!i,n),s=a.detailsModifications,u=a.mergedModifications;return Object.entries(s).forEach((function(t){var e=t[0];s[e].value.length>1&&s[e].isRequested&&r.log.warn('Modification "'+e+'" has further values because the modification is involved in campaigns with (id="'+s[e].campaignId.toString()+'"). Modification value kept is '+e+'="'+s[e].value[0]+'"')})),(n||[]).forEach((function(t){if(void 0!==u[t.key]&&null!==u[t.key])o[t.key]=u[t.key];else{var e=t.defaultValue;o[t.key]=e,!1===r.panic.enabled&&(r.log.debug('No value found for modification "'+t.key+'".\nSetting default value "'+e+'"'),t.activate&&r.log.warn('Unable to activate modification "'+t.key+'" because it does not exist on any existing campaign...'))}})),{desiredModifications:o,detailsModifications:s}},e.prototype.getModificationsPostProcess=function(t,e,n){void 0===n&&(n=null);var i=t,r=i&&i.data?i.data:t;if(e&&r&&"object"==typeof r&&!Array.isArray(t)){var o=this.extractDesiredModifications(r.campaigns,e,n),a=o.desiredModifications,s=o.detailsModifications;return this.log.debug("getModificationsPostProcess - detailsModifications:\n"+JSON.stringify(s)),this.triggerActivateIfNeeded(s),a}return e||this.log.error('Requesting some specific modifications but the "modificationsRequested" argument is "'+typeof e+'"...'),{}},e.prototype.getModifications=function(t,e){if(void 0===e&&(e=null),this.panic.shouldRunSafeMode("getModifications"))return this.extractDesiredModifications([],t,!1).desiredModifications;if(!this.fetchedModifications)return this.log.warn("No modifications found in cache..."),this.extractDesiredModifications([],t,e).desiredModifications;var n=this.fetchAllModifications({activate:!!e,loadFromCache:!0});return this.getModificationsPostProcess(n,t,e)},e.prototype.getModificationInfo=function(t){var e=this;if(this.panic.shouldRunSafeMode("getModificationInfo"))return new Promise((function(t){return t(null)}));var n=function(t){return{campaignId:t.id,isReference:!!t.variation.reference,variationId:t.variation.id,variationGroupId:t.variationGroupId}};return new Promise((function(i,r){e.fetchAllModifications({activate:!1,force:!0}).then((function(r){var o=r;d.default.checkDecisionApiResponseFormat(o,e.log);var a=o.data.campaigns,s=e.extractDesiredModifications(a,[{key:t,defaultValue:"",activate:!1}],!1).detailsModifications;if(s[t]){if(s[t].campaignId.length>1){var u=s[t].campaignId[0];e.log.warn('Modification "'+t+'" is involved in further campgains with:\nid="'+s[t].campaignId.toString()+'"\nKeeping data from:\ncampaignId="'+u+'"'),i(n(a.filter((function(t){return t.id===u}))[0]))}}else i(null);i(n(a.filter((function(e){return e.id===s[t].campaignId[0]}))[0]))})).catch((function(t){r(t)}))}))},e.prototype.updateContext=function(t){this.panic.shouldRunSafeMode("updateContext")||(this.context=d.default.checkVisitorContext(t,this.log))},e.prototype.synchronizeModifications=function(t){var e,n,i=this;void 0===t&&(t=!1);var r=(null===(n=null===(e=this.config.internal)||void 0===e?void 0:e.reactNative)||void 0===n?void 0:n.httpCallback)||null;return"API"!==this.config.decisionMode&&this.panic.shouldRunSafeMode("synchronizeModifications")?new Promise((function(t){return t(400)})):new Promise((function(e,n){var o=function(t,n){i.callEventEndpoint(),e((null==n?void 0:n.status)||200)};if("Bucketing"===i.config.decisionMode&&(null!==i.bucket&&i.bucket.updateVisitorContext(i.context),!i.bucket||i.bucket&&!i.bucket.global.isPollingRunning&&!i.bucket.computedData))return i.log.info("synchronizeModifications - you might synchronize modifications too early because bucketing is empty or did not start"),void o();i.fetchAllModifications({activate:t,force:!0,httpCallback:r}).then((function(t){d.default.checkDecisionApiResponseFormat(t,i.log);o(0,t)})).catch((function(t){n(t)}))}))},e.prototype.getModificationsForCampaign=function(t,e){var n=this;return void 0===e&&(e=!1),this.panic.shouldRunSafeMode("getModificationsForCampaign")?new Promise((function(t){return t({data:d.default.generatePanicDecisionApiResponse(n.id),status:400})})):this.fetchAllModifications({activate:e,campaignCustomID:t})},e.prototype.getAllModifications=function(t,n){var i,r,a=this;void 0===t&&(t=!1),void 0===n&&(n={});var s=(null===(r=null===(i=this.config.internal)||void 0===i?void 0:i.reactNative)||void 0===r?void 0:r.httpCallback)||null;if(this.panic.shouldRunSafeMode("getAllModifications"))return new Promise((function(t){(null==n?void 0:n.simpleMode)?t({}):t({data:[],status:400})}));var u=o(o({},{force:!1,simpleMode:!1}),n);return new Promise((function(n,i){a.fetchAllModifications({activate:t,force:u.force,httpCallback:s}).then((function(t){if(u.simpleMode){var i=e.analyseModifications(t.data.campaigns).detailsModifications;n(Object.keys(i).reduce((function(t,e){var n;return o(o({},t),((n={})[e]=i[e].value[0],n))}),{}))}else n(t)})).catch((function(t){return i(t)}))}))},e.prototype.fetchAllModificationsPostProcess=function(t,n){var i=n.activate,r=n.campaignCustomID,a=t,s=a.data?a:{data:t},u=a.data?a.data:t,c={data:{}},f={},l=[];if(u&&u.campaigns){if(r)l=u.campaigns.filter((function(t){return t.id===r})),f=e.analyseModifications(l,!!i).detailsModifications,c=o(o({},s),{data:{visitorId:this.id,campaigns:l}});else f=e.analyseModifications(u.campaigns,!!i).detailsModifications,c=o({},s)}else{var d="No modification(s) found";r?(d+=' for campaignId="'+r+'"',c=o(o({},s),{data:{campaigns:[],visitorId:this.id}})):c=o({},s),this.log.warn(d)}return this.fetchedModifications&&this.triggerActivateIfNeeded(f),c},e.prototype.saveModificationsInCache=function(t){var e=this,n=!1,i=this.fetchedModifications,r=function(t){void 0===t&&(t=null),e.fetchedModifications=d.default.validateDecisionApiData(t,e.log),e.modificationsInternalStatus=null===e.fetchedModifications?null:e.getModificationsInternalStatus()};this.emit("saveCache",{saveInCacheModifications:function(o){void 0===o&&(o=t),n=!0,i!==o&&e.log.debug("saveModificationsInCache - saving in cache modifications returned by the callback: "+(Array.isArray(o)?JSON.stringify(o):o)),r(o)},modifications:{before:this.fetchedModifications,after:t||null}}),n||(r(t),this.log.debug('saveModificationsInCache - saving in cache those modifications: "'+(this.fetchedModifications?JSON.stringify(this.fetchedModifications):"null")+'"'))},e.prototype.fetchAllModifications=function(t){var e=this,n={activate:!1,campaignCustomID:null,force:!1,loadFromCache:!1},i=o(o({},n),t),r=i.activate,a=i.force,s=i.loadFromCache,u=i.httpCallback,c=""+this.config.flagshipApi+this.envId+"/campaigns?mode=normal";return s?this.fetchedModifications&&!a?(this.log.debug("fetchAllModifications - loadFromCache enabled"),this.fetchAllModificationsPostProcess({visitorId:this.id,campaigns:this.fetchedModifications},o(o({},n),t)).data):(this.log.fatal("fetchAllModifications - loadFromCache enabled but no data in cache. Make sure you fetched at least once before."),{visitorId:this.id,campaigns:this.fetchedModifications}):new Promise((function(i,s){var f;if(e.fetchedModifications&&!a)e.log.info("fetchAllModifications - no calls to the Decision API because it has already been fetched before"),i(e.fetchAllModificationsPostProcess({visitorId:e.id,campaigns:e.fetchedModifications},o(o({},n),t)));else if("Bucketing"===e.config.decisionMode){var l={visitorId:e.id,campaigns:[]};e.bucket.updateCache(),(null===(f=e.bucket)||void 0===f?void 0:f.computedData)&&(l=o(o({},l),{campaigns:e.bucket.computedData.campaigns}),e.saveModificationsInCache(l.campaigns),r&&e.log.debug('fetchAllModifications - activateNow enabled with bucketing mode. Following keys "'+Object.keys(e.modificationsInternalStatus).join(", ")+'" will be activated.')),i(e.fetchAllModificationsPostProcess(l,o(o({},n),t)))}else d.default.postFlagshipApi({callback:u,panic:e.panic,config:e.config,log:e.log,endpoint:c,params:{visitor_id:e.id,anonymous_id:e.anonymousId,trigger_hit:r,context:e.context}},{params:{exposeAllKeys:!0,sendContextEvent:!1}}).then((function(r){e.saveModificationsInCache(r.data.campaigns),i(e.fetchAllModificationsPostProcess(r,o(o({},n),t)))})).catch((function(t){e.log.fatal("fetchAllModifications - an error occurred while fetching "+((null==t?void 0:t.message)||"...")),r&&e.log.fatal("fetchAllModifications - activate canceled due to errors..."),s(t)}))}))},e.prototype.generateCustomTypeParamsOf=function(t){var e={};switch(t.type.toUpperCase()){case"SCREEN":case"SCREENVIEW":var n=t.data,i=n.documentLocation,r=n.pageTitle;if(!i)return this.log.error("sendHits("+t.type+') - failed because following required attribute "documentLocation" is missing...'),null;var a={t:"SCREENVIEW",dl:i};return r&&(a.pt=r),a;case"PAGE":case"PAGEVIEW":var s=t.data;i=s.documentLocation,r=s.pageTitle;if(!i)return this.log.error("sendHits("+t.type+') - failed because following required attribute "documentLocation" is missing...'),null;a={t:"PageView"==t.type?"PAGEVIEW":"SCREENVIEW",dl:i};return r&&(a.pt=r),a;case"TRANSACTION":var u=t.data,c=(i=u.documentLocation,r=u.pageTitle,u.transactionId),f=u.affiliation,l=u.totalRevenue,d=u.shippingCost,h=u.taxes,p=u.currency,g=u.couponCode,v=u.paymentMethod,m=u.shippingMethod,y=u.itemCount;return l&&(e.tr=l),d&&(e.ts=d),h&&(e.tt=h),p&&(e.tc=p),g&&(e.tcc=g),v&&(e.pm=v),m&&(e.sm=m),y&&(e.icn=y),i&&(e.dl=i),r&&(e.pt=r),c&&f?o({t:"TRANSACTION",tid:c,ta:f},e):(c||this.log.error('sendHits(Transaction) - failed because following required attribute "transactionId" is missing...'),f||this.log.error('sendHits(Transaction) - failed because following required attribute "affiliation" is missing...'),null);case"ITEM":var b=t.data,w=(c=b.transactionId,b.name),A=(i=b.documentLocation,r=b.pageTitle,b.price),E=b.code,I=b.category,x=b.quantity;return A&&(e.ip=A),x&&(e.iq=x),I&&(e.iv=I),i&&(e.dl=i),r&&(e.pt=r),c&&w&&E?o({t:"ITEM",tid:c,in:w,ic:E},e):(c||this.log.error('sendHits(Item) - failed because following required attribute "transactionId" is missing...'),w||this.log.error('sendHits(Item) - failed because following required attribute "name" is missing...'),E||this.log.error('sendHits(Item) - failed because following required attribute "code" is missing...'),null);case"EVENT":var k=t.data,M=k.label,C=k.value,P=(i=k.documentLocation,I=k.category,r=k.pageTitle,k.action);return M&&(e.el=M),C&&(e.ev=C),i&&(e.dl=i),r&&(e.pt=r),I&&P?o({t:"EVENT",ea:P,ec:I},e):(this.log.debug("sendHits(Event) - this hits is missing attributes:\n"+JSON.stringify(t)),I||this.log.error('sendHits(Event) - failed because following required attribute "category" is missing...'),P||this.log.error('sendHits(Event) - failed because following required attribute "action" is missing...'),null);default:return this.log.error('sendHits - no type found for hit: "'+JSON.stringify(t)+'"'),null}},e.prototype.sendHits=function(t){var e=this;if(this.panic.shouldRunSafeMode("sendHits"))return new Promise((function(t){return t()}));var n=[],i="https://ariane.abtasty.com";return new Promise((function(r,u){Promise.all(t.map((function(t){return a(e,void 0,void 0,(function(){var e,r;return s(this,(function(a){return(e=this.generateCustomTypeParamsOf(t))?(r=o({vid:this.id,cid:this.envId,ds:"APP"},e),n.push(r),this.log.debug("sending hit "+JSON.stringify(r)),[2,f.default.post(i,r).then((function(){return o({skipped:!1},r)}))]):(this.log.debug('sendHits - skip request to "'+i+'" because current hit not set correctly'),[2,new Promise((function(t){return t({skipped:!0})}))])}))}))}))).then((function(t){t.forEach((function(t){t&&!t.skipped&&(e.log.info('sendHits - hit (type"'+t.t+'") send successfully'),e.log.debug("sendHits - with url "+i),e.log.debug("sendHits - with payload:\n"+n.map((function(t){return JSON.stringify(t)+"\n"}))))})),r()})).catch((function(t){!function(t){e.log.fatal('sendHits - fail with error: "'+t+'"')}(t),u(t)}))}))},e.prototype.sendHit=function(t){return this.panic.shouldRunSafeMode("sendHit")?new Promise((function(t){return t()})):this.sendHits([t])},e.prototype.callEventEndpoint=function(){var t=this;return this.panic.shouldRunSafeMode("callEventEndpoint",{logType:"debug"})?new Promise((function(t){return t(400)})):new Promise((function(e,n){d.default.postFlagshipApi({panic:t.panic,config:t.config,log:t.log,endpoint:""+t.config.flagshipApi+t.envId+"/events",params:{visitor_id:t.id,type:"CONTEXT",data:o({},t.context)}}).then((function(n){t.log.debug("callEventEndpoint - returns status="+n.status),e(n.status)})).catch((function(e){t.log.error('callEventEndpoint - failed with error="'+e+'"'),n(e)}))}))},e}(l.EventEmitter);e.default=g},function(t,e,n){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var r=n(46),o=n(2),a=n(1),s=function(){function t(t,e,n,i,r,a){var s=r.data;this.config=i,this.visitorId=e,this.visitorContext=n,this.global=r,this.log=o.default.getLogger(this.config,"Flagship SDK - Bucketing (visitorId="+this.visitorId+")"),this.envId=t,this.data=s||null,this.computedData=s?{visitorId:this.visitorId,campaigns:this.getEligibleCampaigns()}:null}return t.transformIntoDecisionApiPayload=function(t,e,n){return{id:e.id,variationGroupId:n,variation:{id:t.id,modifications:i({},t.modifications)}}},t.prototype.updateCache=function(){return this.data===this.global.data||(this.log.debug("Updating cache."),this.data=this.global.data,this.computedData={visitorId:this.visitorId,campaigns:this.getEligibleCampaigns()},!0)},t.prototype.updateVisitorContext=function(t){this.log.debug("Updating bucketing visitor context from "+JSON.stringify(this.visitorContext)+" to "+JSON.stringify(t)),this.visitorContext=a.default.checkVisitorContext(t,this.log)},t.prototype.computeMurmurAlgorithm=function(t,e){var n=null,i=r.MurmurHashV3(e+this.visitorId,void 0)%100;this.log.debug('computeMurmurAlgorithm - murmur returned value="'+i+'"');var o=t.reduce((function(t,e){var r=(e.allocation||0)+t;return null===n&&i<r&&(n=e),r}),0);return o<100&&(this.log.debug('computeMurmurAlgorithm - the total variation traffic allocation is equal to "'+o+'"'),null===n&&this.log.info("computeMurmurAlgorithm - current visitor will be untracked as it is outside the total variation traffic allocation")),o>100?(this.log.fatal('computeMurmurAlgorithm - the total variation traffic allocation is equal to "'+o+'" instead of being equal to "100"'),null):n},t.prototype.getEligibleCampaigns=function(){var e=this,n=[],r=this.visitorId,o=this.visitorContext,a=this.log,s=this.data,u=function(t,e){a.warn('getEligibleCampaigns - operator "'+e+'" is not supported for type "'+t+'". Assertion aborted.')},c=function(t,e,n,r){void 0===r&&(r={});return i(i({},{shouldHaveAllAssertionsValid:!1}),r).shouldHaveAllAssertionsValid?e.map((function(e){return n(t,e)})).filter((function(t){return!0===t})).length===e.length:e.map((function(e){return n(t,e)})).filter((function(t){return!0===t})).length>0},f=function(t,e){var n=t.operator,i=t.key,s=t.value,f=e?r:o[i];if(null==f)return a.debug('getEligibleCampaigns - Assertion aborted because visitor context key (="'+i+'") does not exist'),!1;var l=function(t,e,n){return"object"!=typeof e&&typeof t!=typeof e?(a.error('getEligibleCampaigns - The bucketing API returned a value which have not the same type ("'+typeof t+'") as the visitor context key="'+n+'"'),!1):"object"!=typeof e||Array.isArray(e)?!(Array.isArray(e)&&e.filter((function(e){return typeof e!=typeof t})).length>0)||(a.error('getEligibleCampaigns - The bucketing API returned an array where some elements do not have same type ("'+typeof t+'") as the visitor context key="'+n+'"'),!1):(a.error("getEligibleCampaigns - The bucketing API returned a json object which is not supported by the SDK."),!1)};switch(n){case"EQUALS":return Array.isArray(s)?c(f,s,(function(t,e){return t===e})):f===s;case"NOT_EQUALS":return Array.isArray(s)?c(f,s,(function(t,e){return t!==e}),{shouldHaveAllAssertionsValid:!0}):f!==s;case"LOWER_THAN":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase()<e.toLowerCase()})):f.toLowerCase()<s.toLowerCase();case"number":return Array.isArray(s)?c(f,s,(function(t,e){return t<e})):f<s;case"boolean":default:return u("boolean","LOWER_THAN"),!1}case"LOWER_THAN_OR_EQUALS":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase()<=e.toLowerCase()})):f.toLowerCase()<=s.toLowerCase();case"number":return Array.isArray(s)?c(f,s,(function(t,e){return t<=e})):f<=s;case"boolean":default:return u("boolean","LOWER_THAN_OR_EQUALS"),!1}case"GREATER_THAN":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase()>e.toLowerCase()})):f.toLowerCase()>s.toLowerCase();case"number":return Array.isArray(s)?c(f,s,(function(t,e){return t>e})):f>s;case"boolean":default:return u("boolean","GREATER_THAN"),!1}case"GREATER_THAN_OR_EQUALS":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase()>=e.toLowerCase()})):f.toLowerCase()>=s.toLowerCase();case"number":return Array.isArray(s)?c(f,s,(function(t,e){return t>=e})):f>=s;case"boolean":default:return u("boolean","GREATER_THAN_OR_EQUALS"),!1}case"STARTS_WITH":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase().startsWith(e.toLowerCase())})):f.toLowerCase().startsWith(s.toLowerCase());case"number":return u("number","STARTS_WITH"),!1;case"boolean":default:return u("boolean","STARTS_WITH"),!1}case"ENDS_WITH":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase().endsWith(e.toLowerCase())})):f.toLowerCase().endsWith(s.toLowerCase());case"number":return u("number","ENDS_WITH"),!1;case"boolean":default:return u("boolean","ENDS_WITH"),!1}case"CONTAINS":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return t.toLowerCase().includes(e.toLowerCase())})):f.toLowerCase().includes(s.toLowerCase());case"number":return u("number","CONTAINS"),!1;case"boolean":default:return u("boolean","CONTAINS"),!1}case"NOT_CONTAINS":if(!l(f,s,i))return!1;switch(typeof f){case"string":return Array.isArray(s)?c(f,s,(function(t,e){return!t.toLowerCase().includes(e.toLowerCase())}),{shouldHaveAllAssertionsValid:!0}):!f.toLowerCase().includes(s.toLowerCase());case"number":return u("number","NOT_CONTAINS"),!1;case"boolean":default:return u("boolean","NOT_CONTAINS"),!1}default:return a.error('getEligibleCampaigns - unknown operator "'+n+'" found in bucketing api answer. Assertion aborted.'),!1}};return s&&s.campaigns?(s.campaigns.forEach((function(o){var s=null;if(o.variationGroups.forEach((function(t){if(null===s){var e=[];t.targeting.targetingGroups.forEach((function(t){var n=[];t.targetings.forEach((function(t){switch(t.key){case"fs_all_users":n.push(!0);break;case"fs_users":n.push(f(t,!0));break;default:n.push(f(t,!1))}})),e.push(0===n.filter((function(t){return!0!==t})).length)})),s=e.filter((function(t){return!0===t})).length>0?t.id:null}})),null!==s){a.debug('Bucketing - campaign (id="'+o.id+'") is matching visitor context');var u=i(i({},o),{variationGroups:o.variationGroups.filter((function(t){return t.id===s}))}),c=e.computeMurmurAlgorithm(u.variationGroups[0].variations,s);null!==c?n.push(t.transformIntoDecisionApiPayload(c,o,s)):a.debug('computeMurmurAlgorithm - Unable to find the corresponding variation (campaignId="'+o.id+'") using murmur for visitor (id="'+r+'"). This visitor will be untracked.')}else a.debug('Bucketing - campaign (id="'+o.id+'") NOT MATCHING visitor')})),n):(a.warn("getEligibleCampaigns - no bucketing data found"),n)},t}();e.default=s},function(t,e,n){(function(e,i){e.Buffer=e.Buffer||n(18).Buffer;const r=i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?i.from:t=>new i(t);const o={MurmurHashV2:function(t,e){i.isBuffer(t)||(t=r(t));for(var n,o=t.length,a=e^o,s=0;o>=4;)n=1540483477*(65535&(n=255&t[s]|(255&t[++s])<<8|(255&t[++s])<<16|(255&t[++s])<<24))+((1540483477*(n>>>16)&65535)<<16),a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)^(n=1540483477*(65535&(n^=n>>>24))+((1540483477*(n>>>16)&65535)<<16)),o-=4,++s;switch(o){case 3:a^=(255&t[s+2])<<16;case 2:a^=(255&t[s+1])<<8;case 1:a=1540483477*(65535&(a^=255&t[s]))+((1540483477*(a>>>16)&65535)<<16)}return a=1540483477*(65535&(a^=a>>>13))+((1540483477*(a>>>16)&65535)<<16),(a^=a>>>15)>>>0},MurmurHashV3:function(t,e){var n,o,a,s,u,c,f,l;for(i.isBuffer(t)||(t=r(t)),n=3&t.length,o=t.length-n,a=e,u=3432918353,c=461845907,l=0;l<o;)f=255&t[l]|(255&t[++l])<<8|(255&t[++l])<<16|(255&t[++l])<<24,++l,a=27492+(65535&(s=5*(65535&(a=(a^=f=(65535&(f=(f=(65535&f)*u+(((f>>>16)*u&65535)<<16)&4294967295)<<15|f>>>17))*c+(((f>>>16)*c&65535)<<16)&4294967295)<<13|a>>>19))+((5*(a>>>16)&65535)<<16)&4294967295))+((58964+(s>>>16)&65535)<<16);switch(f=0,n){case 3:f^=(255&t[l+2])<<16;case 2:f^=(255&t[l+1])<<8;case 1:a^=f=(65535&(f=(f=(65535&(f^=255&t[l]))*u+(((f>>>16)*u&65535)<<16)&4294967295)<<15|f>>>17))*c+(((f>>>16)*c&65535)<<16)&4294967295}return a^=t.length,a=2246822507*(65535&(a^=a>>>16))+((2246822507*(a>>>16)&65535)<<16)&4294967295,a=3266489909*(65535&(a^=a>>>13))+((3266489909*(a>>>16)&65535)<<16)&4294967295,(a^=a>>>16)>>>0}};t.exports=o}).call(this,n(17),n(18).Buffer)},function(t,e,n){"use strict";e.byteLength=function(t){var e=c(t),n=e[0],i=e[1];return 3*(n+i)/4-i},e.toByteArray=function(t){var e,n,i=c(t),a=i[0],s=i[1],u=new o(function(t,e,n){return 3*(e+n)/4-n}(0,a,s)),f=0,l=s>0?a-4:a;for(n=0;n<l;n+=4)e=r[t.charCodeAt(n)]<<18|r[t.charCodeAt(n+1)]<<12|r[t.charCodeAt(n+2)]<<6|r[t.charCodeAt(n+3)],u[f++]=e>>16&255,u[f++]=e>>8&255,u[f++]=255&e;2===s&&(e=r[t.charCodeAt(n)]<<2|r[t.charCodeAt(n+1)]>>4,u[f++]=255&e);1===s&&(e=r[t.charCodeAt(n)]<<10|r[t.charCodeAt(n+1)]<<4|r[t.charCodeAt(n+2)]>>2,u[f++]=e>>8&255,u[f++]=255&e);return u},e.fromByteArray=function(t){for(var e,n=t.length,r=n%3,o=[],a=0,s=n-r;a<s;a+=16383)o.push(f(t,a,a+16383>s?s:a+16383));1===r?(e=t[n-1],o.push(i[e>>2]+i[e<<4&63]+"==")):2===r&&(e=(t[n-2]<<8)+t[n-1],o.push(i[e>>10]+i[e>>4&63]+i[e<<2&63]+"="));return o.join("")};for(var i=[],r=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,u=a.length;s<u;++s)i[s]=a[s],r[a.charCodeAt(s)]=s;function c(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=t.indexOf("=");return-1===n&&(n=e),[n,n===e?0:4-n%4]}function f(t,e,n){for(var r,o,a=[],s=e;s<n;s+=3)r=(t[s]<<16&16711680)+(t[s+1]<<8&65280)+(255&t[s+2]),a.push(i[(o=r)>>18&63]+i[o>>12&63]+i[o>>6&63]+i[63&o]);return a.join("")}r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63},function(t,e){
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
e.read=function(t,e,n,i,r){var o,a,s=8*r-i-1,u=(1<<s)-1,c=u>>1,f=-7,l=n?r-1:0,d=n?-1:1,h=t[e+l];for(l+=d,o=h&(1<<-f)-1,h>>=-f,f+=s;f>0;o=256*o+t[e+l],l+=d,f-=8);for(a=o&(1<<-f)-1,o>>=-f,f+=i;f>0;a=256*a+t[e+l],l+=d,f-=8);if(0===o)o=1-c;else{if(o===u)return a?NaN:1/0*(h?-1:1);a+=Math.pow(2,i),o-=c}return(h?-1:1)*a*Math.pow(2,o-i)},e.write=function(t,e,n,i,r,o){var a,s,u,c=8*o-r-1,f=(1<<c)-1,l=f>>1,d=23===r?Math.pow(2,-24)-Math.pow(2,-77):0,h=i?0:o-1,p=i?1:-1,g=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,a=f):(a=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-a))<1&&(a--,u*=2),(e+=a+l>=1?d/u:d*Math.pow(2,1-l))*u>=2&&(a++,u/=2),a+l>=f?(s=0,a=f):a+l>=1?(s=(e*u-1)*Math.pow(2,r),a+=l):(s=e*Math.pow(2,l-1)*Math.pow(2,r),a=0));r>=8;t[n+h]=255&s,h+=p,s/=256,r-=8);for(a=a<<r|s,c+=r;c>0;t[n+h]=255&a,h+=p,a/=256,c-=8);t[n+h-p]|=128*g}},function(t,e){var n={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==n.call(t)}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(6),r=function(){function t(t){this.enabled=!1,this.beginDate=null,this.log=i.default.getLogger(t,"Flagship SDK - panic mode")}return t.prototype.setPanicModeTo=function(t,e){void 0===e&&(e={sendLogs:!0});var n=e.sendLogs;t!==this.enabled?(this.enabled=t,this.beginDate=!1===t?null:new Date,n&&this.log.info(t?"panic mode is ENABLED. SDK will turn into safe mode.":"panic mode is DISABLED. Everything is back to normal.")):n&&this.log.debug(t?"panic mode already ENABLED since "+this.beginDate.toDateString():"panic mode already DISABLED.")},t.prototype.checkPanicMode=function(t){var e=!!(null==t?void 0:t.panic);this.setPanicModeTo(e,{sendLogs:e!==this.enabled})},t.prototype.shouldRunSafeMode=function(t,e){void 0===e&&(e={logType:"error"});var n=e.logType;if(this.enabled)switch(n){case"debug":this.log.debug("Can't execute '"+t+"' because the SDK is in panic mode !");break;default:this.log.error("Can't execute '"+t+"' because the SDK is in panic mode !")}return this.enabled},t}();e.default=r},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i={deepCompare:function(t,e){return Object.prototype.toString.call(t)===Object.prototype.toString.call(e)&&("[object Object]"===Object.prototype.toString.call(t)||"[object Array]"===Object.prototype.toString.call(t)?Object.keys(t).length===Object.keys(e).length&&Object.keys(t).every((function(n){return i.deepCompare(t[n],e[n])})):t===e)},isServer:function(){return!("undefined"!=typeof window&&window.document)},isClient:function(){return!i.isServer()}};e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CLIENT_CACHE_KEY=void 0,e.CLIENT_CACHE_KEY="FS_CLIENT_VISITOR";var i={saveVisitorProfile:function(t,n){try{localStorage.setItem(e.CLIENT_CACHE_KEY,JSON.stringify(n))}catch(t){}},loadVisitorProfile:function(t){var n;try{n=localStorage.getItem(e.CLIENT_CACHE_KEY)}catch(t){n=null}return n?JSON.parse(n):null}};e.default=i}]).default}));
/**
 * Debounce method borrowed from Lodash
 * ====================================
 * Creates a function that delays invoking `func` until after `wait` milliseconds
 * have elapsed since the last time it was invoked. The created function comes
 * with a `cancel` method to cancel delayed invocations. Provide an options
 * object to indicate that `func` should be invoked on the leading and/or
 * trailing edge of the `wait` timeout. Subsequent calls to the debounced
 * function return the result of the last `func` invocation.
 *
 * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
 * on the trailing edge of the timeout only if the the debounced function is
 * invoked more than once during the `wait` timeout.
 *
 * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
 * for details over the differences between `_.debounce` and `_.throttle`.
 * 
 * @static
 * @memberOf _
 * @category Function
 * @param {Function} func The function to debounce.
 * @param {number} [wait=0] The number of milliseconds to delay.
 * @param {Object} [options] The options object.
 * @param {boolean} [options.leading=false] Specify invoking on the leading
 *  edge of the timeout.
 * @param {number} [options.maxWait] The maximum time `func` is allowed to be
 *  delayed before it is invoked.
 * @param {boolean} [options.trailing=true] Specify invoking on the trailing
 *  edge of the timeout.
 * @returns {Function} Returns the new debounced function.
 * @example
 *
 * // avoid costly calculations while the window size is in flux
 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
 *
 * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
 * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
     *   'leading': true,
     *   'trailing': false
     * }));
 *
 * // ensure `batchLog` is invoked once after 1 second of debounced calls
 * var source = new EventSource('/stream');
 * jQuery(source).on('message', _.debounce(batchLog, 250, {
     *   'maxWait': 1000
     * }));
 *
 * // cancel a debounced call
 * var todoChanges = _.debounce(batchLog, 1000);
 * Object.observe(models.todo, todoChanges);
 *
 * Object.observe(models, function(changes) {
     *   if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
     *     todoChanges.cancel();
     *   }
     * }, ['delete']);
 *
 * // ...at some point `models.todo` is changed
 * models.todo.completed = true;
 *
 * // ...before 1 second has passed `models.todo` is deleted
 * // which cancels the debounced `todoChanges` call
 * delete models.todo;
 */

 function debounce(func, wait, options) {
	'use strict';

	var args,
		maxTimeoutId,
		result,
		stamp,
		thisArg,
		timeoutId,
		trailingCall,
		lastCalled = 0,
		maxWait = false,
		trailing = true,
		leading,
		now = Date.now || function () {
			return new Date().getTime();
		};

	wait = wait < 0 ? 0 : (+wait || 0);
	if (options === true) {
		leading = true;
		trailing = false;
	} else if (jQuery.isPlainObject(options)) {
		leading = options.leading;
		maxWait = options.hasOwnProperty('maxWait') && Math.max(+options.maxWait || 0, wait);
		trailing = options.hasOwnProperty('trailing') ? options.trailing : trailing;
	}

	function cancel() {
		if (timeoutId) {
			clearTimeout(timeoutId);
		}
		if (maxTimeoutId) {
			clearTimeout(maxTimeoutId);
		}
		maxTimeoutId = timeoutId = trailingCall = undefined;
	}

	function delayed() {
		var remaining = wait - (now() - stamp),
			isCalled;
		if (remaining <= 0 || remaining > wait) {
			if (maxTimeoutId) {
				clearTimeout(maxTimeoutId);
			}
			isCalled = trailingCall;
			maxTimeoutId = timeoutId = trailingCall = undefined;
			if (isCalled) {
				lastCalled = now();
				result = func.apply(thisArg, args);
				if (!timeoutId && !maxTimeoutId) {
					args = thisArg = null;
				}
			}
		} else {
			timeoutId = setTimeout(delayed, remaining);
		}
	}

	function maxDelayed() {
		if (timeoutId) {
			clearTimeout(timeoutId);
		}
		maxTimeoutId = timeoutId = trailingCall = undefined;
		if (trailing || (maxWait !== wait)) {
			lastCalled = now();
			result = func.apply(thisArg, args);
			if (!timeoutId && !maxTimeoutId) {
				args = thisArg = null;
			}
		}
	}

	function debounced() {
		var leadingCall, remaining, isCalled;

		args = arguments;
		stamp = now();
		thisArg = this;
		trailingCall = trailing && (timeoutId || !leading);

		if (maxWait === false) {
			leadingCall = leading && !timeoutId;
		} else {
			if (!maxTimeoutId && !leading) {
				lastCalled = stamp;
			}
			remaining = maxWait - (stamp - lastCalled);
			isCalled = remaining <= 0 || remaining > maxWait;

			if (isCalled) {
				if (maxTimeoutId) {
					maxTimeoutId = clearTimeout(maxTimeoutId);
				}
				lastCalled = stamp;
				result = func.apply(thisArg, args);
			}
			else if (!maxTimeoutId) {
				maxTimeoutId = setTimeout(maxDelayed, remaining);
			}
		}
		if (isCalled && timeoutId) {
			timeoutId = clearTimeout(timeoutId);
		}
		else if (!timeoutId && wait !== maxWait) {
			timeoutId = setTimeout(delayed, wait);
		}
		if (leadingCall) {
			isCalled = true;
			result = func.apply(thisArg, args);
		}
		if (isCalled && !timeoutId && !maxTimeoutId) {
			args = thisArg = null;
		}
		return result;
	}
	debounced.cancel = cancel;
	return debounced;
}

/**
 * Window resize handler binding with a check for IE8 (which triggers resize on changes in the HTML).
 */
(function ($) {

	if ($.fn.accordion) {
		$('.accordion')
			.accordion({ 'openPanelId': 1 })
			.find('.accordion-header')
			.on('click', function () {
				var
					header = $(this);
				if (header.is('.active') && window.animatedScrollTo) {
					window.animatedScrollTo(header.offset().top - 70);
				}
			});
	}

	var $window = $(window),
		resizeHandlers = [],
		oldIE = document.all && !document.getElementsByClassName,
		observing = false,
		currentWidth, currentHeight;


    /**
     * Prevent default and open link in 'popup' window
     */
	function setExternalPopup() {
		$('.popup-extern').each(function () {
			var externalPopup = $(this);
			externalPopup
				.find('a')
				.off('click.externalPopup')
				.on('click.externalPopup', function (event) {
					event.preventDefault();
					if (!externalPopup.is('disabled') && !externalPopup.hasClass('unavailable')) {
						window
							.open(
								this.href,
								'chat',
								'status=no,location=no,toolbar=no,width=800,height=500,resizable=yes')
							.trigger('focus');
					}
				});
		});
	}
	window.setExternalPopup = setExternalPopup;
	setExternalPopup();

	function handleControlledResize() {
		var newWidth = $window.width(),
			newHeight = $window.height(),
			args = arguments;

		if (newWidth !== currentWidth || newHeight !== currentHeight) {
			currentWidth = newWidth;
			currentHeight = newHeight;
			$.each(resizeHandlers, function (i, handler) {
				return handler.apply(window, args);
			});
		}
	}

	function addResizeHandler(handler) {
		if (oldIE) {
			resizeHandlers.push(handler);
			if (!observing) {
				$(window).on('resize', debounce(handleControlledResize, 100, { 'maxWait': 500 }));
			}
		} else {
			$window.on('resize', debounce(handler, 100, { 'maxWait': 500 }));
		}
	}

	window.addResizeHandler = addResizeHandler;
}(jQuery));

var matchedMedia = (function () {
	var retina = '(-webkit-min-device-pixel-ratio: 2), '
		+ '(-moz-min-device-pixel-ratio: 2), '
		+ '(min-resolution: 2dppx), '
		+ '(min-resolution: 192dpi)',
		media = {
			'mobile-portrait': 'screen and (min-width: 320px)',
			'mobile-landscape': 'screen and (min-width: 480px)',
			'tablet-portrait': 'screen and (min-width: 661px)', // 768px
			'tablet-landscape': 'screen and (min-width: 1000px)', // 1024px
			'desktop': 'screen and (min-width: 1151px)'
		},
		matchedMedia = {
			'retina': window.matchMedia(retina).matches
		},
		retinaPostFix = '-x2',
		defaultMedia = jQuery.extend({}, media),
		keys, key;

	if (matchedMedia.retina) {
		for (key in defaultMedia) {
			if (defaultMedia.hasOwnProperty(key)) {
				media[key + retinaPostFix] = media[key];
			}
		}
	}

    /**
     * Updates the matched media to the current state
     */
	function updateMatchedMedia() {
		var medium;
		keys = [];
		for (medium in media) {
			if (media.hasOwnProperty(medium)) {
				if (matchedMedia[medium] = window.matchMedia(media[medium]).matches) {
					keys.push(medium);
				}
			}
		}
	}

	updateMatchedMedia();

	// Create a resize handler
	addResizeHandler(updateMatchedMedia);

	return function () {
		return {
			'keys': keys,
			'media': matchedMedia,
			'matches': function (medium) {
				return keys.indexOf(medium) >= 0;
			}
		};
	};
}());

/**
 * jQuery plug-ins
 */
(function ($) {
	'use strict';

	$.fn.renderHandleBars = function (context) {
		return this.each(function () {
			var
				self = $(this),
				data = self.data('handleBarsData'),
				template = data && data.template ? data.template : Handlebars.compile(
					self
						.find('script')
						.html()
				);
			context = $.extend(
				true,
				data && data.context ? data.context : self.data(),
				context || {}
			);
			self
				.html(
					template(
						context
					)
				)
				.data('handleBarsData', {
					template: template,
					context: context
				});
		});
	}

	/**
	 * Adds responsive behavior to images
	 * @returns {jQuery}
	 */
	$.fn.responsiveImage = $.fn.responsiveImage || function () {
		var images = $(this);

		/**
		 * Updates the image sources
		 */
		function updateSources() {
			var image = $(this),
				originalSrc = image.data('original-src'),
				currentSrc = image.attr('src'),
				breakpoint = matchedMedia(),
				allowHide = false,
				newSrc,
				src,
				i;

			if (!originalSrc) {
				originalSrc = currentSrc;
				image.data('original-src', currentSrc);
				allowHide = true;
			}

			// walk backwards from largest medium to smallest
			for (i = breakpoint.keys.length - 1; i >= 0; i--) {
				src = image.data('src-' + breakpoint.keys[i]);
				if (breakpoint.media[breakpoint.keys[i]] && src) {
					newSrc = src;
					break;
				}
			}

			if (allowHide) {
				if (newSrc && newSrc !== currentSrc) {
					// show the image hidden in the stylesheet
					image
						.one('load', function () {
							setTimeout(function () {
								image.addClass('visible');
							}, 10);
						});
				} else {
					image.addClass('visible');
				}
			}

			// set the new src
			if (newSrc) {
				if (newSrc !== currentSrc) {
					image.attr('src', newSrc);
				}
			} else if (currentSrc !== originalSrc) {
				// revert back to the original source
				image.attr('src', originalSrc);
			}
		}

		// Create a resize handler
		addResizeHandler(function () {
			images.each(updateSources);
		});

		return images.each(updateSources);
	};

	$(window)
		.on('onLoginRequested onLogoutRequested', function(event) {
			var cookie = new Cookie('login-redirect', document.location.href).setDays(.02); // approx 30 minutes
			cookie.path = '/';
			cookie.write();
		})
		.on('onAuthenticationChange', function (event) {
			if (event.detail) {
				window.userDetails = event.detail;
				$(window).trigger('userDetails', window.userDetails);
			}
		});
	
	(function(checkHideElements) {
		if (window.userDetails) {
			checkHideElements();
		}
		$(window).on('userDetails', checkHideElements);
	})(function() {
		$('[data-hide-when-logged-in-business=true]')
			.toggle(!window.userDetails.authenticated);
	});

	$(window).on('userDetails', function(userDetails) {
		var quickLinks = document.getElementsByTagName('pnl-quicklinks');
		if (
			window.userDetails.authenticated
			&& window.userDetails.portal == 'businessportal'
			&& quickLinks.length && $(quickLinks[0].shadowRoot).find('[for-business-module]').length
		) {
			$.get({
				url: "/account/getmodules/?idToken=" + window.userDetails.id_token,
				success: function(result) {
					window.userBusinessDetails = window.userBusinessDetails || {};
					window.userBusinessDetails.accessForModules = result.data.accessForModules;

					var evt = new CustomEvent("userBusinessDetails", window.userBusinessDetails);
					window.dispatchEvent(evt);
				}
			});
		}
	});

	/* cookie notice */
	(function (container) {
		if (!container.length) {
			// old implementation
			/* cookie policy bar h#$%ckery */
			var $container = $('#cookiebar-container');
			$container.find("link[rel='stylesheet']").remove();

			// returns true, false or null if not (properly) set;
			window.hasCookiePermission = function () {

				// for testing purposes without loaded cookie script
				if (typeof TOL_showToestemming !== 'function') {
					return true;
				}
				if (JSON === undefined || typeof JSON.parse !== 'function') {
					return null;
				}
				try {
					var Allow = JSON.parse(getCookie()).Allow;
					return Allow === false || Allow === true ? Allow : null;
				}
				catch (err) {
					return null;
				}
			};

			if (window.hasCookiePermission() === null) {
				if (window.location.pathname === "/privacy-verklaring/" || window.location.pathname === "/cookie-verklaring/" || window.location.pathname === "/privacy-statement/" || window.location.pathname === "/cookie-statement/" || window.location.pathname === "/datenschutzerklarung/" || window.location.pathname === "/cookie-erklarung/") {
					$container.hide();
				}
				else {
					TOL_showToestemming();
					$.magnificPopup.open({
						mainClass: 'cookiewall',
						showCloseBtn: false,
						enableEscapeKey: false,
						closeOnBgClick: false,
						items: {
							type: 'inline',
							src: '#cookiebar-container'
						}
					});
				}
			} else {
				$container.hide();
			}
		} else {
			(function (w, d, o) {
				var e = d.createElement('script');
				e.async = true;
				e.src = (container.data('url') || 'https://jouw.postnl.nl/widgets/cookie-widget/bootstrap.js?') +
					(new Date().getTime());
				var s = d.getElementsByTagName('script')[0];
				s.parentNode.insertBefore(e, s);
				e.onload = function () {
					try {
						w.PostNL = w.PostNL || {};
						w.PostNL.CookieWidget = new w.CookieWidget.Bootstrap(d, e,
							o).getAPI();
					} catch (e) {
						console.error('Error starting CookieWidget');
						console.error(e);
					}
				};
			})(window, document, {
				Element: container,
				Language: container.data('lang'),
				Events: {
				}
			});
		}
	}($('#cookie-notice')));

	/**
	 * Get flagship campaigns and variations
	 */
	(function() {
		var
			currentPath = document.location.pathname,
			isActiveSlug = function(slug) {
				return currentPath.startsWith(slug);
			}
		
		/**
		 * Create or retrieve visitor id for consistent rendering
		 */
		window.flagShipVisitorId = document.cookie.split('visitorId=')[1];
		if (flagShipVisitorId) {
			flagShipVisitorId = flagShipVisitorId.split(';')[0];
		} else {
			flagShipVisitorId = (function() { // Public Domain/MIT
				var d = new Date().getTime();
				if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
					d += performance.now(); //use high-precision timer if available
				}
				return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
					function (c) {
						var r = (d + Math.random() * 16) % 16 | 0;
						d = Math.floor(d / 16);
						return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
					});
			})();
			document.cookie = 'visitorId=' + flagShipVisitorId + ';path=/;max-age=31536000';
		}

		/**
		 * Measure active flags
		 */
		window.flagShipVisitor = Flagship
			.start(
				window.flagshipEnvironmentId,
				window.flagshipApiKey, {
					flagshipApi: window.flagShipEndpoint + '/v2/',
			})
			.newVisitor(flagShipVisitorId, {
				browser: navigator.userAgent.toLowerCase(),
				websitekey: $('meta[name=websiteKey]').attr('content')
			})
			.on('ready', function() {
				this.getAllModifications()
					.then(function(result) {
						if (result.data && result.data.campaigns && result.data.campaigns.length) {
							window.flagShipCampaigns = result.data.campaigns;
							// To reduce the number of calls, only measure what flagship tells us to measure
							// and only measure once per session
							if (document.cookie.indexOf('; fsm=1') === -1) {
								var
									measureCampaigns = [],
									dispatch = function() {
										document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
											detail: {
												visitor: {
													'ab_test_variation': measureCampaigns.map(function(campaign) {return '[' + campaign.id + ']-[' + campaign.variation.id + ']'}).join(),
												},
												name: 'flagship_delayed_ab_test'
											}
										}));
										document.cookie = 'fsm=1;path=/';
									};
								result.data.campaigns.forEach(function(campaign) {
									var
										measure = campaign.variation.modifications.value.measure;
									if (
										typeof measure == 'boolean' && measure
										|| typeof measure == 'string' && isActiveSlug(measure)
										|| Array.isArray(measure) && measure.some(isActiveSlug)
									) {
										measureCampaigns.push(campaign);
									}
								});
								if (measureCampaigns.length) {
									if (window.dataLayer) {
										dispatch();
									} else {
										window.document.body.addEventListener('pnl_datalayer_update', function(event) {
											if (event.detail.reason && event.detail.reason == 'page-load') {
												dispatch();
											}
										});
									}
								}
							}
						}
					});

			});

		/**
		 * Ask flagship if supernav should be shown
		 */
		(function(superHeader, classicHeader) {
			if (classicHeader.length && superHeader.length) {
				var
					templateAlreadyInserted = false,
					maybeAdd = function(template) {
						if (!templateAlreadyInserted) {
							template.after(
								template[0].content.cloneNode(true)
							);
							templateAlreadyInserted = true;
							if (template == classicHeader) {
								PNLNav.Site.init();
								PNLNav.GSA.init();
							}
						}
					};
				// Show default header if flagship timeout or error
				setTimeout(
					function() {
						var
							path = document.location.pathname;
						if (path.startsWith('/over-postnl/') || path.startsWith('/en/about-postnl/')) {
							maybeAdd(superHeader);
						} else {
							maybeAdd(classicHeader);
						}
					}, 
					500
				);
				flagShipVisitor
					.on('ready', function() {
						this.getModificationsForCampaign(flagshipUninavId)
							.then(function(result) {
								maybeAdd(
									result.data && result.data.campaigns && result.data.campaigns.length
									&& result.data.campaigns[0].variation.modifications.value.showForSlug.some(isActiveSlug)
										? superHeader
										: classicHeader
								);
							});

					});
			}
		})($('#super-menu'), $('#classic-menu'));

	})();

	/**
	 * Adds a collapsible behavior to elements
	 * @param {object} [options] Additional settings for the collapsible:
	 * - toggleSelector    {string}   The selector to find the collapsible toggle, defaults to '.collapsible-toggle'.
	 * - collapsedClass    {string}   Class applied to collapsible target when hidden/toggled/collapsed, defaults to 'collapsed'.
	 * - toggledClass      {string}   Class applied to collapsible toggle when hidden/toggled/collapsed, defaults to 'toggled'.
	 * - animationDuration {int}      The duration of the show/hide animation, defaults to 400.
	 * - animationEasing   {string}   Easing function used by the animation, defaults to 'swing'.
	 * - toggleFunction    {Function} Function to toggle the collapsible target, defaults to $.fn.slideToggle.
	 * - hideFunction      {Function} Function to hide the collapsible target after initialisation, defaults to $.fn.hide.
	 * - toggleText        {string}   String for the default or 'open' state of the toggle
	 * - toggledText       {string}   String for hte toggled or 'closed' state of the toggle
	 * - updateOnResize    {boolean}  Set to false to disable the recalculation of the height of the collapsible when the window resizes.
	 *
	 * @returns {jQuery}
	 */
	$.fn.collapsible = function (options) {
		var settings = $.extend({}, {
			toggleSelector: '.collapsible-toggle',
			collapseOthers: 'collapse-others',
			collapsedClass: 'collapsed',
			togglingClass: 'toggling',
			toggledClass: 'toggled',
			animationDuration: 400,
			animationEasing: 'swing',
			toggleFunction: $.fn.slideToggle,
			hideFunction: $.fn.hide,
			showFunction: $.fn.show,
			toggleText: null,
			toggledText: null,
			updateOnResize: true
		}, options),
			$window = $(window),
			$html = $(document.documentElement),
			windowWidth = $window.width(),
			toggles = $(settings.toggleSelector),
			collapsibles = this,
			updateTimer;

		if (this.length && $html.data('collapsible-observer') !== settings.toggleSelector) {
			$html
				.data('collapsible-observer', settings.toggleSelector)
				.on('click', settings.toggleSelector, function (event) {
					var toggle = $(this),
						collapsible = toggle.data('collapsible');

					event.preventDefault();
					if (collapsible) {
						collapsible.trigger('toggle.collapsible');
					}
				});
		}

		collapsibles.each(function () {
			var collapsible = $(this),
				toggle = (function () {
					var id = collapsible.attr('id'),
						elements = [];

					if (id) {
						elements = toggles.filter('[href="#' + id + '"]');
					}

					if (!elements.length) {
						elements = collapsible.prevAll(settings.toggleSelector).first();
					}

					return elements;
				}()),
				padding = collapsible.css(['padding-top', 'padding-bottom']),
				collapsed;

			function updateText() {
				if (settings.toggleText && settings.toggledText) {
					toggle.html(collapsed ? settings.toggledText : settings.toggleText);
				}
				collapsible.attr('aria-hidden', collapsed);
			}

			if (toggle.length) {
				toggle.data('collapsible', collapsible);
				collapsible.data('collapsible-toggle', toggle);
				collapsed = collapsible.hasClass(settings.collapsedClass);

				collapsible.on('hide.collapsible', function () {
					settings.hideFunction.apply(collapsible);
					collapsed = true;
					updateText();
				});

				collapsible.on('show.collapsible', function () {
					settings.showFunction.apply(collapsible);
					collapsed = false;

					updateText();
				});

				collapsible.on('toggle.collapsible', function (event, bubble) {
					collapsed = !collapsed;
					toggle.toggleClass(settings.toggledClass, collapsed);
					toggle.addClass(settings.togglingClass);

					settings.toggleFunction.apply(collapsible.stop(), [settings.animationDuration, settings.animationEasing, function () {
						collapsible.toggleClass(settings.collapsedClass, collapsed);
						toggle.removeClass(settings.togglingClass);
					}]);

					if (bubble != false && collapsible.hasClass(settings.collapseOthers)) {
						collapsible.parents('.block').find('.' + settings.collapseOthers).not(collapsible).not('.collapsed').trigger('toggle.collapsible', [false]);
					}

					if ($(this).parents('.faq-detail-component').length && !collapsed) {
						document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
							detail: {
								name: "in_page_interaction",
								in_page: {
									"name": $(this).prev().text(),
									"category": "faq",
									"location": "body"
								}
							}
						})
						);
					}

					updateText();
				});

				/**
				 * Recalculates the height of the collapsible which is fixed by jQuery
				 */
				collapsible.on('update.collapsible', function () {
					if (collapsed) {
						collapsible.css(padding);
						settings.showFunction.apply(collapsible);
					}

					collapsible
						// Reset height
						.css('height', 'auto')
						// and fixate it again
						.css('height', collapsible.height());

					if (collapsed) {
						settings.hideFunction.apply(collapsible);
					}
				});

				if (collapsed) {
					settings.hideFunction.apply(collapsible);
				}
				toggle.toggleClass(settings.toggledClass, collapsed);
				updateText();
			}
		});

		if (settings.updateOnResize) {
			addResizeHandler(function () {
				var newWindowWidth = $window.width();
				if (newWindowWidth !== windowWidth) {
					window.clearTimeout(updateTimer);
					updateTimer = window.setTimeout(function () {
						collapsibles.trigger('update.collapsible');
						windowWidth = newWindowWidth;
					}, 500);
				}
			});
		}

		return collapsibles;
	};

	/**
	 * Equalizes the same property on each item in each scope resulting in equal values for each 'row' in the scope.
	 * @param {object} [options]
	 * - scopeSelector           {string}     The selector used to determine each 'column'.
	 * - itemSelector            {string}     The selector used to determine each 'row'.
	 * - readProperty            {string}     The CSS property which is read and fed to the equalisation function.
	 * - applyProperty           {string}     The CSS property which is applied to each item with the equalised value.
	 * - resetApplyProperty      {int|string} The apply property is reset to this value before the read property is polled.
	 * - resizingClass           {string}     The container receives this class before the items are polled. This allows you
	 *                                        to use CSS to, for example, undo absolute positioning of specific items.
	 * - equalisationFunction    {Function}   Function used to calculate the value which is applied to each item in a row.
	 *                                        The function receives an array of polled values. Defaults to Math.max().
	 * - firstEqualisationDelay  {int}        The first equalisation is delayed by this amount of milliseconds.
	 * - resizeEqualisationDelay {int}        On window resize, delay the equalisation by this amount of milliseconds.
	 * - mode                    {string}     Use 'flat' to simply equalize all items or 'rows' to equalize each 'row' in each 'column'.
	 *
	 * @returns jQuery
	 */
	$.fn.equalizeStyle = function (options) {
		var defaults = {
			scopeSelector: '.column',
			itemSelector: '.row',
			readProperty: 'height',
			applyProperty: 'min-height',
			defaultPropertyValue: 0,
			resetApplyPropertyValue: 0,
			resizingClass: 'resizing',
			mode: 'columned',
			equalisationFunction: function (rowValues) {
				return Math.max.apply(Math, rowValues);
			},
			firstEqualisationDelay: 500,
			resizeEqualisationDelay: 50
		},
			settings = $.extend({}, defaults, options),
			containers = $(this),
			resizeTimer;

		containers.each(function () {
			var container = $(this),
				scopeSelector = container.data('eq-scope') || settings.scopeSelector,
				itemSelector = container.data('eq-item') || settings.itemSelector,
				mode = container.data('eq-mode') || settings.mode,
				when = container.data('eq-when'),
				columns, columnCount, items, itemCount;

			if (mode === 'flat') {
				items = container.find(itemSelector).map(function () {
					return $(this);
				});
				columnCount = items.length;
				itemCount = 1;
			} else {
				columns = container.find(scopeSelector);
				columnCount = columns.length;
				items = columns.map(function () {
					return $(this).find(itemSelector);
				});
				itemCount = items[0].length;
			}

			function equalize() {
				var x, y, rowValues, rowItems, item, itemHeight, rowMax;
				if (when && !matchedMedia().matches(when)) {
					for (y = 0; y < itemCount; y++) {
						for (x = 0; x < columnCount; x++) {
							items[x].eq(y).css(settings.applyProperty, settings.defaultPropertyValue);
						}
					}
					return;
				}

				// add the resizing class to be able to prepare the element to be measured using CSS:
				container.addClass(settings.resizingClass);
				for (y = 0; y < itemCount; y++) {
					rowValues = [];
					rowItems = $();
					// Collect each row
					for (x = 0; x < columnCount; x++) {
						item = items[x].eq(y);
						rowItems = rowItems.add(item);
						// reset the (possibly) previous applied property to the default value:
						item.css(settings.applyProperty, settings.resetApplyPropertyValue);
						// now read the 'read property' and store it:
						itemHeight = parseInt(item.css(settings.readProperty), 10);
						if (!isNaN(itemHeight)) {
							rowValues.push(itemHeight);
						}
					}
					// determine the maximum value:
					rowMax = settings.equalisationFunction(rowValues);
					// apply the max property to each item in the row:
					rowItems.css(settings.applyProperty, rowMax);
				}
				// remove the resizing class again:
				container.removeClass(settings.resizingClass);
			}

			container.on('resizeContainers.eqStyle', equalize);
		});

		// Delay the first equalize call for
		window.setTimeout(function () {
			containers.trigger('resizeContainers.eqStyle');
		}, settings.firstEqualisationDelay);

		addResizeHandler(function () {
			containers.trigger('resizeContainers.eqStyle');
		});

		return containers;
	};

	/**
	 * Collapsible list
	 */
	$.fn.collapsibleList = function () {
		var lists = $(this).each(function () {
			var list = $(this),
				items = list.children(),
				limit = window.parseInt(list.data('limit')),
				others = items.length - limit,
				moreText = list.data('more'),
				lessText = list.data('less'),
				collapsed = false,
				defaultHeight,
				collapsedHeight,
				moreLink;

			function setStateHeights() {
				list.css('height', 'auto');
				defaultHeight = list.height();
				items.each(function (i, item) {
					item = $(item);
					if (i >= limit) {
						item.hide();
					} else {
						item.show();
					}
				});

				collapsedHeight = list.height();
				if (!collapsed) {
					list.height('auto');
				}
				items.show();
			}

			function updateToggle() {
				moreLink
					.toggleClass('collapsed', collapsed)
					.text(collapsed ? (moreText + ' (' + others + ')') : lessText);
			}

			function toggle(force) {
				force = force !== undefined ? force : collapsed;
				list.stop().animate({
					height: force ? collapsedHeight : defaultHeight
				}, 400, updateToggle);
			}

			if (limit && items.length > limit) {
				setStateHeights();
				moreLink = $('<a>', {
					'class': 'more-link',
					'href': '#'
				}).on('click', function (event) {
					event.preventDefault();
					toggle(!collapsed);
					collapsed = !collapsed;
				});

				$('<p>', {
					'class': 'collapsible-list-toggle'
				}).append(moreLink).insertAfter(list);

				if (list.hasClass('collapsed')) {
					collapsed = true;
					toggle();
				}

				updateToggle();

				list.on('update.collapsibleList', function () {
					setStateHeights();
					list.height(collapsed ? collapsedHeight : defaultHeight);
				});
			}
		}), timer;

		//addResizeHandler
		addResizeHandler(function () {
			window.clearTimeout(timer);
			timer = window.setTimeout(function () {
				lists.trigger('update.collapsibleList');
			}, 500);
		});
	};

	/**
	 * Conditionally display an element based on the state or value of other elements.
	 *
	 * The settings are retrieved from data-* attributes from the element.
	 * - data-cd-fields="[selector]" - A selector specifying the elements to be checked e.g. "input[name=foo]".
	 * - data-cd-filter="[filter]" - An optional filter which is applied on each change on the fields e.g. ":checked"
	 * - data-cd-values="value1, value2" - A list of field values for which the element is displayed.
	 * - data-cd-value="value" - Same as 'values' but doesn't split the string into multiple values.
	 *
	 * @returns {jQuery}
	 */
	$.fn.conditionalDisplay = function () {
		return $(this).each(function () {
			var element = $(this),
				fields = $(element.data('cd-fields')),
				filter = element.data('cd-filter'),
				values = element.data('cd-values'),
				visible;

			if (!values) {
				values = element.data('cd-value');
			}
			values = values ? values.split(/[,\s]{1,}/) : [];

			function isVisible() {
				var filtered = fields;
				if (filter) {
					filtered = filtered.filter(filter);
				}
				if (values) {
					filtered = filtered.filter(function () {
						return values.indexOf($(this).val()) >= 0;
					});
				}
				return !!filtered.length;
			}

			fields
				.on('change keyup', function () {
					var currentState = visible;
					visible = isVisible();
					element.toggleClass('hidden', !visible);
					if (visible !== currentState) {
						element.trigger('change.conditionalDisplay');
					}
				})
				.trigger('change', [false]);
		});
	};

	/**
	 * A date range select behavior, enables or disables the options in the other select element according to the value
	 * selected in this select.
	 *
	 * @param {object} [options]
	 * - isOptionDisabledMethod {Function} A function that determines whether an option should be disabled. See it's
	 *   documentation for more information.
	 * - toggleOptionMethod {Function} The function used to enable or disable an option. See it's documentation for more
	 *   information.
	 *
	 * @returns {jQuery}
	 */
	$.fn.dateRangeSelect = function (options) {
		var defaults = {
			/**
			 * Determines whether this option should be disabled. The function is bound to the extended option element.
			 * @param {int} value The value of the option
			 * @param {int} otherValue The value of the other select
			 * @param {object} parameters An object literal with the following properties:
			 * - select {jQuery} The select element,
			 * - index {int} The index of this option
			 * - options {jQuery} All options in the select element
			 * - range {string} Either 'from' or 'to' depending on the role of this select
			 * - other {jQuery} The 'other' select element
			 *
			 * @returns {boolean}
			 */
			isOptionDisabledMethod: function (value, otherValue, parameters) {
				value = parseInt(value, 10);
				otherValue = parseInt(otherValue, 10);

				return (parameters.range === 'from' && value > otherValue)
					|| (parameters.range === 'to' && value < otherValue);
			},
			/**
			 * The function used to enable or disable an option. The function is bound to the extended option
			 * element. Override this to allow enabling or disabling an option using a select box replacement plugin.
			 * @param {boolean} disabled Whether the option should be disabled
			 * @param {object} parameters An object literal with the following properties:
			 * - select {jQuery} The select element
			 * - index {int} The index of this option
			 * - options {jQuery} All options in the select element
			 * - range {string} Either 'from' or 'to' depending on the role of this select
			 * - other {jQuery} The 'other' select element
			 */
			toggleOptionMethod: function (disabled, parameters) {
				this.prop('disabled', disabled);
			}
		},
			settings = $.extend({}, defaults, options);

		return $(this).each(function () {
			var select = $(this),
				$options = select.find('option'),
				range = select.data('range') || 'from',
				other = $(select.data(range === 'from' ? 'to' : 'from'));

			select.on('update.dateRangeSelect', function () {
				var otherValue = other.val();

				$options.each(function (index) {
					var option = $(this),
						value = option.attr('value'),
						parameters = {
							select: select,
							options: $options,
							range: range,
							other: other,
							index: index
						},
						disabled;

					if (value !== undefined) {
						disabled = settings.isOptionDisabledMethod.call(option, value, otherValue, parameters);
						settings.toggleOptionMethod.call(option, disabled, parameters);
					}
				});
			});

			select.on('change', function () {
				other.trigger('update.dateRangeSelect');
			});
		});
	};

	/**
	 * Converts the given elements to fake select elements
	 * @param {Object} [options]
	 * @returns {jQuery}
	 */
	$.fn.fakeSelect = function (options) {
		var defaults = {
			componentSelectors: {
				value: '.select-value',
				list: '.select-list',
				listItem: '.select-option'
			},
			classes: {
				open: 'is-open',
				closed: 'is-closed',
				selected: 'is-selected'
			},
			callbacks: {
				opened: $.noop,
				closed: $.noop,
				toggled: $.noop,
				changed: $.noop
			},
			outsideEvents: 'click touchend'
		},
			settings = $.extend({}, defaults, options),
			dataKey = 'FakeSelect',
			$document = $(document);

		/**
		 * Creates a fake select from the given element
		 * @param {jQuery} $container
		 * @constructor
		 */
		function FakeSelect($container) {
			var self = this;

			this.settings = settings;

			this.$container = $container;
			this.$value = $container.find(settings.componentSelectors.value);
			this.value = this.$value.html();
			this.$list = $container.find(settings.componentSelectors.list);
			this.$items = this.$list.find(settings.componentSelectors.listItem);
			this.$selectedItem = this.$items.filter('.' + settings.classes.selected);

			if (!this.$selectedItem.length) {
				this.$selectedItem = this.$items.filter(function () {
					return self.value === self.valueFromItem($(this));
				});
			}
			if (!this.$selectedItem.length) {
				this.$selectedItem = this.$items.first();
			}
			if (this.$selectedItem.length && !this.$selectedItem.hasClass(settings.classes.selected)) {
				this.select(this.$selectedItem);
			}

			this.isOpen = $container.hasClass(settings.classes.open);
			this.toggle(this.isOpen);

			this.$value.on('touchstart', $.noop);

			this.$list.on('mouseleave', function () {
				self.close();
			});

			$container
				.on('click', settings.componentSelectors.value, function () {
					self.toggle();
				})
				.on('click', settings.componentSelectors.listItem, function () {
					if (self.select($(this))) {
						var cookie = new Cookie('Language');
						cookie.path = '/';
						cookie.write($(this).find("span").attr("class").replace("language", "").trim());
						self.close();
					}
				})
				.data(dataKey, this);
		}

		/**
		 * Opens the select
		 * @returns {Object} A Promise
		 */
		FakeSelect.prototype.open = function () {
			var $d = $.Deferred(),
				self = this,
				currentState = this.isOpen;

			this.$container.addClass(settings.classes.open).removeClass(settings.classes.closed);
			this.isOpen = true;
			if (!currentState) {
				settings.callbacks.opened(this);
			}

			window.setTimeout(function () {
				self.delayedCloseHandler = function (event) {
					if (!$.contains(self.$container.get(0), event.target)) {
						self.close();
					}
					self.delayedCloseHandler = null;
				};
				$document.one(settings.outsideEvents, self.delayedCloseHandler);
			}, 1);
			$d.resolve();
			return $d.promise();
		};

		/**
		 * Closes the select
		 * @returns {Object} A Promise
		 */
		FakeSelect.prototype.close = function () {
			var $d = $.Deferred(),
				currentState = this.isOpen;

			if (this.delayedCloseHandler) {
				$document.off(settings.outsideEvents, this.delayedCloseHandler);
			}
			this.$container.removeClass(settings.classes.open).addClass(settings.classes.closed);
			this.isOpen = false;
			if (currentState) {
				settings.callbacks.closed(this);
			}
			$d.resolve();
			return $d.promise();
		};

		/**
		 * Toggles the select
		 * @param {boolean} [state]
		 * @returns {Object} A Promise
		 */
		FakeSelect.prototype.toggle = function (state) {
			if (state === undefined) {
				state = !this.isOpen;
			}
			return state ? this.open() : this.close();
		};

		/**
		 * Selects the given item
		 * @param {number|jQuery} $item
		 * @returns {boolean} success
		 */
		FakeSelect.prototype.select = function ($item) {
			if ($.type($item) === 'number') {
				$item = this.$items.get($item);
			}
			if (this.$items.index($item) >= 0) {
				this.$items.removeClass(settings.classes.selected);
				$item.addClass(settings.classes.selected);
				this.$value.html(this.valueFromItem($item));
				settings.callbacks.changed(this, $item);
				return true;
			}
			return false;
		};

		/**
		 * Returns the string value from the given item
		 * @param {jQuery} $item
		 * @returns {String|null}
		 */
		FakeSelect.prototype.valueFromItem = function ($item) {
			if (this.$items.index($item) >= 0) {
				return $item.html();
			}
			return null;
		};

		return this.each(function () {
			var $container = $(this),
				instance = $container.data(dataKey);
			return instance || new FakeSelect($(this));
		});
	};
}(jQuery));

/**
 * DOM:loaded event
 */
jQuery(function ($) {
	'use strict';

	var $window = $(window),
		$html = $(document.documentElement),
		$body = $(document.body),
		isTouch = (window.ontouchstart !== undefined) || (!!window.DocumentTouch && document instanceof window.DocumentTouch),
		isMobile = (function () {
			function poll() {
				return $window.width() <= (660 - 15);
			}

			$window.on('resize', debounce(function () {
				isMobile = poll();
			}, 100));
			return poll();
		}()),
		// MenuOverlay is defined in header.js
		Overlay = window.MenuOverlay || {
			show: $.noop,
			hide: $.noop
		},
		tap = isTouch ? 'touchstart' : 'click',
		isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

	$html.toggleClass('is-ios', isIOS);

	// Scroll to #id after all web components rendered
	window.addEventListener('appload', function() {
		var
			targetElement = document.getElementById(document.location.hash.split('#')[1]);
		if (targetElement) {
			targetElement.scrollIntoView({
				behavior: 'smooth'
			});
		}
	});

	(function (welcome) {
		var
			renderUserInfo = function (user_info) {
				welcome.renderHandleBars({
					user: user_info
				})
			};
		if (welcome.length) {
			if (welcome.data('greeting')) {
				welcome.renderHandleBars({
					greeting: welcome.data('greeting').split(',')[Math.floor((new Date()).getHours() / 6)]
				});
				linearGradientHomePageBanner();
			}
			if (window.userDetails) {
				renderUserInfo(window.userDetails.user_info);
			} else {
				$window
					.on('userDetails', renderUserInfo);
			}
		}
	})($('.full-width.hero-image.page-title h1.title:has(script)'));

	/**
	 * Determine the js folder for the correct paths
	 * @type {string|jsFolder}
	 */
	window.jsFolder = window.jsFolder || (function () {
		var src = $('script[src*="\/main"]').first().attr('src'),
			match = src ? src.match(/(.*)main.*$/i) : null;
		if (match) {
			return match[1];
		}
		return '';
	}());

	/**
	 * Magnific popup translations
	 */
	if ($.magnificPopup) {
		$.extend(true, $.magnificPopup.defaults, {
			tClose: i18n.get('lightbox.close'), // Alt text on close button
			tLoading: i18n.get('lightbox.loading'), // Text that is displayed during loading. Can contain %curr% and %total% keys
			gallery: {
				tPrev: i18n.get('lightbox.previous'), // Alt text on left arrow
				tNext: i18n.get('lightbox.next'), // Alt text on right arrow
				tCounter: i18n.get('lightbox.counter') // Markup for "1 of 7" counter
			},
			image: {
				tError: i18n.get('lightbox.errors.image') // Error message when image could not be loaded
			},
			ajax: {
				tError: i18n.get('lightbox.errors.ajax') // Error message when ajax request failed
			}
		});
	}

	// initialize responsive tables:
	$('table:not(.skip-resonsiveTable)').each(function () {
		var
			fadeWidth,
			table = $(this),
			scroller = table
				.wrap('<div class="scroller"/>')
				.parent(),
			container = scroller
				.wrap('<div class="table-scroll-container"></div>')
				.parent(),
			fadeLeft = $('<div class="fade-gradient-left"/>'),
			fadeRight = $('<div class="fade-gradient-right"/>'),
			checkScrollables = function () {
				var
					scrollLeft = scroller.scrollLeft(),
					scrollRight = table.width() - scroller.width() - scrollLeft;
				// Move fade away when scrolling nears end
				fadeLeft.css({ transform: 'translateX(' + Math.min(2 * scrollLeft - fadeWidth, 0) + 'px)' });
				fadeRight.css({ transform: 'translateX(' + Math.max(-2 * scrollRight + fadeWidth, 0) + 'px)' });
			};
		container
			.prepend(fadeLeft)
			.append(fadeRight);
		fadeWidth = fadeLeft.width(); // Assume both left and right have same width
		scroller.scroll(debounce(checkScrollables, 10));
		$window.resize(debounce(checkScrollables, 200));
		checkScrollables();
	});

	// initialize responsive images:
	$('img.responsive').responsiveImage();
	// initialize conditional display elements:
	$('.conditional-display').conditionalDisplay();
	// initialize killer apps:
	if ($.fn.killerApp !== undefined) {
		$('.killer-app').killerApp({
			onActivate: function () {
				Overlay.show('killer-app');
			},
			onDeactivate: function () {
				Overlay.hide('killer-app');
			}
		});
	}
	if ($.fn.killerAppOld !== undefined) {
		$('.killer-app-old').killerAppOld({
			onActivate: function () {
				Overlay.show('killer-app');
			},
			onDeactivate: function () {
				Overlay.hide('killer-app');
			}
		});
	}

    /**
     * Equal height util
     * Function has been added to window to be able to re-execute the function.
     */
	function equalHeight() {
		// initialize equal height elements
		$('.equal-height').equalizeStyle();
	}

	equalHeight();

	window.equalHeight = equalHeight;

	// initialize fake selects:
	$('.fake-select').fakeSelect();

	if ($body.hasClass('full-width-header')) {
		(function ($swoosh) {
			var swooshOffset = $swoosh.offset().top;
			$window.on('scroll', debounce(function () {
				$html.toggleClass('scrolled-down', $window.scrollTop() > swooshOffset);
			}, 50, { 'maxWait': 100 }));
		}($('.swoosh')));
	}

	if (Modernizr.bgsizecover) {
		$('.cover-image').each(function () {
			var container = this,
				$container = $(container).addClass('cover-applied'),
				$desktopImage = $container.find('> .image:not(.image-tablet)').hide(),
				$tabletImage = $container.find('> .image.image-tablet').hide(),
				updateBgImg = function ($image) {
					$container.css({ 'background-image': 'url(' + $image.attr('src') + ')' });
				};

			if ($tabletImage.length) {
				var
					resizeHandler = function () {
						updateBgImg($(window).width() <= 660 ? $tabletImage : $desktopImage);
					}
				addResizeHandler(resizeHandler);
				resizeHandler();
			} else {
				updateBgImg($desktopImage);
			}

			function isInViewport(element, options) {
				var boundingRect = (options && options.rect) ? options.rect : element.getBoundingClientRect(),
					top = boundingRect.top,
					bottom = boundingRect.bottom,
					left = boundingRect.left,
					right = boundingRect.right,
					settings = options || { 'tolerance': 0 },
					isVisible = false,
					$viewport = (options && options.$viewport) ? options.$viewport : $window,
					viewportHeight = (options && options.viewportHeight) ? options.viewportHeight : $viewport.height(),
					viewportWidth = (options && options.viewportWidth) ? options.viewportWidth : $viewport.width();

				if (settings.tolerance < 0) {
					settings.tolerance = viewportHeight + settings.tolerance;
				}

				if (right <= 0 || left >= viewportWidth) {
					return isVisible;
				}

				isVisible = settings.tolerance ? !!(top <= settings.tolerance && bottom >= settings.tolerance) : !!(bottom > 0 && top <= viewportHeight);

				return isVisible;
			}

			if ($container.hasClass('animate-on-scroll')) {
				//$window.on('scroll', debounce(function () {
				$window.on('scroll', function () {
					var boundingRect = container.getBoundingClientRect(),
						viewportHeight = $window.height(),
						viewportWidth = $window.height(),
						startPosition = 50,
						rectCenter = boundingRect.top + (boundingRect.height / 2),
						offset, diff;

					// console.info(boundingRect);

					if (isInViewport(container, {
						rect: boundingRect,
						viewportHeight: viewportHeight,
						viewportWidth: viewportWidth,
						tolerance: 0
					})) {

						offset = (viewportHeight / 2) - rectCenter;
						diff = 30 * (offset / viewportHeight);
						$container.css('background-position-y', (startPosition + diff) + '%');
					}
				});
				//}, 100, {'maxWait': 150}));
			}
		});
	}

	/**
	 * Initialize collapsible elements:
	 * Collapsible elements can have an optional attribute `data-collapsible-show-items` which alters the collapsible
	 * to instead of collapsing to a height of `0` the collapsible will show a minimum amount of items when collapsed.
	 * The `data-collapsible-item-item` attribute contains a selector for the items to measure the height of. This
	 * attribute is only required when `collapsible-show-items` is set.
	 * The `data-collapsible-item-scope` attribute contains a selector for an optional scope in which items are
	 * searched for. The highest value for each scope is then used as the collapsed height of the collapsible.
	 */
	$('.collapsible').each(function () {
		var collapsible = $(this),
			settings = {
				toggleFunction: $.fn.slideToggle,
				hideFunction: $.fn.hide,
				showFunction: $.fn.show
			},
			showItems = collapsible.data('collapsible-show-items') || 0,
			itemSelector = collapsible.data('collapsible-item'),
			scopeSelector = collapsible.data('collapsible-item-scope'),
			defaultHeight = collapsible.height(),
			collapsibleWidth = collapsible.width(),
			collapsed = false,
			collapsedHeight = 0;

		function hide() {
			collapsed = true;
			return collapsible.height(collapsedHeight);
		}

		function show() {
			collapsed = false;
			return collapsible.height(defaultHeight);
		}

		// Do we want to show a minimum amount of items:
		if (showItems) {
			// calculate the collapsed height for the number of items we want to show
			collapsedHeight = (function () {
				var scopes = scopeSelector ? collapsible.find(scopeSelector) : collapsible,
					heights = scopes.map(function () {
						var scope = $(this),
							items = scope.find(itemSelector),
							height = 0;
						items.each(function (i) {
							var item = $(this);
							if (i < showItems) {
								height += (window.parseFloat(item.outerHeight()) + window.parseFloat(item.css('margin-top'))
									+ window.parseFloat(item.css('margin-bottom')));
								return true;
							}
							return false;
						});
						return height;
					});
				return Math.max.apply(Math, $.makeArray(heights));
			}());
			// custom show/hide functions which use our custom collapsed height
			settings.hideFunction = hide;
			settings.showFunction = show;
			// custom toggle function which uses our custom collapsed height
			settings.toggleFunction = function () {
				collapsible.stop().animate({
					'height': collapsed ? defaultHeight : collapsedHeight
				});
				collapsed = !collapsed;
			};
			// set a resize handler which updates the default height when the width of the collapsible has changed.
			$window.on('resize', debounce(function () {
				var newWidth = collapsible.width();
				if (newWidth !== collapsibleWidth) {
					defaultHeight = collapsible.height('auto').height();
					if (collapsed) {
						hide();
					} else {
						show();
					}
				}
			}, 1000));
		}

		collapsible.collapsible(settings);

		if (showItems) {
			collapsible.data('collapsible-toggle').addClass('toggling');
		}
	});

	$('dl.collapsible-items dd').collapsible({
		toggleSelector: 'dt'
	});

	$('.collapsible-list').collapsibleList();

	if ($.fn.selectBoxIt !== undefined) {
		// The date range behavior combined with the custom select box plugin
		$('.date-range').dateRangeSelect({
			toggleOptionMethod: function (disabled, parameters) {
				var api = parameters.select.data('selectBox-selectBoxIt');
				if (api) {
					api[disabled ? 'disableOption' : 'enableOption'](parameters.index);
				}
			}
		});
		// Initialize the selectBoxIt plugin
		var
			intervalId,
			disabledState = [],
			maxChecks = 30,
			selects = $('select.input');
		selects
			.each(function (selectNr) {
				disabledState[selectNr] = this.disabled;
			})
			.selectBoxIt({
				copyClasses: 'container'
			})
			// Enable selects in webpower
			.closest('form').find(':radio[data-condition], :checkbox[data-condition]')
			.on('change', function () {
				var
					checkNr = 0;
				clearInterval(intervalId);
				intervalId = setInterval(function () {
					checkNr++;
					selects.each(function (selectNr) {
						if (this.disabled !== disabledState[selectNr]) {
							$(this).selectBoxIt('refresh');
							disabledState[selectNr] = this.disabled;
						}
					});
					if (checkNr >= maxChecks) {
						clearInterval(intervalId);
					}
				}, 80);
			});

		// Select inputs with postweb styling
		// They are full width thus auto width is set to false
		$('.postweb select.input').each(function () {
			$(this).data('selectBox-selectBoxIt').setOptions({ autoWidth: false });
		});

	} else {
		// Date range behavior on a native select
		$('.date-range').dateRangeSelect();
	}

	/**
	 * In-page navigation interaction
	 */
	$('nav.sub-menu').each(function () {
		var menu = $(this),
			subMenus = menu.find('.children'),
			openMenus = menu.find('a.active').parents('.children');

		// create menu toggles and hide inactive sub menu's
		subMenus.each(function () {
			var subMenu = $(this),
				parent = subMenu.prev(),
				open = parent.hasClass('active') || openMenus.index(subMenu) >= 0;

			subMenu.before($('<a>', {
				'class': 'menu-toggle' + (open ? ' open' : ''),
				'href': parent.attr('href'),
				'html': open ? '+' : '-'
			}));
			if (!open) {
				subMenu.hide();
			}
		});

		menu
			// Toggle observer
			.on(tap, '.menu-toggle', function (event) {
				var toggle = $(this),
					subMenu = toggle.siblings('.children');
				event.preventDefault();
				toggle
					.html(subMenu.is(':visible') ? '+' : '-')
					.toggleClass('open');
				subMenu.stop().slideToggle('fast');
			})
			.find('.menu-toggle.open')
				.prev().addClass('active');
	});

	/**
	 * Collapsible feature lists
	 */
	(function () {
		var collapsibleFeatures = $('.collapsible-features').each(function (i) {
			var collapsible = $(this).attr('id', 'feature-list-' + i),
				toggleId = 'feature-toggle-' + i;

			collapsible.after($('<a>', {
				'class': 'toggle',
				'id': toggleId,
				'href': '#feature-list-' + i,
				'text': '+'
			})).collapsible({
				toggleSelector: '#' + toggleId,
				toggleText: collapsible.data('toggle-open') || '+',
				toggledText: collapsible.data('toggle-close') || '-'
			});
		}), currentState;

		function updateState() {
			if (isMobile !== currentState) {
				currentState = isMobile;
				collapsibleFeatures.trigger(isMobile ? 'hide.collapsible' : 'show.collapsible');
			}
		}

		if (isMobile) {
			collapsibleFeatures.trigger('hide.collapsible');
		}
		$window.on('resize', debounce(updateState, 100, { 'maxWait': 200 }));
		updateState();
	}());

	// Animated scroll
	window.animatedScrollTo = (function () {
		var scrollElement = $html.add($body);

		function animatedScrollTo(y, hash) {
			scrollElement.animate({ scrollTop: y }, {
				complete: function () {
					if (hash) {
						window.location.hash = hash;
					}
				}
			});
		}

		return animatedScrollTo;
	}());

	/**
	 * Generate an overlay on small screens which reminds the user that he's leaving this website and visiting a site
	 * that might not be optimized for mobile.
	 * @param {jQuery} link The link element which was clicked.
	 * @returns {boolean} True when the pop up is shown, and false when it's not.
	 */
	function mobileExitConfirm(link) {
		var allowRememberChoice = link.data('remember-choice') !== 'false',
			cookie = new Cookie('confirm-not-responsive-exit'),
			rememberInput, popup, buttons;

		if ($window.width() > 768 || cookie.value === 'false') {
			return false;
		}

		popup = $('<div>', {
			'class': 'confirm-content'
		})
			.append($('<h1>', {
				'class': 'title',
				'text': i18n.get('exit-confirm.title')
			}))
			.append($('<p>', {
				'class': 'message',
				'text': i18n.get('exit-confirm.text')
			}));

		if (allowRememberChoice) {
			rememberInput = $('<input>', {
				'class': 'input',
				'type': 'checkbox'
			});
			popup.append($('<p>', {
				'class': 'remember-choice form-row checkbox'
			}).append($('<label>', {
				'class': 'label',
				'text': i18n.get('exit-confirm.remember-choice')
			}).prepend(rememberInput)));
		}

		buttons = $('<p>', {
			'class': 'buttons'
		}).appendTo(popup).on('click', '.button', function (event) {
			if ($(this).hasClass('cancel')) {
				event.preventDefault();
			} else {
				if (allowRememberChoice && rememberInput.prop('checked')) {
					// set the cookie value to false (don't confirm unresponsive exits)
					cookie.write('false');
				}
			}

			$.magnificPopup.close();
		});

		buttons
			.append($('<a>', {
				'class': 'link previous cancel button',
				'href': window.location.href,
				'text': i18n.get('exit-confirm.cancel')
			}))
			.append($('<a>', {
				'class': 'action button',
				'href': link.attr('href'),
				'target': link.attr('target'),
				'text': i18n.get('exit-confirm.proceed')
			}));

		$.magnificPopup.open({
			mainClass: 'lightbox-dialog lightbox-dialog',
			showCloseBtn: false,
			items: {
				type: 'inline',
				src: popup
			}
		});

		return true;
	}

	// fully clickable blocks:
	$html.on('click', '.clickable', function (event) {
		var link = $(event.currentTarget).find('a').first(),
			href = link.attr('href'),
			target = (link.attr('target') || '').toLowerCase();

		if (link.hasClass('mobile-exit-confirm')) {
			if (mobileExitConfirm(link)) {
				// mobile exit confirm is showing, do nothing.
				event.preventDefault();
				event.stopImmediatePropagation();
				return;
			}
		}

		if (target === '_blank') {
			window.open(href);
			event.preventDefault();
		} else {
			window.location.href = href;
		}
	});

	// Event handler for
	$html.on('click', '.mobile-exit-confirm', function (event) {
		var link = $(event.currentTarget);

		if (mobileExitConfirm(link)) {
			// mobile exit confirm is showing, do nothing.
			event.preventDefault();
			event.stopImmediatePropagation();
		}
	});

	// Anchor buttons
	$html.on('click', '.button', function (event) {
		var href = $(this).attr('href'), target;
		if (href && href.match(/^#.*/)) {
			target = $(href);
			if (target.length) {
				event.preventDefault();
				window.animatedScrollTo(target.offset().top, target.attr('id'));
			}
		}
	});

	(function () {
        /**
         * Hashes to remove, '' for 'index.html#' and 'string' for index.html#string
         * @type {string[]}
         */
		var hashesToRemove = ['', 'top'];

        /**
         * Checks if the current hash is in the hashesToRemove list
         * if so, it uses replaceState to remove it from the URL.
         */
		function cleanHash() {
			var parts = window.location.href.split('#');

			if (parts.length > 1) {
				if (hashesToRemove.indexOf(parts[1]) >= 0) {
					window.history.replaceState(window.history.state, document.title, parts[0]);
				}
			}
		}

		if (window.history.replaceState) {
			$window.on('hashchange', cleanHash);
			cleanHash();
		}
	}());

	// Initialize auto complete
	(function () {
		var defaultSettings = {
			minChars: 1,
			deferRequestBy: 300,
			zIndex: 0,
			noCache: false,
			dataType: 'json'
		};

		if (!$.fn.autocomplete) {
			return;
		}
	}());

	/**
	 * Media galleries
	 */
	$('.gallery').each(function () {
		var gallery = $(this),
			galleryTitle = gallery.children('.title').html();

		gallery.magnificPopup({
			delegate: '.preview a',
			type: 'image',
			tLoading: gallery.data('loading-text') || i18n.get('gallery.loading-image'),
			mainClass: 'mfp-img-mobile gallery-lightbox',
			gallery: {
				enabled: true,
				navigateByImgClick: true,
				preload: [0, 1] // Will pre-load 0 - before current, and 1 after the current image
			},
			image: {
				tError: '<a href="%url%">' + (gallery.data('error-text') || i18n.get('gallery.errors.image')) + '</a>',
				titleSrc: function (item) {
					return $('<div>', {
						'class': 'caption-content'
					}).append([
						$('<strong>', {
							'class': 'caption-title',
							'text': galleryTitle
						}),
						$('<div>', {
							'class': 'caption-text',
							'html': item.el.closest('.item').find('.description, .buttons').clone()
						})
					]);
				}
			}
		});
	});

	/**
	 * Carousels
	 */
	if ($.fn.swiper) {
		(function () {
			var containers = $('.swiper-container').each(function () {
				var container = $(this),
					containerWidth = container.width();

				var prev = $('<button>', {
					'class': 'swiper-navigation previous',
					'text': '<'
				}).insertAfter(container);

				var next = $('<button>', {
					'class': 'swiper-navigation next',
					'text': '>'
				}).insertAfter(container);

				var swiperOptions = {
					mode: 'horizontal',
					loop: false,
					slideClass: 'carousel-item',
					slidesPerView: 'auto',
					calculateHeight: true,
					paginationClickable: true,
					nextButton: container.parent().find('.next'),
					prevButton: container.parent().find('.previous'),
				},
					// @var {Swiper} instance
					swiper, pagination;

				if (container.hasClass('swiper-with-pagination')) {
					pagination = $('<div>', {
						'class': 'swiper-pagination'
					}).insertAfter(container);
					swiperOptions.pagination = pagination.get(0);
				}

				container.addClass('initialized').swiper($.extend(swiperOptions, {}));
				swiper = container.data('swiper');
			});

			$window.on('resize', debounce(function () {
				containers.trigger('reinit.carousel');
			}, 500));
		}());
	}

	$('.change-news-date').on('change', function () {
		var year = $('#year').val();
		if (year != 0) {
			var month = $('#month').val();
		}
		var url = "?year=" + year + "&month=" + month;
		window.location.href = url;
	});

	/**
	 * Auto submitting fields (filter lists)
	 */
	$('.change-submit').on('change', function () {
		$(this).closest('form').trigger('submit');
	});

	/**
	 * Placeholder attribute fallback
	 */
	Modernizr.load({
		test: Modernizr.input.placeholder,
		nope: window.jsFolder + 'vendor/jquery.placeholder.min.js',
		callback: function () {
			$('textarea[placeholder], input[placeholder]').placeholder();
		}
	});

	$('body')
		.on('click', '.embeddedServiceHelpButton', function () {
			var
				salesForceOpenClass = 'salesforce-form-open',
				body = $('body').addClass(salesForceOpenClass);
			// start listening for dom change signalling closing of form
			new MutationObserver(function (mutationsList, observer) {
				mutationsList.forEach(function (mutation) {
					mutation.removedNodes.forEach(function (removedNode) {
						if ($(removedNode).hasClass('modalContainer')) {
							body.removeClass(salesForceOpenClass);
							observer.disconnect();
						}
					});
				});
			})
				.observe(
					$(this).closest('.slds-scope')[0], {
					childList: true
				}
				);
		});

	/**
	 * Call me now popup
     * Function has been added to window to be able to re-execute the function.
	 */
	function toCallMeNow() {

		$('.to-call-me-now').each(function (iterator) {
			var minBrowserWidth = 660,
				containerId = '',
				$container = null,
				$currentButton = $(this),
				$activeButton = false,
				defaultPushcallId = 'postnl_dm';

			function isMobileWidth() {
				return $window.width() < minBrowserWidth;
			}

			function openInLightBox() {
				$.magnificPopup.open({
					items: {
						src: '#' + containerId,
						type: 'inline'
					},
					callbacks: {
						close: function () {
							$activeButton.show();
							$activeButton = false;
							$('#generic-chat-container iframe').off('load.chat-frame');
						}
					},
					midClick: true,
					closeOnBgClick: false
				});
			}

			function toCallMeNowOnClick(event) {
				var section = $(this).parent().parent();
				if (section.hasClass("disabled") || section.hasClass("unavailable")) {
					return;
				}

				if ($activeButton.length && $activeButton !== $currentButton) {
					$activeButton.show();
				}

				$activeButton = $currentButton;
				$container.removeClass('mfp-hide');

				if (!isMobileWidth()) {
					openInLightBox();
				}
				else {
					$activeButton.hide();
				}

				event.preventDefault();
			}

			function onResize() {
				var $button, popup;

				if ($activeButton && $activeButton.length) {
					if (isMobileWidth()) {
						popup = $.magnificPopup.instance;
						if (popup) {
							if (popup.content) {
								$button = $activeButton;
								popup.close();
								$activeButton = $button;
								$activeButton.hide();
								$container.removeClass('mfp-hide');
							}
						}
					} else {
						$activeButton.show();
						openInLightBox();
					}
				}
			}

			function validateLabel(element) {
				var messages = {};
				if (element != null) {
					for (var i = 0; i < element.attributes.length; i++) {
						var attr = element.attributes[i];
						if (/^data-/.test(attr.nodeName) && value != '' && attr.nodeValue.substring(0, 16) != 'Missing Resource') {
							var key = attr.nodeName.replace(/^data-/, '');
							var value = attr.nodeValue;
							messages[key.toUpperCase()] = value;
						}
					}
				}
				return messages;
			}

			function chatButtonOnClick() {
				var $firstChat = $container.find('.chat:first'),
					$narrowContent = $firstChat.find('.narrow-content'),
					$h2 = $narrowContent.find('h2'),
					targetName = $firstChat.data('pushcall-id') || defaultPushcallId;

				var element = document.querySelector('#chat_labels');
				var chatMessages = validateLabel(element);

				$narrowContent.html('<div class="chat-container"></div>');
				$narrowContent.prepend($h2);

				$container.find('.chat-container').pcclient({
					targetName: targetName,
					clientType: 'chat',
					skin: '',
					locale: 'nl',
					forceHTML: true,
					userMessages: {
						nl: chatMessages
					},
					eventCallback: function (event) {
						if (event === 'closed') {
							//big hack to hide flash contact mail
							$narrowContent.find('.centerblock > p:not(.header):not(:first)').hide();
						}
					},
					context: this
				});
				event.preventDefault();
			}

			function initChat() {
				$container.find('.chat .button').on('click', chatButtonOnClick);
			}

			function init() {
				var $blockDirectActions = $currentButton.closest('.direct-actions'),
					targetName;

				$container = $('.call-me-now-container:eq(' + iterator + ')');
				containerId = 'call-me-now-container' + iterator;
				$container.attr('id', containerId);

				// 'hack' in case of direct actions
				if ($blockDirectActions.length) {
					$blockDirectActions.after($container);
				} else {
					$currentButton.parent().after($container);
				}

				//$container
				// if the chat container is the livechat container, disable resize action.
				if (!$container.hasClass('livechat')) {
					$window.on('resize', debounce(onResize, 100, { 'maxWait': 200 }));
				}
				$currentButton.on('click', toCallMeNowOnClick);


				var targetNameWhatsapp = $container.find('.whatsapp:first').data('pushcall-id') || defaultPushcallId;
				var whatsappContainer = $container.find('.whatsapp:first .narrow-content');
				var callMeContainer = $container.find('.call-me:first .narrow-content');

				if (whatsappContainer.length > 0) {
					var element = document.querySelector('#amn_labels');
					var amnMessages = validateLabel(element);

					whatsappContainer.html('').pcclient({
						targetName: targetNameWhatsapp,
						clientType: 'amn',
						skin: '',
						headerLevel: 2,
						locale: 'nl',
						forceHTML: true,
						userMessages: {
							nl: amnMessages
						},
						eventCallback: function (event, eventData) {
							$container.find('button.pcac_cmn_call').addClass('button').addClass('action');
						}
					});
				}

				var targetNameCallMeNow = $container.find('.call-me:first').data('pushcall-id') || defaultPushcallId;
				if (callMeContainer.length > 0) {
					var element = document.querySelector('#cmn_labels');
					var cmnMessages = validateLabel(element);

					var cmn_labels = $('#cmn_labels');
					callMeContainer.html('').pcclient({
						targetName: targetNameCallMeNow,
						clientType: 'cmn',
						skin: '',
						locale: 'nl',
						forceHTML: true,
						userMessages: {
							nl: cmnMessages
						}
					});
				}
				initChat();
			}

			init();
		});
	}

	toCallMeNow();

	window.toCallMeNow = toCallMeNow;

	/**
	 * Smart engage
	 */
	(function () {
		var minBrowserWidth = 660,
			$container = $('.smart-engage'),
			$prev = null,
			setMobileWidth = true;

		function isMobileWidth() {
			return $window.width() < minBrowserWidth;
		}

		function onClose() {
			$container.animate({
				bottom: -300
			},
				function () {
					$(this).hide();
				}
			);
		}

		function smartEngage() {
			var smartTimeout = ($('.smart-engage').data('smarttimeout') * 1000);
			if (!isMobileWidth()) { //desktop
				if (!setMobileWidth) {
					return;
				}
				setMobileWidth = false;
				$body.append($container);
				$container.addClass('fold-out');
				$container
					.css({ 'bottom': '-300px' })
					.hide()
					.delay(smartTimeout)
					.animate({
						bottom: 0
					}, {
						start: function () {
							$(this).show();
						},
						duration: 1000
					});
			} else { //mobile
				if (setMobileWidth) {
					//return;
				}
				$container.css({ 'bottom': '0' }).show();
				setMobileWidth = true;
				$container.insertAfter($prev);
				$container.removeClass('fold-out');
			}
		}

		function onResize() {
			if (!isMobileWidth()) { //desktop
				if (!setMobileWidth) {
					return;
				}
				setMobileWidth = false;
				$body.append($container);
				$container.addClass('fold-out');
				$container
					.css({ 'bottom': '-300px' })
					.hide()
					.delay(2000)
					.animate({
						bottom: 0
					}, {
						start: function () {
							$(this).show();
						},
						duration: 1000
					});
			}
			else { //mobile
				if (setMobileWidth) {
					return;
				}
				$container.css({ 'bottom': '0' }).show();
				setMobileWidth = true;
				$container.insertAfter($prev);
				$container.removeClass('fold-out');

			}

		}

		function init() {
			if (!$container.length) {
				return;
			}

			$container.append('<span class="close">X</span>');
			$container.find('span.close').on('click', onClose);
			$container.find('a.decline').on('click', onClose);

			$prev = $container.prev();
			//onResize();

			$window.on('onResize', debounce(smartEngage, 100, { 'maxWait': 200 }));

			var tcm = $('article.smart-engage').data('component');

			$.ajax({
				url: '/services/businessopen?tcm=' + tcm,
				success: function (data) {
					if (data == "true") {
						smartEngage();
					}
				}
			});
		}

		init();
	}());

	$('.calamity + app-root[data-lp-pages!=""]').prev()
		.addClass('calamity-location-picker');

	$('.calamity .close').click(function () {
		$(this).parent().remove();
	});

	/* call (tel numbers)  */
	(function () {
		var $links = $('.phone.option a.action');
		$links.each(function () {
			var link = $(this);
			link.magnificPopup({
				mainClass: 'lightbox-dialog lightbox-phonenumbers',
				//showCloseBtn: false,
				items: {
					type: 'inline',
					src: link.closest('.option').find('.phonenumbers')
				}
			});
		});
	}());

	/* Hashtag-page socialbox popup  */
	(function () {
		var $links = $('.social.option a.action');
		$links.each(function () {
			var link = $(this);
			link.magnificPopup({
				mainClass: 'lightbox-dialog lightbox-socialbox mfp-fade',
				//showCloseBtn: false,

				disableOn: function () {
					if ($(window).width() < 660) {
						return false;
					}
					return true;
				},
				removalDelay: 50, // was 1500
				items: {
					type: 'inline',
					src: link.closest('.option').find('.socialbox')
				}
			});
		});
	}());

	window.addPopupToJobAlertButton = function () {
		var
			button = $('.show-job-alert a'),
			content = button.parent().next('.job-alert');
		button.magnificPopup({
			mainClass: 'lightbox-dialog lightbox-socialbox mfp-fade lightbox-job-alert',
			removalDelay: 50, // was 1500
			items: {
				type: 'inline',
				src: content.remove()
			},
			callbacks: {
				open: function () {
					var
						newFilterHtml = '<span></span>';
					$('.used-filters a.remove-filter').each(
						function () {
							newFilterHtml +=
								'<span class="filter' +
								($(this).hasClass('clear-searchterm') ? ' search-filter' : '') +
								'">' +
								this.innerText +
								'</span>';
						}
					);
					content
						.find('.used-filters')
						.html(newFilterHtml)
						.removeClass('hidden');
				}
			}
		});
	}
	addPopupToJobAlertButton();

    /**
     * Animate elements in view when scrolling
     */
	(function () {
		var defaultOffset = 25,
			defaultAnimationQueueDelay = 500,
			$elements = $('.animate-in-view'),
			$animated = $elements.map(function () {
				var $element = $(this);

				return {
					queue: $element.data('animation-queue'),
					queueDelay: $element.data('animation-queue-delay') || defaultAnimationQueueDelay,
					$element: $element,
					animated: false,
					offsetTop: $element.offset().top + ($element.data('animation-offset') || defaultOffset)
				};
			}),
			animationQueues = {},
			debouncedHandler;

        /**
         * Initializes a new animation queue
         * @param {String} name
         * @param {Function} callback
         * @constructor
         */
		function AnimationQueue(name, callback) {
			this.name = name;
			this.animating = false;
			this.queue = [];
			this.callback = callback;
		}

        /**
         * String representation of the queue for debugging.
         * @returns {string}
         */
		AnimationQueue.prototype.toString = function () {
			return "AnimationQueue '" + this.name + "' (" + this.size() + ")";
		};
        /**
         * Returns the size of the queue
         * @returns {Number}
         */
		AnimationQueue.prototype.size = function () {
			return this.queue.length;
		};
        /**
         * Adds a animation to this queue
         * @param {Object} animation
         * @returns {AnimationQueue}
         */
		AnimationQueue.prototype.add = function (animation) {
			this.queue.push(animation);
			return this;
		};
        /**
         * Starts animating the queue if it's not animating yet.
         * @returns {AnimationQueue}
         */
		AnimationQueue.prototype.start = function () {
			return !this.animating ? this.animate() : this;
		};
        /**
         * Animates the next animation in the queue.
         * @returns {AnimationQueue}
         */
		AnimationQueue.prototype.animate = function () {
			var animation = this.queue.shift(),
				queue = this;

			if (animation) {
				this.animating = true;

				this.callback(animation);

				// We defer resuming the queue to the 'next tick', other animations might have been added to the queue.
				window.setTimeout(function () {
					if (queue.size()) {
						return queue.animate();
					}
					queue.animating = false;
				}, animation.queueDelay);
			}
			return this;
		};

        /**
         * Add the given animation to it's queue
         * @param {object} animation
         */
		function queueAnimation(animation) {
			var queue = animationQueues[animation.queue];
			if (!queue) {
				queue = animationQueues[animation.queue] = new AnimationQueue(animation.queue, triggerAnimation);
			}
			queue.add(animation).start();
		}

        /**
         * Handles the scroll event, checking for new elements within the viewport and triggering their animation
         */
		function scrollHandler() {
			var scrollBottom, $newInView;

			if (!$animated.length) {
				return;
			}

			scrollBottom = $window.scrollTop() + $window.height();
			$newInView = $animated.filter(function () {
				return !this.animated && this.offsetTop < scrollBottom;
			});

			$newInView.each(function () {
				// remove this element from the $animated array, it no longer needs to be checked
				$animated.splice($animated.index(this), 1);
				if (this.queue) {
					// queue this animation:
					queueAnimation(this);
				} else {
					// immedeately trigger the animation:
					triggerAnimation(this);
				}
			});
		}

        /**
         * Triggers the actual animation the animations element.
         * @param {Object} animation
         */
		function triggerAnimation(animation) {
			// We also trigger an event to be able to observe the animation from external sources
			animation.$element.addClass('in-view').trigger('in-view');
			animation.animated = true;
		}

		if ($elements.length) {
			debouncedHandler = debounce(scrollHandler, 50, {
				'leading': true,
				'trailing': false,
				'maxWait': 200
			});
			// observe scroll events
			$window.on('scroll', debouncedHandler);
			// start animating any already visible elements:
			debouncedHandler();
		}
	}());

    /**
     * Custom video's
     */
	(function ($videos) {
		$videos.each(function () {
			var video = videojs(this),
				$videoElement = $(this),
				$wrapper = $videoElement.closest('.cover-video'),
				classes = {
					'playing': 'video-playing',
					'paused': 'video-paused'
				},
				videoTitle = $videoElement.attr('title'),
				$playButton;

			classes.states = [classes.playing, classes.paused].join(' ');

			if ($wrapper.length) {
				// custom play button:
				if (videoTitle) {
					$playButton = $('<a>', {
						'href': '',
						'class': 'play-button',
						'text': $videoElement.attr('title')
					}).appendTo($wrapper);
				}

				// when the video is ready, start attaching event handlers
				video.ready(function () {
					video.on('play', function () {
						$wrapper.toggleClass(classes.states);
					});
					video.on('pause', function () {
						$wrapper.toggleClass(classes.states);
					});

					if ($playButton) {
						// observe our custom play button:
						video.on($playButton.get(0), 'click', function (event) {
							event.preventDefault();
							video.play();
						});
					}

					$wrapper
						.toggleClass(classes.playing, !video.paused())
						.toggleClass(classes.paused, video.paused());
				});
			}
		});
	}($('video')));

	// Open a video in lightbox
	// Use video-playlist to handle multiple videos
	(function ($videos) {
		$videos.each(function () {
			var $video = $(this),
				playButtonClass = 'play-button';

			// Attach lightbox handler to play button(contains iframe url)
			$video.find('.' + playButtonClass).magnificPopup({ type: 'iframe' });
		});
	}($('.video-mfp')));

	$('.column-layout script[data-video-id], .panel-blocks script[data-video-id]').each(function () {
		var
			videoScript = $(this),
			id = videoScript.data('id'),
			addHandler = function () {
				var
					player = QuadiaPlayer.players[id];
				player.$on('play', function () {
					if (!$.magnificPopup.instance.isOpen) {
						var
							iframe = $('#' + id);
						$.magnificPopup.open({
							items: {
								src: iframe
							},
							mainClass: 'video-lightbox',
							callbacks: {
								open: function () {
									player.$on('playerReady', function () {
										if ($.magnificPopup.instance.isOpen) {
											setTimeout(function () {
												player.$emit('play');
											}, 100);
										}
									});
								},
								close: function () {
									videoScript.after(
										iframe
											.remove()
											.removeClass('mfp-hide')
									);
								}
							}
						});
					}
				})
			};
		if (window.QuadiaPlayer) {
			addHandler();
		} else {
			videoScript.on('load', addHandler);
		}
	});

	/* Custom video playlist, with this function we can create a playlist with a quadia player overlay */
	(function () {

		/* this is the container */
		$('.video-playlist').each(function () {

			var $container = $(this),
				$poster = $container.find('.cover-video'),
				$overlay = $container.find('.overlay-block');

			$container.find('.play-button').magnificPopup({ type: 'iframe' });

			/* list for video's in the playlist */
			$container.find('.list a').on('click', function (event) {
				var $item = $(this),
					data = $item.data();

				event.preventDefault();

				/* this fill the poster for the video */
				$poster.css('background-image', 'url(' + data.poster + ')');
				$poster.find('.play-button').attr('href', data.video);
				$poster.find('.play-button').text(data.buttontext);
				$overlay.find('.title').text(data.title);
				$overlay.find('.overlay-block-content').html(data.content);
				$overlay.find('.button').attr('href', data.callToActionUrl);

				$item.parents('ul').find('.is-active').removeClass('is-active');
				$item.addClass('is-active');
			});
		});
	})();

    /** We want collapsible-text closed when used on mobile,
     * we overwrite the settings with css to make sure the fields are always opend on other fields
     * **/
	(function () {

		var collapsible = true;

		function updateCollapsible() {

			if (collapsible) {
				if ($(window).width() <= 660) {
					$('.collapsible-text:gt(0)').find('.collapsible-toggle').not('.toggled').trigger('click');

					collapsible = false;
				}
			}
		}

		updateCollapsible();

		// Create a resize handler
		addResizeHandler(updateCollapsible);

	})();

	/**
	 * Load google maps data
	**/

	(function () {
		$('.maps').each(function () {
			var map = $('#map');

			proj4.defs('EPSG:28992', '+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs');
			var EPSG_28992 = new ol.proj.Projection({
				code: 'EPSG:28992',
				extent: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999],
				units: 'm'
			});
			ol.proj.addProjection(EPSG_28992);

			new ol.Map({
				target: 'map',
				layers: [
					new ol.layer.Tile({
						source: new ol.source.XYZ({
							projection: EPSG_28992,
							url: map.data('tiles')
						})
					}),
					new ol.layer.Vector({
						source: new ol.source.Vector({
							features: [
								new ol.Feature({
									type: 'marker',
									geometry: new ol.geom.Point(
										ol.proj.fromLonLat(
											[map.data('long'), map.data('lat')],
											EPSG_28992
										)
									)

								})
							]
						}),
						style: function () {
							return new ol.style.Style({
								image: new ol.style.Icon({
									anchor: [.5, 1],
									src: '/img/werken-bij/location-marker.png'
								})
							});
						}
					})
				],
				view: new ol.View({
					projection: EPSG_28992,
					center: ol.proj.fromLonLat(
						[map.data('long'), map.data('lat')],
						EPSG_28992
					),
					zoom: 10
				}),
				loadTilesWhileInteracting: true,
				loadTilesWhileAnimating: true,
				controls: [
					new ol.control.Zoom()
				]
			});
		});
	})();

	(function (splashPage) {
		var
			hiddenElements,
			HIDDEN_CLASS = 'hidden-for-splashpage',
			HIDDEN_SELF_CLASS = 'hidden-splashpage',
			COOKIE_NAME = 'show_splashpage',
			cookie = new Cookie(COOKIE_NAME);
		splashPage
			.each(function () {
				if (
					// Cookie reading does not seem to work
					document.cookie.split('; ')
						.some(function (cookie) {
							var
								name_value = cookie.split('='),
								name = name_value[0],
								value = name_value[1];
							return name == COOKIE_NAME && value == 'false';
						})
				) {
					splashPage
						.hide();
				} else {
					hiddenElements =
						$('main > *, #PostNL_globalNav_header')
							.not(splashPage)
							.addClass(HIDDEN_CLASS);
					splashPage
						.append(
							$('body > footer')
								.clone(true)
						);
				}
			})
			.find('.continue')
			.on('click', function (event) {
				document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
					detail: {
						name: "in_page_interaction",
						in_page: {
							"name": $(this).text(),
							"category": "link_click_button",
							"location": "body"
						}
					}
				})
				);
				cookie.write('false');
				hiddenElements
					.removeClass(HIDDEN_CLASS);
				splashPage
					.addClass(HIDDEN_SELF_CLASS);
				event.preventDefault();
			})
			.end()
			.find('.select-country')
			.on('click', function () {
				document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
					detail: {
						name: "in_page_interaction",
						in_page: {
							"name": $(this).text(),
							"category": "link_click_button",
							"location": "body"
						}
					}
				})
				);
			});
	})($('.splashpage'));

	$('.single-line-search form')
		.on('submit', function (event) {
			if (!$(this).find('input[type=search]').val()) {
				event.preventDefault();
			}
		})
		.find('input[type=search]')
		.on('invalid', function (event) {
			event.preventDefault();
		});

	$('.faq-menu-responsive select')
		.on('change', function () {
			document.location.href = this.value;
		});

	$(window).on('load', function () {
		var newHeight = 0;
		$('section.block > article.media-block').each(function (key, value) {
			var blockHeight = $(this).height();
			if (blockHeight > newHeight) {
				newHeight = blockHeight
			}
		});
		$('section.block > article.media-block').height(newHeight);
	});

	(function (carousel) {
		carousel.each(function () {
			var
				scrollTimer,
				scrollContainer = $(this).find('.scroll-container'),
				intersectionObserver = new IntersectionObserver(
					function (entries) {
						var
							carouselButtons = scrollContainer.next().find('.carousel-button');
						entries.forEach(function (entry) {
							$(carouselButtons[
								$(entry.target).prevAll().length
							])
								.toggleClass('active', entry.isIntersecting);
						});
					}, {
					root: scrollContainer[0],
					rootMargin: '0px',
					threshold: 1.0
				}
				);
			scrollContainer
				.after(
					$('<div class="carousel-buttons">')
						.append(
							scrollContainer.find('.equal-heights').map(function (index, panel) {
								intersectionObserver.observe(panel);
								return $('<a class="carousel-button">')
									.click(function () {
										panel.scrollIntoView({
											behavior: "smooth",
											block: "nearest",
											inline: "start"
										});
									});
							}).get()
						)
				)
				.scroll(
					function () {
						if (scrollTimer) {
							clearTimeout(scrollTimer);
						}
						scrollTimer = setTimeout(
							function () {
								// snap slide
								scrollContainer.next().find('.carousel-button.active').first()
									.click();
							},
							250
						);
					}
				)
				.addClass('initialized');
		});
	})($('.panels-wrapper.has-carousel'));

	(function (checkButton) {
		if (checkButton.length) {
			var
				form = checkButton.closest('form'),
				inputs = form.find('.personal-data .form-row input, .check-later .form-row input, .form-row select'),
				storedData = new Cookie('tempFormData'),
				goEdit = function () {
					form.removeClass('checking');
					inputs
						.show()
						.next('span.default.added')
						.remove()
						.closest('.form-row')
						.show();
				},
				goCheck = function () {
					var
						isValid = form.data().validator(form);
					if (isValid) {
						form.addClass('checking');
						inputs.each(function () {
							var
								input = $(this);
							if (input.val()) {
								input
									.hide()
									.after('<span class="default added">' + input.val() + '</span>');
							} else {
								input.closest('.form-row').hide();
							}
						});
					}
					return isValid;
				};

			if (storedData.value) {
				var
					storedNameValues = JSON.parse(
						decodeURIComponent(storedData.value)
					);
				form.find('.personal-data [name]').each(function () {
					var
						name = this.name;
					this.value = storedNameValues.find(function (nameValue) {
						return nameValue.name == name;
					})
						.value;
				});
			}

			window.addEventListener('hashchange', function () {
				if (document.location.hash === '#check') {
					if (!goCheck()) {
						// preventDefault
						window.history.back(-1);
					}
				} else {
					goEdit();
				}
			});

			if (document.location.hash === '#check') {
				goCheck();
			}

			form.find('.back').click(function (event) {
				// make sure enough time is left to store the cookie before navigating away
				event.preventDefault();
				storedData
					.write(
						JSON.stringify(
							form.serializeArray()
						)
					);
				document.location.href = this.href;
			});
		}
	})($('.pre-check-step .submit a'));

	if (window.userDetails) {
		$window
			.trigger('userDetails', window.userDetails);
	}
	$('#postalcodekillerapp').one('keyup', ':input:visible:first', function () {
		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "funnel_interaction",
				funnel: {
					"name": "killer widget - postcode zoeken",
					"technology": "killerwidget",
					"type": "application",
					"step": "10",
					"step_name": "start killerwidget"
				}
			}
		})
		);
	});

	$('#postalcodekillerapp button').on('click', function () {
		var street = $('input[name=street]').val(),
			housenumber = $('input[name=number]').val(),
			addition = $('input[name=addition]').val(),
			city = $('input[name=city]').val();
		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "funnel_interaction",
				funnel: {
					"name": "killer widget - postcode zoeken",
					"technology": "killerwidget",
					"type": "application",
					"step": "laatste",
					"step_name": "succes killerwidget"
				},
				optins: [
					{
						"category": "street",
						"answer": street
					},
					{
						"category": "housenumber",
						"answer": housenumber
					},
					{
						"category": "addition",
						"answer": addition
					},
					{
						"category": "city",
						"answer": city
					}
				]
			}
		})
		);
	});

	$('.recruitment-killer-app').one('keyup', ':input:visible:first', function () {
		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "job_search_interaction",
				funnel: {
					"name": "killer widget - zoeken werkenbij",
					"technology": "killerwidget",
					"type": "application",
					"step": "10",
					"step_name": "start killerwidget"
				}
			}
		})
		);
	});

	$('.production-vacancies-killerapp button').on('click', function () {
		var
			radiusSelect = $('.production-vacancies-killerapp select#search-range'),
			radius = radiusSelect.find('option:selected').val(),
			postCode = $('.production-vacancies-killerapp input#vacancyLocation').val();

		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "job_search_interaction",
				funnel: {
					"name": "killer widget - zoeken werkenbij",
					"technology": "killerwidget",
					"type": "application",
					"step": "laatste",
					"step_name": "succes killerwidget"
				},
				optins: [
					{
						"category": "postalcode",
						"answer": postCode
					},
					{
						"category": "radius",
						"answer": radius
					}
				]
			}
		})
		);
	});

	$('#zipcode-form fieldset').one('keyup', ':input:visible:first', function () {
		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "job_search_interaction",
				funnel: {
					"name": "killer widget - zoeken werkenbij",
					"technology": "killerwidget",
					"type": "application",
					"step": "10",
					"step_name": "start killerwidget"
				}
			}
		})
		);
	});

	$('.office-vacancies-killerapp button').on('click', function () {
		var
			radiusSelect = $('.office-vacancies-killerapp select#search-range'),
			radius = radiusSelect.find('option:selected').val(),
			postCode = $('.office-vacancies-killerapp input#vacancyLocation').val(),
			searchTerm = $('.office-vacancies-killerapp input#vacancyName').val();

		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "job_search_interaction",
				funnel: {
					"name": "killer widget - zoeken werkenbij",
					"technology": "killerwidget",
					"type": "application",
					"step": "laatste",
					"step_name": "succes killerwidget"
				},
				optins: [
					{
						"category": "postalcode",
						"answer": postCode
					},
					{
						"category": "search_term",
						"answer": searchTerm
					},
					{
						"category": "radius",
						"answer": radius
					}
				]
			}
		})
		);
	});

	$('body').on('click', ".vacancy-filters .filter-group input[data-datalayer]", function () {
		var vacancy = $(this).data('vacancyfilter'),
			filter = $(this).data('filteroption'),
			// Retrieve the current filters in datalayer. If the filters property doesn't exist, assign an empty array
			allFilters = (window.Intel && window.Intel.event && window.Intel.event.filters) ? window.Intel.event.filters : [],
			isFilterChecked = $(this).data('datalayer') === "productie" ? !filter.Selected : this.checked;
		if (isFilterChecked) {
			allFilters.push({
				name: vacancy.Title,
				value: filter.Name
			});
		} else {
			allFilters.forEach((currentFilter, index, object) => {
				if (currentFilter.name === vacancy.Title && currentFilter.value === filter.Name) {
					object.splice(index, 1);
				}
			});
		}

		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: 'filter_interaction',
				filter: {
					type: isFilterChecked ? "add filter" : "remove filter",
					interacted_filter_name: vacancy.Title,
					interacted_filter_value: filter.Name,
					nr_results: filter.Amount
				},
				filters: allFilters
			}
		})
		);
	});

	$('.killer-app.location-tool').one('keyup', ':input:visible:first', function () {
		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "funnel_interaction",
				funnel: {
					"name": "killer widget - locatiewijzer",
					"technology": "killerwidget",
					"type": "application",
					"step": "10",
					"step_name": "start killerwidget"
				}
			}
		})
		);
	});

	/**	 
    * Add location form values to the url in a form the angular based location picker understands
    * For backward compatibility we still send the form fields in the query string
    */
	$('.location-tool form').on('submit', function (event) {
		var form = $(this),
			query = $('#address').val() || form.find('[name=geo-address]').val(),
			product = form.find('[name=productpanel]:checked'),
			location = $('input#address').val();
		event.preventDefault();

		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "funnel_interaction",
				funnel: {
					"name": "killer widget - locatiewijzer",
					"technology": "killerwidget",
					"type": "application",
					"step": "laatste",
					"step_name": "succes killerwidget"
				},
				optins: [
					{
						"category": "location",
						"answer": location
					}
				]
			}
		})
		);
		document.location.href =
			this.action + '?' + form.serialize() + (query ? ('&address=' + query) : '') + '#/'
			+ (query ? query : '')
			+ (product.length ? '/' + product.val() : '');
	});

	$('rendered-pnl-a.sc-rendered-pnl-expando').click(function() {
		var
			self = $(this),
			panel = self.prev(),
			container = self.parent().toggleClass('active'),
			chevron = self.find('rendered-pnl-chevron'),
			active = container.hasClass('active');
		panel
			.css('maxHeight', active ? panel[0].scrollHeight : '');
		chevron.attr('active', active ? "" : null);		
	});

	$('rendered-pnl-quicklinks').each(function() {
		var
			quicklinkBlocks = $(this).find('rendered-pnl-quicklinksblock');
		quicklinkBlocks
			.find('rendered-pnl-h3')
				.click(function() {
					var
						clickedBlock = $(this).closest('rendered-pnl-quicklinksblock'),
						alreadyActive = clickedBlock.hasClass('active');
					quicklinkBlocks
						.removeClass('active')
						.find('rendered-pnl-chevron')
							.removeAttr('active');
					if (!alreadyActive) {
						clickedBlock
							.addClass('active')
							.find('rendered-pnl-chevron')
								.attr('active', '');
					}
						
				})
				[0].click();
	});

	// Personalizations
	$('body').on('click', "[data-personalizable] a", function () {
		var element = $(this).closest("[data-personalizable]");

		document.body.dispatchEvent(new CustomEvent('postnl-datalayer-event', {
			detail: {
				name: "personalisation_interaction",
				personalisations: [
					{
						"position": element.children("meta[itemprop='position']").attr("content"),
						"sub_position": element.children("meta[itemprop='sub_position']").attr("content"),
						"text": element.children("meta[itemprop='text']").attr("content"),
						"segment": element.children("meta[itemprop='segment']").attr("content")
					}
				]
			}
		}
		));
	});

	// Add the loaded class to be able to disable CSS animations until after the page load
	window.setTimeout(function () {
		$html.addClass('loaded');
	}, 0);
});

// Zorgt voor de functionaliteit van de samengestelde vacatures op de vacaturepaginas
(function handleCompoundedVacancies() {
	const compoundedVacanciesEl = Array.from(document.querySelectorAll('.compounded-vacancies'));

	if (compoundedVacanciesEl.length) {
		compoundedVacanciesEl.map(function (compoundedVac) {
			const visibleVacancies = 3;
			const singleVacancies = Array.from(compoundedVac.querySelectorAll('.single-vacancy'));

			if (singleVacancies.length > visibleVacancies) {
				setItemsVisibility(false);

				const showMoreBtnEl = document.createElement('a');
				showMoreBtnEl.classList.add('text-button')
				showMoreBtnEl.addEventListener('click', function (e) {
					e.preventDefault();
					setItemsVisibility(true);
				});
				showMoreBtnEl.textContent = 'Bekijk meer ' + (singleVacancies.length - 3);

				compoundedVac.appendChild(showMoreBtnEl);

				function setItemsVisibility(visibleState) {
					if (visibleState) {
						showMoreBtnEl.remove();
					}
					singleVacancies.map(function (vacancy, index) {
						if (index > 2) {
							visibleState ? vacancy.classList.remove('_hidden') : vacancy.classList.add('_hidden');
						}
					})
				}
			}
		})
	}

	$.get('/api/label/' + $('meta[name=publicationID]').attr('content') + '/browser-meldingen')
		.success(function (regEx_Notification) {
			$.each(regEx_Notification, function (regEx, notification) {
				if (navigator.userAgent.match(new RegExp(regEx)) !== null) {
					$('body > main').prepend(
						'<article class="narrow-content calamity block calamity-info"><div>'
						+ notification +
						'</div></article>'
					);
				}
			});
		});
})();

(function (ctaBar) {
	if (ctaBar.length) {
		if (
			ctaBar.is('main > *:last-child') ||
			ctaBar.is('main > .container > article > div > *:last-child')
		) {
			// make bar stick to footer
			$('body > footer').before(ctaBar);
		}
		var
			observing = ctaBar.next();
		(new IntersectionObserver(
			function (entries) {
				ctaBar.toggleClass(
					'stickied',
					!entries[0].isIntersecting
				);
			}, {
			rootMargin: observing.css('margin-top')
		}
		))
			.observe(observing[0]);
	}
})(
	$('.cta-bar')
);
linearGradientHomePageBanner();

// if title is not yet present, linearGradientHomePageBanner is called after renderHandlebars is called
function linearGradientHomePageBanner() {
	bannerTitleEl = document.querySelector('.hero-image .content .title p');
	if (bannerTitleEl) {
		gradientEl = document.querySelector('.hero-image.full-width .gradient');
		gradientEl.querySelector('.gradient__first').style.width = bannerTitleEl.getBoundingClientRect().right + 8 + 'px';
		gradientEl.querySelector('.gradient__last').style.width = document.querySelector('.hero-image.full-width .img').offsetWidth * 0.08 + 'px';
	}
};




/*jslint browser: true, plusplus: true, regexp: true, indent: 4, white:true */
/*global Modernizr, jQuery */

jQuery(function ($) {
	'use strict';

	var $window = $(window);

	// initialize qTip tooltips
	function initializeQTips(container) {
		var style = {
			tip: {
				width: 15,
				height: 10,
				mimic: 'center',
				offset: 15
			}
		};
		container = container || $(document.body);

		container.find('.tooltip, .tooltipped').each(function () {
			var element = $(this),
				target = element.data('tooltip');

			if (target) {
				element.find('> .icon').remove();
				// append a separate trigger
				element = $('<span>', {
					'class': 'icon',
					'text': 'i'
				}).appendTo(element);
			}

			element.qtip({
				// extract content from the element:
				content: target ? $(target) : element.html(),
				show: {
					// show on both mouse enter and click:
					event: 'mouseenter click',
					delay: 350, //necessary for Android
					
					// allow only one open qTip:
					solo: true
				},
				// allow the user to hover the tooltip:
				hide: {
					fixed: true,
					delay: 300
				},
				// reposition using the following viewport:
				position: {
					viewport: $window,
					my: 'bottom center',
					at: 'top center'
				},
				style: style
			});
		});
	}

	window.initializeQTips = initializeQTips;

	initializeQTips();
});

/*!
 * accounting.js v0.4.2, copyright 2014 Open Exchange Rates, MIT license, http://openexchangerates.github.io/accounting.js
 */
(function(p,z){function q(a){return!!(""===a||a&&a.charCodeAt&&a.substr)}function m(a){return u?u(a):"[object Array]"===v.call(a)}function r(a){return"[object Object]"===v.call(a)}function s(a,b){var d,a=a||{},b=b||{};for(d in b)b.hasOwnProperty(d)&&null==a[d]&&(a[d]=b[d]);return a}function j(a,b,d){var c=[],e,h;if(!a)return c;if(w&&a.map===w)return a.map(b,d);for(e=0,h=a.length;e<h;e++)c[e]=b.call(d,a[e],e,a);return c}function n(a,b){a=Math.round(Math.abs(a));return isNaN(a)?b:a}function x(a){var b=c.settings.currency.format;"function"===typeof a&&(a=a());return q(a)&&a.match("%v")?{pos:a,neg:a.replace("-","").replace("%v","-%v"),zero:a}:!a||!a.pos||!a.pos.match("%v")?!q(b)?b:c.settings.currency.format={pos:b,neg:b.replace("%v","-%v"),zero:b}:a}var c={version:"0.4.1",settings:{currency:{symbol:"$",format:"%s%v",decimal:".",thousand:",",precision:2,grouping:3},number:{precision:0,grouping:3,thousand:",",decimal:"."}}},w=Array.prototype.map,u=Array.isArray,v=Object.prototype.toString,o=c.unformat=c.parse=function(a,b){if(m(a))return j(a,function(a){return o(a,b)});a=a||0;if("number"===typeof a)return a;var b=b||".",c=RegExp("[^0-9-"+b+"]",["g"]),c=parseFloat((""+a).replace(/\((.*)\)/,"-$1").replace(c,"").replace(b,"."));return!isNaN(c)?c:0},y=c.toFixed=function(a,b){var b=n(b,c.settings.number.precision),d=Math.pow(10,b);return(Math.round(c.unformat(a)*d)/d).toFixed(b)},t=c.formatNumber=c.format=function(a,b,d,i){if(m(a))return j(a,function(a){return t(a,b,d,i)});var a=o(a),e=s(r(b)?b:{precision:b,thousand:d,decimal:i},c.settings.number),h=n(e.precision),f=0>a?"-":"",g=parseInt(y(Math.abs(a||0),h),10)+"",l=3<g.length?g.length%3:0;return f+(l?g.substr(0,l)+e.thousand:"")+g.substr(l).replace(/(\d{3})(?=\d)/g,"$1"+e.thousand)+(h?e.decimal+y(Math.abs(a),h).split(".")[1]:"")},A=c.formatMoney=function(a,b,d,i,e,h){if(m(a))return j(a,function(a){return A(a,b,d,i,e,h)});var a=o(a),f=s(r(b)?b:{symbol:b,precision:d,thousand:i,decimal:e,format:h},c.settings.currency),g=x(f.format);return(0<a?g.pos:0>a?g.neg:g.zero).replace("%s",f.symbol).replace("%v",t(Math.abs(a),n(f.precision),f.thousand,f.decimal))};c.formatColumn=function(a,b,d,i,e,h){if(!a)return[];var f=s(r(b)?b:{symbol:b,precision:d,thousand:i,decimal:e,format:h},c.settings.currency),g=x(f.format),l=g.pos.indexOf("%s")<g.pos.indexOf("%v")?!0:!1,k=0,a=j(a,function(a){if(m(a))return c.formatColumn(a,f);a=o(a);a=(0<a?g.pos:0>a?g.neg:g.zero).replace("%s",f.symbol).replace("%v",t(Math.abs(a),n(f.precision),f.thousand,f.decimal));if(a.length>k)k=a.length;return a});return j(a,function(a){return q(a)&&a.length<k?l?a.replace(f.symbol,f.symbol+Array(k-a.length+1).join(" ")):Array(k-a.length+1).join(" ")+a:a})};if("undefined"!==typeof exports){if("undefined"!==typeof module&&module.exports)exports=module.exports=c;exports.accounting=c}else"function"===typeof define&&define.amd?define([],function(){return c}):(c.noConflict=function(a){return function(){p.accounting=a;c.noConflict=z;return c}}(p.accounting),p.accounting=c)})(this);

/*jslint browser: true, plusplus: true, regexp: true, indent: 4, white:true */
/*global Modernizr, jQuery, quadiaPlayer, accounting, feed */
jQuery(function ($) {
    "use strict";

    /**
     * Creates an alert pop up
     * @param {{title: String, subtitle: String, content: (*|jQuery|HTMLElement)}} content
     * @param {{containerElement: {}, titleElement: {}, subtitleElement: {}, contentElement: {}, buttonsElement: {}, buttons: {name: String}}} options Options object which allows the definition of sub element attributes and content. Objects are passed directly to the jQuery constructor.
     * @returns {{update: update, $element: (*|jQuery|HTMLElement), mfp: *}}
     * @todo Do we want to globalize this?
     */
    function alertPopUp(content, options) {
        var $container, $title, $subtitle, $content, $buttons, button;

        content = $.extend({}, {
            'title': '[no title]',
            'subtitle': null,
            'content': '[no-text]'
        }, content || {});

        options = $.extend(true, {
            'containerElement': {
                'class': 'lightbox-alert border-less block'
            },
            'titleElement': {
                'class': 'title'
            },
            'subtitleElement': {
                'class': 'subtitle'
            },
            'contentElement': {
                'class': 'popup-content'
            },
            'buttonsElement': {
                'class': 'buttons'
            },
            'buttons': {
                'close': 'Sluiten'
            }
        }, options || {});

        $container = $('<article>', options.containerElement);
        $title = $('<h2>', options.titleElement).appendTo($container);
        $subtitle = $('<p>', options.subtitleElement);
        $content = $('<div>', options.contentElement).appendTo($container);
        $buttons = $('<div>', options.buttonsElement).appendTo($container);

        $.each(options.buttons, function (name, value) {
            $('<button>', {
                'class': 'action button',
                'text': value
            }).appendTo($buttons).on('click', function (event) {
                event.preventDefault();
                $.magnificPopup.close();
            });
        });

        function update(content) {
            if (content.title) {
                $title.text(content.title);
            }
            if (content.hasOwnProperty('subtitle')) {
                if (content.subtitle) {
                    $subtitle.text(content.subtitle).insertAfter($title);
                } else {
                    $subtitle.remove();
                }
            }
            if (content.content) {
                $content.html(content.content);
            }
        }

        update(content);

        return {
            'update': update,
            '$element': $container,
            'mfp': $.magnificPopup.open({
                'items': {
                    'src': $container,
                    'closeBtnInside': false
                }
            })
        };
    }

    /**
     * This form gives us the option to add or remove channels,
     * the feed variable is set on a global level in is generated by incentro
     **/
    $('.price-form').each(function () {
        var $container = $(this),
            $channels = $container.find('.channels-form .channels'),
            $pricingContainer = $container.find('.pricing'),
            $pricing = $pricingContainer.find('.channels'),
            $price = $pricingContainer.find('.price .total span'),
            $reach = $pricingContainer.find('.price .reach span'),

            business = $container.find('input:radio[name=doelgroep][value=Zakelijk]').is(":checked");

            $container.find('input:radio[name=doelgroep]').on('change',function(){
                business = $container.find('input:radio[name=doelgroep][value=Zakelijk]').is(":checked");

                $pricing.find('.amount').trigger('change');
            });

        $channels.find('input').each(function(){
            var $this = $(this),
                $channel = $this.parents('.row'),
                $el, data;


            /* find channel data in json */
            $.each(feed.Pricings, function (i, v) {
                if(feed.Pricings[i].Id == $this.val()){
                    data = feed.Pricings[i].Rate;

                    return false;
                }
            });

            if(data){

            $this.on('change', function(){
                var price;
                /*
                * When a element is checked we add it to the list with the other channels
                * */
                if($this.is(':checked')) {

                    $el = $('<div class="channel"><a href="#" class="delete">Verwijderen</a>' +
                        '<p class="channel-title">' + $channel.find('.description').text() + '</p>' +
                        '</div>');

                    /*
                     * fixed only has a price witch can't be changed.
                     * */

                    if (data.PriceType === 'Fixed') {

                        price = getElementPrice(data, business, false);

                        $el.append('<div class="form-row text"><input type="hidden" name="' + $this.val() + '" class="amount" value="' + data.Rates[0].Amount + '" ><label class="label">Prijs</label> <span class="field"><input type="number" class="input price" value="' + price.price + '" readonly></span></div>');
                    }

                    if (data.PriceType === 'Flexible' || data.PriceType === 'Sliding-scale') {
                        /*
                         * the normal version allows for a price and amount, sliding scale generates a select field
                         * */
                        if (data.PriceType === 'Flexible') {

                            $el.append(
                                '<div class="form-row text"><label class="label">Bereik</label> <span class="field"><input type="number" name="' + $this.val() + '" class="input amount" min="' + data.Rates[0].Amount + '" value="' + data.Rates[0].Amount + '" ></span></div>' +
                                '<div class="form-row text"><label class="label">Prijs</label> <span class="field"><input type="number" step="0.01" class="input price" value="" ></span></div>'
                            );
                        } else {

                            var $options = $('<select class="input amount" name="' + $this.val() + '"></select>');

                            $.each(data.Rates, function (i) {
                                $options.append('<option value="' + data.Rates[i].Amount + '">' + data.Rates[i].Amount + '</option>');
                            });

                            $el.append(
                                '<div class="form-row select"><label class="label">Bereik</label> <span class="field">' + $options[0].outerHTML + '</span></div>' +
                                '<div class="form-row text"><label class="label">Prijs</label> <span class="field"><input type="number" step="0.01" class="input price" value="" readonly></span></div>'
                            );
                        }
                    }
                        /**
                         *  When the channel has a checkbox available add that to the list of options
                         */
                        if (data.ChannelOptions && accounting.toFixed(data.ChannelOptions.ItemPrice, 2) > 0) {


                            var id = Math.floor((Math.random() * 1000) + 1);
                            var channelOption = '<div class="form-row single checkboxes"><span class="field">';
                            var dataChannelChecked = String(data.ChannelOptions.Checked);

                            if (dataChannelChecked.toLowerCase() != 'true') {
                                channelOption += '<input class="input check" type="checkbox" name="" id="field-' + id + '" value="1">';
                            } else {
                                channelOption += '<input class="input check" type="checkbox" name="" id="field-' + id + '" value="1" checked="True">';
                            }
                            channelOption += '<label class="label" for="field-' + id + '">' + data.ChannelOptions.Description + '</label></span></div>';

                            $el.append(channelOption);
                        }

                        var $amount = $el.find('.amount'),
                            $price = $el.find('.price'),
                            $check = $el.find('.check');

                        /*
                         * Price and amount have a relation with each other so we need to change both.
                         */

                        price = getElementPrice(data, business, $check.is(':checked'));

                        $check.on('change', function () {
                            $amount.trigger('change');
                        });

                        $amount.on('change', function () {

                            price = getElementPrice(data, business, $check.is(":checked"), $(this).val());

                            $amount.val(price.amount);
                            $price.val(price.price);

                            $pricing.trigger('recalculate');

                        }).trigger('change');

                        $price.on('change', function () {

                            price = getElementPrice(data, business, $check.is(":checked"), 0, $(this).val());

                            $amount.val(price.amount);
                            $price.val(price.price);

                            $pricing.trigger('recalculate');
                        });


                        /**
                         * When a user  removes ( or unchecks) the element remove it.
                         */
                        $el.find('.delete').on('click', function (event) {
                            event.preventDefault();
                            $el.remove();
                            $this.attr('checked', false).trigger('change');
                        });

                        $pricing.append($el);

                        $('select.input').selectBoxIt();

                        $pricing.trigger('recalculate');

                        // check for up-selling

                        if ($channel.data('up-selling')) {
                            $container.find('.' + $channel.data('up-selling')).show();
                        }

                } else {
                    if ($el) {
                        $el.remove();
                    }
                    /*
                     * We have some up selling options ( when the data element is set show the class )
                     * */

                    if ($channel.data('up-selling')) {
                        $container.find('.' + $channel.data('up-selling')).hide();
                    }

                    $pricing.trigger('recalculate');
                }

                $channel.toggleClass('is-active', $this.is(':checked'));


            }).trigger('change');
            } else{
                $channel.hide();
            }
        });

        $pricing.on('recalculate',function(){

            var totalPrice = 0;
            var totalReach = 0;

            $pricing.find('.price').each(function(){
                totalPrice += Number($(this).val());
            });

            $pricing.find('.amount').each(function(){
                if (Number($(this).val()) > 1) {
                    totalReach += Number($(this).val());
                }
            });

            if(totalReach <= 0){
                $reach.parent().hide();
                $reach.parent().prev().hide();
            }else{
                $reach.parent().show();
                $reach.parent().prev().show();
            }

            $price.text(accounting.formatNumber(totalPrice, 2, ".", ","));
            $reach.text(totalReach);
            $pricingContainer.toggleClass('no-channels',totalPrice == 0);
        });

        $('.price-form .first-step-form').on('submit',function(event){

            event.preventDefault();

            var $popupForm = $('#request-quote'),
                channels = [];

            $('.pricing-form .channels .channel').each(function(){
                var $channel = $(this);

                $channel.find('.amount').each(function(){
                    var $input = $(this);

                    if($input.is('input') || $input.is('select')){
                        channels.push({"id": $input.attr('name'), "Amount" : $input.val(), "Checked": $channel.find('.checkboxes input').is(':checked') });
                    }
                });
            });

            $popupForm.find('input[name="channel"]').val(JSON.stringify(channels));
            $popupForm.find('input[name="target"]').val($('.channels-form input[name="doelgroep"]:checked').val());

            $popupForm.one('submit',function(event){
                var $form = $(this);

                event.preventDefault();

                $.ajax({
                    type: "POST",
                    url: $form.attr("action"),
                    data: $form.serialize(),
                    success: function () {
                        var data = $form.data();

                        $.magnificPopup.close();

                        alertPopUp({
                            'title': data.alertTitle,
                            'subtitle': data.alertSubtitle,
                            'content': $('<p>', {
                                'html': data.alertText
                            })
                        });
                    }
                });
            });

             // open a popup with a new form
            $.magnificPopup.open({
                items: {
                    src: $popupForm
                },
                type: 'inline',
                preloader: false,
                focus: '#name',

                // When element is focused, some mobile browsers in some cases zoom in
                // It looks not nice, so we disable it:
                callbacks: {
                    beforeOpen: function() {
                        if($(window).width() < 700) {
                            this.st.focus = false;
                        } else {
                            this.st.focus = '#name';
                        }
                    }
                }
            });

            $popupForm.find('.cancel').on('click', function(event){ event.preventDefault(); $.magnificPopup.close();});
        });

        $container.find('.trigger-popup').each(function(){

              $(this).magnificPopup({
                type: 'inline',
                preloader: false,
                focus: '#name',

                // When element is focused, some mobile browsers in some cases zoom in
                // It looks not nice, so we disable it:
                callbacks: {
                    beforeOpen: function() {
                        if($(window).width() < 700) {
                            this.st.focus = false;
                        } else {
                            this.st.focus = '#name';
                        }
                    }
                }
            });

            $(this.getAttribute('href')).find('.cancel').on('click', function(event){ event.preventDefault(); $.magnificPopup.close();});
        });

        // we want the channel form to move up ( desktop and up )
        if($(window).width() >= 1001) {

            var $form = $container.find('.channels-form'),
                offset = $form.find('fieldset').first().position();

           $form.css('margin-top', - (80 + offset.top ));

        }

    });

    $('#popup-form').on('submit', function (event) {
        var $form = $(this);

        event.preventDefault();

        $.ajax({
            type: "POST",
            url: $form.attr("action"),
            data: $form.serialize(),
            success: function () {

                var data = $form.data();

                //empty the form
                $form[0].reset();

                // close the popup
                $.magnificPopup.close();


                // show the thank you popup
                alertPopUp({
                    'title': data.alertTitle,
                    'subtitle': data.alertSubtitle,
                    'content': $('<p>', {
                        'html': data.alertText
                    })
                });
            }
        });
    });

/* helper functions */


function getElementPrice(data, isBusiness, isChecked, amount, price){

    var row = {
        min_amount: 0,
        min_price: 0,
        price:0,
        amount: 0
    }

    amount = typeof amount !== 'undefined' ? parseInt(amount) : 0;
    price = typeof price !== 'undefined' ? price : 0;

    var business = 0,
        add = 0;

    if(isBusiness){
        business = data.Rates[0].Business;
    }

    if(data.ChannelOptions && accounting.toFixed(data.ChannelOptions.ItemPrice, 2) > 0){
        add = data.ChannelOptions.ItemPrice;

        if(isChecked){
            add = data.ChannelOptions.PriceChecked;

            if(add < 0 || data.ChannelOptions.PriceChecked == 0){add = 0};
        }

        if(isBusiness){
            add  = data.ChannelOptions.ItemPrice + data.ChannelOptions.Difference;

            if(isChecked){
                add = data.ChannelOptions.PriceChecked + data.ChannelOptions.Difference;
                if(add < 0 || data.ChannelOptions.PriceChecked == 0){add = 0};
            }
        }
    }

    row.min_amount = data.Rates[0].Amount;
    row.min_price  = accounting.toFixed(data.Rates[0].Amount * (data.Rates[0].Price + business + add) + data.Rates[0].FixedPrice, 2);

    if(amount > 0){

        row.amount = amount;

        $.each(data.Rates, function (i, rate) {

            if(row.amount >= rate.Amount){

                if(isBusiness){
                    row.price  = accounting.toFixed(amount * (rate.Price + rate.Business + add) + rate.FixedPrice, 2);
                }else{
                    row.price  = accounting.toFixed(amount * (rate.Price + add) + rate.FixedPrice, 2);
                }


            }else{
                return false;
            }
        });
    }

    if(price > 0){

        row.price = accounting.toFixed(price,2);
        var fixed = data.Rates[0].FixedPrice;

        $.each(data.Rates, function(i) {

            var rulePrice = data.Rates[i].Price + business + add;

            fixed = data.Rates[i].FixedPrice;

            if(row.price - fixed >= (data.Rates[i].Amount * rulePrice)){
                price = rulePrice;
            }else{
                return false;
            }
        });

        row.amount = (Math.floor((row.price - fixed) / price));
    }

    if(accounting.unformat(row.price) < accounting.unformat(row.min_price)){
        row.price = row.min_price;
    }

    if(row.amount < row.min_amount){
        row.amount = row.min_amount;
    }

    return row;
    }
});

// JavaScript Document

var PNLNav = PNLNav || {};
PNLNav.Site = {
	busy: false,

	// Resize
	desktopSize: 1151,
	tabletSize: 1001,
	mobileSize: 767,
	mobilePortraitSize: 481,
	resizeThrottle: undefined,
	activeMenuItem: undefined,
	currentWidth: undefined,
    initialised: false,

	init: function() {
		setTimeout(function() {
            if ($('#PostNL_globalNav_header').length && !PNLNav.Site.initialised) {
                PNLNav.Site.initialised = true;
                PNLNav.Site.currentWidth = $(window).width();

                PNLNav.Site.fixedHeader();
                PNLNav.Site.toggleMobileMenu(); // TODO: this should be triggered from the account-widget.js
                PNLNav.Site.toggleMenuCategories();
                PNLNav.Site.searchFocus();
                PNLNav.Site.initShopcart();
                PNLNav.Site.largeMenuTouch();
                PNLNav.Site.largeLanguageTouch();
                PNLNav.Site.toggleMobileFooterMenu();

                // resize
                $(window).resize(PNLNav.Site.docResize);

                // scroll
                $(window).scroll(PNLNav.Site.docScroll);
            }
		}, 10);
	},

	docResize: function() {
		// on resize several checks are done. This is done with a throttle, so that the events don't flood the browser
		PNLNav.Site.resizeThrottle = setTimeout(function() {
			PNLNav.Site.currentWidth = $(window).width(); // update current width
			PNLNav.Site.closeMobileMenus();	// Close/Reset the menu, when switched from small to large viewport
			PNLNav.Site.largeMenuTouch(); // listen for touch-events in menu on large viewports
			PNLNav.Site.largeLanguageTouch(); // listen for touch-events in language picker on large viewports
			PNLNav.Site.closeShopcartTooltip(); //
		}, 500);
	},

	closeShopcartTooltip: function() {
		clearTimeout(PNLNav.Site.resizeThrottle);
		var shopcartIcon = $('.shopcart-icon');
		if (($(window).width() < PNLNav.Site.tabletSize)) {
			shopcartIcon.removeClass('open');
		};
	},

	largeMenuTouch: function() {
		clearTimeout(PNLNav.Site.resizeThrottle);
		var navItems = $('nav > ul > li:not(.home)');
		navItems.on('touchstart', function ($event) {
			if (PNLNav.Site.currentWidth > PNLNav.Site.tabletSize) {
				var hasSubmenu = $(this).find('ul').length > 0;

				// If submenu should be opened
				if (!$(this).hasClass('hover') && hasSubmenu){
					$event.preventDefault();
					$event.stopPropagation();
					navItems.removeClass('hover');
					$(this).addClass('hover');

					// event listener on body for closing the menu
					$('body').on('touchend', PNLNav.Site.largeMenuCloseMenu);
				}

				// "else" follow link
			}
		});
	},

	largeMenuCloseMenu: function() {
		var navItems = $('nav > ul > li:not(.home)');
		// if touch target is not in the <nav> element
		if (!$(event.target).parents('nav').length > 0 ) {
			navItems.removeClass('hover');
			// remove body event listener, to prevent flooding of eventlisteners
			$('body').off('touchend', PNLNav.Site.largeMenuCloseMenu)
		}
	},

	largeLanguageTouch: function() {
		clearTimeout(PNLNav.Site.resizeThrottle);

        var languageOptions = $('.language-options').find('ul');
		var languageOptionsActive = $('.language-options').find('ul li.active a');

        languageOptionsActive.unbind()
        languageOptions.unbind()

        languageOptionsActive.on('click', function($event) {
            // if picker is not open yet, open it
            if (!$('.language-options ul').hasClass('hover')) {
                $event.preventDefault();
                $event.stopPropagation();
                $('.language-options ul').addClass('hover');


            } else {
                $('.language-options ul').removeClass('hover');
                $event.preventDefault();
                $event.stopPropagation();
            }

        })

        languageOptions.on('click', function($event) {
            // if picker is not open yet, open it
            if ($('.language-options ul').hasClass('hover')) {
                $('.language-options ul').removeClass('hover');
            }
        })
	},

	largeLanguageTouchClose: function() {
		var languageOptions = $('.language-options').find('ul');
		// if touch target is not in the .language-options element
		if (!$(event.target).parents('.language-options').length > 0 ) {
			languageOptions.removeClass('hover');
			// remove body event listener, to prevent flooding of eventlisteners
			$('body').off('touchend', PNLNav.Site.largeLanguageTouchClose);
		}
	},


	closeMobileMenus: function() {
		clearTimeout(PNLNav.Site.resizeThrottle);
		var header = $('#PostNL_globalNav #PostNL_globalNav_header');
		var navButton = header.find('.mobile-nav');

		// simulate 'close' click if window resize results in small viewport to large viewport AND one of the menu's
		// is open.

		if (($(window).width() > PNLNav.Site.tabletSize) && (header.hasClass('show-menu-left'))) {
			navButton.click();
		}

	},

	docScroll: function() {
	},

	fixedHeader: function() {

		var header = $('#PostNL_globalNav_header');
		var lastScrollTop = 0;

		function setHeader() {
			var windowHeight = $(window).height();
			var siteHeight = $('body').outerHeight();
			var scrollMargin = (siteHeight - windowHeight);
			var scrollTop = $(document).scrollTop();
			if (scrollTop > lastScrollTop){
				if (scrollTop > 50) {
					header.addClass('removed');
				}
			}
			else {
				if (scrollTop < scrollMargin) {
					header.removeClass('removed');
				}
			}
			header.toggleClass('PostNL_globalnav_added', scrollTop > 125);

			lastScrollTop = scrollTop;
		}

		$('body').scroll(function(){
			setHeader();
		});

		$(window).scroll(function(){
			setHeader();
		});

		var windowHeight = $(window).height();
		var siteHeight = $('.site').outerHeight();

		if (siteHeight <= windowHeight) {
			header.removeClass('removed');
		}
	},

	toggleMobileMenu: function() {
		var header = $('#PostNL_globalNav #PostNL_globalNav_header');
		var navButton = header.find('.mobile-nav');
		var body = $('body');
		var scrollPos;


		navButton.click(function() {
			if(!header.hasClass('show-menu-left')) {
				header.addClass('show-menu-left');
				scrollPos = $(window).scrollTop();
				body.addClass('menu-open');
				PNLNav.Site.activeMenuItem = header.find('nav').find('.active');
			}
			else {
				header.removeClass('show-menu-left');
				header.find('nav').find('.active').removeClass('active');
				body.removeClass('menu-open');
				window.scrollTo(0, scrollPos);
				PNLNav.Site.activeMenuItem.addClass('active');
			}

			if(header.hasClass('show-menu-right')) {
				header.removeClass('show-menu-right');
			}
		});
	},

	toggleMenuCategories: function() {
		$('#PostNL_globalNav_header').find('li').click(function(e) {
			var target = $(e.target);
			if(($(window).width() < PNLNav.Site.tabletSize) && (!target.is('a') && !target.parents().is('.quicklinks'))) {
				if($(this).find('a').next().is('div')) {
					// alert('parent');
					var thisLi = $(this);
					var otherLi = thisLi.siblings('li');

					if(!thisLi.hasClass('active')) {
						thisLi.addClass('active');
						otherLi.removeClass('active');
						otherLi.find('li').removeClass('active');
					}
					else {
						thisLi.removeClass('active');
						thisLi.find('li').removeClass('active');
					}
					e.preventDefault();
					e.stopPropagation();
				}
			}
		});
	},

	searchFocus: function() {
		var navMenu = $('#PostNL_globalNav_header').find('.navigation-menu');
		var navSearch = $('#PostNL_globalNav_header').find('.navigation-search');
		var navSearchInput = $('#PostNL_globalNav_header').find('.navigation-search input[type="search"]');
		var searchForm = $('#PostNL_globalNav_header').find('#search-form');

		navSearch.hover(function() {
				navMenu.addClass('search-hover');
			},
			function() {
				navMenu.removeClass('search-hover');
			});

		navSearchInput.focus(function() {
			navMenu.addClass('search-focus');
		});

		navSearchInput.blur(function() {
			// small timeout so the blur isn't invoked immediately when the use presses the 'submit' button
			var blurInput = setTimeout((function(){
				navMenu.removeClass('search-focus');
			}), 100);
		});

		searchForm.submit(function() {
			if (!navSearchInput.val()) {
				return false;
			}
		});
	},

	initShopcart: function() {
		var header = $('#PostNL_globalNav_header');
		var shopCart = header.find('.carts');
		if(!shopCart.length) {
			header.addClass('no-carts');
		}
	},

	toggleMobileFooterMenu: function() {
		var
			computedstyle,
			ACTIVE_CLASS = 'active';
			triggers = $('#PostNL_globalNav_footer_variable, #PostNL_globalNav_footer_fixed')
				.find('[data-role=trigger]'),
			lis = triggers.closest('li');

		triggers.on('click', function() {
			var
				triggerLi = $(this).closest('li'),
				ul = triggerLi.find('ul');
			lis.not(triggerLi)
				.removeClass(ACTIVE_CLASS)
				.find('ul').attr('style', null);
			if(triggerLi.hasClass(ACTIVE_CLASS)) {
				ul.attr('style', null);
			} else {
				computedstyle = getComputedStyle(ul[0]);
				ul.height(
					ul[0].scrollHeight -
					computedstyle.paddingTop.split('px')[0] -
					computedstyle.paddingBottom.split('px')[0]
				);
			}
			triggerLi.toggleClass(ACTIVE_CLASS);
		});
	}
};

$(document).ready(PNLNav.Site.init);

(function ($) {

    $.fn.delayKeyup = function (callback, ms) {
        var timer = 0;
        $(this).keyup(function () {
            clearTimeout(timer);
            timer = setTimeout(callback, ms);
        });
        return $(this);
    };

    $.fn.autoSuggest = function () {
        var defaults = {
            input: "",
            data: [],
            clicked: false
        },
            settings = $.extend({}, defaults),

            showSearch = function (that) {
                $(that).find('.suggestion-results').show();
            },

            resetSearch = function (that) {
                $(that).find('.suggestion-results').hide();
                $(that).find('.gsa-suggestions').html('');
                $(that).find('.suggestions').html('');
            },

            // Get all autosuaggest data.
            getData = function (that) {
                $.ajax({
                    type: 'GET',
                    url: '/api/Autosuggestion/' + $(that).data('publication'),
                    dataType: 'json',
                    success: function (response) {
                        settings.data = response;
                    }
                });
            },

            gsaAutoComplete = function (that) {
                var $input = $(that).find('input.autocomplete');
                var currentLanguage = $('body').find('.current-language').data('language');
                var count = 0;
                $.ajax({
                    type: 'GET',
                    url: currentLanguage + '/search/suggest?q=' + $input.val(),
                    dataType: 'json',
                    success: function (response) {
                        response = typeof response === 'string' ? $.parseJSON(response) : response;
                        if (response != null) {
                            var list = $('<ul />');
                            var re = new RegExp($input.val(), "g");
                            $.each(response, function (index, suggestion) {
                                count++;
                                var text = suggestion.replace(re, '<strong>' + $input.val() + '</strong>');
                                var suggest = $('<li />').append(
                                    $('<a />', {
                                        'href': currentLanguage + '/search?q=' + suggestion + '&searchEntry=auto-suggest',
                                        'class': 'gsa-suggest-link',
                                        'html': text
                                    })
                                );
                                list.append(suggest);
                            });
                            $(that).find('.gsa-suggestions').html(list);
                        }

                        $('.gsa-suggestions ul li').on('click', function () {

                            var url = $(this).find('a').attr('href');
                            window.location.href = url;
                        });
                        // show results
                        if (count > 0) {
                            showSearch(that);
                        } else {
                            resetSearch(that);
                        }
                        getMatches(that);
                    }
                });
            },

            getMatches = function (that) {
                var $input = $(that).find('input.autocomplete');
                var suggestData = [];
                $.each(settings.data, function (index, suggestion) {
                    var matched = false;
                    $.each(suggestion.matches, function (index, match) {
                        if (match.indexOf($input.val()) > -1) {
                            matched = true;
                        }
                    });
                    if (matched && $input.val().length > 2) {
                        suggestData.push({
                            type: 'tridion',
                            'data': {
                                title: suggestion.title,
                                description: suggestion.description,
                                image: suggestion.image,
                                button: suggestion.button
                            }
                        });
                    }
                });

                if (suggestData.length > 0) {
                    renderTridionData(that, suggestData);
                    $(that).find('.suggestions').show();
                    showSearch(that);
                } else {
                    $(that).find('.suggestions').hide();
                }
            },

            renderTridionData = function (that, suggestData) {
                var suggestions = [];
                if (suggestData.length > 0) {
                    $.each(suggestData, function (index, suggestion) {
                        // Create suggest
                        var suggest = ('<a href="' + suggestion.data.button.Url + '" target="' + suggestion.data.button.Target + '" class="suggestion">' +
                            '<div class="image-block" style="background-image: url(' + suggestion.data.image.Url + ')"></div>' +
                            '<div class="content">' +
                            '<h2 class="title">' + suggestion.data.title + '</h2>' +
                            '<div class="description">' + suggestion.data.description + '</div>' +
                            '</div>' +
                            '</a>');


                        suggestions.push(suggest);
                    });
                    $(that).find('.suggestions').html(suggestions);
                }
            }

        return this.each(function () {
            var that = this;
            var $input = $(that).find('input.autocomplete');

            // Get autosuggest data if data is zero.
            $input.on('click', function () {
                if (settings.data.length == 0) {
                    getData(that);
                }
            });

            // Start with GSA auto suggests.
            $input.delayKeyup(function () {
                if ($input.val().length > 0) {
                    gsaAutoComplete(that);
                } else {
                    resetSearch(that);
                }
            }, 300);

            $('.suggestions').on('click', function () {
                settings.clicked = true;
            }),
            // If input field focus show results or reset results.
            $(window).on('click', function () {
                if ($input.is(':focus')) {
                    if ($input.val().length > 0) {
                        gsaAutoComplete(that);
                    }
                } else {
                    if (!settings.clicked) {
                        resetSearch(that);
                    }
                    settings.clicked = false;
                }
            });
            $('ol#main-menu li').hover(function () {
                if ($(this).find('a').hasClass('has-children')) {
                    $(that).find('.suggestion-results').hide();
                }
            }, function () {
                if ($input.is(':focus')) {
                    if ($input.val().length > 0) {
                        $(that).find('.suggestion-results').show();
                    }
                }
            });

        });
    };

    PNLNav.GSA = {
        init: function () {
            // Only start if object is available
            // This makes it possible to initialize without objects present. In
            // combination with Angular the object will not be available on
            // ready. Angular will make a second call to initializiation when
            // decided it's ready.
            if ($('form.new-header-search').length > 0) {

                $('.new-header-search').on('submit', function () {
                    if ($(this).find('input.gsa-autocomplete').val() == '') {
                        return false;
                    }
                });

                $('form.new-header-search').autoSuggest();
            }
        }
    };
}(jQuery));

$(document).ready(PNLNav.GSA.init);

$(function () {
    $('div.external-form:not(.win-campaign)').find('form').on('submit', function () {
       $(this).find('span.submit').addClass('loading');
    });
    $('form.popup-form').on('submit', function () {
        $(this).find('button[type=submit]').addClass('loading');
    });
});
var ECOM = ECOM || {};
ECOM.Site = {
    cookieName: 'customerCartId',
    endPoint: undefined,
    customerCartId: null,
    shopcartIcon: $('.shopcart-icon'),
    busyButton: undefined, // Holds active add-to-cart button
    loadingClass: 'loading',
    doneClass: 'added',
    errorClass: 'error',

    init: function() {
        setTimeout(function() {
            ECOM.Site.bindButtons();
        }, 10);
    },

    // listen for click event on 'add' button
    bindButtons: function() {
        $('.add-to-cart').on('click', function() {
          // We only allow on click at a time
            if (!ECOM.Site.busyButton) {
                // console.log('click()', this);

                var productID = $(this).data('productId');
                var amount = $(this).data('cartAmount');
                ECOM.Site.busyButton = $(this);
                ECOM.Site.busyButton.addClass(ECOM.Site.loadingClass);

                ECOM.Site.endPoint = $(this).data('apiUrl') + 'carts/';

                ECOM.Site.addToCart(productID, amount);
            } else {
                //console.log('click() ignored');
            }

        });
    },

    // Check if cookie with cartID exists, if it exists, check that it is still valid
    // if it is valid add the product to the existing cart
    // If not, create a new cart
    addToCart: function(productID, amount) {
        if (ECOM.Site.busyButton) {
            if (ECOM.Site.checkCookie()) {
                $.get(ECOM.Site.endPoint + ECOM.Site.customerCartId)
                    .done(function(result) {
                        if(result.id) {
                            ECOM.Site.addToExistingCart(productID, amount);
                        } else {
                            ECOM.Site.createNewCart(productID, amount);
                        }
                    })
                    .error(function() {
                        ECOM.Site.createNewCart(productID, amount);
                    });
            } else {
                ECOM.Site.createNewCart(productID, amount);
            }
        } else {
            // console.log('addToCart() ignored');
        }
    },

    // checkCookie sets the ECOM.Site.customerCartId variable with the existing cookie and returns true
    // OR it returns false
    checkCookie: function() {
        var value = "; " + document.cookie;
        var parts = value.split("; " + ECOM.Site.cookieName + "=");

        if (parts.length == 2) {
            ECOM.Site.customerCartId = JSON.parse(parts.pop().split(";").shift());
            return true;
        } else {
            return false;
        }
    },

    // set the cookie with the cartID as input
    // This function is called from the createNewCart function
    setCookie: function(cartID) {
        var lifeTime = 7; //7 days
        var date = new Date();
        date.setTime(date.getTime() + (lifeTime * 24 * 60 * 60 * 1000));
        var expires = "; expires=" + date.toGMTString();

        ECOM.Site.customerCartId = cartID;
        document.cookie = ECOM.Site.cookieName + "=" + cartID + expires + ";domain=.postnl.nl;path=/";
    },

    // Post to the API. response contains a cartID in which we can place items
    createNewCart: function(productID, amount) {
        // console.log('createNewCart()');

        $.ajax({
            type: "POST",
            url: ECOM.Site.endPoint,
            error: function(error) {
                ECOM.Site.doneLoading('error');
            },
            success: function(result) {
                // set the cookie with the cartID
                var cartID = result.replace(/['"]+/g, '');
                ECOM.Site.setCookie(cartID);

                if (productID) {
                    // Cart exists now, so add the clicked item to the cart
                    ECOM.Site.addToExistingCart(productID, amount);
                }
            }
        });
    },

    // add product to the cart
    addToExistingCart: function(productID, amount) {
        // console.log('addToExistingCart()');
        var addToCartEndpoint = ECOM.Site.endPoint + ECOM.Site.customerCartId + '/items';
        var cart = {
            "cartItem": {
                "quoteId": ECOM.Site.customerCartId,
                "sku": productID,
                "qty": amount
            }
        };
        var data = {
            'data': cart
        };

        $.ajax({
            type: "POST",
            url: addToCartEndpoint,
            data: data,
            error: function(error) {
                ECOM.Site.doneLoading('error');
            },
            success: function(result) {
                ECOM.Site.doneLoading('success');
                ECOM.Site.updateCartCounter(amount);
            }
        });
    },

    doneLoading: function(state) {
        // console.log('doneLoading()');
        ECOM.Site.busyButton.removeClass(ECOM.Site.loadingClass);

        if (state === 'success') {
            ECOM.Site.busyButton.addClass(ECOM.Site.doneClass);
            // console.log('doneLoading(success)');
            setTimeout(function() {
                ECOM.Site.busyButton.removeClass(ECOM.Site.doneClass);
                ECOM.Site.busyButton = null;
                // console.log('doneLoading(done)');
            }, 1200);
        } else {
            // console.log('doneLoading(error)');
            ECOM.Site.busyButton.addClass(ECOM.Site.errorClass);
            setTimeout(function() {
                ECOM.Site.busyButton.removeClass(ECOM.Site.errorClass);
                ECOM.Site.busyButton = null;
                // console.log('doneLoading(done)');
            }, 1200);
        }
    },

    updateCartCounter: function(amount) {
        // JWB: Following code set's or updates the cart counter.
        //      Due time constraints and deadlines this was changed to just
        //      a (in)active cart.
        // if ($('.cart-counter').length) {
        //     var counter = +($('.cart-counter').text());
        //     counter += amount;
        //     $('.cart-counter').text(counter);
        // }
        // else {
        //     $('.icon-cart').append('<span class="cart-counter">'+amount+'</span>');
        // }

        if (PNLNav && PNLNav.hasOwnProperty('Cart')) {
            if ($('.cart-counter').length) {
                var counter = +($('.cart-counter').text());
                counter += amount;
                if (counter) {
                    // More then 0 products -> active cart
                    PNLNav.Cart.showActiveCart();
                } else {
                    // 0 products -> inactive cart
                    PNLNav.Cart.showInActiveCart();
                }
            } else {
                PNLNav.Cart.showActiveCart();
            }
        }

    }


};
$(document).ready(ECOM.Site.init);

