/**
 * Check if Cash has been replaced by jQuery. If it has not, set jQuery
 * as a `window` element.
 */
if (typeof jQuery === 'undefined') {
	window.jQuery = cash = $;
}


(function (mivaJS) {}(window.mivaJS || (window.mivaJS = {})));

/**
 *    Cash/jQuery Extensions
 */
$.extend({
	debounced: function (fn, timeout, invokeAsap, ctx) {
		/**
		 * Custom function to allow us to delay events until after the
		 * trigger has ended.
		 *
		 * Example: $(window).on('resize', $.debounced(function () {...DO SOMETHING...}, 100));
		 */
		if (arguments.length === 3 && typeof invokeAsap !== 'boolean') {
			ctx = invokeAsap;
			invokeAsap = false;
		}
		var timer;

		return function () {
			var args = arguments;

			ctx = ctx || this;
			invokeAsap && !timer && fn.apply(ctx, args);
			clearTimeout(timer);
			timer = setTimeout(function () {
				invokeAsap || fn.apply(ctx, args);
				timer = null;
			}, timeout);
		};
	},
	hook: function (hookName) {
		/**
		 * Custom function to allow us to unify event triggers/binding
		 * using `data-` elements.
		 *
		 * Usage: $.hook('HOOK NAME')...
		 * Example: $.hook('open-menu').on('click', function (e) {e.preventDefault(); ELEMENT.show();});
		 */
		var selector;

		if (!hookName || hookName === '*') {
			// select all data-hooks
			selector = '[data-hook]';
		}
		else {
			// select specific data-hook
			selector = '[data-hook~="' + hookName + '"]';
		}
		return $(selector);
	},
	loadScript: function (url, callback) {
		/**
		 * Loads a JavaScript file asynchronously with a callback, like
		 * jQuery's `$.getScript()` except without jQuery.
		 *
		 * Usage:
		 * $.loadScript(FILE_PATH, function () {
		 * 		DO SOMETHING...
		 * });
		 */
		var head = document.getElementsByTagName('head')[0];
		var scriptCalled = document.createElement('script');

		scriptCalled.async = true;
		scriptCalled.src = url;
		scriptCalled.onload = scriptCalled.onreadystatechange = function () {
			if (!scriptCalled.readyState || /loaded|complete/.test(scriptCalled.readyState)) {
				scriptCalled.onload = scriptCalled.onreadystatechange = null;

				if (head && scriptCalled.parentNode) {
					head.removeChild(scriptCalled)
				}

				scriptCalled = undefined;

				if (callback) {
					callback();
				}
			}
		};
		//head.insertBefore(scriptCalled, head.firstChild);
		head.appendChild(scriptCalled)
	}
});


/**
 *    HTML Class Name
 *    This function will check if JavaScript is enabled, detect touch and hover
 *    capabilities, and modify the class list as needed.
 */
(function () {
	'use strict';

	var html = document.documentElement;

	html.classList.remove('no-js');
	html.classList.add('js');

	/**
	 * Detect if the user is utilizing a touch interface.
	 */
	window.addEventListener('touchstart', function onFirstTouch() {
		html.classList.add('touch');
		html.setAttribute('data-touch', '');
		window.USER_IS_TOUCHING = true;
		sessionStorage.setItem('USER_IS_TOUCHING', true);
		window.USER_CAN_HOVER = false;
		sessionStorage.setItem('USER_CAN_HOVER', false);
		window.removeEventListener('touchstart', onFirstTouch, false);
	}, false);

	/**
	 * Detect if the user can hover over elements.
	 */
	window.addEventListener('mouseover', function onFirstHover() {
		window.USER_CAN_HOVER = true;
		sessionStorage.setItem('USER_CAN_HOVER', true);
		html.classList.remove('touch');
		html.removeAttribute('data-touch');
		window.USER_IS_TOUCHING = false;
		sessionStorage.setItem('USER_IS_TOUCHING', false);
		window.removeEventListener('mouseover', onFirstHover, false);
	}, false);
}());


/**
 * Breakpoints
 * This function will retrieve the breakpoint value set via CSS. You can use
 * this to trigger a function based on the predefined breakpoints rather than
 * a randomly chosen one.
 *
 * Usage:
 * if (breakpoint === 'medium') {
 *     yourFunctionCall();
 * }
 */
// Setup the breakpoint variable
var breakpoint;

// Get the current breakpoint
var getBreakpoint = function () {
	return window.getComputedStyle(document.body, '::before').content.replace(/\"/g, '');
};

// Setup a timer
var timeout;

// Calculate breakpoint on page load
breakpoint = getBreakpoint();

// Listen for resize events
window.addEventListener('resize', function (event) {
	// If there's a timer, cancel it
	if (timeout) {
		window.cancelAnimationFrame(timeout);
	}

	// Setup the new requestAnimationFrame()
	timeout = window.requestAnimationFrame(function () {
		breakpoint = getBreakpoint();
	});

}, false);


/**
 * CSS Feature Detect - Used in place of Modernizr
 * Returns true or false depending on your browser. Let's hope it's true.
 * NOTE: This may be removed in future versions of the framework as
 * browser compatibility and support changes.
 *
 * Usage: detectCSSFeature('transition');
 */
function detectCSSFeature(featureName) {
	'use strict';

	var feature = false,
		domPrefixes = 'Moz ms Webkit'.split(' '),
		elm = document.createElement('div'),
		featureNameCapital = null;

	featureName = featureName.toLowerCase();
	if (elm.style[featureName] !== undefined) {
		feature = true;
	}
	if (feature === false) {
		featureNameCapital = featureName.charAt(0).toUpperCase() + featureName.substr(1);
		for (var i = 0; i < domPrefixes.length; i++) {
			if (elm.style[domPrefixes[i] + featureNameCapital] !== undefined) {
				feature = true;
				break;
			}
		}
	}
	return feature;
}


/**
 * A complete cookies reader/writer framework with full unicode support.
 *
 * Revision #1 - September 4, 2014
 * https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
 * https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework
 * https://developer.mozilla.org/User:fusionchess
 * https://github.com/madmurphy/cookies.js
 *
 * This framework is released under the GNU Public License, version 3 or later.
 * http://www.gnu.org/licenses/gpl-3.0-standalone.html
 *
 * Syntax:
 * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]]);
 * docCookies.getItem(name);
 * docCookies.removeItem(name[, path[, domain]]);
 * docCookies.hasItem(name);
 * docCookies.keys();
 */
var docCookies = {
	getItem: function (sKey) {
		if (!sKey) {
			return null;
		}
		return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
	},
	setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
		if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
			return false;
		}
		var sExpires = "";
		if (vEnd) {
			switch (vEnd.constructor) {
				case Number:
					sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
					break;
				case String:
					sExpires = "; expires=" + vEnd;
					break;
				case Date:
					sExpires = "; expires=" + vEnd.toUTCString();
					break;
			}
		}
		document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
		return true;
	},
	removeItem: function (sKey, sPath, sDomain) {
		if (!this.hasItem(sKey)) {
			return false;
		}
		document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
		return true;
	},
	hasItem: function (sKey) {
		if (!sKey) {
			return false;
		}
		return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
	},
	keys: function () {
		var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
		for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) {
			aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
		}
		return aKeys;
	}
};


var elementsUI = {
	site: function () {
		/**
		 * Load the `polyfills.js` file and initialise functions.
		 * NOTE: This may be removed in future versions of the framework as
		 * browser compatibility and support changes.
		 */
		if (!window.CSS || !window.CSS.supports('(--foo: red)')) {
			$.loadScript(theme_path + 'core/js/polyfills.js', function () {
				sessionStorage.setItem('outdated', true);
				cssCapabilities.init();
			});
		}


		/**
		 * Load the `mini-modal.js` file and initialize functions if modal elements exist.
		 * This is the default set of modal/light box functionality supplied with the framework.
		 */
		var targets = document.querySelectorAll('[data-mini-modal]');

		if (targets.length) {
			$.loadScript(theme_path + 'core/js/mini-modal.js', function () {
				for (var i = 0; i < targets.length; i += 1) {
					var modal = minimodal(targets[i], {
						// If you would like a global onLoaded callback, add your function here
						//onLoaded: function () {},
						// If you would like a global onClosed callback, add your function here
						//onClosed: function () {},
						// If you are using, and have, a Google Maps API Key, enter it here.
						googleMapsAPIKey: ''
					});

					if (!targets[i].id) {
						targets[i].id = 'miniModal_' + i;
					}
					modal.init();
				}
			});
		}


		/**
		 * Although NodeList is not an Array, it is possible to iterate on it using forEach().
		 * It can also be converted to an Array using Array.from().
		 * However some older browsers have not yet implemented NodeList.forEach() nor Array.from().
		 * But those limitations can be circumvented by using Array.prototype.forEach().
		 * This polyfill adds compatibility to browsers which do not support NodeList.forEach(). [IE11]
		 */
		if (window.NodeList && !NodeList.prototype.forEach) {
			NodeList.prototype.forEach = function (callback, thisArg) {
				thisArg = thisArg || window;
				for (var i = 0; i < this.length; i++) {
					callback.call(thisArg, this[i], i, this);
				}
			};
		}

	},

	pages: {
		/* ----------
		 Common :
		 ---------- */
		common: function () {
			/**
			 * Add `ID` and `CLASS` attributes to `INPUT` and `SELECT` elements
			 * dynamically created by Miva.
			 */
			var mvtInputWraps = document.querySelectorAll('[data-hook~="mvt-input"]');
			var mvtSelectWraps = document.querySelectorAll('[data-hook~="mvt-select"]');

			mvtInputWraps.forEach(function (element) {
				var classes = element.getAttribute('data-classlist');
				var id = element.getAttribute('data-id');
				var mvtInputs = element.querySelectorAll('input');

				mvtInputs.forEach(function (mvtInput) {
					if (mvtInput.getAttribute('type') !== 'hidden') {
						mvtInput.setAttribute('class', classes);
						mvtInput.setAttribute('id', id);
					}
				});
			});

			mvtSelectWraps.forEach(function (element) {
				var classes = element.getAttribute('data-classlist');
				var id = element.getAttribute('data-id');
				var mvtSelects = element.querySelectorAll('select');

				mvtSelects.forEach(function (mvtSelect) {
					mvtSelect.setAttribute('class', classes);
					mvtSelect.setAttribute('id', id);
				});
			});

		},

		jsSFNT: function () {
		},

		jsCTGY: function () {
		},

		jsPROD: function () {
			/**
			 * This removes the default Miva `closeup_backing` container.
			 */
			var closeupBacking = document.querySelector('div.closeup_backing');

			window.addEventListener('load', function () {
				if (closeupBacking) {
					closeupBacking.parentNode.removeChild(document.querySelector('div.closeup_backing'));
				}
			});

		},

		jsPATR: function () {
		},

		jsBASK: function () {
			/**
			 * Estimate Shipping
			 */
			mivaJS.estimateShipping = function (element) {
				'use strict';

				var currentModal = document.querySelector('[data-hook="' + element + '"]');
				var formElement = currentModal.querySelector('[data-hook="shipping-estimate-form"]');
				var formButton = formElement.querySelector('[data-hook="calculate-shipping-estimate"]');

				function createCalculation () {
					var processor = document.createElement('iframe');

					processor.id = 'calculate-shipping';
					processor.name = 'calculate-shipping';
					processor.style.display = 'none';
					formElement.before(processor);
					processor.addEventListener('load', function () {
						displayResults(processor);
					});
					formElement.submit();
				}

				function displayResults (source) {
					var content = source.contentWindow.document.body.innerHTML;

					formElement.querySelector('[data-hook="shipping-estimate-fields"]').classList.add('u-hidden');
					formElement.querySelector('[data-hook="shipping-estimate-results"]').innerHTML = content;
					formElement.setAttribute('data-status', 'idle');

					formElement.querySelector('[data-hook="shipping-estimate-recalculate"]').addEventListener('click', function () {
						formElement.querySelector('[data-hook="shipping-estimate-results"]').innerHTML = '';
						formElement.querySelector('[data-hook="shipping-estimate-fields"]').classList.remove('u-hidden');
					});

					setTimeout(
						function () {
							source.parentNode.removeChild(source);
						}, 1
					);
				}

				formButton.addEventListener('click', function (event) {
					event.preventDefault();
					createCalculation();
				}, false);
			};

		},

		jsORDL: function () {
		},

		jsOCST: function () {
			/**
			 * Use AJAX for coupon form to prevent page refresh.
			 * https://github.com/mivaecommerce/readytheme-shadows/issues/54
			 */
			(function (document) {
				'use strict';

				document.addEventListener('click', function (evt) {
					var submitButton = document.querySelector('[data-hook="basket__coupon-form-submit"]');
					var submitButtonText = ((submitButton.nodeName.toLowerCase() === 'input') ? submitButton.value : submitButton.textContent);
					var ajaxForm = document.querySelector('[data-hook="basket__coupon-form"]');

					if (evt.target.matches('[data-hook="basket__coupon-form-submit"]')) {
						evt.preventDefault();
						evt.stopImmediatePropagation();

						var data = new FormData(ajaxForm);
						var request = new XMLHttpRequest(); // Set up our HTTP request

						ajaxForm.setAttribute('data-status', 'idle');

						if (ajaxForm.getAttribute('data-status') !== 'submitting') {
							ajaxForm.setAttribute('data-status', 'submitting');
							submitButton.setAttribute('disabled', 'disabled');

							if (submitButton.nodeName.toLowerCase() === 'input') {
								submitButton.value = 'Processing...';
							}
							else {
								submitButton.textContent = 'Processing...';
							}

							document.querySelector('#messages').parentNode.removeChild(document.querySelector('#messages'));

							// Setup our listener to process completed requests
							request.onreadystatechange = function () {
								// Only run if the request is complete
								if (request.readyState !== 4) {
									return;
								}

								// Process our return data
								if (request.status === 200) {
									// What do when the request is successful
									var response = request.response;
									var basketSummary = response.querySelector('#checkout_basket_summary');
									var responseMessage = response.querySelector('#messages');

									response.querySelector('[data-hook="basket__coupon-form"]').parentElement.prepend(responseMessage);
									document.querySelector('#checkout_basket_summary').innerHTML = basketSummary.innerHTML;


									// Reset button text and form status
									submitButton.removeAttribute('disabled');

									if (submitButton.nodeName.toLowerCase() === 'input') {
										submitButton.value = submitButtonText;
									}
									else {
										submitButton.textContent = submitButtonText;
									}

									ajaxForm.setAttribute('data-status', 'idle');
								}
								else {
									// What do when the request fails
									console.warn('The request failed!');
									ajaxForm.setAttribute('data-status', 'idle');
								}
							};

							/**
							 * Create and send a request
							 * The first argument is the post type (GET, POST, PUT, DELETE, etc.)
							 * The second argument is the endpoint URL
							 */
							request.open(ajaxForm.method, ajaxForm.action, true);
							request.responseType = 'document';
							request.send(data);
						}
					}
				}, false);

			}(document));

		},

		jsOSEL: function () {
		},

		jsOPAY: function () {
			/**
			 * Credit Card Detection
			 */
			$.loadScript(theme_path + 'core/js/payment-method.js', function () {
				$.hook('detect-card').on('input paste', function () {
					var cardInput = this;

					if (isNaN(this.value)) {
						this.classList.add('has-error');
					}
					paymentMethod(this, function (paymentDetected) {
						if (paymentDetected) {
							cardInput.classList.remove('has-error');
							$.hook('payment-method-display').text(paymentDetected.display);
							$.hook('payment-method').val(supportedPaymentMethods.findPaymentMethod(paymentDetected.name));
						}
					});
				});
			});

			/**
			 * Added functionality to help style the default Miva output payment
			 * fields.
			 */
			$.hook('mvt-input').each(function () {
				var dataHook = $(this).attr('data-datahook');

				if (dataHook) {
					$(this).find('input').attr('data-hook', dataHook);
				}

				Array.prototype.forEach.call($(this), function (el) {
					el.innerHTML = el.innerHTML.replace(/&nbsp;/gi, '');
				});
			});

			$.hook('detect-card').attr('type', 'tel');

			$('[data-id="cvv"]').find('input').attr('type', 'tel');

			/**$.hook('mvt-select').find('select').each(function () {
				var wrapDiv = document.createElement('div');
				var select = this;

				select.attr('data-no-custom', '');
				wrapDiv.classList.add('c-form-select');
				select.parentNode.insertBefore(wrapDiv, select);
				wrapDiv.appendChild(select);
			});*/

		},

		jsINVC: function () {
			/**
			 *  Launch Printer Dialog
			 */
			$.hook('print-invoice').on('click', function (element) {
				element.preventDefault();
				window.print();
			});
		},

		jsORDS: function () {
			/**
			 *  Launch Printer Dialog
			 */
			$.hook('print-invoice').on('click', function (element) {
				element.preventDefault();
				window.print();
			});
		},

		jsLOGN: function () {
		},

		jsACAD: function () {
		},

		jsACED: function () {
		},

		jsCABK: function () {
		},

		jsCADA: function () {
		},

		jsCADE: function () {
		},

		jsAFCL: function () {
		},

		jsAFAD: function () {
		},

		jsAFED: function () {
		},

		jsORHL: function () {
		},

		jsCTUS: function () {
		}
	},

	theme: function (pageID) {
		/**
		 * Call in additional functions as developed for theme.
		 */
		$.loadScript(theme_path + 'ui/js/theme.js', function () {
			window.addEventListener('load',
				$.debounced(function () {
					themeFunctionality.init();

					if (themeFunctionality[pageID]) {
						themeFunctionality[pageID]();
					}
				}, 300),
				false
			);
		});
	}
};


(function () {
	String.prototype.toCamelCase = function (cap1st) {
		'use strict';

		return ((cap1st ? '-' : '') + this).replace(/-+([^-])/g, function (a, b) {
			return b.toUpperCase();
		});
	};
	var pageID = document.body.id.toCamelCase();

	/**
	 * Initialize Global Site Functions
	 */
	elementsUI.site();

	/**
	 * Initialize Common Page Functions
	 */
	elementsUI.pages.common();

	/**
	 * Initialize Page Specific Functions
	 */
	if (elementsUI.pages[pageID]) {
		elementsUI.pages[pageID]();
	}

	/**
	 * Initialize Theme Specific Function
	 */
	elementsUI.theme(pageID);
}());
/**
 * Use this file to all in scripts and functions you would like to have globally or on specific
 * pages. You will use this to extend your theme instead of adding code to the core framework files.
 */

var themeFunctionality = {
	init: function () {
		/**
		 * Load and initialize the Fasten Header extension
		 */
		const fastenHeaderActive = document.querySelector('[data-hook="fasten-header"]');

		if (typeof fastenHeaderActive !== 'undefined') {
			$.loadScript(theme_path + 'extensions/fasten-header/fasten-header.js');
		}


		/**
		 * Load and initialize the Show Related extension
		 */
		$.loadScript(theme_path + 'extensions/show-related/show-dont-tell.js');


		/**
		 * Load and initialize the Mini-Basket extension
		 */
		$.loadScript(theme_path + 'extensions/mini-basket/mini-basket.js', function () {
			miniBasket.init();
		});

			/**
			 * If clicking outside of the mini-basket, close the mini-basket.
			 */
			(function () {
				let miniBasket = document.querySelector('[data-hook="mini-basket"]');

				/**
				 * Polyfill for browsers that do not support Element.matches() [IE 11]
				 */
				if (!Element.prototype.matches) {
					Element.prototype.matches = Element.prototype.msMatchesSelector;
				}

				/**
				 * Polyfill for browsers that do not support Element.closest() [IE 11]
				 */
				if (!Element.prototype.closest) {
					Element.prototype.closest = function (s) {
						let el = this;

						if (!document.documentElement.contains(el)) {
							return null;
						}
						do {
							if (el.matches(s)) {
								return el;
							}
							el = el.parentElement || el.parentNode;
						}
						while (el !== null && el.nodeType === 1);
						return null;
					};
				}

				document.addEventListener('click', function (event) {
					if (event.target.closest('[data-hook="mini-basket"]')) {
						return;
					}

					if (event.target.closest('[data-hook~="open-mini-basket"]') && miniBasket.classList.contains('x-mini-basket--open')) {
						event.preventDefault();
						event.stopImmediatePropagation();
						document.documentElement.classList.remove('u-overflow-hidden');
						document.documentElement.classList.remove('x-mini-basket-is-active');
						miniBasket.classList.remove('x-mini-basket--open');
					}

					if (miniBasket.classList.contains('x-mini-basket--open')) {
						document.documentElement.classList.toggle('u-overflow-hidden');
						document.documentElement.classList.toggle('x-mini-basket-is-active');
						miniBasket.classList.toggle('x-mini-basket--open');
					}
				});
			})();


		/**
		 * Load and initialize the Omega Navigation extension
		 */
		$.loadScript(theme_path + 'extensions/navigation/omega/omega-navigation.js');


		/**
		 * Load and initialize the Collapsing Breadcrumbs extension
		 */
		$.loadScript(theme_path + 'extensions/breadcrumbs/collapsing/collapsing-breadcrumbs.js');


		/**
		 * This is a a minimal polyfill for <template> use in IE 9-11.
		 * http://ironlasso.com/template-tag-polyfill-for-internet-explorer/
		 */
		Element.prototype.getTemplateContent = function () {
			'use strict';

			return function (element) {

				if (element.content) {
					return element.content;
				}

				var template = element,
					templateContent,
					documentContent;

				templateContent = template.childNodes;
				documentContent = document.createDocumentFragment();

				while (templateContent[0]) {
					documentContent.appendChild(templateContent[0]);
				}

				template.content = documentContent;
				return documentContent;

			}(this);
		};


		/**
		 * This is a basic "lazy-load" function for complete DOM sections and images
		 * base of `data-` attributes.
		 */
		function observeDeferred() {
			'use strict';

			const deferredDOMItems = document.querySelectorAll('[data-defer]');
			const deferredImages = document.querySelectorAll('[data-src]');
			const config = {
				root: null, // avoiding 'root' or setting it to 'null' sets it to default value: viewport
				rootMargin: '0px',
				threshold: 0.25
			};

			if ('IntersectionObserver' in window) {
				let deferredObjectsObserver = new IntersectionObserver(function (DOMItems, self) {
					DOMItems.forEach(function (DOMItem) {
						if (DOMItem.isIntersecting) {
							loadDOMItems(DOMItem.target);
							// Stop watching and load the deferred object
							self.unobserve(DOMItem.target);
						}
					});
				}, config);
				let deferredImagesObserver = new IntersectionObserver(function (images, self) {
					images.forEach(function (image) {
						if (image.isIntersecting) {
							loadImages(image.target);
							// Stop watching and load the deferred object
							self.unobserve(image.target);
						}
					});
				}, config);

				deferredDOMItems.forEach(function (deferredDOMItem) {
					deferredObjectsObserver.observe(deferredDOMItem);
				});
				deferredImages.forEach(function (deferredImage) {
					deferredImagesObserver.observe(deferredImage);
				});
			}
			else {
				Array.from(deferredDOMItems).forEach(function (deferredDOMItem) {
					return loadDOMItems(deferredDOMItem);
				});
				Array.from(deferredImages).forEach(function (deferredImage) {
					return loadImages(deferredImage);
				});
			}

			function loadDOMItems(deferredObject) {
				deferredObject.classList.add('t-defer-object--loaded');
			}

			function loadImages(deferredImage) {
				const src = deferredImage.getAttribute('data-src');

				if (!src) {
					return;
				}
				deferredImage.classList.add('t-lazy-load-image');
				deferredImage.src = src;
			}

		}

		var observeDeferredTimeout;

		window.addEventListener('resize', function () {
			if (!observeDeferredTimeout) {
				observeDeferredTimeout = setTimeout(function () {
					observeDeferredTimeout = null;

					observeDeferred();
				}, 100);
			}
		}, false);
		observeDeferred();


	},
	jsSFNT: function() {
		/**
		 * Create promo image text overlays for every `storefront-promo__item`
		 */
		(function () {
			'use strict';

			let promoItems = document.querySelectorAll('[data-hook="storefront-promo__item"]');

			for (let id = 0; id < promoItems.length; id++) {
				let promoCaption = document.createElement('figcaption');
				let promoImage = promoItems[id].querySelector('img');
				let promoImageAlt = promoImage.getAttribute('alt');
				let promoLink = promoItems[id].querySelector('a');

				promoCaption.classList.add('t-storefront-promo__caption');
				promoCaption.textContent = promoImageAlt;

				if (promoLink) {
					promoLink.append(promoCaption);
				}
				else {
					promoItems[id].append(promoCaption);
				}
			}
		})();


		/**
		 * Create spotlight image text overlays for every `spotlight__figure`
		 */
		(function () {
			'use strict';

			let spotlightItems = document.querySelectorAll('[data-hook="spotlight__figure"]');

			for (let id = 0; id < spotlightItems.length; id++) {
				let spotlightCaption = document.createElement('figcaption');
				let spotlightImage = spotlightItems[id].querySelector('img');
				let spotlightImageAlt = spotlightImage.getAttribute('alt');
				let spotlightLink = spotlightItems[id].querySelector('a');

				spotlightCaption.classList.add('t-spotlight__figure-text');
				spotlightCaption.textContent = spotlightImageAlt;

				if (spotlightLink) {
					spotlightLink.append(spotlightCaption);
				}
				else {
					spotlightItems[id].append(spotlightCaption);
				}
			}
		})();


		/**
		 * Load and initialize the Slick plugin for Featured Products
		 */
/*
		$.loadScript(theme_path + 'plugins/slick/slick.min.js', function () {
			$.hook('featured-products').slick({
				draggable: false,
				infinite: false,
				slidesToScroll: 5,
				slidesToShow: 5,
				responsive: [
					{
						breakpoint: 1200,
						settings: {
							slidesToScroll: 4,
							slidesToShow: 4
						}
					},
					{
						breakpoint: 960,
						settings: {
							slidesToScroll: 3,
							slidesToShow: 3
						}
					},
					{
						breakpoint: 748,
						settings: {
							slidesToScroll: 2,
							slidesToShow: 2
						}
					},
					{
						breakpoint: 360,
						settings: {
							slidesToScroll: 1,
							slidesToShow: 1
						}
					}
				]
			});
		});
*/
	},
	jsCTGY: function() {
		var subcategoryNavigation = document.querySelector('[data-hook="subcategory-navigation"]');
		var subcategoryNavigationBlock = $.hook('subcategory-navigation-block');
		var subcategoryNavigationSlider = $.hook('subcategory-navigation-slider');

		function loadSubcategoryNavigation() {
			subcategoryNavigationBlock.css('visibility', 'hidden');
			if (/**document.body.clientWidth >= 960 &&*/ subcategoryNavigationSlider.html() === '') {
				subcategoryNavigationSlider.append(document.importNode(subcategoryNavigation.getTemplateContent(), true));

				$.loadScript(theme_path + 'plugins/slick/slick.min.js', function () {
					subcategoryNavigationSlider.slick({
						draggable: false,
						infinite: false,
						slidesToScroll: 8,
						slidesToShow: 8,
						responsive: [
							{
								breakpoint: 1200,
								settings: {
									slidesToScroll: 6,
									slidesToShow: 6
								}
							},
							{
								breakpoint: 960,
								settings: {
									slidesToScroll: 4,
									slidesToShow: 4
								}
							},
							{
								breakpoint: 959,
								//settings: 'unslick'
								settings: {
									slidesToScroll: 2,
									slidesToShow: 2
								}
							}
						]
					});
				});

				subcategoryNavigationSlider.on('destroy', function () {
					subcategoryNavigationSlider.empty();
				});

				subcategoryNavigationBlock.css('visibility', 'visible');
			}
			subcategoryNavigationBlock.css('visibility', 'visible');
		}


		/**
		 * Load and initialize the Refinery extension
		 */
		var facetsContainer = $.hook('add-refinery');
		var facetTemplate = document.querySelector('[data-hook="horizontal-refinery"]');

		if (facetTemplate !== null) {
			var facetTemplateContent = facetTemplate.getTemplateContent();
		}

		var hasRefinery = $.hook('refinery');
		var hasRefineryAnnex = $.hook('refinery-annex');

		function loadRefinery() {
			facetsContainer.css('visibility', 'hidden');
			if (document.body.clientWidth >= 959 && facetsContainer.html() === '') {
				facetsContainer.append(document.importNode(facetTemplateContent, true));
				facetsContainer.css('visibility', 'visible');
			}
			else if (document.body.clientWidth < 959) {
				facetsContainer.empty();
			}
			$.loadScript(theme_path + 'extensions/facets/refinery/refinery.js');

		}

		var loadSubcategoryTimeout;
		var loadRefineryTimeout;

		window.addEventListener('resize', function () {
			if (!loadSubcategoryTimeout) {
				loadSubcategoryTimeout = setTimeout(function () {
					loadSubcategoryTimeout = null;

					subcategoryNavigationBlock.css('visibility', 'hidden');
					loadSubcategoryNavigation();
				}, 100);
			}
		}, false);
		window.addEventListener('resize', function () {
			if (!loadRefineryTimeout) {
				loadRefineryTimeout = setTimeout(function () {
					loadRefineryTimeout = null;

					if (hasRefinery) {
						facetsContainer.css('visibility', 'hidden');
						loadRefinery();
					}
				}, 100);
			}
		}, false);
		loadSubcategoryNavigation();

		if (hasRefinery || hasRefineryAnnex) {
			loadRefinery();
		}

		/**
		 * Accordion Extension
		 */
		(function () {
			'use strict';

			let accordionToggles = document.querySelectorAll('[data-hook="accordion-toggle"]');

			for (let id = 0; id < accordionToggles.length; id++) {
				accordionToggles[id].addEventListener('click', function (event) {
					let parent = this.parentElement.closest('li');

					parent.classList.toggle('is-active');
				});
			}
		})();


		/**
		 * Sub-Subcategory/Product Slider
		 */
		var subcategoryProductList = $.hook('subcategory-product-list');

		if (subcategoryProductList.length > 0) {
			$.loadScript(theme_path + 'plugins/slick/slick.min.js', function () {
				subcategoryProductList.each(function () {
					var header = $(this).prev($.hook('subcategory-product-list__heading'));

					$(this).slick({
						appendArrows: header,
						draggable: false,
						infinite: false,
						slidesToScroll: 4,
						slidesToShow: 4,
						responsive: [
							{
								breakpoint: 768,
								settings: {
									appendArrows: header,
									slidesToScroll: 2,
									slidesToShow: 2
								}
							},
							{
								breakpoint: 640,
								settings: {
									appendArrows: $(this),
									slidesToScroll: 2,
									slidesToShow: 2
								}
							}
						]
					});
				});
			});

		}


	},
	jsCTLG: function() {
		themeFunctionality.jsCTGY();
	},
	jsPROD: function() {
		/**
		 * This function set will update an attributes label when choosing an option from a radio or select element.
		 */
		(function () {
			'use strict';

			let updateSelection = document.querySelectorAll('[data-hook="update-selection"]');

			for (let id = 0; id < updateSelection.length; id++) {
				let updateSelectionLabel = updateSelection[id].querySelector('[data-hook="update-selection-label"]');
				let updateRadio = updateSelection[id].querySelectorAll('input[type="radio"]');
				let updateSelect = updateSelection[id].querySelectorAll('select');

				if (updateRadio.length > 0) {
					for (let radioID = 0; radioID < updateRadio.length; radioID++) {
						if (updateRadio[radioID].checked) {
							updateSelectionLabel.textContent = updateRadio[radioID].value;
						}

						updateRadio[radioID].addEventListener('change', function (event) {
							updateSelectionLabel.textContent = this.value;
						});
					}
				}
				if (updateSelect.length > 0) {
					for (let selectID = 0; selectID < updateSelect.length; selectID++) {
						updateSelectionLabel.textContent = updateSelect[selectID].options[updateSelect[selectID].selectedIndex].text;

						updateSelect[selectID].addEventListener('change', function (event) {
							updateSelectionLabel.textContent = this.options[this.selectedIndex].text;
						});
					}
				}

			}
		})();

		/**
		 * This function toggles the radio when selecting a subscription term.
		 */
		let canSubscribe = document.querySelector('[data-hook="select-subscription"]');

		if (canSubscribe) {
			canSubscribe.addEventListener('click', function (event) {
				if (event.target !== event.currentTarget) {
					event.currentTarget.click();
				}
			});
		}

		/**
		 * Product Imagery
		 * This set of functions control the creation and operation of the product image gallery carousels.
		 */
		let productThumbnails = document.querySelector('[data-hook="product-thumbnails"]');
		let debouncedThumbnailSlider = $.debounced(function () {
			if ($(productThumbnails).hasClass('slick-initialized')) {
				$(productThumbnails).css('opacity', 0).removeClass('slick-slider slick-vertical slick-initialized');
			}

			$(productThumbnails).on('init', function (event, slick) {
				$(event.target).css('opacity', 0);
				setTimeout(function () {
					$(event.target).css('opacity', 1);
				}, 50);
			});

			$(productThumbnails).not('.slick-initialized').slick({
				draggable: false,
				infinite: false,
				slidesToScroll: 5,
				slidesToShow: 5,
				vertical: true,
				verticalSwiping: true,
				responsive: [
					{
						breakpoint: 768,
						settings: {
							slidesToScroll: 4,
							slidesToShow: 4,
							vertical: false,
							verticalSwiping: false
						}
					}
				]
			});
		}, 250);


		/**
		 * Update Display When Attribute Machine Fires
		 */
		MivaEvents.SubscribeToEvent('variant_changed', function () {
			$(productThumbnails).not('.slick-initialized').slick({
				draggable: false,
				infinite: false,
				slidesToScroll: 5,
				slidesToShow: 5,
				vertical: true,
				verticalSwiping: true,
				responsive: [
					{
						breakpoint: 768,
						settings: {
							slidesToScroll: 4,
							slidesToShow: 4,
							vertical: false,
							verticalSwiping: false
						}
					}
				]
			});
		});

		if (productThumbnails.innerHTML !== '') {
			$.loadScript(theme_path + 'plugins/slick/slick.min.js', debouncedThumbnailSlider);
			$(document).on('ImageMachine_Generate_Thumbnail', debouncedThumbnailSlider);
		}

		let productImage = $.hook('product-image');

		if (productImage.length > 0) {
			$.loadScript(theme_path + 'plugins/slick/slick.min.js', function () {
				$.hook('product-image').on('click', function (event) {
					let goTo = this.getAttribute('data-index');
					let activePhotoGallery = $.hook('active-main_image').find($.hook('photo-gallery'));

					var slick = activePhotoGallery.slick({
						draggable: false,
						infinite: false,
						slidesToScroll: 1,
						slidesToShow: 1,
					});

					// make arrow keys work initially
					$(slick).find('.slick-next').focus();

					// go to current thumbnail image
					activePhotoGallery.slick('slickGoTo', goTo, true);
				});
			});
		}


		/**
		 * Load and initialize the AJAX Add to Cart extension
		 */
		$.loadScript(theme_path + 'extensions/product-layout/ajax-add-to-cart.js');


		/**
		 * Load and initialize the Slick plugin for Related Products
		 */
		let relatedProductList = $.hook('related-products');

		if (relatedProductList.length > 0) {
			$.loadScript(theme_path + 'plugins/slick/slick.min.js', function () {
				relatedProductList.each(function () {
					var header = $(this).prev($.hook('related-product-list__heading'));

					$(this).slick({
						appendArrows: header,
						draggable: false,
						infinite: false,
						slidesToScroll: 5,
						slidesToShow: 5,
						responsive: [
							{
								breakpoint: 1200,
								settings: {
									appendArrows: header,
									slidesToScroll: 4,
									slidesToShow: 4
								}
							},
							{
								breakpoint: 960,
								settings: {
									appendArrows: header,
									slidesToScroll: 3,
									slidesToShow: 3
								}
							},
							{
								breakpoint: 768,
								settings: {
									appendArrows: header,
									slidesToScroll: 2,
									slidesToShow: 2
								}
							},
							{
								breakpoint: 640,
								settings: {
									appendArrows: $(this),
									slidesToScroll: 1,
									slidesToShow: 1
								}
							}
						]
					});
				});
			});
		}


		/**
		 * This is the Show/Hide functionality for the Show More links in the
		 * product description section.
		 */
		(function () {
			'use strict';

			function vw(v) {
				let w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
				return (v * w) / 100;
			}

			let showMoreSections = document.querySelectorAll('[data-hook="show-more"]');

			function peekaboo (reset) {
				if (showMoreSections.length > 0) {
					if (reset) {
						document.querySelectorAll('[data-hook="show-more-toggle"]').forEach(function (toggle) {
							toggle.parentNode.removeChild(toggle);
						});
						return;
					}

					showMoreSections.forEach(function (showMore) {
						if (showMore.clientHeight > vw(30)) {
							let showMoreToggle = document.createElement('button');
							let showContent = '<span class="t-show-more__toggle-text">See More <span class="u-icon-chevron-down u-font-small"></span></span>';
							let lessContent = '<span class="t-show-more__toggle-text">See Less <span class="u-icon-chevron-up u-font-small"></span></span>';

							showMoreToggle.innerHTML = showContent;
							showMoreToggle.classList.add('t-show-more__toggle');
							showMoreToggle.setAttribute('data-hook', 'show-more-toggle');
							showMore.classList.add('t-show-more');
							showMore.appendChild(showMoreToggle);

							showMoreToggle.addEventListener('click', function (clickEvent) {
								clickEvent.preventDefault();
								showMore.classList.toggle('t-show-more--active');
								if (showMoreToggle.innerHTML === showContent) {
									showMoreToggle.innerHTML = lessContent;
								}
								else {
									showMoreToggle.innerHTML = showContent;
								}
							});
						}

					});
				}
			}
			peekaboo();

			let peekabooTimeout;

			window.addEventListener('resize', function () {
				peekaboo(true);
				if (peekabooTimeout) {
					window.cancelAnimationFrame(peekabooTimeout);
				}

				peekabooTimeout = window.requestAnimationFrame(function () {
					peekaboo();
				});
			}, false);

		}());

	},
	jsPATR: function() {
		/**
		 * This function set will update an attributes label when choosing an option from a radio or select element.
		 */
		(function () {
			'use strict';

			let updateSelection = document.querySelectorAll('[data-hook="update-selection"]');

			for (let id = 0; id < updateSelection.length; id++) {
				let updateSelectionLabel = updateSelection[id].querySelector('[data-hook="update-selection-label"]');
				let updateRadio = updateSelection[id].querySelectorAll('input[type="radio"]');
				let updateSelect = updateSelection[id].querySelectorAll('select');

				if (updateRadio.length > 0) {
					for (let radioID = 0; radioID < updateRadio.length; radioID++) {
						if (updateRadio[radioID].checked) {
							updateSelectionLabel.textContent = updateRadio[radioID].value;
						}

						updateRadio[radioID].addEventListener('change', function (event) {
							updateSelectionLabel.textContent = this.value;
						});
					}
				}
				if (updateSelect.length > 0) {
					for (let selectID = 0; selectID < updateSelect.length; selectID++) {
						updateSelectionLabel.textContent = updateSelect[selectID].options[updateSelect[selectID].selectedIndex].text;

						updateSelect[selectID].addEventListener('change', function (event) {
							updateSelectionLabel.textContent = this.options[this.selectedIndex].text;
						});
					}
				}

			}
		})();

		let canSubscribe = document.querySelector('[data-hook="select-subscription"]');

		if (canSubscribe) {
			canSubscribe.addEventListener('click', function (event) {
				if (event.target !== event.currentTarget) {
					event.currentTarget.click();
				}
			});
		}
	},
	jsPLST: function() {
		themeFunctionality.jsCTGY();
	},
	jsSRCH: function() {
		themeFunctionality.jsCTGY();
	},
	jsBASK: function() {
		/**
		 * Load and initialize the Quantify extension
		 */
		$.loadScript(theme_path + 'extensions/quantify/quantify.js');

		/**
		 * Enable the shipping estimate functionality.
		 */
		mivaJS.estimateShipping('basket');
	},
	jsORDL: function() {
	},
	jsOCST: function() {
	},
	jsOSEL: function() {
	},
	jsOPAY: function() {
	},
	jsINVC: function() {
	},
	jsACLN: function() {
		/**
		 * This set of functions makes for a better overflow scrolling navigation section.
		 * @type {Element}
		 */
		const $navList = document.querySelector('[data-hook="account-navigation__list"]');
		const $shadowStart = document.querySelector('[data-hook="account-navigation__shadow--start"]');
		const $shadowEnd = document.querySelector('[data-hook="account-navigation__shadow--end"]');

		function handleShadowVisibility() {
			const maxScrollStartReached = $navList.scrollLeft <= 0;
			const maxScrollEndReached = $navList.scrollLeft >= $navList.scrollWidth - $navList.offsetWidth;

			toggleShadow($shadowStart, maxScrollStartReached);
			toggleShadow($shadowEnd, maxScrollEndReached);
		}

		function toggleShadow($el, maxScrollReached) {
			const shadowIsVisible = $el.classList.contains('is-visible');
			const showShadow = !maxScrollReached && !shadowIsVisible;
			const hideShadow = maxScrollReached && shadowIsVisible;

			if (showShadow) {
				window.requestAnimationFrame(function () {
					$el.classList.add('is-visible');
				});
			}
			else if (hideShadow) {
				window.requestAnimationFrame(function () {
					$el.classList.remove('is-visible');
				});
			}
		}

		if ($navList !== null) {
			$navList.addEventListener('scroll', function (scrollEvent) {
				handleShadowVisibility(scrollEvent);
			});

			handleShadowVisibility();
		}

	},
	jsABAL: function() {
		themeFunctionality.jsACLN();
	},
	jsACRT: function() {
		themeFunctionality.jsACLN();
	},
	jsCABK: function() {
		themeFunctionality.jsACLN();
	},
	jsCADA: function() {
		themeFunctionality.jsACLN();
	},
	jsCADE: function() {
		themeFunctionality.jsACLN();
	},
	jsCEML: function() {
		themeFunctionality.jsACLN();
	},
	jsCPCA: function() {
		themeFunctionality.jsACLN();
	},
	jsCPCD: function() {
		themeFunctionality.jsACLN();
	},
	jsCPCE: function() {
		themeFunctionality.jsACLN();
	},
	jsCPRO: function() {
		themeFunctionality.jsACLN();
	},
	jsCPWD: function() {
		themeFunctionality.jsACLN();
	},
	jsCSBE: function() {
		themeFunctionality.jsACLN();
	},
	jsCSTR: function() {
		themeFunctionality.jsACLN();
	},
	jsCSUB: function() {
		themeFunctionality.jsACLN();
	},
	jsORDH: function() {
		themeFunctionality.jsACLN();
	},
	jsORDS: function() {
		themeFunctionality.jsACLN();
	},
	jsRGFT: function() {
		themeFunctionality.jsACLN();
	},
	jsWISH: function() {
		themeFunctionality.jsACLN();
	},
	jsWLAD: function() {
		themeFunctionality.jsACLN();
	},
	jsWLED: function() {
		themeFunctionality.jsACLN();
	},
	jsWLST: function() {
		themeFunctionality.jsACLN();
	},
	jsWPCK: function() {
		themeFunctionality.jsACLN();
	}
};
