diff --git a/.gitignore b/.gitignore index 4acd5ee..375ffad 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules/ dist/ .magento/ +.env # Compiled Java class files *.class diff --git a/Block/CategoryInfoBlock.php b/Block/CategoryInfoBlock.php index d3ea967..e4c7793 100644 --- a/Block/CategoryInfoBlock.php +++ b/Block/CategoryInfoBlock.php @@ -1,10 +1,34 @@ _registry->registry('current_category'); } + /** + * @return mixed|null + */ public function getCurrentProduct() { return $this->_registry->registry('current_product'); } } -?> diff --git a/Observer/ConfigObserver.php b/Observer/ConfigObserver.php index ed66931..e3e8bfd 100644 --- a/Observer/ConfigObserver.php +++ b/Observer/ConfigObserver.php @@ -12,6 +12,10 @@ class ConfigObserver implements ObserverInterface * @var RequestInterface */ private $request; + /** + * @var WriterInterface + */ + private $configWriter; /** * ConfigChange constructor. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 496a80e..81df95d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,13 @@ +## 1.8.0 + +## Added + +- [`ADDED`]: Added support for [Bloomreach Discovery Facet Response V3](https://documentation.bloomreach.com/discovery/reference/facet-response-v3-unified-ranking). + +## Fixed + +- [`FIXED`]: When adding multiple Recommendations widgets in storefronts, only one was showing. + ## 1.7.1 ## Fixed diff --git a/ViewModel/Head/ScriptInit.php b/ViewModel/Head/ScriptInit.php index 335314b..c314c1a 100644 --- a/ViewModel/Head/ScriptInit.php +++ b/ViewModel/Head/ScriptInit.php @@ -40,7 +40,6 @@ use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Directory\Model\Currency; - /** * Class ScriptInit * package Bloomreach\Connector\ViewModel\Head @@ -687,7 +686,6 @@ public function isPixelDevelopment() { $val = $this->getStoreConfigValue(self::RECOMM_PIXEL_DEVELOPMENT); return 1 == $val; - } /** @@ -730,8 +728,7 @@ public function getAccountId() } /** - * Get current customer unique id. This will become a visitor ID if customer - * is not logged in. + * Get current customer unique id. This will become a visitor ID if customer is not logged in. */ public function getCustomerId() { diff --git a/bin/main.js b/bin/main.js index 72ad395..4b300af 100755 --- a/bin/main.js +++ b/bin/main.js @@ -2,6 +2,7 @@ const commander = require("commander"); const path = require("path"); const shell = require("shelljs"); +require('dotenv').config(); const { Command } = commander; const program = new Command(); diff --git a/composer.json b/composer.json index 0944629..b257f3b 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "bloomreach/bloomreach-connector-magento", "description": "Bloomreach connector for autosuggest,collection and product search", - "version": "1.7.1", + "version": "1.8.0", "type": "magento2-module", "license": "proprietary", "authors": [ diff --git a/etc/config.xml b/etc/config.xml index b6cc1be..3ce1b66 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -203,15 +203,9 @@ <%= checkedFacets.price ? config.format_money(checkedFacets.price[0] * 100) : config.format_money(priceRangeFacet.start * 100) %> - <% if (checkedFacets.price) { %> - - <%= checkedFacets.price ? config.format_money(checkedFacets.price[1] * 100) : config.format_money(priceRangeFacet.start * 100) %> - - <% } else { %> - - <%= config.format_money(priceRangeFacet.end * 100) %> - - <% } %> + + <%= checkedFacets.price ? config.format_money(checkedFacets.price[1] * 100) : config.format_money(priceRangeFacet.end * 100) %> + <% if (checkedFacets.price) { %>
@@ -231,8 +225,8 @@ checked<% } %> - name="<%- facet.original_title %>" - value="<%- escapeSpecialCharacters(item.id) %>" + name="<%= facet.original_title %>" + value="<%= escapeSpecialCharacters(item.id) %>" id="<%- facet.original_title + '[' + escapeSpecialCharacters(item.name) + ']' %>" class="blm-product-search-filter-item__checkbox" /> @@ -576,15 +570,9 @@ <%= checkedFacets.price ? config.format_money(checkedFacets.price[0] * 100) : config.format_money(priceRangeFacet.start * 100) %> - <% if (checkedFacets.price) { %> - - <%= checkedFacets.price ? config.format_money(checkedFacets.price[1] * 100) : config.format_money(priceRangeFacet.start * 100) %> - - <% } else { %> - - <%= config.format_money(priceRangeFacet.end * 100) %> - - <% } %> + + <%= checkedFacets.price ? config.format_money(checkedFacets.price[1] * 100) : config.format_money(priceRangeFacet.end * 100) %> +
<% if (checkedFacets.price) { %>
@@ -604,8 +592,8 @@ checked<% } %> - name="<%- facet.original_title %>" - value="<%- escapeSpecialCharacters(item.id) %>" + name="<%= facet.original_title %>" + value="<%= escapeSpecialCharacters(item.id) %>" id="<%- facet.original_title + '[' + escapeSpecialCharacters(item.name) + ']' %>" class="blm-product-search-filter-item__checkbox" /> diff --git a/package.json b/package.json index bd26634..e546537 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magento-connector", - "version": "1.7.1", + "version": "1.8.0", "description": "NPM tools to aid in developing this connector application", "main": "index.js", "repository": { @@ -29,6 +29,7 @@ "change-case": "4.1.2", "colors": "1.4.0", "commander": "10.0.0", + "dotenv": "16.4.5", "enquirer": "2.3.6", "fs-extra": "11.1.0", "hostile": "1.3.3", diff --git a/view/frontend/web/js/autosuggest.js b/view/frontend/web/js/autosuggest.js index 05a0977..f5d3faf 100644 --- a/view/frontend/web/js/autosuggest.js +++ b/view/frontend/web/js/autosuggest.js @@ -1,3156 +1,10 @@ -(function () { - 'use strict'; - - const AUTOSUGGEST_MINIMUM_QUERY_LENGTH = 2; - const AUTOSUGGEST_TYPED_QUERY_TEMPLATE = '<%= query %>'; - const COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS = 'cdp_segments'; - const COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE = 'customer_profile'; - const DEFAULT_CURRENCY = '$'; - const DEFAULT_PAGE_SIZE = 16; - const DEFAULT_SEARCH_PARAMETER = 'q'; - const DEFAULT_SORTING_OPTIONS = [{ - label: 'Relevance', - value: '' - }, { - label: 'Price (low - high)', - value: 'price+asc' - }, { - label: 'Price (high - low)', - value: 'price+desc' - }, { - label: 'Name (A - Z)', - value: 'title+asc' - }, { - label: 'Name (Z - A)', - value: 'title+desc' - }]; - const DEFAULT_START = 0; - const DEFAULT_WIDGETS_TO_DISPLAY = 4; - const FIELD_NAME_PRICE = 'price'; - const MAX_COLOR_SWATCHES = 4; - const MAX_PAGINATION_NUMBER_BEFORE_CURRENT = 2; - const MAX_PAGINATION_NUMBER_AFTER_CURRENT = 2; - const NUMBER_OF_AUTOSUGGEST_COLLECTIONS = 8; - const NUMBER_OF_AUTOSUGGEST_PRODUCTS = 8; - const NUMBER_OF_AUTOSUGGEST_TERMS = 4; - const NUMBER_OF_FACET_GROUPS = 5; - const NUMBER_OF_FACET_VALUES = 6; - const PARAMETER_NAME_FACETS = 'fq'; - const PARAMETER_NAME_FILTERS_PANEL = 'filterpanel'; - const PARAMETER_NAME_GROUPBY = 'groupby'; - const PARAMETER_NAME_PAGE = 'page'; - const PARAMETER_NAME_SIZE = 'size'; - const PARAMETER_NAME_SORT = 'sort'; - const REQUEST_TYPE_SEARCH = 'search'; - const REQUEST_TYPE_SUGGEST = 'suggest'; - const SEARCH_TYPE_CATEGORY = 'category'; - const SEARCH_TYPE_KEYWORD = 'keyword'; - const SELECTOR_AUTOSUGGEST_INPUT = '.search__input'; - const SELECTOR_SEARCH_RESULTS_CONTAINER = '.main-content'; - /** - * This is the attribute name used to flag an element as an add to cart event - * generator, such as a butto or link. - */ - const ADD_TO_CART_ATTRIBUTE_NAME = 'data-blm-add-to-cart'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the sku value sent in the - * pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_SKU = 'data-blm-add-to-cart-sku'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the prod_id value sent in - * the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_PROD_ID = 'data-blm-add-to-cart-prod-id'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to prevent emitting the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_DISABLE = 'data-blm-add-to-cart-disable'; - const QUICKVIEW_ATTRIBUTE_NAME = 'data-blm-quickview'; - const QUICKVIEW_ATTRIBUTE_SKU = 'data-blm-quickview-sku'; - const QUICKVIEW_ATTRIBUTE_PROD_ID = 'data-blm-quickview-prod-id'; - const QUICKVIEW_ATTRIBUTE_PROD_NAME = 'data-blm-quickview-prod-name'; - - var constants = /*#__PURE__*/Object.freeze({ - __proto__: null, - AUTOSUGGEST_MINIMUM_QUERY_LENGTH: AUTOSUGGEST_MINIMUM_QUERY_LENGTH, - AUTOSUGGEST_TYPED_QUERY_TEMPLATE: AUTOSUGGEST_TYPED_QUERY_TEMPLATE, - COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS: COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS, - COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE: COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE, - DEFAULT_CURRENCY: DEFAULT_CURRENCY, - DEFAULT_PAGE_SIZE: DEFAULT_PAGE_SIZE, - DEFAULT_SEARCH_PARAMETER: DEFAULT_SEARCH_PARAMETER, - DEFAULT_SORTING_OPTIONS: DEFAULT_SORTING_OPTIONS, - DEFAULT_START: DEFAULT_START, - DEFAULT_WIDGETS_TO_DISPLAY: DEFAULT_WIDGETS_TO_DISPLAY, - FIELD_NAME_PRICE: FIELD_NAME_PRICE, - MAX_COLOR_SWATCHES: MAX_COLOR_SWATCHES, - MAX_PAGINATION_NUMBER_BEFORE_CURRENT: MAX_PAGINATION_NUMBER_BEFORE_CURRENT, - MAX_PAGINATION_NUMBER_AFTER_CURRENT: MAX_PAGINATION_NUMBER_AFTER_CURRENT, - NUMBER_OF_AUTOSUGGEST_COLLECTIONS: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - NUMBER_OF_AUTOSUGGEST_PRODUCTS: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - NUMBER_OF_AUTOSUGGEST_TERMS: NUMBER_OF_AUTOSUGGEST_TERMS, - NUMBER_OF_FACET_GROUPS: NUMBER_OF_FACET_GROUPS, - NUMBER_OF_FACET_VALUES: NUMBER_OF_FACET_VALUES, - PARAMETER_NAME_FACETS: PARAMETER_NAME_FACETS, - PARAMETER_NAME_FILTERS_PANEL: PARAMETER_NAME_FILTERS_PANEL, - PARAMETER_NAME_GROUPBY: PARAMETER_NAME_GROUPBY, - PARAMETER_NAME_PAGE: PARAMETER_NAME_PAGE, - PARAMETER_NAME_SIZE: PARAMETER_NAME_SIZE, - PARAMETER_NAME_SORT: PARAMETER_NAME_SORT, - REQUEST_TYPE_SEARCH: REQUEST_TYPE_SEARCH, - REQUEST_TYPE_SUGGEST: REQUEST_TYPE_SUGGEST, - SEARCH_TYPE_CATEGORY: SEARCH_TYPE_CATEGORY, - SEARCH_TYPE_KEYWORD: SEARCH_TYPE_KEYWORD, - SELECTOR_AUTOSUGGEST_INPUT: SELECTOR_AUTOSUGGEST_INPUT, - SELECTOR_SEARCH_RESULTS_CONTAINER: SELECTOR_SEARCH_RESULTS_CONTAINER, - ADD_TO_CART_ATTRIBUTE_NAME: ADD_TO_CART_ATTRIBUTE_NAME, - ADD_TO_CART_ATTRIBUTE_SKU: ADD_TO_CART_ATTRIBUTE_SKU, - ADD_TO_CART_ATTRIBUTE_PROD_ID: ADD_TO_CART_ATTRIBUTE_PROD_ID, - ADD_TO_CART_ATTRIBUTE_DISABLE: ADD_TO_CART_ATTRIBUTE_DISABLE, - QUICKVIEW_ATTRIBUTE_NAME: QUICKVIEW_ATTRIBUTE_NAME, - QUICKVIEW_ATTRIBUTE_SKU: QUICKVIEW_ATTRIBUTE_SKU, - QUICKVIEW_ATTRIBUTE_PROD_ID: QUICKVIEW_ATTRIBUTE_PROD_ID, - QUICKVIEW_ATTRIBUTE_PROD_NAME: QUICKVIEW_ATTRIBUTE_PROD_NAME - }); - - const globalBloomreachModules = Object.assign(Object.assign({}, window.BloomreachModules ? window.BloomreachModules : {}), { - version: '4.0.0', - constants - }); - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getAugmentedNamespace(n) { - var f = n.default; - if (typeof f == "function") { - var a = function () { - return f.apply(this, arguments); - }; - a.prototype = f.prototype; - } else a = {}; - Object.defineProperty(a, '__esModule', {value: true}); - Object.keys(n).forEach(function (k) { - var d = Object.getOwnPropertyDescriptor(n, k); - Object.defineProperty(a, k, d.get ? d : { - enumerable: true, - get: function () { - return n[k]; - } - }); - }); - return a; - } - - var ejs = {}; - - var _polyfillNode_fs = {}; - - var _polyfillNode_fs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _polyfillNode_fs - }); - - var require$$0 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_fs$1); - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // resolves . and .. elements in a path array with directory names there - // must be no slashes, empty elements, or device names (c:\) in the array - // (so also no leading and trailing slashes - it does not distinguish - // relative and absolute paths) - function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; - } - - // Split a filename into [root, dir, basename, ext], unix version - // 'root' is just a slash, or nothing. - var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); - }; - - // path.resolve([from ...], to) - // posix version - function resolve() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : '/'; - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - } - // path.normalize(path) - // posix version - function normalize(path) { - var isPathAbsolute = isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isPathAbsolute).join('/'); - - if (!path && !isPathAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isPathAbsolute ? '/' : '') + path; - } - // posix version - function isAbsolute(path) { - return path.charAt(0) === '/'; - } - - // posix version - function join() { - var paths = Array.prototype.slice.call(arguments, 0); - return normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); - } - - - // path.relative(from, to) - // posix version - function relative(from, to) { - from = resolve(from).substr(1); - to = resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - } - - var sep = '/'; - var delimiter = ':'; - - function dirname(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; - } - - function basename(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; - } - - - function extname(path) { - return splitPath(path)[3]; - } - var _polyfillNode_path = { - extname: extname, - basename: basename, - dirname: dirname, - sep: sep, - delimiter: delimiter, - relative: relative, - join: join, - isAbsolute: isAbsolute, - normalize: normalize, - resolve: resolve - }; - function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; - } - - // String.prototype.substr - negative index don't work in IE8 - var substr = 'ab'.substr(-1) === 'b' ? - function (str, start, len) { return str.substr(start, len) } : - function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } - ; - - var _polyfillNode_path$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - resolve: resolve, - normalize: normalize, - isAbsolute: isAbsolute, - join: join, - relative: relative, - sep: sep, - delimiter: delimiter, - dirname: dirname, - basename: basename, - extname: extname, - 'default': _polyfillNode_path - }); - - var require$$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_path$1); - - var utils = {}; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - var regExpChars = /[|\\{}()[\]^$+*?.]/g; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); }; - - /** - * Escape characters reserved in regular expressions. - * - * If `string` is `undefined` or `null`, the empty string is returned. - * - * @param {String} string Input string - * @return {String} Escaped string - * @static - * @private - */ - exports.escapeRegExpChars = function (string) { - // istanbul ignore if - if (!string) { - return ''; - } - return String(string).replace(regExpChars, '\\$&'); - }; - - var _ENCODE_HTML_RULES = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - var _MATCH_HTML = /[&<>'"]/g; - - function encode_char(c) { - return _ENCODE_HTML_RULES[c] || c; - } - - /** - * Stringified version of constants used by {@link module:utils.escapeXML}. - * - * It is used in the process of generating {@link ClientFunction}s. - * - * @readonly - * @type {String} - */ - - var escapeFuncStr = - 'var _ENCODE_HTML_RULES = {\n' - + ' "&": "&"\n' - + ' , "<": "<"\n' - + ' , ">": ">"\n' - + ' , \'"\': """\n' - + ' , "\'": "'"\n' - + ' }\n' - + ' , _MATCH_HTML = /[&<>\'"]/g;\n' - + 'function encode_char(c) {\n' - + ' return _ENCODE_HTML_RULES[c] || c;\n' - + '};\n'; - - /** - * Escape characters reserved in XML. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @implements {EscapeCallback} - * @param {String} markup Input string - * @return {String} Escaped string - * @static - * @private - */ - - exports.escapeXML = function (markup) { - return markup == undefined - ? '' - : String(markup) - .replace(_MATCH_HTML, encode_char); - }; - exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; - }; - - /** - * Naive copy of properties from one object to another. - * Does not recurse into non-scalar properties - * Does not check to see if the property has a value before copying - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopy = function (to, from) { - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var p in from) { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - return to; - }; - - /** - * Naive copy of a list of key names, from one object to another. - * Only copies property if it is actually defined - * Does not recurse into non-scalar properties - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @param {Array} list List of properties to copy - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopyFromList = function (to, from, list) { - list = list || []; - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var i = 0; i < list.length; i++) { - var p = list[i]; - if (typeof from[p] != 'undefined') { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - } - return to; - }; - - /** - * Simple in-process cache implementation. Does not implement limits of any - * sort. - * - * @implements {Cache} - * @static - * @private - */ - exports.cache = { - _data: {}, - set: function (key, val) { - this._data[key] = val; - }, - get: function (key) { - return this._data[key]; - }, - remove: function (key) { - delete this._data[key]; - }, - reset: function () { - this._data = {}; - } - }; - - /** - * Transforms hyphen case variable into camel case. - * - * @param {String} string Hyphen case string - * @return {String} Camel case string - * @static - * @private - */ - exports.hyphenToCamel = function (str) { - return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); }); - }; - - /** - * Returns a null-prototype object in runtimes that support it - * - * @return {Object} Object, prototype will be set to null where possible - * @static - * @private - */ - exports.createNullProtoObjWherePossible = (function () { - if (typeof Object.create == 'function') { - return function () { - return Object.create(null); - }; - } - if (!({__proto__: null} instanceof Object)) { - return function () { - return {__proto__: null}; - }; - } - // Not possible, just pass through - return function () { - return {}; - }; - })(); - } (utils)); - - var name = "ejs"; - var description = "Embedded JavaScript templates"; - var keywords = [ - "template", - "engine", - "ejs" - ]; - var version = "3.1.8"; - var author = "Matthew Eernisse (http://fleegix.org)"; - var license = "Apache-2.0"; - var bin = { - ejs: "./bin/cli.js" - }; - var main = "./lib/ejs.js"; - var jsdelivr = "ejs.min.js"; - var unpkg = "ejs.min.js"; - var repository = { - type: "git", - url: "git://github.com/mde/ejs.git" - }; - var bugs = "https://github.com/mde/ejs/issues"; - var homepage = "https://github.com/mde/ejs"; - var dependencies = { - jake: "^10.8.5" - }; - var devDependencies = { - browserify: "^16.5.1", - eslint: "^6.8.0", - "git-directory-deploy": "^1.5.1", - jsdoc: "^3.6.7", - "lru-cache": "^4.0.1", - mocha: "^7.1.1", - "uglify-js": "^3.3.16" - }; - var engines = { - node: ">=0.10.0" - }; - var scripts = { - test: "mocha" - }; - var require$$3 = { - name: name, - description: description, - keywords: keywords, - version: version, - author: author, - license: license, - bin: bin, - main: main, - jsdelivr: jsdelivr, - unpkg: unpkg, - repository: repository, - bugs: bugs, - homepage: homepage, - dependencies: dependencies, - devDependencies: devDependencies, - engines: engines, - scripts: scripts - }; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - /** +!function(){"use strict";const e=Object.assign(Object.assign({},window.BloomreachModules?window.BloomreachModules:{}),{version:"3.1.0"});var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(e){var t=e.default;if("function"==typeof t){var n=function(){return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach((function(t){var r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:function(){return e[t]}})})),n}var r={},o=n(Object.freeze({__proto__:null,default:{}}));function s(e,t){for(var n=0,r=e.length-1;r>=0;r--){var o=e[r];"."===o?e.splice(r,1):".."===o?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var i=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,a=function(e){return i.exec(e).slice(1)};function u(){for(var e="",t=!1,n=arguments.length-1;n>=-1&&!t;n--){var r=n>=0?arguments[n]:"/";if("string"!=typeof r)throw new TypeError("Arguments to path.resolve must be strings");r&&(e=r+"/"+e,t="/"===r.charAt(0))}return(t?"/":"")+(e=s(v(e.split("/"),(function(e){return!!e})),!t).join("/"))||"."}function c(e){var t=l(e),n="/"===_(e,-1);return(e=s(v(e.split("/"),(function(e){return!!e})),!t).join("/"))||t||(e="."),e&&n&&(e+="/"),(t?"/":"")+e}function l(e){return"/"===e.charAt(0)}function g(){return c(v(Array.prototype.slice.call(arguments,0),(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))}function d(e,t){function n(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=u(e).substr(1),t=u(t).substr(1);for(var r=n(e.split("/")),o=n(t.split("/")),s=Math.min(r.length,o.length),i=s,a=0;a":">",'"':""","'":"'"},s=/[&<>'"]/g;function i(e){return o[e]||e}function a(){return Function.prototype.toString.call(this)+';\nvar _ENCODE_HTML_RULES = {\n "&": "&"\n , "<": "<"\n , ">": ">"\n , \'"\': """\n , "\'": "'"\n }\n , _MATCH_HTML = /[&<>\'"]/g;\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n};\n'}e.escapeXML=function(e){return null==e?"":String(e).replace(s,i)};try{"function"==typeof Object.defineProperty?Object.defineProperty(e.escapeXML,"toString",{value:a}):e.escapeXML.toString=a}catch(e){console.warn("Unable to set escapeXML.toString (is the Function prototype frozen?)")}e.shallowCopy=function(e,t){if(t=t||{},null!=e)for(var n in t)r(t,n)&&"__proto__"!==n&&"constructor"!==n&&(e[n]=t[n]);return e},e.shallowCopyFromList=function(e,t,n){if(n=n||[],t=t||{},null!=e)for(var o=0;o * @author Tiancheng "Timothy" Gu * @project EJS * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} */ - - /** - * EJS internal functions. - * - * Technically this "module" lies in the same file as {@link module:ejs}, for - * the sake of organization all the private functions re grouped into this - * module. - * - * @module ejs-internal - * @private - */ - - /** - * Embedded JavaScript templating engine. - * - * @module ejs - * @public - */ - - - var fs = require$$0; - var path = require$$1; - var utils$1 = utils; - - var scopeOptionWarned = false; - /** @type {string} */ - var _VERSION_STRING = require$$3.version; - var _DEFAULT_OPEN_DELIMITER = '<'; - var _DEFAULT_CLOSE_DELIMITER = '>'; - var _DEFAULT_DELIMITER = '%'; - var _DEFAULT_LOCALS_NAME = 'locals'; - var _NAME = 'ejs'; - var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; - var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', - 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; - // We don't allow 'cache' option to be passed in the data obj for - // the normal `render` call, but this is where Express 2 & 3 put it - // so we make an exception for `renderFile` - var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); - var _BOM = /^\uFEFF/; - var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; - - /** - * EJS template function cache. This can be a LRU object from lru-cache NPM - * module. By default, it is {@link module:utils.cache}, a simple in-process - * cache that grows continuously. - * - * @type {Cache} - */ - - exports.cache = utils$1.cache; - - /** - * Custom file loader. Useful for template preprocessing or restricting access - * to a certain part of the filesystem. - * - * @type {fileLoader} - */ - - exports.fileLoader = fs.readFileSync; - - /** - * Name of the object containing the locals. - * - * This variable is overridden by {@link Options}`.localsName` if it is not - * `undefined`. - * - * @type {String} - * @public - */ - - exports.localsName = _DEFAULT_LOCALS_NAME; - - /** - * Promise implementation -- defaults to the native implementation if available - * This is mostly just for testability - * - * @type {PromiseConstructorLike} - * @public - */ - - exports.promiseImpl = (new Function('return this;'))().Promise; - - /** - * Get the path to the included file from the parent file path and the - * specified path. - * - * @param {String} name specified path - * @param {String} filename parent file path - * @param {Boolean} [isDir=false] whether the parent file path is a directory - * @return {String} - */ - exports.resolveInclude = function(name, filename, isDir) { - var dirname = path.dirname; - var extname = path.extname; - var resolve = path.resolve; - var includePath = resolve(isDir ? filename : dirname(filename), name); - var ext = extname(name); - if (!ext) { - includePath += '.ejs'; - } - return includePath; - }; - - /** - * Try to resolve file path on multiple directories - * - * @param {String} name specified path - * @param {Array} paths list of possible parent directory paths - * @return {String} - */ - function resolvePaths(name, paths) { - var filePath; - if (paths.some(function (v) { - filePath = exports.resolveInclude(name, v, true); - return fs.existsSync(filePath); - })) { - return filePath; - } - } - - /** - * Get the path to the included file by Options - * - * @param {String} path specified path - * @param {Options} options compilation options - * @return {String} - */ - function getIncludePath(path, options) { - var includePath; - var filePath; - var views = options.views; - var match = /^[A-Za-z]+:\\|^\//.exec(path); - - // Abs path - if (match && match.length) { - path = path.replace(/^\/*/, ''); - if (Array.isArray(options.root)) { - includePath = resolvePaths(path, options.root); - } else { - includePath = exports.resolveInclude(path, options.root || '/', true); - } - } - // Relative paths - else { - // Look relative to a passed filename first - if (options.filename) { - filePath = exports.resolveInclude(path, options.filename); - if (fs.existsSync(filePath)) { - includePath = filePath; - } - } - // Then look in any views directories - if (!includePath && Array.isArray(views)) { - includePath = resolvePaths(path, views); - } - if (!includePath && typeof options.includer !== 'function') { - throw new Error('Could not find the include file "' + - options.escapeFunction(path) + '"'); - } - } - return includePath; - } - - /** - * Get the template from a string or a file, either compiled on-the-fly or - * read from cache (if enabled), and cache the template if needed. - * - * If `template` is not set, the file specified in `options.filename` will be - * read. - * - * If `options.cache` is true, this function reads the file from - * `options.filename` so it must be set prior to calling this function. - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {String} [template] template source - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned. - * @static - */ - - function handleCache(options, template) { - var func; - var filename = options.filename; - var hasTemplate = arguments.length > 1; - - if (options.cache) { - if (!filename) { - throw new Error('cache option requires a filename'); - } - func = exports.cache.get(filename); - if (func) { - return func; - } - if (!hasTemplate) { - template = fileLoader(filename).toString().replace(_BOM, ''); - } - } - else if (!hasTemplate) { - // istanbul ignore if: should not happen at all - if (!filename) { - throw new Error('Internal EJS error: no file name or template ' - + 'provided'); - } - template = fileLoader(filename).toString().replace(_BOM, ''); - } - func = exports.compile(template, options); - if (options.cache) { - exports.cache.set(filename, func); - } - return func; - } - - /** - * Try calling handleCache with the given options and data and call the - * callback with the result. If an error occurs, call the callback with - * the error. Used by renderFile(). - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {Object} data template data - * @param {RenderFileCallback} cb callback - * @static - */ - - function tryHandleCache(options, data, cb) { - var result; - if (!cb) { - if (typeof exports.promiseImpl == 'function') { - return new exports.promiseImpl(function (resolve, reject) { - try { - result = handleCache(options)(data); - resolve(result); - } - catch (err) { - reject(err); - } - }); - } - else { - throw new Error('Please provide a callback function'); - } - } - else { - try { - result = handleCache(options)(data); - } - catch (err) { - return cb(err); - } - - cb(null, result); - } - } - - /** - * fileLoader is independent - * - * @param {String} filePath ejs file path. - * @return {String} The contents of the specified file. - * @static - */ - - function fileLoader(filePath){ - return exports.fileLoader(filePath); - } - - /** - * Get the template function. - * - * If `options.cache` is `true`, then the template is cached. - * - * @memberof module:ejs-internal - * @param {String} path path for the specified file - * @param {Options} options compilation options - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned - * @static - */ - - function includeFile(path, options) { - var opts = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), options); - opts.filename = getIncludePath(path, opts); - if (typeof options.includer === 'function') { - var includerResult = options.includer(path, opts.filename); - if (includerResult) { - if (includerResult.filename) { - opts.filename = includerResult.filename; - } - if (includerResult.template) { - return handleCache(opts, includerResult.template); - } - } - } - return handleCache(opts); - } - - /** - * Re-throw the given `err` in context to the `str` of ejs, `filename`, and - * `lineno`. - * - * @implements {RethrowCallback} - * @memberof module:ejs-internal - * @param {Error} err Error object - * @param {String} str EJS source - * @param {String} flnm file name of the EJS file - * @param {Number} lineno line number of the error - * @param {EscapeCallback} esc - * @static - */ - - function rethrow(err, str, flnm, lineno, esc) { - var lines = str.split('\n'); - var start = Math.max(lineno - 3, 0); - var end = Math.min(lines.length, lineno + 3); - var filename = esc(flnm); - // Error context - var context = lines.slice(start, end).map(function (line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; - } - - function stripSemi(str){ - return str.replace(/;(\s*$)/, '$1'); - } - - /** - * Compile the given `str` of ejs into a template function. - * - * @param {String} template EJS template - * - * @param {Options} [opts] compilation options - * - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `opts.client`, either type might be returned. - * Note that the return type of the function also depends on the value of `opts.async`. - * @public - */ - - exports.compile = function compile(template, opts) { - var templ; - - // v1 compat - // 'scope' is 'context' - // FIXME: Remove this in a future version - if (opts && opts.scope) { - if (!scopeOptionWarned){ - console.warn('`scope` option is deprecated and will be removed in EJS 3'); - scopeOptionWarned = true; - } - if (!opts.context) { - opts.context = opts.scope; - } - delete opts.scope; - } - templ = new Template(template, opts); - return templ.compile(); - }; - - /** - * Render the given `template` of ejs. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} template EJS template - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @return {(String|Promise)} - * Return value type depends on `opts.async`. - * @public - */ - - exports.render = function (template, d, o) { - var data = d || utils$1.createNullProtoObjWherePossible(); - var opts = o || utils$1.createNullProtoObjWherePossible(); - - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 2) { - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); - } - - return handleCache(opts, template)(data); - }; - - /** - * Render an EJS file at the given `path` and callback `cb(err, str)`. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} path path to the EJS file - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @param {RenderFileCallback} cb callback - * @public - */ - - exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments); - var filename = args.shift(); - var cb; - var opts = {filename: filename}; - var data; - var viewOpts; - - // Do we have a callback? - if (typeof arguments[arguments.length - 1] == 'function') { - cb = args.pop(); - } - // Do we have data/opts? - if (args.length) { - // Should always have data obj - data = args.shift(); - // Normal passed opts (data obj + opts obj) - if (args.length) { - // Use shallowCopy so we don't pollute passed in opts obj with new vals - utils$1.shallowCopy(opts, args.pop()); - } - // Special casing for Express (settings + opts-in-data) - else { - // Express 3 and 4 - if (data.settings) { - // Pull a few things from known locations - if (data.settings.views) { - opts.views = data.settings.views; - } - if (data.settings['view cache']) { - opts.cache = true; - } - // Undocumented after Express 2, but still usable, esp. for - // items that are unsafe to be passed along with data, like `root` - viewOpts = data.settings['view options']; - if (viewOpts) { - utils$1.shallowCopy(opts, viewOpts); - } - } - // Express 2 and lower, values set in app.locals, or people who just - // want to pass options in their data. NOTE: These values will override - // anything previously set in settings or settings['view options'] - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); - } - opts.filename = filename; - } - else { - data = utils$1.createNullProtoObjWherePossible(); - } - - return tryHandleCache(opts, data, cb); - }; - - /** - * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. - * @public - */ - - /** - * EJS template class - * @public - */ - exports.Template = Template; - - exports.clearCache = function () { - exports.cache.reset(); - }; - - function Template(text, opts) { - opts = opts || utils$1.createNullProtoObjWherePossible(); - var options = utils$1.createNullProtoObjWherePossible(); - this.templateText = text; - /** @type {string | null} */ - this.mode = null; - this.truncate = false; - this.currentLine = 1; - this.source = ''; - options.client = opts.client || false; - options.escapeFunction = opts.escape || opts.escapeFunction || utils$1.escapeXML; - options.compileDebug = opts.compileDebug !== false; - options.debug = !!opts.debug; - options.filename = opts.filename; - options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; - options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; - options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; - options.strict = opts.strict || false; - options.context = opts.context; - options.cache = opts.cache || false; - options.rmWhitespace = opts.rmWhitespace; - options.root = opts.root; - options.includer = opts.includer; - options.outputFunctionName = opts.outputFunctionName; - options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; - options.views = opts.views; - options.async = opts.async; - options.destructuredLocals = opts.destructuredLocals; - options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; - - if (options.strict) { - options._with = false; - } - else { - options._with = typeof opts._with != 'undefined' ? opts._with : true; - } - - this.opts = options; - - this.regex = this.createRegex(); - } - - Template.modes = { - EVAL: 'eval', - ESCAPED: 'escaped', - RAW: 'raw', - COMMENT: 'comment', - LITERAL: 'literal' - }; - - Template.prototype = { - createRegex: function () { - var str = _REGEX_STRING; - var delim = utils$1.escapeRegExpChars(this.opts.delimiter); - var open = utils$1.escapeRegExpChars(this.opts.openDelimiter); - var close = utils$1.escapeRegExpChars(this.opts.closeDelimiter); - str = str.replace(/%/g, delim) - .replace(//g, close); - return new RegExp(str); - }, - - compile: function () { - /** @type {string} */ - var src; - /** @type {ClientFunction} */ - var fn; - var opts = this.opts; - var prepended = ''; - var appended = ''; - /** @type {EscapeCallback} */ - var escapeFn = opts.escapeFunction; - /** @type {FunctionConstructor} */ - var ctor; - /** @type {string} */ - var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined'; - - if (!this.source) { - this.generateSource(); - prepended += - ' var __output = "";\n' + - ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; - if (opts.outputFunctionName) { - if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) { - throw new Error('outputFunctionName is not a valid JS identifier.'); - } - prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; - } - if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) { - throw new Error('localsName is not a valid JS identifier.'); - } - if (opts.destructuredLocals && opts.destructuredLocals.length) { - var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; - for (var i = 0; i < opts.destructuredLocals.length; i++) { - var name = opts.destructuredLocals[i]; - if (!_JS_IDENTIFIER.test(name)) { - throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.'); - } - if (i > 0) { - destructuring += ',\n '; - } - destructuring += name + ' = __locals.' + name; - } - prepended += destructuring + ';\n'; - } - if (opts._with !== false) { - prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; - appended += ' }' + '\n'; - } - appended += ' return __output;' + '\n'; - this.source = prepended + this.source + appended; - } - - if (opts.compileDebug) { - src = 'var __line = 1' + '\n' - + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' - + ' , __filename = ' + sanitizedFilename + ';' + '\n' - + 'try {' + '\n' - + this.source - + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' - + '}' + '\n'; - } - else { - src = this.source; - } - - if (opts.client) { - src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; - if (opts.compileDebug) { - src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; - } - } - - if (opts.strict) { - src = '"use strict";\n' + src; - } - if (opts.debug) { - console.log(src); - } - if (opts.compileDebug && opts.filename) { - src = src + '\n' - + '//# sourceURL=' + sanitizedFilename + '\n'; - } - - try { - if (opts.async) { - // Have to use generated function for this, since in envs without support, - // it breaks in parsing - try { - ctor = (new Function('return (async function(){}).constructor;'))(); - } - catch(e) { - if (e instanceof SyntaxError) { - throw new Error('This environment does not support async/await'); - } - else { - throw e; - } - } - } - else { - ctor = Function; - } - fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); - } - catch(e) { - // istanbul ignore else - if (e instanceof SyntaxError) { - if (opts.filename) { - e.message += ' in ' + opts.filename; - } - e.message += ' while compiling ejs\n\n'; - e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; - e.message += 'https://github.com/RyanZim/EJS-Lint'; - if (!opts.async) { - e.message += '\n'; - e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; - } - } - throw e; - } - - // Return a callable function which will execute the function - // created by the source-code, with the passed data as locals - // Adds a local `include` function which allows full recursive include - var returnedFn = opts.client ? fn : function anonymous(data) { - var include = function (path, includeData) { - var d = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), data); - if (includeData) { - d = utils$1.shallowCopy(d, includeData); - } - return includeFile(path, opts)(d); - }; - return fn.apply(opts.context, - [data || utils$1.createNullProtoObjWherePossible(), escapeFn, include, rethrow]); - }; - if (opts.filename && typeof Object.defineProperty === 'function') { - var filename = opts.filename; - var basename = path.basename(filename, path.extname(filename)); - try { - Object.defineProperty(returnedFn, 'name', { - value: basename, - writable: false, - enumerable: false, - configurable: true - }); - } catch (e) {/* ignore */} - } - return returnedFn; - }, - - generateSource: function () { - var opts = this.opts; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r` and empty lines don't work well with the `m` flag. - this.templateText = - this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); - - var self = this; - var matches = this.parseTemplateText(); - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - - if (matches && matches.length) { - matches.forEach(function (line, index) { - var closing; - // If this is an opening tag, check for closing tags - // FIXME: May end up with some false positives here - // Better to store modes as k/v with openDelimiter + delimiter as key - // Then this can simply check against the map - if ( line.indexOf(o + d) === 0 // If it is a tag - && line.indexOf(o + d + d) !== 0) { // and is not escaped - closing = matches[index + 2]; - if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { - throw new Error('Could not find matching close tag for "' + line + '".'); - } - } - self.scanLine(line); - }); - } - - }, - - parseTemplateText: function () { - var str = this.templateText; - var pat = this.regex; - var result = pat.exec(str); - var arr = []; - var firstPos; - - while (result) { - firstPos = result.index; - - if (firstPos !== 0) { - arr.push(str.substring(0, firstPos)); - str = str.slice(firstPos); - } - - arr.push(result[0]); - str = str.slice(result[0].length); - result = pat.exec(str); - } - - if (str) { - arr.push(str); - } - - return arr; - }, - - _addOutput: function (line) { - if (this.truncate) { - // Only replace single leading linebreak in the line after - // -%> tag -- this is the single, trailing linebreak - // after the tag that the truncation mode replaces - // Handle Win / Unix / old Mac linebreaks -- do the \r\n - // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, ''); - this.truncate = false; - } - if (!line) { - return line; - } - - // Preserve literal slashes - line = line.replace(/\\/g, '\\\\'); - - // Convert linebreaks - line = line.replace(/\n/g, '\\n'); - line = line.replace(/\r/g, '\\r'); - - // Escape double-quotes - // - this will be the delimiter during execution - line = line.replace(/"/g, '\\"'); - this.source += ' ; __append("' + line + '")' + '\n'; - }, - - scanLine: function (line) { - var self = this; - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - var newLineCount = 0; - - newLineCount = (line.split('\n').length - 1); - - switch (line) { - case o + d: - case o + d + '_': - this.mode = Template.modes.EVAL; - break; - case o + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case o + d + '-': - this.mode = Template.modes.RAW; - break; - case o + d + '#': - this.mode = Template.modes.COMMENT; - break; - case o + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; - break; - case d + d + c: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; - break; - case d + c: - case '-' + d + c: - case '_' + d + c: - if (this.mode == Template.modes.LITERAL) { - this._addOutput(line); - } - - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: - // In script mode, depends on type of tag - if (this.mode) { - // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } - } - switch (this.mode) { - // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; - // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; - break; - // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; - break; - case Template.modes.COMMENT: - // Do nothing - break; - // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - this._addOutput(line); - break; - } - } - // In string mode, just add the output - else { - this._addOutput(line); - } - } - - if (self.opts.compileDebug && newLineCount) { - this.currentLine += newLineCount; - this.source += ' ; __line = ' + this.currentLine + '\n'; - } - } - }; - - /** - * Escape characters reserved in XML. - * - * This is simply an export of {@link module:utils.escapeXML}. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @param {String} markup Input string - * @return {String} Escaped string - * @public - * @func - * */ - exports.escapeXML = utils$1.escapeXML; - - /** - * Express.js support. - * - * This is an alias for {@link module:ejs.renderFile}, in order to support - * Express.js out-of-the-box. - * - * @func - */ - - exports.__express = exports.renderFile; - - /** - * Version of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.VERSION = _VERSION_STRING; - - /** - * Name for detection of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.name = _NAME; - - /* istanbul ignore if */ - if (typeof window != 'undefined') { - window.ejs = exports; - } - } (ejs)); - - // /utils/getRequest.ts - /** - * Method used to initiate the API request - * @remarks The Assignment of the API specific promise is set in the respective API - * @param {string} url - * @param {{}} options - * @returns {Promise} - */ - async function getRequest(url, options) { - /** - * Use of Client-Side Fetch API to retrieve the response - * @type {Response} - */ - const response = await fetch(url, options); - /** - * Formats the response as json and returns the typed promise - * @type {any} - */ - const result = await response.json(); - /** - * Sets the type for the promise - */ - return result; - } - - // utils.requestOptions.ts - /** - * - * @type {{headers: {'Content-Type': string}, method: string}} - */ - const requestOptions = { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }; - - // utils/extractTrackingCookie.ts - /** - * Extracts the tracking cookie from the Bloomreach cookie pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractTrackingCookie() { - const trackingCookie = document.cookie.split('; ').find(cookie => cookie.startsWith('_br_uid_2=')); - return trackingCookie ? trackingCookie.replace('_br_uid_2=', '') : 'uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55'; - } - - // utils/formatAsCurrency.ts - /** - * Formats a value returned as a double into currency - * @param {number} cents - * @param {string} currencySign - * @param {boolean} onFront - * @returns {string} - */ - const formatAsCurrency = (cents, currencySign = '$', onFront = true) => `${onFront ? currencySign : ''}${(cents / 100.0).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 -})}${!onFront ? ` ${currencySign}` : ''}`; - - // utils/generateRequestID.ts - /** - * Generates a randomized request ID that is 13 characters long - * @returns {number} - */ - function generateRequestId() { - // eslint-disable-next-line no-mixed-operators - const requestID = Math.floor(1000000000000 + Math.random() * 9000000000000); - return requestID; - } - - // api-client/constants - // todo Refactor vanilla js / react implementation to either use or not use the constants config - const ENDPOINT_AUTOSUGGEST_API = 'https://suggest.dxpapi.com/api/v2/suggest/'; - const NO_ENCODE_PARAMETERS = ['_br_uid_2', 'fq', 'sort']; - - function buildQueryParameters(apiCallParameters) { - return `?${Object.keys(apiCallParameters).reduce((queryParameters, parameterName) => [...queryParameters, `${parameterName}=${NO_ENCODE_PARAMETERS.includes(parameterName) ? apiCallParameters[parameterName] : encodeURIComponent(apiCallParameters[parameterName])}`], []).join('&')}`; - } - function buildAutosuggestRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_AUTOSUGGEST_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSuggestions(params) { - const url = buildAutosuggestRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - var searchLayoutTemplate = "<% if (did_you_mean.length) { %>\n
\n
\n

Results for\n <% if (locals.keywordRedirect && keywordRedirect.redirected_url) { %>\n <%- keywordRedirect.redirected_url %>\n <% } else { %>\n <%- did_you_mean[0] %>\n <% } %>\n instead of <%- locals[config.default_search_parameter] %>

\n
\n \n <% did_you_mean.forEach(function(word) { %>\n ?<%= config.default_search_parameter %>=<%= word %>\" class=\"blm-did-you-mean-suggestion__link\"><%- word %>\n <% }); %>\n
\n <% if (locals.keywordRedirect && keywordRedirect.redirected_query) { %>\n
Redirected from \"<%- keywordRedirect.redirected_query %>\".
\n <% } %>\n
\n
\n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from \"<%- keywordRedirect.original_query %>\"
\n
\n
\n<% } %>\n
category<% } else { %>product-search<% } %> blm-results <% if (config.search.facets_included) { %>with-facets<% } %>\">\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class=\"blm-product-search__results\"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n"; - - var searchListTemplate = "<% function printProduct(product) { %>\n
title=\"<%- product.variant_name %>\"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : 'variant_index' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style=\"display: block\"<% } %>\n >\n \"\n />\n
\n <% }); %>\n <% } else { %>\n
\n \"\n />\n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n active<% } %>\"\n style=\"background-image: url('<%= variant.image %>')\"\n >\n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n"; - - var autosuggestTemplate = "<% if (terms.length || productSuggestions.length) { %>\n
\n <% } %>\n"; - - function buildBaseConfig() { - var _a; - const connectorConfig = (_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config; - const config = Object.assign({ - default_search_parameter: DEFAULT_SEARCH_PARAMETER, - url: window.location.href, - ref_url: window.location.href, - tracking_cookie: extractTrackingCookie(), - format_money: cents => formatAsCurrency(cents, window.bloomreachDefaultCurrency || DEFAULT_CURRENCY), - default_currency: window.bloomreachDefaultCurrency || DEFAULT_CURRENCY - }, connectorConfig); - return config; - } - function buildAutosuggestConfig() { - const baseConfig = buildBaseConfig(); - const config = Object.assign(Object.assign({ - request_type: REQUEST_TYPE_SUGGEST - }, baseConfig), { - autosuggest: Object.assign({ - enabled: true, - endpoint: '', - number_of_terms: NUMBER_OF_AUTOSUGGEST_TERMS, - number_of_products: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - number_of_collections: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - selector: SELECTOR_AUTOSUGGEST_INPUT, - template: autosuggestTemplate, - catalog_views: '' - }, baseConfig.autosuggest) - }); - return config; - } - function buildSearchConfig() { - var _a, _b, _c; - const baseConfig = buildBaseConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const state = getCurrentSearchRequestState(); - const defaultSearchProperties = Object.assign({ - display_variants: false, - enabled: true, - endpoint: '', - items_per_page: DEFAULT_PAGE_SIZE, - facets_included: true, - initial_number_of_facets: NUMBER_OF_FACET_GROUPS, - initial_number_of_facet_values: NUMBER_OF_FACET_VALUES, - infinite_scroll: false, - selector: SELECTOR_SEARCH_RESULTS_CONTAINER, - sorting_options: DEFAULT_SORTING_OPTIONS, - template: searchLayoutTemplate, - product_list_template: searchListTemplate - }, (baseConfig === null || baseConfig === void 0 ? void 0 : baseConfig.search) ? baseConfig.search : {}); - const config = Object.assign(Object.assign({}, baseConfig), { - request_type: REQUEST_TYPE_SEARCH, - search_type: state.is_category_page ? SEARCH_TYPE_CATEGORY : SEARCH_TYPE_KEYWORD, - start: DEFAULT_START, - 'facet.range': FIELD_NAME_PRICE, - 'stats.field': FIELD_NAME_PRICE, - sort: urlParameters.get(PARAMETER_NAME_SORT) || '', - search: Object.assign(Object.assign(Object.assign({}, defaultSearchProperties), (state.is_category_page ? baseConfig.category : baseConfig.search) || {}), state.category_to_load ? { - category_id: state.category_to_load - } : {}) - }); - (_c = (_b = (_a = config.search) === null || _a === void 0 ? void 0 : _a.sorting_options) === null || _b === void 0 ? void 0 : _b.sort) === null || _c === void 0 ? void 0 : _c.call(_b, (option1, option2) => option1.value > option2.value ? 1 : -1); - if (config.search) { - config.search = Object.assign(Object.assign({}, config.search), { - items_per_page: Number(urlParameters.has(PARAMETER_NAME_SIZE) ? urlParameters.get(PARAMETER_NAME_SIZE) : config.search.items_per_page), - groupby: urlParameters.get(PARAMETER_NAME_GROUPBY) || config.search.groupby || '' - }); - } - return config; - } - - let memoizedNS; - const NOOP = Object.assign(() => {}, { - warn: () => {}, - error: () => {}, - verbose: () => {} - }); - let colorIndex = -1; - const memoizedColor = new Map(); - /** - * List of colors our debugger can pick from. The colors should be slightly - * desautrated to help with reading and should be highly varied. - */ - const pickColor = ns => { - if (memoizedColor.has(ns)) return memoizedColor.get(ns); - const color = ['#00a3ff', '#ff00a3', '#a3ff00', '#00ffa3', '#a300ff', '#ffaa00', '#00ffaa', '#ff00aa', '#aa00ff', '#00aaff'][++colorIndex % 10] || '#00a3ff'; - memoizedColor.set(ns, color); - return color; - }; - /** - * Creates a simple debug logger system that is only activated by the stored - * state within localStorage.debug. The value in the state can be: - * - * namespace1;namespace2;namespace3;etc - * - * or - * - * namepspace1 - * - * or - * - * * - * - * Where `*` is a wildcard that will activate all namespaces. - */ - const Debug = ns => { - const active = activeNS(); - // If the namespace is not active, return a noop function set - if (!active.has(ns) && !active.has('*')) return NOOP; - const color = pickColor(ns); - const logger = console.log.bind(console, `%c${ns}`, `color: ${color}`); - logger.warn = console.warn.bind(console, `%c${ns}`, `color: ${color}`); - logger.error = console.error.bind(console, `%c${ns}`, `color: ${color}`); - if (active.has(`${ns}:verbose`) || active.has('*')) { - logger.verbose = console.log.bind(console, `%c${ns}:verbose`, `color: ${color}`); - } else { - logger.verbose = () => {}; - } - return logger; - }; - function activeNS() { - if (memoizedNS) return memoizedNS; - const storage = window.localStorage; - if (!storage) return new Set(); - const ns = storage.getItem('debug') || ''; - memoizedNS = new Set(ns.split(';')); - return memoizedNS; - } - - /** - * If a truthy value is false, this throws an error and displays the message for - * the error. - */ - function invariant(truthy, message) { - if (truthy) return; - throw new Error(message); - } - - const autosuggestLog = Debug('br:autosuggest'); - function findUpElementWithClassName(startElement, className) { - var _a; - let element = startElement; - // eslint-disable-next-line functional/no-loop-statement - while (element && element.parentElement) { - element = element.parentElement; - if (element && ((_a = element.classList) === null || _a === void 0 ? void 0 : _a.contains(className))) { - return element; - } - } - return null; - } - function findUpElementByTagName(startElement, tagName) { - let element = startElement; - // eslint-disable-next-line functional/no-loop-statement - while (element && element.parentNode) { - element = element.parentNode; - if (element && element.tagName.toLowerCase() === tagName.toLowerCase()) { - return element; - } - } - return null; - } - function hideAllDynamicFacetGroups() { - ['.blm-dynamic-filter', '.blm-product-search-filter-item', '.blm-product-search-load-more'].forEach(selector => { - document.querySelectorAll(selector).forEach(item => { - item.removeAttribute('style'); - }); - }); - } - function loadMoreFacetGroups(numberOfFacetGroupsParameter) { - var _a; - let i = 0; - let numberOfHiddenBoxWithVisibleChildren = 0; - const config = buildSearchConfig(); - const numberOfFacetGroups = Number(numberOfFacetGroupsParameter || ((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets)); - document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach(item => { - const visibleChildren = item === null || item === void 0 ? void 0 : item.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]'); - if (i < numberOfFacetGroups && visibleChildren.length > 0) { - item === null || item === void 0 ? void 0 : item.setAttribute('style', 'display: block'); - } - i++; - numberOfHiddenBoxWithVisibleChildren += visibleChildren.length > 0 ? 1 : 0; - }); - const currentSearchRequestState = getCurrentSearchRequestState(); - const loadMoreFacetGroupsElement = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - const numberOfHiddenBoxes = document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length; - if (numberOfHiddenBoxes === 0 || numberOfHiddenBoxWithVisibleChildren === 0) { - loadMoreFacetGroupsElement === null || loadMoreFacetGroupsElement === void 0 ? void 0 : loadMoreFacetGroupsElement.classList.add('blm-hide'); - } - } - function getLoadMoreFacetGroupsElement() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const element = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - invariant(element, 'the element for loading more facet groups must be in the DOM'); - return element; - } - function resetFacetGroups() { - var _a, _b, _c; - const config = buildSearchConfig(); - const numberOfDisplayedFacetGroups = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets); - const numberOfDisplayedFacetValues = Number((_b = config.search) === null || _b === void 0 ? void 0 : _b.initial_number_of_facet_values); - hideAllDynamicFacetGroups(); - loadMoreFacetGroups(numberOfDisplayedFacetGroups - 1); - // init facet items visibility - document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${numberOfDisplayedFacetValues})`).forEach(item => item.style.display = 'block'); - (_c = getLoadMoreFacetGroupsElement()) === null || _c === void 0 ? void 0 : _c.removeAttribute('style'); - } - function getAutosuggestSearchInputElement() { - const config = buildAutosuggestConfig(); - if (!config.autosuggest) return null; - invariant(config.autosuggest.selector, 'the selector of search results container element must be set'); - const autosuggestInputElement = document.querySelector(config.autosuggest.selector); - return autosuggestInputElement; - } - function getAutosuggestResultsContainerElement() { - const autosuggestResultsContainerElement = document.querySelector('.blm-autosuggest-search-results'); - return autosuggestResultsContainerElement; - } - function getAutosuggestDynamicStyle() { - const autosuggestResultsContainerElement = document.querySelector('#blm-autosuggest-dynamic-style'); - return autosuggestResultsContainerElement; - } - function injectAutosuggestElements() { - var _a; - const searchInput = getAutosuggestSearchInputElement(); - autosuggestLog('Will inject autosuggest elements for:', searchInput); - if (!searchInput || !searchInput.parentElement) return; - if (!getAutosuggestDynamicStyle()) { - const searchResultsContainerStyles = document.createElement('style'); - searchResultsContainerStyles.id = '#blm-autosuggest-dynamic-style'; - searchResultsContainerStyles.innerHTML = `.blm-autosuggest-search-results { - width: 100%; - position: absolute; - z-index: 100; - left: 0; - transform: translateY(${(_a = searchInput.offsetHeight) !== null && _a !== void 0 ? _a : 35}px); - }`; - document.head.appendChild(searchResultsContainerStyles); - autosuggestLog.verbose('Added custom style tag', searchResultsContainerStyles); - } - if (!getAutosuggestResultsContainerElement()) { - const searchResultsContainerElement = document.createElement('div'); - searchResultsContainerElement.classList.add('blm-autosuggest-search-results'); - searchInput.parentElement.appendChild(searchResultsContainerElement); - autosuggestLog.verbose('Added search results container:', searchResultsContainerElement); - } - } - function removeAutosuggestElements() { - const searchResultsContainerElement = getAutosuggestResultsContainerElement(); - autosuggestLog('Will remove container:', searchResultsContainerElement); - searchResultsContainerElement === null || searchResultsContainerElement === void 0 ? void 0 : searchResultsContainerElement.remove(); - const searchResultsContainerStyles = getAutosuggestDynamicStyle(); - autosuggestLog('Will remove style:', searchResultsContainerStyles); - searchResultsContainerStyles === null || searchResultsContainerStyles === void 0 ? void 0 : searchResultsContainerStyles.remove(); - } - - var breakpoints; - (function (breakpoints) { - breakpoints["small"] = "480px"; - breakpoints["medium"] = "680px"; - breakpoints["large"] = "750px"; - breakpoints["xlarge"] = "875px"; - breakpoints["xxlarge"] = "1000px"; - breakpoints["xxxlarge"] = "1200px"; - })(breakpoints || (breakpoints = {})); - window.matchMedia(`(max-width: ${breakpoints.medium})`); - window.matchMedia(`(min-width:${breakpoints.medium}) and (max-width: ${breakpoints.xlarge})`); - - const log$1 = Debug('br:url'); - function updateUrl(urlParameters) { - var _a, _b, _c, _d; - const historyStateObject = {}; - // eslint-disable-next-line functional/no-loop-statement - for (const pair of urlParameters.entries()) { - historyStateObject[pair[0]] = pair[1]; - } - window.history.pushState(historyStateObject, document.title, `?${urlParameters.toString()}`); - const br_data = window.br_data || {}; - if (br_data.orig_ref_url !== location.href) { - br_data.orig_ref_url = location.href; - log$1('Generating virtual page view event for url update', location.href); - (_b = (_a = window.BrTrk) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.updateBrData(br_data); - (_d = (_c = window.BrTrk) === null || _c === void 0 ? void 0 : _c.getTracker()) === null || _d === void 0 ? void 0 : _d.logPageView(); - } - } - function updateParameterInUrl(parameterName, newValue) { - const urlParameters = new URLSearchParams(window.location.search); - if (typeof newValue === 'function') { - urlParameters.set(parameterName, - // @ts-ignore - newValue(urlParameters.get(parameterName)).replace(/"/g, '\\"')); - } else if (newValue === '') { - urlParameters.delete(parameterName); - } else { - urlParameters.set(parameterName, newValue.replace(/"/g, '\\"')); - } - updateUrl(urlParameters); - } - - const categoryLinkElementClickListener = event => { - var _a, _b, _c; - event.preventDefault(); - const clickedElement = event.target; - const categoryId = ((_a = clickedElement.dataset) === null || _a === void 0 ? void 0 : _a.categoryId) || ''; - const module = ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.search) || ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category); - if (module) { - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - module.load(categoryId).then(() => { - const autosuggestSearchElement = getAutosuggestSearchInputElement(); - const autosuggestResultsElement = getAutosuggestResultsContainerElement(); - if (autosuggestSearchElement) { - autosuggestSearchElement.value = (clickedElement === null || clickedElement === void 0 ? void 0 : clickedElement.textContent) || ''; - } - if (autosuggestResultsElement) { - autosuggestResultsElement.innerHTML = ''; - } - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - return true; - }).catch(console.error); - } - }; - function addCategoryLinkElementClickListener() { - var _a; - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link--category').forEach(categoryLinkElement => { - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.removeEventListener('click', categoryLinkElementClickListener); - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.addEventListener('click', categoryLinkElementClickListener); - }); - } - - let scheduleSubmission = false; - const formFocusListener = () => { - scheduleSubmission = true; - }; - const formBlurListener = () => { - scheduleSubmission = false; - }; - const formElementSubmitListener = () => { - var _a, _b, _c; - scheduleSubmission = false; - const searchData = { - q: (_a = getAutosuggestSearchInputElement()) === null || _a === void 0 ? void 0 : _a.value - // catalogs: [{name: 'example_en'}] - }; - - (_c = (_b = window.BrTrk || {}) === null || _b === void 0 ? void 0 : _b.getTracker()) === null || _c === void 0 ? void 0 : _c.logEvent('suggest', 'submit', searchData, {}, true); - }; - /** - * We listen to the window unload event to see if the user left the page without - * the form submit listener executing properly. This has been seen to happen - * when the user presses enter instead of clicking the submit button in some - * contexts. - */ - const windowUnloadListener = () => { - if (scheduleSubmission) { - formElementSubmitListener(); - } - }; - function addFormElementSubmitListener() { - const suggestElement = getAutosuggestSearchInputElement(); - if (!suggestElement) return; - const element = findUpElementByTagName(suggestElement, 'form'); - if (!element) return; - // NOTES: Our environments this is deployed to is largely unknown. The only - // known we are given is the text input provided to us. We can hope it is in a - // form for which we can gracefully handle the submission event. But if the - // submissions are circumvented by using other means for submission, we can - // only rely on our little input and it's focus state. Essentially, if the - // element is in focus and our window is loading to a new page, that is our - // most reliable indicator of capturing things like enter key being pressed or - // other odds and end. - // Add listeners in re-entrant fashion - element === null || element === void 0 ? void 0 : element.removeEventListener('submit', formElementSubmitListener, true); - suggestElement === null || suggestElement === void 0 ? void 0 : suggestElement.removeEventListener('focus', formFocusListener, { - capture: true - }); - suggestElement === null || suggestElement === void 0 ? void 0 : suggestElement.removeEventListener('blur', formBlurListener, { - capture: true - }); - window.removeEventListener('beforeunload', windowUnloadListener, true); - element === null || element === void 0 ? void 0 : element.addEventListener('submit', formElementSubmitListener, true); - suggestElement === null || suggestElement === void 0 ? void 0 : suggestElement.addEventListener('focus', formFocusListener, { - capture: true - }); - suggestElement === null || suggestElement === void 0 ? void 0 : suggestElement.addEventListener('blur', formBlurListener, { - capture: true - }); - window.addEventListener('beforeunload', windowUnloadListener, true); - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - - function isObject$2(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - var isObject_1 = isObject$2; - - /** Detect free variable `global` from Node.js. */ - - var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; - - var _freeGlobal = freeGlobal$1; - - var freeGlobal = _freeGlobal; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root$2 = freeGlobal || freeSelf || Function('return this')(); - - var _root = root$2; - - var root$1 = _root; - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now$1 = function() { - return root$1.Date.now(); - }; - - var now_1 = now$1; - - /** Used to match a single whitespace character. */ - - var reWhitespace = /\s/; - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ - function trimmedEndIndex$1(string) { - var index = string.length; - - while (index-- && reWhitespace.test(string.charAt(index))) {} - return index; - } - - var _trimmedEndIndex = trimmedEndIndex$1; - - var trimmedEndIndex = _trimmedEndIndex; - - /** Used to match leading whitespace. */ - var reTrimStart = /^\s+/; - - /** - * The base implementation of `_.trim`. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function baseTrim$1(string) { - return string - ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') - : string; - } - - var _baseTrim = baseTrim$1; - - var root = _root; - - /** Built-in value references. */ - var Symbol$2 = root.Symbol; - - var _Symbol = Symbol$2; - - var Symbol$1 = _Symbol; - - /** Used for built-in method references. */ - var objectProto$1 = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto$1.hasOwnProperty; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString$1 = objectProto$1.toString; - - /** Built-in value references. */ - var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag$1(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; - } - - var _getRawTag = getRawTag$1; - - /** Used for built-in method references. */ - - var objectProto = Object.prototype; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString$1(value) { - return nativeObjectToString.call(value); - } - - var _objectToString = objectToString$1; - - var Symbol = _Symbol, - getRawTag = _getRawTag, - objectToString = _objectToString; - - /** `Object#toString` result references. */ - var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - - /** Built-in value references. */ - var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag$1(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - var _baseGetTag = baseGetTag$1; - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - - function isObjectLike$1(value) { - return value != null && typeof value == 'object'; - } - - var isObjectLike_1 = isObjectLike$1; - - var baseGetTag = _baseGetTag, - isObjectLike = isObjectLike_1; - - /** `Object#toString` result references. */ - var symbolTag = '[object Symbol]'; - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol$1(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - var isSymbol_1 = isSymbol$1; - - var baseTrim = _baseTrim, - isObject$1 = isObject_1, - isSymbol = isSymbol_1; - - /** Used as references for various `Number` constants. */ - var NAN = 0 / 0; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Built-in method references without a dependency on `root`. */ - var freeParseInt = parseInt; - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber$1(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject$1(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject$1(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - var toNumber_1 = toNumber$1; - - var isObject = isObject_1, - now = now_1, - toNumber = toNumber_1; - - /** Error message constants. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max, - nativeMin = Math.min; - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. 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 debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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's 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 clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - var debounce_1 = debounce; - - const searchInputElementBlurListener = () => { - if (getCurrentAutosuggestUiState().mouseDownEventHappenedInsideAutosuggestResultsContainer) { - updateCurrentAutosuggestUiState({ - mouseDownEventHappenedInsideAutosuggestResultsContainer: false - }); - return false; - } - const containerElement = getAutosuggestResultsContainerElement(); - if (!containerElement) return; - containerElement.innerHTML = ''; - return true; - }; - const generalClickListenerForSearchInputBlur = event => { - if (!event.target || !(event.target instanceof HTMLElement)) return; - const clickHappenedOnInputOrAutosuggestResultsPanel = findUpElementWithClassName(event.target, 'blm-autosuggest'); - if (clickHappenedOnInputOrAutosuggestResultsPanel) { - updateCurrentAutosuggestUiState({ - mouseDownEventHappenedInsideAutosuggestResultsContainer: true - }); - } else { - const containerElement = getAutosuggestResultsContainerElement(); - if (!containerElement) return; - containerElement.innerHTML = ''; - } - }; - const searchInputElementFocusListener = () => { - const lastTemplateData = getCurrentAutosuggestRequestState().last_template_data; - getCurrentAutosuggestRequestState(); - if (lastTemplateData) { - const containerElement = getAutosuggestResultsContainerElement(); - if (!containerElement) return; - containerElement.innerHTML = ejs.render(autosuggestTemplate, lastTemplateData); - } - }; - const searchInputElementKeyupListener = debounce_1(event => { - const query = event.target.value; - const searchInputElement = getAutosuggestSearchInputElement(); - if (!searchInputElement) return; - if (query.length >= AUTOSUGGEST_MINIMUM_QUERY_LENGTH) { - searchInputElement.dataset.originalQuery = query; - suggest(query).catch(console.error); - } else { - const autosuggestResultsContainerElement = getAutosuggestResultsContainerElement(); - if (autosuggestResultsContainerElement) { - autosuggestResultsContainerElement.innerHTML = ''; - } - searchInputElement.dataset.originalQuery = ''; - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - } - }, 500); - function addSearchInputElementBlurListener() { - // Add listeners in re-entrant fashion - document.body.removeEventListener('mousedown', generalClickListenerForSearchInputBlur); - document.body.addEventListener('mousedown', generalClickListenerForSearchInputBlur); - const element = getAutosuggestSearchInputElement(); - if (!element) return; - element.removeEventListener('blur', searchInputElementBlurListener); - element.addEventListener('blur', searchInputElementBlurListener); - } - function addSearchInputElementFocusListener() { - const element = getAutosuggestSearchInputElement(); - if (!element) return; - // Add listeners in re-entrant fashion - element.removeEventListener('focus', searchInputElementFocusListener); - element.addEventListener('focus', searchInputElementFocusListener); - } - function addSearchInputElementChangeListener() { - const element = getAutosuggestSearchInputElement(); - // Add listeners in re-entrant fashion - element === null || element === void 0 ? void 0 : element.removeEventListener('input', searchInputElementKeyupListener); - element === null || element === void 0 ? void 0 : element.addEventListener('input', searchInputElementKeyupListener); - } - function addSearchInputElementListeners() { - addSearchInputElementBlurListener(); - addSearchInputElementFocusListener(); - addSearchInputElementChangeListener(); - } - - const listeners = new WeakMap(); - const suggestionTermElementClickListener = suggestionTermElement => { - return () => { - var _a, _b; - const { - suggestionText - } = suggestionTermElement.dataset; - const input = getAutosuggestSearchInputElement(); - if (!input) return; - const { - originalQuery - } = input.dataset; - const suggestionData = { - aq: originalQuery, - q: suggestionText, - catalogs: [{ - name: 'example_en' - }] - }; - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('suggest', 'click', suggestionData, {}, true); - }; - }; - function addSuggestionTermElementClickListener() { - var _a; - // Apply listeners in re-entrant fashion - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link').forEach(suggestionTermElement => { - const listener = suggestionTermElementClickListener(suggestionTermElement); - const old = listeners.get(suggestionTermElement); - if (old) suggestionTermElement.removeEventListener('click', old); - listeners.set(suggestionTermElement, listener); - suggestionTermElement === null || suggestionTermElement === void 0 ? void 0 : suggestionTermElement.addEventListener('click', listener); - }); - } - - function mapAutosuggestApiResponse(responseData) { - return isV2Response(responseData) ? mapV2Response(responseData) : mapV1Response(responseData); - } - function mapV2Response(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j; - const config = buildAutosuggestConfig(); - const productSuggestions = ((_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.searchSuggestions) || []; - const suggestions = ((_d = (_c = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.querySuggestions) || []; - const categorySuggestions = ((_f = (_e = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.attributeSuggestions) || []; - const mappedApiResponse = Object.assign(Object.assign({}, ((_g = responseData === null || responseData === void 0 ? void 0 : responseData.queryContext) === null || _g === void 0 ? void 0 : _g.originalQuery) ? { - originalQuery: responseData.queryContext.originalQuery - } : {}), { - terms: [...suggestions.map((term, index) => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.query, - displayText: term.displayText, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.query)}` - }), index === 0 && categorySuggestions ? { - categories: categorySuggestions.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.attributeType - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - })].slice(0, (_h = config.autosuggest) === null || _h === void 0 ? void 0 : _h.number_of_terms), - productSuggestions: [...productSuggestions.map(product => Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: Number((product === null || product === void 0 ? void 0 : product.sale_price) || '0') - }))].slice(0, (_j = config.autosuggest) === null || _j === void 0 ? void 0 : _j.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function isV2Response(responseData) { - return 'suggestionGroups' in responseData; - } - function mapV1Response(responseData) { - var _a, _b; - const config = buildAutosuggestConfig(); - const mappedApiResponse = Object.assign(Object.assign({}, responseData.response.q ? { - originalQuery: responseData.response.q - } : {}), { - terms: [...(responseData.response.suggestions ? responseData.response.suggestions.map(term => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.q, - displayText: term.dq, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.q)}` - }), term.filters ? { - categories: term.filters.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.key - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - }) : [])].slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_terms), - productSuggestions: [...(responseData.response.products ? responseData.response.products.map(product => Object.assign(Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: !Number.isNaN(product.sale_price) ? product.sale_price : !Number.isNaN(product.price) ? product.price : '0' - }), 'price' in product && 'sale_price' in product ? { - price: product.price - } : {})) : [])].slice(0, (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function highlightQueryInTermLabels(results) { - const processedResults = Object.assign({}, results); - results.terms.forEach((term, index) => { - const typedQueryHtml = ejs.render(AUTOSUGGEST_TYPED_QUERY_TEMPLATE, { - query: results.originalQuery - }).trim(); - (processedResults.terms[index] || {}).processedText = term.text.replace(results.originalQuery || '', typedQueryHtml); - }); - return processedResults; - } - - const log = Debug('br:autosuggest'); - function buildAutosuggestModule() { - log('Build Autosuggest Module:', '4.0.0'); - let currentAutosuggestRequestState = { - request_id: 0, - last_template_data: null, - currentElement: null, - pollIntervalId: null - }; - let currentAutosuggestUiState = { - mouseDownEventHappenedInsideAutosuggestResultsContainer: false - }; - return { - setCurrentAutosuggestRequestState: requestState => { - currentAutosuggestRequestState = requestState; - }, - getCurrentAutosuggestRequestState: () => currentAutosuggestRequestState, - setCurrentAutosuggestUiState: uiState => { - currentAutosuggestUiState = uiState; - }, - getCurrentAutosuggestUiState: () => currentAutosuggestUiState, - load: async () => { - initPolling(); - }, - unload: () => { - var _a; - const state = getCurrentAutosuggestRequestState(); - window.clearInterval((_a = state.pollIntervalId) !== null && _a !== void 0 ? _a : void 0); - moduleWillUnmount(); - } - }; - } - /** - * We poll for the element in the DOM that is required to be present for - * this module to work to make itself available. We perform polling as we - * do not want to examine broad swathes of mutatations and we can not - * assume the element in question is readily available on the page. We - * also perform the poll to examine the element for moments it may or may - * not be removed from the DOM which can trigger this module to pause and - * reinitialize if the DOM element makes itself available again. Lastly, a - * polling routine with a simple query selector will be minimally taxing - * on the UI and keep it responsive. - */ - function initPolling() { - var _a; - let state = getCurrentAutosuggestRequestState(); - window.clearInterval((_a = state.pollIntervalId) !== null && _a !== void 0 ? _a : void 0); - const doPoll = () => { - state = getCurrentAutosuggestRequestState(); - const currentElement = state.currentElement; - const foundElement = getAutosuggestSearchInputElement(); - if (currentElement && !foundElement) { - // Teardown this module to put it in a waiting state - updateCurrentAutosuggestRequestState({ - currentElement: null - }); - moduleWillUnmount(); - } else if (!currentElement && foundElement) { - updateCurrentAutosuggestRequestState({ - currentElement: foundElement - }); - moduleWillMount(); - } - }; - if (!state.pollIntervalId) log('Polling initialized'); - // Begin the polling service. - const pollTimer = window.setInterval(doPoll, 100); - updateCurrentAutosuggestRequestState({ - pollIntervalId: pollTimer - }); - // We execute the poll immediately so if we have a script that is "smarter" - // about when all conditions are ready for the module, there is a path to have - // an immediate initialization. - doPoll(); - } - /** - * Lifecycle: - * When the conditions for the module to operate are no longer met, this will - * perform all the necessary teardowns to ensure the module is not operating or - * modifying the page and puts the module in a dormant state. Polling may still - * be in place to trigger a reinitialization of the module if the conditions - * are met again. Use "unload" to stop polling from automatic reinitialization. - */ - function moduleWillUnmount() { - log('Unmounting Module'); - removeAutosuggestElements(); - } - /** - * Lifecycle: - * When the module has been requested to load and the conditions on - * the page are met to allow the module to operate, this module will mount and - * initialize everything it needs to operate and modify any elements on the page - * that appear. - */ - function moduleWillMount() { - var _a, _b; - log('Mounting Module'); - try { - injectAutosuggestElements(); - } catch (err) { - log((err === null || err === void 0 ? void 0 : err.stack) || (err === null || err === void 0 ? void 0 : err.message)); - } - try { - areRequirementsMet(); - } catch (err) { - log('Requirements not met, aborting'); - moduleWillUnmount(); - return; - } - addSearchInputElementListeners(); - addFormElementSubmitListener(); - (_a = getAutosuggestSearchInputElement()) === null || _a === void 0 ? void 0 : _a.setAttribute('autocomplete', 'off'); - (_b = getAutosuggestSearchInputElement()) === null || _b === void 0 ? void 0 : _b.setAttribute('aria-autocomplete', 'off'); - } - /** - * Retrieves suggestions from the suggest API and renders them to the DOM. - */ - async function suggest(query) { - var _a, _b, _c; - log('Fetching suggestions for', query); - const config = buildAutosuggestConfig(); - updateCurrentAutosuggestRequestState({ - request_id: generateRequestId() - }); - const apiCallParameters = buildApiCallParameters(query); - // todo remediate typescript issue - // @ts-ignore - const results = await getSuggestions(apiCallParameters); - const templateData = mapAutosuggestApiResponse(results); - updateCurrentAutosuggestRequestState({ - last_template_data: templateData - }); - const container = getAutosuggestResultsContainerElement(); - if (!container) return; - log.verbose('Using config', config); - log.verbose('Render to:', container); - log.verbose('Is using default template?', !((_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.template)); - log.verbose('Rendering with template:', { - template: ((_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.template) || autosuggestTemplate, - templateData - }); - container.innerHTML = ejs.render(((_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.template) || autosuggestTemplate, templateData); - addCategoryLinkElementClickListener(); - addSuggestionTermElementClickListener(); - } - /** - * Generates the API paramters fed into the suggest API call body. - */ - function buildApiCallParameters(query) { - var _a, _b, _c; - const config = buildAutosuggestConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentAutosuggestRequestState = getCurrentAutosuggestRequestState(); - const apiParameters = Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.autosuggest) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.autosuggest.endpoint - } : {}), { - q: query || urlParameters.get((config === null || config === void 0 ? void 0 : config.default_search_parameter) || '') || '', - aq: query, - sort: (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.sort, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentAutosuggestRequestState.request_id, - _br_uid_2: config.tracking_cookie, - ref_url: config.ref_url, - url: config.url, - request_type: config.request_type, - catalog_views: (_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.catalog_views, - search_type: 'keyword' - }); - if (!apiParameters.catalog_views) { - apiParameters.catalog_views = ''; - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === undefined) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function getCurrentAutosuggestRequestState() { - return window.BloomreachModules.autosuggest.getCurrentAutosuggestRequestState(); - } - function updateCurrentAutosuggestRequestState(state) { - window.BloomreachModules.autosuggest.setCurrentAutosuggestRequestState(Object.assign(Object.assign({}, getCurrentAutosuggestRequestState()), state)); - } - function getCurrentAutosuggestUiState() { - return window.BloomreachModules.autosuggest.getCurrentAutosuggestUiState(); - } - function updateCurrentAutosuggestUiState(state) { - window.BloomreachModules.autosuggest.setCurrentAutosuggestUiState(Object.assign(Object.assign({}, getCurrentAutosuggestUiState()), state)); - } - /** - * This examines all of the pieces to ensure after - */ - function areRequirementsMet() { - var _a; - const config = buildAutosuggestConfig(); - const check = { - account_id: config.account_id, - domain_key: config.domain_key, - searchInputElement: getAutosuggestSearchInputElement(), - resultsContainer: getAutosuggestResultsContainerElement(), - enabled: (_a = config === null || config === void 0 ? void 0 : config.autosuggest) === null || _a === void 0 ? void 0 : _a.enabled - }; - log('Checking requirements', check); - invariant(check.account_id, 'account_id must be set'); - invariant(check.domain_key, 'domain_key must be set'); - return check.enabled; - } - - Debug('br:product-events'); - - Debug('br:recommendations'); - - debounce_1(event => { - var _a; - const inputValue = (((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) || '').trim(); - document.querySelectorAll('.blm-dynamic-filter').forEach(facetBox => { - let displayedItems = 0; - facetBox.querySelectorAll('.blm-product-search-filter-item').forEach(facetItem => { - var _a; - const label = ((_a = facetItem.querySelector('label')) === null || _a === void 0 ? void 0 : _a.textContent) || ''; - const shouldDisplay = !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()); - const displayStyle = shouldDisplay ? 'block' : 'none'; - displayedItems += shouldDisplay ? 1 : 0; - facetItem.style.display = displayStyle; - }); - facetBox.style.display = displayedItems ? 'block' : 'none'; - }); - document.querySelectorAll('.blm-product-search-load-more').forEach(loadMoreLink => { - loadMoreLink.style.display = 'none'; - }); - const groupsELement = getLoadMoreFacetGroupsElement(); - if (!groupsELement) return; - groupsELement.style.display = 'none'; - if (!inputValue) { - resetFacetGroups(); - } - }, 500); - - Debug('br:search'); - function buildDefaultSearchRequestState(options) { - const { - isCategoryPage - } = options; - return { - request_id: 0, - price_range_max_value: 0, - price_range_min_value: 0, - is_first_request: true, - is_category_page: isCategoryPage, - category_to_load: '', - pollIntervalId: void 0, - currentElement: null - }; - } - /** - * Attempts to get the search request state from the existing module - */ - function getCurrentSearchRequestState() { - var _a, _b, _c; - return ((_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.getCurrentSearchRequestState()) || buildDefaultSearchRequestState({ - isCategoryPage: false - }); - } - - const autosuggestModule = buildAutosuggestModule(); - window.BloomreachModules = Object.assign(Object.assign({}, globalBloomreachModules), { - autosuggest: autosuggestModule - }); - autosuggestModule.load().catch(console.error); - -})(); +var t=o,n=b,r=y,s=!1,i=w,a="locals",u=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],c=u.concat("cache"),l=/^\uFEFF/,g=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/;function d(n,r){var o;if(r.some((function(r){return o=e.resolveInclude(n,r,!0),t.existsSync(o)})))return o}function f(t,n){var r,o=t.filename,s=arguments.length>1;if(t.cache){if(!o)throw new Error("cache option requires a filename");if(r=e.cache.get(o))return r;s||(n=p(o).toString().replace(l,""))}else if(!s){if(!o)throw new Error("Internal EJS error: no file name or template provided");n=p(o).toString().replace(l,"")}return r=e.compile(n,t),t.cache&&e.cache.set(o,r),r}function p(t){return e.fileLoader(t)}function m(n,o){var s=r.shallowCopy(r.createNullProtoObjWherePossible(),o);if(s.filename=function(n,r){var o,s,i=r.views,a=/^[A-Za-z]+:\\|^\//.exec(n);if(a&&a.length)n=n.replace(/^\/*/,""),o=Array.isArray(r.root)?d(n,r.root):e.resolveInclude(n,r.root||"/",!0);else if(r.filename&&(s=e.resolveInclude(n,r.filename),t.existsSync(s)&&(o=s)),!o&&Array.isArray(i)&&(o=d(n,i)),!o&&"function"!=typeof r.includer)throw new Error('Could not find the include file "'+r.escapeFunction(n)+'"');return o}(n,s),"function"==typeof o.includer){var i=o.includer(n,s.filename);if(i&&(i.filename&&(s.filename=i.filename),i.template))return f(s,i.template)}return f(s)}function h(e,t,n,r,o){var s=t.split("\n"),i=Math.max(r-3,0),a=Math.min(s.length,r+3),u=o(n),c=s.slice(i,a).map((function(e,t){var n=t+i+1;return(n==r?" >> ":" ")+n+"| "+e})).join("\n");throw e.path=u,e.message=(u||"ejs")+":"+r+"\n"+c+"\n\n"+e.message,e}function v(e){return e.replace(/;(\s*$)/,"$1")}function _(t,n){var o=r.hasOwnOnlyObject(n),s=r.createNullProtoObjWherePossible();this.templateText=t,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",s.client=o.client||!1,s.escapeFunction=o.escape||o.escapeFunction||r.escapeXML,s.compileDebug=!1!==o.compileDebug,s.debug=!!o.debug,s.filename=o.filename,s.openDelimiter=o.openDelimiter||e.openDelimiter||"<",s.closeDelimiter=o.closeDelimiter||e.closeDelimiter||">",s.delimiter=o.delimiter||e.delimiter||"%",s.strict=o.strict||!1,s.context=o.context,s.cache=o.cache||!1,s.rmWhitespace=o.rmWhitespace,s.root=o.root,s.includer=o.includer,s.outputFunctionName=o.outputFunctionName,s.localsName=o.localsName||e.localsName||a,s.views=o.views,s.async=o.async,s.destructuredLocals=o.destructuredLocals,s.legacyInclude=void 0===o.legacyInclude||!!o.legacyInclude,s.strict?s._with=!1:s._with=void 0===o._with||o._with,this.opts=s,this.regex=this.createRegex()}e.cache=r.cache,e.fileLoader=t.readFileSync,e.localsName=a,e.promiseImpl=new Function("return this;")().Promise,e.resolveInclude=function(e,t,r){var o=n.dirname,s=n.extname,i=(0,n.resolve)(r?t:o(t),e);return s(e)||(i+=".ejs"),i},e.compile=function(e,t){return t&&t.scope&&(s||(console.warn("`scope` option is deprecated and will be removed in EJS 3"),s=!0),t.context||(t.context=t.scope),delete t.scope),new _(e,t).compile()},e.render=function(e,t,n){var o=t||r.createNullProtoObjWherePossible(),s=n||r.createNullProtoObjWherePossible();return 2==arguments.length&&r.shallowCopyFromList(s,o,u),f(s,e)(o)},e.renderFile=function(){var t,n,o,s=Array.prototype.slice.call(arguments),i=s.shift(),a={filename:i};return"function"==typeof arguments[arguments.length-1]&&(t=s.pop()),s.length?(n=s.shift(),s.length?r.shallowCopy(a,s.pop()):(n.settings&&(n.settings.views&&(a.views=n.settings.views),n.settings["view cache"]&&(a.cache=!0),(o=n.settings["view options"])&&r.shallowCopy(a,o)),r.shallowCopyFromList(a,n,c)),a.filename=i):n=r.createNullProtoObjWherePossible(),function(t,n,r){var o;if(!r){if("function"==typeof e.promiseImpl)return new e.promiseImpl((function(e,r){try{e(o=f(t)(n))}catch(e){r(e)}}));throw new Error("Please provide a callback function")}try{o=f(t)(n)}catch(e){return r(e)}r(null,o)}(a,n,t)},e.Template=_,e.clearCache=function(){e.cache.reset()},_.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},_.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=r.escapeRegExpChars(this.opts.delimiter),n=r.escapeRegExpChars(this.opts.openDelimiter),o=r.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,o),new RegExp(e)},compile:function(){var e,t,o,s=this.opts,i="",a="",u=s.escapeFunction,c=s.filename?JSON.stringify(s.filename):"undefined";if(!this.source){if(this.generateSource(),i+=' var __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n',s.outputFunctionName){if(!g.test(s.outputFunctionName))throw new Error("outputFunctionName is not a valid JS identifier.");i+=" var "+s.outputFunctionName+" = __append;\n"}if(s.localsName&&!g.test(s.localsName))throw new Error("localsName is not a valid JS identifier.");if(s.destructuredLocals&&s.destructuredLocals.length){for(var l=" var __locals = ("+s.localsName+" || {}),\n",d=0;d0&&(l+=",\n "),l+=f+" = __locals."+f}i+=l+";\n"}!1!==s._with&&(i+=" with ("+s.localsName+" || {}) {\n",a+=" }\n"),a+=" return __output;\n",this.source=i+this.source+a}e=s.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+c+";\ntry {\n"+this.source+"} catch (e) {\n rethrow(e, __lines, __filename, __line, escapeFn);\n}\n":this.source,s.client&&(e="escapeFn = escapeFn || "+u.toString()+";\n"+e,s.compileDebug&&(e="rethrow = rethrow || "+h.toString()+";\n"+e)),s.strict&&(e='"use strict";\n'+e),s.debug&&console.log(e),s.compileDebug&&s.filename&&(e=e+"\n//# sourceURL="+c+"\n");try{if(s.async)try{o=new Function("return (async function(){}).constructor;")()}catch(e){throw e instanceof SyntaxError?new Error("This environment does not support async/await"):e}else o=Function;t=new o(s.localsName+", escapeFn, include, rethrow",e)}catch(e){throw e instanceof SyntaxError&&(s.filename&&(e.message+=" in "+s.filename),e.message+=" while compiling ejs\n\n",e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n",e.message+="https://github.com/RyanZim/EJS-Lint",s.async||(e.message+="\n",e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}var p=s.client?t:function(e){return t.apply(s.context,[e||r.createNullProtoObjWherePossible(),u,function(t,n){var o=r.shallowCopy(r.createNullProtoObjWherePossible(),e);return n&&(o=r.shallowCopy(o,n)),m(t,s)(o)},h])};if(s.filename&&"function"==typeof Object.defineProperty){var v=s.filename,_=n.basename(v,n.extname(v));try{Object.defineProperty(p,"name",{value:_,writable:!1,enumerable:!1,configurable:!0})}catch(e){}}return p},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")),this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var e=this,t=this.parseTemplateText(),n=this.opts.delimiter,r=this.opts.openDelimiter,o=this.opts.closeDelimiter;t&&t.length&&t.forEach((function(s,i){var a;if(0===s.indexOf(r+n)&&0!==s.indexOf(r+n+n)&&(a=t[i+2])!=n+o&&a!="-"+n+o&&a!="_"+n+o)throw new Error('Could not find matching close tag for "'+s+'".');e.scanLine(s)}))},parseTemplateText:function(){for(var e,t=this.templateText,n=this.regex,r=n.exec(t),o=[];r;)0!==(e=r.index)&&(o.push(t.substring(0,e)),t=t.slice(e)),o.push(r[0]),t=t.slice(r[0].length),r=n.exec(t);return t&&o.push(t),o},_addOutput:function(e){if(this.truncate&&(e=e.replace(/^(?:\r\n|\r|\n)/,""),this.truncate=!1),!e)return e;e=(e=(e=(e=e.replace(/\\/g,"\\\\")).replace(/\n/g,"\\n")).replace(/\r/g,"\\r")).replace(/"/g,'\\"'),this.source+=' ; __append("'+e+'")\n'},scanLine:function(e){var t,n=this.opts.delimiter,r=this.opts.openDelimiter,o=this.opts.closeDelimiter;switch(t=e.split("\n").length-1,e){case r+n:case r+n+"_":this.mode=_.modes.EVAL;break;case r+n+"=":this.mode=_.modes.ESCAPED;break;case r+n+"-":this.mode=_.modes.RAW;break;case r+n+"#":this.mode=_.modes.COMMENT;break;case r+n+n:this.mode=_.modes.LITERAL,this.source+=' ; __append("'+e.replace(r+n+n,r+n)+'")\n';break;case n+n+o:this.mode=_.modes.LITERAL,this.source+=' ; __append("'+e.replace(n+n+o,n+o)+'")\n';break;case n+o:case"-"+n+o:case"_"+n+o:this.mode==_.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=0===e.indexOf("-")||0===e.indexOf("_");break;default:if(this.mode){switch(this.mode){case _.modes.EVAL:case _.modes.ESCAPED:case _.modes.RAW:e.lastIndexOf("//")>e.lastIndexOf("\n")&&(e+="\n")}switch(this.mode){case _.modes.EVAL:this.source+=" ; "+e+"\n";break;case _.modes.ESCAPED:this.source+=" ; __append(escapeFn("+v(e)+"))\n";break;case _.modes.RAW:this.source+=" ; __append("+v(e)+")\n";break;case _.modes.COMMENT:break;case _.modes.LITERAL:this._addOutput(e)}}else this._addOutput(e)}this.opts.compileDebug&&t&&(this.currentLine+=t,this.source+=" ; __line = "+this.currentLine+"\n")}},e.escapeXML=r.escapeXML,e.__express=e.renderFile,e.VERSION=i,e.name="ejs","undefined"!=typeof window&&(window.ejs=e)}(r);var O="Invariant failed";function j(e,t){if(!e)throw new Error(O)}const x=2,L='<%= query %>',E="$",A="q",S=8,T=8,C=4,N="page",k="suggest",M=".search__input";const D={method:"GET",headers:{"Content-Type":"application/json"}};function F(){const e=document.cookie.split("; ").find((e=>e.startsWith("_br_uid_2=")));return e?e.replace("_br_uid_2=",""):"uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55"}const q=(e,t="$",n=!0)=>`${n?t:""}${(e/100).toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2})}${n?"":` ${t}`}`;function P(){return Math.floor(1e12+9e12*Math.random())}const R="https://suggest.dxpapi.com/api/v2/suggest/",$=["_br_uid_2","fq","sort"];function I(e){const t=Object.assign({},e),n=(null==t?void 0:t.endpoint)||R;return(null==t?void 0:t.endpoint)&&(null==t||delete t.endpoint),`${n}${r=t,`?${Object.keys(r).reduce(((e,t)=>[...e,`${t}=${$.includes(t)?r[t]:encodeURIComponent(r[t])}`]),[]).join("&")}`}`;var r}async function W(e){return async function(e,t){const n=await fetch(e,t);return await n.json()}(I(e),D)}var H,U='<% if (terms.length || productSuggestions.length) { %>\n \n <% } %>\n';function B(){const e=function(){var e;const t=null===(e=null===window||void 0===window?void 0:window.bloomreachConnector)||void 0===e?void 0:e.config;return Object.assign({default_search_parameter:A,url:window.location.href,ref_url:window.location.href,tracking_cookie:F(),format_money:e=>q(e,window.bloomreachDefaultCurrency||E),default_currency:window.bloomreachDefaultCurrency||E},t)}();return Object.assign(Object.assign({request_type:k},e),{autosuggest:Object.assign({enabled:!0,endpoint:"",number_of_terms:C,number_of_products:T,number_of_collections:S,selector:M,template:U,catalog_views:""},e.autosuggest)})}function z(){var e;const t=B();j(null===(e=t.autosuggest)||void 0===e?void 0:e.selector);return document.querySelector(t.autosuggest.selector)}function J(){return document.querySelector(".blm-autosuggest-search-results")}function Q(e,t){const n=new URLSearchParams(window.location.search);"function"==typeof t?n.set(e,t(n.get(e)).replace(/"/g,'\\"')):""===t?n.delete(e):n.set(e,t.replace(/"/g,'\\"')),function(e){const t={};for(const n of e.entries())t[n[0]]=n[1];window.history.pushState(t,document.title,`?${e.toString()}`)}(n)}function X(){J().querySelectorAll(".blm-autosuggest__suggestion-term-link--category").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",(e=>{var t;e.preventDefault();const n=e.target,r=(null===(t=n.dataset)||void 0===t?void 0:t.categoryId)||"";window.BloomreachModules&&window.BloomreachModules.search&&(Q(N,"1"),window.BloomreachModules.search.load(r).then((()=>(z().value=(null==n?void 0:n.textContent)||"",J().innerHTML="",Re({last_template_data:null}),!0))).catch(console.error))})),e.setAttribute("hasListener","true"))}))}function G(){const e=function(e,t){let n=e;for(;n&&n.parentNode;)if(n=n.parentNode,n&&n.tagName.toLowerCase()===t.toLowerCase())return n;return null}(z(),"form");e.getAttribute("hasListener")||(e.addEventListener("submit",(()=>{var e,t;const n={q:z().value,catalogs:[{name:"example_en"}]};null===(t=null===(e=window.BrTrk||{})||void 0===e?void 0:e.getTracker())||void 0===t||t.logEvent("suggest","submit",n,{},!0)})),e.setAttribute("hasListener","true"))}!function(e){e.small="480px",e.medium="680px",e.large="750px",e.xlarge="875px",e.xxlarge="1000px",e.xxxlarge="1200px"}(H||(H={})),window.matchMedia(`(max-width: ${H.medium})`),window.matchMedia(`(min-width:${H.medium}) and (max-width: ${H.xlarge})`);var V=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)},Z="object"==typeof t&&t&&t.Object===Object&&t,K="object"==typeof self&&self&&self.Object===Object&&self,Y=Z||K||Function("return this")(),ee=Y,te=function(){return ee.Date.now()},ne=/\s/;var re=function(e){for(var t=e.length;t--&&ne.test(e.charAt(t)););return t},oe=/^\s+/;var se=function(e){return e?e.slice(0,re(e)+1).replace(oe,""):e},ie=Y.Symbol,ae=ie,ue=Object.prototype,ce=ue.hasOwnProperty,le=ue.toString,ge=ae?ae.toStringTag:void 0;var de=function(e){var t=ce.call(e,ge),n=e[ge];try{e[ge]=void 0;var r=!0}catch(e){}var o=le.call(e);return r&&(t?e[ge]=n:delete e[ge]),o},fe=Object.prototype.toString;var pe=de,me=function(e){return fe.call(e)},he=ie?ie.toStringTag:void 0;var ve=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":he&&he in Object(e)?pe(e):me(e)},_e=function(e){return null!=e&&"object"==typeof e};var be=se,ye=V,we=function(e){return"symbol"==typeof e||_e(e)&&"[object Symbol]"==ve(e)},Oe=/^[-+]0x[0-9a-f]+$/i,je=/^0b[01]+$/i,xe=/^0o[0-7]+$/i,Le=parseInt;var Ee=V,Ae=te,Se=function(e){if("number"==typeof e)return e;if(we(e))return NaN;if(ye(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=ye(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=be(e);var n=je.test(e);return n||xe.test(e)?Le(e.slice(2),n?2:8):Oe.test(e)?NaN:+e},Te=Math.max,Ce=Math.min;var Ne=function(e,t,n){var r,o,s,i,a,u,c=0,l=!1,g=!1,d=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function f(t){var n=r,s=o;return r=o=void 0,c=t,i=e.apply(s,n)}function p(e){var n=e-u;return void 0===u||n>=t||n<0||g&&e-c>=s}function m(){var e=Ae();if(p(e))return h(e);a=setTimeout(m,function(e){var n=t-(e-u);return g?Ce(n,s-(e-c)):n}(e))}function h(e){return a=void 0,d&&r?f(e):(r=o=void 0,i)}function v(){var e=Ae(),n=p(e);if(r=arguments,o=this,u=e,n){if(void 0===a)return function(e){return c=e,a=setTimeout(m,t),l?f(e):i}(u);if(g)return clearTimeout(a),a=setTimeout(m,t),f(u)}return void 0===a&&(a=setTimeout(m,t)),i}return t=Se(t)||0,Ee(n)&&(l=!!n.leading,s=(g="maxWait"in n)?Te(Se(n.maxWait)||0,t):s,d="trailing"in n?!!n.trailing:d),v.cancel=function(){void 0!==a&&clearTimeout(a),c=0,r=u=o=a=void 0},v.flush=function(){return void 0===a?i:h(Ae())},v};function ke(){return e=>{const t=e.target.value,n=z();t.length>=x?(n.dataset.originalQuery=t,async function(e){Re({request_id:P()});const t=function(e){var t,n,r;const o=B(),s=new URLSearchParams(window.location.search),i=Pe(),a=Object.assign(Object.assign({},(null===(t=null==o?void 0:o.autosuggest)||void 0===t?void 0:t.endpoint)?{endpoint:o.autosuggest.endpoint}:{}),{q:e||s.get((null==o?void 0:o.default_search_parameter)||"")||"",sort:null===(n=o.autosuggest)||void 0===n?void 0:n.sort,account_id:o.account_id,domain_key:o.domain_key,request_id:i.request_id,_br_uid_2:o.tracking_cookie,ref_url:o.ref_url,url:o.url,request_type:o.request_type,catalog_views:null===(r=o.autosuggest)||void 0===r?void 0:r.catalog_views});for(const[e,t]of s.entries())Object.keys(a).includes(e)||(a[e]=t);return a}(e),n=(o=await W(t),function(e){return"suggestionGroups"in e}(o)?function(e){var t,n,r,o,s,i,a,u,c;const l=B(),g=(null===(n=null===(t=null==e?void 0:e.suggestionGroups)||void 0===t?void 0:t[0])||void 0===n?void 0:n.searchSuggestions)||[],d=(null===(o=null===(r=null==e?void 0:e.suggestionGroups)||void 0===r?void 0:r[0])||void 0===o?void 0:o.querySuggestions)||[],f=(null===(i=null===(s=null==e?void 0:e.suggestionGroups)||void 0===s?void 0:s[0])||void 0===i?void 0:i.attributeSuggestions)||[],p=Object.assign(Object.assign({},(null===(a=null==e?void 0:e.queryContext)||void 0===a?void 0:a.originalQuery)?{originalQuery:e.queryContext.originalQuery}:{}),{terms:[...d.map(((e,t)=>{var n;return Object.assign(Object.assign(Object.assign({},e),{text:e.query,displayText:e.displayText,link:`${l.search_page_url}?${l.default_search_parameter}=${encodeURIComponent(e.query)}`}),0===t&&f?{categories:f.map((e=>Object.assign(Object.assign({},e),{name:e.name,value:e.value,type:e.attributeType}))).slice(0,null===(n=l.autosuggest)||void 0===n?void 0:n.number_of_collections)}:{})}))].slice(0,null===(u=l.autosuggest)||void 0===u?void 0:u.number_of_terms),productSuggestions:[...g.map((e=>Object.assign(Object.assign({},e),{id:e.pid,image:e.thumb_image,title:e.title,link:e.url,sale_price:Number((null==e?void 0:e.sale_price)||"0")})))].slice(0,null===(c=l.autosuggest)||void 0===c?void 0:c.number_of_products),config:l});return qe(p)}(o):function(e){var t,n;const r=B(),o=Object.assign(Object.assign({},e.response.q?{originalQuery:e.response.q}:{}),{terms:[...e.response.suggestions?e.response.suggestions.map((e=>{var t;return Object.assign(Object.assign(Object.assign({},e),{text:e.q,displayText:e.dq,link:`${r.search_page_url}?${r.default_search_parameter}=${encodeURIComponent(e.q)}`}),e.filters?{categories:e.filters.map((e=>Object.assign(Object.assign({},e),{name:e.name,value:e.value,type:e.key}))).slice(0,null===(t=r.autosuggest)||void 0===t?void 0:t.number_of_collections)}:{})})):[]].slice(0,null===(t=r.autosuggest)||void 0===t?void 0:t.number_of_terms),productSuggestions:[...e.response.products?e.response.products.map((e=>Object.assign(Object.assign(Object.assign({},e),{id:e.pid,image:e.thumb_image,title:e.title,link:e.url,sale_price:Number.isNaN(e.sale_price)?Number.isNaN(e.price)?"0":e.price:e.sale_price}),"price"in e&&"sale_price"in e?{price:e.price}:{}))):[]].slice(0,null===(n=r.autosuggest)||void 0===n?void 0:n.number_of_products),config:r});return qe(o)}(o));var o;Re({last_template_data:n}),J().innerHTML=r.render(U,n),X(),J().querySelectorAll(".blm-autosuggest__suggestion-term-link").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",function(e){return()=>{var t,n;const{suggestionText:r}=e.dataset,{originalQuery:o}=z().dataset,s={aq:o,q:r,catalogs:[{name:"example_en"}]};null===(n=null===(t=window.BrTrk||{})||void 0===t?void 0:t.getTracker())||void 0===n||n.logEvent("suggest","click",s,{},!0)}}(e)),e.setAttribute("hasListener","true"))}))}(t).catch(console.error)):(J().innerHTML="",n.dataset.originalQuery="",Re({last_template_data:null}))}}function Me(){document.body.getAttribute("hasMousedownListener")||(document.body.addEventListener("mousedown",(e=>{!function(e,t){var n;let r=e;for(;r&&r.parentNode;)if(r=r.parentNode,r&&(null===(n=r.classList)||void 0===n?void 0:n.contains(t)))return r;return null}(e.target,"blm-autosuggest")?J().innerHTML="":Ie({mouseDownEventHappenedInsideAutosuggestResultsContainer:!0})})),document.body.setAttribute("hasMousedownListener","true"));const e=z();e.getAttribute("hasBlurListener")||(e.addEventListener("blur",(()=>$e().mouseDownEventHappenedInsideAutosuggestResultsContainer?(Ie({mouseDownEventHappenedInsideAutosuggestResultsContainer:!1}),!1):(J().innerHTML="",!0))),e.setAttribute("hasBlurListener","true"))}function De(){const e=z();e.getAttribute("hasFocusListener")||(e.addEventListener("focus",(()=>{const e=Pe().last_template_data;Pe(),e&&(J().innerHTML=r.render(U,e))})),e.setAttribute("hasFocusListener","true"))}function Fe(){Me(),De(),function(){const e=z();e.getAttribute("hasKeyupListener")||(e.addEventListener("keyup",Ne(ke(),500)),e.setAttribute("hasKeyupListener","true"))}()}function qe(e){const t=Object.assign({},e);return e.terms.forEach(((n,o)=>{const s=r.render(L,{query:e.originalQuery}).trim();(t.terms[o]||{}).processedText=n.text.replace(e.originalQuery||"",s)})),t}function Pe(){return window.BloomreachModules.autosuggest.getCurrentAutosuggestRequestState()}function Re(e){window.BloomreachModules.autosuggest.setCurrentAutosuggestRequestState(Object.assign(Object.assign({},Pe()),e))}function $e(){return window.BloomreachModules.autosuggest.getCurrentAutosuggestUiState()}function Ie(e){window.BloomreachModules.autosuggest.setCurrentAutosuggestUiState(Object.assign(Object.assign({},$e()),e))}const We=function(){let e={request_id:0,last_template_data:null},t={mouseDownEventHappenedInsideAutosuggestResultsContainer:!1};return{setCurrentAutosuggestRequestState:t=>{e=t},getCurrentAutosuggestRequestState:()=>e,setCurrentAutosuggestUiState:e=>{t=e},getCurrentAutosuggestUiState:()=>t,load:async()=>{!function(){if(!J()){const e=document.createElement("style");e.innerHTML=`.blm-autosuggest-search-results {\n width: 100%;\n position: absolute;\n z-index: 100;\n left: 0;\n transform: translateY(${z().offsetHeight}px);\n }`,document.head.appendChild(e)}}(),function(){var e;if(!J()){const t=document.createElement("div");t.classList.add("blm-autosuggest-search-results"),null===(e=z().parentElement)||void 0===e||e.appendChild(t)}}(),function(){var e;const t=B();return j(t.account_id),j(t.domain_key),z(),J(),null===(e=null==t?void 0:t.autosuggest)||void 0===e?void 0:e.enabled}()&&(Fe(),G(),z().setAttribute("autocomplete","off"))}}}();window.BloomreachModules=Object.assign(Object.assign({},e),{autosuggest:We}),We.load().catch(console.error)}(); //# sourceMappingURL=autosuggest.js.map diff --git a/view/frontend/web/js/category.js b/view/frontend/web/js/category.js index 1172564..2f43d90 100644 --- a/view/frontend/web/js/category.js +++ b/view/frontend/web/js/category.js @@ -1,4068 +1,10 @@ -(function () { - 'use strict'; - - const AUTOSUGGEST_MINIMUM_QUERY_LENGTH = 2; - const AUTOSUGGEST_TYPED_QUERY_TEMPLATE = '<%= query %>'; - const COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS = 'cdp_segments'; - const COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE = 'customer_profile'; - const DEFAULT_CURRENCY = '$'; - const DEFAULT_PAGE_SIZE = 16; - const DEFAULT_SEARCH_PARAMETER = 'q'; - const DEFAULT_SORTING_OPTIONS = [{ - label: 'Relevance', - value: '' - }, { - label: 'Price (low - high)', - value: 'price+asc' - }, { - label: 'Price (high - low)', - value: 'price+desc' - }, { - label: 'Name (A - Z)', - value: 'title+asc' - }, { - label: 'Name (Z - A)', - value: 'title+desc' - }]; - const DEFAULT_START = 0; - const DEFAULT_WIDGETS_TO_DISPLAY = 4; - const FIELD_NAME_PRICE = 'price'; - const MAX_COLOR_SWATCHES = 4; - const MAX_PAGINATION_NUMBER_BEFORE_CURRENT = 2; - const MAX_PAGINATION_NUMBER_AFTER_CURRENT = 2; - const NUMBER_OF_AUTOSUGGEST_COLLECTIONS = 8; - const NUMBER_OF_AUTOSUGGEST_PRODUCTS = 8; - const NUMBER_OF_AUTOSUGGEST_TERMS = 4; - const NUMBER_OF_FACET_GROUPS = 5; - const NUMBER_OF_FACET_VALUES = 6; - const PARAMETER_NAME_FACETS = 'fq'; - const PARAMETER_NAME_FILTERS_PANEL = 'filterpanel'; - const PARAMETER_NAME_GROUPBY = 'groupby'; - const PARAMETER_NAME_PAGE = 'page'; - const PARAMETER_NAME_SIZE = 'size'; - const PARAMETER_NAME_SORT = 'sort'; - const REQUEST_TYPE_SEARCH = 'search'; - const REQUEST_TYPE_SUGGEST = 'suggest'; - const SEARCH_TYPE_CATEGORY = 'category'; - const SEARCH_TYPE_KEYWORD = 'keyword'; - const SELECTOR_AUTOSUGGEST_INPUT = '.search__input'; - const SELECTOR_SEARCH_RESULTS_CONTAINER = '.main-content'; - /** - * This is the attribute name used to flag an element as an add to cart event - * generator, such as a butto or link. - */ - const ADD_TO_CART_ATTRIBUTE_NAME = 'data-blm-add-to-cart'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the sku value sent in the - * pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_SKU = 'data-blm-add-to-cart-sku'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the prod_id value sent in - * the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_PROD_ID = 'data-blm-add-to-cart-prod-id'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to prevent emitting the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_DISABLE = 'data-blm-add-to-cart-disable'; - const QUICKVIEW_ATTRIBUTE_NAME = 'data-blm-quickview'; - const QUICKVIEW_ATTRIBUTE_SKU = 'data-blm-quickview-sku'; - const QUICKVIEW_ATTRIBUTE_PROD_ID = 'data-blm-quickview-prod-id'; - const QUICKVIEW_ATTRIBUTE_PROD_NAME = 'data-blm-quickview-prod-name'; - - var constants = /*#__PURE__*/Object.freeze({ - __proto__: null, - AUTOSUGGEST_MINIMUM_QUERY_LENGTH: AUTOSUGGEST_MINIMUM_QUERY_LENGTH, - AUTOSUGGEST_TYPED_QUERY_TEMPLATE: AUTOSUGGEST_TYPED_QUERY_TEMPLATE, - COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS: COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS, - COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE: COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE, - DEFAULT_CURRENCY: DEFAULT_CURRENCY, - DEFAULT_PAGE_SIZE: DEFAULT_PAGE_SIZE, - DEFAULT_SEARCH_PARAMETER: DEFAULT_SEARCH_PARAMETER, - DEFAULT_SORTING_OPTIONS: DEFAULT_SORTING_OPTIONS, - DEFAULT_START: DEFAULT_START, - DEFAULT_WIDGETS_TO_DISPLAY: DEFAULT_WIDGETS_TO_DISPLAY, - FIELD_NAME_PRICE: FIELD_NAME_PRICE, - MAX_COLOR_SWATCHES: MAX_COLOR_SWATCHES, - MAX_PAGINATION_NUMBER_BEFORE_CURRENT: MAX_PAGINATION_NUMBER_BEFORE_CURRENT, - MAX_PAGINATION_NUMBER_AFTER_CURRENT: MAX_PAGINATION_NUMBER_AFTER_CURRENT, - NUMBER_OF_AUTOSUGGEST_COLLECTIONS: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - NUMBER_OF_AUTOSUGGEST_PRODUCTS: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - NUMBER_OF_AUTOSUGGEST_TERMS: NUMBER_OF_AUTOSUGGEST_TERMS, - NUMBER_OF_FACET_GROUPS: NUMBER_OF_FACET_GROUPS, - NUMBER_OF_FACET_VALUES: NUMBER_OF_FACET_VALUES, - PARAMETER_NAME_FACETS: PARAMETER_NAME_FACETS, - PARAMETER_NAME_FILTERS_PANEL: PARAMETER_NAME_FILTERS_PANEL, - PARAMETER_NAME_GROUPBY: PARAMETER_NAME_GROUPBY, - PARAMETER_NAME_PAGE: PARAMETER_NAME_PAGE, - PARAMETER_NAME_SIZE: PARAMETER_NAME_SIZE, - PARAMETER_NAME_SORT: PARAMETER_NAME_SORT, - REQUEST_TYPE_SEARCH: REQUEST_TYPE_SEARCH, - REQUEST_TYPE_SUGGEST: REQUEST_TYPE_SUGGEST, - SEARCH_TYPE_CATEGORY: SEARCH_TYPE_CATEGORY, - SEARCH_TYPE_KEYWORD: SEARCH_TYPE_KEYWORD, - SELECTOR_AUTOSUGGEST_INPUT: SELECTOR_AUTOSUGGEST_INPUT, - SELECTOR_SEARCH_RESULTS_CONTAINER: SELECTOR_SEARCH_RESULTS_CONTAINER, - ADD_TO_CART_ATTRIBUTE_NAME: ADD_TO_CART_ATTRIBUTE_NAME, - ADD_TO_CART_ATTRIBUTE_SKU: ADD_TO_CART_ATTRIBUTE_SKU, - ADD_TO_CART_ATTRIBUTE_PROD_ID: ADD_TO_CART_ATTRIBUTE_PROD_ID, - ADD_TO_CART_ATTRIBUTE_DISABLE: ADD_TO_CART_ATTRIBUTE_DISABLE, - QUICKVIEW_ATTRIBUTE_NAME: QUICKVIEW_ATTRIBUTE_NAME, - QUICKVIEW_ATTRIBUTE_SKU: QUICKVIEW_ATTRIBUTE_SKU, - QUICKVIEW_ATTRIBUTE_PROD_ID: QUICKVIEW_ATTRIBUTE_PROD_ID, - QUICKVIEW_ATTRIBUTE_PROD_NAME: QUICKVIEW_ATTRIBUTE_PROD_NAME - }); - - const globalBloomreachModules = Object.assign(Object.assign({}, window.BloomreachModules ? window.BloomreachModules : {}), { - version: '4.0.0', - constants - }); - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getAugmentedNamespace(n) { - var f = n.default; - if (typeof f == "function") { - var a = function () { - return f.apply(this, arguments); - }; - a.prototype = f.prototype; - } else a = {}; - Object.defineProperty(a, '__esModule', {value: true}); - Object.keys(n).forEach(function (k) { - var d = Object.getOwnPropertyDescriptor(n, k); - Object.defineProperty(a, k, d.get ? d : { - enumerable: true, - get: function () { - return n[k]; - } - }); - }); - return a; - } - - var ejs = {}; - - var _polyfillNode_fs = {}; - - var _polyfillNode_fs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _polyfillNode_fs - }); - - var require$$0 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_fs$1); - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // resolves . and .. elements in a path array with directory names there - // must be no slashes, empty elements, or device names (c:\) in the array - // (so also no leading and trailing slashes - it does not distinguish - // relative and absolute paths) - function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; - } - - // Split a filename into [root, dir, basename, ext], unix version - // 'root' is just a slash, or nothing. - var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); - }; - - // path.resolve([from ...], to) - // posix version - function resolve() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : '/'; - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - } - // path.normalize(path) - // posix version - function normalize(path) { - var isPathAbsolute = isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isPathAbsolute).join('/'); - - if (!path && !isPathAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isPathAbsolute ? '/' : '') + path; - } - // posix version - function isAbsolute(path) { - return path.charAt(0) === '/'; - } - - // posix version - function join() { - var paths = Array.prototype.slice.call(arguments, 0); - return normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); - } - - - // path.relative(from, to) - // posix version - function relative(from, to) { - from = resolve(from).substr(1); - to = resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - } - - var sep = '/'; - var delimiter = ':'; - - function dirname(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; - } - - function basename(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; - } - - - function extname(path) { - return splitPath(path)[3]; - } - var _polyfillNode_path = { - extname: extname, - basename: basename, - dirname: dirname, - sep: sep, - delimiter: delimiter, - relative: relative, - join: join, - isAbsolute: isAbsolute, - normalize: normalize, - resolve: resolve - }; - function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; - } - - // String.prototype.substr - negative index don't work in IE8 - var substr = 'ab'.substr(-1) === 'b' ? - function (str, start, len) { return str.substr(start, len) } : - function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } - ; - - var _polyfillNode_path$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - resolve: resolve, - normalize: normalize, - isAbsolute: isAbsolute, - join: join, - relative: relative, - sep: sep, - delimiter: delimiter, - dirname: dirname, - basename: basename, - extname: extname, - 'default': _polyfillNode_path - }); - - var require$$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_path$1); - - var utils = {}; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - var regExpChars = /[|\\{}()[\]^$+*?.]/g; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); }; - - /** - * Escape characters reserved in regular expressions. - * - * If `string` is `undefined` or `null`, the empty string is returned. - * - * @param {String} string Input string - * @return {String} Escaped string - * @static - * @private - */ - exports.escapeRegExpChars = function (string) { - // istanbul ignore if - if (!string) { - return ''; - } - return String(string).replace(regExpChars, '\\$&'); - }; - - var _ENCODE_HTML_RULES = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - var _MATCH_HTML = /[&<>'"]/g; - - function encode_char(c) { - return _ENCODE_HTML_RULES[c] || c; - } - - /** - * Stringified version of constants used by {@link module:utils.escapeXML}. - * - * It is used in the process of generating {@link ClientFunction}s. - * - * @readonly - * @type {String} - */ - - var escapeFuncStr = - 'var _ENCODE_HTML_RULES = {\n' - + ' "&": "&"\n' - + ' , "<": "<"\n' - + ' , ">": ">"\n' - + ' , \'"\': """\n' - + ' , "\'": "'"\n' - + ' }\n' - + ' , _MATCH_HTML = /[&<>\'"]/g;\n' - + 'function encode_char(c) {\n' - + ' return _ENCODE_HTML_RULES[c] || c;\n' - + '};\n'; - - /** - * Escape characters reserved in XML. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @implements {EscapeCallback} - * @param {String} markup Input string - * @return {String} Escaped string - * @static - * @private - */ - - exports.escapeXML = function (markup) { - return markup == undefined - ? '' - : String(markup) - .replace(_MATCH_HTML, encode_char); - }; - exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; - }; - - /** - * Naive copy of properties from one object to another. - * Does not recurse into non-scalar properties - * Does not check to see if the property has a value before copying - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopy = function (to, from) { - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var p in from) { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - return to; - }; - - /** - * Naive copy of a list of key names, from one object to another. - * Only copies property if it is actually defined - * Does not recurse into non-scalar properties - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @param {Array} list List of properties to copy - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopyFromList = function (to, from, list) { - list = list || []; - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var i = 0; i < list.length; i++) { - var p = list[i]; - if (typeof from[p] != 'undefined') { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - } - return to; - }; - - /** - * Simple in-process cache implementation. Does not implement limits of any - * sort. - * - * @implements {Cache} - * @static - * @private - */ - exports.cache = { - _data: {}, - set: function (key, val) { - this._data[key] = val; - }, - get: function (key) { - return this._data[key]; - }, - remove: function (key) { - delete this._data[key]; - }, - reset: function () { - this._data = {}; - } - }; - - /** - * Transforms hyphen case variable into camel case. - * - * @param {String} string Hyphen case string - * @return {String} Camel case string - * @static - * @private - */ - exports.hyphenToCamel = function (str) { - return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); }); - }; - - /** - * Returns a null-prototype object in runtimes that support it - * - * @return {Object} Object, prototype will be set to null where possible - * @static - * @private - */ - exports.createNullProtoObjWherePossible = (function () { - if (typeof Object.create == 'function') { - return function () { - return Object.create(null); - }; - } - if (!({__proto__: null} instanceof Object)) { - return function () { - return {__proto__: null}; - }; - } - // Not possible, just pass through - return function () { - return {}; - }; - })(); - } (utils)); - - var name = "ejs"; - var description = "Embedded JavaScript templates"; - var keywords = [ - "template", - "engine", - "ejs" - ]; - var version = "3.1.8"; - var author = "Matthew Eernisse (http://fleegix.org)"; - var license = "Apache-2.0"; - var bin = { - ejs: "./bin/cli.js" - }; - var main = "./lib/ejs.js"; - var jsdelivr = "ejs.min.js"; - var unpkg = "ejs.min.js"; - var repository = { - type: "git", - url: "git://github.com/mde/ejs.git" - }; - var bugs = "https://github.com/mde/ejs/issues"; - var homepage = "https://github.com/mde/ejs"; - var dependencies = { - jake: "^10.8.5" - }; - var devDependencies = { - browserify: "^16.5.1", - eslint: "^6.8.0", - "git-directory-deploy": "^1.5.1", - jsdoc: "^3.6.7", - "lru-cache": "^4.0.1", - mocha: "^7.1.1", - "uglify-js": "^3.3.16" - }; - var engines = { - node: ">=0.10.0" - }; - var scripts = { - test: "mocha" - }; - var require$$3 = { - name: name, - description: description, - keywords: keywords, - version: version, - author: author, - license: license, - bin: bin, - main: main, - jsdelivr: jsdelivr, - unpkg: unpkg, - repository: repository, - bugs: bugs, - homepage: homepage, - dependencies: dependencies, - devDependencies: devDependencies, - engines: engines, - scripts: scripts - }; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - /** +!function(){"use strict";const e=Object.assign(Object.assign({},window.BloomreachModules?window.BloomreachModules:{}),{version:"3.1.0"});var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(e){var t=e.default;if("function"==typeof t){var n=function(){return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach((function(t){var r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:function(){return e[t]}})})),n}var r={},i=n(Object.freeze({__proto__:null,default:{}}));function a(e,t){for(var n=0,r=e.length-1;r>=0;r--){var i=e[r];"."===i?e.splice(r,1):".."===i?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var o=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,c=function(e){return o.exec(e).slice(1)};function s(){for(var e="",t=!1,n=arguments.length-1;n>=-1&&!t;n--){var r=n>=0?arguments[n]:"/";if("string"!=typeof r)throw new TypeError("Arguments to path.resolve must be strings");r&&(e=r+"/"+e,t="/"===r.charAt(0))}return(t?"/":"")+(e=a(g(e.split("/"),(function(e){return!!e})),!t).join("/"))||"."}function l(e){var t=u(e),n="/"===v(e,-1);return(e=a(g(e.split("/"),(function(e){return!!e})),!t).join("/"))||t||(e="."),e&&n&&(e+="/"),(t?"/":"")+e}function u(e){return"/"===e.charAt(0)}function d(){return l(g(Array.prototype.slice.call(arguments,0),(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))}function p(e,t){function n(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=s(e).substr(1),t=s(t).substr(1);for(var r=n(e.split("/")),i=n(t.split("/")),a=Math.min(r.length,i.length),o=a,c=0;c":">",'"':""","'":"'"},a=/[&<>'"]/g;function o(e){return i[e]||e}function c(){return Function.prototype.toString.call(this)+';\nvar _ENCODE_HTML_RULES = {\n "&": "&"\n , "<": "<"\n , ">": ">"\n , \'"\': """\n , "\'": "'"\n }\n , _MATCH_HTML = /[&<>\'"]/g;\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n};\n'}e.escapeXML=function(e){return null==e?"":String(e).replace(a,o)};try{"function"==typeof Object.defineProperty?Object.defineProperty(e.escapeXML,"toString",{value:c}):e.escapeXML.toString=c}catch(e){console.warn("Unable to set escapeXML.toString (is the Function prototype frozen?)")}e.shallowCopy=function(e,t){if(t=t||{},null!=e)for(var n in t)r(t,n)&&"__proto__"!==n&&"constructor"!==n&&(e[n]=t[n]);return e},e.shallowCopyFromList=function(e,t,n){if(n=n||[],t=t||{},null!=e)for(var i=0;i * @author Tiancheng "Timothy" Gu * @project EJS * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} */ - - /** - * EJS internal functions. - * - * Technically this "module" lies in the same file as {@link module:ejs}, for - * the sake of organization all the private functions re grouped into this - * module. - * - * @module ejs-internal - * @private - */ - - /** - * Embedded JavaScript templating engine. - * - * @module ejs - * @public - */ - - - var fs = require$$0; - var path = require$$1; - var utils$1 = utils; - - var scopeOptionWarned = false; - /** @type {string} */ - var _VERSION_STRING = require$$3.version; - var _DEFAULT_OPEN_DELIMITER = '<'; - var _DEFAULT_CLOSE_DELIMITER = '>'; - var _DEFAULT_DELIMITER = '%'; - var _DEFAULT_LOCALS_NAME = 'locals'; - var _NAME = 'ejs'; - var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; - var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', - 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; - // We don't allow 'cache' option to be passed in the data obj for - // the normal `render` call, but this is where Express 2 & 3 put it - // so we make an exception for `renderFile` - var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); - var _BOM = /^\uFEFF/; - var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; - - /** - * EJS template function cache. This can be a LRU object from lru-cache NPM - * module. By default, it is {@link module:utils.cache}, a simple in-process - * cache that grows continuously. - * - * @type {Cache} - */ - - exports.cache = utils$1.cache; - - /** - * Custom file loader. Useful for template preprocessing or restricting access - * to a certain part of the filesystem. - * - * @type {fileLoader} - */ - - exports.fileLoader = fs.readFileSync; - - /** - * Name of the object containing the locals. - * - * This variable is overridden by {@link Options}`.localsName` if it is not - * `undefined`. - * - * @type {String} - * @public - */ - - exports.localsName = _DEFAULT_LOCALS_NAME; - - /** - * Promise implementation -- defaults to the native implementation if available - * This is mostly just for testability - * - * @type {PromiseConstructorLike} - * @public - */ - - exports.promiseImpl = (new Function('return this;'))().Promise; - - /** - * Get the path to the included file from the parent file path and the - * specified path. - * - * @param {String} name specified path - * @param {String} filename parent file path - * @param {Boolean} [isDir=false] whether the parent file path is a directory - * @return {String} - */ - exports.resolveInclude = function(name, filename, isDir) { - var dirname = path.dirname; - var extname = path.extname; - var resolve = path.resolve; - var includePath = resolve(isDir ? filename : dirname(filename), name); - var ext = extname(name); - if (!ext) { - includePath += '.ejs'; - } - return includePath; - }; - - /** - * Try to resolve file path on multiple directories - * - * @param {String} name specified path - * @param {Array} paths list of possible parent directory paths - * @return {String} - */ - function resolvePaths(name, paths) { - var filePath; - if (paths.some(function (v) { - filePath = exports.resolveInclude(name, v, true); - return fs.existsSync(filePath); - })) { - return filePath; - } - } - - /** - * Get the path to the included file by Options - * - * @param {String} path specified path - * @param {Options} options compilation options - * @return {String} - */ - function getIncludePath(path, options) { - var includePath; - var filePath; - var views = options.views; - var match = /^[A-Za-z]+:\\|^\//.exec(path); - - // Abs path - if (match && match.length) { - path = path.replace(/^\/*/, ''); - if (Array.isArray(options.root)) { - includePath = resolvePaths(path, options.root); - } else { - includePath = exports.resolveInclude(path, options.root || '/', true); - } - } - // Relative paths - else { - // Look relative to a passed filename first - if (options.filename) { - filePath = exports.resolveInclude(path, options.filename); - if (fs.existsSync(filePath)) { - includePath = filePath; - } - } - // Then look in any views directories - if (!includePath && Array.isArray(views)) { - includePath = resolvePaths(path, views); - } - if (!includePath && typeof options.includer !== 'function') { - throw new Error('Could not find the include file "' + - options.escapeFunction(path) + '"'); - } - } - return includePath; - } - - /** - * Get the template from a string or a file, either compiled on-the-fly or - * read from cache (if enabled), and cache the template if needed. - * - * If `template` is not set, the file specified in `options.filename` will be - * read. - * - * If `options.cache` is true, this function reads the file from - * `options.filename` so it must be set prior to calling this function. - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {String} [template] template source - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned. - * @static - */ - - function handleCache(options, template) { - var func; - var filename = options.filename; - var hasTemplate = arguments.length > 1; - - if (options.cache) { - if (!filename) { - throw new Error('cache option requires a filename'); - } - func = exports.cache.get(filename); - if (func) { - return func; - } - if (!hasTemplate) { - template = fileLoader(filename).toString().replace(_BOM, ''); - } - } - else if (!hasTemplate) { - // istanbul ignore if: should not happen at all - if (!filename) { - throw new Error('Internal EJS error: no file name or template ' - + 'provided'); - } - template = fileLoader(filename).toString().replace(_BOM, ''); - } - func = exports.compile(template, options); - if (options.cache) { - exports.cache.set(filename, func); - } - return func; - } - - /** - * Try calling handleCache with the given options and data and call the - * callback with the result. If an error occurs, call the callback with - * the error. Used by renderFile(). - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {Object} data template data - * @param {RenderFileCallback} cb callback - * @static - */ - - function tryHandleCache(options, data, cb) { - var result; - if (!cb) { - if (typeof exports.promiseImpl == 'function') { - return new exports.promiseImpl(function (resolve, reject) { - try { - result = handleCache(options)(data); - resolve(result); - } - catch (err) { - reject(err); - } - }); - } - else { - throw new Error('Please provide a callback function'); - } - } - else { - try { - result = handleCache(options)(data); - } - catch (err) { - return cb(err); - } - - cb(null, result); - } - } - - /** - * fileLoader is independent - * - * @param {String} filePath ejs file path. - * @return {String} The contents of the specified file. - * @static - */ - - function fileLoader(filePath){ - return exports.fileLoader(filePath); - } - - /** - * Get the template function. - * - * If `options.cache` is `true`, then the template is cached. - * - * @memberof module:ejs-internal - * @param {String} path path for the specified file - * @param {Options} options compilation options - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned - * @static - */ - - function includeFile(path, options) { - var opts = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), options); - opts.filename = getIncludePath(path, opts); - if (typeof options.includer === 'function') { - var includerResult = options.includer(path, opts.filename); - if (includerResult) { - if (includerResult.filename) { - opts.filename = includerResult.filename; - } - if (includerResult.template) { - return handleCache(opts, includerResult.template); - } - } - } - return handleCache(opts); - } - - /** - * Re-throw the given `err` in context to the `str` of ejs, `filename`, and - * `lineno`. - * - * @implements {RethrowCallback} - * @memberof module:ejs-internal - * @param {Error} err Error object - * @param {String} str EJS source - * @param {String} flnm file name of the EJS file - * @param {Number} lineno line number of the error - * @param {EscapeCallback} esc - * @static - */ - - function rethrow(err, str, flnm, lineno, esc) { - var lines = str.split('\n'); - var start = Math.max(lineno - 3, 0); - var end = Math.min(lines.length, lineno + 3); - var filename = esc(flnm); - // Error context - var context = lines.slice(start, end).map(function (line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; - } - - function stripSemi(str){ - return str.replace(/;(\s*$)/, '$1'); - } - - /** - * Compile the given `str` of ejs into a template function. - * - * @param {String} template EJS template - * - * @param {Options} [opts] compilation options - * - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `opts.client`, either type might be returned. - * Note that the return type of the function also depends on the value of `opts.async`. - * @public - */ - - exports.compile = function compile(template, opts) { - var templ; - - // v1 compat - // 'scope' is 'context' - // FIXME: Remove this in a future version - if (opts && opts.scope) { - if (!scopeOptionWarned){ - console.warn('`scope` option is deprecated and will be removed in EJS 3'); - scopeOptionWarned = true; - } - if (!opts.context) { - opts.context = opts.scope; - } - delete opts.scope; - } - templ = new Template(template, opts); - return templ.compile(); - }; - - /** - * Render the given `template` of ejs. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} template EJS template - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @return {(String|Promise)} - * Return value type depends on `opts.async`. - * @public - */ - - exports.render = function (template, d, o) { - var data = d || utils$1.createNullProtoObjWherePossible(); - var opts = o || utils$1.createNullProtoObjWherePossible(); - - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 2) { - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); - } - - return handleCache(opts, template)(data); - }; - - /** - * Render an EJS file at the given `path` and callback `cb(err, str)`. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} path path to the EJS file - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @param {RenderFileCallback} cb callback - * @public - */ - - exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments); - var filename = args.shift(); - var cb; - var opts = {filename: filename}; - var data; - var viewOpts; - - // Do we have a callback? - if (typeof arguments[arguments.length - 1] == 'function') { - cb = args.pop(); - } - // Do we have data/opts? - if (args.length) { - // Should always have data obj - data = args.shift(); - // Normal passed opts (data obj + opts obj) - if (args.length) { - // Use shallowCopy so we don't pollute passed in opts obj with new vals - utils$1.shallowCopy(opts, args.pop()); - } - // Special casing for Express (settings + opts-in-data) - else { - // Express 3 and 4 - if (data.settings) { - // Pull a few things from known locations - if (data.settings.views) { - opts.views = data.settings.views; - } - if (data.settings['view cache']) { - opts.cache = true; - } - // Undocumented after Express 2, but still usable, esp. for - // items that are unsafe to be passed along with data, like `root` - viewOpts = data.settings['view options']; - if (viewOpts) { - utils$1.shallowCopy(opts, viewOpts); - } - } - // Express 2 and lower, values set in app.locals, or people who just - // want to pass options in their data. NOTE: These values will override - // anything previously set in settings or settings['view options'] - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); - } - opts.filename = filename; - } - else { - data = utils$1.createNullProtoObjWherePossible(); - } - - return tryHandleCache(opts, data, cb); - }; - - /** - * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. - * @public - */ - - /** - * EJS template class - * @public - */ - exports.Template = Template; - - exports.clearCache = function () { - exports.cache.reset(); - }; - - function Template(text, opts) { - opts = opts || utils$1.createNullProtoObjWherePossible(); - var options = utils$1.createNullProtoObjWherePossible(); - this.templateText = text; - /** @type {string | null} */ - this.mode = null; - this.truncate = false; - this.currentLine = 1; - this.source = ''; - options.client = opts.client || false; - options.escapeFunction = opts.escape || opts.escapeFunction || utils$1.escapeXML; - options.compileDebug = opts.compileDebug !== false; - options.debug = !!opts.debug; - options.filename = opts.filename; - options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; - options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; - options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; - options.strict = opts.strict || false; - options.context = opts.context; - options.cache = opts.cache || false; - options.rmWhitespace = opts.rmWhitespace; - options.root = opts.root; - options.includer = opts.includer; - options.outputFunctionName = opts.outputFunctionName; - options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; - options.views = opts.views; - options.async = opts.async; - options.destructuredLocals = opts.destructuredLocals; - options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; - - if (options.strict) { - options._with = false; - } - else { - options._with = typeof opts._with != 'undefined' ? opts._with : true; - } - - this.opts = options; - - this.regex = this.createRegex(); - } - - Template.modes = { - EVAL: 'eval', - ESCAPED: 'escaped', - RAW: 'raw', - COMMENT: 'comment', - LITERAL: 'literal' - }; - - Template.prototype = { - createRegex: function () { - var str = _REGEX_STRING; - var delim = utils$1.escapeRegExpChars(this.opts.delimiter); - var open = utils$1.escapeRegExpChars(this.opts.openDelimiter); - var close = utils$1.escapeRegExpChars(this.opts.closeDelimiter); - str = str.replace(/%/g, delim) - .replace(//g, close); - return new RegExp(str); - }, - - compile: function () { - /** @type {string} */ - var src; - /** @type {ClientFunction} */ - var fn; - var opts = this.opts; - var prepended = ''; - var appended = ''; - /** @type {EscapeCallback} */ - var escapeFn = opts.escapeFunction; - /** @type {FunctionConstructor} */ - var ctor; - /** @type {string} */ - var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined'; - - if (!this.source) { - this.generateSource(); - prepended += - ' var __output = "";\n' + - ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; - if (opts.outputFunctionName) { - if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) { - throw new Error('outputFunctionName is not a valid JS identifier.'); - } - prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; - } - if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) { - throw new Error('localsName is not a valid JS identifier.'); - } - if (opts.destructuredLocals && opts.destructuredLocals.length) { - var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; - for (var i = 0; i < opts.destructuredLocals.length; i++) { - var name = opts.destructuredLocals[i]; - if (!_JS_IDENTIFIER.test(name)) { - throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.'); - } - if (i > 0) { - destructuring += ',\n '; - } - destructuring += name + ' = __locals.' + name; - } - prepended += destructuring + ';\n'; - } - if (opts._with !== false) { - prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; - appended += ' }' + '\n'; - } - appended += ' return __output;' + '\n'; - this.source = prepended + this.source + appended; - } - - if (opts.compileDebug) { - src = 'var __line = 1' + '\n' - + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' - + ' , __filename = ' + sanitizedFilename + ';' + '\n' - + 'try {' + '\n' - + this.source - + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' - + '}' + '\n'; - } - else { - src = this.source; - } - - if (opts.client) { - src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; - if (opts.compileDebug) { - src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; - } - } - - if (opts.strict) { - src = '"use strict";\n' + src; - } - if (opts.debug) { - console.log(src); - } - if (opts.compileDebug && opts.filename) { - src = src + '\n' - + '//# sourceURL=' + sanitizedFilename + '\n'; - } - - try { - if (opts.async) { - // Have to use generated function for this, since in envs without support, - // it breaks in parsing - try { - ctor = (new Function('return (async function(){}).constructor;'))(); - } - catch(e) { - if (e instanceof SyntaxError) { - throw new Error('This environment does not support async/await'); - } - else { - throw e; - } - } - } - else { - ctor = Function; - } - fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); - } - catch(e) { - // istanbul ignore else - if (e instanceof SyntaxError) { - if (opts.filename) { - e.message += ' in ' + opts.filename; - } - e.message += ' while compiling ejs\n\n'; - e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; - e.message += 'https://github.com/RyanZim/EJS-Lint'; - if (!opts.async) { - e.message += '\n'; - e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; - } - } - throw e; - } - - // Return a callable function which will execute the function - // created by the source-code, with the passed data as locals - // Adds a local `include` function which allows full recursive include - var returnedFn = opts.client ? fn : function anonymous(data) { - var include = function (path, includeData) { - var d = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), data); - if (includeData) { - d = utils$1.shallowCopy(d, includeData); - } - return includeFile(path, opts)(d); - }; - return fn.apply(opts.context, - [data || utils$1.createNullProtoObjWherePossible(), escapeFn, include, rethrow]); - }; - if (opts.filename && typeof Object.defineProperty === 'function') { - var filename = opts.filename; - var basename = path.basename(filename, path.extname(filename)); - try { - Object.defineProperty(returnedFn, 'name', { - value: basename, - writable: false, - enumerable: false, - configurable: true - }); - } catch (e) {/* ignore */} - } - return returnedFn; - }, - - generateSource: function () { - var opts = this.opts; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r` and empty lines don't work well with the `m` flag. - this.templateText = - this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); - - var self = this; - var matches = this.parseTemplateText(); - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - - if (matches && matches.length) { - matches.forEach(function (line, index) { - var closing; - // If this is an opening tag, check for closing tags - // FIXME: May end up with some false positives here - // Better to store modes as k/v with openDelimiter + delimiter as key - // Then this can simply check against the map - if ( line.indexOf(o + d) === 0 // If it is a tag - && line.indexOf(o + d + d) !== 0) { // and is not escaped - closing = matches[index + 2]; - if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { - throw new Error('Could not find matching close tag for "' + line + '".'); - } - } - self.scanLine(line); - }); - } - - }, - - parseTemplateText: function () { - var str = this.templateText; - var pat = this.regex; - var result = pat.exec(str); - var arr = []; - var firstPos; - - while (result) { - firstPos = result.index; - - if (firstPos !== 0) { - arr.push(str.substring(0, firstPos)); - str = str.slice(firstPos); - } - - arr.push(result[0]); - str = str.slice(result[0].length); - result = pat.exec(str); - } - - if (str) { - arr.push(str); - } - - return arr; - }, - - _addOutput: function (line) { - if (this.truncate) { - // Only replace single leading linebreak in the line after - // -%> tag -- this is the single, trailing linebreak - // after the tag that the truncation mode replaces - // Handle Win / Unix / old Mac linebreaks -- do the \r\n - // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, ''); - this.truncate = false; - } - if (!line) { - return line; - } - - // Preserve literal slashes - line = line.replace(/\\/g, '\\\\'); - - // Convert linebreaks - line = line.replace(/\n/g, '\\n'); - line = line.replace(/\r/g, '\\r'); - - // Escape double-quotes - // - this will be the delimiter during execution - line = line.replace(/"/g, '\\"'); - this.source += ' ; __append("' + line + '")' + '\n'; - }, - - scanLine: function (line) { - var self = this; - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - var newLineCount = 0; - - newLineCount = (line.split('\n').length - 1); - - switch (line) { - case o + d: - case o + d + '_': - this.mode = Template.modes.EVAL; - break; - case o + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case o + d + '-': - this.mode = Template.modes.RAW; - break; - case o + d + '#': - this.mode = Template.modes.COMMENT; - break; - case o + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; - break; - case d + d + c: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; - break; - case d + c: - case '-' + d + c: - case '_' + d + c: - if (this.mode == Template.modes.LITERAL) { - this._addOutput(line); - } - - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: - // In script mode, depends on type of tag - if (this.mode) { - // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } - } - switch (this.mode) { - // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; - // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; - break; - // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; - break; - case Template.modes.COMMENT: - // Do nothing - break; - // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - this._addOutput(line); - break; - } - } - // In string mode, just add the output - else { - this._addOutput(line); - } - } - - if (self.opts.compileDebug && newLineCount) { - this.currentLine += newLineCount; - this.source += ' ; __line = ' + this.currentLine + '\n'; - } - } - }; - - /** - * Escape characters reserved in XML. - * - * This is simply an export of {@link module:utils.escapeXML}. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @param {String} markup Input string - * @return {String} Escaped string - * @public - * @func - * */ - exports.escapeXML = utils$1.escapeXML; - - /** - * Express.js support. - * - * This is an alias for {@link module:ejs.renderFile}, in order to support - * Express.js out-of-the-box. - * - * @func - */ - - exports.__express = exports.renderFile; - - /** - * Version of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.VERSION = _VERSION_STRING; - - /** - * Name for detection of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.name = _NAME; - - /* istanbul ignore if */ - if (typeof window != 'undefined') { - window.ejs = exports; - } - } (ejs)); - - /** - * Extracts the segmentation value from the Bloomreach segmentation pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractSegmentationCookie() { - const cookiePrefix = `${COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS}=`; - const segmentationCookie = document.cookie.split('; ').find(cookie => cookie.startsWith(cookiePrefix)); - return (segmentationCookie || '').replace(cookiePrefix, ''); - } - function applyKeywordRedirection(response) { - var _a; - if (response === null || response === void 0 ? void 0 : response.keywordRedirect) { - localStorage.setItem('keywordRedirect', JSON.stringify({ - original_query: response.keywordRedirect['original query'], - redirected_query: response.keywordRedirect['redirected query'], - redirected_url: response.keywordRedirect['redirected url'] - })); - const redirectedUrl = ((_a = response.keywordRedirect) === null || _a === void 0 ? void 0 : _a['redirected url']) || ''; - window.location.href = `${!redirectedUrl.startsWith('http') ? 'https://' : ''}${redirectedUrl}`; - } - } - - // /utils/getRequest.ts - /** - * Method used to initiate the API request - * @remarks The Assignment of the API specific promise is set in the respective API - * @param {string} url - * @param {{}} options - * @returns {Promise} - */ - async function getRequest(url, options) { - /** - * Use of Client-Side Fetch API to retrieve the response - * @type {Response} - */ - const response = await fetch(url, options); - /** - * Formats the response as json and returns the typed promise - * @type {any} - */ - const result = await response.json(); - /** - * Sets the type for the promise - */ - return result; - } - - // utils.requestOptions.ts - /** - * - * @type {{headers: {'Content-Type': string}, method: string}} - */ - const requestOptions = { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }; - - // utils/extractTrackingCookie.ts - /** - * Extracts the tracking cookie from the Bloomreach cookie pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractTrackingCookie() { - const trackingCookie = document.cookie.split('; ').find(cookie => cookie.startsWith('_br_uid_2=')); - return trackingCookie ? trackingCookie.replace('_br_uid_2=', '') : 'uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55'; - } - - // utils/formatAsCurrency.ts - /** - * Formats a value returned as a double into currency - * @param {number} cents - * @param {string} currencySign - * @param {boolean} onFront - * @returns {string} - */ - const formatAsCurrency = (cents, currencySign = '$', onFront = true) => `${onFront ? currencySign : ''}${(cents / 100.0).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 -})}${!onFront ? ` ${currencySign}` : ''}`; - - // utils/generateRequestID.ts - /** - * Generates a randomized request ID that is 13 characters long - * @returns {number} - */ - function generateRequestId() { - // eslint-disable-next-line no-mixed-operators - const requestID = Math.floor(1000000000000 + Math.random() * 9000000000000); - return requestID; - } - - // api-client/constants - // todo Refactor vanilla js / react implementation to either use or not use the constants config - const ENDPOINT_AUTOSUGGEST_API = 'https://suggest.dxpapi.com/api/v2/suggest/'; - const ENDPOINT_PRODUCT_SEARCH_API = 'https://core.dxpapi.com/api/v1/core/'; - const NO_ENCODE_PARAMETERS = ['_br_uid_2', 'fq', 'sort']; - const FIELD_LIST_DEFAULT = 'pid,title,brand,price,sale_price,thumb_image,sku_thumb_images,sku_swatch_images,sku_color_group,url,price_range,sale_price_range,description,is_live,score,skuid,group'; - - function buildQueryParameters(apiCallParameters) { - return `?${Object.keys(apiCallParameters).reduce((queryParameters, parameterName) => [...queryParameters, `${parameterName}=${NO_ENCODE_PARAMETERS.includes(parameterName) ? apiCallParameters[parameterName] : encodeURIComponent(apiCallParameters[parameterName])}`], []).join('&')}`; - } - function buildSearchRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_PRODUCT_SEARCH_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - if (!(apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.fl)) apiParameters.fl = FIELD_LIST_DEFAULT; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - function buildAutosuggestRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_AUTOSUGGEST_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSuggestions(params) { - const url = buildAutosuggestRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSearchResults(params) { - // Retrieves the URL and Options from the buildQueryParams function - const url = buildSearchRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - var searchLayoutTemplate = "<% if (did_you_mean.length) { %>\n \n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from \"<%- keywordRedirect.original_query %>\"
\n
\n
\n<% } %>\n
category<% } else { %>product-search<% } %> blm-results <% if (config.search.facets_included) { %>with-facets<% } %>\">\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class=\"blm-product-search__results\"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n"; - - var searchListTemplate = "<% function printProduct(product) { %>\n
title=\"<%- product.variant_name %>\"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : 'variant_index' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style=\"display: block\"<% } %>\n >\n \"\n />\n
\n <% }); %>\n <% } else { %>\n
\n \"\n />\n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n active<% } %>\"\n style=\"background-image: url('<%= variant.image %>')\"\n >\n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n"; - - var autosuggestTemplate = "<% if (terms.length || productSuggestions.length) { %>\n
\n <% } %>\n"; - - function buildBaseConfig() { - var _a; - const connectorConfig = (_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config; - const config = Object.assign({ - default_search_parameter: DEFAULT_SEARCH_PARAMETER, - url: window.location.href, - ref_url: window.location.href, - tracking_cookie: extractTrackingCookie(), - format_money: cents => formatAsCurrency(cents, window.bloomreachDefaultCurrency || DEFAULT_CURRENCY), - default_currency: window.bloomreachDefaultCurrency || DEFAULT_CURRENCY - }, connectorConfig); - return config; - } - function buildAutosuggestConfig() { - const baseConfig = buildBaseConfig(); - const config = Object.assign(Object.assign({ - request_type: REQUEST_TYPE_SUGGEST - }, baseConfig), { - autosuggest: Object.assign({ - enabled: true, - endpoint: '', - number_of_terms: NUMBER_OF_AUTOSUGGEST_TERMS, - number_of_products: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - number_of_collections: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - selector: SELECTOR_AUTOSUGGEST_INPUT, - template: autosuggestTemplate, - catalog_views: '' - }, baseConfig.autosuggest) - }); - return config; - } - function buildSearchConfig() { - var _a, _b, _c; - const baseConfig = buildBaseConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const state = getCurrentSearchRequestState(); - const defaultSearchProperties = Object.assign({ - display_variants: false, - enabled: true, - endpoint: '', - items_per_page: DEFAULT_PAGE_SIZE, - facets_included: true, - initial_number_of_facets: NUMBER_OF_FACET_GROUPS, - initial_number_of_facet_values: NUMBER_OF_FACET_VALUES, - infinite_scroll: false, - selector: SELECTOR_SEARCH_RESULTS_CONTAINER, - sorting_options: DEFAULT_SORTING_OPTIONS, - template: searchLayoutTemplate, - product_list_template: searchListTemplate - }, (baseConfig === null || baseConfig === void 0 ? void 0 : baseConfig.search) ? baseConfig.search : {}); - const config = Object.assign(Object.assign({}, baseConfig), { - request_type: REQUEST_TYPE_SEARCH, - search_type: state.is_category_page ? SEARCH_TYPE_CATEGORY : SEARCH_TYPE_KEYWORD, - start: DEFAULT_START, - 'facet.range': FIELD_NAME_PRICE, - 'stats.field': FIELD_NAME_PRICE, - sort: urlParameters.get(PARAMETER_NAME_SORT) || '', - search: Object.assign(Object.assign(Object.assign({}, defaultSearchProperties), (state.is_category_page ? baseConfig.category : baseConfig.search) || {}), state.category_to_load ? { - category_id: state.category_to_load - } : {}) - }); - (_c = (_b = (_a = config.search) === null || _a === void 0 ? void 0 : _a.sorting_options) === null || _b === void 0 ? void 0 : _b.sort) === null || _c === void 0 ? void 0 : _c.call(_b, (option1, option2) => option1.value > option2.value ? 1 : -1); - if (config.search) { - config.search = Object.assign(Object.assign({}, config.search), { - items_per_page: Number(urlParameters.has(PARAMETER_NAME_SIZE) ? urlParameters.get(PARAMETER_NAME_SIZE) : config.search.items_per_page), - groupby: urlParameters.get(PARAMETER_NAME_GROUPBY) || config.search.groupby || '' - }); - } - return config; - } - - function buildPaginationData(results) { - if ('grouped_products' in results) return buildGroupedPaginationData(results); - return buildRegularPaginationData(results); - } - function buildRegularPaginationData(results) { - const pageSize = results.size || 1; - if (results.number_of_results <= pageSize) { - return []; - } - const page = Math.ceil((results.start + 1) / pageSize); - const numberOfAllPages = Math.ceil(results.number_of_results / pageSize); - const beforeNumbers = Array(page - 1).fill(null).map((_, index) => index + 1).slice(-MAX_PAGINATION_NUMBER_BEFORE_CURRENT); - const afterNumbers = Array(numberOfAllPages - page).fill(null).map((_, index) => index + (page + 1)).slice(0, MAX_PAGINATION_NUMBER_AFTER_CURRENT); - return [...(page > 1 ? [{ - value: 'previous', - label: '←' - }] : []), ...(page - 1 > MAX_PAGINATION_NUMBER_BEFORE_CURRENT ? [{ - label: '…', - value: (page - MAX_PAGINATION_NUMBER_BEFORE_CURRENT - 1).toString() - }] : []), ...beforeNumbers.map(number => ({ - value: number.toString() - })), { - value: page.toString(), - disabled: true, - active: true - }, ...afterNumbers.map(number => ({ - value: number.toString() - })), ...(page + MAX_PAGINATION_NUMBER_AFTER_CURRENT < numberOfAllPages ? [{ - label: '…', - value: (page + MAX_PAGINATION_NUMBER_AFTER_CURRENT + 1).toString() - }] : []), ...(page < numberOfAllPages ? [{ - value: 'next', - label: '→' - }] : [])]; - } - function buildGroupedPaginationData(results) { - var _a; - const page = Number(results.page || 1); - const pageSize = results.size || 1; - const numberOfGroups = (((_a = results === null || results === void 0 ? void 0 : results.grouped_products) === null || _a === void 0 ? void 0 : _a.groups) || []).length; - return [{ - value: 'previous', - label: 'Previous', - disabled: page <= 1 - }, { - value: 'next', - label: 'Next', - disabled: numberOfGroups < pageSize - }]; - } - const escapeSpecialCharacters = value => value.replace(/"/g, '"').replace(/,/g, '%%-COMMA-%%'); - const decodeSpecialCharacters = value => value.replace(/%%-COMMA-%%/g, ',').replace(/"/g, '"'); - const convertFacetsToQueryString = facets => { - return Object.keys(facets).map(facetName => { - if (facetName === 'price') { - return encodeURIComponent( - // @ts-ignore - `${facetName}:[${facets[facetName].map(value => `${value}`).join(' TO ')}]`); - } - return encodeURIComponent( - // @ts-ignore - `${facetName}:${facets[facetName].map(value => `"${decodeSpecialCharacters(value)}"`).join(' OR ')}`); - }).join('&fq='); - }; - - let memoizedNS; - const NOOP = Object.assign(() => {}, { - warn: () => {}, - error: () => {}, - verbose: () => {} - }); - let colorIndex = -1; - const memoizedColor = new Map(); - /** - * List of colors our debugger can pick from. The colors should be slightly - * desautrated to help with reading and should be highly varied. - */ - const pickColor = ns => { - if (memoizedColor.has(ns)) return memoizedColor.get(ns); - const color = ['#00a3ff', '#ff00a3', '#a3ff00', '#00ffa3', '#a300ff', '#ffaa00', '#00ffaa', '#ff00aa', '#aa00ff', '#00aaff'][++colorIndex % 10] || '#00a3ff'; - memoizedColor.set(ns, color); - return color; - }; - /** - * Creates a simple debug logger system that is only activated by the stored - * state within localStorage.debug. The value in the state can be: - * - * namespace1;namespace2;namespace3;etc - * - * or - * - * namepspace1 - * - * or - * - * * - * - * Where `*` is a wildcard that will activate all namespaces. - */ - const Debug = ns => { - const active = activeNS(); - // If the namespace is not active, return a noop function set - if (!active.has(ns) && !active.has('*')) return NOOP; - const color = pickColor(ns); - const logger = console.log.bind(console, `%c${ns}`, `color: ${color}`); - logger.warn = console.warn.bind(console, `%c${ns}`, `color: ${color}`); - logger.error = console.error.bind(console, `%c${ns}`, `color: ${color}`); - if (active.has(`${ns}:verbose`) || active.has('*')) { - logger.verbose = console.log.bind(console, `%c${ns}:verbose`, `color: ${color}`); - } else { - logger.verbose = () => {}; - } - return logger; - }; - function activeNS() { - if (memoizedNS) return memoizedNS; - const storage = window.localStorage; - if (!storage) return new Set(); - const ns = storage.getItem('debug') || ''; - memoizedNS = new Set(ns.split(';')); - return memoizedNS; - } - - /** - * If a truthy value is false, this throws an error and displays the message for - * the error. - */ - function invariant(truthy, message) { - if (truthy) return; - throw new Error(message); - } - - Debug('br:autosuggest'); - function hideAllDynamicFacetGroups() { - ['.blm-dynamic-filter', '.blm-product-search-filter-item', '.blm-product-search-load-more'].forEach(selector => { - document.querySelectorAll(selector).forEach(item => { - item.removeAttribute('style'); - }); - }); - } - function loadMoreFacetGroups(numberOfFacetGroupsParameter) { - var _a; - let i = 0; - let numberOfHiddenBoxWithVisibleChildren = 0; - const config = buildSearchConfig(); - const numberOfFacetGroups = Number(numberOfFacetGroupsParameter || ((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets)); - document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach(item => { - const visibleChildren = item === null || item === void 0 ? void 0 : item.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]'); - if (i < numberOfFacetGroups && visibleChildren.length > 0) { - item === null || item === void 0 ? void 0 : item.setAttribute('style', 'display: block'); - } - i++; - numberOfHiddenBoxWithVisibleChildren += visibleChildren.length > 0 ? 1 : 0; - }); - const currentSearchRequestState = getCurrentSearchRequestState(); - const loadMoreFacetGroupsElement = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - const numberOfHiddenBoxes = document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length; - if (numberOfHiddenBoxes === 0 || numberOfHiddenBoxWithVisibleChildren === 0) { - loadMoreFacetGroupsElement === null || loadMoreFacetGroupsElement === void 0 ? void 0 : loadMoreFacetGroupsElement.classList.add('blm-hide'); - } - } - function getLoadMoreFacetGroupsElement() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const element = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - invariant(element, 'the element for loading more facet groups must be in the DOM'); - return element; - } - function resetFacetGroups() { - var _a, _b, _c; - const config = buildSearchConfig(); - const numberOfDisplayedFacetGroups = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets); - const numberOfDisplayedFacetValues = Number((_b = config.search) === null || _b === void 0 ? void 0 : _b.initial_number_of_facet_values); - hideAllDynamicFacetGroups(); - loadMoreFacetGroups(numberOfDisplayedFacetGroups - 1); - // init facet items visibility - document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${numberOfDisplayedFacetValues})`).forEach(item => item.style.display = 'block'); - (_c = getLoadMoreFacetGroupsElement()) === null || _c === void 0 ? void 0 : _c.removeAttribute('style'); - } - function getSearchResultsContainerElement() { - var _a; - const config = buildSearchConfig(); - invariant((_a = config.search) === null || _a === void 0 ? void 0 : _a.selector, 'the selector of search results container element must be set'); - const searchResultsContainerElement = document.querySelector(config.search.selector); - return searchResultsContainerElement; - } - function getSearchResultsListContainerElement() { - var _a; - const searchResultsListContainerElement = (_a = document.querySelector('.blm-product-search-main')) === null || _a === void 0 ? void 0 : _a.lastElementChild; - return searchResultsListContainerElement; - } - function getAutosuggestSearchInputElement() { - const config = buildAutosuggestConfig(); - if (!config.autosuggest) return null; - invariant(config.autosuggest.selector, 'the selector of search results container element must be set'); - const autosuggestInputElement = document.querySelector(config.autosuggest.selector); - return autosuggestInputElement; - } - function getAutosuggestResultsContainerElement() { - const autosuggestResultsContainerElement = document.querySelector('.blm-autosuggest-search-results'); - return autosuggestResultsContainerElement; - } - function resetLoadingIndicator() { - const scrollIndicator = document.querySelector('.blm-scroll-indicator'); - if (scrollIndicator) { - scrollIndicator.innerHTML = ''; - const loaderElement = document.createElement('div'); - loaderElement.classList.add('blm-scroll-indicator__loading'); - scrollIndicator.appendChild(loaderElement); - } - } - function getCheckedFacetValues() { - const checkedCheckboxes = document.querySelectorAll('.blm-product-search-filter-item__checkbox:checked'); - return checkedCheckboxes ? Array.from(checkedCheckboxes).reduce((all, current) => { - return Object.assign(Object.assign({}, all), { - [current.name]: all[current.name] ? [...(all[current.name] || []), current.value] : [current.value] - }); - }, {}) : {}; - } - function restoreScrollPosition() { - var _a; - // Get saved scroll positions - const storedScrollPositions = JSON.parse(window.localStorage.getItem('scrollPositions') || '{}'); - // Restore it if it's found for current page - const currentUriEncoded = encodeURI(window.location.href); - if (currentUriEncoded in storedScrollPositions) { - const scrollPosition = parseInt((_a = storedScrollPositions[currentUriEncoded]) === null || _a === void 0 ? void 0 : _a.scrollPosition, 10); - setTimeout(() => { - document.documentElement.scrollTop = scrollPosition; - document.body.scrollTop = scrollPosition; - }, 250); - } - delete storedScrollPositions[encodeURI(window.location.href)]; - window.localStorage.setItem('scrollPositions', JSON.stringify(storedScrollPositions)); - } - function beforeUnloadWindowEvent() { - let scrollPosition; - if (typeof window.pageYOffset !== 'undefined') { - scrollPosition = window.pageYOffset; - } else if (typeof document.compatMode !== 'undefined' && document.compatMode !== 'BackCompat') { - scrollPosition = document.documentElement.scrollTop; - } else if (typeof document.body !== 'undefined') { - scrollPosition = document.body.scrollTop; - } - const storedScrollPositions = JSON.parse(window.localStorage.getItem('scrollPositions') || '{}'); - window.localStorage.setItem('scrollPositions', JSON.stringify(Object.assign(Object.assign({}, storedScrollPositions), { - [encodeURI(window.location.href)]: { - scrollPosition - } - }))); - } - function setupSavingScrollPosition() { - // Add listeners in re-entrant fashion - unmountSaveScrollPosition(); - window.addEventListener('beforeunload', beforeUnloadWindowEvent); - } - function unmountSaveScrollPosition() { - window.removeEventListener('beforeunload', beforeUnloadWindowEvent); - } - - var breakpoints; - (function (breakpoints) { - breakpoints["small"] = "480px"; - breakpoints["medium"] = "680px"; - breakpoints["large"] = "750px"; - breakpoints["xlarge"] = "875px"; - breakpoints["xxlarge"] = "1000px"; - breakpoints["xxxlarge"] = "1200px"; - })(breakpoints || (breakpoints = {})); - const isMobileView = window.matchMedia(`(max-width: ${breakpoints.medium})`); - window.matchMedia(`(min-width:${breakpoints.medium}) and (max-width: ${breakpoints.xlarge})`); - - const log$2 = Debug('br:url'); - function updateUrl(urlParameters) { - var _a, _b, _c, _d; - const historyStateObject = {}; - // eslint-disable-next-line functional/no-loop-statement - for (const pair of urlParameters.entries()) { - historyStateObject[pair[0]] = pair[1]; - } - window.history.pushState(historyStateObject, document.title, `?${urlParameters.toString()}`); - const br_data = window.br_data || {}; - if (br_data.orig_ref_url !== location.href) { - br_data.orig_ref_url = location.href; - log$2('Generating virtual page view event for url update', location.href); - (_b = (_a = window.BrTrk) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.updateBrData(br_data); - (_d = (_c = window.BrTrk) === null || _c === void 0 ? void 0 : _c.getTracker()) === null || _d === void 0 ? void 0 : _d.logPageView(); - } - } - function updateMultipleInstanceParametersInUrl(parameterName, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - parameters, userOptions) { - const defaultOptions = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - valueSerializer: parameterValue => parameterValue.toString().replace(/"/g, '\\"'), - nameValueSeparator: ':' - }; - const options = Object.assign(Object.assign({}, defaultOptions), userOptions); - const urlParameters = new URLSearchParams(window.location.search); - urlParameters.delete(parameterName); - if (Array.isArray(parameters)) { - parameters.forEach(value => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - urlParameters.append(parameterName, options.valueSerializer(value)); - }); - } else { - Object.keys(parameters).forEach(key => { - urlParameters.append(parameterName, `${key}${options.nameValueSeparator}${options.valueSerializer(parameters[key])}`); - }); - } - updateUrl(urlParameters); - } - function updateParameterInUrl(parameterName, newValue) { - const urlParameters = new URLSearchParams(window.location.search); - if (typeof newValue === 'function') { - urlParameters.set(parameterName, - // @ts-ignore - newValue(urlParameters.get(parameterName)).replace(/"/g, '\\"')); - } else if (newValue === '') { - urlParameters.delete(parameterName); - } else { - urlParameters.set(parameterName, newValue.replace(/"/g, '\\"')); - } - updateUrl(urlParameters); - } - function incrementParameterInUrl(parameterName) { - updateParameterInUrl(parameterName, oldValue => { - if (!oldValue) return '2'; - let newValue = Number.parseInt(oldValue, 10); - return (++newValue).toString(); - }); - } - function decrementParameterInUrl(parameterName) { - updateParameterInUrl(parameterName, oldValue => { - if (!oldValue) return '1'; - let newValue = Number.parseInt(oldValue, 10); - return (--newValue).toString(); - }); - } - function buildPriceUrlParameterObject() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeLowerBoundaryInput = document.querySelector('.blm-price-range-input--lower'); - const priceRangeUpperBoundaryInput = document.querySelector('.blm-price-range-input--upper'); - let lowerBoundary = parseFloat(priceRangeLowerBoundaryInput.value); - let upperBoundary = parseFloat(priceRangeUpperBoundaryInput.value); - if (lowerBoundary === upperBoundary) { - if (upperBoundary === currentSearchRequestState.price_range_max_value) { - lowerBoundary -= 1; - } else { - upperBoundary += 1; - } - } - if (upperBoundary === currentSearchRequestState.price_range_max_value && (Number(lowerBoundary) === 0 || Number(lowerBoundary) === currentSearchRequestState.price_range_min_value)) { - return {}; - } - return { - price: `${lowerBoundary},${upperBoundary}` - }; - } - function getFacetsFromUrl() { - return new URLSearchParams(window.location.search).getAll(PARAMETER_NAME_FACETS).reduce((all, current) => Object.assign(Object.assign({}, all), { - [current.split(':')[0] || '']: (current.split(':')[1] || '').split(',') - }), {}); - } - function getSelectedColors() { - const selectedFacetValues = getFacetsFromUrl(); - return Object.keys(selectedFacetValues).reduce((colors, key) => { - if (key.toLowerCase() === 'color') { - colors = (selectedFacetValues[key] || []).map(color => color.toLowerCase()); - } - return colors; - }, []); - } - - const categoryLinkElementClickListener = event => { - var _a, _b, _c; - event.preventDefault(); - const clickedElement = event.target; - const categoryId = ((_a = clickedElement.dataset) === null || _a === void 0 ? void 0 : _a.categoryId) || ''; - const module = ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.search) || ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category); - if (module) { - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - module.load(categoryId).then(() => { - const autosuggestSearchElement = getAutosuggestSearchInputElement(); - const autosuggestResultsElement = getAutosuggestResultsContainerElement(); - if (autosuggestSearchElement) { - autosuggestSearchElement.value = (clickedElement === null || clickedElement === void 0 ? void 0 : clickedElement.textContent) || ''; - } - if (autosuggestResultsElement) { - autosuggestResultsElement.innerHTML = ''; - } - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - return true; - }).catch(console.error); - } - }; - function addCategoryLinkElementClickListener() { - var _a; - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link--category').forEach(categoryLinkElement => { - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.removeEventListener('click', categoryLinkElementClickListener); - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.addEventListener('click', categoryLinkElementClickListener); - }); - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - - function isObject$2(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - var isObject_1 = isObject$2; - - /** Detect free variable `global` from Node.js. */ - - var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; - - var _freeGlobal = freeGlobal$1; - - var freeGlobal = _freeGlobal; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root$2 = freeGlobal || freeSelf || Function('return this')(); - - var _root = root$2; - - var root$1 = _root; - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now$1 = function() { - return root$1.Date.now(); - }; - - var now_1 = now$1; - - /** Used to match a single whitespace character. */ - - var reWhitespace = /\s/; - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ - function trimmedEndIndex$1(string) { - var index = string.length; - - while (index-- && reWhitespace.test(string.charAt(index))) {} - return index; - } - - var _trimmedEndIndex = trimmedEndIndex$1; - - var trimmedEndIndex = _trimmedEndIndex; - - /** Used to match leading whitespace. */ - var reTrimStart = /^\s+/; - - /** - * The base implementation of `_.trim`. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function baseTrim$1(string) { - return string - ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') - : string; - } - - var _baseTrim = baseTrim$1; - - var root = _root; - - /** Built-in value references. */ - var Symbol$2 = root.Symbol; - - var _Symbol = Symbol$2; - - var Symbol$1 = _Symbol; - - /** Used for built-in method references. */ - var objectProto$1 = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto$1.hasOwnProperty; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString$1 = objectProto$1.toString; - - /** Built-in value references. */ - var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag$1(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; - } - - var _getRawTag = getRawTag$1; - - /** Used for built-in method references. */ - - var objectProto = Object.prototype; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString$1(value) { - return nativeObjectToString.call(value); - } - - var _objectToString = objectToString$1; - - var Symbol = _Symbol, - getRawTag = _getRawTag, - objectToString = _objectToString; - - /** `Object#toString` result references. */ - var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - - /** Built-in value references. */ - var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag$1(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - var _baseGetTag = baseGetTag$1; - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - - function isObjectLike$1(value) { - return value != null && typeof value == 'object'; - } - - var isObjectLike_1 = isObjectLike$1; - - var baseGetTag = _baseGetTag, - isObjectLike = isObjectLike_1; - - /** `Object#toString` result references. */ - var symbolTag = '[object Symbol]'; - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol$1(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - var isSymbol_1 = isSymbol$1; - - var baseTrim = _baseTrim, - isObject$1 = isObject_1, - isSymbol = isSymbol_1; - - /** Used as references for various `Number` constants. */ - var NAN = 0 / 0; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Built-in method references without a dependency on `root`. */ - var freeParseInt = parseInt; - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber$1(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject$1(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject$1(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - var toNumber_1 = toNumber$1; - - var isObject = isObject_1, - now = now_1, - toNumber = toNumber_1; - - /** Error message constants. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max, - nativeMin = Math.min; - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. 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 debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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's 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 clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - var debounce_1 = debounce; - - debounce_1(event => { - const query = event.target.value; - const searchInputElement = getAutosuggestSearchInputElement(); - if (!searchInputElement) return; - if (query.length >= AUTOSUGGEST_MINIMUM_QUERY_LENGTH) { - searchInputElement.dataset.originalQuery = query; - suggest(query).catch(console.error); - } else { - const autosuggestResultsContainerElement = getAutosuggestResultsContainerElement(); - if (autosuggestResultsContainerElement) { - autosuggestResultsContainerElement.innerHTML = ''; - } - searchInputElement.dataset.originalQuery = ''; - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - } - }, 500); - - const listeners$2 = new WeakMap(); - const suggestionTermElementClickListener = suggestionTermElement => { - return () => { - var _a, _b; - const { - suggestionText - } = suggestionTermElement.dataset; - const input = getAutosuggestSearchInputElement(); - if (!input) return; - const { - originalQuery - } = input.dataset; - const suggestionData = { - aq: originalQuery, - q: suggestionText, - catalogs: [{ - name: 'example_en' - }] - }; - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('suggest', 'click', suggestionData, {}, true); - }; - }; - function addSuggestionTermElementClickListener() { - var _a; - // Apply listeners in re-entrant fashion - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link').forEach(suggestionTermElement => { - const listener = suggestionTermElementClickListener(suggestionTermElement); - const old = listeners$2.get(suggestionTermElement); - if (old) suggestionTermElement.removeEventListener('click', old); - listeners$2.set(suggestionTermElement, listener); - suggestionTermElement === null || suggestionTermElement === void 0 ? void 0 : suggestionTermElement.addEventListener('click', listener); - }); - } - - function mapAutosuggestApiResponse(responseData) { - return isV2Response(responseData) ? mapV2Response(responseData) : mapV1Response(responseData); - } - function mapV2Response(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j; - const config = buildAutosuggestConfig(); - const productSuggestions = ((_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.searchSuggestions) || []; - const suggestions = ((_d = (_c = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.querySuggestions) || []; - const categorySuggestions = ((_f = (_e = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.attributeSuggestions) || []; - const mappedApiResponse = Object.assign(Object.assign({}, ((_g = responseData === null || responseData === void 0 ? void 0 : responseData.queryContext) === null || _g === void 0 ? void 0 : _g.originalQuery) ? { - originalQuery: responseData.queryContext.originalQuery - } : {}), { - terms: [...suggestions.map((term, index) => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.query, - displayText: term.displayText, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.query)}` - }), index === 0 && categorySuggestions ? { - categories: categorySuggestions.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.attributeType - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - })].slice(0, (_h = config.autosuggest) === null || _h === void 0 ? void 0 : _h.number_of_terms), - productSuggestions: [...productSuggestions.map(product => Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: Number((product === null || product === void 0 ? void 0 : product.sale_price) || '0') - }))].slice(0, (_j = config.autosuggest) === null || _j === void 0 ? void 0 : _j.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function isV2Response(responseData) { - return 'suggestionGroups' in responseData; - } - function mapV1Response(responseData) { - var _a, _b; - const config = buildAutosuggestConfig(); - const mappedApiResponse = Object.assign(Object.assign({}, responseData.response.q ? { - originalQuery: responseData.response.q - } : {}), { - terms: [...(responseData.response.suggestions ? responseData.response.suggestions.map(term => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.q, - displayText: term.dq, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.q)}` - }), term.filters ? { - categories: term.filters.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.key - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - }) : [])].slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_terms), - productSuggestions: [...(responseData.response.products ? responseData.response.products.map(product => Object.assign(Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: !Number.isNaN(product.sale_price) ? product.sale_price : !Number.isNaN(product.price) ? product.price : '0' - }), 'price' in product && 'sale_price' in product ? { - price: product.price - } : {})) : [])].slice(0, (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function highlightQueryInTermLabels(results) { - const processedResults = Object.assign({}, results); - results.terms.forEach((term, index) => { - const typedQueryHtml = ejs.render(AUTOSUGGEST_TYPED_QUERY_TEMPLATE, { - query: results.originalQuery - }).trim(); - (processedResults.terms[index] || {}).processedText = term.text.replace(results.originalQuery || '', typedQueryHtml); - }); - return processedResults; - } - - function mapSearchApiResponse(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - const config = buildSearchConfig(); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ - response: responseData, - autoCorrectQuery: responseData === null || responseData === void 0 ? void 0 : responseData.autoCorrectQuery, - facets: Object.entries(((_a = responseData === null || responseData === void 0 ? void 0 : responseData.facet_counts) === null || _a === void 0 ? void 0 : _a.facet_fields) || {}).map(fieldName => { - return { - original_title: fieldName[0], - title: fieldName[0].replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase()), - section: fieldName[1].map(section => { - if (section.name === 'true') { - section.name = 'Yes'; - } else if (section.name === 'false') { - section.name = 'No'; - } - return { - count: section.count, - name: section.cat_name || section.name, - id: section.cat_id || section.name, - raw: section - }; - }) - }; - }).filter(facet => facet.section.length) - }, ((_c = (_b = responseData === null || responseData === void 0 ? void 0 : responseData.facet_counts) === null || _b === void 0 ? void 0 : _b.facet_ranges) === null || _c === void 0 ? void 0 : _c.price) ? { - priceRanges: responseData.facet_counts.facet_ranges.price.map(range => ({ - count: range.count, - start: range.start.toString(), - end: range.end.toString() - })) - } : {}), ((_e = (_d = responseData === null || responseData === void 0 ? void 0 : responseData.stats) === null || _d === void 0 ? void 0 : _d.stats_fields) === null || _e === void 0 ? void 0 : _e.price) ? { - maxPrice: responseData.stats.stats_fields.price.max, - minPrice: responseData.stats.stats_fields.price.min - } : {}), ((_g = (_f = responseData === null || responseData === void 0 ? void 0 : responseData.stats) === null || _f === void 0 ? void 0 : _f.stats_fields) === null || _g === void 0 ? void 0 : _g.sale_price) ? { - maxPrice: responseData.stats.stats_fields.sale_price.max, - minPrice: responseData.stats.stats_fields.sale_price.min - } : {}), { - products: processDocs(((_h = responseData.response) === null || _h === void 0 ? void 0 : _h.docs) || []) - }), (responseData === null || responseData === void 0 ? void 0 : responseData.group_response) ? { - grouped_products: Object.keys(responseData === null || responseData === void 0 ? void 0 : responseData.group_response).reduce((_, groupCategoryId) => { - var _a, _b, _c, _d; - // Assuming we have only one group category in the group response object - return Object.assign(Object.assign({ - group_category_id: groupCategoryId - }, (_a = responseData.group_response) === null || _a === void 0 ? void 0 : _a[groupCategoryId]), { - groups: ((_d = (_c = (_b = responseData.group_response) === null || _b === void 0 ? void 0 : _b[groupCategoryId]) === null || _c === void 0 ? void 0 : _c.groups) === null || _d === void 0 ? void 0 : _d.map(group => { - var _a; - return { - title: group.groupValue, - products: processDocs(((_a = group === null || group === void 0 ? void 0 : group.doclist) === null || _a === void 0 ? void 0 : _a.docs) || []) - }; - })) || [] - }); - }, {}) - } : {}), { - did_you_mean: responseData.did_you_mean || [], - number_of_results: Number((_j = responseData.response) === null || _j === void 0 ? void 0 : _j.numFound), - start: Number((_k = responseData.response) === null || _k === void 0 ? void 0 : _k.start), - config - }), responseData.keywordRedirect ? { - keywordRedirect: { - original_query: responseData.keywordRedirect['original query'], - redirected_query: responseData.keywordRedirect['redirected query'], - redirected_url: responseData.keywordRedirect['redirected url'] - } - } : {}); - } - function processDocs(docs) { - const config = buildSearchConfig(); - return docs.reduce((allProducts, currentProduct) => { - return [...allProducts, ...(config.search.display_variants ? extractVariants(currentProduct) : [transformProductResponseToProductData(currentProduct)])]; - }, []); - } - function extractVariants(productResponse) { - if (!productResponse.variants || !productResponse.variants.length) { - return [transformProductResponseToProductData(productResponse)]; - } - return (transformProductResponseToProductData(productResponse).variants || []).map((variant, index) => Object.assign(Object.assign(Object.assign({}, transformProductResponseToProductData(productResponse)), variant), { - variant_index: index - })); - } - function transformProductResponseToProductData(productResponse) { - return Object.assign(Object.assign(Object.assign({}, productResponse), { - title: productResponse.title, - image: productResponse.thumb_image, - link: productResponse.url, - id: productResponse.pid, - price: productResponse.price, - sale_price: productResponse.sale_price - }), productResponse.variants ? { - variants: productResponse.variants.map(variant => Object.assign(Object.assign({}, variant), { - sku_color_group: variant.sku_color_group, - sku_swatch_images: variant.sku_swatch_images, - sku_thumb_images: variant.sku_thumb_images, - sku_sale_price: variant.sku_sale_price, - sku_price: variant.sku_price, - image: variant.sku_thumb_images && Array.isArray(variant.sku_thumb_images) ? variant.sku_thumb_images[0] : variant.sku_swatch_images[0], - variant_name: variant.sku_color_group - })) - } : {}); - } - - const log$1 = Debug('br:autosuggest'); - /** - * Retrieves suggestions from the suggest API and renders them to the DOM. - */ - async function suggest(query) { - var _a, _b, _c; - log$1('Fetching suggestions for', query); - const config = buildAutosuggestConfig(); - updateCurrentAutosuggestRequestState({ - request_id: generateRequestId() - }); - const apiCallParameters = buildApiCallParameters$1(query); - // todo remediate typescript issue - // @ts-ignore - const results = await getSuggestions(apiCallParameters); - const templateData = mapAutosuggestApiResponse(results); - updateCurrentAutosuggestRequestState({ - last_template_data: templateData - }); - const container = getAutosuggestResultsContainerElement(); - if (!container) return; - log$1.verbose('Using config', config); - log$1.verbose('Render to:', container); - log$1.verbose('Is using default template?', !((_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.template)); - log$1.verbose('Rendering with template:', { - template: ((_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.template) || autosuggestTemplate, - templateData - }); - container.innerHTML = ejs.render(((_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.template) || autosuggestTemplate, templateData); - addCategoryLinkElementClickListener(); - addSuggestionTermElementClickListener(); - } - /** - * Generates the API paramters fed into the suggest API call body. - */ - function buildApiCallParameters$1(query) { - var _a, _b, _c; - const config = buildAutosuggestConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentAutosuggestRequestState = getCurrentAutosuggestRequestState(); - const apiParameters = Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.autosuggest) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.autosuggest.endpoint - } : {}), { - q: query || urlParameters.get((config === null || config === void 0 ? void 0 : config.default_search_parameter) || '') || '', - aq: query, - sort: (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.sort, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentAutosuggestRequestState.request_id, - _br_uid_2: config.tracking_cookie, - ref_url: config.ref_url, - url: config.url, - request_type: config.request_type, - catalog_views: (_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.catalog_views, - search_type: 'keyword' - }); - if (!apiParameters.catalog_views) { - apiParameters.catalog_views = ''; - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === undefined) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function getCurrentAutosuggestRequestState() { - return window.BloomreachModules.autosuggest.getCurrentAutosuggestRequestState(); - } - function updateCurrentAutosuggestRequestState(state) { - window.BloomreachModules.autosuggest.setCurrentAutosuggestRequestState(Object.assign(Object.assign({}, getCurrentAutosuggestRequestState()), state)); - } - - Debug('br:product-events'); - - Debug('br:recommendations'); - - const clearPriceRangeValueButtonClickListener = () => { - resetLoadingIndicator(); - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign({}, getCheckedFacetValues())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - updateCurrentSearchRequestState({ - price_range_max_value: 0, - price_range_min_value: 0 - }); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addClearPriceRangeValueButtonClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeValueClearButton = document.querySelector(`.blm-range-slider__clear-values-button--${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeValueClearButton) { - priceRangeValueClearButton.removeEventListener('click', clearPriceRangeValueButtonClickListener); - priceRangeValueClearButton.addEventListener('click', clearPriceRangeValueButtonClickListener); - } - } - function removeClearPriceRangeValueButtonClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeValueClearButton = document.querySelector(`.blm-range-slider__clear-values-button--${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeValueClearButton) { - priceRangeValueClearButton.removeEventListener('click', clearPriceRangeValueButtonClickListener); - } - } - - const clearSelectedFacetButtonClickListener = event => { - var _a, _b, _c, _d; - const checkboxId = (_c = (_b = (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.filterCheckboxId; - if (checkboxId) { - (_d = document.getElementById(checkboxId)) === null || _d === void 0 ? void 0 : _d.click(); - } - }; - function addClearSelectedFacetButtonClickListener() { - const clearSelectedFacetButtons = document.querySelectorAll('.blm-product-search-selected-filter__clear'); - // Apply listeners in re-entrant fashion - clearSelectedFacetButtons.forEach(button => { - button === null || button === void 0 ? void 0 : button.removeEventListener('click', clearSelectedFacetButtonClickListener); - button === null || button === void 0 ? void 0 : button.addEventListener('click', clearSelectedFacetButtonClickListener); - }); - } - function removeClearSelectedFacetButtonClickListener() { - const clearSelectedFacetButtons = document.querySelectorAll('.blm-product-search-selected-filter__clear'); - // Apply listeners in re-entrant fashion - clearSelectedFacetButtons.forEach(button => { - button === null || button === void 0 ? void 0 : button.removeEventListener('click', clearSelectedFacetButtonClickListener); - }); - } - - const clearAllSelectedFacetsButtonClickListener = () => { - resetLoadingIndicator(); - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign({}, buildPriceUrlParameterObject())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addClearAllSelectedFacetsButtonClickListener() { - const selectedFiltersClearAllButton = document.querySelector('.blm-product-search-selected-filters__clear-all'); - // Apply listeners in re-entrant fashion - if (selectedFiltersClearAllButton) { - selectedFiltersClearAllButton.removeEventListener('click', clearAllSelectedFacetsButtonClickListener); - selectedFiltersClearAllButton.addEventListener('click', clearAllSelectedFacetsButtonClickListener); - } - } - function removeClearAllSelectedFacetsButtonClickListener() { - const selectedFiltersClearAllButton = document.querySelector('.blm-product-search-selected-filters__clear-all'); - // Apply listeners in re-entrant fashion - if (selectedFiltersClearAllButton) { - selectedFiltersClearAllButton.removeEventListener('click', clearAllSelectedFacetsButtonClickListener); - } - } - - const facetCheckboxChangeListener = () => { - resetLoadingIndicator(); - /* - If the checkedFacets is - { colors: ["gray", "black"], reviews: ["4.7", "5.0"] } - then we're setting these values in the URL in this format: - &fq=colors%3Agray%2Cblack&fq=reviews%3A4.7%2C5.0 - because it's easier to read it like that when we're performing the search, - than it would be if we'd store it in the format how we're using them - in the API call's URL parameter list - */ - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign(Object.assign({}, getCheckedFacetValues()), buildPriceUrlParameterObject())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addFacetCheckboxChangeListener() { - const facetCheckboxes = document.querySelectorAll('.blm-product-search-filter-item__checkbox'); - // Apply listeners in re-entrant fashion - if (facetCheckboxes) { - facetCheckboxes.forEach(checkbox => { - checkbox === null || checkbox === void 0 ? void 0 : checkbox.removeEventListener('change', facetCheckboxChangeListener); - checkbox === null || checkbox === void 0 ? void 0 : checkbox.addEventListener('change', facetCheckboxChangeListener); - }); - } - } - function removeFacetCheckboxChangeListener() { - const facetCheckboxes = document.querySelectorAll('.blm-product-search-filter-item__checkbox'); - // Apply listeners in re-entrant fashion - if (facetCheckboxes) { - facetCheckboxes.forEach(checkbox => { - checkbox === null || checkbox === void 0 ? void 0 : checkbox.removeEventListener('change', facetCheckboxChangeListener); - }); - } - } - - const facetSearchInputChangeListener = debounce_1(event => { - var _a; - const inputValue = (((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) || '').trim(); - document.querySelectorAll('.blm-dynamic-filter').forEach(facetBox => { - let displayedItems = 0; - facetBox.querySelectorAll('.blm-product-search-filter-item').forEach(facetItem => { - var _a; - const label = ((_a = facetItem.querySelector('label')) === null || _a === void 0 ? void 0 : _a.textContent) || ''; - const shouldDisplay = !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()); - const displayStyle = shouldDisplay ? 'block' : 'none'; - displayedItems += shouldDisplay ? 1 : 0; - facetItem.style.display = displayStyle; - }); - facetBox.style.display = displayedItems ? 'block' : 'none'; - }); - document.querySelectorAll('.blm-product-search-load-more').forEach(loadMoreLink => { - loadMoreLink.style.display = 'none'; - }); - const groupsELement = getLoadMoreFacetGroupsElement(); - if (!groupsELement) return; - groupsELement.style.display = 'none'; - if (!inputValue) { - resetFacetGroups(); - } - }, 500); - function addFacetSearchInputChangeListener() { - const facetSearchInput = document.querySelector('#blm-product-search-search-filters__input'); - // Apply listeners in re-entrant fashion - if (facetSearchInput) { - facetSearchInput.removeEventListener('input', facetSearchInputChangeListener); - facetSearchInput.addEventListener('input', facetSearchInputChangeListener); - } - } - function removeFacetSearchInputChangeListener() { - const facetSearchInput = document.querySelector('#blm-product-search-search-filters__input'); - // Apply listeners in re-entrant fashion - if (facetSearchInput) { - facetSearchInput.removeEventListener('input', facetSearchInputChangeListener); - } - } - - const groupbySelectChangeListener = event => { - var _a; - updateParameterInUrl(PARAMETER_NAME_GROUPBY, (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value); - resetLoadingIndicator(); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addGroupbySelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const groupbySelector = document.querySelector(`#groupby-${currentSearchRequestState === null || currentSearchRequestState === void 0 ? void 0 : currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (groupbySelector) { - groupbySelector.removeEventListener('change', groupbySelectChangeListener); - groupbySelector.addEventListener('change', groupbySelectChangeListener); - } - } - function removeGroupbySelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const groupbySelector = document.querySelector(`#groupby-${currentSearchRequestState === null || currentSearchRequestState === void 0 ? void 0 : currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (groupbySelector) { - groupbySelector.removeEventListener('change', groupbySelectChangeListener); - } - } - - const loadMoreFacetGroupsButtonClickListener = () => { - loadMoreFacetGroups(); - }; - function addLoadMoreFacetGroupsButtonClickListener() { - const element = getLoadMoreFacetGroupsElement(); - // Apply listeners in re-entrant fashion - element === null || element === void 0 ? void 0 : element.removeEventListener('click', loadMoreFacetGroupsButtonClickListener); - element === null || element === void 0 ? void 0 : element.addEventListener('click', loadMoreFacetGroupsButtonClickListener); - } - function removeLoadMoreFacetGroupsButtonClickListener() { - const element = getLoadMoreFacetGroupsElement(); - // Apply listeners in re-entrant fashion - element === null || element === void 0 ? void 0 : element.removeEventListener('click', loadMoreFacetGroupsButtonClickListener); - } - - // Our listeners have item specific context so we need to be able to reference - // the generated closure for each item, but we can not let the closure or item - // reference leak. So we use a weakmap so the listener will naturally die when - // the the item is garbage collected. - const listeners$1 = new WeakMap(); - const loadMoreFacetValuesButtonClickListener = () => { - var _a; - const config = buildSearchConfig(); - const numberOfDisplayedFacetValues = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facet_values); - let showFilterItems = numberOfDisplayedFacetValues; - const incrementFilterBy = numberOfDisplayedFacetValues; - return event => { - const itemIndex = event.target.getAttribute('data-item'); - const facetBlock = document.getElementById(`blm-facet-block-item-${itemIndex}`); - const filterListItems = facetBlock.getElementsByTagName('li'); - // eslint-disable-next-line functional/no-loop-statement - for (let i = showFilterItems; i < showFilterItems + incrementFilterBy; i++) { - if (filterListItems[i]) { - filterListItems[i].style.display = 'block'; - } - } - showFilterItems += incrementFilterBy; - if (showFilterItems >= filterListItems.length) { - event.target.style.display = 'none'; - } - }; - }; - function addLoadMoreFacetValuesButtonClickListener() { - document.querySelectorAll('.blm-product-search-load-more').forEach(item => { - // Apply listeners in re-entrant fashion - const old = listeners$1.get(item); - if (old) item.removeEventListener('click', old); - const listener = listeners$1.get(item) || loadMoreFacetValuesButtonClickListener(); - listeners$1.set(item, listener); - item.addEventListener('click', listener); - }); - } - function removeLoadMoreFacetValuesButtonClickListener() { - document.querySelectorAll('.blm-product-search-load-more').forEach(item => { - // Apply listeners in re-entrant fashion - const old = listeners$1.get(item); - if (old) item.removeEventListener('click', old); - }); - } - - const pageSizeSelectChangeListener = event => { - updateParameterInUrl(PARAMETER_NAME_SIZE, event.target.value); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - resetLoadingIndicator(); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addPageSizeSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to page size select field changes - const sizeSelector = document.querySelector(`#sort-size-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sizeSelector) { - sizeSelector.removeEventListener('change', pageSizeSelectChangeListener); - sizeSelector.addEventListener('change', pageSizeSelectChangeListener); - } - } - function removePageSizeSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to page size select field changes - const sizeSelector = document.querySelector(`#sort-size-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sizeSelector) { - sizeSelector.removeEventListener('change', pageSizeSelectChangeListener); - } - } - - const paginationContainerClickListener = event => { - resetLoadingIndicator(); - const clickedPaginationValue = event.target.dataset.value; - if (clickedPaginationValue) { - switch (event.target.dataset.value) { - case 'previous': - decrementParameterInUrl(PARAMETER_NAME_PAGE); - break; - case 'next': - incrementParameterInUrl(PARAMETER_NAME_PAGE); - break; - default: - updateParameterInUrl(PARAMETER_NAME_PAGE, clickedPaginationValue); - } - initiateSearch({ - toReplace: true - }).catch(console.error); - } - }; - function addPaginationContainerClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to pagination events - const paginationContainer = document.querySelector(`.blm-product-search-pagination__pages--${currentSearchRequestState.request_id}`); - if (!paginationContainer) return; - // Apply listeners in re-entrant fashion - paginationContainer.removeEventListener('click', paginationContainerClickListener); - paginationContainer.addEventListener('click', paginationContainerClickListener); - } - function removePaginationContainerClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to pagination events - const paginationContainer = document.querySelector(`.blm-product-search-pagination__pages--${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - paginationContainer === null || paginationContainer === void 0 ? void 0 : paginationContainer.removeEventListener('click', paginationContainerClickListener); - } - - const priceRangeChangeListener = () => { - resetLoadingIndicator(); - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign(Object.assign({}, getCheckedFacetValues()), buildPriceUrlParameterObject())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addPriceRangeChangeListeners() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeLowerBoundaryInput = document.querySelector(`.blm-price-range-input--lower-${currentSearchRequestState.request_id}`); - const priceRangeUpperBoundaryInput = document.querySelector(`.blm-price-range-input--upper-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeLowerBoundaryInput && priceRangeUpperBoundaryInput) { - priceRangeLowerBoundaryInput.removeEventListener('change', priceRangeChangeListener); - priceRangeLowerBoundaryInput.addEventListener('change', priceRangeChangeListener); - priceRangeUpperBoundaryInput.removeEventListener('change', priceRangeChangeListener); - priceRangeUpperBoundaryInput.addEventListener('change', priceRangeChangeListener); - } - } - function removePriceRangeChangeListeners() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeLowerBoundaryInput = document.querySelector(`.blm-price-range-input--lower-${currentSearchRequestState.request_id}`); - const priceRangeUpperBoundaryInput = document.querySelector(`.blm-price-range-input--upper-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeLowerBoundaryInput && priceRangeUpperBoundaryInput) { - priceRangeLowerBoundaryInput.removeEventListener('change', priceRangeChangeListener); - priceRangeUpperBoundaryInput.removeEventListener('change', priceRangeChangeListener); - } - } - - const contexts = new WeakMap(); - const intersectionListener = config => { - return entries => { - var _a; - const first = entries[0]; - if (!first || first.intersectionRatio <= 0) { - return; - } - const connectorConfigObject = ((_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config) || {}; - const currentStart = connectorConfigObject.start || 0; - connectorConfigObject.start = currentStart + config.search.items_per_page; - incrementParameterInUrl(PARAMETER_NAME_PAGE); - initiateSearch().catch(error => { - decrementParameterInUrl(PARAMETER_NAME_PAGE); - console.error(error); - }); - }; - }; - function addScrollListener() { - var _a, _b; - const config = buildSearchConfig(); - if (((_a = config.search) === null || _a === void 0 ? void 0 : _a.infinite_scroll) && !document.querySelector('.blm-scroll-indicator')) { - // Add listeners in re-entrant fashion - const searchResultsContainerElement = getSearchResultsContainerElement(); - const ctx = contexts.get(searchResultsContainerElement) || {}; - // Clean out old ctx so we don't duplocate anything - removeScrollListener(); - const indicatorElement = document.createElement('div'); - indicatorElement.classList.add('blm-scroll-indicator'); - const loaderElement = document.createElement('div'); - loaderElement.classList.add('blm-scroll-indicator__loading'); - indicatorElement.appendChild(loaderElement); - (_b = searchResultsContainerElement === null || searchResultsContainerElement === void 0 ? void 0 : searchResultsContainerElement.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(indicatorElement, searchResultsContainerElement.nextSibling); - const scrollIndicator = document.querySelector('.blm-scroll-indicator'); - const intersectionObserver = new IntersectionObserver(intersectionListener(config)); - ctx.observer = intersectionObserver; - ctx.indicator = indicatorElement; - if (scrollIndicator) { - intersectionObserver.observe(scrollIndicator); - } - } - } - function removeScrollListener() { - var _a, _b; - const searchResultsContainerElement = getSearchResultsContainerElement(); - const ctx = contexts.get(searchResultsContainerElement) || {}; - // Clean out old ctx - if (ctx) { - (_a = ctx.observer) === null || _a === void 0 ? void 0 : _a.disconnect(); - (_b = ctx.indicator) === null || _b === void 0 ? void 0 : _b.remove(); - } - } - - const sidebarControlButtonClickHandler = () => { - const sidebarContentElement = document.querySelector('.blm-product-search-sidebar-content'); - if (sidebarContentElement === null || sidebarContentElement === void 0 ? void 0 : sidebarContentElement.classList.contains('blm-open')) { - sidebarContentElement === null || sidebarContentElement === void 0 ? void 0 : sidebarContentElement.classList.remove('blm-open'); - document.body.classList.remove('blm-out-of-view'); - updateParameterInUrl(PARAMETER_NAME_FILTERS_PANEL, ''); - } else { - document.body.classList.add('blm-out-of-view'); - sidebarContentElement === null || sidebarContentElement === void 0 ? void 0 : sidebarContentElement.classList.add('blm-open'); - updateParameterInUrl(PARAMETER_NAME_FILTERS_PANEL, 'on'); - } - }; - function addSidebarControlButtonClickListener() { - const sidebarControlButtons = document.querySelectorAll('.blm-product-search-control-button--sidebar'); - // Apply listeners in re-entrant fashion - sidebarControlButtons.forEach(button => { - button.removeEventListener('click', sidebarControlButtonClickHandler); - button.addEventListener('click', sidebarControlButtonClickHandler); - }); - } - function removeSidebarControlButtonClickListener() { - const sidebarControlButtons = document.querySelectorAll('.blm-product-search-control-button--sidebar'); - // Apply listeners in re-entrant fashion - sidebarControlButtons.forEach(button => { - button.removeEventListener('click', sidebarControlButtonClickHandler); - }); - } - - const sortSelectChangeListener = event => { - var _a; - updateParameterInUrl(PARAMETER_NAME_SORT, (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value); - resetLoadingIndicator(); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addSortSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const sortSelector = document.querySelector(`#sort-by-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sortSelector) { - sortSelector.removeEventListener('change', sortSelectChangeListener); - sortSelector.addEventListener('change', sortSelectChangeListener); - } - } - function removeSortSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const sortSelector = document.querySelector(`#sort-by-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sortSelector) { - sortSelector.removeEventListener('change', sortSelectChangeListener); - } - } - - const listeners = new WeakMap(); - const swatchElementHoverListener = dependencies => { - const { - result, - swatchItems, - swatchIndex - } = dependencies; - return event => { - swatchItems.forEach(swatchItem => { - swatchItem.classList.remove('active'); - }); - event.target.classList.add('active'); - // Update image - const imageContainer = result.querySelectorAll('.blm-product-search-image-container'); - imageContainer.forEach(imageItems => { - imageItems.querySelectorAll('.blm-product-search-swatch-image').forEach((image, i) => { - image.style.display = 'none'; - if (swatchIndex === i) { - image.style.display = 'block'; - } - }); - }); - // Update price - result.querySelectorAll('.blm-product-search-details-container__price').forEach((price, index) => { - price.classList.remove('active'); - if (swatchIndex === index) { - price.classList.add('active'); - } - }); - }; - }; - function addSwatchElementHoverListener() { - document.querySelectorAll('.blm-product-search__result').forEach(result => { - const swatchContainers = result.querySelectorAll('.blm-product-search-swatch-container'); - swatchContainers.forEach(swatchContainer => { - const swatchItems = swatchContainer.querySelectorAll('.blm-product-search-swatch-container__swatch'); - // Apply listeners in re-entrant fashion - swatchItems.forEach((swatchItem, swatchIndex) => { - const old = listeners.get(swatchItem); - if (old) swatchItem.removeEventListener('mouseover', old); - const listener = swatchElementHoverListener({ - result, - swatchItems, - swatchIndex - }); - listeners.set(swatchItem, listener); - swatchItem.addEventListener('mouseover', listener); - }); - }); - }); - } - function removeSwatchElementHoverListener() { - document.querySelectorAll('.blm-product-search__result').forEach(result => { - const swatchContainers = result.querySelectorAll('.blm-product-search-swatch-container'); - swatchContainers.forEach(swatchContainer => { - const swatchItems = swatchContainer.querySelectorAll('.blm-product-search-swatch-container__swatch'); - // Apply listeners in re-entrant fashion - swatchItems.forEach(swatchItem => { - const old = listeners.get(swatchItem); - if (old) swatchItem.removeEventListener('mouseover', old); - }); - }); - }); - } - - const log = Debug('br:search'); - function buildDefaultSearchRequestState(options) { - const { - isCategoryPage - } = options; - return { - request_id: 0, - price_range_max_value: 0, - price_range_min_value: 0, - is_first_request: true, - is_category_page: isCategoryPage, - category_to_load: '', - pollIntervalId: void 0, - currentElement: null - }; - } - function buildProductSearchModule({ - isCategoryPage - } = { - isCategoryPage: false - }) { - var _a, _b, _c; - log('Build Search Module:', '4.0.0'); - let currentSearchRequestState = buildDefaultSearchRequestState({ - isCategoryPage - }); - // Provide module compatibility errors - if (isCategoryPage) { - // If we see a search module and no category module, we can assume the - // search module loaded already. - if (((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) && !((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) { - console.warn('Search and catalog modules are not compatible with each other at this time. Please only load one of them. Undefined behavior may occur.'); - } - // If a catalog module is loaded, this search module may have issues. - } else if ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category) { - console.warn('Search and catalog modules are not compatible with each other at this time. Please only load one of them. Undefined behavior may occur.'); - } - return { - setCurrentSearchRequestState: requestState => { - currentSearchRequestState = requestState; - }, - getCurrentSearchRequestState: () => currentSearchRequestState, - load: async categoryToLoad => { - await initPolling(isCategoryPage, categoryToLoad); - } - }; - } - async function initPolling(isCategoryPage = false, categoryToLoad) { - let state = getCurrentSearchRequestState(); - window.clearInterval(state.pollIntervalId); - const doPoll = async () => { - state = getCurrentSearchRequestState(); - const currentElement = state.currentElement; - const foundElement = getSearchResultsContainerElement(); - if (currentElement && !foundElement) { - // Teardown this module to put it in a waiting state - updateCurrentSearchRequestState({ - currentElement: null - }); - moduleWillUnmount(); - } else if (!currentElement && foundElement) { - updateCurrentSearchRequestState({ - currentElement: foundElement - }); - await moduleWillMount(isCategoryPage, categoryToLoad); - } - }; - if (!state.pollIntervalId) log('Polling initialized'); - // Begin the polling service. - // eslint-disable-next-line @typescript-eslint/no-misused-promises - const pollTimer = window.setInterval(doPoll, 100); - updateCurrentSearchRequestState({ - pollIntervalId: pollTimer - }); - // We execute the poll immediately so if we have a script that is "smarter" - // about when all conditions are ready for the module, there is a path to have - // an immediate initialization. - await doPoll(); - } - function moduleWillUnmount() { - var _a, _b; - log('Umounting module...'); - const state = getCurrentSearchRequestState(); - (_a = state.afterLoadedObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); - (_b = getSearchResultsContainerElement()) === null || _b === void 0 ? void 0 : _b.classList.remove('blm-has-loaded'); - unmountSaveScrollPosition(); - removeScrollListener(); - // eslint-disable-next-line @typescript-eslint/no-misused-promises - window.removeEventListener('popstate', popStateWindowEvent); - removePriceRangeChangeListeners(); - removeClearPriceRangeValueButtonClickListener(); - removeClearSelectedFacetButtonClickListener(); - removeClearAllSelectedFacetsButtonClickListener(); - removeSidebarControlButtonClickListener(); - removeFacetCheckboxChangeListener(); - removeLoadMoreFacetGroupsButtonClickListener(); - removeLoadMoreFacetValuesButtonClickListener(); - removeFacetSearchInputChangeListener(); - removePageSizeSelectChangeListener(); - removeSortSelectChangeListener(); - removeGroupbySelectChangeListener(); - removePaginationContainerClickListener(); - removeSwatchElementHoverListener(); - } - async function moduleWillMount(isCategoryPage = false, categoryToLoad) { - log('Mounting module...'); - if (isCategoryPage && categoryToLoad) { - updateCurrentSearchRequestState({ - category_to_load: categoryToLoad - }); - } - if (!areRequirementsMet()) { - log('Search/Category module requirements aren\'t met.'); - return; - } - storeSegmentationPixelData(); - // Add mutation observer on container, - // so it needs to be here before the first actual API call - afterElementsLoaded(() => { - var _a; - log('Search/Category module\'s content has loaded.'); - // Add a class to show that the module's content has loaded - (_a = getSearchResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.classList.add('blm-has-loaded'); - setupSavingScrollPosition(); - // If infinite scroll is on then add intersection observer - addScrollListener(); - addChangeListeners(); - }); - // Initiate search with config values and URL parameters - await initiateSearch(); - restoreScrollPosition(); - } - function areRequirementsMet() { - var _a; - const config = buildSearchConfig(); - invariant(config.account_id, 'account_id must be set'); - invariant(config.domain_key, 'domain_key must be set'); - invariant(config.default_search_parameter, 'default_search_parameter must be set'); - invariant((_a = config === null || config === void 0 ? void 0 : config.search) === null || _a === void 0 ? void 0 : _a.selector, 'the selector of search results container element must be set'); - // this checks if the element is in the DOM - getSearchResultsContainerElement(); - const urlParameters = new URLSearchParams(window.location.search); - const searchPageHasQueryToLoad = config.search.is_search_page && urlParameters.has(config.default_search_parameter); - const categoryPageHasCategoryToLoad = config.search.is_category_page && (urlParameters.has(config.default_search_parameter) || config.search.category_id); - return searchPageHasQueryToLoad || categoryPageHasCategoryToLoad; - } - function storeSegmentationPixelData() { - const segmentationData = extractSegmentationCookie(); - if (segmentationData) { - const br_data = window.br_data || {}; - br_data[COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS] = segmentationData; - } - } - async function initiateSearch(options = { - toReplace: false - }) { - var _a, _b, _c, _d; - log('Initiate Search'); - const requestContextId = generateRequestId(); - updateCurrentSearchRequestState({ - request_id: requestContextId - }); - const config = buildSearchConfig(); - const apiCallParameters = buildApiCallParameters(); - log('Fetch search results with params:', apiCallParameters); - const response = await getSearchResults(apiCallParameters); - log('Search results:', response); - // We need to make sure overlapping calls to initiateSearch don't cause race - // conditions, so this pattern discards the earliest requests made and only - // allows the most recent request to pass - if (requestContextId !== getCurrentSearchRequestState().request_id) { - return; - } - if (response === null || response === void 0 ? void 0 : response.keywordRedirect) { - applyKeywordRedirection(response); - return; - } - // Builds template data - const templateData = buildTemplateData(response); - // Takes care of scroll loader - const scrollLoader = document.querySelector('.blm-scroll-indicator__loading'); - const notEnoughProducts = (templateData === null || templateData === void 0 ? void 0 : templateData.grouped_products) ? (((_a = templateData === null || templateData === void 0 ? void 0 : templateData.grouped_products) === null || _a === void 0 ? void 0 : _a.groups) || []).length < Number(apiCallParameters.rows) : !templateData.products.length || templateData.number_of_results < Number(apiCallParameters.rows); - if (scrollLoader && notEnoughProducts) { - scrollLoader.remove(); - decrementParameterInUrl(PARAMETER_NAME_PAGE); - } - const currentSearchRequestState = getCurrentSearchRequestState(); - if (currentSearchRequestState.is_first_request || !config.search.infinite_scroll || options.toReplace) { - const container = getSearchResultsContainerElement(); - if (container) { - log('Render with data: ', templateData); - container.innerHTML = ejs.render((((_b = config.search) === null || _b === void 0 ? void 0 : _b.template) || '').replace('%%-PRODUCT_LIST_TEMPLATE-%%', ((_c = config.search) === null || _c === void 0 ? void 0 : _c.product_list_template) || '').replace(/%%-REQUEST_ID-%%/g, currentSearchRequestState.request_id.toString()), templateData); - window.scrollTo(0, 0); - } - } else if (config.search.infinite_scroll) { - const resultElements = ejs.render(((_d = config.search) === null || _d === void 0 ? void 0 : _d.product_list_template) || '', templateData); - getSearchResultsListContainerElement().insertAdjacentHTML('beforeend', resultElements); - } - // Reapply listeners - addChangeListeners(); - // adds swatch hover listener to newly added elements as well - addSwatchElementHoverListener(); - // marks as initial call happened - updateCurrentSearchRequestState({ - is_first_request: false - }); - } - /** - * Attempts to get the search request state from the existing module - */ - function getCurrentSearchRequestState() { - var _a, _b, _c; - return ((_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.getCurrentSearchRequestState()) || buildDefaultSearchRequestState({ - isCategoryPage: false - }); - } - function updateCurrentSearchRequestState(state) { - var _a, _b, _c; - (_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.setCurrentSearchRequestState(Object.assign(Object.assign({}, getCurrentSearchRequestState()), state)); - } - function afterElementsLoaded(afterLoadCallback) { - const state = getCurrentSearchRequestState(); - const searchElement = getSearchResultsContainerElement(); - // Clear out existing observers to make this method re-entrant. - if (state.afterLoadedObserver) { - state.afterLoadedObserver.disconnect(); - } - // Early exit if the element does not exist so we don't cause errors - if (!searchElement) { - return; - } - // Perform start up check to see if elements already exists, if they do we do - // not need mutation observation - const existingNodes = searchElement.querySelector('.blm-results'); - if (existingNodes) { - afterLoadCallback(); - return; - } - // Without the Element existing, we now watch the entry DOM node for mutations - // until the required elements are added - let observer = void 0; - const mutationObserverCallback = mutationsList => { - const productListAdded = mutationsList.find(mutationRecord => mutationRecord.type === 'childList' && Array.from(mutationRecord.addedNodes).find(node => node.classList && node.classList.contains('blm-results'))); - if (productListAdded) { - // Here we can be sure that the template is rendered into the DOM - afterLoadCallback(); - // Stop the observer - observer === null || observer === void 0 ? void 0 : observer.disconnect(); - } - }; - observer = new MutationObserver(mutationObserverCallback); - observer.observe(searchElement, { - childList: true, - subtree: true - }); - } - async function popStateWindowEvent() { - await initiateSearch({ - toReplace: true - }); - } - function addChangeListeners() { - // When we're going back in history, we want to initiate - // eslint-disable-next-line @typescript-eslint/no-misused-promises - window.removeEventListener('popstate', popStateWindowEvent); - // eslint-disable-next-line @typescript-eslint/no-misused-promises - window.addEventListener('popstate', popStateWindowEvent); - addPriceRangeChangeListeners(); - addClearPriceRangeValueButtonClickListener(); - addClearSelectedFacetButtonClickListener(); - addClearAllSelectedFacetsButtonClickListener(); - if (document.querySelector('.blm-product-search-sidebar')) { - addSidebarControlButtonClickListener(); - addFacetCheckboxChangeListener(); - addLoadMoreFacetGroupsButtonClickListener(); - addLoadMoreFacetValuesButtonClickListener(); - addFacetSearchInputChangeListener(); - // Show the initial number of facets on load - resetFacetGroups(); - } - addPageSizeSelectChangeListener(); - addSortSelectChangeListener(); - addGroupbySelectChangeListener(); - addPaginationContainerClickListener(); - addSwatchElementHoverListener(); - } - function buildTemplateData(response) { - var _a; - const config = buildSearchConfig(); - // map values from API response - const templateData = mapSearchApiResponse(response); - // add stored keyword redirection info - const storedKeywordRedirect = JSON.parse(localStorage.getItem('keywordRedirect') || '{}'); - if (storedKeywordRedirect === null || storedKeywordRedirect === void 0 ? void 0 : storedKeywordRedirect.redirected_query) { - templateData.keywordRedirect = storedKeywordRedirect; - localStorage.removeItem('keywordRedirect'); - } - const urlParameters = new URLSearchParams(window.location.search); - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(templateData).includes(key)) { - templateData[key] = value; - } - } - if (urlParameters.has(PARAMETER_NAME_SIZE)) { - templateData.size = Number.parseInt(urlParameters.get(PARAMETER_NAME_SIZE) || '', 10); - } else { - templateData.size = Number.parseInt(config.search.items_per_page.toString(), 10); - } - templateData.checkedFacets = getFacetsFromUrl(); - templateData.selectedFilterItems = ((templateData === null || templateData === void 0 ? void 0 : templateData.facets) || []).reduce((all, facet) => { - if (facet.section.length > 0) { - facet.section.forEach(item => { - var _a, _b, _c; - if (templateData.checkedFacets && facet.original_title in templateData.checkedFacets && ((_c = (_b = (_a = templateData.checkedFacets) === null || _a === void 0 ? void 0 : _a[facet.original_title]) === null || _b === void 0 ? void 0 : _b.includes) === null || _c === void 0 ? void 0 : _c.call(_b, escapeSpecialCharacters(item.id)))) { - (all || []).push({ - checkbox_id: `${facet.original_title}[${escapeSpecialCharacters(item.name)}]`, - label: item.name - }); - } - }); - } - return all; - }, []); - let currentSearchRequestState = getCurrentSearchRequestState(); - // This fixes the price range facet when the facet has no valid range - if ('minPrice' in templateData && 'maxPrice' in templateData && currentSearchRequestState.price_range_min_value === 0 && currentSearchRequestState.price_range_max_value === 0) { - updateCurrentSearchRequestState({ - price_range_min_value: Math.floor(Number(templateData.minPrice)), - price_range_max_value: Math.ceil(Number(templateData.maxPrice)) - }); - } - currentSearchRequestState = getCurrentSearchRequestState(); - templateData.priceRangeFacet = { - start: currentSearchRequestState.price_range_min_value, - end: currentSearchRequestState.price_range_max_value - }; - if (!((_a = config === null || config === void 0 ? void 0 : config.search) === null || _a === void 0 ? void 0 : _a.infinite_scroll)) { - templateData.paginationData = buildPaginationData(templateData); - } - templateData.isFiltersPanelOpened = urlParameters.has(PARAMETER_NAME_FILTERS_PANEL); - templateData.defaultMaxColorSwatches = MAX_COLOR_SWATCHES; - templateData.mobileView = isMobileView; - templateData.escapeSpecialCharacters = escapeSpecialCharacters; - templateData.selectedColors = getSelectedColors(); - templateData.formatMoney = templateData.formatMoney || config.format_money; - return templateData; - } - function buildApiCallParameters() { - var _a, _b, _c, _d, _e; - const config = buildSearchConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentSearchRequestState = getCurrentSearchRequestState(); - const apiParameters = Object.assign(Object.assign(Object.assign(Object.assign({}, ((_a = config.search) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.search.endpoint - } : {}), ((_b = config.search) === null || _b === void 0 ? void 0 : _b.groupby) ? { - groupby: config.search.groupby - } : {}), ((_c = config.search) === null || _c === void 0 ? void 0 : _c.group_limit) ? { - group_limit: config.search.group_limit - } : {}), { - q: urlParameters.get(config.default_search_parameter || '') || config.search.category_id || '', - rows: (_d = config.search) === null || _d === void 0 ? void 0 : _d.items_per_page, - sort: config === null || config === void 0 ? void 0 : config.sort, - start: config.start, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentSearchRequestState.request_id, - _br_uid_2: config.tracking_cookie || '', - ref_url: config.ref_url, - url: config.url || '', - request_type: config.request_type, - search_type: config.search_type, - fl: (_e = config.search) === null || _e === void 0 ? void 0 : _e.fields, - 'facet.range': config['facet.range'], - 'stats.field': config['stats.field'] - }); - const pageUrlParameter = urlParameters.get(PARAMETER_NAME_PAGE); - if (pageUrlParameter) { - if (config.search.infinite_scroll && currentSearchRequestState.is_first_request) { - apiParameters.start = 0; - apiParameters.rows = Number.parseInt(pageUrlParameter, 10) * config.search.items_per_page; - } else { - apiParameters.start = (Number.parseInt(pageUrlParameter, 10) - 1) * config.search.items_per_page; - } - } - const facets = getFacetsFromUrl(); - if (Object.keys(facets).length) { - /* - And we're setting the 'fq' parameter value as: - 'colors:"gray" OR "black"&fq=reviews:"4.7" OR "5.0"' - so we can use multiple parameter instances in the API call - */ - apiParameters.fq = convertFacetsToQueryString(facets); - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-unsafe-argument - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - const segmentationData = extractSegmentationCookie(); - if (segmentationData) { - apiParameters.brSeg = `seg:${segmentationData}`; - apiParameters.segment = `customer_profile:${segmentationData}`; - apiParameters.cdp_segments = segmentationData; - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === void 0 || isString(apiParameters[key]) && apiParameters[key].length === 0) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function isString(value) { - return typeof value === 'string'; - } - - const categoryModule = buildProductSearchModule({ - isCategoryPage: true - }); - window.BloomreachModules = Object.assign(Object.assign({}, globalBloomreachModules), { - category: categoryModule - }); - categoryModule.load().catch(console.error); - -})(); +var t=i,n=b,r=y,a=!1,o=w,c="locals",s=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],l=s.concat("cache"),u=/^\uFEFF/,d=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/;function p(n,r){var i;if(r.some((function(r){return i=e.resolveInclude(n,r,!0),t.existsSync(i)})))return i}function m(t,n){var r,i=t.filename,a=arguments.length>1;if(t.cache){if(!i)throw new Error("cache option requires a filename");if(r=e.cache.get(i))return r;a||(n=f(i).toString().replace(u,""))}else if(!a){if(!i)throw new Error("Internal EJS error: no file name or template provided");n=f(i).toString().replace(u,"")}return r=e.compile(n,t),t.cache&&e.cache.set(i,r),r}function f(t){return e.fileLoader(t)}function h(n,i){var a=r.shallowCopy(r.createNullProtoObjWherePossible(),i);if(a.filename=function(n,r){var i,a,o=r.views,c=/^[A-Za-z]+:\\|^\//.exec(n);if(c&&c.length)n=n.replace(/^\/*/,""),i=Array.isArray(r.root)?p(n,r.root):e.resolveInclude(n,r.root||"/",!0);else if(r.filename&&(a=e.resolveInclude(n,r.filename),t.existsSync(a)&&(i=a)),!i&&Array.isArray(o)&&(i=p(n,o)),!i&&"function"!=typeof r.includer)throw new Error('Could not find the include file "'+r.escapeFunction(n)+'"');return i}(n,a),"function"==typeof i.includer){var o=i.includer(n,a.filename);if(o&&(o.filename&&(a.filename=o.filename),o.template))return m(a,o.template)}return m(a)}function _(e,t,n,r,i){var a=t.split("\n"),o=Math.max(r-3,0),c=Math.min(a.length,r+3),s=i(n),l=a.slice(o,c).map((function(e,t){var n=t+o+1;return(n==r?" >> ":" ")+n+"| "+e})).join("\n");throw e.path=s,e.message=(s||"ejs")+":"+r+"\n"+l+"\n\n"+e.message,e}function g(e){return e.replace(/;(\s*$)/,"$1")}function v(t,n){var i=r.hasOwnOnlyObject(n),a=r.createNullProtoObjWherePossible();this.templateText=t,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",a.client=i.client||!1,a.escapeFunction=i.escape||i.escapeFunction||r.escapeXML,a.compileDebug=!1!==i.compileDebug,a.debug=!!i.debug,a.filename=i.filename,a.openDelimiter=i.openDelimiter||e.openDelimiter||"<",a.closeDelimiter=i.closeDelimiter||e.closeDelimiter||">",a.delimiter=i.delimiter||e.delimiter||"%",a.strict=i.strict||!1,a.context=i.context,a.cache=i.cache||!1,a.rmWhitespace=i.rmWhitespace,a.root=i.root,a.includer=i.includer,a.outputFunctionName=i.outputFunctionName,a.localsName=i.localsName||e.localsName||c,a.views=i.views,a.async=i.async,a.destructuredLocals=i.destructuredLocals,a.legacyInclude=void 0===i.legacyInclude||!!i.legacyInclude,a.strict?a._with=!1:a._with=void 0===i._with||i._with,this.opts=a,this.regex=this.createRegex()}e.cache=r.cache,e.fileLoader=t.readFileSync,e.localsName=c,e.promiseImpl=new Function("return this;")().Promise,e.resolveInclude=function(e,t,r){var i=n.dirname,a=n.extname,o=(0,n.resolve)(r?t:i(t),e);return a(e)||(o+=".ejs"),o},e.compile=function(e,t){return t&&t.scope&&(a||(console.warn("`scope` option is deprecated and will be removed in EJS 3"),a=!0),t.context||(t.context=t.scope),delete t.scope),new v(e,t).compile()},e.render=function(e,t,n){var i=t||r.createNullProtoObjWherePossible(),a=n||r.createNullProtoObjWherePossible();return 2==arguments.length&&r.shallowCopyFromList(a,i,s),m(a,e)(i)},e.renderFile=function(){var t,n,i,a=Array.prototype.slice.call(arguments),o=a.shift(),c={filename:o};return"function"==typeof arguments[arguments.length-1]&&(t=a.pop()),a.length?(n=a.shift(),a.length?r.shallowCopy(c,a.pop()):(n.settings&&(n.settings.views&&(c.views=n.settings.views),n.settings["view cache"]&&(c.cache=!0),(i=n.settings["view options"])&&r.shallowCopy(c,i)),r.shallowCopyFromList(c,n,l)),c.filename=o):n=r.createNullProtoObjWherePossible(),function(t,n,r){var i;if(!r){if("function"==typeof e.promiseImpl)return new e.promiseImpl((function(e,r){try{e(i=m(t)(n))}catch(e){r(e)}}));throw new Error("Please provide a callback function")}try{i=m(t)(n)}catch(e){return r(e)}r(null,i)}(c,n,t)},e.Template=v,e.clearCache=function(){e.cache.reset()},v.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},v.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=r.escapeRegExpChars(this.opts.delimiter),n=r.escapeRegExpChars(this.opts.openDelimiter),i=r.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,i),new RegExp(e)},compile:function(){var e,t,i,a=this.opts,o="",c="",s=a.escapeFunction,l=a.filename?JSON.stringify(a.filename):"undefined";if(!this.source){if(this.generateSource(),o+=' var __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n',a.outputFunctionName){if(!d.test(a.outputFunctionName))throw new Error("outputFunctionName is not a valid JS identifier.");o+=" var "+a.outputFunctionName+" = __append;\n"}if(a.localsName&&!d.test(a.localsName))throw new Error("localsName is not a valid JS identifier.");if(a.destructuredLocals&&a.destructuredLocals.length){for(var u=" var __locals = ("+a.localsName+" || {}),\n",p=0;p0&&(u+=",\n "),u+=m+" = __locals."+m}o+=u+";\n"}!1!==a._with&&(o+=" with ("+a.localsName+" || {}) {\n",c+=" }\n"),c+=" return __output;\n",this.source=o+this.source+c}e=a.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+l+";\ntry {\n"+this.source+"} catch (e) {\n rethrow(e, __lines, __filename, __line, escapeFn);\n}\n":this.source,a.client&&(e="escapeFn = escapeFn || "+s.toString()+";\n"+e,a.compileDebug&&(e="rethrow = rethrow || "+_.toString()+";\n"+e)),a.strict&&(e='"use strict";\n'+e),a.debug&&console.log(e),a.compileDebug&&a.filename&&(e=e+"\n//# sourceURL="+l+"\n");try{if(a.async)try{i=new Function("return (async function(){}).constructor;")()}catch(e){throw e instanceof SyntaxError?new Error("This environment does not support async/await"):e}else i=Function;t=new i(a.localsName+", escapeFn, include, rethrow",e)}catch(e){throw e instanceof SyntaxError&&(a.filename&&(e.message+=" in "+a.filename),e.message+=" while compiling ejs\n\n",e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n",e.message+="https://github.com/RyanZim/EJS-Lint",a.async||(e.message+="\n",e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}var f=a.client?t:function(e){return t.apply(a.context,[e||r.createNullProtoObjWherePossible(),s,function(t,n){var i=r.shallowCopy(r.createNullProtoObjWherePossible(),e);return n&&(i=r.shallowCopy(i,n)),h(t,a)(i)},_])};if(a.filename&&"function"==typeof Object.defineProperty){var g=a.filename,v=n.basename(g,n.extname(g));try{Object.defineProperty(f,"name",{value:v,writable:!1,enumerable:!1,configurable:!0})}catch(e){}}return f},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")),this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var e=this,t=this.parseTemplateText(),n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter;t&&t.length&&t.forEach((function(a,o){var c;if(0===a.indexOf(r+n)&&0!==a.indexOf(r+n+n)&&(c=t[o+2])!=n+i&&c!="-"+n+i&&c!="_"+n+i)throw new Error('Could not find matching close tag for "'+a+'".');e.scanLine(a)}))},parseTemplateText:function(){for(var e,t=this.templateText,n=this.regex,r=n.exec(t),i=[];r;)0!==(e=r.index)&&(i.push(t.substring(0,e)),t=t.slice(e)),i.push(r[0]),t=t.slice(r[0].length),r=n.exec(t);return t&&i.push(t),i},_addOutput:function(e){if(this.truncate&&(e=e.replace(/^(?:\r\n|\r|\n)/,""),this.truncate=!1),!e)return e;e=(e=(e=(e=e.replace(/\\/g,"\\\\")).replace(/\n/g,"\\n")).replace(/\r/g,"\\r")).replace(/"/g,'\\"'),this.source+=' ; __append("'+e+'")\n'},scanLine:function(e){var t,n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter;switch(t=e.split("\n").length-1,e){case r+n:case r+n+"_":this.mode=v.modes.EVAL;break;case r+n+"=":this.mode=v.modes.ESCAPED;break;case r+n+"-":this.mode=v.modes.RAW;break;case r+n+"#":this.mode=v.modes.COMMENT;break;case r+n+n:this.mode=v.modes.LITERAL,this.source+=' ; __append("'+e.replace(r+n+n,r+n)+'")\n';break;case n+n+i:this.mode=v.modes.LITERAL,this.source+=' ; __append("'+e.replace(n+n+i,n+i)+'")\n';break;case n+i:case"-"+n+i:case"_"+n+i:this.mode==v.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=0===e.indexOf("-")||0===e.indexOf("_");break;default:if(this.mode){switch(this.mode){case v.modes.EVAL:case v.modes.ESCAPED:case v.modes.RAW:e.lastIndexOf("//")>e.lastIndexOf("\n")&&(e+="\n")}switch(this.mode){case v.modes.EVAL:this.source+=" ; "+e+"\n";break;case v.modes.ESCAPED:this.source+=" ; __append(escapeFn("+g(e)+"))\n";break;case v.modes.RAW:this.source+=" ; __append("+g(e)+")\n";break;case v.modes.COMMENT:break;case v.modes.LITERAL:this._addOutput(e)}}else this._addOutput(e)}this.opts.compileDebug&&t&&(this.currentLine+=t,this.source+=" ; __line = "+this.currentLine+"\n")}},e.escapeXML=r.escapeXML,e.__express=e.renderFile,e.VERSION=o,e.name="ejs","undefined"!=typeof window&&(window.ejs=e)}(r);var S="Invariant failed";function k(e,t){if(!e)throw new Error(S)}const E="cdp_segments",x="$",O=16,L="q",j=[{label:"Relevance",value:""},{label:"Price (low - high)",value:"price+asc"},{label:"Price (high - low)",value:"price+desc"},{label:"Name (A - Z)",value:"title+asc"},{label:"Name (Z - A)",value:"title+desc"}],A=0,R="price",q=4,N=2,C=2,I=5,P=6,T="fq",F="filterpanel",M="groupby",$="page",D="size",U="sort",z="search",V="category",W="keyword",J=".main-content";function B(){const e=`${E}=`;return(document.cookie.split("; ").find((t=>t.startsWith(e)))||"").replace(e,"")}const Q={method:"GET",headers:{"Content-Type":"application/json"}};function H(){const e=document.cookie.split("; ").find((e=>e.startsWith("_br_uid_2=")));return e?e.replace("_br_uid_2=",""):"uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55"}const X=(e,t="$",n=!0)=>`${n?t:""}${(e/100).toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2})}${n?"":` ${t}`}`;const Z="https://core.dxpapi.com/api/v1/core/",G=["_br_uid_2","fq","sort"],Y="pid,title,brand,price,sale_price,thumb_image,sku_thumb_images,sku_swatch_images,sku_color_group,url,price_range,sale_price_range,description,is_live,score,skuid,group";function K(e){const t=Object.assign({},e),n=(null==t?void 0:t.endpoint)||Z;return(null==t?void 0:t.endpoint)&&(null==t||delete t.endpoint),(null==t?void 0:t.fl)||(t.fl=Y),`${n}${r=t,`?${Object.keys(r).reduce(((e,t)=>[...e,`${t}=${G.includes(t)?r[t]:encodeURIComponent(r[t])}`]),[]).join("&")}`}`;var r}async function ee(e){return async function(e,t){const n=await fetch(e,t);return await n.json()}(K(e),Q)}var te='<% if (did_you_mean.length) { %>\n \n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from "<%- keywordRedirect.original_query %>"
\n
\n
\n<% } %>\n
\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class="blm-product-search__results"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n',ne='<% function printProduct(product) { %>\n
title="<%- product.variant_name %>"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : \'variant_index\' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !(\'variant_index\' in product) && !selectedColors.length\n ? index === 0\n : \'variant_index\' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style="display: block"<% } %>\n >\n \n
\n <% }); %>\n <% } else { %>\n
\n \n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !(\'variant_index\' in product) && !selectedColors.length\n ? index === 0\n : \'variant_index\' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n \n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n';function re(){var e,t,n;const r=function(){var e;const t=null===(e=null===window||void 0===window?void 0:window.bloomreachConnector)||void 0===e?void 0:e.config;return Object.assign({default_search_parameter:L,url:window.location.href,ref_url:window.location.href,tracking_cookie:H(),format_money:e=>X(e,window.bloomreachDefaultCurrency||x),default_currency:window.bloomreachDefaultCurrency||x},t)}(),i=new URLSearchParams(window.location.search),a=At(),o=Object.assign({display_variants:!1,enabled:!0,endpoint:"",items_per_page:O,facets_included:!0,initial_number_of_facets:I,initial_number_of_facet_values:P,infinite_scroll:!1,selector:J,sorting_options:j,template:te,product_list_template:ne},(null==r?void 0:r.search)?r.search:{}),c=Object.assign(Object.assign({},r),{request_type:z,search_type:a.is_category_page?V:W,start:A,"facet.range":R,"stats.field":R,sort:i.get(U)||"",search:Object.assign(Object.assign(Object.assign({},o),(a.is_category_page?r.category:r.search)||{}),a.category_to_load?{category_id:a.category_to_load}:{})});return null===(n=null===(t=null===(e=c.search)||void 0===e?void 0:e.sorting_options)||void 0===t?void 0:t.sort)||void 0===n||n.call(t,((e,t)=>e.value>t.value?1:-1)),c.search&&(c.search=Object.assign(Object.assign({},c.search),{items_per_page:Number(i.has(D)?i.get(D):c.search.items_per_page),groupby:i.get(M)||c.search.groupby||""})),c}function ie(e){return"grouped_products"in e?function(e){var t;const n=Number(e.page||1),r=e.size||1,i=((null===(t=null==e?void 0:e.grouped_products)||void 0===t?void 0:t.groups)||[]).length;return[{value:"previous",label:"Previous",disabled:n<=1},{value:"next",label:"Next",disabled:it+1)).slice(-N),a=Array(r-n).fill(null).map(((e,t)=>t+(n+1))).slice(0,C);return[...n>1?[{value:"previous",label:"←"}]:[],...n-1>N?[{label:"…",value:(n-N-1).toString()}]:[],...i.map((e=>({value:e.toString()}))),{value:n.toString(),disabled:!0,active:!0},...a.map((e=>({value:e.toString()}))),...n+Ce.replace(/"/g,""").replace(/,/g,"%%-COMMA-%%"),oe=e=>Object.keys(e).map((t=>"price"===t?encodeURIComponent(`${t}:[${e[t].map((e=>`${e||"*"}`)).join(" TO ")}]`):encodeURIComponent(`${t}:${e[t].map((e=>`"${(e=>e.replace(/%%-COMMA-%%/g,",").replace(/"/g,'"'))(e)}"`)).join(" OR ")}`))).join("&fq=");function ce(e){var t;let n=0,r=0;const i=re(),a=Number(e||(null===(t=i.search)||void 0===t?void 0:t.initial_number_of_facets));document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach((e=>{const t=e.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]');n0&&e.setAttribute("style","display: block"),n++,r+=t.length>0?1:0}));const o=At(),c=document.querySelector(`.blm-load-more-facet--${o.request_id}`);0!==document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length&&0!==r||null==c||c.classList.add("blm-hide")}function se(){const e=At(),t=document.querySelector(`.blm-load-more-facet--${e.request_id}`);return k(t),t}function le(){var e,t;const n=re(),r=Number(null===(e=n.search)||void 0===e?void 0:e.initial_number_of_facets),i=Number(null===(t=n.search)||void 0===t?void 0:t.initial_number_of_facet_values);[".blm-dynamic-filter",".blm-product-search-filter-item",".blm-product-search-load-more"].forEach((e=>{document.querySelectorAll(e).forEach((e=>{e.removeAttribute("style")}))})),ce(r-1),document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${i})`).forEach((e=>e.style.display="block")),se().removeAttribute("style")}function ue(){var e;const t=re();k(null===(e=t.search)||void 0===e?void 0:e.selector);return document.querySelector(t.search.selector)}function de(){const e=document.querySelector(".blm-scroll-indicator");if(e){e.innerHTML="";const t=document.createElement("div");t.classList.add("blm-scroll-indicator__loading"),e.appendChild(t)}}function pe(){const e=document.querySelectorAll(".blm-product-search-filter-item__checkbox:checked");return e?Array.from(e).reduce(((e,t)=>Object.assign(Object.assign({},e),{[t.name]:e[t.name]?[...e[t.name]||[],t.value]:[t.value]})),{}):{}}var me;!function(e){e.small="480px",e.medium="680px",e.large="750px",e.xlarge="875px",e.xxlarge="1000px",e.xxxlarge="1200px"}(me||(me={}));const fe=window.matchMedia(`(max-width: ${me.medium})`);function he(e){const t={};for(const n of e.entries())t[n[0]]=n[1];window.history.pushState(t,document.title,`?${e.toString()}`)}function _e(e,t,n){const r=Object.assign(Object.assign({},{valueSerializer:e=>e.toString().replace(/"/g,'\\"'),nameValueSeparator:":"}),n),i=new URLSearchParams(window.location.search);i.delete(e),Array.isArray(t)?t.forEach((t=>{i.append(e,r.valueSerializer(t))})):Object.keys(t).forEach((n=>{i.append(e,`${n}${r.nameValueSeparator}${r.valueSerializer(t[n])}`)})),he(i)}function ge(e,t){const n=new URLSearchParams(window.location.search);"function"==typeof t?n.set(e,t(n.get(e)).replace(/"/g,'\\"')):""===t?n.delete(e):n.set(e,t.replace(/"/g,'\\"')),he(n)}function ve(e){ge(e,(e=>{if(!e)return"2";let t=Number.parseInt(e,10);return(++t).toString()}))}function be(e){ge(e,(e=>{if(!e)return"1";let t=Number.parseInt(e,10);return(--t).toString()}))}function ye(){const e=At(),t=we(),n=document.querySelector(".blm-price-range-input--lower"),r=document.querySelector(".blm-price-range-input--upper");let i=parseFloat(n.value),a=parseFloat(r.value);return i>a&&([i,a]=[a,i]),i===a&&(i>e.price_range_min_value||aObject.assign(Object.assign({},e),{[t.split(":")[0]||""]:(t.split(":")[1]||"").split(",")})),{})}window.matchMedia(`(min-width:${me.medium}) and (max-width: ${me.xlarge})`);var Se=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)},ke="object"==typeof t&&t&&t.Object===Object&&t,Ee="object"==typeof self&&self&&self.Object===Object&&self,xe=ke||Ee||Function("return this")(),Oe=xe,Le=function(){return Oe.Date.now()},je=/\s/;var Ae=function(e){for(var t=e.length;t--&&je.test(e.charAt(t)););return t},Re=/^\s+/;var qe=function(e){return e?e.slice(0,Ae(e)+1).replace(Re,""):e},Ne=xe.Symbol,Ce=Ne,Ie=Object.prototype,Pe=Ie.hasOwnProperty,Te=Ie.toString,Fe=Ce?Ce.toStringTag:void 0;var Me=function(e){var t=Pe.call(e,Fe),n=e[Fe];try{e[Fe]=void 0;var r=!0}catch(e){}var i=Te.call(e);return r&&(t?e[Fe]=n:delete e[Fe]),i},$e=Object.prototype.toString;var De=Me,Ue=function(e){return $e.call(e)},ze=Ne?Ne.toStringTag:void 0;var Ve=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":ze&&ze in Object(e)?De(e):Ue(e)},We=function(e){return null!=e&&"object"==typeof e};var Je=qe,Be=Se,Qe=function(e){return"symbol"==typeof e||We(e)&&"[object Symbol]"==Ve(e)},He=/^[-+]0x[0-9a-f]+$/i,Xe=/^0b[01]+$/i,Ze=/^0o[0-7]+$/i,Ge=parseInt;var Ye=Se,Ke=Le,et=function(e){if("number"==typeof e)return e;if(Qe(e))return NaN;if(Be(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Be(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=Je(e);var n=Xe.test(e);return n||Ze.test(e)?Ge(e.slice(2),n?2:8):He.test(e)?NaN:+e},tt=Math.max,nt=Math.min;var rt=function(e,t,n){var r,i,a,o,c,s,l=0,u=!1,d=!1,p=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function m(t){var n=r,a=i;return r=i=void 0,l=t,o=e.apply(a,n)}function f(e){var n=e-s;return void 0===s||n>=t||n<0||d&&e-l>=a}function h(){var e=Ke();if(f(e))return _(e);c=setTimeout(h,function(e){var n=t-(e-s);return d?nt(n,a-(e-l)):n}(e))}function _(e){return c=void 0,p&&r?m(e):(r=i=void 0,o)}function g(){var e=Ke(),n=f(e);if(r=arguments,i=this,s=e,n){if(void 0===c)return function(e){return l=e,c=setTimeout(h,t),u?m(e):o}(s);if(d)return clearTimeout(c),c=setTimeout(h,t),m(s)}return void 0===c&&(c=setTimeout(h,t)),o}return t=et(t)||0,Ye(n)&&(u=!!n.leading,a=(d="maxWait"in n)?tt(et(n.maxWait)||0,t):a,p="trailing"in n?!!n.trailing:p),g.cancel=function(){void 0!==c&&clearTimeout(c),l=0,r=s=i=c=void 0},g.flush=function(){return void 0===c?o:_(Ke())},g};function it(e){var t,n,r;const i=re(),a=(null==e?void 0:e.facet_counts)?"facets"in e.facet_counts?function(e){var t,n;return Object.assign(Object.assign({facets:null!==(n=null===(t=e.facets)||void 0===t?void 0:t.filter((e=>"text"===e.type||"number"===e.type)).filter((e=>e.value.length)).map(st))&&void 0!==n?n:[]},function(e){var t;const n=null===(t=null==e?void 0:e.filter((e=>"number_range"===e.type)).find((e=>"price"===e.name.toLowerCase())))||void 0===t?void 0:t.value.map((e=>({count:e.count,start:e.start.toString(),end:e.end.toString()})));return n?{priceRanges:n}:{}}(e.facets)),function(e){var t;const n=null==e?void 0:e.filter((e=>"number_stats"===e.type)).map((e=>({name:e.name.toLowerCase(),value:e.value}))),r=null!==(t=null==n?void 0:n.find((e=>"sale price"===e.name||"sale_price"===e.name)))&&void 0!==t?t:null==n?void 0:n.find((e=>"price"===e.name));return(null==r?void 0:r.value)?{maxPrice:r.value.end,minPrice:r.value.start}:{}}(e.facets))}(e.facet_counts):function(e,t){var n,r;return Object.assign(Object.assign(Object.assign({facets:Object.entries(e.facet_fields||{}).filter((e=>e[1].length)).map(at)},function(e){if(null==e?void 0:e.price)return{priceRanges:e.price.map((e=>({count:e.count,start:e.start.toString(),end:e.end.toString()})))};return{}}(e.facet_ranges)),ct(null===(n=null==t?void 0:t.stats_fields)||void 0===n?void 0:n.price)),ct(null===(r=null==t?void 0:t.stats_fields)||void 0===r?void 0:r.sale_price))}(e.facet_counts,e.stats):{facets:[]};return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},a),{products:lt((null===(t=e.response)||void 0===t?void 0:t.docs)||[])}),(null==e?void 0:e.group_response)?{grouped_products:Object.keys(null==e?void 0:e.group_response).reduce(((t,n)=>{var r,i,a,o;return Object.assign(Object.assign({group_category_id:n},null===(r=e.group_response)||void 0===r?void 0:r[n]),{groups:(null===(o=null===(a=null===(i=e.group_response)||void 0===i?void 0:i[n])||void 0===a?void 0:a.groups)||void 0===o?void 0:o.map((e=>{var t;return{title:e.groupValue,products:lt((null===(t=null==e?void 0:e.doclist)||void 0===t?void 0:t.docs)||[])}})))||[]})}),{})}:{}),{did_you_mean:e.did_you_mean||[],number_of_results:Number(null===(n=e.response)||void 0===n?void 0:n.numFound),start:Number(null===(r=e.response)||void 0===r?void 0:r.start),config:i}),e.keywordRedirect?{keywordRedirect:{original_query:e.keywordRedirect["original query"],redirected_query:e.keywordRedirect["redirected query"],redirected_url:e.keywordRedirect["redirected url"]}}:{})}function at(e){return{original_title:e[0],title:e[0].replace("_"," ").replace(/\b\w/g,(e=>e.toUpperCase())),section:e[1].map(ot)}}function ot(e){var t,n,r,i,a;if("name"in e){let r=null!==(t=e.name)&&void 0!==t?t:"";return"true"===e.name?r="Yes":"false"===e.name&&(r="No"),{count:null!==(n=e.count)&&void 0!==n?n:0,name:r,id:r}}return{count:null!==(r=e.count)&&void 0!==r?r:0,name:null!==(i=e.cat_name)&&void 0!==i?i:"",id:null!==(a=e.cat_id)&&void 0!==a?a:""}}function ct(e){return e?{maxPrice:e.max,minPrice:e.min}:{}}function st(e){return{original_title:e.name,title:e.name.replace("_"," ").replace(/\b\w/g,(e=>e.toUpperCase())),section:e.value.map(ot)}}function lt(e){const t=re();return e.reduce(((e,n)=>[...e,...t.search.display_variants?ut(n):[dt(n)]]),[])}function ut(e){return e.variants&&e.variants.length?(dt(e).variants||[]).map(((t,n)=>Object.assign(Object.assign(Object.assign({},dt(e)),t),{variant_index:n}))):[dt(e)]}function dt(e){return Object.assign(Object.assign(Object.assign({},e),{title:e.title,image:e.thumb_image,link:e.url,id:e.pid,price:e.price,sale_price:e.sale_price}),e.variants?{variants:e.variants.map((e=>Object.assign(Object.assign({},e),{sku_color_group:e.sku_color_group,sku_swatch_images:e.sku_swatch_images,sku_thumb_images:e.sku_thumb_images,sku_sale_price:e.sku_sale_price,sku_price:e.sku_price,image:e.sku_thumb_images&&Array.isArray(e.sku_thumb_images)?e.sku_thumb_images[0]:e.sku_swatch_images[0],variant_name:e.sku_color_group})))}:{})}function pt(){const e=At(),t=document.querySelector(`.blm-range-slider__clear-values-button--${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("click",(()=>{de(),_e(T,Object.assign({},pe())),ge($,"1"),Rt({price_range_max_value:0,price_range_min_value:0}),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function mt(){document.querySelectorAll(".blm-product-search-selected-filter__clear").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",(e=>{var t,n,r,i;const a=null===(r=null===(n=null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.parentNode)||void 0===n?void 0:n.dataset)||void 0===r?void 0:r.filterCheckboxId;a&&(null===(i=document.getElementById(a))||void 0===i||i.click())})),e.setAttribute("hasListener","true"))}))}function ft(){const e=document.querySelector(".blm-product-search-selected-filters__clear-all");e&&(e.getAttribute("hasListener")||(e.addEventListener("click",(()=>{de(),_e(T,Object.assign({},ye())),ge($,"1"),Rt({price_range_min_value:0,price_range_max_value:0}),jt({toReplace:!0}).catch(console.error)})),e.setAttribute("hasListener","true")))}function ht(){const e=document.querySelectorAll(".blm-product-search-filter-item__checkbox");e&&e.forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("change",(()=>{de(),_e(T,Object.assign(Object.assign({},pe()),ye())),ge($,"1"),Rt({price_range_min_value:0,price_range_max_value:0}),jt({toReplace:!0}).catch(console.error)})),e.setAttribute("hasListener","true"))}))}function _t(){const e=document.querySelector("#blm-product-search-search-filters__input");e&&(e.getAttribute("hasInputListener")||(e.addEventListener("input",rt((e=>{var t;const n=((null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.value)||"").trim();document.querySelectorAll(".blm-dynamic-filter").forEach((e=>{let t=0;e.querySelectorAll(".blm-product-search-filter-item").forEach((e=>{var r;const i=(null===(r=e.querySelector("label"))||void 0===r?void 0:r.textContent)||"",a=!n||i.toLowerCase().includes(n.toLowerCase()),o=a?"block":"none";t+=a?1:0,e.style.display=o})),e.style.display=t?"block":"none"})),document.querySelectorAll(".blm-product-search-load-more").forEach((e=>{e.style.display="none"})),se().style.display="none",n||le()}),500)),e.setAttribute("hasInputListener","true")))}function gt(){const e=At(),t=document.querySelector(`#groupby-${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("change",(e=>{var t;ge(M,null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.value),de(),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function vt(){const e=se();e&&!e.getAttribute("hasListener")&&(e.addEventListener("click",(()=>{ce()})),e.setAttribute("hasListener","true"))}function bt(){document.querySelectorAll(".blm-product-search-load-more").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",function(){var e;const t=re(),n=Number(null===(e=t.search)||void 0===e?void 0:e.initial_number_of_facet_values);let r=n;const i=n;return e=>{const t=e.target.getAttribute("data-item"),n=document.getElementById(`blm-facet-block-item-${t}`).getElementsByTagName("li");for(let e=r;e=n.length&&(e.target.style.display="none")}}()),e.setAttribute("hasListener","true"))}))}function yt(){const e=At(),t=document.querySelector(`#sort-size-${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("change",(e=>{ge(D,e.target.value),ge($,"1"),de(),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function wt(){const e=At(),t=document.querySelector(`.blm-product-search-pagination__pages--${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("click",(e=>{de();const t=e.target.dataset.value;if(t){switch(e.target.dataset.value){case"previous":be($);break;case"next":ve($);break;default:ge($,t)}jt({toReplace:!0}).catch(console.error)}})),t.setAttribute("hasListener","true")))}function St(){return()=>{de(),_e(T,Object.assign(Object.assign({},pe()),ye())),ge($,"1"),jt({toReplace:!0}).catch(console.error)}}function kt(e){const t=re();return n=>{var r,i;const a=document.querySelector(e);a&&(a.innerHTML=null!==(i=null===(r=t.format_money)||void 0===r?void 0:r.call(t,100*Number(n.target.value)))&&void 0!==i?i:n.target.value)}}function Et(){var e,t;const n=re();if((null===(e=n.search)||void 0===e?void 0:e.infinite_scroll)&&!document.querySelector(".blm-scroll-indicator")){const e=ue(),r=document.createElement("div");r.classList.add("blm-scroll-indicator");const i=document.createElement("div");i.classList.add("blm-scroll-indicator__loading"),r.appendChild(i),null===(t=null==e?void 0:e.parentNode)||void 0===t||t.insertBefore(r,e.nextSibling);const a=document.querySelector(".blm-scroll-indicator"),o=new IntersectionObserver(function(e){return t=>{var n;if(t[0].intersectionRatio<=0)return;const r=(null===(n=null===window||void 0===window?void 0:window.bloomreachConnector)||void 0===n?void 0:n.config)||{},i=r.start||0;r.start=i+e.search.items_per_page,ve($),jt().catch((e=>{r.start=i,be($),console.error(e)}))}}(n));a&&o.observe(a)}}function xt(){document.querySelectorAll(".blm-product-search-control-button--sidebar").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",(()=>{const e=document.querySelector(".blm-product-search-sidebar-content");(null==e?void 0:e.classList.contains("blm-open"))?(null==e||e.classList.remove("blm-open"),document.body.classList.remove("blm-out-of-view"),ge(F,"")):(document.body.classList.add("blm-out-of-view"),null==e||e.classList.add("blm-open"),ge(F,"on"))})),e.setAttribute("hasListener","true"))}))}function Ot(){const e=At(),t=document.querySelector(`#sort-by-${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("change",(e=>{var t;ge(U,null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.value),de(),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function Lt(){document.querySelectorAll(".blm-product-search__result").forEach((e=>{e.querySelectorAll(".blm-product-search-swatch-container").forEach((t=>{const n=t.querySelectorAll(".blm-product-search-swatch-container__swatch");n.forEach(((t,r)=>{t.getAttribute("hasListener")||(t.addEventListener("mouseover",function(e){const{result:t,swatchItems:n,swatchIndex:r}=e;return e=>{n.forEach((e=>{e.classList.remove("active")})),e.target.classList.add("active"),t.querySelectorAll(".blm-product-search-image-container").forEach((e=>{e.querySelectorAll(".blm-product-search-swatch-image").forEach(((e,t)=>{e.style.display="none",r===t&&(e.style.display="block")}))})),t.querySelectorAll(".blm-product-search-details-container__price").forEach(((e,t)=>{e.classList.remove("active"),r===t&&e.classList.add("active")}))}}({result:e,swatchItems:n,swatchIndex:r})),t.setAttribute("hasListener","true"))}))}))}))}async function jt(e={toReplace:!1}){var t,n,i,a;Rt({request_id:Math.floor(1e12+9e12*Math.random())});const o=re(),c=function(){var e,t,n,r,i;const a=re(),o=new URLSearchParams(window.location.search),c=At(),s=Object.assign(Object.assign(Object.assign(Object.assign({},(null===(e=a.search)||void 0===e?void 0:e.endpoint)?{endpoint:a.search.endpoint}:{}),(null===(t=a.search)||void 0===t?void 0:t.groupby)?{groupby:a.search.groupby}:{}),(null===(n=a.search)||void 0===n?void 0:n.group_limit)?{group_limit:a.search.group_limit}:{}),{q:o.get(a.default_search_parameter||"")||a.search.category_id||"",rows:null===(r=a.search)||void 0===r?void 0:r.items_per_page,sort:null==a?void 0:a.sort,start:a.start,account_id:a.account_id,domain_key:a.domain_key,request_id:c.request_id,_br_uid_2:a.tracking_cookie,ref_url:a.ref_url,url:a.url,request_type:a.request_type,search_type:a.search_type,fl:null===(i=a.search)||void 0===i?void 0:i.fields,"facet.range":a["facet.range"],"stats.field":a["stats.field"]}),l=o.get($);l&&(a.search.infinite_scroll&&c.is_first_request?(s.start=0,s.rows=Number.parseInt(l,10)*a.search.items_per_page):s.start=(Number.parseInt(l,10)-1)*a.search.items_per_page);const u=we();Object.keys(u).length&&(s.fq=oe(u));for(const[e,t]of o.entries())Object.keys(s).includes(e)||(s[e]=t);const d=B();d&&(s.brSeg=`seg:${d}`,s.segment=`customer_profile:${d}`,s.cdp_segments=d);a.search.force_v3_facets&&(s["facet.version"]="3.0");return s}(),s=await ee(c);if(null==s?void 0:s.keywordRedirect)return void function(e){var t;if(null==e?void 0:e.keywordRedirect){localStorage.setItem("keywordRedirect",JSON.stringify({original_query:e.keywordRedirect["original query"],redirected_query:e.keywordRedirect["redirected query"],redirected_url:e.keywordRedirect["redirected url"]}));const n=(null===(t=e.keywordRedirect)||void 0===t?void 0:t["redirected url"])||"";window.location.href=`${n.startsWith("http")?"":"https://"}${n}`}}(s);const l=function(e){var t;const n=re(),r=it(e),i=JSON.parse(localStorage.getItem("keywordRedirect")||"{}");(null==i?void 0:i.redirected_query)&&(r.keywordRedirect=i,localStorage.removeItem("keywordRedirect"));const a=new URLSearchParams(window.location.search);for(const[e,t]of a.entries())Object.keys(r).includes(e)||(r[e]=t);a.has(D)?r.size=Number.parseInt(a.get(D)||"",10):r.size=Number.parseInt(n.search.items_per_page.toString(),10);r.checkedFacets=we(),r.selectedFilterItems=((null==r?void 0:r.facets)||[]).reduce(((e,t)=>(t.section.length>0&&t.section.forEach((n=>{var i,a,o;r.checkedFacets&&t.original_title in r.checkedFacets&&(null===(o=null===(a=null===(i=r.checkedFacets)||void 0===i?void 0:i[t.original_title])||void 0===a?void 0:a.includes)||void 0===o?void 0:o.call(a,ae(n.id)))&&(e||[]).push({checkbox_id:`${t.original_title}[${ae(n.name)}]`,label:n.name})})),e)),[]);let o=At();"minPrice"in r&&"maxPrice"in r&&0===o.price_range_min_value&&0===o.price_range_max_value&&Rt({price_range_min_value:Math.floor(Number(r.minPrice)),price_range_max_value:Math.ceil(Number(r.maxPrice))});o=At(),r.priceRangeFacet={start:o.price_range_min_value,end:o.price_range_max_value},(null===(t=null==n?void 0:n.search)||void 0===t?void 0:t.infinite_scroll)||(r.paginationData=ie(r));return r.isFiltersPanelOpened=a.has(F),r.defaultMaxColorSwatches=q,r.mobileView=fe,r.escapeSpecialCharacters=ae,r.selectedColors=function(){const e=we();return Object.keys(e).reduce(((t,n)=>("color"===n.toLowerCase()&&(t=(e[n]||[]).map((e=>e.toLowerCase()))),t)),[])}(),r}(s),u=document.querySelector(".blm-scroll-indicator__loading"),d=(null==l?void 0:l.grouped_products)?((null===(t=null==l?void 0:l.grouped_products)||void 0===t?void 0:t.groups)||[]).length{t=e},getCurrentSearchRequestState:()=>t,load:async t=>{e&&t&&Rt({category_to_load:t}),function(){var e;const t=re();k(t.account_id),k(t.domain_key),k(t.default_search_parameter),k(null===(e=null==t?void 0:t.search)||void 0===e?void 0:e.selector),ue();const n=new URLSearchParams(window.location.search),r=t.search.is_search_page&&n.has(t.default_search_parameter),i=t.search.is_category_page&&(n.has(t.default_search_parameter)||t.search.category_id);return r||i}()&&(function(){const e=B();if(e){(window.br_data||{})[E]=e}}(),function(e){const t={childList:!0,subtree:!0};new MutationObserver((t=>{t.find((e=>"childList"===e.type&&Array.from(e.addedNodes).find((e=>e.classList&&e.classList.contains("blm-results")))))&&e()})).observe(ue(),t)}((()=>{ue().classList.add("blm-has-loaded"),window.onbeforeunload=function(){let e;void 0!==window.pageYOffset?e=window.pageYOffset:void 0!==document.compatMode&&"BackCompat"!==document.compatMode?e=document.documentElement.scrollTop:void 0!==document.body&&(e=document.body.scrollTop);const t=JSON.parse(window.localStorage.getItem("scrollPositions")||"{}");window.localStorage.setItem("scrollPositions",JSON.stringify(Object.assign(Object.assign({},t),{[encodeURI(window.location.href)]:{scrollPosition:e}})))},Et(),function(){window.onpopstate=async()=>{await jt({toReplace:!0})},function(){const e=At(),t=document.querySelector(`.blm-price-range-input--lower-${e.request_id}`),n=document.querySelector(`.blm-price-range-input--upper-${e.request_id}`);t&&n&&(t.getAttribute("hasListener")||(t.addEventListener("change",St()),t.addEventListener("input",kt(".blm-range-slider__values--min")),t.setAttribute("hasListener","true")),n.getAttribute("hasListener")||(n.addEventListener("change",St()),n.addEventListener("input",kt(".blm-range-slider__values--max")),n.setAttribute("hasListener","true")))}(),pt(),mt(),ft(),document.querySelector(".blm-product-search-sidebar")&&(xt(),ht(),vt(),bt(),_t(),le());yt(),Ot(),gt(),wt(),Lt()}()})),await jt(),function(){var e;const t=JSON.parse(window.localStorage.getItem("scrollPositions")||"{}"),n=encodeURI(window.location.href);if(n in t){const r=parseInt(null===(e=t[n])||void 0===e?void 0:e.scrollPosition,10);setTimeout((()=>{document.documentElement.scrollTop=r,document.body.scrollTop=r}),250)}delete t[encodeURI(window.location.href)],window.localStorage.setItem("scrollPositions",JSON.stringify(t))}())}}}({isCategoryPage:!0});window.BloomreachModules=Object.assign(Object.assign({},e),{search:qt}),qt.load().catch(console.error)}(); //# sourceMappingURL=category.js.map diff --git a/view/frontend/web/js/events.js b/view/frontend/web/js/events.js index 5204477..7ee118b 100644 --- a/view/frontend/web/js/events.js +++ b/view/frontend/web/js/events.js @@ -1,2978 +1,10 @@ -(function () { - 'use strict'; - - const AUTOSUGGEST_MINIMUM_QUERY_LENGTH = 2; - const AUTOSUGGEST_TYPED_QUERY_TEMPLATE = '<%= query %>'; - const COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS = 'cdp_segments'; - const COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE = 'customer_profile'; - const DEFAULT_CURRENCY = '$'; - const DEFAULT_PAGE_SIZE = 16; - const DEFAULT_SEARCH_PARAMETER = 'q'; - const DEFAULT_SORTING_OPTIONS = [{ - label: 'Relevance', - value: '' - }, { - label: 'Price (low - high)', - value: 'price+asc' - }, { - label: 'Price (high - low)', - value: 'price+desc' - }, { - label: 'Name (A - Z)', - value: 'title+asc' - }, { - label: 'Name (Z - A)', - value: 'title+desc' - }]; - const DEFAULT_START = 0; - const DEFAULT_WIDGETS_TO_DISPLAY = 4; - const FIELD_NAME_PRICE = 'price'; - const MAX_COLOR_SWATCHES = 4; - const MAX_PAGINATION_NUMBER_BEFORE_CURRENT = 2; - const MAX_PAGINATION_NUMBER_AFTER_CURRENT = 2; - const NUMBER_OF_AUTOSUGGEST_COLLECTIONS = 8; - const NUMBER_OF_AUTOSUGGEST_PRODUCTS = 8; - const NUMBER_OF_AUTOSUGGEST_TERMS = 4; - const NUMBER_OF_FACET_GROUPS = 5; - const NUMBER_OF_FACET_VALUES = 6; - const PARAMETER_NAME_FACETS = 'fq'; - const PARAMETER_NAME_FILTERS_PANEL = 'filterpanel'; - const PARAMETER_NAME_GROUPBY = 'groupby'; - const PARAMETER_NAME_PAGE = 'page'; - const PARAMETER_NAME_SIZE = 'size'; - const PARAMETER_NAME_SORT = 'sort'; - const REQUEST_TYPE_SEARCH = 'search'; - const REQUEST_TYPE_SUGGEST = 'suggest'; - const SEARCH_TYPE_CATEGORY = 'category'; - const SEARCH_TYPE_KEYWORD = 'keyword'; - const SELECTOR_AUTOSUGGEST_INPUT = '.search__input'; - const SELECTOR_SEARCH_RESULTS_CONTAINER = '.main-content'; - /** - * This is the attribute name used to flag an element as an add to cart event - * generator, such as a butto or link. - */ - const ADD_TO_CART_ATTRIBUTE_NAME = 'data-blm-add-to-cart'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the sku value sent in the - * pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_SKU = 'data-blm-add-to-cart-sku'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the prod_id value sent in - * the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_PROD_ID = 'data-blm-add-to-cart-prod-id'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to prevent emitting the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_DISABLE = 'data-blm-add-to-cart-disable'; - const QUICKVIEW_ATTRIBUTE_NAME = 'data-blm-quickview'; - const QUICKVIEW_ATTRIBUTE_SKU = 'data-blm-quickview-sku'; - const QUICKVIEW_ATTRIBUTE_PROD_ID = 'data-blm-quickview-prod-id'; - const QUICKVIEW_ATTRIBUTE_PROD_NAME = 'data-blm-quickview-prod-name'; - - var constants = /*#__PURE__*/Object.freeze({ - __proto__: null, - AUTOSUGGEST_MINIMUM_QUERY_LENGTH: AUTOSUGGEST_MINIMUM_QUERY_LENGTH, - AUTOSUGGEST_TYPED_QUERY_TEMPLATE: AUTOSUGGEST_TYPED_QUERY_TEMPLATE, - COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS: COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS, - COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE: COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE, - DEFAULT_CURRENCY: DEFAULT_CURRENCY, - DEFAULT_PAGE_SIZE: DEFAULT_PAGE_SIZE, - DEFAULT_SEARCH_PARAMETER: DEFAULT_SEARCH_PARAMETER, - DEFAULT_SORTING_OPTIONS: DEFAULT_SORTING_OPTIONS, - DEFAULT_START: DEFAULT_START, - DEFAULT_WIDGETS_TO_DISPLAY: DEFAULT_WIDGETS_TO_DISPLAY, - FIELD_NAME_PRICE: FIELD_NAME_PRICE, - MAX_COLOR_SWATCHES: MAX_COLOR_SWATCHES, - MAX_PAGINATION_NUMBER_BEFORE_CURRENT: MAX_PAGINATION_NUMBER_BEFORE_CURRENT, - MAX_PAGINATION_NUMBER_AFTER_CURRENT: MAX_PAGINATION_NUMBER_AFTER_CURRENT, - NUMBER_OF_AUTOSUGGEST_COLLECTIONS: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - NUMBER_OF_AUTOSUGGEST_PRODUCTS: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - NUMBER_OF_AUTOSUGGEST_TERMS: NUMBER_OF_AUTOSUGGEST_TERMS, - NUMBER_OF_FACET_GROUPS: NUMBER_OF_FACET_GROUPS, - NUMBER_OF_FACET_VALUES: NUMBER_OF_FACET_VALUES, - PARAMETER_NAME_FACETS: PARAMETER_NAME_FACETS, - PARAMETER_NAME_FILTERS_PANEL: PARAMETER_NAME_FILTERS_PANEL, - PARAMETER_NAME_GROUPBY: PARAMETER_NAME_GROUPBY, - PARAMETER_NAME_PAGE: PARAMETER_NAME_PAGE, - PARAMETER_NAME_SIZE: PARAMETER_NAME_SIZE, - PARAMETER_NAME_SORT: PARAMETER_NAME_SORT, - REQUEST_TYPE_SEARCH: REQUEST_TYPE_SEARCH, - REQUEST_TYPE_SUGGEST: REQUEST_TYPE_SUGGEST, - SEARCH_TYPE_CATEGORY: SEARCH_TYPE_CATEGORY, - SEARCH_TYPE_KEYWORD: SEARCH_TYPE_KEYWORD, - SELECTOR_AUTOSUGGEST_INPUT: SELECTOR_AUTOSUGGEST_INPUT, - SELECTOR_SEARCH_RESULTS_CONTAINER: SELECTOR_SEARCH_RESULTS_CONTAINER, - ADD_TO_CART_ATTRIBUTE_NAME: ADD_TO_CART_ATTRIBUTE_NAME, - ADD_TO_CART_ATTRIBUTE_SKU: ADD_TO_CART_ATTRIBUTE_SKU, - ADD_TO_CART_ATTRIBUTE_PROD_ID: ADD_TO_CART_ATTRIBUTE_PROD_ID, - ADD_TO_CART_ATTRIBUTE_DISABLE: ADD_TO_CART_ATTRIBUTE_DISABLE, - QUICKVIEW_ATTRIBUTE_NAME: QUICKVIEW_ATTRIBUTE_NAME, - QUICKVIEW_ATTRIBUTE_SKU: QUICKVIEW_ATTRIBUTE_SKU, - QUICKVIEW_ATTRIBUTE_PROD_ID: QUICKVIEW_ATTRIBUTE_PROD_ID, - QUICKVIEW_ATTRIBUTE_PROD_NAME: QUICKVIEW_ATTRIBUTE_PROD_NAME - }); - - const globalBloomreachModules = Object.assign(Object.assign({}, window.BloomreachModules ? window.BloomreachModules : {}), { - version: '4.0.0', - constants - }); - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getAugmentedNamespace(n) { - var f = n.default; - if (typeof f == "function") { - var a = function () { - return f.apply(this, arguments); - }; - a.prototype = f.prototype; - } else a = {}; - Object.defineProperty(a, '__esModule', {value: true}); - Object.keys(n).forEach(function (k) { - var d = Object.getOwnPropertyDescriptor(n, k); - Object.defineProperty(a, k, d.get ? d : { - enumerable: true, - get: function () { - return n[k]; - } - }); - }); - return a; - } - - var ejs = {}; - - var _polyfillNode_fs = {}; - - var _polyfillNode_fs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _polyfillNode_fs - }); - - var require$$0 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_fs$1); - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // resolves . and .. elements in a path array with directory names there - // must be no slashes, empty elements, or device names (c:\) in the array - // (so also no leading and trailing slashes - it does not distinguish - // relative and absolute paths) - function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; - } - - // Split a filename into [root, dir, basename, ext], unix version - // 'root' is just a slash, or nothing. - var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); - }; - - // path.resolve([from ...], to) - // posix version - function resolve() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : '/'; - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - } - // path.normalize(path) - // posix version - function normalize(path) { - var isPathAbsolute = isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isPathAbsolute).join('/'); - - if (!path && !isPathAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isPathAbsolute ? '/' : '') + path; - } - // posix version - function isAbsolute(path) { - return path.charAt(0) === '/'; - } - - // posix version - function join() { - var paths = Array.prototype.slice.call(arguments, 0); - return normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); - } - - - // path.relative(from, to) - // posix version - function relative(from, to) { - from = resolve(from).substr(1); - to = resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - } - - var sep = '/'; - var delimiter = ':'; - - function dirname(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; - } - - function basename(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; - } - - - function extname(path) { - return splitPath(path)[3]; - } - var _polyfillNode_path = { - extname: extname, - basename: basename, - dirname: dirname, - sep: sep, - delimiter: delimiter, - relative: relative, - join: join, - isAbsolute: isAbsolute, - normalize: normalize, - resolve: resolve - }; - function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; - } - - // String.prototype.substr - negative index don't work in IE8 - var substr = 'ab'.substr(-1) === 'b' ? - function (str, start, len) { return str.substr(start, len) } : - function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } - ; - - var _polyfillNode_path$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - resolve: resolve, - normalize: normalize, - isAbsolute: isAbsolute, - join: join, - relative: relative, - sep: sep, - delimiter: delimiter, - dirname: dirname, - basename: basename, - extname: extname, - 'default': _polyfillNode_path - }); - - var require$$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_path$1); - - var utils = {}; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - var regExpChars = /[|\\{}()[\]^$+*?.]/g; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); }; - - /** - * Escape characters reserved in regular expressions. - * - * If `string` is `undefined` or `null`, the empty string is returned. - * - * @param {String} string Input string - * @return {String} Escaped string - * @static - * @private - */ - exports.escapeRegExpChars = function (string) { - // istanbul ignore if - if (!string) { - return ''; - } - return String(string).replace(regExpChars, '\\$&'); - }; - - var _ENCODE_HTML_RULES = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - var _MATCH_HTML = /[&<>'"]/g; - - function encode_char(c) { - return _ENCODE_HTML_RULES[c] || c; - } - - /** - * Stringified version of constants used by {@link module:utils.escapeXML}. - * - * It is used in the process of generating {@link ClientFunction}s. - * - * @readonly - * @type {String} - */ - - var escapeFuncStr = - 'var _ENCODE_HTML_RULES = {\n' - + ' "&": "&"\n' - + ' , "<": "<"\n' - + ' , ">": ">"\n' - + ' , \'"\': """\n' - + ' , "\'": "'"\n' - + ' }\n' - + ' , _MATCH_HTML = /[&<>\'"]/g;\n' - + 'function encode_char(c) {\n' - + ' return _ENCODE_HTML_RULES[c] || c;\n' - + '};\n'; - - /** - * Escape characters reserved in XML. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @implements {EscapeCallback} - * @param {String} markup Input string - * @return {String} Escaped string - * @static - * @private - */ - - exports.escapeXML = function (markup) { - return markup == undefined - ? '' - : String(markup) - .replace(_MATCH_HTML, encode_char); - }; - exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; - }; - - /** - * Naive copy of properties from one object to another. - * Does not recurse into non-scalar properties - * Does not check to see if the property has a value before copying - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopy = function (to, from) { - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var p in from) { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - return to; - }; - - /** - * Naive copy of a list of key names, from one object to another. - * Only copies property if it is actually defined - * Does not recurse into non-scalar properties - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @param {Array} list List of properties to copy - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopyFromList = function (to, from, list) { - list = list || []; - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var i = 0; i < list.length; i++) { - var p = list[i]; - if (typeof from[p] != 'undefined') { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - } - return to; - }; - - /** - * Simple in-process cache implementation. Does not implement limits of any - * sort. - * - * @implements {Cache} - * @static - * @private - */ - exports.cache = { - _data: {}, - set: function (key, val) { - this._data[key] = val; - }, - get: function (key) { - return this._data[key]; - }, - remove: function (key) { - delete this._data[key]; - }, - reset: function () { - this._data = {}; - } - }; - - /** - * Transforms hyphen case variable into camel case. - * - * @param {String} string Hyphen case string - * @return {String} Camel case string - * @static - * @private - */ - exports.hyphenToCamel = function (str) { - return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); }); - }; - - /** - * Returns a null-prototype object in runtimes that support it - * - * @return {Object} Object, prototype will be set to null where possible - * @static - * @private - */ - exports.createNullProtoObjWherePossible = (function () { - if (typeof Object.create == 'function') { - return function () { - return Object.create(null); - }; - } - if (!({__proto__: null} instanceof Object)) { - return function () { - return {__proto__: null}; - }; - } - // Not possible, just pass through - return function () { - return {}; - }; - })(); - } (utils)); - - var name = "ejs"; - var description = "Embedded JavaScript templates"; - var keywords = [ - "template", - "engine", - "ejs" - ]; - var version = "3.1.8"; - var author = "Matthew Eernisse (http://fleegix.org)"; - var license = "Apache-2.0"; - var bin = { - ejs: "./bin/cli.js" - }; - var main = "./lib/ejs.js"; - var jsdelivr = "ejs.min.js"; - var unpkg = "ejs.min.js"; - var repository = { - type: "git", - url: "git://github.com/mde/ejs.git" - }; - var bugs = "https://github.com/mde/ejs/issues"; - var homepage = "https://github.com/mde/ejs"; - var dependencies = { - jake: "^10.8.5" - }; - var devDependencies = { - browserify: "^16.5.1", - eslint: "^6.8.0", - "git-directory-deploy": "^1.5.1", - jsdoc: "^3.6.7", - "lru-cache": "^4.0.1", - mocha: "^7.1.1", - "uglify-js": "^3.3.16" - }; - var engines = { - node: ">=0.10.0" - }; - var scripts = { - test: "mocha" - }; - var require$$3 = { - name: name, - description: description, - keywords: keywords, - version: version, - author: author, - license: license, - bin: bin, - main: main, - jsdelivr: jsdelivr, - unpkg: unpkg, - repository: repository, - bugs: bugs, - homepage: homepage, - dependencies: dependencies, - devDependencies: devDependencies, - engines: engines, - scripts: scripts - }; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - /** +!function(){"use strict";const e=Object.assign(Object.assign({},window.BloomreachModules?window.BloomreachModules:{}),{version:"3.1.0"});var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(e){var t=e.default;if("function"==typeof t){var n=function(){return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach((function(t){var r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:function(){return e[t]}})})),n}var r=n(Object.freeze({__proto__:null,default:{}}));function i(e,t){for(var n=0,r=e.length-1;r>=0;r--){var i=e[r];"."===i?e.splice(r,1):".."===i?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var o=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,a=function(e){return o.exec(e).slice(1)};function s(){for(var e="",t=!1,n=arguments.length-1;n>=-1&&!t;n--){var r=n>=0?arguments[n]:"/";if("string"!=typeof r)throw new TypeError("Arguments to path.resolve must be strings");r&&(e=r+"/"+e,t="/"===r.charAt(0))}return(t?"/":"")+(e=i(g(e.split("/"),(function(e){return!!e})),!t).join("/"))||"."}function c(e){var t=l(e),n="/"===v(e,-1);return(e=i(g(e.split("/"),(function(e){return!!e})),!t).join("/"))||t||(e="."),e&&n&&(e+="/"),(t?"/":"")+e}function l(e){return"/"===e.charAt(0)}function u(){return c(g(Array.prototype.slice.call(arguments,0),(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))}function p(e,t){function n(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=s(e).substr(1),t=s(t).substr(1);for(var r=n(e.split("/")),i=n(t.split("/")),o=Math.min(r.length,i.length),a=o,c=0;c":">",'"':""","'":"'"},o=/[&<>'"]/g;function a(e){return i[e]||e}function s(){return Function.prototype.toString.call(this)+';\nvar _ENCODE_HTML_RULES = {\n "&": "&"\n , "<": "<"\n , ">": ">"\n , \'"\': """\n , "\'": "'"\n }\n , _MATCH_HTML = /[&<>\'"]/g;\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n};\n'}e.escapeXML=function(e){return null==e?"":String(e).replace(o,a)};try{"function"==typeof Object.defineProperty?Object.defineProperty(e.escapeXML,"toString",{value:s}):e.escapeXML.toString=s}catch(e){console.warn("Unable to set escapeXML.toString (is the Function prototype frozen?)")}e.shallowCopy=function(e,t){if(t=t||{},null!=e)for(var n in t)r(t,n)&&"__proto__"!==n&&"constructor"!==n&&(e[n]=t[n]);return e},e.shallowCopyFromList=function(e,t,n){if(n=n||[],t=t||{},null!=e)for(var i=0;i * @author Tiancheng "Timothy" Gu * @project EJS * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} */ - - /** - * EJS internal functions. - * - * Technically this "module" lies in the same file as {@link module:ejs}, for - * the sake of organization all the private functions re grouped into this - * module. - * - * @module ejs-internal - * @private - */ - - /** - * Embedded JavaScript templating engine. - * - * @module ejs - * @public - */ - - - var fs = require$$0; - var path = require$$1; - var utils$1 = utils; - - var scopeOptionWarned = false; - /** @type {string} */ - var _VERSION_STRING = require$$3.version; - var _DEFAULT_OPEN_DELIMITER = '<'; - var _DEFAULT_CLOSE_DELIMITER = '>'; - var _DEFAULT_DELIMITER = '%'; - var _DEFAULT_LOCALS_NAME = 'locals'; - var _NAME = 'ejs'; - var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; - var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', - 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; - // We don't allow 'cache' option to be passed in the data obj for - // the normal `render` call, but this is where Express 2 & 3 put it - // so we make an exception for `renderFile` - var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); - var _BOM = /^\uFEFF/; - var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; - - /** - * EJS template function cache. This can be a LRU object from lru-cache NPM - * module. By default, it is {@link module:utils.cache}, a simple in-process - * cache that grows continuously. - * - * @type {Cache} - */ - - exports.cache = utils$1.cache; - - /** - * Custom file loader. Useful for template preprocessing or restricting access - * to a certain part of the filesystem. - * - * @type {fileLoader} - */ - - exports.fileLoader = fs.readFileSync; - - /** - * Name of the object containing the locals. - * - * This variable is overridden by {@link Options}`.localsName` if it is not - * `undefined`. - * - * @type {String} - * @public - */ - - exports.localsName = _DEFAULT_LOCALS_NAME; - - /** - * Promise implementation -- defaults to the native implementation if available - * This is mostly just for testability - * - * @type {PromiseConstructorLike} - * @public - */ - - exports.promiseImpl = (new Function('return this;'))().Promise; - - /** - * Get the path to the included file from the parent file path and the - * specified path. - * - * @param {String} name specified path - * @param {String} filename parent file path - * @param {Boolean} [isDir=false] whether the parent file path is a directory - * @return {String} - */ - exports.resolveInclude = function(name, filename, isDir) { - var dirname = path.dirname; - var extname = path.extname; - var resolve = path.resolve; - var includePath = resolve(isDir ? filename : dirname(filename), name); - var ext = extname(name); - if (!ext) { - includePath += '.ejs'; - } - return includePath; - }; - - /** - * Try to resolve file path on multiple directories - * - * @param {String} name specified path - * @param {Array} paths list of possible parent directory paths - * @return {String} - */ - function resolvePaths(name, paths) { - var filePath; - if (paths.some(function (v) { - filePath = exports.resolveInclude(name, v, true); - return fs.existsSync(filePath); - })) { - return filePath; - } - } - - /** - * Get the path to the included file by Options - * - * @param {String} path specified path - * @param {Options} options compilation options - * @return {String} - */ - function getIncludePath(path, options) { - var includePath; - var filePath; - var views = options.views; - var match = /^[A-Za-z]+:\\|^\//.exec(path); - - // Abs path - if (match && match.length) { - path = path.replace(/^\/*/, ''); - if (Array.isArray(options.root)) { - includePath = resolvePaths(path, options.root); - } else { - includePath = exports.resolveInclude(path, options.root || '/', true); - } - } - // Relative paths - else { - // Look relative to a passed filename first - if (options.filename) { - filePath = exports.resolveInclude(path, options.filename); - if (fs.existsSync(filePath)) { - includePath = filePath; - } - } - // Then look in any views directories - if (!includePath && Array.isArray(views)) { - includePath = resolvePaths(path, views); - } - if (!includePath && typeof options.includer !== 'function') { - throw new Error('Could not find the include file "' + - options.escapeFunction(path) + '"'); - } - } - return includePath; - } - - /** - * Get the template from a string or a file, either compiled on-the-fly or - * read from cache (if enabled), and cache the template if needed. - * - * If `template` is not set, the file specified in `options.filename` will be - * read. - * - * If `options.cache` is true, this function reads the file from - * `options.filename` so it must be set prior to calling this function. - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {String} [template] template source - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned. - * @static - */ - - function handleCache(options, template) { - var func; - var filename = options.filename; - var hasTemplate = arguments.length > 1; - - if (options.cache) { - if (!filename) { - throw new Error('cache option requires a filename'); - } - func = exports.cache.get(filename); - if (func) { - return func; - } - if (!hasTemplate) { - template = fileLoader(filename).toString().replace(_BOM, ''); - } - } - else if (!hasTemplate) { - // istanbul ignore if: should not happen at all - if (!filename) { - throw new Error('Internal EJS error: no file name or template ' - + 'provided'); - } - template = fileLoader(filename).toString().replace(_BOM, ''); - } - func = exports.compile(template, options); - if (options.cache) { - exports.cache.set(filename, func); - } - return func; - } - - /** - * Try calling handleCache with the given options and data and call the - * callback with the result. If an error occurs, call the callback with - * the error. Used by renderFile(). - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {Object} data template data - * @param {RenderFileCallback} cb callback - * @static - */ - - function tryHandleCache(options, data, cb) { - var result; - if (!cb) { - if (typeof exports.promiseImpl == 'function') { - return new exports.promiseImpl(function (resolve, reject) { - try { - result = handleCache(options)(data); - resolve(result); - } - catch (err) { - reject(err); - } - }); - } - else { - throw new Error('Please provide a callback function'); - } - } - else { - try { - result = handleCache(options)(data); - } - catch (err) { - return cb(err); - } - - cb(null, result); - } - } - - /** - * fileLoader is independent - * - * @param {String} filePath ejs file path. - * @return {String} The contents of the specified file. - * @static - */ - - function fileLoader(filePath){ - return exports.fileLoader(filePath); - } - - /** - * Get the template function. - * - * If `options.cache` is `true`, then the template is cached. - * - * @memberof module:ejs-internal - * @param {String} path path for the specified file - * @param {Options} options compilation options - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned - * @static - */ - - function includeFile(path, options) { - var opts = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), options); - opts.filename = getIncludePath(path, opts); - if (typeof options.includer === 'function') { - var includerResult = options.includer(path, opts.filename); - if (includerResult) { - if (includerResult.filename) { - opts.filename = includerResult.filename; - } - if (includerResult.template) { - return handleCache(opts, includerResult.template); - } - } - } - return handleCache(opts); - } - - /** - * Re-throw the given `err` in context to the `str` of ejs, `filename`, and - * `lineno`. - * - * @implements {RethrowCallback} - * @memberof module:ejs-internal - * @param {Error} err Error object - * @param {String} str EJS source - * @param {String} flnm file name of the EJS file - * @param {Number} lineno line number of the error - * @param {EscapeCallback} esc - * @static - */ - - function rethrow(err, str, flnm, lineno, esc) { - var lines = str.split('\n'); - var start = Math.max(lineno - 3, 0); - var end = Math.min(lines.length, lineno + 3); - var filename = esc(flnm); - // Error context - var context = lines.slice(start, end).map(function (line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; - } - - function stripSemi(str){ - return str.replace(/;(\s*$)/, '$1'); - } - - /** - * Compile the given `str` of ejs into a template function. - * - * @param {String} template EJS template - * - * @param {Options} [opts] compilation options - * - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `opts.client`, either type might be returned. - * Note that the return type of the function also depends on the value of `opts.async`. - * @public - */ - - exports.compile = function compile(template, opts) { - var templ; - - // v1 compat - // 'scope' is 'context' - // FIXME: Remove this in a future version - if (opts && opts.scope) { - if (!scopeOptionWarned){ - console.warn('`scope` option is deprecated and will be removed in EJS 3'); - scopeOptionWarned = true; - } - if (!opts.context) { - opts.context = opts.scope; - } - delete opts.scope; - } - templ = new Template(template, opts); - return templ.compile(); - }; - - /** - * Render the given `template` of ejs. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} template EJS template - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @return {(String|Promise)} - * Return value type depends on `opts.async`. - * @public - */ - - exports.render = function (template, d, o) { - var data = d || utils$1.createNullProtoObjWherePossible(); - var opts = o || utils$1.createNullProtoObjWherePossible(); - - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 2) { - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); - } - - return handleCache(opts, template)(data); - }; - - /** - * Render an EJS file at the given `path` and callback `cb(err, str)`. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} path path to the EJS file - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @param {RenderFileCallback} cb callback - * @public - */ - - exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments); - var filename = args.shift(); - var cb; - var opts = {filename: filename}; - var data; - var viewOpts; - - // Do we have a callback? - if (typeof arguments[arguments.length - 1] == 'function') { - cb = args.pop(); - } - // Do we have data/opts? - if (args.length) { - // Should always have data obj - data = args.shift(); - // Normal passed opts (data obj + opts obj) - if (args.length) { - // Use shallowCopy so we don't pollute passed in opts obj with new vals - utils$1.shallowCopy(opts, args.pop()); - } - // Special casing for Express (settings + opts-in-data) - else { - // Express 3 and 4 - if (data.settings) { - // Pull a few things from known locations - if (data.settings.views) { - opts.views = data.settings.views; - } - if (data.settings['view cache']) { - opts.cache = true; - } - // Undocumented after Express 2, but still usable, esp. for - // items that are unsafe to be passed along with data, like `root` - viewOpts = data.settings['view options']; - if (viewOpts) { - utils$1.shallowCopy(opts, viewOpts); - } - } - // Express 2 and lower, values set in app.locals, or people who just - // want to pass options in their data. NOTE: These values will override - // anything previously set in settings or settings['view options'] - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); - } - opts.filename = filename; - } - else { - data = utils$1.createNullProtoObjWherePossible(); - } - - return tryHandleCache(opts, data, cb); - }; - - /** - * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. - * @public - */ - - /** - * EJS template class - * @public - */ - exports.Template = Template; - - exports.clearCache = function () { - exports.cache.reset(); - }; - - function Template(text, opts) { - opts = opts || utils$1.createNullProtoObjWherePossible(); - var options = utils$1.createNullProtoObjWherePossible(); - this.templateText = text; - /** @type {string | null} */ - this.mode = null; - this.truncate = false; - this.currentLine = 1; - this.source = ''; - options.client = opts.client || false; - options.escapeFunction = opts.escape || opts.escapeFunction || utils$1.escapeXML; - options.compileDebug = opts.compileDebug !== false; - options.debug = !!opts.debug; - options.filename = opts.filename; - options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; - options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; - options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; - options.strict = opts.strict || false; - options.context = opts.context; - options.cache = opts.cache || false; - options.rmWhitespace = opts.rmWhitespace; - options.root = opts.root; - options.includer = opts.includer; - options.outputFunctionName = opts.outputFunctionName; - options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; - options.views = opts.views; - options.async = opts.async; - options.destructuredLocals = opts.destructuredLocals; - options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; - - if (options.strict) { - options._with = false; - } - else { - options._with = typeof opts._with != 'undefined' ? opts._with : true; - } - - this.opts = options; - - this.regex = this.createRegex(); - } - - Template.modes = { - EVAL: 'eval', - ESCAPED: 'escaped', - RAW: 'raw', - COMMENT: 'comment', - LITERAL: 'literal' - }; - - Template.prototype = { - createRegex: function () { - var str = _REGEX_STRING; - var delim = utils$1.escapeRegExpChars(this.opts.delimiter); - var open = utils$1.escapeRegExpChars(this.opts.openDelimiter); - var close = utils$1.escapeRegExpChars(this.opts.closeDelimiter); - str = str.replace(/%/g, delim) - .replace(//g, close); - return new RegExp(str); - }, - - compile: function () { - /** @type {string} */ - var src; - /** @type {ClientFunction} */ - var fn; - var opts = this.opts; - var prepended = ''; - var appended = ''; - /** @type {EscapeCallback} */ - var escapeFn = opts.escapeFunction; - /** @type {FunctionConstructor} */ - var ctor; - /** @type {string} */ - var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined'; - - if (!this.source) { - this.generateSource(); - prepended += - ' var __output = "";\n' + - ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; - if (opts.outputFunctionName) { - if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) { - throw new Error('outputFunctionName is not a valid JS identifier.'); - } - prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; - } - if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) { - throw new Error('localsName is not a valid JS identifier.'); - } - if (opts.destructuredLocals && opts.destructuredLocals.length) { - var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; - for (var i = 0; i < opts.destructuredLocals.length; i++) { - var name = opts.destructuredLocals[i]; - if (!_JS_IDENTIFIER.test(name)) { - throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.'); - } - if (i > 0) { - destructuring += ',\n '; - } - destructuring += name + ' = __locals.' + name; - } - prepended += destructuring + ';\n'; - } - if (opts._with !== false) { - prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; - appended += ' }' + '\n'; - } - appended += ' return __output;' + '\n'; - this.source = prepended + this.source + appended; - } - - if (opts.compileDebug) { - src = 'var __line = 1' + '\n' - + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' - + ' , __filename = ' + sanitizedFilename + ';' + '\n' - + 'try {' + '\n' - + this.source - + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' - + '}' + '\n'; - } - else { - src = this.source; - } - - if (opts.client) { - src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; - if (opts.compileDebug) { - src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; - } - } - - if (opts.strict) { - src = '"use strict";\n' + src; - } - if (opts.debug) { - console.log(src); - } - if (opts.compileDebug && opts.filename) { - src = src + '\n' - + '//# sourceURL=' + sanitizedFilename + '\n'; - } - - try { - if (opts.async) { - // Have to use generated function for this, since in envs without support, - // it breaks in parsing - try { - ctor = (new Function('return (async function(){}).constructor;'))(); - } - catch(e) { - if (e instanceof SyntaxError) { - throw new Error('This environment does not support async/await'); - } - else { - throw e; - } - } - } - else { - ctor = Function; - } - fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); - } - catch(e) { - // istanbul ignore else - if (e instanceof SyntaxError) { - if (opts.filename) { - e.message += ' in ' + opts.filename; - } - e.message += ' while compiling ejs\n\n'; - e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; - e.message += 'https://github.com/RyanZim/EJS-Lint'; - if (!opts.async) { - e.message += '\n'; - e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; - } - } - throw e; - } - - // Return a callable function which will execute the function - // created by the source-code, with the passed data as locals - // Adds a local `include` function which allows full recursive include - var returnedFn = opts.client ? fn : function anonymous(data) { - var include = function (path, includeData) { - var d = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), data); - if (includeData) { - d = utils$1.shallowCopy(d, includeData); - } - return includeFile(path, opts)(d); - }; - return fn.apply(opts.context, - [data || utils$1.createNullProtoObjWherePossible(), escapeFn, include, rethrow]); - }; - if (opts.filename && typeof Object.defineProperty === 'function') { - var filename = opts.filename; - var basename = path.basename(filename, path.extname(filename)); - try { - Object.defineProperty(returnedFn, 'name', { - value: basename, - writable: false, - enumerable: false, - configurable: true - }); - } catch (e) {/* ignore */} - } - return returnedFn; - }, - - generateSource: function () { - var opts = this.opts; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r` and empty lines don't work well with the `m` flag. - this.templateText = - this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); - - var self = this; - var matches = this.parseTemplateText(); - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - - if (matches && matches.length) { - matches.forEach(function (line, index) { - var closing; - // If this is an opening tag, check for closing tags - // FIXME: May end up with some false positives here - // Better to store modes as k/v with openDelimiter + delimiter as key - // Then this can simply check against the map - if ( line.indexOf(o + d) === 0 // If it is a tag - && line.indexOf(o + d + d) !== 0) { // and is not escaped - closing = matches[index + 2]; - if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { - throw new Error('Could not find matching close tag for "' + line + '".'); - } - } - self.scanLine(line); - }); - } - - }, - - parseTemplateText: function () { - var str = this.templateText; - var pat = this.regex; - var result = pat.exec(str); - var arr = []; - var firstPos; - - while (result) { - firstPos = result.index; - - if (firstPos !== 0) { - arr.push(str.substring(0, firstPos)); - str = str.slice(firstPos); - } - - arr.push(result[0]); - str = str.slice(result[0].length); - result = pat.exec(str); - } - - if (str) { - arr.push(str); - } - - return arr; - }, - - _addOutput: function (line) { - if (this.truncate) { - // Only replace single leading linebreak in the line after - // -%> tag -- this is the single, trailing linebreak - // after the tag that the truncation mode replaces - // Handle Win / Unix / old Mac linebreaks -- do the \r\n - // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, ''); - this.truncate = false; - } - if (!line) { - return line; - } - - // Preserve literal slashes - line = line.replace(/\\/g, '\\\\'); - - // Convert linebreaks - line = line.replace(/\n/g, '\\n'); - line = line.replace(/\r/g, '\\r'); - - // Escape double-quotes - // - this will be the delimiter during execution - line = line.replace(/"/g, '\\"'); - this.source += ' ; __append("' + line + '")' + '\n'; - }, - - scanLine: function (line) { - var self = this; - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - var newLineCount = 0; - - newLineCount = (line.split('\n').length - 1); - - switch (line) { - case o + d: - case o + d + '_': - this.mode = Template.modes.EVAL; - break; - case o + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case o + d + '-': - this.mode = Template.modes.RAW; - break; - case o + d + '#': - this.mode = Template.modes.COMMENT; - break; - case o + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; - break; - case d + d + c: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; - break; - case d + c: - case '-' + d + c: - case '_' + d + c: - if (this.mode == Template.modes.LITERAL) { - this._addOutput(line); - } - - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: - // In script mode, depends on type of tag - if (this.mode) { - // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } - } - switch (this.mode) { - // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; - // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; - break; - // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; - break; - case Template.modes.COMMENT: - // Do nothing - break; - // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - this._addOutput(line); - break; - } - } - // In string mode, just add the output - else { - this._addOutput(line); - } - } - - if (self.opts.compileDebug && newLineCount) { - this.currentLine += newLineCount; - this.source += ' ; __line = ' + this.currentLine + '\n'; - } - } - }; - - /** - * Escape characters reserved in XML. - * - * This is simply an export of {@link module:utils.escapeXML}. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @param {String} markup Input string - * @return {String} Escaped string - * @public - * @func - * */ - exports.escapeXML = utils$1.escapeXML; - - /** - * Express.js support. - * - * This is an alias for {@link module:ejs.renderFile}, in order to support - * Express.js out-of-the-box. - * - * @func - */ - - exports.__express = exports.renderFile; - - /** - * Version of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.VERSION = _VERSION_STRING; - - /** - * Name for detection of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.name = _NAME; - - /* istanbul ignore if */ - if (typeof window != 'undefined') { - window.ejs = exports; - } - } (ejs)); - - // /utils/getRequest.ts - /** - * Method used to initiate the API request - * @remarks The Assignment of the API specific promise is set in the respective API - * @param {string} url - * @param {{}} options - * @returns {Promise} - */ - async function getRequest(url, options) { - /** - * Use of Client-Side Fetch API to retrieve the response - * @type {Response} - */ - const response = await fetch(url, options); - /** - * Formats the response as json and returns the typed promise - * @type {any} - */ - const result = await response.json(); - /** - * Sets the type for the promise - */ - return result; - } - - // utils.requestOptions.ts - /** - * - * @type {{headers: {'Content-Type': string}, method: string}} - */ - const requestOptions = { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }; - - // utils/extractTrackingCookie.ts - /** - * Extracts the tracking cookie from the Bloomreach cookie pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractTrackingCookie() { - const trackingCookie = document.cookie.split('; ').find(cookie => cookie.startsWith('_br_uid_2=')); - return trackingCookie ? trackingCookie.replace('_br_uid_2=', '') : 'uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55'; - } - - // utils/formatAsCurrency.ts - /** - * Formats a value returned as a double into currency - * @param {number} cents - * @param {string} currencySign - * @param {boolean} onFront - * @returns {string} - */ - const formatAsCurrency = (cents, currencySign = '$', onFront = true) => `${onFront ? currencySign : ''}${(cents / 100.0).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 -})}${!onFront ? ` ${currencySign}` : ''}`; - - // utils/generateRequestID.ts - /** - * Generates a randomized request ID that is 13 characters long - * @returns {number} - */ - function generateRequestId() { - // eslint-disable-next-line no-mixed-operators - const requestID = Math.floor(1000000000000 + Math.random() * 9000000000000); - return requestID; - } - - // api-client/constants - // todo Refactor vanilla js / react implementation to either use or not use the constants config - const ENDPOINT_AUTOSUGGEST_API = 'https://suggest.dxpapi.com/api/v2/suggest/'; - const NO_ENCODE_PARAMETERS = ['_br_uid_2', 'fq', 'sort']; - - function buildQueryParameters(apiCallParameters) { - return `?${Object.keys(apiCallParameters).reduce((queryParameters, parameterName) => [...queryParameters, `${parameterName}=${NO_ENCODE_PARAMETERS.includes(parameterName) ? apiCallParameters[parameterName] : encodeURIComponent(apiCallParameters[parameterName])}`], []).join('&')}`; - } - function buildAutosuggestRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_AUTOSUGGEST_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSuggestions(params) { - const url = buildAutosuggestRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - var searchLayoutTemplate = "<% if (did_you_mean.length) { %>\n
\n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from \"<%- keywordRedirect.original_query %>\"
\n
\n
\n<% } %>\n
category<% } else { %>product-search<% } %> blm-results <% if (config.search.facets_included) { %>with-facets<% } %>\">\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class=\"blm-product-search__results\"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n"; - - var searchListTemplate = "<% function printProduct(product) { %>\n
title=\"<%- product.variant_name %>\"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : 'variant_index' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style=\"display: block\"<% } %>\n >\n \"\n />\n
\n <% }); %>\n <% } else { %>\n
\n \"\n />\n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n active<% } %>\"\n style=\"background-image: url('<%= variant.image %>')\"\n >\n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n"; - - var autosuggestTemplate = "<% if (terms.length || productSuggestions.length) { %>\n
\n <% } %>\n"; - - function buildBaseConfig() { - var _a; - const connectorConfig = (_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config; - const config = Object.assign({ - default_search_parameter: DEFAULT_SEARCH_PARAMETER, - url: window.location.href, - ref_url: window.location.href, - tracking_cookie: extractTrackingCookie(), - format_money: cents => formatAsCurrency(cents, window.bloomreachDefaultCurrency || DEFAULT_CURRENCY), - default_currency: window.bloomreachDefaultCurrency || DEFAULT_CURRENCY - }, connectorConfig); - return config; - } - function buildAutosuggestConfig() { - const baseConfig = buildBaseConfig(); - const config = Object.assign(Object.assign({ - request_type: REQUEST_TYPE_SUGGEST - }, baseConfig), { - autosuggest: Object.assign({ - enabled: true, - endpoint: '', - number_of_terms: NUMBER_OF_AUTOSUGGEST_TERMS, - number_of_products: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - number_of_collections: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - selector: SELECTOR_AUTOSUGGEST_INPUT, - template: autosuggestTemplate, - catalog_views: '' - }, baseConfig.autosuggest) - }); - return config; - } - function buildSearchConfig() { - var _a, _b, _c; - const baseConfig = buildBaseConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const state = getCurrentSearchRequestState(); - const defaultSearchProperties = Object.assign({ - display_variants: false, - enabled: true, - endpoint: '', - items_per_page: DEFAULT_PAGE_SIZE, - facets_included: true, - initial_number_of_facets: NUMBER_OF_FACET_GROUPS, - initial_number_of_facet_values: NUMBER_OF_FACET_VALUES, - infinite_scroll: false, - selector: SELECTOR_SEARCH_RESULTS_CONTAINER, - sorting_options: DEFAULT_SORTING_OPTIONS, - template: searchLayoutTemplate, - product_list_template: searchListTemplate - }, (baseConfig === null || baseConfig === void 0 ? void 0 : baseConfig.search) ? baseConfig.search : {}); - const config = Object.assign(Object.assign({}, baseConfig), { - request_type: REQUEST_TYPE_SEARCH, - search_type: state.is_category_page ? SEARCH_TYPE_CATEGORY : SEARCH_TYPE_KEYWORD, - start: DEFAULT_START, - 'facet.range': FIELD_NAME_PRICE, - 'stats.field': FIELD_NAME_PRICE, - sort: urlParameters.get(PARAMETER_NAME_SORT) || '', - search: Object.assign(Object.assign(Object.assign({}, defaultSearchProperties), (state.is_category_page ? baseConfig.category : baseConfig.search) || {}), state.category_to_load ? { - category_id: state.category_to_load - } : {}) - }); - (_c = (_b = (_a = config.search) === null || _a === void 0 ? void 0 : _a.sorting_options) === null || _b === void 0 ? void 0 : _b.sort) === null || _c === void 0 ? void 0 : _c.call(_b, (option1, option2) => option1.value > option2.value ? 1 : -1); - if (config.search) { - config.search = Object.assign(Object.assign({}, config.search), { - items_per_page: Number(urlParameters.has(PARAMETER_NAME_SIZE) ? urlParameters.get(PARAMETER_NAME_SIZE) : config.search.items_per_page), - groupby: urlParameters.get(PARAMETER_NAME_GROUPBY) || config.search.groupby || '' - }); - } - return config; - } - - let memoizedNS; - const NOOP = Object.assign(() => {}, { - warn: () => {}, - error: () => {}, - verbose: () => {} - }); - let colorIndex = -1; - const memoizedColor = new Map(); - /** - * List of colors our debugger can pick from. The colors should be slightly - * desautrated to help with reading and should be highly varied. - */ - const pickColor = ns => { - if (memoizedColor.has(ns)) return memoizedColor.get(ns); - const color = ['#00a3ff', '#ff00a3', '#a3ff00', '#00ffa3', '#a300ff', '#ffaa00', '#00ffaa', '#ff00aa', '#aa00ff', '#00aaff'][++colorIndex % 10] || '#00a3ff'; - memoizedColor.set(ns, color); - return color; - }; - /** - * Creates a simple debug logger system that is only activated by the stored - * state within localStorage.debug. The value in the state can be: - * - * namespace1;namespace2;namespace3;etc - * - * or - * - * namepspace1 - * - * or - * - * * - * - * Where `*` is a wildcard that will activate all namespaces. - */ - const Debug = ns => { - const active = activeNS(); - // If the namespace is not active, return a noop function set - if (!active.has(ns) && !active.has('*')) return NOOP; - const color = pickColor(ns); - const logger = console.log.bind(console, `%c${ns}`, `color: ${color}`); - logger.warn = console.warn.bind(console, `%c${ns}`, `color: ${color}`); - logger.error = console.error.bind(console, `%c${ns}`, `color: ${color}`); - if (active.has(`${ns}:verbose`) || active.has('*')) { - logger.verbose = console.log.bind(console, `%c${ns}:verbose`, `color: ${color}`); - } else { - logger.verbose = () => {}; - } - return logger; - }; - function activeNS() { - if (memoizedNS) return memoizedNS; - const storage = window.localStorage; - if (!storage) return new Set(); - const ns = storage.getItem('debug') || ''; - memoizedNS = new Set(ns.split(';')); - return memoizedNS; - } - - /** - * If a truthy value is false, this throws an error and displays the message for - * the error. - */ - function invariant(truthy, message) { - if (truthy) return; - throw new Error(message); - } - - Debug('br:autosuggest'); - function hideAllDynamicFacetGroups() { - ['.blm-dynamic-filter', '.blm-product-search-filter-item', '.blm-product-search-load-more'].forEach(selector => { - document.querySelectorAll(selector).forEach(item => { - item.removeAttribute('style'); - }); - }); - } - function loadMoreFacetGroups(numberOfFacetGroupsParameter) { - var _a; - let i = 0; - let numberOfHiddenBoxWithVisibleChildren = 0; - const config = buildSearchConfig(); - const numberOfFacetGroups = Number(numberOfFacetGroupsParameter || ((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets)); - document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach(item => { - const visibleChildren = item === null || item === void 0 ? void 0 : item.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]'); - if (i < numberOfFacetGroups && visibleChildren.length > 0) { - item === null || item === void 0 ? void 0 : item.setAttribute('style', 'display: block'); - } - i++; - numberOfHiddenBoxWithVisibleChildren += visibleChildren.length > 0 ? 1 : 0; - }); - const currentSearchRequestState = getCurrentSearchRequestState(); - const loadMoreFacetGroupsElement = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - const numberOfHiddenBoxes = document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length; - if (numberOfHiddenBoxes === 0 || numberOfHiddenBoxWithVisibleChildren === 0) { - loadMoreFacetGroupsElement === null || loadMoreFacetGroupsElement === void 0 ? void 0 : loadMoreFacetGroupsElement.classList.add('blm-hide'); - } - } - function getLoadMoreFacetGroupsElement() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const element = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - invariant(element, 'the element for loading more facet groups must be in the DOM'); - return element; - } - function resetFacetGroups() { - var _a, _b, _c; - const config = buildSearchConfig(); - const numberOfDisplayedFacetGroups = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets); - const numberOfDisplayedFacetValues = Number((_b = config.search) === null || _b === void 0 ? void 0 : _b.initial_number_of_facet_values); - hideAllDynamicFacetGroups(); - loadMoreFacetGroups(numberOfDisplayedFacetGroups - 1); - // init facet items visibility - document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${numberOfDisplayedFacetValues})`).forEach(item => item.style.display = 'block'); - (_c = getLoadMoreFacetGroupsElement()) === null || _c === void 0 ? void 0 : _c.removeAttribute('style'); - } - function getAutosuggestSearchInputElement() { - const config = buildAutosuggestConfig(); - if (!config.autosuggest) return null; - invariant(config.autosuggest.selector, 'the selector of search results container element must be set'); - const autosuggestInputElement = document.querySelector(config.autosuggest.selector); - return autosuggestInputElement; - } - function getAutosuggestResultsContainerElement() { - const autosuggestResultsContainerElement = document.querySelector('.blm-autosuggest-search-results'); - return autosuggestResultsContainerElement; - } - function getAddToCartElements() { - return Array.from(document.querySelectorAll(`[${ADD_TO_CART_ATTRIBUTE_NAME}]`)); - } - function getQuickviewElements() { - return Array.from(document.querySelectorAll(`[${QUICKVIEW_ATTRIBUTE_NAME}]`)); - } - - var breakpoints; - (function (breakpoints) { - breakpoints["small"] = "480px"; - breakpoints["medium"] = "680px"; - breakpoints["large"] = "750px"; - breakpoints["xlarge"] = "875px"; - breakpoints["xxlarge"] = "1000px"; - breakpoints["xxxlarge"] = "1200px"; - })(breakpoints || (breakpoints = {})); - window.matchMedia(`(max-width: ${breakpoints.medium})`); - window.matchMedia(`(min-width:${breakpoints.medium}) and (max-width: ${breakpoints.xlarge})`); - - const log$2 = Debug('br:url'); - function updateUrl(urlParameters) { - var _a, _b, _c, _d; - const historyStateObject = {}; - // eslint-disable-next-line functional/no-loop-statement - for (const pair of urlParameters.entries()) { - historyStateObject[pair[0]] = pair[1]; - } - window.history.pushState(historyStateObject, document.title, `?${urlParameters.toString()}`); - const br_data = window.br_data || {}; - if (br_data.orig_ref_url !== location.href) { - br_data.orig_ref_url = location.href; - log$2('Generating virtual page view event for url update', location.href); - (_b = (_a = window.BrTrk) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.updateBrData(br_data); - (_d = (_c = window.BrTrk) === null || _c === void 0 ? void 0 : _c.getTracker()) === null || _d === void 0 ? void 0 : _d.logPageView(); - } - } - function updateParameterInUrl(parameterName, newValue) { - const urlParameters = new URLSearchParams(window.location.search); - if (typeof newValue === 'function') { - urlParameters.set(parameterName, - // @ts-ignore - newValue(urlParameters.get(parameterName)).replace(/"/g, '\\"')); - } else if (newValue === '') { - urlParameters.delete(parameterName); - } else { - urlParameters.set(parameterName, newValue.replace(/"/g, '\\"')); - } - updateUrl(urlParameters); - } - - const categoryLinkElementClickListener = event => { - var _a, _b, _c; - event.preventDefault(); - const clickedElement = event.target; - const categoryId = ((_a = clickedElement.dataset) === null || _a === void 0 ? void 0 : _a.categoryId) || ''; - const module = ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.search) || ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category); - if (module) { - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - module.load(categoryId).then(() => { - const autosuggestSearchElement = getAutosuggestSearchInputElement(); - const autosuggestResultsElement = getAutosuggestResultsContainerElement(); - if (autosuggestSearchElement) { - autosuggestSearchElement.value = (clickedElement === null || clickedElement === void 0 ? void 0 : clickedElement.textContent) || ''; - } - if (autosuggestResultsElement) { - autosuggestResultsElement.innerHTML = ''; - } - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - return true; - }).catch(console.error); - } - }; - function addCategoryLinkElementClickListener() { - var _a; - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link--category').forEach(categoryLinkElement => { - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.removeEventListener('click', categoryLinkElementClickListener); - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.addEventListener('click', categoryLinkElementClickListener); - }); - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - - function isObject$2(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - var isObject_1 = isObject$2; - - /** Detect free variable `global` from Node.js. */ - - var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; - - var _freeGlobal = freeGlobal$1; - - var freeGlobal = _freeGlobal; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root$2 = freeGlobal || freeSelf || Function('return this')(); - - var _root = root$2; - - var root$1 = _root; - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now$1 = function() { - return root$1.Date.now(); - }; - - var now_1 = now$1; - - /** Used to match a single whitespace character. */ - - var reWhitespace = /\s/; - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ - function trimmedEndIndex$1(string) { - var index = string.length; - - while (index-- && reWhitespace.test(string.charAt(index))) {} - return index; - } - - var _trimmedEndIndex = trimmedEndIndex$1; - - var trimmedEndIndex = _trimmedEndIndex; - - /** Used to match leading whitespace. */ - var reTrimStart = /^\s+/; - - /** - * The base implementation of `_.trim`. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function baseTrim$1(string) { - return string - ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') - : string; - } - - var _baseTrim = baseTrim$1; - - var root = _root; - - /** Built-in value references. */ - var Symbol$2 = root.Symbol; - - var _Symbol = Symbol$2; - - var Symbol$1 = _Symbol; - - /** Used for built-in method references. */ - var objectProto$1 = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto$1.hasOwnProperty; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString$1 = objectProto$1.toString; - - /** Built-in value references. */ - var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag$1(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; - } - - var _getRawTag = getRawTag$1; - - /** Used for built-in method references. */ - - var objectProto = Object.prototype; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString$1(value) { - return nativeObjectToString.call(value); - } - - var _objectToString = objectToString$1; - - var Symbol = _Symbol, - getRawTag = _getRawTag, - objectToString = _objectToString; - - /** `Object#toString` result references. */ - var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - - /** Built-in value references. */ - var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag$1(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - var _baseGetTag = baseGetTag$1; - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - - function isObjectLike$1(value) { - return value != null && typeof value == 'object'; - } - - var isObjectLike_1 = isObjectLike$1; - - var baseGetTag = _baseGetTag, - isObjectLike = isObjectLike_1; - - /** `Object#toString` result references. */ - var symbolTag = '[object Symbol]'; - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol$1(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - var isSymbol_1 = isSymbol$1; - - var baseTrim = _baseTrim, - isObject$1 = isObject_1, - isSymbol = isSymbol_1; - - /** Used as references for various `Number` constants. */ - var NAN = 0 / 0; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Built-in method references without a dependency on `root`. */ - var freeParseInt = parseInt; - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber$1(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject$1(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject$1(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - var toNumber_1 = toNumber$1; - - var isObject = isObject_1, - now = now_1, - toNumber = toNumber_1; - - /** Error message constants. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max, - nativeMin = Math.min; - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. 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 debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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's 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 clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - var debounce_1 = debounce; - - debounce_1(event => { - const query = event.target.value; - const searchInputElement = getAutosuggestSearchInputElement(); - if (!searchInputElement) return; - if (query.length >= AUTOSUGGEST_MINIMUM_QUERY_LENGTH) { - searchInputElement.dataset.originalQuery = query; - suggest(query).catch(console.error); - } else { - const autosuggestResultsContainerElement = getAutosuggestResultsContainerElement(); - if (autosuggestResultsContainerElement) { - autosuggestResultsContainerElement.innerHTML = ''; - } - searchInputElement.dataset.originalQuery = ''; - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - } - }, 500); - - const listeners = new WeakMap(); - const suggestionTermElementClickListener = suggestionTermElement => { - return () => { - var _a, _b; - const { - suggestionText - } = suggestionTermElement.dataset; - const input = getAutosuggestSearchInputElement(); - if (!input) return; - const { - originalQuery - } = input.dataset; - const suggestionData = { - aq: originalQuery, - q: suggestionText, - catalogs: [{ - name: 'example_en' - }] - }; - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('suggest', 'click', suggestionData, {}, true); - }; - }; - function addSuggestionTermElementClickListener() { - var _a; - // Apply listeners in re-entrant fashion - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link').forEach(suggestionTermElement => { - const listener = suggestionTermElementClickListener(suggestionTermElement); - const old = listeners.get(suggestionTermElement); - if (old) suggestionTermElement.removeEventListener('click', old); - listeners.set(suggestionTermElement, listener); - suggestionTermElement === null || suggestionTermElement === void 0 ? void 0 : suggestionTermElement.addEventListener('click', listener); - }); - } - - function mapAutosuggestApiResponse(responseData) { - return isV2Response(responseData) ? mapV2Response(responseData) : mapV1Response(responseData); - } - function mapV2Response(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j; - const config = buildAutosuggestConfig(); - const productSuggestions = ((_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.searchSuggestions) || []; - const suggestions = ((_d = (_c = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.querySuggestions) || []; - const categorySuggestions = ((_f = (_e = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.attributeSuggestions) || []; - const mappedApiResponse = Object.assign(Object.assign({}, ((_g = responseData === null || responseData === void 0 ? void 0 : responseData.queryContext) === null || _g === void 0 ? void 0 : _g.originalQuery) ? { - originalQuery: responseData.queryContext.originalQuery - } : {}), { - terms: [...suggestions.map((term, index) => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.query, - displayText: term.displayText, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.query)}` - }), index === 0 && categorySuggestions ? { - categories: categorySuggestions.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.attributeType - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - })].slice(0, (_h = config.autosuggest) === null || _h === void 0 ? void 0 : _h.number_of_terms), - productSuggestions: [...productSuggestions.map(product => Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: Number((product === null || product === void 0 ? void 0 : product.sale_price) || '0') - }))].slice(0, (_j = config.autosuggest) === null || _j === void 0 ? void 0 : _j.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function isV2Response(responseData) { - return 'suggestionGroups' in responseData; - } - function mapV1Response(responseData) { - var _a, _b; - const config = buildAutosuggestConfig(); - const mappedApiResponse = Object.assign(Object.assign({}, responseData.response.q ? { - originalQuery: responseData.response.q - } : {}), { - terms: [...(responseData.response.suggestions ? responseData.response.suggestions.map(term => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.q, - displayText: term.dq, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.q)}` - }), term.filters ? { - categories: term.filters.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.key - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - }) : [])].slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_terms), - productSuggestions: [...(responseData.response.products ? responseData.response.products.map(product => Object.assign(Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: !Number.isNaN(product.sale_price) ? product.sale_price : !Number.isNaN(product.price) ? product.price : '0' - }), 'price' in product && 'sale_price' in product ? { - price: product.price - } : {})) : [])].slice(0, (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function highlightQueryInTermLabels(results) { - const processedResults = Object.assign({}, results); - results.terms.forEach((term, index) => { - const typedQueryHtml = ejs.render(AUTOSUGGEST_TYPED_QUERY_TEMPLATE, { - query: results.originalQuery - }).trim(); - (processedResults.terms[index] || {}).processedText = term.text.replace(results.originalQuery || '', typedQueryHtml); - }); - return processedResults; - } - - const log$1 = Debug('br:autosuggest'); - /** - * Retrieves suggestions from the suggest API and renders them to the DOM. - */ - async function suggest(query) { - var _a, _b, _c; - log$1('Fetching suggestions for', query); - const config = buildAutosuggestConfig(); - updateCurrentAutosuggestRequestState({ - request_id: generateRequestId() - }); - const apiCallParameters = buildApiCallParameters(query); - // todo remediate typescript issue - // @ts-ignore - const results = await getSuggestions(apiCallParameters); - const templateData = mapAutosuggestApiResponse(results); - updateCurrentAutosuggestRequestState({ - last_template_data: templateData - }); - const container = getAutosuggestResultsContainerElement(); - if (!container) return; - log$1.verbose('Using config', config); - log$1.verbose('Render to:', container); - log$1.verbose('Is using default template?', !((_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.template)); - log$1.verbose('Rendering with template:', { - template: ((_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.template) || autosuggestTemplate, - templateData - }); - container.innerHTML = ejs.render(((_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.template) || autosuggestTemplate, templateData); - addCategoryLinkElementClickListener(); - addSuggestionTermElementClickListener(); - } - /** - * Generates the API paramters fed into the suggest API call body. - */ - function buildApiCallParameters(query) { - var _a, _b, _c; - const config = buildAutosuggestConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentAutosuggestRequestState = getCurrentAutosuggestRequestState(); - const apiParameters = Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.autosuggest) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.autosuggest.endpoint - } : {}), { - q: query || urlParameters.get((config === null || config === void 0 ? void 0 : config.default_search_parameter) || '') || '', - aq: query, - sort: (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.sort, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentAutosuggestRequestState.request_id, - _br_uid_2: config.tracking_cookie, - ref_url: config.ref_url, - url: config.url, - request_type: config.request_type, - catalog_views: (_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.catalog_views, - search_type: 'keyword' - }); - if (!apiParameters.catalog_views) { - apiParameters.catalog_views = ''; - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === undefined) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function getCurrentAutosuggestRequestState() { - return window.BloomreachModules.autosuggest.getCurrentAutosuggestRequestState(); - } - function updateCurrentAutosuggestRequestState(state) { - window.BloomreachModules.autosuggest.setCurrentAutosuggestRequestState(Object.assign(Object.assign({}, getCurrentAutosuggestRequestState()), state)); - } - - /** - * This is the listener for clicking on an add to cart element. This triggers an - * add to cart pixel event. - */ - function addToCartElementClickListener(e) { - var _a, _b; - const addToCartElement = e.currentTarget; - // We retrieve the dataset items from our element - const blmAddToCartSku = addToCartElement.getAttribute(ADD_TO_CART_ATTRIBUTE_SKU); - const blmAddToCartProdId = addToCartElement.getAttribute(ADD_TO_CART_ATTRIBUTE_PROD_ID); - const blmAddToCartDisable = addToCartElement.getAttribute(ADD_TO_CART_ATTRIBUTE_DISABLE); - // Get the properties we will send to the tracker as adjustments to the - // potentially configured brtk config object on the window. - const eventProperties = { - prod_id: blmAddToCartProdId, - sku: blmAddToCartSku - }; - // Make the product id and sku adjustable via data attributes on the add to - // cart element. But don't make them required. - if (!blmAddToCartProdId) delete eventProperties.prod_id; - if (!blmAddToCartSku) delete eventProperties.sku; - // If the disable attribute is present, we will not fire the add to cart - // event. This will - if (blmAddToCartDisable !== 'true') { - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('cart', 'click-add', eventProperties); - } - } - /** - * Add the event listener to all add to cart elements. This is re-entrant, so - * this can be safely called to ensure events if there are moments when there may be - * reasonable doubt for the DOM to have been updated which could cause new - * elements to be generated. - */ - function addAddToCartElementClickListener() { - const elements = getAddToCartElements(); - // Apply listeners in re-entrant fashion - elements.forEach(element => { - // Clear event to prevent duplication - element === null || element === void 0 ? void 0 : element.removeEventListener('click', addToCartElementClickListener); - // Read the event - element === null || element === void 0 ? void 0 : element.addEventListener('click', addToCartElementClickListener); - }); - } - - function quickviewElementClickListener(e) { - var _a, _b; - const quickviewElement = e.currentTarget; - quickviewElement.dataset; - // Get the data from the element using getAttribute so we can use the - // constants for consistency - const blmQuickviewSku = quickviewElement.getAttribute(QUICKVIEW_ATTRIBUTE_SKU); - const blmQuickviewProdId = quickviewElement.getAttribute(QUICKVIEW_ATTRIBUTE_PROD_ID); - const blmQuickviewProdName = quickviewElement.getAttribute(QUICKVIEW_ATTRIBUTE_PROD_NAME); - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('product', 'quickview', { - prod_id: blmQuickviewProdId, - prod_name: blmQuickviewProdName, - sku: blmQuickviewSku - }); - } - /** - * Looks for all quickview elements and adds the click listener to them. This is - * re-entrant, so this can be safely called to ensure events if there are - * moments when there may be reasonable doubt for the DOM to have been updated - * which could cause new elements to be generated. - */ - function addQuickviewElementClickListener() { - const elements = getQuickviewElements(); - // Add listeners in re-entrant fashion - elements.forEach(quickviewElement => { - quickviewElement === null || quickviewElement === void 0 ? void 0 : quickviewElement.removeEventListener('click', quickviewElementClickListener); - quickviewElement === null || quickviewElement === void 0 ? void 0 : quickviewElement.addEventListener('click', quickviewElementClickListener); - }); - } - - const log = Debug('br:product-events'); - let pollTimer = void 0; - const current = { - addToCart: [], - quickview: [] - }; - function buildProductEventsModule() { - return { - load: async () => { - initPolling(); - } - }; - } - function initPolling() { - window.clearInterval(pollTimer); - const doPoll = () => { - const found = { - addToCart: [], - quickview: [] - }; - found.addToCart = getAddToCartElements(); - found.quickview = getQuickviewElements(); - if (current.addToCart.length && !found.addToCart.length) { - // Teardown this module to put it in a waiting state - current.addToCart = []; - addToCartWillUnmount(); - } else if (!current.addToCart.length && found.addToCart.length) { - current.addToCart = found.addToCart; - addToCartWillMount(); - } - if (current.quickview.length && !found.quickview.length) { - // Teardown this module to put it in a waiting state - current.quickview = []; - quickviewWillUnmount(); - } else if (!current.quickview.length && found.quickview.length) { - current.quickview = found.quickview; - quickviewWillMount(); - } - }; - if (!pollTimer) log('Polling initialized'); - // Begin the polling service. - pollTimer = window.setInterval(doPoll, 100); - // We execute the poll immediately so if we have a script that is "smarter" - // about when all conditions are ready for the module, there is a path to have - // an immediate initialization. - doPoll(); - } - function addToCartWillMount() { - log('Add to cart events will mount'); - addAddToCartElementClickListener(); - } - function addToCartWillUnmount() { - log('Add to cart events will unmount'); - } - function quickviewWillMount() { - log('Quickview events will mount'); - addQuickviewElementClickListener(); - } - function quickviewWillUnmount() { - log('Quickview events will unmount'); - } - - Debug('br:recommendations'); - - debounce_1(event => { - var _a; - const inputValue = (((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) || '').trim(); - document.querySelectorAll('.blm-dynamic-filter').forEach(facetBox => { - let displayedItems = 0; - facetBox.querySelectorAll('.blm-product-search-filter-item').forEach(facetItem => { - var _a; - const label = ((_a = facetItem.querySelector('label')) === null || _a === void 0 ? void 0 : _a.textContent) || ''; - const shouldDisplay = !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()); - const displayStyle = shouldDisplay ? 'block' : 'none'; - displayedItems += shouldDisplay ? 1 : 0; - facetItem.style.display = displayStyle; - }); - facetBox.style.display = displayedItems ? 'block' : 'none'; - }); - document.querySelectorAll('.blm-product-search-load-more').forEach(loadMoreLink => { - loadMoreLink.style.display = 'none'; - }); - const groupsELement = getLoadMoreFacetGroupsElement(); - if (!groupsELement) return; - groupsELement.style.display = 'none'; - if (!inputValue) { - resetFacetGroups(); - } - }, 500); - - Debug('br:search'); - function buildDefaultSearchRequestState(options) { - const { - isCategoryPage - } = options; - return { - request_id: 0, - price_range_max_value: 0, - price_range_min_value: 0, - is_first_request: true, - is_category_page: isCategoryPage, - category_to_load: '', - pollIntervalId: void 0, - currentElement: null - }; - } - /** - * Attempts to get the search request state from the existing module - */ - function getCurrentSearchRequestState() { - var _a, _b, _c; - return ((_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.getCurrentSearchRequestState()) || buildDefaultSearchRequestState({ - isCategoryPage: false - }); - } - - const productEventsModule = buildProductEventsModule(); - window.BloomreachModules = Object.assign(Object.assign({}, globalBloomreachModules), { - events: productEventsModule - }); - productEventsModule.load().catch(console.error); - -})(); +var t=r,n=b,i=_,o=!1,a=y,s="locals",c=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],l=c.concat("cache"),u=/^\uFEFF/,p=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/;function f(n,r){var i;if(r.some((function(r){return i=e.resolveInclude(n,r,!0),t.existsSync(i)})))return i}function h(t,n){var r,i=t.filename,o=arguments.length>1;if(t.cache){if(!i)throw new Error("cache option requires a filename");if(r=e.cache.get(i))return r;o||(n=d(i).toString().replace(u,""))}else if(!o){if(!i)throw new Error("Internal EJS error: no file name or template provided");n=d(i).toString().replace(u,"")}return r=e.compile(n,t),t.cache&&e.cache.set(i,r),r}function d(t){return e.fileLoader(t)}function m(n,r){var o=i.shallowCopy(i.createNullProtoObjWherePossible(),r);if(o.filename=function(n,r){var i,o,a=r.views,s=/^[A-Za-z]+:\\|^\//.exec(n);if(s&&s.length)n=n.replace(/^\/*/,""),i=Array.isArray(r.root)?f(n,r.root):e.resolveInclude(n,r.root||"/",!0);else if(r.filename&&(o=e.resolveInclude(n,r.filename),t.existsSync(o)&&(i=o)),!i&&Array.isArray(a)&&(i=f(n,a)),!i&&"function"!=typeof r.includer)throw new Error('Could not find the include file "'+r.escapeFunction(n)+'"');return i}(n,o),"function"==typeof r.includer){var a=r.includer(n,o.filename);if(a&&(a.filename&&(o.filename=a.filename),a.template))return h(o,a.template)}return h(o)}function g(e,t,n,r,i){var o=t.split("\n"),a=Math.max(r-3,0),s=Math.min(o.length,r+3),c=i(n),l=o.slice(a,s).map((function(e,t){var n=t+a+1;return(n==r?" >> ":" ")+n+"| "+e})).join("\n");throw e.path=c,e.message=(c||"ejs")+":"+r+"\n"+l+"\n\n"+e.message,e}function v(e){return e.replace(/;(\s*$)/,"$1")}function w(t,n){var r=i.hasOwnOnlyObject(n),o=i.createNullProtoObjWherePossible();this.templateText=t,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",o.client=r.client||!1,o.escapeFunction=r.escape||r.escapeFunction||i.escapeXML,o.compileDebug=!1!==r.compileDebug,o.debug=!!r.debug,o.filename=r.filename,o.openDelimiter=r.openDelimiter||e.openDelimiter||"<",o.closeDelimiter=r.closeDelimiter||e.closeDelimiter||">",o.delimiter=r.delimiter||e.delimiter||"%",o.strict=r.strict||!1,o.context=r.context,o.cache=r.cache||!1,o.rmWhitespace=r.rmWhitespace,o.root=r.root,o.includer=r.includer,o.outputFunctionName=r.outputFunctionName,o.localsName=r.localsName||e.localsName||s,o.views=r.views,o.async=r.async,o.destructuredLocals=r.destructuredLocals,o.legacyInclude=void 0===r.legacyInclude||!!r.legacyInclude,o.strict?o._with=!1:o._with=void 0===r._with||r._with,this.opts=o,this.regex=this.createRegex()}e.cache=i.cache,e.fileLoader=t.readFileSync,e.localsName=s,e.promiseImpl=new Function("return this;")().Promise,e.resolveInclude=function(e,t,r){var i=n.dirname,o=n.extname,a=(0,n.resolve)(r?t:i(t),e);return o(e)||(a+=".ejs"),a},e.compile=function(e,t){return t&&t.scope&&(o||(console.warn("`scope` option is deprecated and will be removed in EJS 3"),o=!0),t.context||(t.context=t.scope),delete t.scope),new w(e,t).compile()},e.render=function(e,t,n){var r=t||i.createNullProtoObjWherePossible(),o=n||i.createNullProtoObjWherePossible();return 2==arguments.length&&i.shallowCopyFromList(o,r,c),h(o,e)(r)},e.renderFile=function(){var t,n,r,o=Array.prototype.slice.call(arguments),a=o.shift(),s={filename:a};return"function"==typeof arguments[arguments.length-1]&&(t=o.pop()),o.length?(n=o.shift(),o.length?i.shallowCopy(s,o.pop()):(n.settings&&(n.settings.views&&(s.views=n.settings.views),n.settings["view cache"]&&(s.cache=!0),(r=n.settings["view options"])&&i.shallowCopy(s,r)),i.shallowCopyFromList(s,n,l)),s.filename=a):n=i.createNullProtoObjWherePossible(),function(t,n,r){var i;if(!r){if("function"==typeof e.promiseImpl)return new e.promiseImpl((function(e,r){try{e(i=h(t)(n))}catch(e){r(e)}}));throw new Error("Please provide a callback function")}try{i=h(t)(n)}catch(e){return r(e)}r(null,i)}(s,n,t)},e.Template=w,e.clearCache=function(){e.cache.reset()},w.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},w.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=i.escapeRegExpChars(this.opts.delimiter),n=i.escapeRegExpChars(this.opts.openDelimiter),r=i.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,r),new RegExp(e)},compile:function(){var e,t,r,o=this.opts,a="",s="",c=o.escapeFunction,l=o.filename?JSON.stringify(o.filename):"undefined";if(!this.source){if(this.generateSource(),a+=' var __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n',o.outputFunctionName){if(!p.test(o.outputFunctionName))throw new Error("outputFunctionName is not a valid JS identifier.");a+=" var "+o.outputFunctionName+" = __append;\n"}if(o.localsName&&!p.test(o.localsName))throw new Error("localsName is not a valid JS identifier.");if(o.destructuredLocals&&o.destructuredLocals.length){for(var u=" var __locals = ("+o.localsName+" || {}),\n",f=0;f0&&(u+=",\n "),u+=h+" = __locals."+h}a+=u+";\n"}!1!==o._with&&(a+=" with ("+o.localsName+" || {}) {\n",s+=" }\n"),s+=" return __output;\n",this.source=a+this.source+s}e=o.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+l+";\ntry {\n"+this.source+"} catch (e) {\n rethrow(e, __lines, __filename, __line, escapeFn);\n}\n":this.source,o.client&&(e="escapeFn = escapeFn || "+c.toString()+";\n"+e,o.compileDebug&&(e="rethrow = rethrow || "+g.toString()+";\n"+e)),o.strict&&(e='"use strict";\n'+e),o.debug&&console.log(e),o.compileDebug&&o.filename&&(e=e+"\n//# sourceURL="+l+"\n");try{if(o.async)try{r=new Function("return (async function(){}).constructor;")()}catch(e){throw e instanceof SyntaxError?new Error("This environment does not support async/await"):e}else r=Function;t=new r(o.localsName+", escapeFn, include, rethrow",e)}catch(e){throw e instanceof SyntaxError&&(o.filename&&(e.message+=" in "+o.filename),e.message+=" while compiling ejs\n\n",e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n",e.message+="https://github.com/RyanZim/EJS-Lint",o.async||(e.message+="\n",e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}var d=o.client?t:function(e){return t.apply(o.context,[e||i.createNullProtoObjWherePossible(),c,function(t,n){var r=i.shallowCopy(i.createNullProtoObjWherePossible(),e);return n&&(r=i.shallowCopy(r,n)),m(t,o)(r)},g])};if(o.filename&&"function"==typeof Object.defineProperty){var v=o.filename,b=n.basename(v,n.extname(v));try{Object.defineProperty(d,"name",{value:b,writable:!1,enumerable:!1,configurable:!0})}catch(e){}}return d},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")),this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var e=this,t=this.parseTemplateText(),n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter;t&&t.length&&t.forEach((function(o,a){var s;if(0===o.indexOf(r+n)&&0!==o.indexOf(r+n+n)&&(s=t[a+2])!=n+i&&s!="-"+n+i&&s!="_"+n+i)throw new Error('Could not find matching close tag for "'+o+'".');e.scanLine(o)}))},parseTemplateText:function(){for(var e,t=this.templateText,n=this.regex,r=n.exec(t),i=[];r;)0!==(e=r.index)&&(i.push(t.substring(0,e)),t=t.slice(e)),i.push(r[0]),t=t.slice(r[0].length),r=n.exec(t);return t&&i.push(t),i},_addOutput:function(e){if(this.truncate&&(e=e.replace(/^(?:\r\n|\r|\n)/,""),this.truncate=!1),!e)return e;e=(e=(e=(e=e.replace(/\\/g,"\\\\")).replace(/\n/g,"\\n")).replace(/\r/g,"\\r")).replace(/"/g,'\\"'),this.source+=' ; __append("'+e+'")\n'},scanLine:function(e){var t,n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter;switch(t=e.split("\n").length-1,e){case r+n:case r+n+"_":this.mode=w.modes.EVAL;break;case r+n+"=":this.mode=w.modes.ESCAPED;break;case r+n+"-":this.mode=w.modes.RAW;break;case r+n+"#":this.mode=w.modes.COMMENT;break;case r+n+n:this.mode=w.modes.LITERAL,this.source+=' ; __append("'+e.replace(r+n+n,r+n)+'")\n';break;case n+n+i:this.mode=w.modes.LITERAL,this.source+=' ; __append("'+e.replace(n+n+i,n+i)+'")\n';break;case n+i:case"-"+n+i:case"_"+n+i:this.mode==w.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=0===e.indexOf("-")||0===e.indexOf("_");break;default:if(this.mode){switch(this.mode){case w.modes.EVAL:case w.modes.ESCAPED:case w.modes.RAW:e.lastIndexOf("//")>e.lastIndexOf("\n")&&(e+="\n")}switch(this.mode){case w.modes.EVAL:this.source+=" ; "+e+"\n";break;case w.modes.ESCAPED:this.source+=" ; __append(escapeFn("+v(e)+"))\n";break;case w.modes.RAW:this.source+=" ; __append("+v(e)+")\n";break;case w.modes.COMMENT:break;case w.modes.LITERAL:this._addOutput(e)}}else this._addOutput(e)}this.opts.compileDebug&&t&&(this.currentLine+=t,this.source+=" ; __line = "+this.currentLine+"\n")}},e.escapeXML=i.escapeXML,e.__express=e.renderFile,e.VERSION=a,e.name="ejs","undefined"!=typeof window&&(window.ejs=e)}({}),function(e){e.small="480px",e.medium="680px",e.large="750px",e.xlarge="875px",e.xxlarge="1000px",e.xxxlarge="1200px"}(w||(w={})),window.matchMedia(`(max-width: ${w.medium})`),window.matchMedia(`(min-width:${w.medium}) and (max-width: ${w.xlarge})`);var x="object"==typeof t&&t&&t.Object===Object&&t,E="object"==typeof self&&self&&self.Object===Object&&self,O=(x||E||Function("return this")()).Symbol;O&&O.toStringTag;function L(){document.querySelectorAll("[data-blm-add-to-cart]").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",function(e){const{blmAddToCartSku:t,blmAddToCartProdId:n}=e.dataset;return()=>{var e,r;null===(r=null===(e=window.BrTrk||{})||void 0===e?void 0:e.getTracker())||void 0===r||r.logEvent("cart","click-add",{prod_id:n,sku:t})}}(e)),e.setAttribute("hasListener","true"))}))}function j(){document.querySelectorAll("[data-blm-quickview]").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",function(e){const{blmQuickviewSku:t,blmQuickviewProdId:n,blmQuickviewProdName:r}=e.dataset;return()=>{var e,i;null===(i=null===(e=window.BrTrk||{})||void 0===e?void 0:e.getTracker())||void 0===i||i.logEvent("product","quickview",{prod_id:n,prod_name:r,sku:t})}}(e)),e.setAttribute("hasListener","true"))}))}O&&O.toStringTag;const A={load:async()=>{L(),j()}};window.BloomreachModules=Object.assign(Object.assign({},e),{events:A}),A.load().catch(console.error)}(); //# sourceMappingURL=events.js.map diff --git a/view/frontend/web/js/recommendations.js b/view/frontend/web/js/recommendations.js index e5afe37..b3cc079 100644 --- a/view/frontend/web/js/recommendations.js +++ b/view/frontend/web/js/recommendations.js @@ -1,3345 +1,10 @@ -(function () { - 'use strict'; - - const AUTOSUGGEST_MINIMUM_QUERY_LENGTH = 2; - const AUTOSUGGEST_TYPED_QUERY_TEMPLATE = '<%= query %>'; - const COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS = 'cdp_segments'; - const COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE = 'customer_profile'; - const DEFAULT_CURRENCY = '$'; - const DEFAULT_PAGE_SIZE = 16; - const DEFAULT_SEARCH_PARAMETER = 'q'; - const DEFAULT_SORTING_OPTIONS = [{ - label: 'Relevance', - value: '' - }, { - label: 'Price (low - high)', - value: 'price+asc' - }, { - label: 'Price (high - low)', - value: 'price+desc' - }, { - label: 'Name (A - Z)', - value: 'title+asc' - }, { - label: 'Name (Z - A)', - value: 'title+desc' - }]; - const DEFAULT_START = 0; - const DEFAULT_WIDGETS_TO_DISPLAY = 4; - const FIELD_NAME_PRICE = 'price'; - const MAX_COLOR_SWATCHES = 4; - const MAX_PAGINATION_NUMBER_BEFORE_CURRENT = 2; - const MAX_PAGINATION_NUMBER_AFTER_CURRENT = 2; - const NUMBER_OF_AUTOSUGGEST_COLLECTIONS = 8; - const NUMBER_OF_AUTOSUGGEST_PRODUCTS = 8; - const NUMBER_OF_AUTOSUGGEST_TERMS = 4; - const NUMBER_OF_FACET_GROUPS = 5; - const NUMBER_OF_FACET_VALUES = 6; - const PARAMETER_NAME_FACETS = 'fq'; - const PARAMETER_NAME_FILTERS_PANEL = 'filterpanel'; - const PARAMETER_NAME_GROUPBY = 'groupby'; - const PARAMETER_NAME_PAGE = 'page'; - const PARAMETER_NAME_SIZE = 'size'; - const PARAMETER_NAME_SORT = 'sort'; - const REQUEST_TYPE_SEARCH = 'search'; - const REQUEST_TYPE_SUGGEST = 'suggest'; - const SEARCH_TYPE_CATEGORY = 'category'; - const SEARCH_TYPE_KEYWORD = 'keyword'; - const SELECTOR_AUTOSUGGEST_INPUT = '.search__input'; - const SELECTOR_SEARCH_RESULTS_CONTAINER = '.main-content'; - /** - * This is the attribute name used to flag an element as an add to cart event - * generator, such as a butto or link. - */ - const ADD_TO_CART_ATTRIBUTE_NAME = 'data-blm-add-to-cart'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the sku value sent in the - * pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_SKU = 'data-blm-add-to-cart-sku'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the prod_id value sent in - * the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_PROD_ID = 'data-blm-add-to-cart-prod-id'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to prevent emitting the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_DISABLE = 'data-blm-add-to-cart-disable'; - const QUICKVIEW_ATTRIBUTE_NAME = 'data-blm-quickview'; - const QUICKVIEW_ATTRIBUTE_SKU = 'data-blm-quickview-sku'; - const QUICKVIEW_ATTRIBUTE_PROD_ID = 'data-blm-quickview-prod-id'; - const QUICKVIEW_ATTRIBUTE_PROD_NAME = 'data-blm-quickview-prod-name'; - - var constants = /*#__PURE__*/Object.freeze({ - __proto__: null, - AUTOSUGGEST_MINIMUM_QUERY_LENGTH: AUTOSUGGEST_MINIMUM_QUERY_LENGTH, - AUTOSUGGEST_TYPED_QUERY_TEMPLATE: AUTOSUGGEST_TYPED_QUERY_TEMPLATE, - COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS: COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS, - COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE: COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE, - DEFAULT_CURRENCY: DEFAULT_CURRENCY, - DEFAULT_PAGE_SIZE: DEFAULT_PAGE_SIZE, - DEFAULT_SEARCH_PARAMETER: DEFAULT_SEARCH_PARAMETER, - DEFAULT_SORTING_OPTIONS: DEFAULT_SORTING_OPTIONS, - DEFAULT_START: DEFAULT_START, - DEFAULT_WIDGETS_TO_DISPLAY: DEFAULT_WIDGETS_TO_DISPLAY, - FIELD_NAME_PRICE: FIELD_NAME_PRICE, - MAX_COLOR_SWATCHES: MAX_COLOR_SWATCHES, - MAX_PAGINATION_NUMBER_BEFORE_CURRENT: MAX_PAGINATION_NUMBER_BEFORE_CURRENT, - MAX_PAGINATION_NUMBER_AFTER_CURRENT: MAX_PAGINATION_NUMBER_AFTER_CURRENT, - NUMBER_OF_AUTOSUGGEST_COLLECTIONS: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - NUMBER_OF_AUTOSUGGEST_PRODUCTS: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - NUMBER_OF_AUTOSUGGEST_TERMS: NUMBER_OF_AUTOSUGGEST_TERMS, - NUMBER_OF_FACET_GROUPS: NUMBER_OF_FACET_GROUPS, - NUMBER_OF_FACET_VALUES: NUMBER_OF_FACET_VALUES, - PARAMETER_NAME_FACETS: PARAMETER_NAME_FACETS, - PARAMETER_NAME_FILTERS_PANEL: PARAMETER_NAME_FILTERS_PANEL, - PARAMETER_NAME_GROUPBY: PARAMETER_NAME_GROUPBY, - PARAMETER_NAME_PAGE: PARAMETER_NAME_PAGE, - PARAMETER_NAME_SIZE: PARAMETER_NAME_SIZE, - PARAMETER_NAME_SORT: PARAMETER_NAME_SORT, - REQUEST_TYPE_SEARCH: REQUEST_TYPE_SEARCH, - REQUEST_TYPE_SUGGEST: REQUEST_TYPE_SUGGEST, - SEARCH_TYPE_CATEGORY: SEARCH_TYPE_CATEGORY, - SEARCH_TYPE_KEYWORD: SEARCH_TYPE_KEYWORD, - SELECTOR_AUTOSUGGEST_INPUT: SELECTOR_AUTOSUGGEST_INPUT, - SELECTOR_SEARCH_RESULTS_CONTAINER: SELECTOR_SEARCH_RESULTS_CONTAINER, - ADD_TO_CART_ATTRIBUTE_NAME: ADD_TO_CART_ATTRIBUTE_NAME, - ADD_TO_CART_ATTRIBUTE_SKU: ADD_TO_CART_ATTRIBUTE_SKU, - ADD_TO_CART_ATTRIBUTE_PROD_ID: ADD_TO_CART_ATTRIBUTE_PROD_ID, - ADD_TO_CART_ATTRIBUTE_DISABLE: ADD_TO_CART_ATTRIBUTE_DISABLE, - QUICKVIEW_ATTRIBUTE_NAME: QUICKVIEW_ATTRIBUTE_NAME, - QUICKVIEW_ATTRIBUTE_SKU: QUICKVIEW_ATTRIBUTE_SKU, - QUICKVIEW_ATTRIBUTE_PROD_ID: QUICKVIEW_ATTRIBUTE_PROD_ID, - QUICKVIEW_ATTRIBUTE_PROD_NAME: QUICKVIEW_ATTRIBUTE_PROD_NAME - }); - - const globalBloomreachModules = Object.assign(Object.assign({}, window.BloomreachModules ? window.BloomreachModules : {}), { - version: '4.0.0', - constants - }); - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getAugmentedNamespace(n) { - var f = n.default; - if (typeof f == "function") { - var a = function () { - return f.apply(this, arguments); - }; - a.prototype = f.prototype; - } else a = {}; - Object.defineProperty(a, '__esModule', {value: true}); - Object.keys(n).forEach(function (k) { - var d = Object.getOwnPropertyDescriptor(n, k); - Object.defineProperty(a, k, d.get ? d : { - enumerable: true, - get: function () { - return n[k]; - } - }); - }); - return a; - } - - var ejs = {}; - - var _polyfillNode_fs = {}; - - var _polyfillNode_fs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _polyfillNode_fs - }); - - var require$$0 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_fs$1); - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // resolves . and .. elements in a path array with directory names there - // must be no slashes, empty elements, or device names (c:\) in the array - // (so also no leading and trailing slashes - it does not distinguish - // relative and absolute paths) - function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; - } - - // Split a filename into [root, dir, basename, ext], unix version - // 'root' is just a slash, or nothing. - var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); - }; - - // path.resolve([from ...], to) - // posix version - function resolve() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : '/'; - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - } - // path.normalize(path) - // posix version - function normalize(path) { - var isPathAbsolute = isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isPathAbsolute).join('/'); - - if (!path && !isPathAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isPathAbsolute ? '/' : '') + path; - } - // posix version - function isAbsolute(path) { - return path.charAt(0) === '/'; - } - - // posix version - function join() { - var paths = Array.prototype.slice.call(arguments, 0); - return normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); - } - - - // path.relative(from, to) - // posix version - function relative(from, to) { - from = resolve(from).substr(1); - to = resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - } - - var sep = '/'; - var delimiter = ':'; - - function dirname(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; - } - - function basename(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; - } - - - function extname(path) { - return splitPath(path)[3]; - } - var _polyfillNode_path = { - extname: extname, - basename: basename, - dirname: dirname, - sep: sep, - delimiter: delimiter, - relative: relative, - join: join, - isAbsolute: isAbsolute, - normalize: normalize, - resolve: resolve - }; - function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; - } - - // String.prototype.substr - negative index don't work in IE8 - var substr = 'ab'.substr(-1) === 'b' ? - function (str, start, len) { return str.substr(start, len) } : - function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } - ; - - var _polyfillNode_path$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - resolve: resolve, - normalize: normalize, - isAbsolute: isAbsolute, - join: join, - relative: relative, - sep: sep, - delimiter: delimiter, - dirname: dirname, - basename: basename, - extname: extname, - 'default': _polyfillNode_path - }); - - var require$$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_path$1); - - var utils = {}; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - var regExpChars = /[|\\{}()[\]^$+*?.]/g; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); }; - - /** - * Escape characters reserved in regular expressions. - * - * If `string` is `undefined` or `null`, the empty string is returned. - * - * @param {String} string Input string - * @return {String} Escaped string - * @static - * @private - */ - exports.escapeRegExpChars = function (string) { - // istanbul ignore if - if (!string) { - return ''; - } - return String(string).replace(regExpChars, '\\$&'); - }; - - var _ENCODE_HTML_RULES = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - var _MATCH_HTML = /[&<>'"]/g; - - function encode_char(c) { - return _ENCODE_HTML_RULES[c] || c; - } - - /** - * Stringified version of constants used by {@link module:utils.escapeXML}. - * - * It is used in the process of generating {@link ClientFunction}s. - * - * @readonly - * @type {String} - */ - - var escapeFuncStr = - 'var _ENCODE_HTML_RULES = {\n' - + ' "&": "&"\n' - + ' , "<": "<"\n' - + ' , ">": ">"\n' - + ' , \'"\': """\n' - + ' , "\'": "'"\n' - + ' }\n' - + ' , _MATCH_HTML = /[&<>\'"]/g;\n' - + 'function encode_char(c) {\n' - + ' return _ENCODE_HTML_RULES[c] || c;\n' - + '};\n'; - - /** - * Escape characters reserved in XML. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @implements {EscapeCallback} - * @param {String} markup Input string - * @return {String} Escaped string - * @static - * @private - */ - - exports.escapeXML = function (markup) { - return markup == undefined - ? '' - : String(markup) - .replace(_MATCH_HTML, encode_char); - }; - exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; - }; - - /** - * Naive copy of properties from one object to another. - * Does not recurse into non-scalar properties - * Does not check to see if the property has a value before copying - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopy = function (to, from) { - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var p in from) { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - return to; - }; - - /** - * Naive copy of a list of key names, from one object to another. - * Only copies property if it is actually defined - * Does not recurse into non-scalar properties - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @param {Array} list List of properties to copy - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopyFromList = function (to, from, list) { - list = list || []; - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var i = 0; i < list.length; i++) { - var p = list[i]; - if (typeof from[p] != 'undefined') { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - } - return to; - }; - - /** - * Simple in-process cache implementation. Does not implement limits of any - * sort. - * - * @implements {Cache} - * @static - * @private - */ - exports.cache = { - _data: {}, - set: function (key, val) { - this._data[key] = val; - }, - get: function (key) { - return this._data[key]; - }, - remove: function (key) { - delete this._data[key]; - }, - reset: function () { - this._data = {}; - } - }; - - /** - * Transforms hyphen case variable into camel case. - * - * @param {String} string Hyphen case string - * @return {String} Camel case string - * @static - * @private - */ - exports.hyphenToCamel = function (str) { - return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); }); - }; - - /** - * Returns a null-prototype object in runtimes that support it - * - * @return {Object} Object, prototype will be set to null where possible - * @static - * @private - */ - exports.createNullProtoObjWherePossible = (function () { - if (typeof Object.create == 'function') { - return function () { - return Object.create(null); - }; - } - if (!({__proto__: null} instanceof Object)) { - return function () { - return {__proto__: null}; - }; - } - // Not possible, just pass through - return function () { - return {}; - }; - })(); - } (utils)); - - var name = "ejs"; - var description = "Embedded JavaScript templates"; - var keywords = [ - "template", - "engine", - "ejs" - ]; - var version = "3.1.8"; - var author = "Matthew Eernisse (http://fleegix.org)"; - var license = "Apache-2.0"; - var bin = { - ejs: "./bin/cli.js" - }; - var main = "./lib/ejs.js"; - var jsdelivr = "ejs.min.js"; - var unpkg = "ejs.min.js"; - var repository = { - type: "git", - url: "git://github.com/mde/ejs.git" - }; - var bugs = "https://github.com/mde/ejs/issues"; - var homepage = "https://github.com/mde/ejs"; - var dependencies = { - jake: "^10.8.5" - }; - var devDependencies = { - browserify: "^16.5.1", - eslint: "^6.8.0", - "git-directory-deploy": "^1.5.1", - jsdoc: "^3.6.7", - "lru-cache": "^4.0.1", - mocha: "^7.1.1", - "uglify-js": "^3.3.16" - }; - var engines = { - node: ">=0.10.0" - }; - var scripts = { - test: "mocha" - }; - var require$$3 = { - name: name, - description: description, - keywords: keywords, - version: version, - author: author, - license: license, - bin: bin, - main: main, - jsdelivr: jsdelivr, - unpkg: unpkg, - repository: repository, - bugs: bugs, - homepage: homepage, - dependencies: dependencies, - devDependencies: devDependencies, - engines: engines, - scripts: scripts - }; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - /** +!function(){"use strict";const e=Object.assign(Object.assign({},window.BloomreachModules?window.BloomreachModules:{}),{version:"3.1.0"});var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(e){var t=e.default;if("function"==typeof t){var n=function(){return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach((function(t){var i=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,i.get?i:{enumerable:!0,get:function(){return e[t]}})})),n}var i={},r=n(Object.freeze({__proto__:null,default:{}}));function o(e,t){for(var n=0,i=e.length-1;i>=0;i--){var r=e[i];"."===r?e.splice(i,1):".."===r?(e.splice(i,1),n++):n&&(e.splice(i,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var s=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,a=function(e){return s.exec(e).slice(1)};function c(){for(var e="",t=!1,n=arguments.length-1;n>=-1&&!t;n--){var i=n>=0?arguments[n]:"/";if("string"!=typeof i)throw new TypeError("Arguments to path.resolve must be strings");i&&(e=i+"/"+e,t="/"===i.charAt(0))}return(t?"/":"")+(e=o(w(e.split("/"),(function(e){return!!e})),!t).join("/"))||"."}function l(e){var t=u(e),n="/"===_(e,-1);return(e=o(w(e.split("/"),(function(e){return!!e})),!t).join("/"))||t||(e="."),e&&n&&(e+="/"),(t?"/":"")+e}function u(e){return"/"===e.charAt(0)}function d(){return l(w(Array.prototype.slice.call(arguments,0),(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))}function p(e,t){function n(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=c(e).substr(1),t=c(t).substr(1);for(var i=n(e.split("/")),r=n(t.split("/")),o=Math.min(i.length,r.length),s=o,a=0;a":">",'"':""","'":"'"},o=/[&<>'"]/g;function s(e){return r[e]||e}function a(){return Function.prototype.toString.call(this)+';\nvar _ENCODE_HTML_RULES = {\n "&": "&"\n , "<": "<"\n , ">": ">"\n , \'"\': """\n , "\'": "'"\n }\n , _MATCH_HTML = /[&<>\'"]/g;\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n};\n'}e.escapeXML=function(e){return null==e?"":String(e).replace(o,s)};try{"function"==typeof Object.defineProperty?Object.defineProperty(e.escapeXML,"toString",{value:a}):e.escapeXML.toString=a}catch(e){console.warn("Unable to set escapeXML.toString (is the Function prototype frozen?)")}e.shallowCopy=function(e,t){if(t=t||{},null!=e)for(var n in t)i(t,n)&&"__proto__"!==n&&"constructor"!==n&&(e[n]=t[n]);return e},e.shallowCopyFromList=function(e,t,n){if(n=n||[],t=t||{},null!=e)for(var r=0;r * @author Tiancheng "Timothy" Gu * @project EJS * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} */ - - /** - * EJS internal functions. - * - * Technically this "module" lies in the same file as {@link module:ejs}, for - * the sake of organization all the private functions re grouped into this - * module. - * - * @module ejs-internal - * @private - */ - - /** - * Embedded JavaScript templating engine. - * - * @module ejs - * @public - */ - - - var fs = require$$0; - var path = require$$1; - var utils$1 = utils; - - var scopeOptionWarned = false; - /** @type {string} */ - var _VERSION_STRING = require$$3.version; - var _DEFAULT_OPEN_DELIMITER = '<'; - var _DEFAULT_CLOSE_DELIMITER = '>'; - var _DEFAULT_DELIMITER = '%'; - var _DEFAULT_LOCALS_NAME = 'locals'; - var _NAME = 'ejs'; - var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; - var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', - 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; - // We don't allow 'cache' option to be passed in the data obj for - // the normal `render` call, but this is where Express 2 & 3 put it - // so we make an exception for `renderFile` - var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); - var _BOM = /^\uFEFF/; - var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; - - /** - * EJS template function cache. This can be a LRU object from lru-cache NPM - * module. By default, it is {@link module:utils.cache}, a simple in-process - * cache that grows continuously. - * - * @type {Cache} - */ - - exports.cache = utils$1.cache; - - /** - * Custom file loader. Useful for template preprocessing or restricting access - * to a certain part of the filesystem. - * - * @type {fileLoader} - */ - - exports.fileLoader = fs.readFileSync; - - /** - * Name of the object containing the locals. - * - * This variable is overridden by {@link Options}`.localsName` if it is not - * `undefined`. - * - * @type {String} - * @public - */ - - exports.localsName = _DEFAULT_LOCALS_NAME; - - /** - * Promise implementation -- defaults to the native implementation if available - * This is mostly just for testability - * - * @type {PromiseConstructorLike} - * @public - */ - - exports.promiseImpl = (new Function('return this;'))().Promise; - - /** - * Get the path to the included file from the parent file path and the - * specified path. - * - * @param {String} name specified path - * @param {String} filename parent file path - * @param {Boolean} [isDir=false] whether the parent file path is a directory - * @return {String} - */ - exports.resolveInclude = function(name, filename, isDir) { - var dirname = path.dirname; - var extname = path.extname; - var resolve = path.resolve; - var includePath = resolve(isDir ? filename : dirname(filename), name); - var ext = extname(name); - if (!ext) { - includePath += '.ejs'; - } - return includePath; - }; - - /** - * Try to resolve file path on multiple directories - * - * @param {String} name specified path - * @param {Array} paths list of possible parent directory paths - * @return {String} - */ - function resolvePaths(name, paths) { - var filePath; - if (paths.some(function (v) { - filePath = exports.resolveInclude(name, v, true); - return fs.existsSync(filePath); - })) { - return filePath; - } - } - - /** - * Get the path to the included file by Options - * - * @param {String} path specified path - * @param {Options} options compilation options - * @return {String} - */ - function getIncludePath(path, options) { - var includePath; - var filePath; - var views = options.views; - var match = /^[A-Za-z]+:\\|^\//.exec(path); - - // Abs path - if (match && match.length) { - path = path.replace(/^\/*/, ''); - if (Array.isArray(options.root)) { - includePath = resolvePaths(path, options.root); - } else { - includePath = exports.resolveInclude(path, options.root || '/', true); - } - } - // Relative paths - else { - // Look relative to a passed filename first - if (options.filename) { - filePath = exports.resolveInclude(path, options.filename); - if (fs.existsSync(filePath)) { - includePath = filePath; - } - } - // Then look in any views directories - if (!includePath && Array.isArray(views)) { - includePath = resolvePaths(path, views); - } - if (!includePath && typeof options.includer !== 'function') { - throw new Error('Could not find the include file "' + - options.escapeFunction(path) + '"'); - } - } - return includePath; - } - - /** - * Get the template from a string or a file, either compiled on-the-fly or - * read from cache (if enabled), and cache the template if needed. - * - * If `template` is not set, the file specified in `options.filename` will be - * read. - * - * If `options.cache` is true, this function reads the file from - * `options.filename` so it must be set prior to calling this function. - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {String} [template] template source - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned. - * @static - */ - - function handleCache(options, template) { - var func; - var filename = options.filename; - var hasTemplate = arguments.length > 1; - - if (options.cache) { - if (!filename) { - throw new Error('cache option requires a filename'); - } - func = exports.cache.get(filename); - if (func) { - return func; - } - if (!hasTemplate) { - template = fileLoader(filename).toString().replace(_BOM, ''); - } - } - else if (!hasTemplate) { - // istanbul ignore if: should not happen at all - if (!filename) { - throw new Error('Internal EJS error: no file name or template ' - + 'provided'); - } - template = fileLoader(filename).toString().replace(_BOM, ''); - } - func = exports.compile(template, options); - if (options.cache) { - exports.cache.set(filename, func); - } - return func; - } - - /** - * Try calling handleCache with the given options and data and call the - * callback with the result. If an error occurs, call the callback with - * the error. Used by renderFile(). - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {Object} data template data - * @param {RenderFileCallback} cb callback - * @static - */ - - function tryHandleCache(options, data, cb) { - var result; - if (!cb) { - if (typeof exports.promiseImpl == 'function') { - return new exports.promiseImpl(function (resolve, reject) { - try { - result = handleCache(options)(data); - resolve(result); - } - catch (err) { - reject(err); - } - }); - } - else { - throw new Error('Please provide a callback function'); - } - } - else { - try { - result = handleCache(options)(data); - } - catch (err) { - return cb(err); - } - - cb(null, result); - } - } - - /** - * fileLoader is independent - * - * @param {String} filePath ejs file path. - * @return {String} The contents of the specified file. - * @static - */ - - function fileLoader(filePath){ - return exports.fileLoader(filePath); - } - - /** - * Get the template function. - * - * If `options.cache` is `true`, then the template is cached. - * - * @memberof module:ejs-internal - * @param {String} path path for the specified file - * @param {Options} options compilation options - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned - * @static - */ - - function includeFile(path, options) { - var opts = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), options); - opts.filename = getIncludePath(path, opts); - if (typeof options.includer === 'function') { - var includerResult = options.includer(path, opts.filename); - if (includerResult) { - if (includerResult.filename) { - opts.filename = includerResult.filename; - } - if (includerResult.template) { - return handleCache(opts, includerResult.template); - } - } - } - return handleCache(opts); - } - - /** - * Re-throw the given `err` in context to the `str` of ejs, `filename`, and - * `lineno`. - * - * @implements {RethrowCallback} - * @memberof module:ejs-internal - * @param {Error} err Error object - * @param {String} str EJS source - * @param {String} flnm file name of the EJS file - * @param {Number} lineno line number of the error - * @param {EscapeCallback} esc - * @static - */ - - function rethrow(err, str, flnm, lineno, esc) { - var lines = str.split('\n'); - var start = Math.max(lineno - 3, 0); - var end = Math.min(lines.length, lineno + 3); - var filename = esc(flnm); - // Error context - var context = lines.slice(start, end).map(function (line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; - } - - function stripSemi(str){ - return str.replace(/;(\s*$)/, '$1'); - } - - /** - * Compile the given `str` of ejs into a template function. - * - * @param {String} template EJS template - * - * @param {Options} [opts] compilation options - * - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `opts.client`, either type might be returned. - * Note that the return type of the function also depends on the value of `opts.async`. - * @public - */ - - exports.compile = function compile(template, opts) { - var templ; - - // v1 compat - // 'scope' is 'context' - // FIXME: Remove this in a future version - if (opts && opts.scope) { - if (!scopeOptionWarned){ - console.warn('`scope` option is deprecated and will be removed in EJS 3'); - scopeOptionWarned = true; - } - if (!opts.context) { - opts.context = opts.scope; - } - delete opts.scope; - } - templ = new Template(template, opts); - return templ.compile(); - }; - - /** - * Render the given `template` of ejs. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} template EJS template - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @return {(String|Promise)} - * Return value type depends on `opts.async`. - * @public - */ - - exports.render = function (template, d, o) { - var data = d || utils$1.createNullProtoObjWherePossible(); - var opts = o || utils$1.createNullProtoObjWherePossible(); - - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 2) { - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); - } - - return handleCache(opts, template)(data); - }; - - /** - * Render an EJS file at the given `path` and callback `cb(err, str)`. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} path path to the EJS file - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @param {RenderFileCallback} cb callback - * @public - */ - - exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments); - var filename = args.shift(); - var cb; - var opts = {filename: filename}; - var data; - var viewOpts; - - // Do we have a callback? - if (typeof arguments[arguments.length - 1] == 'function') { - cb = args.pop(); - } - // Do we have data/opts? - if (args.length) { - // Should always have data obj - data = args.shift(); - // Normal passed opts (data obj + opts obj) - if (args.length) { - // Use shallowCopy so we don't pollute passed in opts obj with new vals - utils$1.shallowCopy(opts, args.pop()); - } - // Special casing for Express (settings + opts-in-data) - else { - // Express 3 and 4 - if (data.settings) { - // Pull a few things from known locations - if (data.settings.views) { - opts.views = data.settings.views; - } - if (data.settings['view cache']) { - opts.cache = true; - } - // Undocumented after Express 2, but still usable, esp. for - // items that are unsafe to be passed along with data, like `root` - viewOpts = data.settings['view options']; - if (viewOpts) { - utils$1.shallowCopy(opts, viewOpts); - } - } - // Express 2 and lower, values set in app.locals, or people who just - // want to pass options in their data. NOTE: These values will override - // anything previously set in settings or settings['view options'] - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); - } - opts.filename = filename; - } - else { - data = utils$1.createNullProtoObjWherePossible(); - } - - return tryHandleCache(opts, data, cb); - }; - - /** - * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. - * @public - */ - - /** - * EJS template class - * @public - */ - exports.Template = Template; - - exports.clearCache = function () { - exports.cache.reset(); - }; - - function Template(text, opts) { - opts = opts || utils$1.createNullProtoObjWherePossible(); - var options = utils$1.createNullProtoObjWherePossible(); - this.templateText = text; - /** @type {string | null} */ - this.mode = null; - this.truncate = false; - this.currentLine = 1; - this.source = ''; - options.client = opts.client || false; - options.escapeFunction = opts.escape || opts.escapeFunction || utils$1.escapeXML; - options.compileDebug = opts.compileDebug !== false; - options.debug = !!opts.debug; - options.filename = opts.filename; - options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; - options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; - options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; - options.strict = opts.strict || false; - options.context = opts.context; - options.cache = opts.cache || false; - options.rmWhitespace = opts.rmWhitespace; - options.root = opts.root; - options.includer = opts.includer; - options.outputFunctionName = opts.outputFunctionName; - options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; - options.views = opts.views; - options.async = opts.async; - options.destructuredLocals = opts.destructuredLocals; - options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; - - if (options.strict) { - options._with = false; - } - else { - options._with = typeof opts._with != 'undefined' ? opts._with : true; - } - - this.opts = options; - - this.regex = this.createRegex(); - } - - Template.modes = { - EVAL: 'eval', - ESCAPED: 'escaped', - RAW: 'raw', - COMMENT: 'comment', - LITERAL: 'literal' - }; - - Template.prototype = { - createRegex: function () { - var str = _REGEX_STRING; - var delim = utils$1.escapeRegExpChars(this.opts.delimiter); - var open = utils$1.escapeRegExpChars(this.opts.openDelimiter); - var close = utils$1.escapeRegExpChars(this.opts.closeDelimiter); - str = str.replace(/%/g, delim) - .replace(//g, close); - return new RegExp(str); - }, - - compile: function () { - /** @type {string} */ - var src; - /** @type {ClientFunction} */ - var fn; - var opts = this.opts; - var prepended = ''; - var appended = ''; - /** @type {EscapeCallback} */ - var escapeFn = opts.escapeFunction; - /** @type {FunctionConstructor} */ - var ctor; - /** @type {string} */ - var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined'; - - if (!this.source) { - this.generateSource(); - prepended += - ' var __output = "";\n' + - ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; - if (opts.outputFunctionName) { - if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) { - throw new Error('outputFunctionName is not a valid JS identifier.'); - } - prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; - } - if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) { - throw new Error('localsName is not a valid JS identifier.'); - } - if (opts.destructuredLocals && opts.destructuredLocals.length) { - var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; - for (var i = 0; i < opts.destructuredLocals.length; i++) { - var name = opts.destructuredLocals[i]; - if (!_JS_IDENTIFIER.test(name)) { - throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.'); - } - if (i > 0) { - destructuring += ',\n '; - } - destructuring += name + ' = __locals.' + name; - } - prepended += destructuring + ';\n'; - } - if (opts._with !== false) { - prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; - appended += ' }' + '\n'; - } - appended += ' return __output;' + '\n'; - this.source = prepended + this.source + appended; - } - - if (opts.compileDebug) { - src = 'var __line = 1' + '\n' - + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' - + ' , __filename = ' + sanitizedFilename + ';' + '\n' - + 'try {' + '\n' - + this.source - + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' - + '}' + '\n'; - } - else { - src = this.source; - } - - if (opts.client) { - src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; - if (opts.compileDebug) { - src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; - } - } - - if (opts.strict) { - src = '"use strict";\n' + src; - } - if (opts.debug) { - console.log(src); - } - if (opts.compileDebug && opts.filename) { - src = src + '\n' - + '//# sourceURL=' + sanitizedFilename + '\n'; - } - - try { - if (opts.async) { - // Have to use generated function for this, since in envs without support, - // it breaks in parsing - try { - ctor = (new Function('return (async function(){}).constructor;'))(); - } - catch(e) { - if (e instanceof SyntaxError) { - throw new Error('This environment does not support async/await'); - } - else { - throw e; - } - } - } - else { - ctor = Function; - } - fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); - } - catch(e) { - // istanbul ignore else - if (e instanceof SyntaxError) { - if (opts.filename) { - e.message += ' in ' + opts.filename; - } - e.message += ' while compiling ejs\n\n'; - e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; - e.message += 'https://github.com/RyanZim/EJS-Lint'; - if (!opts.async) { - e.message += '\n'; - e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; - } - } - throw e; - } - - // Return a callable function which will execute the function - // created by the source-code, with the passed data as locals - // Adds a local `include` function which allows full recursive include - var returnedFn = opts.client ? fn : function anonymous(data) { - var include = function (path, includeData) { - var d = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), data); - if (includeData) { - d = utils$1.shallowCopy(d, includeData); - } - return includeFile(path, opts)(d); - }; - return fn.apply(opts.context, - [data || utils$1.createNullProtoObjWherePossible(), escapeFn, include, rethrow]); - }; - if (opts.filename && typeof Object.defineProperty === 'function') { - var filename = opts.filename; - var basename = path.basename(filename, path.extname(filename)); - try { - Object.defineProperty(returnedFn, 'name', { - value: basename, - writable: false, - enumerable: false, - configurable: true - }); - } catch (e) {/* ignore */} - } - return returnedFn; - }, - - generateSource: function () { - var opts = this.opts; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r` and empty lines don't work well with the `m` flag. - this.templateText = - this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); - - var self = this; - var matches = this.parseTemplateText(); - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - - if (matches && matches.length) { - matches.forEach(function (line, index) { - var closing; - // If this is an opening tag, check for closing tags - // FIXME: May end up with some false positives here - // Better to store modes as k/v with openDelimiter + delimiter as key - // Then this can simply check against the map - if ( line.indexOf(o + d) === 0 // If it is a tag - && line.indexOf(o + d + d) !== 0) { // and is not escaped - closing = matches[index + 2]; - if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { - throw new Error('Could not find matching close tag for "' + line + '".'); - } - } - self.scanLine(line); - }); - } - - }, - - parseTemplateText: function () { - var str = this.templateText; - var pat = this.regex; - var result = pat.exec(str); - var arr = []; - var firstPos; - - while (result) { - firstPos = result.index; - - if (firstPos !== 0) { - arr.push(str.substring(0, firstPos)); - str = str.slice(firstPos); - } - - arr.push(result[0]); - str = str.slice(result[0].length); - result = pat.exec(str); - } - - if (str) { - arr.push(str); - } - - return arr; - }, - - _addOutput: function (line) { - if (this.truncate) { - // Only replace single leading linebreak in the line after - // -%> tag -- this is the single, trailing linebreak - // after the tag that the truncation mode replaces - // Handle Win / Unix / old Mac linebreaks -- do the \r\n - // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, ''); - this.truncate = false; - } - if (!line) { - return line; - } - - // Preserve literal slashes - line = line.replace(/\\/g, '\\\\'); - - // Convert linebreaks - line = line.replace(/\n/g, '\\n'); - line = line.replace(/\r/g, '\\r'); - - // Escape double-quotes - // - this will be the delimiter during execution - line = line.replace(/"/g, '\\"'); - this.source += ' ; __append("' + line + '")' + '\n'; - }, - - scanLine: function (line) { - var self = this; - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - var newLineCount = 0; - - newLineCount = (line.split('\n').length - 1); - - switch (line) { - case o + d: - case o + d + '_': - this.mode = Template.modes.EVAL; - break; - case o + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case o + d + '-': - this.mode = Template.modes.RAW; - break; - case o + d + '#': - this.mode = Template.modes.COMMENT; - break; - case o + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; - break; - case d + d + c: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; - break; - case d + c: - case '-' + d + c: - case '_' + d + c: - if (this.mode == Template.modes.LITERAL) { - this._addOutput(line); - } - - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: - // In script mode, depends on type of tag - if (this.mode) { - // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } - } - switch (this.mode) { - // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; - // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; - break; - // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; - break; - case Template.modes.COMMENT: - // Do nothing - break; - // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - this._addOutput(line); - break; - } - } - // In string mode, just add the output - else { - this._addOutput(line); - } - } - - if (self.opts.compileDebug && newLineCount) { - this.currentLine += newLineCount; - this.source += ' ; __line = ' + this.currentLine + '\n'; - } - } - }; - - /** - * Escape characters reserved in XML. - * - * This is simply an export of {@link module:utils.escapeXML}. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @param {String} markup Input string - * @return {String} Escaped string - * @public - * @func - * */ - exports.escapeXML = utils$1.escapeXML; - - /** - * Express.js support. - * - * This is an alias for {@link module:ejs.renderFile}, in order to support - * Express.js out-of-the-box. - * - * @func - */ - - exports.__express = exports.renderFile; - - /** - * Version of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.VERSION = _VERSION_STRING; - - /** - * Name for detection of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.name = _NAME; - - /* istanbul ignore if */ - if (typeof window != 'undefined') { - window.ejs = exports; - } - } (ejs)); - - /** - * Extracts the segmentation value from the Bloomreach segmentation pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractSegmentationCookie() { - const cookiePrefix = `${COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS}=`; - const segmentationCookie = document.cookie.split('; ').find(cookie => cookie.startsWith(cookiePrefix)); - return (segmentationCookie || '').replace(cookiePrefix, ''); - } - - // /utils/getRequest.ts - /** - * Method used to initiate the API request - * @remarks The Assignment of the API specific promise is set in the respective API - * @param {string} url - * @param {{}} options - * @returns {Promise} - */ - async function getRequest(url, options) { - /** - * Use of Client-Side Fetch API to retrieve the response - * @type {Response} - */ - const response = await fetch(url, options); - /** - * Formats the response as json and returns the typed promise - * @type {any} - */ - const result = await response.json(); - /** - * Sets the type for the promise - */ - return result; - } - - // utils.requestOptions.ts - /** - * - * @type {{headers: {'Content-Type': string}, method: string}} - */ - const requestOptions = { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }; - - // utils/extractTrackingCookie.ts - /** - * Extracts the tracking cookie from the Bloomreach cookie pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractTrackingCookie() { - const trackingCookie = document.cookie.split('; ').find(cookie => cookie.startsWith('_br_uid_2=')); - return trackingCookie ? trackingCookie.replace('_br_uid_2=', '') : 'uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55'; - } - - // utils/formatAsCurrency.ts - /** - * Formats a value returned as a double into currency - * @param {number} cents - * @param {string} currencySign - * @param {boolean} onFront - * @returns {string} - */ - const formatAsCurrency = (cents, currencySign = '$', onFront = true) => `${onFront ? currencySign : ''}${(cents / 100.0).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 -})}${!onFront ? ` ${currencySign}` : ''}`; - - // utils/generateRequestID.ts - /** - * Generates a randomized request ID that is 13 characters long - * @returns {number} - */ - function generateRequestId() { - // eslint-disable-next-line no-mixed-operators - const requestID = Math.floor(1000000000000 + Math.random() * 9000000000000); - return requestID; - } - - // api-client/constants - // todo Refactor vanilla js / react implementation to either use or not use the constants config - const ENDPOINT_AUTOSUGGEST_API = 'https://suggest.dxpapi.com/api/v2/suggest/'; - const ENDPOINT_WIDGETS_API = 'https://pathways.dxpapi.com/api/v2/widgets/'; - const NO_ENCODE_PARAMETERS = ['_br_uid_2', 'fq', 'sort']; - const FIELD_LIST_WIDGETS = 'pid,price,sale_price,title,thumb_image,url'; - - function buildQueryParameters(apiCallParameters) { - return `?${Object.keys(apiCallParameters).reduce((queryParameters, parameterName) => [...queryParameters, `${parameterName}=${NO_ENCODE_PARAMETERS.includes(parameterName) ? apiCallParameters[parameterName] : encodeURIComponent(apiCallParameters[parameterName])}`], []).join('&')}`; - } - function buildAutosuggestRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_AUTOSUGGEST_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - function buildRecommendationWidgetsRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = `${(apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_WIDGETS_API}${apiParameters.type}/${apiParameters.id}`; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - if (!(apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.fields)) apiParameters.fields = FIELD_LIST_WIDGETS; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSuggestions(params) { - const url = buildAutosuggestRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - /** - * Get category widget API - * @returns {Promise} - */ - async function getCategoryWidget(params) { - const url = buildRecommendationWidgetsRequestUrl(Object.assign(Object.assign({}, params), { - type: 'category' - })); - const options = requestOptions; - return getRequest(url, options); - } - /** - * Get keyword widget API - * @returns {Promise} - */ - async function getKeywordWidget(params) { - const url = buildRecommendationWidgetsRequestUrl(Object.assign(Object.assign({}, params), { - type: 'keyword' - })); - const options = requestOptions; - return getRequest(url, options); - } - /** - * Get global widget API - * @returns {Promise} - */ - async function getGlobalWidget(params) { - const url = buildRecommendationWidgetsRequestUrl(Object.assign(Object.assign({}, params), { - type: 'global' - })); - const options = requestOptions; - return getRequest(url, options); - } - /** - * Get personalized widget API - * @returns {Promise} - */ - async function getPersonalizedWidget(params) { - const url = buildRecommendationWidgetsRequestUrl(Object.assign(Object.assign({}, params), { - type: 'personalized' - })); - const options = requestOptions; - return getRequest(url, options); - } - /** - * Get item widget API - * @returns {Promise} - */ - async function getItemWidget(params) { - const url = buildRecommendationWidgetsRequestUrl(Object.assign(Object.assign({}, params), { - type: 'item' - })); - const options = requestOptions; - return getRequest(url, options); - } - - var searchLayoutTemplate = "<% if (did_you_mean.length) { %>\n \n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from \"<%- keywordRedirect.original_query %>\"
\n
\n
\n<% } %>\n
category<% } else { %>product-search<% } %> blm-results <% if (config.search.facets_included) { %>with-facets<% } %>\">\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class=\"blm-product-search__results\"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n"; - - var searchListTemplate = "<% function printProduct(product) { %>\n
title=\"<%- product.variant_name %>\"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : 'variant_index' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style=\"display: block\"<% } %>\n >\n \"\n />\n
\n <% }); %>\n <% } else { %>\n
\n \"\n />\n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n active<% } %>\"\n style=\"background-image: url('<%= variant.image %>')\"\n >\n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n"; - - var autosuggestTemplate = "<% if (terms.length || productSuggestions.length) { %>\n
\n <% } %>\n"; - - var recommendationWidgetTemplate = "
\" data-type=\"<%= widgetMetadata.type %>\" data-id=\"<%= widgetMetadata.id %>\">\n <% if (products.length > config.number_of_items_to_show) { %>\n \n \n \n \n \n \n <% } %>\n\n
\">\n <% products.forEach(function(product) { %>\n
\">\n
\n \n
\n \n <% if (product.price && product.sale_price) { %>\n

\n <% if (config.format_money) { %>\n <%= config.format_money(product.sale_price.toFixed(2) * 100) %> <%= config.format_money(product.price.toFixed(2) * 100) %>\n <% } else { %>\n <%= config.default_currency %><%= product.sale_price.toFixed(2) %> <%= config.default_currency %><%= product.price.toFixed(2) %>\n <% } %>\n

\n <% } else { %>\n

\n <% if (config.format_money) { %>\n <%= config.format_money(product.price.toFixed(2) * 100) %>\n <% } else { %>\n <%= config.default_currency %><%= product.price.toFixed(2) %>\n <% } %>\n

\n <% } %>\n
\n
\n
\n <% }); %>\n
\n\n <% if (products.length > config.number_of_items_to_show) { %>\n \n \n \n \n \n \n <% } %>\n
\n"; - - function buildBaseConfig() { - var _a; - const connectorConfig = (_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config; - const config = Object.assign({ - default_search_parameter: DEFAULT_SEARCH_PARAMETER, - url: window.location.href, - ref_url: window.location.href, - tracking_cookie: extractTrackingCookie(), - format_money: cents => formatAsCurrency(cents, window.bloomreachDefaultCurrency || DEFAULT_CURRENCY), - default_currency: window.bloomreachDefaultCurrency || DEFAULT_CURRENCY - }, connectorConfig); - return config; - } - function buildAutosuggestConfig() { - const baseConfig = buildBaseConfig(); - const config = Object.assign(Object.assign({ - request_type: REQUEST_TYPE_SUGGEST - }, baseConfig), { - autosuggest: Object.assign({ - enabled: true, - endpoint: '', - number_of_terms: NUMBER_OF_AUTOSUGGEST_TERMS, - number_of_products: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - number_of_collections: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - selector: SELECTOR_AUTOSUGGEST_INPUT, - template: autosuggestTemplate, - catalog_views: '' - }, baseConfig.autosuggest) - }); - return config; - } - function buildSearchConfig() { - var _a, _b, _c; - const baseConfig = buildBaseConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const state = getCurrentSearchRequestState(); - const defaultSearchProperties = Object.assign({ - display_variants: false, - enabled: true, - endpoint: '', - items_per_page: DEFAULT_PAGE_SIZE, - facets_included: true, - initial_number_of_facets: NUMBER_OF_FACET_GROUPS, - initial_number_of_facet_values: NUMBER_OF_FACET_VALUES, - infinite_scroll: false, - selector: SELECTOR_SEARCH_RESULTS_CONTAINER, - sorting_options: DEFAULT_SORTING_OPTIONS, - template: searchLayoutTemplate, - product_list_template: searchListTemplate - }, (baseConfig === null || baseConfig === void 0 ? void 0 : baseConfig.search) ? baseConfig.search : {}); - const config = Object.assign(Object.assign({}, baseConfig), { - request_type: REQUEST_TYPE_SEARCH, - search_type: state.is_category_page ? SEARCH_TYPE_CATEGORY : SEARCH_TYPE_KEYWORD, - start: DEFAULT_START, - 'facet.range': FIELD_NAME_PRICE, - 'stats.field': FIELD_NAME_PRICE, - sort: urlParameters.get(PARAMETER_NAME_SORT) || '', - search: Object.assign(Object.assign(Object.assign({}, defaultSearchProperties), (state.is_category_page ? baseConfig.category : baseConfig.search) || {}), state.category_to_load ? { - category_id: state.category_to_load - } : {}) - }); - (_c = (_b = (_a = config.search) === null || _a === void 0 ? void 0 : _a.sorting_options) === null || _b === void 0 ? void 0 : _b.sort) === null || _c === void 0 ? void 0 : _c.call(_b, (option1, option2) => option1.value > option2.value ? 1 : -1); - if (config.search) { - config.search = Object.assign(Object.assign({}, config.search), { - items_per_page: Number(urlParameters.has(PARAMETER_NAME_SIZE) ? urlParameters.get(PARAMETER_NAME_SIZE) : config.search.items_per_page), - groupby: urlParameters.get(PARAMETER_NAME_GROUPBY) || config.search.groupby || '' - }); - } - return config; - } - function buildRecommendationsConfig() { - const baseConfig = buildBaseConfig(); - const config = Object.assign(Object.assign({}, baseConfig), { - widget: Object.assign({ - endpoint: '', - fields: '', - template: recommendationWidgetTemplate - }, baseConfig.widget) - }); - return config; - } - - let memoizedNS; - const NOOP = Object.assign(() => {}, { - warn: () => {}, - error: () => {}, - verbose: () => {} - }); - let colorIndex = -1; - const memoizedColor = new Map(); - /** - * List of colors our debugger can pick from. The colors should be slightly - * desautrated to help with reading and should be highly varied. - */ - const pickColor = ns => { - if (memoizedColor.has(ns)) return memoizedColor.get(ns); - const color = ['#00a3ff', '#ff00a3', '#a3ff00', '#00ffa3', '#a300ff', '#ffaa00', '#00ffaa', '#ff00aa', '#aa00ff', '#00aaff'][++colorIndex % 10] || '#00a3ff'; - memoizedColor.set(ns, color); - return color; - }; - /** - * Creates a simple debug logger system that is only activated by the stored - * state within localStorage.debug. The value in the state can be: - * - * namespace1;namespace2;namespace3;etc - * - * or - * - * namepspace1 - * - * or - * - * * - * - * Where `*` is a wildcard that will activate all namespaces. - */ - const Debug = ns => { - const active = activeNS(); - // If the namespace is not active, return a noop function set - if (!active.has(ns) && !active.has('*')) return NOOP; - const color = pickColor(ns); - const logger = console.log.bind(console, `%c${ns}`, `color: ${color}`); - logger.warn = console.warn.bind(console, `%c${ns}`, `color: ${color}`); - logger.error = console.error.bind(console, `%c${ns}`, `color: ${color}`); - if (active.has(`${ns}:verbose`) || active.has('*')) { - logger.verbose = console.log.bind(console, `%c${ns}:verbose`, `color: ${color}`); - } else { - logger.verbose = () => {}; - } - return logger; - }; - function activeNS() { - if (memoizedNS) return memoizedNS; - const storage = window.localStorage; - if (!storage) return new Set(); - const ns = storage.getItem('debug') || ''; - memoizedNS = new Set(ns.split(';')); - return memoizedNS; - } - - /** - * If a truthy value is false, this throws an error and displays the message for - * the error. - */ - function invariant(truthy, message) { - if (truthy) return; - throw new Error(message); - } - - Debug('br:autosuggest'); - function findUpElementWithClassName(startElement, className) { - var _a; - let element = startElement; - // eslint-disable-next-line functional/no-loop-statement - while (element && element.parentElement) { - element = element.parentElement; - if (element && ((_a = element.classList) === null || _a === void 0 ? void 0 : _a.contains(className))) { - return element; - } - } - return null; - } - function hideAllDynamicFacetGroups() { - ['.blm-dynamic-filter', '.blm-product-search-filter-item', '.blm-product-search-load-more'].forEach(selector => { - document.querySelectorAll(selector).forEach(item => { - item.removeAttribute('style'); - }); - }); - } - function loadMoreFacetGroups(numberOfFacetGroupsParameter) { - var _a; - let i = 0; - let numberOfHiddenBoxWithVisibleChildren = 0; - const config = buildSearchConfig(); - const numberOfFacetGroups = Number(numberOfFacetGroupsParameter || ((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets)); - document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach(item => { - const visibleChildren = item === null || item === void 0 ? void 0 : item.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]'); - if (i < numberOfFacetGroups && visibleChildren.length > 0) { - item === null || item === void 0 ? void 0 : item.setAttribute('style', 'display: block'); - } - i++; - numberOfHiddenBoxWithVisibleChildren += visibleChildren.length > 0 ? 1 : 0; - }); - const currentSearchRequestState = getCurrentSearchRequestState(); - const loadMoreFacetGroupsElement = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - const numberOfHiddenBoxes = document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length; - if (numberOfHiddenBoxes === 0 || numberOfHiddenBoxWithVisibleChildren === 0) { - loadMoreFacetGroupsElement === null || loadMoreFacetGroupsElement === void 0 ? void 0 : loadMoreFacetGroupsElement.classList.add('blm-hide'); - } - } - function getLoadMoreFacetGroupsElement() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const element = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - invariant(element, 'the element for loading more facet groups must be in the DOM'); - return element; - } - function resetFacetGroups() { - var _a, _b, _c; - const config = buildSearchConfig(); - const numberOfDisplayedFacetGroups = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets); - const numberOfDisplayedFacetValues = Number((_b = config.search) === null || _b === void 0 ? void 0 : _b.initial_number_of_facet_values); - hideAllDynamicFacetGroups(); - loadMoreFacetGroups(numberOfDisplayedFacetGroups - 1); - // init facet items visibility - document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${numberOfDisplayedFacetValues})`).forEach(item => item.style.display = 'block'); - (_c = getLoadMoreFacetGroupsElement()) === null || _c === void 0 ? void 0 : _c.removeAttribute('style'); - } - function getAutosuggestSearchInputElement() { - const config = buildAutosuggestConfig(); - if (!config.autosuggest) return null; - invariant(config.autosuggest.selector, 'the selector of search results container element must be set'); - const autosuggestInputElement = document.querySelector(config.autosuggest.selector); - return autosuggestInputElement; - } - function getAutosuggestResultsContainerElement() { - const autosuggestResultsContainerElement = document.querySelector('.blm-autosuggest-search-results'); - return autosuggestResultsContainerElement; - } - - var breakpoints; - (function (breakpoints) { - breakpoints["small"] = "480px"; - breakpoints["medium"] = "680px"; - breakpoints["large"] = "750px"; - breakpoints["xlarge"] = "875px"; - breakpoints["xxlarge"] = "1000px"; - breakpoints["xxxlarge"] = "1200px"; - })(breakpoints || (breakpoints = {})); - const isMobileView = window.matchMedia(`(max-width: ${breakpoints.medium})`); - const isTabletView = window.matchMedia(`(min-width:${breakpoints.medium}) and (max-width: ${breakpoints.xlarge})`); - - const log$2 = Debug('br:url'); - function updateUrl(urlParameters) { - var _a, _b, _c, _d; - const historyStateObject = {}; - // eslint-disable-next-line functional/no-loop-statement - for (const pair of urlParameters.entries()) { - historyStateObject[pair[0]] = pair[1]; - } - window.history.pushState(historyStateObject, document.title, `?${urlParameters.toString()}`); - const br_data = window.br_data || {}; - if (br_data.orig_ref_url !== location.href) { - br_data.orig_ref_url = location.href; - log$2('Generating virtual page view event for url update', location.href); - (_b = (_a = window.BrTrk) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.updateBrData(br_data); - (_d = (_c = window.BrTrk) === null || _c === void 0 ? void 0 : _c.getTracker()) === null || _d === void 0 ? void 0 : _d.logPageView(); - } - } - function updateParameterInUrl(parameterName, newValue) { - const urlParameters = new URLSearchParams(window.location.search); - if (typeof newValue === 'function') { - urlParameters.set(parameterName, - // @ts-ignore - newValue(urlParameters.get(parameterName)).replace(/"/g, '\\"')); - } else if (newValue === '') { - urlParameters.delete(parameterName); - } else { - urlParameters.set(parameterName, newValue.replace(/"/g, '\\"')); - } - updateUrl(urlParameters); - } - - const categoryLinkElementClickListener = event => { - var _a, _b, _c; - event.preventDefault(); - const clickedElement = event.target; - const categoryId = ((_a = clickedElement.dataset) === null || _a === void 0 ? void 0 : _a.categoryId) || ''; - const module = ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.search) || ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category); - if (module) { - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - module.load(categoryId).then(() => { - const autosuggestSearchElement = getAutosuggestSearchInputElement(); - const autosuggestResultsElement = getAutosuggestResultsContainerElement(); - if (autosuggestSearchElement) { - autosuggestSearchElement.value = (clickedElement === null || clickedElement === void 0 ? void 0 : clickedElement.textContent) || ''; - } - if (autosuggestResultsElement) { - autosuggestResultsElement.innerHTML = ''; - } - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - return true; - }).catch(console.error); - } - }; - function addCategoryLinkElementClickListener() { - var _a; - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link--category').forEach(categoryLinkElement => { - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.removeEventListener('click', categoryLinkElementClickListener); - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.addEventListener('click', categoryLinkElementClickListener); - }); - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - - function isObject$2(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - var isObject_1 = isObject$2; - - /** Detect free variable `global` from Node.js. */ - - var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; - - var _freeGlobal = freeGlobal$1; - - var freeGlobal = _freeGlobal; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root$2 = freeGlobal || freeSelf || Function('return this')(); - - var _root = root$2; - - var root$1 = _root; - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now$1 = function() { - return root$1.Date.now(); - }; - - var now_1 = now$1; - - /** Used to match a single whitespace character. */ - - var reWhitespace = /\s/; - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ - function trimmedEndIndex$1(string) { - var index = string.length; - - while (index-- && reWhitespace.test(string.charAt(index))) {} - return index; - } - - var _trimmedEndIndex = trimmedEndIndex$1; - - var trimmedEndIndex = _trimmedEndIndex; - - /** Used to match leading whitespace. */ - var reTrimStart = /^\s+/; - - /** - * The base implementation of `_.trim`. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function baseTrim$1(string) { - return string - ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') - : string; - } - - var _baseTrim = baseTrim$1; - - var root = _root; - - /** Built-in value references. */ - var Symbol$2 = root.Symbol; - - var _Symbol = Symbol$2; - - var Symbol$1 = _Symbol; - - /** Used for built-in method references. */ - var objectProto$1 = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto$1.hasOwnProperty; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString$1 = objectProto$1.toString; - - /** Built-in value references. */ - var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag$1(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; - } - - var _getRawTag = getRawTag$1; - - /** Used for built-in method references. */ - - var objectProto = Object.prototype; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString$1(value) { - return nativeObjectToString.call(value); - } - - var _objectToString = objectToString$1; - - var Symbol = _Symbol, - getRawTag = _getRawTag, - objectToString = _objectToString; - - /** `Object#toString` result references. */ - var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - - /** Built-in value references. */ - var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag$1(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - var _baseGetTag = baseGetTag$1; - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - - function isObjectLike$1(value) { - return value != null && typeof value == 'object'; - } - - var isObjectLike_1 = isObjectLike$1; - - var baseGetTag = _baseGetTag, - isObjectLike = isObjectLike_1; - - /** `Object#toString` result references. */ - var symbolTag = '[object Symbol]'; - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol$1(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - var isSymbol_1 = isSymbol$1; - - var baseTrim = _baseTrim, - isObject$1 = isObject_1, - isSymbol = isSymbol_1; - - /** Used as references for various `Number` constants. */ - var NAN = 0 / 0; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Built-in method references without a dependency on `root`. */ - var freeParseInt = parseInt; - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber$1(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject$1(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject$1(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - var toNumber_1 = toNumber$1; - - var isObject = isObject_1, - now = now_1, - toNumber = toNumber_1; - - /** Error message constants. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max, - nativeMin = Math.min; - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. 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 debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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's 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 clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - var debounce_1 = debounce; - - debounce_1(event => { - const query = event.target.value; - const searchInputElement = getAutosuggestSearchInputElement(); - if (!searchInputElement) return; - if (query.length >= AUTOSUGGEST_MINIMUM_QUERY_LENGTH) { - searchInputElement.dataset.originalQuery = query; - suggest(query).catch(console.error); - } else { - const autosuggestResultsContainerElement = getAutosuggestResultsContainerElement(); - if (autosuggestResultsContainerElement) { - autosuggestResultsContainerElement.innerHTML = ''; - } - searchInputElement.dataset.originalQuery = ''; - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - } - }, 500); - - const listeners$2 = new WeakMap(); - const suggestionTermElementClickListener = suggestionTermElement => { - return () => { - var _a, _b; - const { - suggestionText - } = suggestionTermElement.dataset; - const input = getAutosuggestSearchInputElement(); - if (!input) return; - const { - originalQuery - } = input.dataset; - const suggestionData = { - aq: originalQuery, - q: suggestionText, - catalogs: [{ - name: 'example_en' - }] - }; - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('suggest', 'click', suggestionData, {}, true); - }; - }; - function addSuggestionTermElementClickListener() { - var _a; - // Apply listeners in re-entrant fashion - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link').forEach(suggestionTermElement => { - const listener = suggestionTermElementClickListener(suggestionTermElement); - const old = listeners$2.get(suggestionTermElement); - if (old) suggestionTermElement.removeEventListener('click', old); - listeners$2.set(suggestionTermElement, listener); - suggestionTermElement === null || suggestionTermElement === void 0 ? void 0 : suggestionTermElement.addEventListener('click', listener); - }); - } - - function mapAutosuggestApiResponse(responseData) { - return isV2Response(responseData) ? mapV2Response(responseData) : mapV1Response(responseData); - } - function mapV2Response(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j; - const config = buildAutosuggestConfig(); - const productSuggestions = ((_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.searchSuggestions) || []; - const suggestions = ((_d = (_c = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.querySuggestions) || []; - const categorySuggestions = ((_f = (_e = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.attributeSuggestions) || []; - const mappedApiResponse = Object.assign(Object.assign({}, ((_g = responseData === null || responseData === void 0 ? void 0 : responseData.queryContext) === null || _g === void 0 ? void 0 : _g.originalQuery) ? { - originalQuery: responseData.queryContext.originalQuery - } : {}), { - terms: [...suggestions.map((term, index) => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.query, - displayText: term.displayText, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.query)}` - }), index === 0 && categorySuggestions ? { - categories: categorySuggestions.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.attributeType - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - })].slice(0, (_h = config.autosuggest) === null || _h === void 0 ? void 0 : _h.number_of_terms), - productSuggestions: [...productSuggestions.map(product => Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: Number((product === null || product === void 0 ? void 0 : product.sale_price) || '0') - }))].slice(0, (_j = config.autosuggest) === null || _j === void 0 ? void 0 : _j.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function isV2Response(responseData) { - return 'suggestionGroups' in responseData; - } - function mapV1Response(responseData) { - var _a, _b; - const config = buildAutosuggestConfig(); - const mappedApiResponse = Object.assign(Object.assign({}, responseData.response.q ? { - originalQuery: responseData.response.q - } : {}), { - terms: [...(responseData.response.suggestions ? responseData.response.suggestions.map(term => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.q, - displayText: term.dq, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.q)}` - }), term.filters ? { - categories: term.filters.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.key - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - }) : [])].slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_terms), - productSuggestions: [...(responseData.response.products ? responseData.response.products.map(product => Object.assign(Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: !Number.isNaN(product.sale_price) ? product.sale_price : !Number.isNaN(product.price) ? product.price : '0' - }), 'price' in product && 'sale_price' in product ? { - price: product.price - } : {})) : [])].slice(0, (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function highlightQueryInTermLabels(results) { - const processedResults = Object.assign({}, results); - results.terms.forEach((term, index) => { - const typedQueryHtml = ejs.render(AUTOSUGGEST_TYPED_QUERY_TEMPLATE, { - query: results.originalQuery - }).trim(); - (processedResults.terms[index] || {}).processedText = term.text.replace(results.originalQuery || '', typedQueryHtml); - }); - return processedResults; - } - - function mapRecommendationsApiResponse(responseData) { - const config = buildRecommendationsConfig(); - return { - config, - products: [...(responseData.response.docs ? responseData.response.docs.map(product => Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: product.sale_price, - price: product.price - })) : [])], - widgetMetadata: responseData.metadata.widget - }; - } - - const log$1 = Debug('br:autosuggest'); - /** - * Retrieves suggestions from the suggest API and renders them to the DOM. - */ - async function suggest(query) { - var _a, _b, _c; - log$1('Fetching suggestions for', query); - const config = buildAutosuggestConfig(); - updateCurrentAutosuggestRequestState({ - request_id: generateRequestId() - }); - const apiCallParameters = buildApiCallParameters$1(query); - // todo remediate typescript issue - // @ts-ignore - const results = await getSuggestions(apiCallParameters); - const templateData = mapAutosuggestApiResponse(results); - updateCurrentAutosuggestRequestState({ - last_template_data: templateData - }); - const container = getAutosuggestResultsContainerElement(); - if (!container) return; - log$1.verbose('Using config', config); - log$1.verbose('Render to:', container); - log$1.verbose('Is using default template?', !((_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.template)); - log$1.verbose('Rendering with template:', { - template: ((_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.template) || autosuggestTemplate, - templateData - }); - container.innerHTML = ejs.render(((_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.template) || autosuggestTemplate, templateData); - addCategoryLinkElementClickListener(); - addSuggestionTermElementClickListener(); - } - /** - * Generates the API paramters fed into the suggest API call body. - */ - function buildApiCallParameters$1(query) { - var _a, _b, _c; - const config = buildAutosuggestConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentAutosuggestRequestState = getCurrentAutosuggestRequestState(); - const apiParameters = Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.autosuggest) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.autosuggest.endpoint - } : {}), { - q: query || urlParameters.get((config === null || config === void 0 ? void 0 : config.default_search_parameter) || '') || '', - aq: query, - sort: (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.sort, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentAutosuggestRequestState.request_id, - _br_uid_2: config.tracking_cookie, - ref_url: config.ref_url, - url: config.url, - request_type: config.request_type, - catalog_views: (_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.catalog_views, - search_type: 'keyword' - }); - if (!apiParameters.catalog_views) { - apiParameters.catalog_views = ''; - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === undefined) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function getCurrentAutosuggestRequestState() { - return window.BloomreachModules.autosuggest.getCurrentAutosuggestRequestState(); - } - function updateCurrentAutosuggestRequestState(state) { - window.BloomreachModules.autosuggest.setCurrentAutosuggestRequestState(Object.assign(Object.assign({}, getCurrentAutosuggestRequestState()), state)); - } - - Debug('br:product-events'); - - const listeners$1 = new WeakMap(); - const widgetAddToCartButtonClickListener = parameters => { - const widgetAddToCartEventData = Object.assign(Object.assign({ - wrid: parameters.widgetRid, - wid: parameters.widgetId, - wty: parameters.widgetType, - item_id: parameters.blmWidgetAddToCartProdId - }, parameters.query ? { - wq: parameters.query - } : {}), { - sku: parameters.blmWidgetAddToCartSku - }); - return () => { - var _a, _b; - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('cart', 'widget-add', widgetAddToCartEventData); - }; - }; - function addWidgetAddToCartButtonClickListener() { - getCurrentRecommendationsUiState().widgets.forEach(widgetData => { - const widgetElement = widgetData.node; - const widgetContentElement = widgetElement.querySelector('.blm-recommendation-widget-content'); - const { - id: widgetId = '', - type: widgetType = '', - rid: widgetRid = '' - } = widgetContentElement.dataset; - widgetElement.querySelectorAll('[data-blm-widget-add-to-cart]').forEach(addToCartElement => { - var _a; - const { - blmWidgetAddToCartSku = '', - blmWidgetAddToCartProdId = '' - } = addToCartElement.dataset; - const old = listeners$1.get(addToCartElement); - if (old) addToCartElement.removeEventListener('click', old); - const listener = widgetAddToCartButtonClickListener({ - widgetRid, - widgetId, - widgetType, - blmWidgetAddToCartSku, - blmWidgetAddToCartProdId, - query: (_a = widgetElement === null || widgetElement === void 0 ? void 0 : widgetElement.dataset) === null || _a === void 0 ? void 0 : _a.query - }); - listeners$1.set(addToCartElement, listener); - addToCartElement === null || addToCartElement === void 0 ? void 0 : addToCartElement.addEventListener('click', listener); - }); - }); - } - - const listeners = new WeakMap(); - const widgetLinkElementClickListener = parameters => { - return () => { - var _a, _b; - const widgetClickEventData = Object.assign({ - wrid: parameters.widgetRid, - wid: parameters.widgetId, - wty: parameters.widgetType, - item_id: parameters.productId - }, parameters.query ? { - wq: parameters.query - } : {}); - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('widget', 'widget-click', widgetClickEventData, true); - }; - }; - function addWidgetLinkElementClickListener() { - getCurrentRecommendationsUiState().widgets.forEach(widgetData => { - const widgetElement = widgetData.node; - const widgetContentElement = widgetElement.querySelector('.blm-recommendation-widget-content'); - const { - id: widgetId = '', - type: widgetType = '', - rid: widgetRid = '' - } = widgetContentElement.dataset; - // Add listeners in re-entrant fashion - widgetElement.querySelectorAll('.blm-widget-link').forEach(linkElement => { - var _a; - const productElement = findUpElementWithClassName(linkElement, 'blm-recommendation__product'); - const productId = (productElement === null || productElement === void 0 ? void 0 : productElement.dataset.id) || ''; - const old = listeners.get(linkElement); - if (old) linkElement.removeEventListener('click', old); - const listener = widgetLinkElementClickListener({ - widgetRid, - widgetId, - widgetType, - productId, - query: (_a = widgetElement === null || widgetElement === void 0 ? void 0 : widgetElement.dataset) === null || _a === void 0 ? void 0 : _a.query - }); - listeners.set(linkElement, listener); - linkElement === null || linkElement === void 0 ? void 0 : linkElement.addEventListener('click', listener); - }); - }); - } - - const log = Debug('br:recommendations'); - function buildRecommendationsModule() { - log('Build Recommendations Module:', '4.0.0'); - let currentRecommendationsRequestState = { - request_id: 0 - }; - let currentRecommendationsUiState = { - widgets: [] - }; - return { - setCurrentRecommendationsRequestState: requestState => { - currentRecommendationsRequestState = requestState; - }, - getCurrentRecommendationsRequestState: () => currentRecommendationsRequestState, - setCurrentRecommendationsUiState: uiState => { - currentRecommendationsUiState = uiState; - }, - getCurrentRecommendationsUiState: () => currentRecommendationsUiState, - load: async () => { - await initPolling(); - } - }; - } - /** - * Polls for conditions to be met to mount this module. - */ - async function initPolling() { - let state = getCurrentRecommendationsUiState(); - window.clearInterval(state.pollIntervalId); - buildRecommendationsConfig(); - const doPoll = async () => { - state = getCurrentRecommendationsUiState(); - const currentWidgets = state.widgets; - collectWidgetsFromDom(); - state = getCurrentRecommendationsUiState(); - const foundWidgets = state.widgets; - if (currentWidgets.length && !foundWidgets.length) ; else if (!currentWidgets.length && foundWidgets.length) { - // We went from having no widgets to having widgets, so we need to mount the module. - await moduleWillMount(); - } - }; - if (!state.pollIntervalId) log('Polling initialized'); - // Begin the polling service. - // eslint-disable-next-line @typescript-eslint/no-misused-promises - const pollTimer = window.setInterval(doPoll, 100); - updateCurrentRecommendationsUiState({ - pollIntervalId: pollTimer - }); - // We execute the poll immediately so if we have a script that is "smarter" - // about when all conditions are ready for the module, there is a path to have - // an immediate initialization. - await doPoll(); - } - /** - * Conditions for this module are met and now the module will initialize all of - * it's functionality. - */ - async function moduleWillMount() { - log('Mounting module...'); - updateCurrentRecommendationsRequestState({ - request_id: generateRequestId() - }); - storeSegmentationPixelData(); - - collectWidgetsFromDom(); - - // get and populate widgets data into the DOM - const loadWidgets = getCurrentRecommendationsUiState().widgets.reduce((allPromises, widgetData) => [...allPromises, new Promise(resolve => { - // build API call parameters - const apiCallParameters = buildApiCallParameters(widgetData.node); - // call api and get data - let widgetResponse; - if (isKeywordWidgetRequest(apiCallParameters)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - widgetResponse = getKeywordWidget(apiCallParameters); - } else if (isCategoryWidgetRequest(apiCallParameters)) { - widgetResponse = getCategoryWidget(apiCallParameters); - } else if (isItemWidgetRequest(apiCallParameters)) { - widgetResponse = getItemWidget(apiCallParameters); - } else if (isPersonalizedWidgetRequest(apiCallParameters)) { - widgetResponse = getPersonalizedWidget(apiCallParameters); - } else { - widgetResponse = getGlobalWidget(apiCallParameters); - } - resolve(widgetResponse); - }).then(widgetResponse => { - var _a; - const widgetElement = widgetData.node; - const config = buildRecommendationsConfig(); - // build template data - const templateData = mapRecommendationsApiResponse(widgetResponse); - const widgetAttributes = widgetElement.dataset; - templateData.config.number_of_items_to_show = Number(widgetAttributes.numberOfItemsToShow); - // render widget template into its container - widgetElement.innerHTML = ejs.render(((_a = config.widget) === null || _a === void 0 ? void 0 : _a.template) || '', templateData); - logWidgetViewEvent(widgetElement); - widgetElement.classList.add('blm-widget-loaded'); - return { - widgetElement, - templateData - }; - })], []); - const loadedWidgets = await Promise.all(loadWidgets).catch(console.error); - // add event listeners to loaded widget content - addWidgetAddToCartButtonClickListener(); - addWidgetLinkElementClickListener(); - (loadedWidgets || []).forEach(widgetResult => { - setupCarousel(widgetResult.widgetElement, widgetResult.templateData); - }); - } - function buildApiCallParameters(widgetNode) { - var _a; - const config = buildRecommendationsConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentRecommendationsRequestState = getCurrentRecommendationsRequestState(); - const widgetAttributes = widgetNode.dataset; - const apiParameters = Object.assign(Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.widget) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.widget.endpoint - } : {}), { - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentRecommendationsRequestState.request_id, - _br_uid_2: config.tracking_cookie, - ref_url: config.ref_url, - url: config.url, - rows: Number(widgetAttributes.numberOfItemsToFetch) || DEFAULT_PAGE_SIZE, - start: DEFAULT_START - }), widgetAttributes); - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - const segmentationData = extractSegmentationCookie(); - if (segmentationData) { - apiParameters.brSeg = `seg:${segmentationData}`; - apiParameters.segment = `customer_profile:${segmentationData}`; - apiParameters.cdp_segments = segmentationData; - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === undefined) { - delete apiParameters[key]; - } - }); - switch (widgetAttributes.type) { - case 'keyword': - apiParameters.query = widgetAttributes.query; - return apiParameters; - case 'category': - apiParameters.cat_id = widgetAttributes.categoryId; - return apiParameters; - case 'item': - apiParameters.item_ids = widgetAttributes.itemIds; - return apiParameters; - case 'personalized': - apiParameters.user_id = widgetAttributes.userId; - return apiParameters; - case 'global': - return apiParameters; - default: - return new Error(`Invalid widget type: "${widgetAttributes.type}"`); - } - } - function getCurrentRecommendationsUiState() { - return window.BloomreachModules.pathwaysRecommendations.getCurrentRecommendationsUiState(); - } - function updateCurrentRecommendationsUiState(state) { - window.BloomreachModules.pathwaysRecommendations.setCurrentRecommendationsUiState(Object.assign(Object.assign({}, getCurrentRecommendationsUiState()), state)); - } - function getCurrentRecommendationsRequestState() { - return window.BloomreachModules.pathwaysRecommendations.getCurrentRecommendationsRequestState(); - } - function updateCurrentRecommendationsRequestState(state) { - window.BloomreachModules.pathwaysRecommendations.setCurrentRecommendationsRequestState(Object.assign(Object.assign({}, getCurrentRecommendationsRequestState()), state)); - } - function collectWidgetsFromDom() { - const widgets = []; - document.querySelectorAll('.blm-recommendations-widget').forEach(widgetNode => { - widgets.push({ - loaded: false, - node: widgetNode - }); - }); - updateCurrentRecommendationsUiState({ - widgets - }); - } - function storeSegmentationPixelData() { - const segmentationData = extractSegmentationCookie(); - if (segmentationData) { - const br_data = window.br_data || {}; - br_data[COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE] = segmentationData; - } - } - function isKeywordWidgetRequest(apiCallParameters) { - return 'query' in apiCallParameters; - } - function isCategoryWidgetRequest(apiCallParameters) { - return 'cat_id' in apiCallParameters; - } - function isItemWidgetRequest(apiCallParameters) { - return 'item_ids' in apiCallParameters; - } - function isPersonalizedWidgetRequest(apiCallParameters) { - return 'user_id' in apiCallParameters; - } - function logWidgetViewEvent(widgetElement) { - var _a, _b; - const widgetContentElement = widgetElement.querySelector('.blm-recommendation-widget-content'); - const { - id: widgetId = '', - type: widgetType = '', - rid: widgetRid = '' - } = widgetContentElement.dataset; - const widgetViewEventData = Object.assign({ - wrid: widgetRid, - wid: widgetId, - wty: widgetType - }, widgetElement.dataset.query ? { - wq: widgetElement.dataset.query - } : {}); - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('widget', 'widget-view', widgetViewEventData, true); - } - const carouselListeners = new WeakMap(); - function setupCarousel(widgetElement, templateData) { - const carouselPrevious = widgetElement.querySelector('.blm-carousel-previous'); - const carouselNext = widgetElement.querySelector('.blm-carousel-next'); - // @ts-ignore - const products = widgetElement.querySelectorAll('.blm-recommendation__product'); - const displayedProducts = Number(isMobileView.matches ? 1 : isTabletView.matches ? 2 : templateData.config.number_of_items_to_show); - const productPage = Math.ceil(products.length / displayedProducts); - let productCardWidth = 0; - if (products.length) { - const productsContainer = widgetElement.querySelector('.blm-recommendation__products'); - if (productsContainer) { - const computedStyles = window.getComputedStyle(productsContainer); - productCardWidth = Number(computedStyles.width.replace('px', '')) / displayedProducts; - } - } - let eachItemWidth = 0; - const movePer = productCardWidth; - const maxMove = (products.length - displayedProducts) * productCardWidth; - const adjustArrowVisibilities = () => { - var _a, _b, _c, _d; - if (((_b = (_a = products === null || products === void 0 ? void 0 : products[0]) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.left) === '0px') { - carouselPrevious === null || carouselPrevious === void 0 ? void 0 : carouselPrevious.classList.add('blm-invisible'); - } else { - carouselPrevious === null || carouselPrevious === void 0 ? void 0 : carouselPrevious.classList.remove('blm-invisible'); - } - if (((_d = (_c = products === null || products === void 0 ? void 0 : products[0]) === null || _c === void 0 ? void 0 : _c.style) === null || _d === void 0 ? void 0 : _d.left) === `-${maxMove}px`) { - carouselNext === null || carouselNext === void 0 ? void 0 : carouselNext.classList.add('blm-invisible'); - } else { - carouselNext === null || carouselNext === void 0 ? void 0 : carouselNext.classList.remove('blm-invisible'); - } - }; - const moveRight = () => { - eachItemWidth = eachItemWidth + movePer; - if (products.length === 1) { - eachItemWidth = 0; - } - // eslint-disable-next-line functional/no-loop-statement - for (const product of products) { - if (eachItemWidth > maxMove) { - eachItemWidth = eachItemWidth - movePer; - } - product.style.left = `-${eachItemWidth}px`; - } - adjustArrowVisibilities(); - }; - const moveLeft = () => { - eachItemWidth = eachItemWidth - movePer; - if (eachItemWidth <= 0) { - eachItemWidth = 0; - } - // eslint-disable-next-line functional/no-loop-statement - for (const product of products) { - if (productPage > 1) product.style.left = `-${eachItemWidth}px`; - } - adjustArrowVisibilities(); - }; - // Apply listeners in re-entrant fashion - if (carouselPrevious !== null && carouselNext !== null) { - const old = carouselListeners.get(widgetElement); - if (old) { - old.left[0].removeEventListener('click', old.left[1]); - old.right[0].removeEventListener('click', old.right[1]); - } - carouselListeners.set(widgetElement, { - left: [carouselPrevious, moveLeft], - right: [carouselNext, moveRight] - }); - carouselPrevious.addEventListener('click', moveLeft); - carouselNext.addEventListener('click', moveRight); - } - } - - debounce_1(event => { - var _a; - const inputValue = (((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) || '').trim(); - document.querySelectorAll('.blm-dynamic-filter').forEach(facetBox => { - let displayedItems = 0; - facetBox.querySelectorAll('.blm-product-search-filter-item').forEach(facetItem => { - var _a; - const label = ((_a = facetItem.querySelector('label')) === null || _a === void 0 ? void 0 : _a.textContent) || ''; - const shouldDisplay = !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()); - const displayStyle = shouldDisplay ? 'block' : 'none'; - displayedItems += shouldDisplay ? 1 : 0; - facetItem.style.display = displayStyle; - }); - facetBox.style.display = displayedItems ? 'block' : 'none'; - }); - document.querySelectorAll('.blm-product-search-load-more').forEach(loadMoreLink => { - loadMoreLink.style.display = 'none'; - }); - const groupsELement = getLoadMoreFacetGroupsElement(); - if (!groupsELement) return; - groupsELement.style.display = 'none'; - if (!inputValue) { - resetFacetGroups(); - } - }, 500); - - Debug('br:search'); - function buildDefaultSearchRequestState(options) { - const { - isCategoryPage - } = options; - return { - request_id: 0, - price_range_max_value: 0, - price_range_min_value: 0, - is_first_request: true, - is_category_page: isCategoryPage, - category_to_load: '', - pollIntervalId: void 0, - currentElement: null - }; - } - /** - * Attempts to get the search request state from the existing module - */ - function getCurrentSearchRequestState() { - var _a, _b, _c; - return ((_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.getCurrentSearchRequestState()) || buildDefaultSearchRequestState({ - isCategoryPage: false - }); - } - - const recommendationsModule = buildRecommendationsModule(); - window.BloomreachModules = Object.assign(Object.assign({}, globalBloomreachModules), { - pathwaysRecommendations: recommendationsModule - }); - recommendationsModule.load().catch(console.error); - -})(); +var t=r,n=b,i=v,o=!1,s=y,a="locals",c=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],l=c.concat("cache"),u=/^\uFEFF/,d=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/;function p(n,i){var r;if(i.some((function(i){return r=e.resolveInclude(n,i,!0),t.existsSync(r)})))return r}function m(t,n){var i,r=t.filename,o=arguments.length>1;if(t.cache){if(!r)throw new Error("cache option requires a filename");if(i=e.cache.get(r))return i;o||(n=f(r).toString().replace(u,""))}else if(!o){if(!r)throw new Error("Internal EJS error: no file name or template provided");n=f(r).toString().replace(u,"")}return i=e.compile(n,t),t.cache&&e.cache.set(r,i),i}function f(t){return e.fileLoader(t)}function h(n,r){var o=i.shallowCopy(i.createNullProtoObjWherePossible(),r);if(o.filename=function(n,i){var r,o,s=i.views,a=/^[A-Za-z]+:\\|^\//.exec(n);if(a&&a.length)n=n.replace(/^\/*/,""),r=Array.isArray(i.root)?p(n,i.root):e.resolveInclude(n,i.root||"/",!0);else if(i.filename&&(o=e.resolveInclude(n,i.filename),t.existsSync(o)&&(r=o)),!r&&Array.isArray(s)&&(r=p(n,s)),!r&&"function"!=typeof i.includer)throw new Error('Could not find the include file "'+i.escapeFunction(n)+'"');return r}(n,o),"function"==typeof r.includer){var s=r.includer(n,o.filename);if(s&&(s.filename&&(o.filename=s.filename),s.template))return m(o,s.template)}return m(o)}function g(e,t,n,i,r){var o=t.split("\n"),s=Math.max(i-3,0),a=Math.min(o.length,i+3),c=r(n),l=o.slice(s,a).map((function(e,t){var n=t+s+1;return(n==i?" >> ":" ")+n+"| "+e})).join("\n");throw e.path=c,e.message=(c||"ejs")+":"+i+"\n"+l+"\n\n"+e.message,e}function w(e){return e.replace(/;(\s*$)/,"$1")}function _(t,n){var r=i.hasOwnOnlyObject(n),o=i.createNullProtoObjWherePossible();this.templateText=t,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",o.client=r.client||!1,o.escapeFunction=r.escape||r.escapeFunction||i.escapeXML,o.compileDebug=!1!==r.compileDebug,o.debug=!!r.debug,o.filename=r.filename,o.openDelimiter=r.openDelimiter||e.openDelimiter||"<",o.closeDelimiter=r.closeDelimiter||e.closeDelimiter||">",o.delimiter=r.delimiter||e.delimiter||"%",o.strict=r.strict||!1,o.context=r.context,o.cache=r.cache||!1,o.rmWhitespace=r.rmWhitespace,o.root=r.root,o.includer=r.includer,o.outputFunctionName=r.outputFunctionName,o.localsName=r.localsName||e.localsName||a,o.views=r.views,o.async=r.async,o.destructuredLocals=r.destructuredLocals,o.legacyInclude=void 0===r.legacyInclude||!!r.legacyInclude,o.strict?o._with=!1:o._with=void 0===r._with||r._with,this.opts=o,this.regex=this.createRegex()}e.cache=i.cache,e.fileLoader=t.readFileSync,e.localsName=a,e.promiseImpl=new Function("return this;")().Promise,e.resolveInclude=function(e,t,i){var r=n.dirname,o=n.extname,s=(0,n.resolve)(i?t:r(t),e);return o(e)||(s+=".ejs"),s},e.compile=function(e,t){return t&&t.scope&&(o||(console.warn("`scope` option is deprecated and will be removed in EJS 3"),o=!0),t.context||(t.context=t.scope),delete t.scope),new _(e,t).compile()},e.render=function(e,t,n){var r=t||i.createNullProtoObjWherePossible(),o=n||i.createNullProtoObjWherePossible();return 2==arguments.length&&i.shallowCopyFromList(o,r,c),m(o,e)(r)},e.renderFile=function(){var t,n,r,o=Array.prototype.slice.call(arguments),s=o.shift(),a={filename:s};return"function"==typeof arguments[arguments.length-1]&&(t=o.pop()),o.length?(n=o.shift(),o.length?i.shallowCopy(a,o.pop()):(n.settings&&(n.settings.views&&(a.views=n.settings.views),n.settings["view cache"]&&(a.cache=!0),(r=n.settings["view options"])&&i.shallowCopy(a,r)),i.shallowCopyFromList(a,n,l)),a.filename=s):n=i.createNullProtoObjWherePossible(),function(t,n,i){var r;if(!i){if("function"==typeof e.promiseImpl)return new e.promiseImpl((function(e,i){try{e(r=m(t)(n))}catch(e){i(e)}}));throw new Error("Please provide a callback function")}try{r=m(t)(n)}catch(e){return i(e)}i(null,r)}(a,n,t)},e.Template=_,e.clearCache=function(){e.cache.reset()},_.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},_.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=i.escapeRegExpChars(this.opts.delimiter),n=i.escapeRegExpChars(this.opts.openDelimiter),r=i.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,r),new RegExp(e)},compile:function(){var e,t,r,o=this.opts,s="",a="",c=o.escapeFunction,l=o.filename?JSON.stringify(o.filename):"undefined";if(!this.source){if(this.generateSource(),s+=' var __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n',o.outputFunctionName){if(!d.test(o.outputFunctionName))throw new Error("outputFunctionName is not a valid JS identifier.");s+=" var "+o.outputFunctionName+" = __append;\n"}if(o.localsName&&!d.test(o.localsName))throw new Error("localsName is not a valid JS identifier.");if(o.destructuredLocals&&o.destructuredLocals.length){for(var u=" var __locals = ("+o.localsName+" || {}),\n",p=0;p0&&(u+=",\n "),u+=m+" = __locals."+m}s+=u+";\n"}!1!==o._with&&(s+=" with ("+o.localsName+" || {}) {\n",a+=" }\n"),a+=" return __output;\n",this.source=s+this.source+a}e=o.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+l+";\ntry {\n"+this.source+"} catch (e) {\n rethrow(e, __lines, __filename, __line, escapeFn);\n}\n":this.source,o.client&&(e="escapeFn = escapeFn || "+c.toString()+";\n"+e,o.compileDebug&&(e="rethrow = rethrow || "+g.toString()+";\n"+e)),o.strict&&(e='"use strict";\n'+e),o.debug&&console.log(e),o.compileDebug&&o.filename&&(e=e+"\n//# sourceURL="+l+"\n");try{if(o.async)try{r=new Function("return (async function(){}).constructor;")()}catch(e){throw e instanceof SyntaxError?new Error("This environment does not support async/await"):e}else r=Function;t=new r(o.localsName+", escapeFn, include, rethrow",e)}catch(e){throw e instanceof SyntaxError&&(o.filename&&(e.message+=" in "+o.filename),e.message+=" while compiling ejs\n\n",e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n",e.message+="https://github.com/RyanZim/EJS-Lint",o.async||(e.message+="\n",e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}var f=o.client?t:function(e){return t.apply(o.context,[e||i.createNullProtoObjWherePossible(),c,function(t,n){var r=i.shallowCopy(i.createNullProtoObjWherePossible(),e);return n&&(r=i.shallowCopy(r,n)),h(t,o)(r)},g])};if(o.filename&&"function"==typeof Object.defineProperty){var w=o.filename,_=n.basename(w,n.extname(w));try{Object.defineProperty(f,"name",{value:_,writable:!1,enumerable:!1,configurable:!0})}catch(e){}}return f},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")),this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var e=this,t=this.parseTemplateText(),n=this.opts.delimiter,i=this.opts.openDelimiter,r=this.opts.closeDelimiter;t&&t.length&&t.forEach((function(o,s){var a;if(0===o.indexOf(i+n)&&0!==o.indexOf(i+n+n)&&(a=t[s+2])!=n+r&&a!="-"+n+r&&a!="_"+n+r)throw new Error('Could not find matching close tag for "'+o+'".');e.scanLine(o)}))},parseTemplateText:function(){for(var e,t=this.templateText,n=this.regex,i=n.exec(t),r=[];i;)0!==(e=i.index)&&(r.push(t.substring(0,e)),t=t.slice(e)),r.push(i[0]),t=t.slice(i[0].length),i=n.exec(t);return t&&r.push(t),r},_addOutput:function(e){if(this.truncate&&(e=e.replace(/^(?:\r\n|\r|\n)/,""),this.truncate=!1),!e)return e;e=(e=(e=(e=e.replace(/\\/g,"\\\\")).replace(/\n/g,"\\n")).replace(/\r/g,"\\r")).replace(/"/g,'\\"'),this.source+=' ; __append("'+e+'")\n'},scanLine:function(e){var t,n=this.opts.delimiter,i=this.opts.openDelimiter,r=this.opts.closeDelimiter;switch(t=e.split("\n").length-1,e){case i+n:case i+n+"_":this.mode=_.modes.EVAL;break;case i+n+"=":this.mode=_.modes.ESCAPED;break;case i+n+"-":this.mode=_.modes.RAW;break;case i+n+"#":this.mode=_.modes.COMMENT;break;case i+n+n:this.mode=_.modes.LITERAL,this.source+=' ; __append("'+e.replace(i+n+n,i+n)+'")\n';break;case n+n+r:this.mode=_.modes.LITERAL,this.source+=' ; __append("'+e.replace(n+n+r,n+r)+'")\n';break;case n+r:case"-"+n+r:case"_"+n+r:this.mode==_.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=0===e.indexOf("-")||0===e.indexOf("_");break;default:if(this.mode){switch(this.mode){case _.modes.EVAL:case _.modes.ESCAPED:case _.modes.RAW:e.lastIndexOf("//")>e.lastIndexOf("\n")&&(e+="\n")}switch(this.mode){case _.modes.EVAL:this.source+=" ; "+e+"\n";break;case _.modes.ESCAPED:this.source+=" ; __append(escapeFn("+w(e)+"))\n";break;case _.modes.RAW:this.source+=" ; __append("+w(e)+")\n";break;case _.modes.COMMENT:break;case _.modes.LITERAL:this._addOutput(e)}}else this._addOutput(e)}this.opts.compileDebug&&t&&(this.currentLine+=t,this.source+=" ; __line = "+this.currentLine+"\n")}},e.escapeXML=i.escapeXML,e.__express=e.renderFile,e.VERSION=s,e.name="ejs","undefined"!=typeof window&&(window.ejs=e)}(i);const O="cdp_segments",j="customer_profile",x="$",E=16,L="q",S=0;function T(){const e=`${O}=`;return(document.cookie.split("; ").find((t=>t.startsWith(e)))||"").replace(e,"")}async function k(e,t){const n=await fetch(e,t);return await n.json()}const A={method:"GET",headers:{"Content-Type":"application/json"}};function C(){const e=document.cookie.split("; ").find((e=>e.startsWith("_br_uid_2=")));return e?e.replace("_br_uid_2=",""):"uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55"}const R=(e,t="$",n=!0)=>`${n?t:""}${(e/100).toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2})}${n?"":` ${t}`}`;const M="https://pathways.dxpapi.com/api/v2/widgets/",F=["_br_uid_2","fq","sort"],N="pid,price,sale_price,title,thumb_image,url";function P(e){const t=Object.assign({},e),n=`${(null==t?void 0:t.endpoint)||M}${t.type}/${t.id}`;return(null==t?void 0:t.endpoint)&&(null==t||delete t.endpoint),(null==t?void 0:t.fields)||(t.fields=N),`${n}${i=t,`?${Object.keys(i).reduce(((e,t)=>[...e,`${t}=${F.includes(t)?i[t]:encodeURIComponent(i[t])}`]),[]).join("&")}`}`;var i}var q,D='
\n <% if (products.length > config.number_of_items_to_show) { %>\n \n \n \n \n \n \n <% } %>\n\n
\n <% products.forEach(function(product) { %>\n
\n
\n
\n \n \n \n
\n
\n \n <% if (product.price && product.sale_price) { %>\n

\n <% if (config.format_money) { %>\n <%= config.format_money(product.sale_price.toFixed(2) * 100) %> <%= config.format_money(product.price.toFixed(2) * 100) %>\n <% } else { %>\n <%= config.default_currency %><%= product.sale_price.toFixed(2) %> <%= config.default_currency %><%= product.price.toFixed(2) %>\n <% } %>\n

\n <% } else { %>\n

\n <% if (config.format_money) { %>\n <%= config.format_money(product.price.toFixed(2) * 100) %>\n <% } else { %>\n <%= config.default_currency %><%= product.price.toFixed(2) %>\n <% } %>\n

\n <% } %>\n
\n
\n
\n <% }); %>\n
\n\n <% if (products.length > config.number_of_items_to_show) { %>\n \n \n \n \n \n \n <% } %>\n
\n';function I(){const e=function(){var e;const t=null===(e=null===window||void 0===window?void 0:window.bloomreachConnector)||void 0===e?void 0:e.config;return Object.assign({default_search_parameter:L,url:window.location.href,ref_url:window.location.href,tracking_cookie:C(),format_money:e=>R(e,window.bloomreachDefaultCurrency||x),default_currency:window.bloomreachDefaultCurrency||x},t)}();return Object.assign(Object.assign({},e),{widget:Object.assign({endpoint:"",fields:"",template:D},e.widget)})}!function(e){e.small="480px",e.medium="680px",e.large="750px",e.xlarge="875px",e.xxlarge="1000px",e.xxxlarge="1200px"}(q||(q={}));const $=window.matchMedia(`(max-width: ${q.medium})`),W=window.matchMedia(`(min-width:${q.medium}) and (max-width: ${q.xlarge})`);var z="object"==typeof t&&t&&t.Object===Object&&t,B="object"==typeof self&&self&&self.Object===Object&&self,U=(z||B||Function("return this")()).Symbol;U&&U.toStringTag;function J(){V().widgets.forEach((e=>{const t=e.node,n=t.querySelector(".blm-recommendation-widget-content"),{id:i="",type:r="",rid:o=""}=n.dataset;t.querySelectorAll("[data-blm-widget-add-to-cart]").forEach((e=>{var n;const{blmWidgetAddToCartSku:s="",blmWidgetAddToCartProdId:a=""}=e.dataset;e.getAttribute("hasListener")||(e.addEventListener("click",function(e){const t=Object.assign(Object.assign({wrid:e.widgetRid,wid:e.widgetId,wty:e.widgetType,item_id:e.blmWidgetAddToCartProdId},e.query?{wq:e.query}:{}),{sku:e.blmWidgetAddToCartSku});return()=>{var e,n;null===(n=null===(e=window.BrTrk||{})||void 0===e?void 0:e.getTracker())||void 0===n||n.logEvent("cart","widget-add",t)}}({widgetRid:o,widgetId:i,widgetType:r,blmWidgetAddToCartSku:s,blmWidgetAddToCartProdId:a,query:null===(n=null==t?void 0:t.dataset)||void 0===n?void 0:n.query})),e.setAttribute("hasListener","true"))}))}))}function H(){V().widgets.forEach((e=>{const t=e.node,n=t.querySelector(".blm-recommendation-widget-content"),{id:i="",type:r="",rid:o=""}=n.dataset;t.querySelectorAll(".blm-widget-link").forEach((e=>{var n;const s=function(e,t){var n;let i=e;for(;i&&i.parentNode;)if(i=i.parentNode,i&&(null===(n=i.classList)||void 0===n?void 0:n.contains(t)))return i;return null}(e,"blm-recommendation__product"),a=s.dataset.id||"";var c;e.getAttribute("hasListener")||(e.addEventListener("click",(c={widgetRid:o,widgetId:i,widgetType:r,productId:a,query:null===(n=null==t?void 0:t.dataset)||void 0===n?void 0:n.query},()=>{var e,t;const n=Object.assign({wrid:c.widgetRid,wid:c.widgetId,wty:c.widgetType,item_id:c.productId},c.query?{wq:c.query}:{});null===(t=null===(e=window.BrTrk||{})||void 0===e?void 0:e.getTracker())||void 0===t||t.logEvent("widget","widget-click",n,!0)})),e.setAttribute("hasListener","true"))}))}))}function V(){return window.BloomreachModules.pathwaysRecommendations.getCurrentRecommendationsUiState()}function X(){return window.BloomreachModules.pathwaysRecommendations.getCurrentRecommendationsRequestState()}U&&U.toStringTag;const Z=function(){let e={request_id:0},t={widgets:[]};return{setCurrentRecommendationsRequestState:t=>{e=t},getCurrentRecommendationsRequestState:()=>e,setCurrentRecommendationsUiState:e=>{t=e},getCurrentRecommendationsUiState:()=>t,load:async()=>{var e;e={request_id:Math.floor(1e12+9e12*Math.random())},window.BloomreachModules.pathwaysRecommendations.setCurrentRecommendationsRequestState(Object.assign(Object.assign({},X()),e)),function(){const e=T();if(e){(window.br_data||{})[j]=e}}(),function(){const e=[];document.querySelectorAll(".blm-recommendations-widget").forEach((t=>{e.push({loaded:!1,node:t})})),function(e){window.BloomreachModules.pathwaysRecommendations.setCurrentRecommendationsUiState(Object.assign(Object.assign({},V()),e))}({widgets:e})}();const t=V().widgets.reduce(((e,t)=>[...e,new Promise((e=>{const n=function(e){var t;const n=I(),i=new URLSearchParams(window.location.search),r=X(),o=e.dataset,s=Object.assign(Object.assign(Object.assign({},(null===(t=null==n?void 0:n.widget)||void 0===t?void 0:t.endpoint)?{endpoint:n.widget.endpoint}:{}),{account_id:n.account_id,domain_key:n.domain_key,request_id:r.request_id,_br_uid_2:n.tracking_cookie,ref_url:n.ref_url,url:n.url,rows:Number(o.numberOfItemsToFetch)||E,start:S}),o);for(const[e,t]of i.entries())Object.keys(s).includes(e)||(s[e]=t);const a=T();a&&(s.brSeg=`seg:${a}`,s.segment=`customer_profile:${a}`,s.cdp_segments=a);switch(o.type){case"keyword":return s.query=o.query,s;case"category":return s.cat_id=o.categoryId,s;case"item":return s.item_ids=o.itemIds,s;case"personalized":return s.user_id=o.userId,s;case"global":return s;default:return new Error(`Invalid widget type: "${o.type}"`)}}(t.node);let i;i=function(e){return"query"in e}(n)?async function(e){return k(P(Object.assign(Object.assign({},e),{type:"keyword"})),A)}(n):function(e){return"cat_id"in e}(n)?async function(e){return k(P(Object.assign(Object.assign({},e),{type:"category"})),A)}(n):function(e){return"item_ids"in e}(n)?async function(e){return k(P(Object.assign(Object.assign({},e),{type:"item"})),A)}(n):function(e){return"user_id"in e}(n)?async function(e){return k(P(Object.assign(Object.assign({},e),{type:"personalized"})),A)}(n):async function(e){return k(P(Object.assign(Object.assign({},e),{type:"global"})),A)}(n),e(i)})).then((e=>{var n;const r=t.node,o=I(),s=(a=e,{config:I(),products:[...a.response.docs?a.response.docs.map((e=>Object.assign(Object.assign({},e),{id:e.pid,image:e.thumb_image,title:e.title,link:e.url,sale_price:e.sale_price,price:e.price}))):[]],widgetMetadata:a.metadata.widget});var a;const c=r.dataset;return s.config.number_of_items_to_show=Number(c.numberOfItemsToShow),r.innerHTML=i.render((null===(n=o.widget)||void 0===n?void 0:n.template)||"",s),function(e){var t,n;const i=e.querySelector(".blm-recommendation-widget-content"),{id:r="",type:o="",rid:s=""}=i.dataset,a=Object.assign({wrid:s,wid:r,wty:o},e.dataset.query?{wq:e.dataset.query}:{});null===(n=null===(t=window.BrTrk||{})||void 0===t?void 0:t.getTracker())||void 0===n||n.logEvent("widget","widget-view",a,!0)}(r),r.classList.add("blm-widget-loaded"),{widgetElement:r,templateData:s}}))]),[]),n=await Promise.all(t).catch(console.error);J(),H(),(n||[]).forEach((e=>{!function(e,t){const n=e.querySelector(".blm-carousel-previous"),i=e.querySelector(".blm-carousel-next"),r=e.querySelectorAll(".blm-recommendation__product"),o=Number($.matches?1:W.matches?2:t.config.number_of_items_to_show),s=Math.ceil(r.length/o);let a=0;if(r.length){const t=e.querySelector(".blm-recommendation__products"),n=window.getComputedStyle(t);a=Number(n.width.replace("px",""))/o}let c=0;const l=a,u=(r.length-o)*a,d=()=>{var e,t,o,s;"0px"===(null===(t=null===(e=null==r?void 0:r[0])||void 0===e?void 0:e.style)||void 0===t?void 0:t.left)?null==n||n.classList.add("blm-invisible"):null==n||n.classList.remove("blm-invisible"),(null===(s=null===(o=null==r?void 0:r[0])||void 0===o?void 0:o.style)||void 0===s?void 0:s.left)===`-${u}px`?null==i||i.classList.add("blm-invisible"):null==i||i.classList.remove("blm-invisible")},p=()=>{c+=l,1===r.length&&(c=0);for(const e of r)c>u&&(c-=l),e.style.left=`-${c}px`;d()},m=()=>{c-=l,c<=0&&(c=0);for(const e of r)s>1&&(e.style.left=`-${c}px`);d()};null!==n&&null!==i&&(n.addEventListener("click",(()=>{m()})),i.addEventListener("click",(()=>{p()})))}(e.widgetElement,e.templateData)}))}}}();window.BloomreachModules=Object.assign(Object.assign({},e),{pathwaysRecommendations:Z}),Z.load().catch(console.error)}(); //# sourceMappingURL=recommendations.js.map diff --git a/view/frontend/web/js/search.js b/view/frontend/web/js/search.js index ee06ec6..f1e8ace 100644 --- a/view/frontend/web/js/search.js +++ b/view/frontend/web/js/search.js @@ -1,4066 +1,10 @@ -(function () { - 'use strict'; - - const AUTOSUGGEST_MINIMUM_QUERY_LENGTH = 2; - const AUTOSUGGEST_TYPED_QUERY_TEMPLATE = '<%= query %>'; - const COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS = 'cdp_segments'; - const COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE = 'customer_profile'; - const DEFAULT_CURRENCY = '$'; - const DEFAULT_PAGE_SIZE = 16; - const DEFAULT_SEARCH_PARAMETER = 'q'; - const DEFAULT_SORTING_OPTIONS = [{ - label: 'Relevance', - value: '' - }, { - label: 'Price (low - high)', - value: 'price+asc' - }, { - label: 'Price (high - low)', - value: 'price+desc' - }, { - label: 'Name (A - Z)', - value: 'title+asc' - }, { - label: 'Name (Z - A)', - value: 'title+desc' - }]; - const DEFAULT_START = 0; - const DEFAULT_WIDGETS_TO_DISPLAY = 4; - const FIELD_NAME_PRICE = 'price'; - const MAX_COLOR_SWATCHES = 4; - const MAX_PAGINATION_NUMBER_BEFORE_CURRENT = 2; - const MAX_PAGINATION_NUMBER_AFTER_CURRENT = 2; - const NUMBER_OF_AUTOSUGGEST_COLLECTIONS = 8; - const NUMBER_OF_AUTOSUGGEST_PRODUCTS = 8; - const NUMBER_OF_AUTOSUGGEST_TERMS = 4; - const NUMBER_OF_FACET_GROUPS = 5; - const NUMBER_OF_FACET_VALUES = 6; - const PARAMETER_NAME_FACETS = 'fq'; - const PARAMETER_NAME_FILTERS_PANEL = 'filterpanel'; - const PARAMETER_NAME_GROUPBY = 'groupby'; - const PARAMETER_NAME_PAGE = 'page'; - const PARAMETER_NAME_SIZE = 'size'; - const PARAMETER_NAME_SORT = 'sort'; - const REQUEST_TYPE_SEARCH = 'search'; - const REQUEST_TYPE_SUGGEST = 'suggest'; - const SEARCH_TYPE_CATEGORY = 'category'; - const SEARCH_TYPE_KEYWORD = 'keyword'; - const SELECTOR_AUTOSUGGEST_INPUT = '.search__input'; - const SELECTOR_SEARCH_RESULTS_CONTAINER = '.main-content'; - /** - * This is the attribute name used to flag an element as an add to cart event - * generator, such as a butto or link. - */ - const ADD_TO_CART_ATTRIBUTE_NAME = 'data-blm-add-to-cart'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the sku value sent in the - * pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_SKU = 'data-blm-add-to-cart-sku'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to populate the prod_id value sent in - * the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_PROD_ID = 'data-blm-add-to-cart-prod-id'; - /** - * Attribute that should be applied to the element that has - * ADD_TO_CART_ATTRIBUTE_NAME added to it to prevent emitting the pixel event. - */ - const ADD_TO_CART_ATTRIBUTE_DISABLE = 'data-blm-add-to-cart-disable'; - const QUICKVIEW_ATTRIBUTE_NAME = 'data-blm-quickview'; - const QUICKVIEW_ATTRIBUTE_SKU = 'data-blm-quickview-sku'; - const QUICKVIEW_ATTRIBUTE_PROD_ID = 'data-blm-quickview-prod-id'; - const QUICKVIEW_ATTRIBUTE_PROD_NAME = 'data-blm-quickview-prod-name'; - - var constants = /*#__PURE__*/Object.freeze({ - __proto__: null, - AUTOSUGGEST_MINIMUM_QUERY_LENGTH: AUTOSUGGEST_MINIMUM_QUERY_LENGTH, - AUTOSUGGEST_TYPED_QUERY_TEMPLATE: AUTOSUGGEST_TYPED_QUERY_TEMPLATE, - COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS: COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS, - COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE: COOKIE_NAME_SEGMENTATION_CUSTOMER_PROFILE, - DEFAULT_CURRENCY: DEFAULT_CURRENCY, - DEFAULT_PAGE_SIZE: DEFAULT_PAGE_SIZE, - DEFAULT_SEARCH_PARAMETER: DEFAULT_SEARCH_PARAMETER, - DEFAULT_SORTING_OPTIONS: DEFAULT_SORTING_OPTIONS, - DEFAULT_START: DEFAULT_START, - DEFAULT_WIDGETS_TO_DISPLAY: DEFAULT_WIDGETS_TO_DISPLAY, - FIELD_NAME_PRICE: FIELD_NAME_PRICE, - MAX_COLOR_SWATCHES: MAX_COLOR_SWATCHES, - MAX_PAGINATION_NUMBER_BEFORE_CURRENT: MAX_PAGINATION_NUMBER_BEFORE_CURRENT, - MAX_PAGINATION_NUMBER_AFTER_CURRENT: MAX_PAGINATION_NUMBER_AFTER_CURRENT, - NUMBER_OF_AUTOSUGGEST_COLLECTIONS: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - NUMBER_OF_AUTOSUGGEST_PRODUCTS: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - NUMBER_OF_AUTOSUGGEST_TERMS: NUMBER_OF_AUTOSUGGEST_TERMS, - NUMBER_OF_FACET_GROUPS: NUMBER_OF_FACET_GROUPS, - NUMBER_OF_FACET_VALUES: NUMBER_OF_FACET_VALUES, - PARAMETER_NAME_FACETS: PARAMETER_NAME_FACETS, - PARAMETER_NAME_FILTERS_PANEL: PARAMETER_NAME_FILTERS_PANEL, - PARAMETER_NAME_GROUPBY: PARAMETER_NAME_GROUPBY, - PARAMETER_NAME_PAGE: PARAMETER_NAME_PAGE, - PARAMETER_NAME_SIZE: PARAMETER_NAME_SIZE, - PARAMETER_NAME_SORT: PARAMETER_NAME_SORT, - REQUEST_TYPE_SEARCH: REQUEST_TYPE_SEARCH, - REQUEST_TYPE_SUGGEST: REQUEST_TYPE_SUGGEST, - SEARCH_TYPE_CATEGORY: SEARCH_TYPE_CATEGORY, - SEARCH_TYPE_KEYWORD: SEARCH_TYPE_KEYWORD, - SELECTOR_AUTOSUGGEST_INPUT: SELECTOR_AUTOSUGGEST_INPUT, - SELECTOR_SEARCH_RESULTS_CONTAINER: SELECTOR_SEARCH_RESULTS_CONTAINER, - ADD_TO_CART_ATTRIBUTE_NAME: ADD_TO_CART_ATTRIBUTE_NAME, - ADD_TO_CART_ATTRIBUTE_SKU: ADD_TO_CART_ATTRIBUTE_SKU, - ADD_TO_CART_ATTRIBUTE_PROD_ID: ADD_TO_CART_ATTRIBUTE_PROD_ID, - ADD_TO_CART_ATTRIBUTE_DISABLE: ADD_TO_CART_ATTRIBUTE_DISABLE, - QUICKVIEW_ATTRIBUTE_NAME: QUICKVIEW_ATTRIBUTE_NAME, - QUICKVIEW_ATTRIBUTE_SKU: QUICKVIEW_ATTRIBUTE_SKU, - QUICKVIEW_ATTRIBUTE_PROD_ID: QUICKVIEW_ATTRIBUTE_PROD_ID, - QUICKVIEW_ATTRIBUTE_PROD_NAME: QUICKVIEW_ATTRIBUTE_PROD_NAME - }); - - const globalBloomreachModules = Object.assign(Object.assign({}, window.BloomreachModules ? window.BloomreachModules : {}), { - version: '4.0.0', - constants - }); - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getAugmentedNamespace(n) { - var f = n.default; - if (typeof f == "function") { - var a = function () { - return f.apply(this, arguments); - }; - a.prototype = f.prototype; - } else a = {}; - Object.defineProperty(a, '__esModule', {value: true}); - Object.keys(n).forEach(function (k) { - var d = Object.getOwnPropertyDescriptor(n, k); - Object.defineProperty(a, k, d.get ? d : { - enumerable: true, - get: function () { - return n[k]; - } - }); - }); - return a; - } - - var ejs = {}; - - var _polyfillNode_fs = {}; - - var _polyfillNode_fs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _polyfillNode_fs - }); - - var require$$0 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_fs$1); - - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // resolves . and .. elements in a path array with directory names there - // must be no slashes, empty elements, or device names (c:\) in the array - // (so also no leading and trailing slashes - it does not distinguish - // relative and absolute paths) - function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; - } - - // Split a filename into [root, dir, basename, ext], unix version - // 'root' is just a slash, or nothing. - var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); - }; - - // path.resolve([from ...], to) - // posix version - function resolve() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : '/'; - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - } - // path.normalize(path) - // posix version - function normalize(path) { - var isPathAbsolute = isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isPathAbsolute).join('/'); - - if (!path && !isPathAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isPathAbsolute ? '/' : '') + path; - } - // posix version - function isAbsolute(path) { - return path.charAt(0) === '/'; - } - - // posix version - function join() { - var paths = Array.prototype.slice.call(arguments, 0); - return normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); - } - - - // path.relative(from, to) - // posix version - function relative(from, to) { - from = resolve(from).substr(1); - to = resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - } - - var sep = '/'; - var delimiter = ':'; - - function dirname(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; - } - - function basename(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; - } - - - function extname(path) { - return splitPath(path)[3]; - } - var _polyfillNode_path = { - extname: extname, - basename: basename, - dirname: dirname, - sep: sep, - delimiter: delimiter, - relative: relative, - join: join, - isAbsolute: isAbsolute, - normalize: normalize, - resolve: resolve - }; - function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; - } - - // String.prototype.substr - negative index don't work in IE8 - var substr = 'ab'.substr(-1) === 'b' ? - function (str, start, len) { return str.substr(start, len) } : - function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } - ; - - var _polyfillNode_path$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - resolve: resolve, - normalize: normalize, - isAbsolute: isAbsolute, - join: join, - relative: relative, - sep: sep, - delimiter: delimiter, - dirname: dirname, - basename: basename, - extname: extname, - 'default': _polyfillNode_path - }); - - var require$$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_path$1); - - var utils = {}; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - var regExpChars = /[|\\{}()[\]^$+*?.]/g; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); }; - - /** - * Escape characters reserved in regular expressions. - * - * If `string` is `undefined` or `null`, the empty string is returned. - * - * @param {String} string Input string - * @return {String} Escaped string - * @static - * @private - */ - exports.escapeRegExpChars = function (string) { - // istanbul ignore if - if (!string) { - return ''; - } - return String(string).replace(regExpChars, '\\$&'); - }; - - var _ENCODE_HTML_RULES = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - var _MATCH_HTML = /[&<>'"]/g; - - function encode_char(c) { - return _ENCODE_HTML_RULES[c] || c; - } - - /** - * Stringified version of constants used by {@link module:utils.escapeXML}. - * - * It is used in the process of generating {@link ClientFunction}s. - * - * @readonly - * @type {String} - */ - - var escapeFuncStr = - 'var _ENCODE_HTML_RULES = {\n' - + ' "&": "&"\n' - + ' , "<": "<"\n' - + ' , ">": ">"\n' - + ' , \'"\': """\n' - + ' , "\'": "'"\n' - + ' }\n' - + ' , _MATCH_HTML = /[&<>\'"]/g;\n' - + 'function encode_char(c) {\n' - + ' return _ENCODE_HTML_RULES[c] || c;\n' - + '};\n'; - - /** - * Escape characters reserved in XML. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @implements {EscapeCallback} - * @param {String} markup Input string - * @return {String} Escaped string - * @static - * @private - */ - - exports.escapeXML = function (markup) { - return markup == undefined - ? '' - : String(markup) - .replace(_MATCH_HTML, encode_char); - }; - exports.escapeXML.toString = function () { - return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr; - }; - - /** - * Naive copy of properties from one object to another. - * Does not recurse into non-scalar properties - * Does not check to see if the property has a value before copying - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopy = function (to, from) { - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var p in from) { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - return to; - }; - - /** - * Naive copy of a list of key names, from one object to another. - * Only copies property if it is actually defined - * Does not recurse into non-scalar properties - * - * @param {Object} to Destination object - * @param {Object} from Source object - * @param {Array} list List of properties to copy - * @return {Object} Destination object - * @static - * @private - */ - exports.shallowCopyFromList = function (to, from, list) { - list = list || []; - from = from || {}; - if ((to !== null) && (to !== undefined)) { - for (var i = 0; i < list.length; i++) { - var p = list[i]; - if (typeof from[p] != 'undefined') { - if (!hasOwn(from, p)) { - continue; - } - if (p === '__proto__' || p === 'constructor') { - continue; - } - to[p] = from[p]; - } - } - } - return to; - }; - - /** - * Simple in-process cache implementation. Does not implement limits of any - * sort. - * - * @implements {Cache} - * @static - * @private - */ - exports.cache = { - _data: {}, - set: function (key, val) { - this._data[key] = val; - }, - get: function (key) { - return this._data[key]; - }, - remove: function (key) { - delete this._data[key]; - }, - reset: function () { - this._data = {}; - } - }; - - /** - * Transforms hyphen case variable into camel case. - * - * @param {String} string Hyphen case string - * @return {String} Camel case string - * @static - * @private - */ - exports.hyphenToCamel = function (str) { - return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); }); - }; - - /** - * Returns a null-prototype object in runtimes that support it - * - * @return {Object} Object, prototype will be set to null where possible - * @static - * @private - */ - exports.createNullProtoObjWherePossible = (function () { - if (typeof Object.create == 'function') { - return function () { - return Object.create(null); - }; - } - if (!({__proto__: null} instanceof Object)) { - return function () { - return {__proto__: null}; - }; - } - // Not possible, just pass through - return function () { - return {}; - }; - })(); - } (utils)); - - var name = "ejs"; - var description = "Embedded JavaScript templates"; - var keywords = [ - "template", - "engine", - "ejs" - ]; - var version = "3.1.8"; - var author = "Matthew Eernisse (http://fleegix.org)"; - var license = "Apache-2.0"; - var bin = { - ejs: "./bin/cli.js" - }; - var main = "./lib/ejs.js"; - var jsdelivr = "ejs.min.js"; - var unpkg = "ejs.min.js"; - var repository = { - type: "git", - url: "git://github.com/mde/ejs.git" - }; - var bugs = "https://github.com/mde/ejs/issues"; - var homepage = "https://github.com/mde/ejs"; - var dependencies = { - jake: "^10.8.5" - }; - var devDependencies = { - browserify: "^16.5.1", - eslint: "^6.8.0", - "git-directory-deploy": "^1.5.1", - jsdoc: "^3.6.7", - "lru-cache": "^4.0.1", - mocha: "^7.1.1", - "uglify-js": "^3.3.16" - }; - var engines = { - node: ">=0.10.0" - }; - var scripts = { - test: "mocha" - }; - var require$$3 = { - name: name, - description: description, - keywords: keywords, - version: version, - author: author, - license: license, - bin: bin, - main: main, - jsdelivr: jsdelivr, - unpkg: unpkg, - repository: repository, - bugs: bugs, - homepage: homepage, - dependencies: dependencies, - devDependencies: devDependencies, - engines: engines, - scripts: scripts - }; - - /* - * EJS Embedded JavaScript templates - * Copyright 2112 Matthew Eernisse (mde@fleegix.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - (function (exports) { - - /** +!function(){"use strict";const e=Object.assign(Object.assign({},window.BloomreachModules?window.BloomreachModules:{}),{version:"3.1.0"});var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(e){var t=e.default;if("function"==typeof t){var n=function(){return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach((function(t){var r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:function(){return e[t]}})})),n}var r={},i=n(Object.freeze({__proto__:null,default:{}}));function a(e,t){for(var n=0,r=e.length-1;r>=0;r--){var i=e[r];"."===i?e.splice(r,1):".."===i?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}var o=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,c=function(e){return o.exec(e).slice(1)};function s(){for(var e="",t=!1,n=arguments.length-1;n>=-1&&!t;n--){var r=n>=0?arguments[n]:"/";if("string"!=typeof r)throw new TypeError("Arguments to path.resolve must be strings");r&&(e=r+"/"+e,t="/"===r.charAt(0))}return(t?"/":"")+(e=a(g(e.split("/"),(function(e){return!!e})),!t).join("/"))||"."}function l(e){var t=u(e),n="/"===v(e,-1);return(e=a(g(e.split("/"),(function(e){return!!e})),!t).join("/"))||t||(e="."),e&&n&&(e+="/"),(t?"/":"")+e}function u(e){return"/"===e.charAt(0)}function d(){return l(g(Array.prototype.slice.call(arguments,0),(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))}function p(e,t){function n(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=s(e).substr(1),t=s(t).substr(1);for(var r=n(e.split("/")),i=n(t.split("/")),a=Math.min(r.length,i.length),o=a,c=0;c":">",'"':""","'":"'"},a=/[&<>'"]/g;function o(e){return i[e]||e}function c(){return Function.prototype.toString.call(this)+';\nvar _ENCODE_HTML_RULES = {\n "&": "&"\n , "<": "<"\n , ">": ">"\n , \'"\': """\n , "\'": "'"\n }\n , _MATCH_HTML = /[&<>\'"]/g;\nfunction encode_char(c) {\n return _ENCODE_HTML_RULES[c] || c;\n};\n'}e.escapeXML=function(e){return null==e?"":String(e).replace(a,o)};try{"function"==typeof Object.defineProperty?Object.defineProperty(e.escapeXML,"toString",{value:c}):e.escapeXML.toString=c}catch(e){console.warn("Unable to set escapeXML.toString (is the Function prototype frozen?)")}e.shallowCopy=function(e,t){if(t=t||{},null!=e)for(var n in t)r(t,n)&&"__proto__"!==n&&"constructor"!==n&&(e[n]=t[n]);return e},e.shallowCopyFromList=function(e,t,n){if(n=n||[],t=t||{},null!=e)for(var i=0;i * @author Tiancheng "Timothy" Gu * @project EJS * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0} */ - - /** - * EJS internal functions. - * - * Technically this "module" lies in the same file as {@link module:ejs}, for - * the sake of organization all the private functions re grouped into this - * module. - * - * @module ejs-internal - * @private - */ - - /** - * Embedded JavaScript templating engine. - * - * @module ejs - * @public - */ - - - var fs = require$$0; - var path = require$$1; - var utils$1 = utils; - - var scopeOptionWarned = false; - /** @type {string} */ - var _VERSION_STRING = require$$3.version; - var _DEFAULT_OPEN_DELIMITER = '<'; - var _DEFAULT_CLOSE_DELIMITER = '>'; - var _DEFAULT_DELIMITER = '%'; - var _DEFAULT_LOCALS_NAME = 'locals'; - var _NAME = 'ejs'; - var _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)'; - var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug', - 'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async']; - // We don't allow 'cache' option to be passed in the data obj for - // the normal `render` call, but this is where Express 2 & 3 put it - // so we make an exception for `renderFile` - var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache'); - var _BOM = /^\uFEFF/; - var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; - - /** - * EJS template function cache. This can be a LRU object from lru-cache NPM - * module. By default, it is {@link module:utils.cache}, a simple in-process - * cache that grows continuously. - * - * @type {Cache} - */ - - exports.cache = utils$1.cache; - - /** - * Custom file loader. Useful for template preprocessing or restricting access - * to a certain part of the filesystem. - * - * @type {fileLoader} - */ - - exports.fileLoader = fs.readFileSync; - - /** - * Name of the object containing the locals. - * - * This variable is overridden by {@link Options}`.localsName` if it is not - * `undefined`. - * - * @type {String} - * @public - */ - - exports.localsName = _DEFAULT_LOCALS_NAME; - - /** - * Promise implementation -- defaults to the native implementation if available - * This is mostly just for testability - * - * @type {PromiseConstructorLike} - * @public - */ - - exports.promiseImpl = (new Function('return this;'))().Promise; - - /** - * Get the path to the included file from the parent file path and the - * specified path. - * - * @param {String} name specified path - * @param {String} filename parent file path - * @param {Boolean} [isDir=false] whether the parent file path is a directory - * @return {String} - */ - exports.resolveInclude = function(name, filename, isDir) { - var dirname = path.dirname; - var extname = path.extname; - var resolve = path.resolve; - var includePath = resolve(isDir ? filename : dirname(filename), name); - var ext = extname(name); - if (!ext) { - includePath += '.ejs'; - } - return includePath; - }; - - /** - * Try to resolve file path on multiple directories - * - * @param {String} name specified path - * @param {Array} paths list of possible parent directory paths - * @return {String} - */ - function resolvePaths(name, paths) { - var filePath; - if (paths.some(function (v) { - filePath = exports.resolveInclude(name, v, true); - return fs.existsSync(filePath); - })) { - return filePath; - } - } - - /** - * Get the path to the included file by Options - * - * @param {String} path specified path - * @param {Options} options compilation options - * @return {String} - */ - function getIncludePath(path, options) { - var includePath; - var filePath; - var views = options.views; - var match = /^[A-Za-z]+:\\|^\//.exec(path); - - // Abs path - if (match && match.length) { - path = path.replace(/^\/*/, ''); - if (Array.isArray(options.root)) { - includePath = resolvePaths(path, options.root); - } else { - includePath = exports.resolveInclude(path, options.root || '/', true); - } - } - // Relative paths - else { - // Look relative to a passed filename first - if (options.filename) { - filePath = exports.resolveInclude(path, options.filename); - if (fs.existsSync(filePath)) { - includePath = filePath; - } - } - // Then look in any views directories - if (!includePath && Array.isArray(views)) { - includePath = resolvePaths(path, views); - } - if (!includePath && typeof options.includer !== 'function') { - throw new Error('Could not find the include file "' + - options.escapeFunction(path) + '"'); - } - } - return includePath; - } - - /** - * Get the template from a string or a file, either compiled on-the-fly or - * read from cache (if enabled), and cache the template if needed. - * - * If `template` is not set, the file specified in `options.filename` will be - * read. - * - * If `options.cache` is true, this function reads the file from - * `options.filename` so it must be set prior to calling this function. - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {String} [template] template source - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned. - * @static - */ - - function handleCache(options, template) { - var func; - var filename = options.filename; - var hasTemplate = arguments.length > 1; - - if (options.cache) { - if (!filename) { - throw new Error('cache option requires a filename'); - } - func = exports.cache.get(filename); - if (func) { - return func; - } - if (!hasTemplate) { - template = fileLoader(filename).toString().replace(_BOM, ''); - } - } - else if (!hasTemplate) { - // istanbul ignore if: should not happen at all - if (!filename) { - throw new Error('Internal EJS error: no file name or template ' - + 'provided'); - } - template = fileLoader(filename).toString().replace(_BOM, ''); - } - func = exports.compile(template, options); - if (options.cache) { - exports.cache.set(filename, func); - } - return func; - } - - /** - * Try calling handleCache with the given options and data and call the - * callback with the result. If an error occurs, call the callback with - * the error. Used by renderFile(). - * - * @memberof module:ejs-internal - * @param {Options} options compilation options - * @param {Object} data template data - * @param {RenderFileCallback} cb callback - * @static - */ - - function tryHandleCache(options, data, cb) { - var result; - if (!cb) { - if (typeof exports.promiseImpl == 'function') { - return new exports.promiseImpl(function (resolve, reject) { - try { - result = handleCache(options)(data); - resolve(result); - } - catch (err) { - reject(err); - } - }); - } - else { - throw new Error('Please provide a callback function'); - } - } - else { - try { - result = handleCache(options)(data); - } - catch (err) { - return cb(err); - } - - cb(null, result); - } - } - - /** - * fileLoader is independent - * - * @param {String} filePath ejs file path. - * @return {String} The contents of the specified file. - * @static - */ - - function fileLoader(filePath){ - return exports.fileLoader(filePath); - } - - /** - * Get the template function. - * - * If `options.cache` is `true`, then the template is cached. - * - * @memberof module:ejs-internal - * @param {String} path path for the specified file - * @param {Options} options compilation options - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `options.client`, either type might be returned - * @static - */ - - function includeFile(path, options) { - var opts = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), options); - opts.filename = getIncludePath(path, opts); - if (typeof options.includer === 'function') { - var includerResult = options.includer(path, opts.filename); - if (includerResult) { - if (includerResult.filename) { - opts.filename = includerResult.filename; - } - if (includerResult.template) { - return handleCache(opts, includerResult.template); - } - } - } - return handleCache(opts); - } - - /** - * Re-throw the given `err` in context to the `str` of ejs, `filename`, and - * `lineno`. - * - * @implements {RethrowCallback} - * @memberof module:ejs-internal - * @param {Error} err Error object - * @param {String} str EJS source - * @param {String} flnm file name of the EJS file - * @param {Number} lineno line number of the error - * @param {EscapeCallback} esc - * @static - */ - - function rethrow(err, str, flnm, lineno, esc) { - var lines = str.split('\n'); - var start = Math.max(lineno - 3, 0); - var end = Math.min(lines.length, lineno + 3); - var filename = esc(flnm); - // Error context - var context = lines.slice(start, end).map(function (line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; - } - - function stripSemi(str){ - return str.replace(/;(\s*$)/, '$1'); - } - - /** - * Compile the given `str` of ejs into a template function. - * - * @param {String} template EJS template - * - * @param {Options} [opts] compilation options - * - * @return {(TemplateFunction|ClientFunction)} - * Depending on the value of `opts.client`, either type might be returned. - * Note that the return type of the function also depends on the value of `opts.async`. - * @public - */ - - exports.compile = function compile(template, opts) { - var templ; - - // v1 compat - // 'scope' is 'context' - // FIXME: Remove this in a future version - if (opts && opts.scope) { - if (!scopeOptionWarned){ - console.warn('`scope` option is deprecated and will be removed in EJS 3'); - scopeOptionWarned = true; - } - if (!opts.context) { - opts.context = opts.scope; - } - delete opts.scope; - } - templ = new Template(template, opts); - return templ.compile(); - }; - - /** - * Render the given `template` of ejs. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} template EJS template - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @return {(String|Promise)} - * Return value type depends on `opts.async`. - * @public - */ - - exports.render = function (template, d, o) { - var data = d || utils$1.createNullProtoObjWherePossible(); - var opts = o || utils$1.createNullProtoObjWherePossible(); - - // No options object -- if there are optiony names - // in the data, copy them to options - if (arguments.length == 2) { - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA); - } - - return handleCache(opts, template)(data); - }; - - /** - * Render an EJS file at the given `path` and callback `cb(err, str)`. - * - * If you would like to include options but not data, you need to explicitly - * call this function with `data` being an empty object or `null`. - * - * @param {String} path path to the EJS file - * @param {Object} [data={}] template data - * @param {Options} [opts={}] compilation and rendering options - * @param {RenderFileCallback} cb callback - * @public - */ - - exports.renderFile = function () { - var args = Array.prototype.slice.call(arguments); - var filename = args.shift(); - var cb; - var opts = {filename: filename}; - var data; - var viewOpts; - - // Do we have a callback? - if (typeof arguments[arguments.length - 1] == 'function') { - cb = args.pop(); - } - // Do we have data/opts? - if (args.length) { - // Should always have data obj - data = args.shift(); - // Normal passed opts (data obj + opts obj) - if (args.length) { - // Use shallowCopy so we don't pollute passed in opts obj with new vals - utils$1.shallowCopy(opts, args.pop()); - } - // Special casing for Express (settings + opts-in-data) - else { - // Express 3 and 4 - if (data.settings) { - // Pull a few things from known locations - if (data.settings.views) { - opts.views = data.settings.views; - } - if (data.settings['view cache']) { - opts.cache = true; - } - // Undocumented after Express 2, but still usable, esp. for - // items that are unsafe to be passed along with data, like `root` - viewOpts = data.settings['view options']; - if (viewOpts) { - utils$1.shallowCopy(opts, viewOpts); - } - } - // Express 2 and lower, values set in app.locals, or people who just - // want to pass options in their data. NOTE: These values will override - // anything previously set in settings or settings['view options'] - utils$1.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS); - } - opts.filename = filename; - } - else { - data = utils$1.createNullProtoObjWherePossible(); - } - - return tryHandleCache(opts, data, cb); - }; - - /** - * Clear intermediate JavaScript cache. Calls {@link Cache#reset}. - * @public - */ - - /** - * EJS template class - * @public - */ - exports.Template = Template; - - exports.clearCache = function () { - exports.cache.reset(); - }; - - function Template(text, opts) { - opts = opts || utils$1.createNullProtoObjWherePossible(); - var options = utils$1.createNullProtoObjWherePossible(); - this.templateText = text; - /** @type {string | null} */ - this.mode = null; - this.truncate = false; - this.currentLine = 1; - this.source = ''; - options.client = opts.client || false; - options.escapeFunction = opts.escape || opts.escapeFunction || utils$1.escapeXML; - options.compileDebug = opts.compileDebug !== false; - options.debug = !!opts.debug; - options.filename = opts.filename; - options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER; - options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER; - options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER; - options.strict = opts.strict || false; - options.context = opts.context; - options.cache = opts.cache || false; - options.rmWhitespace = opts.rmWhitespace; - options.root = opts.root; - options.includer = opts.includer; - options.outputFunctionName = opts.outputFunctionName; - options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME; - options.views = opts.views; - options.async = opts.async; - options.destructuredLocals = opts.destructuredLocals; - options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true; - - if (options.strict) { - options._with = false; - } - else { - options._with = typeof opts._with != 'undefined' ? opts._with : true; - } - - this.opts = options; - - this.regex = this.createRegex(); - } - - Template.modes = { - EVAL: 'eval', - ESCAPED: 'escaped', - RAW: 'raw', - COMMENT: 'comment', - LITERAL: 'literal' - }; - - Template.prototype = { - createRegex: function () { - var str = _REGEX_STRING; - var delim = utils$1.escapeRegExpChars(this.opts.delimiter); - var open = utils$1.escapeRegExpChars(this.opts.openDelimiter); - var close = utils$1.escapeRegExpChars(this.opts.closeDelimiter); - str = str.replace(/%/g, delim) - .replace(//g, close); - return new RegExp(str); - }, - - compile: function () { - /** @type {string} */ - var src; - /** @type {ClientFunction} */ - var fn; - var opts = this.opts; - var prepended = ''; - var appended = ''; - /** @type {EscapeCallback} */ - var escapeFn = opts.escapeFunction; - /** @type {FunctionConstructor} */ - var ctor; - /** @type {string} */ - var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined'; - - if (!this.source) { - this.generateSource(); - prepended += - ' var __output = "";\n' + - ' function __append(s) { if (s !== undefined && s !== null) __output += s }\n'; - if (opts.outputFunctionName) { - if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) { - throw new Error('outputFunctionName is not a valid JS identifier.'); - } - prepended += ' var ' + opts.outputFunctionName + ' = __append;' + '\n'; - } - if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) { - throw new Error('localsName is not a valid JS identifier.'); - } - if (opts.destructuredLocals && opts.destructuredLocals.length) { - var destructuring = ' var __locals = (' + opts.localsName + ' || {}),\n'; - for (var i = 0; i < opts.destructuredLocals.length; i++) { - var name = opts.destructuredLocals[i]; - if (!_JS_IDENTIFIER.test(name)) { - throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.'); - } - if (i > 0) { - destructuring += ',\n '; - } - destructuring += name + ' = __locals.' + name; - } - prepended += destructuring + ';\n'; - } - if (opts._with !== false) { - prepended += ' with (' + opts.localsName + ' || {}) {' + '\n'; - appended += ' }' + '\n'; - } - appended += ' return __output;' + '\n'; - this.source = prepended + this.source + appended; - } - - if (opts.compileDebug) { - src = 'var __line = 1' + '\n' - + ' , __lines = ' + JSON.stringify(this.templateText) + '\n' - + ' , __filename = ' + sanitizedFilename + ';' + '\n' - + 'try {' + '\n' - + this.source - + '} catch (e) {' + '\n' - + ' rethrow(e, __lines, __filename, __line, escapeFn);' + '\n' - + '}' + '\n'; - } - else { - src = this.source; - } - - if (opts.client) { - src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\n' + src; - if (opts.compileDebug) { - src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\n' + src; - } - } - - if (opts.strict) { - src = '"use strict";\n' + src; - } - if (opts.debug) { - console.log(src); - } - if (opts.compileDebug && opts.filename) { - src = src + '\n' - + '//# sourceURL=' + sanitizedFilename + '\n'; - } - - try { - if (opts.async) { - // Have to use generated function for this, since in envs without support, - // it breaks in parsing - try { - ctor = (new Function('return (async function(){}).constructor;'))(); - } - catch(e) { - if (e instanceof SyntaxError) { - throw new Error('This environment does not support async/await'); - } - else { - throw e; - } - } - } - else { - ctor = Function; - } - fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src); - } - catch(e) { - // istanbul ignore else - if (e instanceof SyntaxError) { - if (opts.filename) { - e.message += ' in ' + opts.filename; - } - e.message += ' while compiling ejs\n\n'; - e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\n'; - e.message += 'https://github.com/RyanZim/EJS-Lint'; - if (!opts.async) { - e.message += '\n'; - e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.'; - } - } - throw e; - } - - // Return a callable function which will execute the function - // created by the source-code, with the passed data as locals - // Adds a local `include` function which allows full recursive include - var returnedFn = opts.client ? fn : function anonymous(data) { - var include = function (path, includeData) { - var d = utils$1.shallowCopy(utils$1.createNullProtoObjWherePossible(), data); - if (includeData) { - d = utils$1.shallowCopy(d, includeData); - } - return includeFile(path, opts)(d); - }; - return fn.apply(opts.context, - [data || utils$1.createNullProtoObjWherePossible(), escapeFn, include, rethrow]); - }; - if (opts.filename && typeof Object.defineProperty === 'function') { - var filename = opts.filename; - var basename = path.basename(filename, path.extname(filename)); - try { - Object.defineProperty(returnedFn, 'name', { - value: basename, - writable: false, - enumerable: false, - configurable: true - }); - } catch (e) {/* ignore */} - } - return returnedFn; - }, - - generateSource: function () { - var opts = this.opts; - - if (opts.rmWhitespace) { - // Have to use two separate replace here as `^` and `$` operators don't - // work well with `\r` and empty lines don't work well with the `m` flag. - this.templateText = - this.templateText.replace(/[\r\n]+/g, '\n').replace(/^\s+|\s+$/gm, ''); - } - - // Slurp spaces and tabs before <%_ and after _%> - this.templateText = - this.templateText.replace(/[ \t]*<%_/gm, '<%_').replace(/_%>[ \t]*/gm, '_%>'); - - var self = this; - var matches = this.parseTemplateText(); - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - - if (matches && matches.length) { - matches.forEach(function (line, index) { - var closing; - // If this is an opening tag, check for closing tags - // FIXME: May end up with some false positives here - // Better to store modes as k/v with openDelimiter + delimiter as key - // Then this can simply check against the map - if ( line.indexOf(o + d) === 0 // If it is a tag - && line.indexOf(o + d + d) !== 0) { // and is not escaped - closing = matches[index + 2]; - if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) { - throw new Error('Could not find matching close tag for "' + line + '".'); - } - } - self.scanLine(line); - }); - } - - }, - - parseTemplateText: function () { - var str = this.templateText; - var pat = this.regex; - var result = pat.exec(str); - var arr = []; - var firstPos; - - while (result) { - firstPos = result.index; - - if (firstPos !== 0) { - arr.push(str.substring(0, firstPos)); - str = str.slice(firstPos); - } - - arr.push(result[0]); - str = str.slice(result[0].length); - result = pat.exec(str); - } - - if (str) { - arr.push(str); - } - - return arr; - }, - - _addOutput: function (line) { - if (this.truncate) { - // Only replace single leading linebreak in the line after - // -%> tag -- this is the single, trailing linebreak - // after the tag that the truncation mode replaces - // Handle Win / Unix / old Mac linebreaks -- do the \r\n - // combo first in the regex-or - line = line.replace(/^(?:\r\n|\r|\n)/, ''); - this.truncate = false; - } - if (!line) { - return line; - } - - // Preserve literal slashes - line = line.replace(/\\/g, '\\\\'); - - // Convert linebreaks - line = line.replace(/\n/g, '\\n'); - line = line.replace(/\r/g, '\\r'); - - // Escape double-quotes - // - this will be the delimiter during execution - line = line.replace(/"/g, '\\"'); - this.source += ' ; __append("' + line + '")' + '\n'; - }, - - scanLine: function (line) { - var self = this; - var d = this.opts.delimiter; - var o = this.opts.openDelimiter; - var c = this.opts.closeDelimiter; - var newLineCount = 0; - - newLineCount = (line.split('\n').length - 1); - - switch (line) { - case o + d: - case o + d + '_': - this.mode = Template.modes.EVAL; - break; - case o + d + '=': - this.mode = Template.modes.ESCAPED; - break; - case o + d + '-': - this.mode = Template.modes.RAW; - break; - case o + d + '#': - this.mode = Template.modes.COMMENT; - break; - case o + d + d: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(o + d + d, o + d) + '")' + '\n'; - break; - case d + d + c: - this.mode = Template.modes.LITERAL; - this.source += ' ; __append("' + line.replace(d + d + c, d + c) + '")' + '\n'; - break; - case d + c: - case '-' + d + c: - case '_' + d + c: - if (this.mode == Template.modes.LITERAL) { - this._addOutput(line); - } - - this.mode = null; - this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0; - break; - default: - // In script mode, depends on type of tag - if (this.mode) { - // If '//' is found without a line break, add a line break. - switch (this.mode) { - case Template.modes.EVAL: - case Template.modes.ESCAPED: - case Template.modes.RAW: - if (line.lastIndexOf('//') > line.lastIndexOf('\n')) { - line += '\n'; - } - } - switch (this.mode) { - // Just executing code - case Template.modes.EVAL: - this.source += ' ; ' + line + '\n'; - break; - // Exec, esc, and output - case Template.modes.ESCAPED: - this.source += ' ; __append(escapeFn(' + stripSemi(line) + '))' + '\n'; - break; - // Exec and output - case Template.modes.RAW: - this.source += ' ; __append(' + stripSemi(line) + ')' + '\n'; - break; - case Template.modes.COMMENT: - // Do nothing - break; - // Literal <%% mode, append as raw output - case Template.modes.LITERAL: - this._addOutput(line); - break; - } - } - // In string mode, just add the output - else { - this._addOutput(line); - } - } - - if (self.opts.compileDebug && newLineCount) { - this.currentLine += newLineCount; - this.source += ' ; __line = ' + this.currentLine + '\n'; - } - } - }; - - /** - * Escape characters reserved in XML. - * - * This is simply an export of {@link module:utils.escapeXML}. - * - * If `markup` is `undefined` or `null`, the empty string is returned. - * - * @param {String} markup Input string - * @return {String} Escaped string - * @public - * @func - * */ - exports.escapeXML = utils$1.escapeXML; - - /** - * Express.js support. - * - * This is an alias for {@link module:ejs.renderFile}, in order to support - * Express.js out-of-the-box. - * - * @func - */ - - exports.__express = exports.renderFile; - - /** - * Version of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.VERSION = _VERSION_STRING; - - /** - * Name for detection of EJS. - * - * @readonly - * @type {String} - * @public - */ - - exports.name = _NAME; - - /* istanbul ignore if */ - if (typeof window != 'undefined') { - window.ejs = exports; - } - } (ejs)); - - /** - * Extracts the segmentation value from the Bloomreach segmentation pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractSegmentationCookie() { - const cookiePrefix = `${COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS}=`; - const segmentationCookie = document.cookie.split('; ').find(cookie => cookie.startsWith(cookiePrefix)); - return (segmentationCookie || '').replace(cookiePrefix, ''); - } - function applyKeywordRedirection(response) { - var _a; - if (response === null || response === void 0 ? void 0 : response.keywordRedirect) { - localStorage.setItem('keywordRedirect', JSON.stringify({ - original_query: response.keywordRedirect['original query'], - redirected_query: response.keywordRedirect['redirected query'], - redirected_url: response.keywordRedirect['redirected url'] - })); - const redirectedUrl = ((_a = response.keywordRedirect) === null || _a === void 0 ? void 0 : _a['redirected url']) || ''; - window.location.href = `${!redirectedUrl.startsWith('http') ? 'https://' : ''}${redirectedUrl}`; - } - } - - // /utils/getRequest.ts - /** - * Method used to initiate the API request - * @remarks The Assignment of the API specific promise is set in the respective API - * @param {string} url - * @param {{}} options - * @returns {Promise} - */ - async function getRequest(url, options) { - /** - * Use of Client-Side Fetch API to retrieve the response - * @type {Response} - */ - const response = await fetch(url, options); - /** - * Formats the response as json and returns the typed promise - * @type {any} - */ - const result = await response.json(); - /** - * Sets the type for the promise - */ - return result; - } - - // utils.requestOptions.ts - /** - * - * @type {{headers: {'Content-Type': string}, method: string}} - */ - const requestOptions = { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }; - - // utils/extractTrackingCookie.ts - /** - * Extracts the tracking cookie from the Bloomreach cookie pixel - * @remarks Designed to check for the cookie,and if not present will set a default - * @returns {string} - */ - function extractTrackingCookie() { - const trackingCookie = document.cookie.split('; ').find(cookie => cookie.startsWith('_br_uid_2=')); - return trackingCookie ? trackingCookie.replace('_br_uid_2=', '') : 'uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55'; - } - - // utils/formatAsCurrency.ts - /** - * Formats a value returned as a double into currency - * @param {number} cents - * @param {string} currencySign - * @param {boolean} onFront - * @returns {string} - */ - const formatAsCurrency = (cents, currencySign = '$', onFront = true) => `${onFront ? currencySign : ''}${(cents / 100.0).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2 -})}${!onFront ? ` ${currencySign}` : ''}`; - - // utils/generateRequestID.ts - /** - * Generates a randomized request ID that is 13 characters long - * @returns {number} - */ - function generateRequestId() { - // eslint-disable-next-line no-mixed-operators - const requestID = Math.floor(1000000000000 + Math.random() * 9000000000000); - return requestID; - } - - // api-client/constants - // todo Refactor vanilla js / react implementation to either use or not use the constants config - const ENDPOINT_AUTOSUGGEST_API = 'https://suggest.dxpapi.com/api/v2/suggest/'; - const ENDPOINT_PRODUCT_SEARCH_API = 'https://core.dxpapi.com/api/v1/core/'; - const NO_ENCODE_PARAMETERS = ['_br_uid_2', 'fq', 'sort']; - const FIELD_LIST_DEFAULT = 'pid,title,brand,price,sale_price,thumb_image,sku_thumb_images,sku_swatch_images,sku_color_group,url,price_range,sale_price_range,description,is_live,score,skuid,group'; - - function buildQueryParameters(apiCallParameters) { - return `?${Object.keys(apiCallParameters).reduce((queryParameters, parameterName) => [...queryParameters, `${parameterName}=${NO_ENCODE_PARAMETERS.includes(parameterName) ? apiCallParameters[parameterName] : encodeURIComponent(apiCallParameters[parameterName])}`], []).join('&')}`; - } - function buildSearchRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_PRODUCT_SEARCH_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - if (!(apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.fl)) apiParameters.fl = FIELD_LIST_DEFAULT; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - function buildAutosuggestRequestUrl(parameters) { - const apiParameters = Object.assign({}, parameters); - const endpoint = (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) || ENDPOINT_AUTOSUGGEST_API; - if (apiParameters === null || apiParameters === void 0 ? void 0 : apiParameters.endpoint) apiParameters === null || apiParameters === void 0 ? true : delete apiParameters.endpoint; - return `${endpoint}${buildQueryParameters(apiParameters)}`; - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSuggestions(params) { - const url = buildAutosuggestRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - /** - * Get suggestions API - * @returns {Promise} - */ - async function getSearchResults(params) { - // Retrieves the URL and Options from the buildQueryParams function - const url = buildSearchRequestUrl(params); - const options = requestOptions; - return getRequest(url, options); - } - - var searchLayoutTemplate = "<% if (did_you_mean.length) { %>\n
\n
\n

Results for\n <% if (locals.keywordRedirect && keywordRedirect.redirected_url) { %>\n <%- keywordRedirect.redirected_url %>\n <% } else { %>\n <%- did_you_mean[0] %>\n <% } %>\n instead of <%- locals[config.default_search_parameter] %>

\n
\n \n <% did_you_mean.forEach(function(word) { %>\n ?<%= config.default_search_parameter %>=<%= word %>\" class=\"blm-did-you-mean-suggestion__link\"><%- word %>\n <% }); %>\n
\n <% if (locals.keywordRedirect && keywordRedirect.redirected_query) { %>\n
Redirected from \"<%- keywordRedirect.redirected_query %>\".
\n <% } %>\n
\n
\n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from \"<%- keywordRedirect.original_query %>\"
\n
\n
\n<% } %>\n
category<% } else { %>product-search<% } %> blm-results <% if (config.search.facets_included) { %>with-facets<% } %>\">\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class=\"blm-product-search__results\"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n"; - - var searchListTemplate = "<% function printProduct(product) { %>\n
title=\"<%- product.variant_name %>\"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : 'variant_index' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style=\"display: block\"<% } %>\n >\n \"\n />\n
\n <% }); %>\n <% } else { %>\n
\n \"\n />\n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !('variant_index' in product) && !selectedColors.length\n ? index === 0\n : 'variant_index' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n active<% } %>\"\n style=\"background-image: url('<%= variant.image %>')\"\n >\n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n"; - - var autosuggestTemplate = "<% if (terms.length || productSuggestions.length) { %>\n
\n <% } %>\n"; - - function buildBaseConfig() { - var _a; - const connectorConfig = (_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config; - const config = Object.assign({ - default_search_parameter: DEFAULT_SEARCH_PARAMETER, - url: window.location.href, - ref_url: window.location.href, - tracking_cookie: extractTrackingCookie(), - format_money: cents => formatAsCurrency(cents, window.bloomreachDefaultCurrency || DEFAULT_CURRENCY), - default_currency: window.bloomreachDefaultCurrency || DEFAULT_CURRENCY - }, connectorConfig); - return config; - } - function buildAutosuggestConfig() { - const baseConfig = buildBaseConfig(); - const config = Object.assign(Object.assign({ - request_type: REQUEST_TYPE_SUGGEST - }, baseConfig), { - autosuggest: Object.assign({ - enabled: true, - endpoint: '', - number_of_terms: NUMBER_OF_AUTOSUGGEST_TERMS, - number_of_products: NUMBER_OF_AUTOSUGGEST_PRODUCTS, - number_of_collections: NUMBER_OF_AUTOSUGGEST_COLLECTIONS, - selector: SELECTOR_AUTOSUGGEST_INPUT, - template: autosuggestTemplate, - catalog_views: '' - }, baseConfig.autosuggest) - }); - return config; - } - function buildSearchConfig() { - var _a, _b, _c; - const baseConfig = buildBaseConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const state = getCurrentSearchRequestState(); - const defaultSearchProperties = Object.assign({ - display_variants: false, - enabled: true, - endpoint: '', - items_per_page: DEFAULT_PAGE_SIZE, - facets_included: true, - initial_number_of_facets: NUMBER_OF_FACET_GROUPS, - initial_number_of_facet_values: NUMBER_OF_FACET_VALUES, - infinite_scroll: false, - selector: SELECTOR_SEARCH_RESULTS_CONTAINER, - sorting_options: DEFAULT_SORTING_OPTIONS, - template: searchLayoutTemplate, - product_list_template: searchListTemplate - }, (baseConfig === null || baseConfig === void 0 ? void 0 : baseConfig.search) ? baseConfig.search : {}); - const config = Object.assign(Object.assign({}, baseConfig), { - request_type: REQUEST_TYPE_SEARCH, - search_type: state.is_category_page ? SEARCH_TYPE_CATEGORY : SEARCH_TYPE_KEYWORD, - start: DEFAULT_START, - 'facet.range': FIELD_NAME_PRICE, - 'stats.field': FIELD_NAME_PRICE, - sort: urlParameters.get(PARAMETER_NAME_SORT) || '', - search: Object.assign(Object.assign(Object.assign({}, defaultSearchProperties), (state.is_category_page ? baseConfig.category : baseConfig.search) || {}), state.category_to_load ? { - category_id: state.category_to_load - } : {}) - }); - (_c = (_b = (_a = config.search) === null || _a === void 0 ? void 0 : _a.sorting_options) === null || _b === void 0 ? void 0 : _b.sort) === null || _c === void 0 ? void 0 : _c.call(_b, (option1, option2) => option1.value > option2.value ? 1 : -1); - if (config.search) { - config.search = Object.assign(Object.assign({}, config.search), { - items_per_page: Number(urlParameters.has(PARAMETER_NAME_SIZE) ? urlParameters.get(PARAMETER_NAME_SIZE) : config.search.items_per_page), - groupby: urlParameters.get(PARAMETER_NAME_GROUPBY) || config.search.groupby || '' - }); - } - return config; - } - - function buildPaginationData(results) { - if ('grouped_products' in results) return buildGroupedPaginationData(results); - return buildRegularPaginationData(results); - } - function buildRegularPaginationData(results) { - const pageSize = results.size || 1; - if (results.number_of_results <= pageSize) { - return []; - } - const page = Math.ceil((results.start + 1) / pageSize); - const numberOfAllPages = Math.ceil(results.number_of_results / pageSize); - const beforeNumbers = Array(page - 1).fill(null).map((_, index) => index + 1).slice(-MAX_PAGINATION_NUMBER_BEFORE_CURRENT); - const afterNumbers = Array(numberOfAllPages - page).fill(null).map((_, index) => index + (page + 1)).slice(0, MAX_PAGINATION_NUMBER_AFTER_CURRENT); - return [...(page > 1 ? [{ - value: 'previous', - label: '←' - }] : []), ...(page - 1 > MAX_PAGINATION_NUMBER_BEFORE_CURRENT ? [{ - label: '…', - value: (page - MAX_PAGINATION_NUMBER_BEFORE_CURRENT - 1).toString() - }] : []), ...beforeNumbers.map(number => ({ - value: number.toString() - })), { - value: page.toString(), - disabled: true, - active: true - }, ...afterNumbers.map(number => ({ - value: number.toString() - })), ...(page + MAX_PAGINATION_NUMBER_AFTER_CURRENT < numberOfAllPages ? [{ - label: '…', - value: (page + MAX_PAGINATION_NUMBER_AFTER_CURRENT + 1).toString() - }] : []), ...(page < numberOfAllPages ? [{ - value: 'next', - label: '→' - }] : [])]; - } - function buildGroupedPaginationData(results) { - var _a; - const page = Number(results.page || 1); - const pageSize = results.size || 1; - const numberOfGroups = (((_a = results === null || results === void 0 ? void 0 : results.grouped_products) === null || _a === void 0 ? void 0 : _a.groups) || []).length; - return [{ - value: 'previous', - label: 'Previous', - disabled: page <= 1 - }, { - value: 'next', - label: 'Next', - disabled: numberOfGroups < pageSize - }]; - } - const escapeSpecialCharacters = value => value.replace(/"/g, '"').replace(/,/g, '%%-COMMA-%%'); - const decodeSpecialCharacters = value => value.replace(/%%-COMMA-%%/g, ',').replace(/"/g, '"'); - const convertFacetsToQueryString = facets => { - return Object.keys(facets).map(facetName => { - if (facetName === 'price') { - return encodeURIComponent( - // @ts-ignore - `${facetName}:[${facets[facetName].map(value => `${value}`).join(' TO ')}]`); - } - return encodeURIComponent( - // @ts-ignore - `${facetName}:${facets[facetName].map(value => `"${decodeSpecialCharacters(value)}"`).join(' OR ')}`); - }).join('&fq='); - }; - - let memoizedNS; - const NOOP = Object.assign(() => {}, { - warn: () => {}, - error: () => {}, - verbose: () => {} - }); - let colorIndex = -1; - const memoizedColor = new Map(); - /** - * List of colors our debugger can pick from. The colors should be slightly - * desautrated to help with reading and should be highly varied. - */ - const pickColor = ns => { - if (memoizedColor.has(ns)) return memoizedColor.get(ns); - const color = ['#00a3ff', '#ff00a3', '#a3ff00', '#00ffa3', '#a300ff', '#ffaa00', '#00ffaa', '#ff00aa', '#aa00ff', '#00aaff'][++colorIndex % 10] || '#00a3ff'; - memoizedColor.set(ns, color); - return color; - }; - /** - * Creates a simple debug logger system that is only activated by the stored - * state within localStorage.debug. The value in the state can be: - * - * namespace1;namespace2;namespace3;etc - * - * or - * - * namepspace1 - * - * or - * - * * - * - * Where `*` is a wildcard that will activate all namespaces. - */ - const Debug = ns => { - const active = activeNS(); - // If the namespace is not active, return a noop function set - if (!active.has(ns) && !active.has('*')) return NOOP; - const color = pickColor(ns); - const logger = console.log.bind(console, `%c${ns}`, `color: ${color}`); - logger.warn = console.warn.bind(console, `%c${ns}`, `color: ${color}`); - logger.error = console.error.bind(console, `%c${ns}`, `color: ${color}`); - if (active.has(`${ns}:verbose`) || active.has('*')) { - logger.verbose = console.log.bind(console, `%c${ns}:verbose`, `color: ${color}`); - } else { - logger.verbose = () => {}; - } - return logger; - }; - function activeNS() { - if (memoizedNS) return memoizedNS; - const storage = window.localStorage; - if (!storage) return new Set(); - const ns = storage.getItem('debug') || ''; - memoizedNS = new Set(ns.split(';')); - return memoizedNS; - } - - /** - * If a truthy value is false, this throws an error and displays the message for - * the error. - */ - function invariant(truthy, message) { - if (truthy) return; - throw new Error(message); - } - - Debug('br:autosuggest'); - function hideAllDynamicFacetGroups() { - ['.blm-dynamic-filter', '.blm-product-search-filter-item', '.blm-product-search-load-more'].forEach(selector => { - document.querySelectorAll(selector).forEach(item => { - item.removeAttribute('style'); - }); - }); - } - function loadMoreFacetGroups(numberOfFacetGroupsParameter) { - var _a; - let i = 0; - let numberOfHiddenBoxWithVisibleChildren = 0; - const config = buildSearchConfig(); - const numberOfFacetGroups = Number(numberOfFacetGroupsParameter || ((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets)); - document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach(item => { - const visibleChildren = item === null || item === void 0 ? void 0 : item.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]'); - if (i < numberOfFacetGroups && visibleChildren.length > 0) { - item === null || item === void 0 ? void 0 : item.setAttribute('style', 'display: block'); - } - i++; - numberOfHiddenBoxWithVisibleChildren += visibleChildren.length > 0 ? 1 : 0; - }); - const currentSearchRequestState = getCurrentSearchRequestState(); - const loadMoreFacetGroupsElement = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - const numberOfHiddenBoxes = document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length; - if (numberOfHiddenBoxes === 0 || numberOfHiddenBoxWithVisibleChildren === 0) { - loadMoreFacetGroupsElement === null || loadMoreFacetGroupsElement === void 0 ? void 0 : loadMoreFacetGroupsElement.classList.add('blm-hide'); - } - } - function getLoadMoreFacetGroupsElement() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const element = document.querySelector(`.blm-load-more-facet--${currentSearchRequestState.request_id}`); - invariant(element, 'the element for loading more facet groups must be in the DOM'); - return element; - } - function resetFacetGroups() { - var _a, _b, _c; - const config = buildSearchConfig(); - const numberOfDisplayedFacetGroups = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facets); - const numberOfDisplayedFacetValues = Number((_b = config.search) === null || _b === void 0 ? void 0 : _b.initial_number_of_facet_values); - hideAllDynamicFacetGroups(); - loadMoreFacetGroups(numberOfDisplayedFacetGroups - 1); - // init facet items visibility - document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${numberOfDisplayedFacetValues})`).forEach(item => item.style.display = 'block'); - (_c = getLoadMoreFacetGroupsElement()) === null || _c === void 0 ? void 0 : _c.removeAttribute('style'); - } - function getSearchResultsContainerElement() { - var _a; - const config = buildSearchConfig(); - invariant((_a = config.search) === null || _a === void 0 ? void 0 : _a.selector, 'the selector of search results container element must be set'); - const searchResultsContainerElement = document.querySelector(config.search.selector); - return searchResultsContainerElement; - } - function getSearchResultsListContainerElement() { - var _a; - const searchResultsListContainerElement = (_a = document.querySelector('.blm-product-search-main')) === null || _a === void 0 ? void 0 : _a.lastElementChild; - return searchResultsListContainerElement; - } - function getAutosuggestSearchInputElement() { - const config = buildAutosuggestConfig(); - if (!config.autosuggest) return null; - invariant(config.autosuggest.selector, 'the selector of search results container element must be set'); - const autosuggestInputElement = document.querySelector(config.autosuggest.selector); - return autosuggestInputElement; - } - function getAutosuggestResultsContainerElement() { - const autosuggestResultsContainerElement = document.querySelector('.blm-autosuggest-search-results'); - return autosuggestResultsContainerElement; - } - function resetLoadingIndicator() { - const scrollIndicator = document.querySelector('.blm-scroll-indicator'); - if (scrollIndicator) { - scrollIndicator.innerHTML = ''; - const loaderElement = document.createElement('div'); - loaderElement.classList.add('blm-scroll-indicator__loading'); - scrollIndicator.appendChild(loaderElement); - } - } - function getCheckedFacetValues() { - const checkedCheckboxes = document.querySelectorAll('.blm-product-search-filter-item__checkbox:checked'); - return checkedCheckboxes ? Array.from(checkedCheckboxes).reduce((all, current) => { - return Object.assign(Object.assign({}, all), { - [current.name]: all[current.name] ? [...(all[current.name] || []), current.value] : [current.value] - }); - }, {}) : {}; - } - function restoreScrollPosition() { - var _a; - // Get saved scroll positions - const storedScrollPositions = JSON.parse(window.localStorage.getItem('scrollPositions') || '{}'); - // Restore it if it's found for current page - const currentUriEncoded = encodeURI(window.location.href); - if (currentUriEncoded in storedScrollPositions) { - const scrollPosition = parseInt((_a = storedScrollPositions[currentUriEncoded]) === null || _a === void 0 ? void 0 : _a.scrollPosition, 10); - setTimeout(() => { - document.documentElement.scrollTop = scrollPosition; - document.body.scrollTop = scrollPosition; - }, 250); - } - delete storedScrollPositions[encodeURI(window.location.href)]; - window.localStorage.setItem('scrollPositions', JSON.stringify(storedScrollPositions)); - } - function beforeUnloadWindowEvent() { - let scrollPosition; - if (typeof window.pageYOffset !== 'undefined') { - scrollPosition = window.pageYOffset; - } else if (typeof document.compatMode !== 'undefined' && document.compatMode !== 'BackCompat') { - scrollPosition = document.documentElement.scrollTop; - } else if (typeof document.body !== 'undefined') { - scrollPosition = document.body.scrollTop; - } - const storedScrollPositions = JSON.parse(window.localStorage.getItem('scrollPositions') || '{}'); - window.localStorage.setItem('scrollPositions', JSON.stringify(Object.assign(Object.assign({}, storedScrollPositions), { - [encodeURI(window.location.href)]: { - scrollPosition - } - }))); - } - function setupSavingScrollPosition() { - // Add listeners in re-entrant fashion - unmountSaveScrollPosition(); - window.addEventListener('beforeunload', beforeUnloadWindowEvent); - } - function unmountSaveScrollPosition() { - window.removeEventListener('beforeunload', beforeUnloadWindowEvent); - } - - var breakpoints; - (function (breakpoints) { - breakpoints["small"] = "480px"; - breakpoints["medium"] = "680px"; - breakpoints["large"] = "750px"; - breakpoints["xlarge"] = "875px"; - breakpoints["xxlarge"] = "1000px"; - breakpoints["xxxlarge"] = "1200px"; - })(breakpoints || (breakpoints = {})); - const isMobileView = window.matchMedia(`(max-width: ${breakpoints.medium})`); - window.matchMedia(`(min-width:${breakpoints.medium}) and (max-width: ${breakpoints.xlarge})`); - - const log$2 = Debug('br:url'); - function updateUrl(urlParameters) { - var _a, _b, _c, _d; - const historyStateObject = {}; - // eslint-disable-next-line functional/no-loop-statement - for (const pair of urlParameters.entries()) { - historyStateObject[pair[0]] = pair[1]; - } - window.history.pushState(historyStateObject, document.title, `?${urlParameters.toString()}`); - const br_data = window.br_data || {}; - if (br_data.orig_ref_url !== location.href) { - br_data.orig_ref_url = location.href; - log$2('Generating virtual page view event for url update', location.href); - (_b = (_a = window.BrTrk) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.updateBrData(br_data); - (_d = (_c = window.BrTrk) === null || _c === void 0 ? void 0 : _c.getTracker()) === null || _d === void 0 ? void 0 : _d.logPageView(); - } - } - function updateMultipleInstanceParametersInUrl(parameterName, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - parameters, userOptions) { - const defaultOptions = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - valueSerializer: parameterValue => parameterValue.toString().replace(/"/g, '\\"'), - nameValueSeparator: ':' - }; - const options = Object.assign(Object.assign({}, defaultOptions), userOptions); - const urlParameters = new URLSearchParams(window.location.search); - urlParameters.delete(parameterName); - if (Array.isArray(parameters)) { - parameters.forEach(value => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - urlParameters.append(parameterName, options.valueSerializer(value)); - }); - } else { - Object.keys(parameters).forEach(key => { - urlParameters.append(parameterName, `${key}${options.nameValueSeparator}${options.valueSerializer(parameters[key])}`); - }); - } - updateUrl(urlParameters); - } - function updateParameterInUrl(parameterName, newValue) { - const urlParameters = new URLSearchParams(window.location.search); - if (typeof newValue === 'function') { - urlParameters.set(parameterName, - // @ts-ignore - newValue(urlParameters.get(parameterName)).replace(/"/g, '\\"')); - } else if (newValue === '') { - urlParameters.delete(parameterName); - } else { - urlParameters.set(parameterName, newValue.replace(/"/g, '\\"')); - } - updateUrl(urlParameters); - } - function incrementParameterInUrl(parameterName) { - updateParameterInUrl(parameterName, oldValue => { - if (!oldValue) return '2'; - let newValue = Number.parseInt(oldValue, 10); - return (++newValue).toString(); - }); - } - function decrementParameterInUrl(parameterName) { - updateParameterInUrl(parameterName, oldValue => { - if (!oldValue) return '1'; - let newValue = Number.parseInt(oldValue, 10); - return (--newValue).toString(); - }); - } - function buildPriceUrlParameterObject() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeLowerBoundaryInput = document.querySelector('.blm-price-range-input--lower'); - const priceRangeUpperBoundaryInput = document.querySelector('.blm-price-range-input--upper'); - let lowerBoundary = parseFloat(priceRangeLowerBoundaryInput.value); - let upperBoundary = parseFloat(priceRangeUpperBoundaryInput.value); - if (lowerBoundary === upperBoundary) { - if (upperBoundary === currentSearchRequestState.price_range_max_value) { - lowerBoundary -= 1; - } else { - upperBoundary += 1; - } - } - if (upperBoundary === currentSearchRequestState.price_range_max_value && (Number(lowerBoundary) === 0 || Number(lowerBoundary) === currentSearchRequestState.price_range_min_value)) { - return {}; - } - return { - price: `${lowerBoundary},${upperBoundary}` - }; - } - function getFacetsFromUrl() { - return new URLSearchParams(window.location.search).getAll(PARAMETER_NAME_FACETS).reduce((all, current) => Object.assign(Object.assign({}, all), { - [current.split(':')[0] || '']: (current.split(':')[1] || '').split(',') - }), {}); - } - function getSelectedColors() { - const selectedFacetValues = getFacetsFromUrl(); - return Object.keys(selectedFacetValues).reduce((colors, key) => { - if (key.toLowerCase() === 'color') { - colors = (selectedFacetValues[key] || []).map(color => color.toLowerCase()); - } - return colors; - }, []); - } - - const categoryLinkElementClickListener = event => { - var _a, _b, _c; - event.preventDefault(); - const clickedElement = event.target; - const categoryId = ((_a = clickedElement.dataset) === null || _a === void 0 ? void 0 : _a.categoryId) || ''; - const module = ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.search) || ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category); - if (module) { - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - module.load(categoryId).then(() => { - const autosuggestSearchElement = getAutosuggestSearchInputElement(); - const autosuggestResultsElement = getAutosuggestResultsContainerElement(); - if (autosuggestSearchElement) { - autosuggestSearchElement.value = (clickedElement === null || clickedElement === void 0 ? void 0 : clickedElement.textContent) || ''; - } - if (autosuggestResultsElement) { - autosuggestResultsElement.innerHTML = ''; - } - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - return true; - }).catch(console.error); - } - }; - function addCategoryLinkElementClickListener() { - var _a; - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link--category').forEach(categoryLinkElement => { - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.removeEventListener('click', categoryLinkElementClickListener); - categoryLinkElement === null || categoryLinkElement === void 0 ? void 0 : categoryLinkElement.addEventListener('click', categoryLinkElementClickListener); - }); - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - - function isObject$2(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - var isObject_1 = isObject$2; - - /** Detect free variable `global` from Node.js. */ - - var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; - - var _freeGlobal = freeGlobal$1; - - var freeGlobal = _freeGlobal; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root$2 = freeGlobal || freeSelf || Function('return this')(); - - var _root = root$2; - - var root$1 = _root; - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now$1 = function() { - return root$1.Date.now(); - }; - - var now_1 = now$1; - - /** Used to match a single whitespace character. */ - - var reWhitespace = /\s/; - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace - * character of `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the index of the last non-whitespace character. - */ - function trimmedEndIndex$1(string) { - var index = string.length; - - while (index-- && reWhitespace.test(string.charAt(index))) {} - return index; - } - - var _trimmedEndIndex = trimmedEndIndex$1; - - var trimmedEndIndex = _trimmedEndIndex; - - /** Used to match leading whitespace. */ - var reTrimStart = /^\s+/; - - /** - * The base implementation of `_.trim`. - * - * @private - * @param {string} string The string to trim. - * @returns {string} Returns the trimmed string. - */ - function baseTrim$1(string) { - return string - ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') - : string; - } - - var _baseTrim = baseTrim$1; - - var root = _root; - - /** Built-in value references. */ - var Symbol$2 = root.Symbol; - - var _Symbol = Symbol$2; - - var Symbol$1 = _Symbol; - - /** Used for built-in method references. */ - var objectProto$1 = Object.prototype; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto$1.hasOwnProperty; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString$1 = objectProto$1.toString; - - /** Built-in value references. */ - var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag$1(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; - } - - var _getRawTag = getRawTag$1; - - /** Used for built-in method references. */ - - var objectProto = Object.prototype; - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString$1(value) { - return nativeObjectToString.call(value); - } - - var _objectToString = objectToString$1; - - var Symbol = _Symbol, - getRawTag = _getRawTag, - objectToString = _objectToString; - - /** `Object#toString` result references. */ - var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - - /** Built-in value references. */ - var symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag$1(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - var _baseGetTag = baseGetTag$1; - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - - function isObjectLike$1(value) { - return value != null && typeof value == 'object'; - } - - var isObjectLike_1 = isObjectLike$1; - - var baseGetTag = _baseGetTag, - isObjectLike = isObjectLike_1; - - /** `Object#toString` result references. */ - var symbolTag = '[object Symbol]'; - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol$1(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - var isSymbol_1 = isSymbol$1; - - var baseTrim = _baseTrim, - isObject$1 = isObject_1, - isSymbol = isSymbol_1; - - /** Used as references for various `Number` constants. */ - var NAN = 0 / 0; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Built-in method references without a dependency on `root`. */ - var freeParseInt = parseInt; - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber$1(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject$1(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject$1(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - var toNumber_1 = toNumber$1; - - var isObject = isObject_1, - now = now_1, - toNumber = toNumber_1; - - /** Error message constants. */ - var FUNC_ERROR_TEXT = 'Expected a function'; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeMax = Math.max, - nativeMin = Math.min; - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. 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 debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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's 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 clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - var debounce_1 = debounce; - - debounce_1(event => { - const query = event.target.value; - const searchInputElement = getAutosuggestSearchInputElement(); - if (!searchInputElement) return; - if (query.length >= AUTOSUGGEST_MINIMUM_QUERY_LENGTH) { - searchInputElement.dataset.originalQuery = query; - suggest(query).catch(console.error); - } else { - const autosuggestResultsContainerElement = getAutosuggestResultsContainerElement(); - if (autosuggestResultsContainerElement) { - autosuggestResultsContainerElement.innerHTML = ''; - } - searchInputElement.dataset.originalQuery = ''; - updateCurrentAutosuggestRequestState({ - last_template_data: null - }); - } - }, 500); - - const listeners$2 = new WeakMap(); - const suggestionTermElementClickListener = suggestionTermElement => { - return () => { - var _a, _b; - const { - suggestionText - } = suggestionTermElement.dataset; - const input = getAutosuggestSearchInputElement(); - if (!input) return; - const { - originalQuery - } = input.dataset; - const suggestionData = { - aq: originalQuery, - q: suggestionText, - catalogs: [{ - name: 'example_en' - }] - }; - (_b = (_a = window.BrTrk || {}) === null || _a === void 0 ? void 0 : _a.getTracker()) === null || _b === void 0 ? void 0 : _b.logEvent('suggest', 'click', suggestionData, {}, true); - }; - }; - function addSuggestionTermElementClickListener() { - var _a; - // Apply listeners in re-entrant fashion - (_a = getAutosuggestResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.blm-autosuggest__suggestion-term-link').forEach(suggestionTermElement => { - const listener = suggestionTermElementClickListener(suggestionTermElement); - const old = listeners$2.get(suggestionTermElement); - if (old) suggestionTermElement.removeEventListener('click', old); - listeners$2.set(suggestionTermElement, listener); - suggestionTermElement === null || suggestionTermElement === void 0 ? void 0 : suggestionTermElement.addEventListener('click', listener); - }); - } - - function mapAutosuggestApiResponse(responseData) { - return isV2Response(responseData) ? mapV2Response(responseData) : mapV1Response(responseData); - } - function mapV2Response(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j; - const config = buildAutosuggestConfig(); - const productSuggestions = ((_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.searchSuggestions) || []; - const suggestions = ((_d = (_c = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.querySuggestions) || []; - const categorySuggestions = ((_f = (_e = responseData === null || responseData === void 0 ? void 0 : responseData.suggestionGroups) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.attributeSuggestions) || []; - const mappedApiResponse = Object.assign(Object.assign({}, ((_g = responseData === null || responseData === void 0 ? void 0 : responseData.queryContext) === null || _g === void 0 ? void 0 : _g.originalQuery) ? { - originalQuery: responseData.queryContext.originalQuery - } : {}), { - terms: [...suggestions.map((term, index) => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.query, - displayText: term.displayText, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.query)}` - }), index === 0 && categorySuggestions ? { - categories: categorySuggestions.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.attributeType - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - })].slice(0, (_h = config.autosuggest) === null || _h === void 0 ? void 0 : _h.number_of_terms), - productSuggestions: [...productSuggestions.map(product => Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: Number((product === null || product === void 0 ? void 0 : product.sale_price) || '0') - }))].slice(0, (_j = config.autosuggest) === null || _j === void 0 ? void 0 : _j.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function isV2Response(responseData) { - return 'suggestionGroups' in responseData; - } - function mapV1Response(responseData) { - var _a, _b; - const config = buildAutosuggestConfig(); - const mappedApiResponse = Object.assign(Object.assign({}, responseData.response.q ? { - originalQuery: responseData.response.q - } : {}), { - terms: [...(responseData.response.suggestions ? responseData.response.suggestions.map(term => { - var _a; - return Object.assign(Object.assign(Object.assign({}, term), { - text: term.q, - displayText: term.dq, - link: `${config.search_page_url}?${config.default_search_parameter}=${encodeURIComponent(term.q)}` - }), term.filters ? { - categories: term.filters.map(category => Object.assign(Object.assign({}, category), { - name: category.name, - value: category.value, - type: category.key - })).slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_collections) - } : {}); - }) : [])].slice(0, (_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.number_of_terms), - productSuggestions: [...(responseData.response.products ? responseData.response.products.map(product => Object.assign(Object.assign(Object.assign({}, product), { - id: product.pid, - image: product.thumb_image, - title: product.title, - link: product.url, - sale_price: !Number.isNaN(product.sale_price) ? product.sale_price : !Number.isNaN(product.price) ? product.price : '0' - }), 'price' in product && 'sale_price' in product ? { - price: product.price - } : {})) : [])].slice(0, (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.number_of_products), - config - }); - return highlightQueryInTermLabels(mappedApiResponse); - } - function highlightQueryInTermLabels(results) { - const processedResults = Object.assign({}, results); - results.terms.forEach((term, index) => { - const typedQueryHtml = ejs.render(AUTOSUGGEST_TYPED_QUERY_TEMPLATE, { - query: results.originalQuery - }).trim(); - (processedResults.terms[index] || {}).processedText = term.text.replace(results.originalQuery || '', typedQueryHtml); - }); - return processedResults; - } - - function mapSearchApiResponse(responseData) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - const config = buildSearchConfig(); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ - response: responseData, - autoCorrectQuery: responseData === null || responseData === void 0 ? void 0 : responseData.autoCorrectQuery, - facets: Object.entries(((_a = responseData === null || responseData === void 0 ? void 0 : responseData.facet_counts) === null || _a === void 0 ? void 0 : _a.facet_fields) || {}).map(fieldName => { - return { - original_title: fieldName[0], - title: fieldName[0].replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase()), - section: fieldName[1].map(section => { - if (section.name === 'true') { - section.name = 'Yes'; - } else if (section.name === 'false') { - section.name = 'No'; - } - return { - count: section.count, - name: section.cat_name || section.name, - id: section.cat_id || section.name, - raw: section - }; - }) - }; - }).filter(facet => facet.section.length) - }, ((_c = (_b = responseData === null || responseData === void 0 ? void 0 : responseData.facet_counts) === null || _b === void 0 ? void 0 : _b.facet_ranges) === null || _c === void 0 ? void 0 : _c.price) ? { - priceRanges: responseData.facet_counts.facet_ranges.price.map(range => ({ - count: range.count, - start: range.start.toString(), - end: range.end.toString() - })) - } : {}), ((_e = (_d = responseData === null || responseData === void 0 ? void 0 : responseData.stats) === null || _d === void 0 ? void 0 : _d.stats_fields) === null || _e === void 0 ? void 0 : _e.price) ? { - maxPrice: responseData.stats.stats_fields.price.max, - minPrice: responseData.stats.stats_fields.price.min - } : {}), ((_g = (_f = responseData === null || responseData === void 0 ? void 0 : responseData.stats) === null || _f === void 0 ? void 0 : _f.stats_fields) === null || _g === void 0 ? void 0 : _g.sale_price) ? { - maxPrice: responseData.stats.stats_fields.sale_price.max, - minPrice: responseData.stats.stats_fields.sale_price.min - } : {}), { - products: processDocs(((_h = responseData.response) === null || _h === void 0 ? void 0 : _h.docs) || []) - }), (responseData === null || responseData === void 0 ? void 0 : responseData.group_response) ? { - grouped_products: Object.keys(responseData === null || responseData === void 0 ? void 0 : responseData.group_response).reduce((_, groupCategoryId) => { - var _a, _b, _c, _d; - // Assuming we have only one group category in the group response object - return Object.assign(Object.assign({ - group_category_id: groupCategoryId - }, (_a = responseData.group_response) === null || _a === void 0 ? void 0 : _a[groupCategoryId]), { - groups: ((_d = (_c = (_b = responseData.group_response) === null || _b === void 0 ? void 0 : _b[groupCategoryId]) === null || _c === void 0 ? void 0 : _c.groups) === null || _d === void 0 ? void 0 : _d.map(group => { - var _a; - return { - title: group.groupValue, - products: processDocs(((_a = group === null || group === void 0 ? void 0 : group.doclist) === null || _a === void 0 ? void 0 : _a.docs) || []) - }; - })) || [] - }); - }, {}) - } : {}), { - did_you_mean: responseData.did_you_mean || [], - number_of_results: Number((_j = responseData.response) === null || _j === void 0 ? void 0 : _j.numFound), - start: Number((_k = responseData.response) === null || _k === void 0 ? void 0 : _k.start), - config - }), responseData.keywordRedirect ? { - keywordRedirect: { - original_query: responseData.keywordRedirect['original query'], - redirected_query: responseData.keywordRedirect['redirected query'], - redirected_url: responseData.keywordRedirect['redirected url'] - } - } : {}); - } - function processDocs(docs) { - const config = buildSearchConfig(); - return docs.reduce((allProducts, currentProduct) => { - return [...allProducts, ...(config.search.display_variants ? extractVariants(currentProduct) : [transformProductResponseToProductData(currentProduct)])]; - }, []); - } - function extractVariants(productResponse) { - if (!productResponse.variants || !productResponse.variants.length) { - return [transformProductResponseToProductData(productResponse)]; - } - return (transformProductResponseToProductData(productResponse).variants || []).map((variant, index) => Object.assign(Object.assign(Object.assign({}, transformProductResponseToProductData(productResponse)), variant), { - variant_index: index - })); - } - function transformProductResponseToProductData(productResponse) { - return Object.assign(Object.assign(Object.assign({}, productResponse), { - title: productResponse.title, - image: productResponse.thumb_image, - link: productResponse.url, - id: productResponse.pid, - price: productResponse.price, - sale_price: productResponse.sale_price - }), productResponse.variants ? { - variants: productResponse.variants.map(variant => Object.assign(Object.assign({}, variant), { - sku_color_group: variant.sku_color_group, - sku_swatch_images: variant.sku_swatch_images, - sku_thumb_images: variant.sku_thumb_images, - sku_sale_price: variant.sku_sale_price, - sku_price: variant.sku_price, - image: variant.sku_thumb_images && Array.isArray(variant.sku_thumb_images) ? variant.sku_thumb_images[0] : variant.sku_swatch_images[0], - variant_name: variant.sku_color_group - })) - } : {}); - } - - const log$1 = Debug('br:autosuggest'); - /** - * Retrieves suggestions from the suggest API and renders them to the DOM. - */ - async function suggest(query) { - var _a, _b, _c; - log$1('Fetching suggestions for', query); - const config = buildAutosuggestConfig(); - updateCurrentAutosuggestRequestState({ - request_id: generateRequestId() - }); - const apiCallParameters = buildApiCallParameters$1(query); - // todo remediate typescript issue - // @ts-ignore - const results = await getSuggestions(apiCallParameters); - const templateData = mapAutosuggestApiResponse(results); - updateCurrentAutosuggestRequestState({ - last_template_data: templateData - }); - const container = getAutosuggestResultsContainerElement(); - if (!container) return; - log$1.verbose('Using config', config); - log$1.verbose('Render to:', container); - log$1.verbose('Is using default template?', !((_a = config.autosuggest) === null || _a === void 0 ? void 0 : _a.template)); - log$1.verbose('Rendering with template:', { - template: ((_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.template) || autosuggestTemplate, - templateData - }); - container.innerHTML = ejs.render(((_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.template) || autosuggestTemplate, templateData); - addCategoryLinkElementClickListener(); - addSuggestionTermElementClickListener(); - } - /** - * Generates the API paramters fed into the suggest API call body. - */ - function buildApiCallParameters$1(query) { - var _a, _b, _c; - const config = buildAutosuggestConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentAutosuggestRequestState = getCurrentAutosuggestRequestState(); - const apiParameters = Object.assign(Object.assign({}, ((_a = config === null || config === void 0 ? void 0 : config.autosuggest) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.autosuggest.endpoint - } : {}), { - q: query || urlParameters.get((config === null || config === void 0 ? void 0 : config.default_search_parameter) || '') || '', - aq: query, - sort: (_b = config.autosuggest) === null || _b === void 0 ? void 0 : _b.sort, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentAutosuggestRequestState.request_id, - _br_uid_2: config.tracking_cookie, - ref_url: config.ref_url, - url: config.url, - request_type: config.request_type, - catalog_views: (_c = config.autosuggest) === null || _c === void 0 ? void 0 : _c.catalog_views, - search_type: 'keyword' - }); - if (!apiParameters.catalog_views) { - apiParameters.catalog_views = ''; - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === undefined) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function getCurrentAutosuggestRequestState() { - return window.BloomreachModules.autosuggest.getCurrentAutosuggestRequestState(); - } - function updateCurrentAutosuggestRequestState(state) { - window.BloomreachModules.autosuggest.setCurrentAutosuggestRequestState(Object.assign(Object.assign({}, getCurrentAutosuggestRequestState()), state)); - } - - Debug('br:product-events'); - - Debug('br:recommendations'); - - const clearPriceRangeValueButtonClickListener = () => { - resetLoadingIndicator(); - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign({}, getCheckedFacetValues())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - updateCurrentSearchRequestState({ - price_range_max_value: 0, - price_range_min_value: 0 - }); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addClearPriceRangeValueButtonClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeValueClearButton = document.querySelector(`.blm-range-slider__clear-values-button--${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeValueClearButton) { - priceRangeValueClearButton.removeEventListener('click', clearPriceRangeValueButtonClickListener); - priceRangeValueClearButton.addEventListener('click', clearPriceRangeValueButtonClickListener); - } - } - function removeClearPriceRangeValueButtonClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeValueClearButton = document.querySelector(`.blm-range-slider__clear-values-button--${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeValueClearButton) { - priceRangeValueClearButton.removeEventListener('click', clearPriceRangeValueButtonClickListener); - } - } - - const clearSelectedFacetButtonClickListener = event => { - var _a, _b, _c, _d; - const checkboxId = (_c = (_b = (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.filterCheckboxId; - if (checkboxId) { - (_d = document.getElementById(checkboxId)) === null || _d === void 0 ? void 0 : _d.click(); - } - }; - function addClearSelectedFacetButtonClickListener() { - const clearSelectedFacetButtons = document.querySelectorAll('.blm-product-search-selected-filter__clear'); - // Apply listeners in re-entrant fashion - clearSelectedFacetButtons.forEach(button => { - button === null || button === void 0 ? void 0 : button.removeEventListener('click', clearSelectedFacetButtonClickListener); - button === null || button === void 0 ? void 0 : button.addEventListener('click', clearSelectedFacetButtonClickListener); - }); - } - function removeClearSelectedFacetButtonClickListener() { - const clearSelectedFacetButtons = document.querySelectorAll('.blm-product-search-selected-filter__clear'); - // Apply listeners in re-entrant fashion - clearSelectedFacetButtons.forEach(button => { - button === null || button === void 0 ? void 0 : button.removeEventListener('click', clearSelectedFacetButtonClickListener); - }); - } - - const clearAllSelectedFacetsButtonClickListener = () => { - resetLoadingIndicator(); - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign({}, buildPriceUrlParameterObject())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addClearAllSelectedFacetsButtonClickListener() { - const selectedFiltersClearAllButton = document.querySelector('.blm-product-search-selected-filters__clear-all'); - // Apply listeners in re-entrant fashion - if (selectedFiltersClearAllButton) { - selectedFiltersClearAllButton.removeEventListener('click', clearAllSelectedFacetsButtonClickListener); - selectedFiltersClearAllButton.addEventListener('click', clearAllSelectedFacetsButtonClickListener); - } - } - function removeClearAllSelectedFacetsButtonClickListener() { - const selectedFiltersClearAllButton = document.querySelector('.blm-product-search-selected-filters__clear-all'); - // Apply listeners in re-entrant fashion - if (selectedFiltersClearAllButton) { - selectedFiltersClearAllButton.removeEventListener('click', clearAllSelectedFacetsButtonClickListener); - } - } - - const facetCheckboxChangeListener = () => { - resetLoadingIndicator(); - /* - If the checkedFacets is - { colors: ["gray", "black"], reviews: ["4.7", "5.0"] } - then we're setting these values in the URL in this format: - &fq=colors%3Agray%2Cblack&fq=reviews%3A4.7%2C5.0 - because it's easier to read it like that when we're performing the search, - than it would be if we'd store it in the format how we're using them - in the API call's URL parameter list - */ - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign(Object.assign({}, getCheckedFacetValues()), buildPriceUrlParameterObject())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addFacetCheckboxChangeListener() { - const facetCheckboxes = document.querySelectorAll('.blm-product-search-filter-item__checkbox'); - // Apply listeners in re-entrant fashion - if (facetCheckboxes) { - facetCheckboxes.forEach(checkbox => { - checkbox === null || checkbox === void 0 ? void 0 : checkbox.removeEventListener('change', facetCheckboxChangeListener); - checkbox === null || checkbox === void 0 ? void 0 : checkbox.addEventListener('change', facetCheckboxChangeListener); - }); - } - } - function removeFacetCheckboxChangeListener() { - const facetCheckboxes = document.querySelectorAll('.blm-product-search-filter-item__checkbox'); - // Apply listeners in re-entrant fashion - if (facetCheckboxes) { - facetCheckboxes.forEach(checkbox => { - checkbox === null || checkbox === void 0 ? void 0 : checkbox.removeEventListener('change', facetCheckboxChangeListener); - }); - } - } - - const facetSearchInputChangeListener = debounce_1(event => { - var _a; - const inputValue = (((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) || '').trim(); - document.querySelectorAll('.blm-dynamic-filter').forEach(facetBox => { - let displayedItems = 0; - facetBox.querySelectorAll('.blm-product-search-filter-item').forEach(facetItem => { - var _a; - const label = ((_a = facetItem.querySelector('label')) === null || _a === void 0 ? void 0 : _a.textContent) || ''; - const shouldDisplay = !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()); - const displayStyle = shouldDisplay ? 'block' : 'none'; - displayedItems += shouldDisplay ? 1 : 0; - facetItem.style.display = displayStyle; - }); - facetBox.style.display = displayedItems ? 'block' : 'none'; - }); - document.querySelectorAll('.blm-product-search-load-more').forEach(loadMoreLink => { - loadMoreLink.style.display = 'none'; - }); - const groupsELement = getLoadMoreFacetGroupsElement(); - if (!groupsELement) return; - groupsELement.style.display = 'none'; - if (!inputValue) { - resetFacetGroups(); - } - }, 500); - function addFacetSearchInputChangeListener() { - const facetSearchInput = document.querySelector('#blm-product-search-search-filters__input'); - // Apply listeners in re-entrant fashion - if (facetSearchInput) { - facetSearchInput.removeEventListener('input', facetSearchInputChangeListener); - facetSearchInput.addEventListener('input', facetSearchInputChangeListener); - } - } - function removeFacetSearchInputChangeListener() { - const facetSearchInput = document.querySelector('#blm-product-search-search-filters__input'); - // Apply listeners in re-entrant fashion - if (facetSearchInput) { - facetSearchInput.removeEventListener('input', facetSearchInputChangeListener); - } - } - - const groupbySelectChangeListener = event => { - var _a; - updateParameterInUrl(PARAMETER_NAME_GROUPBY, (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value); - resetLoadingIndicator(); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addGroupbySelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const groupbySelector = document.querySelector(`#groupby-${currentSearchRequestState === null || currentSearchRequestState === void 0 ? void 0 : currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (groupbySelector) { - groupbySelector.removeEventListener('change', groupbySelectChangeListener); - groupbySelector.addEventListener('change', groupbySelectChangeListener); - } - } - function removeGroupbySelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const groupbySelector = document.querySelector(`#groupby-${currentSearchRequestState === null || currentSearchRequestState === void 0 ? void 0 : currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (groupbySelector) { - groupbySelector.removeEventListener('change', groupbySelectChangeListener); - } - } - - const loadMoreFacetGroupsButtonClickListener = () => { - loadMoreFacetGroups(); - }; - function addLoadMoreFacetGroupsButtonClickListener() { - const element = getLoadMoreFacetGroupsElement(); - // Apply listeners in re-entrant fashion - element === null || element === void 0 ? void 0 : element.removeEventListener('click', loadMoreFacetGroupsButtonClickListener); - element === null || element === void 0 ? void 0 : element.addEventListener('click', loadMoreFacetGroupsButtonClickListener); - } - function removeLoadMoreFacetGroupsButtonClickListener() { - const element = getLoadMoreFacetGroupsElement(); - // Apply listeners in re-entrant fashion - element === null || element === void 0 ? void 0 : element.removeEventListener('click', loadMoreFacetGroupsButtonClickListener); - } - - // Our listeners have item specific context so we need to be able to reference - // the generated closure for each item, but we can not let the closure or item - // reference leak. So we use a weakmap so the listener will naturally die when - // the the item is garbage collected. - const listeners$1 = new WeakMap(); - const loadMoreFacetValuesButtonClickListener = () => { - var _a; - const config = buildSearchConfig(); - const numberOfDisplayedFacetValues = Number((_a = config.search) === null || _a === void 0 ? void 0 : _a.initial_number_of_facet_values); - let showFilterItems = numberOfDisplayedFacetValues; - const incrementFilterBy = numberOfDisplayedFacetValues; - return event => { - const itemIndex = event.target.getAttribute('data-item'); - const facetBlock = document.getElementById(`blm-facet-block-item-${itemIndex}`); - const filterListItems = facetBlock.getElementsByTagName('li'); - // eslint-disable-next-line functional/no-loop-statement - for (let i = showFilterItems; i < showFilterItems + incrementFilterBy; i++) { - if (filterListItems[i]) { - filterListItems[i].style.display = 'block'; - } - } - showFilterItems += incrementFilterBy; - if (showFilterItems >= filterListItems.length) { - event.target.style.display = 'none'; - } - }; - }; - function addLoadMoreFacetValuesButtonClickListener() { - document.querySelectorAll('.blm-product-search-load-more').forEach(item => { - // Apply listeners in re-entrant fashion - const old = listeners$1.get(item); - if (old) item.removeEventListener('click', old); - const listener = listeners$1.get(item) || loadMoreFacetValuesButtonClickListener(); - listeners$1.set(item, listener); - item.addEventListener('click', listener); - }); - } - function removeLoadMoreFacetValuesButtonClickListener() { - document.querySelectorAll('.blm-product-search-load-more').forEach(item => { - // Apply listeners in re-entrant fashion - const old = listeners$1.get(item); - if (old) item.removeEventListener('click', old); - }); - } - - const pageSizeSelectChangeListener = event => { - updateParameterInUrl(PARAMETER_NAME_SIZE, event.target.value); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - resetLoadingIndicator(); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addPageSizeSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to page size select field changes - const sizeSelector = document.querySelector(`#sort-size-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sizeSelector) { - sizeSelector.removeEventListener('change', pageSizeSelectChangeListener); - sizeSelector.addEventListener('change', pageSizeSelectChangeListener); - } - } - function removePageSizeSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to page size select field changes - const sizeSelector = document.querySelector(`#sort-size-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sizeSelector) { - sizeSelector.removeEventListener('change', pageSizeSelectChangeListener); - } - } - - const paginationContainerClickListener = event => { - resetLoadingIndicator(); - const clickedPaginationValue = event.target.dataset.value; - if (clickedPaginationValue) { - switch (event.target.dataset.value) { - case 'previous': - decrementParameterInUrl(PARAMETER_NAME_PAGE); - break; - case 'next': - incrementParameterInUrl(PARAMETER_NAME_PAGE); - break; - default: - updateParameterInUrl(PARAMETER_NAME_PAGE, clickedPaginationValue); - } - initiateSearch({ - toReplace: true - }).catch(console.error); - } - }; - function addPaginationContainerClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to pagination events - const paginationContainer = document.querySelector(`.blm-product-search-pagination__pages--${currentSearchRequestState.request_id}`); - if (!paginationContainer) return; - // Apply listeners in re-entrant fashion - paginationContainer.removeEventListener('click', paginationContainerClickListener); - paginationContainer.addEventListener('click', paginationContainerClickListener); - } - function removePaginationContainerClickListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - // Listen to pagination events - const paginationContainer = document.querySelector(`.blm-product-search-pagination__pages--${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - paginationContainer === null || paginationContainer === void 0 ? void 0 : paginationContainer.removeEventListener('click', paginationContainerClickListener); - } - - const priceRangeChangeListener = () => { - resetLoadingIndicator(); - updateMultipleInstanceParametersInUrl(PARAMETER_NAME_FACETS, Object.assign(Object.assign({}, getCheckedFacetValues()), buildPriceUrlParameterObject())); - updateParameterInUrl(PARAMETER_NAME_PAGE, '1'); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addPriceRangeChangeListeners() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeLowerBoundaryInput = document.querySelector(`.blm-price-range-input--lower-${currentSearchRequestState.request_id}`); - const priceRangeUpperBoundaryInput = document.querySelector(`.blm-price-range-input--upper-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeLowerBoundaryInput && priceRangeUpperBoundaryInput) { - priceRangeLowerBoundaryInput.removeEventListener('change', priceRangeChangeListener); - priceRangeLowerBoundaryInput.addEventListener('change', priceRangeChangeListener); - priceRangeUpperBoundaryInput.removeEventListener('change', priceRangeChangeListener); - priceRangeUpperBoundaryInput.addEventListener('change', priceRangeChangeListener); - } - } - function removePriceRangeChangeListeners() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const priceRangeLowerBoundaryInput = document.querySelector(`.blm-price-range-input--lower-${currentSearchRequestState.request_id}`); - const priceRangeUpperBoundaryInput = document.querySelector(`.blm-price-range-input--upper-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (priceRangeLowerBoundaryInput && priceRangeUpperBoundaryInput) { - priceRangeLowerBoundaryInput.removeEventListener('change', priceRangeChangeListener); - priceRangeUpperBoundaryInput.removeEventListener('change', priceRangeChangeListener); - } - } - - const contexts = new WeakMap(); - const intersectionListener = config => { - return entries => { - var _a; - const first = entries[0]; - if (!first || first.intersectionRatio <= 0) { - return; - } - const connectorConfigObject = ((_a = window === null || window === void 0 ? void 0 : window.bloomreachConnector) === null || _a === void 0 ? void 0 : _a.config) || {}; - const currentStart = connectorConfigObject.start || 0; - connectorConfigObject.start = currentStart + config.search.items_per_page; - incrementParameterInUrl(PARAMETER_NAME_PAGE); - initiateSearch().catch(error => { - decrementParameterInUrl(PARAMETER_NAME_PAGE); - console.error(error); - }); - }; - }; - function addScrollListener() { - var _a, _b; - const config = buildSearchConfig(); - if (((_a = config.search) === null || _a === void 0 ? void 0 : _a.infinite_scroll) && !document.querySelector('.blm-scroll-indicator')) { - // Add listeners in re-entrant fashion - const searchResultsContainerElement = getSearchResultsContainerElement(); - const ctx = contexts.get(searchResultsContainerElement) || {}; - // Clean out old ctx so we don't duplocate anything - removeScrollListener(); - const indicatorElement = document.createElement('div'); - indicatorElement.classList.add('blm-scroll-indicator'); - const loaderElement = document.createElement('div'); - loaderElement.classList.add('blm-scroll-indicator__loading'); - indicatorElement.appendChild(loaderElement); - (_b = searchResultsContainerElement === null || searchResultsContainerElement === void 0 ? void 0 : searchResultsContainerElement.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(indicatorElement, searchResultsContainerElement.nextSibling); - const scrollIndicator = document.querySelector('.blm-scroll-indicator'); - const intersectionObserver = new IntersectionObserver(intersectionListener(config)); - ctx.observer = intersectionObserver; - ctx.indicator = indicatorElement; - if (scrollIndicator) { - intersectionObserver.observe(scrollIndicator); - } - } - } - function removeScrollListener() { - var _a, _b; - const searchResultsContainerElement = getSearchResultsContainerElement(); - const ctx = contexts.get(searchResultsContainerElement) || {}; - // Clean out old ctx - if (ctx) { - (_a = ctx.observer) === null || _a === void 0 ? void 0 : _a.disconnect(); - (_b = ctx.indicator) === null || _b === void 0 ? void 0 : _b.remove(); - } - } - - const sidebarControlButtonClickHandler = () => { - const sidebarContentElement = document.querySelector('.blm-product-search-sidebar-content'); - if (sidebarContentElement === null || sidebarContentElement === void 0 ? void 0 : sidebarContentElement.classList.contains('blm-open')) { - sidebarContentElement === null || sidebarContentElement === void 0 ? void 0 : sidebarContentElement.classList.remove('blm-open'); - document.body.classList.remove('blm-out-of-view'); - updateParameterInUrl(PARAMETER_NAME_FILTERS_PANEL, ''); - } else { - document.body.classList.add('blm-out-of-view'); - sidebarContentElement === null || sidebarContentElement === void 0 ? void 0 : sidebarContentElement.classList.add('blm-open'); - updateParameterInUrl(PARAMETER_NAME_FILTERS_PANEL, 'on'); - } - }; - function addSidebarControlButtonClickListener() { - const sidebarControlButtons = document.querySelectorAll('.blm-product-search-control-button--sidebar'); - // Apply listeners in re-entrant fashion - sidebarControlButtons.forEach(button => { - button.removeEventListener('click', sidebarControlButtonClickHandler); - button.addEventListener('click', sidebarControlButtonClickHandler); - }); - } - function removeSidebarControlButtonClickListener() { - const sidebarControlButtons = document.querySelectorAll('.blm-product-search-control-button--sidebar'); - // Apply listeners in re-entrant fashion - sidebarControlButtons.forEach(button => { - button.removeEventListener('click', sidebarControlButtonClickHandler); - }); - } - - const sortSelectChangeListener = event => { - var _a; - updateParameterInUrl(PARAMETER_NAME_SORT, (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value); - resetLoadingIndicator(); - initiateSearch({ - toReplace: true - }).catch(console.error); - }; - function addSortSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const sortSelector = document.querySelector(`#sort-by-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sortSelector) { - sortSelector.removeEventListener('change', sortSelectChangeListener); - sortSelector.addEventListener('change', sortSelectChangeListener); - } - } - function removeSortSelectChangeListener() { - const currentSearchRequestState = getCurrentSearchRequestState(); - const sortSelector = document.querySelector(`#sort-by-${currentSearchRequestState.request_id}`); - // Apply listeners in re-entrant fashion - if (sortSelector) { - sortSelector.removeEventListener('change', sortSelectChangeListener); - } - } - - const listeners = new WeakMap(); - const swatchElementHoverListener = dependencies => { - const { - result, - swatchItems, - swatchIndex - } = dependencies; - return event => { - swatchItems.forEach(swatchItem => { - swatchItem.classList.remove('active'); - }); - event.target.classList.add('active'); - // Update image - const imageContainer = result.querySelectorAll('.blm-product-search-image-container'); - imageContainer.forEach(imageItems => { - imageItems.querySelectorAll('.blm-product-search-swatch-image').forEach((image, i) => { - image.style.display = 'none'; - if (swatchIndex === i) { - image.style.display = 'block'; - } - }); - }); - // Update price - result.querySelectorAll('.blm-product-search-details-container__price').forEach((price, index) => { - price.classList.remove('active'); - if (swatchIndex === index) { - price.classList.add('active'); - } - }); - }; - }; - function addSwatchElementHoverListener() { - document.querySelectorAll('.blm-product-search__result').forEach(result => { - const swatchContainers = result.querySelectorAll('.blm-product-search-swatch-container'); - swatchContainers.forEach(swatchContainer => { - const swatchItems = swatchContainer.querySelectorAll('.blm-product-search-swatch-container__swatch'); - // Apply listeners in re-entrant fashion - swatchItems.forEach((swatchItem, swatchIndex) => { - const old = listeners.get(swatchItem); - if (old) swatchItem.removeEventListener('mouseover', old); - const listener = swatchElementHoverListener({ - result, - swatchItems, - swatchIndex - }); - listeners.set(swatchItem, listener); - swatchItem.addEventListener('mouseover', listener); - }); - }); - }); - } - function removeSwatchElementHoverListener() { - document.querySelectorAll('.blm-product-search__result').forEach(result => { - const swatchContainers = result.querySelectorAll('.blm-product-search-swatch-container'); - swatchContainers.forEach(swatchContainer => { - const swatchItems = swatchContainer.querySelectorAll('.blm-product-search-swatch-container__swatch'); - // Apply listeners in re-entrant fashion - swatchItems.forEach(swatchItem => { - const old = listeners.get(swatchItem); - if (old) swatchItem.removeEventListener('mouseover', old); - }); - }); - }); - } - - const log = Debug('br:search'); - function buildDefaultSearchRequestState(options) { - const { - isCategoryPage - } = options; - return { - request_id: 0, - price_range_max_value: 0, - price_range_min_value: 0, - is_first_request: true, - is_category_page: isCategoryPage, - category_to_load: '', - pollIntervalId: void 0, - currentElement: null - }; - } - function buildProductSearchModule({ - isCategoryPage - } = { - isCategoryPage: false - }) { - var _a, _b, _c; - log('Build Search Module:', '4.0.0'); - let currentSearchRequestState = buildDefaultSearchRequestState({ - isCategoryPage - }); - // Provide module compatibility errors - if (isCategoryPage) { - // If we see a search module and no category module, we can assume the - // search module loaded already. - if (((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) && !((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) { - console.warn('Search and catalog modules are not compatible with each other at this time. Please only load one of them. Undefined behavior may occur.'); - } - // If a catalog module is loaded, this search module may have issues. - } else if ((_c = window.BloomreachModules) === null || _c === void 0 ? void 0 : _c.category) { - console.warn('Search and catalog modules are not compatible with each other at this time. Please only load one of them. Undefined behavior may occur.'); - } - return { - setCurrentSearchRequestState: requestState => { - currentSearchRequestState = requestState; - }, - getCurrentSearchRequestState: () => currentSearchRequestState, - load: async categoryToLoad => { - await initPolling(isCategoryPage, categoryToLoad); - } - }; - } - async function initPolling(isCategoryPage = false, categoryToLoad) { - let state = getCurrentSearchRequestState(); - window.clearInterval(state.pollIntervalId); - const doPoll = async () => { - state = getCurrentSearchRequestState(); - const currentElement = state.currentElement; - const foundElement = getSearchResultsContainerElement(); - if (currentElement && !foundElement) { - // Teardown this module to put it in a waiting state - updateCurrentSearchRequestState({ - currentElement: null - }); - moduleWillUnmount(); - } else if (!currentElement && foundElement) { - updateCurrentSearchRequestState({ - currentElement: foundElement - }); - await moduleWillMount(isCategoryPage, categoryToLoad); - } - }; - if (!state.pollIntervalId) log('Polling initialized'); - // Begin the polling service. - // eslint-disable-next-line @typescript-eslint/no-misused-promises - const pollTimer = window.setInterval(doPoll, 100); - updateCurrentSearchRequestState({ - pollIntervalId: pollTimer - }); - // We execute the poll immediately so if we have a script that is "smarter" - // about when all conditions are ready for the module, there is a path to have - // an immediate initialization. - await doPoll(); - } - function moduleWillUnmount() { - var _a, _b; - log('Umounting module...'); - const state = getCurrentSearchRequestState(); - (_a = state.afterLoadedObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); - (_b = getSearchResultsContainerElement()) === null || _b === void 0 ? void 0 : _b.classList.remove('blm-has-loaded'); - unmountSaveScrollPosition(); - removeScrollListener(); - // eslint-disable-next-line @typescript-eslint/no-misused-promises - window.removeEventListener('popstate', popStateWindowEvent); - removePriceRangeChangeListeners(); - removeClearPriceRangeValueButtonClickListener(); - removeClearSelectedFacetButtonClickListener(); - removeClearAllSelectedFacetsButtonClickListener(); - removeSidebarControlButtonClickListener(); - removeFacetCheckboxChangeListener(); - removeLoadMoreFacetGroupsButtonClickListener(); - removeLoadMoreFacetValuesButtonClickListener(); - removeFacetSearchInputChangeListener(); - removePageSizeSelectChangeListener(); - removeSortSelectChangeListener(); - removeGroupbySelectChangeListener(); - removePaginationContainerClickListener(); - removeSwatchElementHoverListener(); - } - async function moduleWillMount(isCategoryPage = false, categoryToLoad) { - log('Mounting module...'); - if (isCategoryPage && categoryToLoad) { - updateCurrentSearchRequestState({ - category_to_load: categoryToLoad - }); - } - if (!areRequirementsMet()) { - log('Search/Category module requirements aren\'t met.'); - return; - } - storeSegmentationPixelData(); - // Add mutation observer on container, - // so it needs to be here before the first actual API call - afterElementsLoaded(() => { - var _a; - log('Search/Category module\'s content has loaded.'); - // Add a class to show that the module's content has loaded - (_a = getSearchResultsContainerElement()) === null || _a === void 0 ? void 0 : _a.classList.add('blm-has-loaded'); - setupSavingScrollPosition(); - // If infinite scroll is on then add intersection observer - addScrollListener(); - addChangeListeners(); - }); - // Initiate search with config values and URL parameters - await initiateSearch(); - restoreScrollPosition(); - } - function areRequirementsMet() { - var _a; - const config = buildSearchConfig(); - invariant(config.account_id, 'account_id must be set'); - invariant(config.domain_key, 'domain_key must be set'); - invariant(config.default_search_parameter, 'default_search_parameter must be set'); - invariant((_a = config === null || config === void 0 ? void 0 : config.search) === null || _a === void 0 ? void 0 : _a.selector, 'the selector of search results container element must be set'); - // this checks if the element is in the DOM - getSearchResultsContainerElement(); - const urlParameters = new URLSearchParams(window.location.search); - const searchPageHasQueryToLoad = config.search.is_search_page && urlParameters.has(config.default_search_parameter); - const categoryPageHasCategoryToLoad = config.search.is_category_page && (urlParameters.has(config.default_search_parameter) || config.search.category_id); - return searchPageHasQueryToLoad || categoryPageHasCategoryToLoad; - } - function storeSegmentationPixelData() { - const segmentationData = extractSegmentationCookie(); - if (segmentationData) { - const br_data = window.br_data || {}; - br_data[COOKIE_NAME_SEGMENTATION_CDP_SEGMENTS] = segmentationData; - } - } - async function initiateSearch(options = { - toReplace: false - }) { - var _a, _b, _c, _d; - log('Initiate Search'); - const requestContextId = generateRequestId(); - updateCurrentSearchRequestState({ - request_id: requestContextId - }); - const config = buildSearchConfig(); - const apiCallParameters = buildApiCallParameters(); - log('Fetch search results with params:', apiCallParameters); - const response = await getSearchResults(apiCallParameters); - log('Search results:', response); - // We need to make sure overlapping calls to initiateSearch don't cause race - // conditions, so this pattern discards the earliest requests made and only - // allows the most recent request to pass - if (requestContextId !== getCurrentSearchRequestState().request_id) { - return; - } - if (response === null || response === void 0 ? void 0 : response.keywordRedirect) { - applyKeywordRedirection(response); - return; - } - // Builds template data - const templateData = buildTemplateData(response); - // Takes care of scroll loader - const scrollLoader = document.querySelector('.blm-scroll-indicator__loading'); - const notEnoughProducts = (templateData === null || templateData === void 0 ? void 0 : templateData.grouped_products) ? (((_a = templateData === null || templateData === void 0 ? void 0 : templateData.grouped_products) === null || _a === void 0 ? void 0 : _a.groups) || []).length < Number(apiCallParameters.rows) : !templateData.products.length || templateData.number_of_results < Number(apiCallParameters.rows); - if (scrollLoader && notEnoughProducts) { - scrollLoader.remove(); - decrementParameterInUrl(PARAMETER_NAME_PAGE); - } - const currentSearchRequestState = getCurrentSearchRequestState(); - if (currentSearchRequestState.is_first_request || !config.search.infinite_scroll || options.toReplace) { - const container = getSearchResultsContainerElement(); - if (container) { - log('Render with data: ', templateData); - container.innerHTML = ejs.render((((_b = config.search) === null || _b === void 0 ? void 0 : _b.template) || '').replace('%%-PRODUCT_LIST_TEMPLATE-%%', ((_c = config.search) === null || _c === void 0 ? void 0 : _c.product_list_template) || '').replace(/%%-REQUEST_ID-%%/g, currentSearchRequestState.request_id.toString()), templateData); - window.scrollTo(0, 0); - } - } else if (config.search.infinite_scroll) { - const resultElements = ejs.render(((_d = config.search) === null || _d === void 0 ? void 0 : _d.product_list_template) || '', templateData); - getSearchResultsListContainerElement().insertAdjacentHTML('beforeend', resultElements); - } - // Reapply listeners - addChangeListeners(); - // adds swatch hover listener to newly added elements as well - addSwatchElementHoverListener(); - // marks as initial call happened - updateCurrentSearchRequestState({ - is_first_request: false - }); - } - /** - * Attempts to get the search request state from the existing module - */ - function getCurrentSearchRequestState() { - var _a, _b, _c; - return ((_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.getCurrentSearchRequestState()) || buildDefaultSearchRequestState({ - isCategoryPage: false - }); - } - function updateCurrentSearchRequestState(state) { - var _a, _b, _c; - (_c = ((_a = window.BloomreachModules) === null || _a === void 0 ? void 0 : _a.search) || ((_b = window.BloomreachModules) === null || _b === void 0 ? void 0 : _b.category)) === null || _c === void 0 ? void 0 : _c.setCurrentSearchRequestState(Object.assign(Object.assign({}, getCurrentSearchRequestState()), state)); - } - function afterElementsLoaded(afterLoadCallback) { - const state = getCurrentSearchRequestState(); - const searchElement = getSearchResultsContainerElement(); - // Clear out existing observers to make this method re-entrant. - if (state.afterLoadedObserver) { - state.afterLoadedObserver.disconnect(); - } - // Early exit if the element does not exist so we don't cause errors - if (!searchElement) { - return; - } - // Perform start up check to see if elements already exists, if they do we do - // not need mutation observation - const existingNodes = searchElement.querySelector('.blm-results'); - if (existingNodes) { - afterLoadCallback(); - return; - } - // Without the Element existing, we now watch the entry DOM node for mutations - // until the required elements are added - let observer = void 0; - const mutationObserverCallback = mutationsList => { - const productListAdded = mutationsList.find(mutationRecord => mutationRecord.type === 'childList' && Array.from(mutationRecord.addedNodes).find(node => node.classList && node.classList.contains('blm-results'))); - if (productListAdded) { - // Here we can be sure that the template is rendered into the DOM - afterLoadCallback(); - // Stop the observer - observer === null || observer === void 0 ? void 0 : observer.disconnect(); - } - }; - observer = new MutationObserver(mutationObserverCallback); - observer.observe(searchElement, { - childList: true, - subtree: true - }); - } - async function popStateWindowEvent() { - await initiateSearch({ - toReplace: true - }); - } - function addChangeListeners() { - // When we're going back in history, we want to initiate - // eslint-disable-next-line @typescript-eslint/no-misused-promises - window.removeEventListener('popstate', popStateWindowEvent); - // eslint-disable-next-line @typescript-eslint/no-misused-promises - window.addEventListener('popstate', popStateWindowEvent); - addPriceRangeChangeListeners(); - addClearPriceRangeValueButtonClickListener(); - addClearSelectedFacetButtonClickListener(); - addClearAllSelectedFacetsButtonClickListener(); - if (document.querySelector('.blm-product-search-sidebar')) { - addSidebarControlButtonClickListener(); - addFacetCheckboxChangeListener(); - addLoadMoreFacetGroupsButtonClickListener(); - addLoadMoreFacetValuesButtonClickListener(); - addFacetSearchInputChangeListener(); - // Show the initial number of facets on load - resetFacetGroups(); - } - addPageSizeSelectChangeListener(); - addSortSelectChangeListener(); - addGroupbySelectChangeListener(); - addPaginationContainerClickListener(); - addSwatchElementHoverListener(); - } - function buildTemplateData(response) { - var _a; - const config = buildSearchConfig(); - // map values from API response - const templateData = mapSearchApiResponse(response); - // add stored keyword redirection info - const storedKeywordRedirect = JSON.parse(localStorage.getItem('keywordRedirect') || '{}'); - if (storedKeywordRedirect === null || storedKeywordRedirect === void 0 ? void 0 : storedKeywordRedirect.redirected_query) { - templateData.keywordRedirect = storedKeywordRedirect; - localStorage.removeItem('keywordRedirect'); - } - const urlParameters = new URLSearchParams(window.location.search); - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - if (!Object.keys(templateData).includes(key)) { - templateData[key] = value; - } - } - if (urlParameters.has(PARAMETER_NAME_SIZE)) { - templateData.size = Number.parseInt(urlParameters.get(PARAMETER_NAME_SIZE) || '', 10); - } else { - templateData.size = Number.parseInt(config.search.items_per_page.toString(), 10); - } - templateData.checkedFacets = getFacetsFromUrl(); - templateData.selectedFilterItems = ((templateData === null || templateData === void 0 ? void 0 : templateData.facets) || []).reduce((all, facet) => { - if (facet.section.length > 0) { - facet.section.forEach(item => { - var _a, _b, _c; - if (templateData.checkedFacets && facet.original_title in templateData.checkedFacets && ((_c = (_b = (_a = templateData.checkedFacets) === null || _a === void 0 ? void 0 : _a[facet.original_title]) === null || _b === void 0 ? void 0 : _b.includes) === null || _c === void 0 ? void 0 : _c.call(_b, escapeSpecialCharacters(item.id)))) { - (all || []).push({ - checkbox_id: `${facet.original_title}[${escapeSpecialCharacters(item.name)}]`, - label: item.name - }); - } - }); - } - return all; - }, []); - let currentSearchRequestState = getCurrentSearchRequestState(); - // This fixes the price range facet when the facet has no valid range - if ('minPrice' in templateData && 'maxPrice' in templateData && currentSearchRequestState.price_range_min_value === 0 && currentSearchRequestState.price_range_max_value === 0) { - updateCurrentSearchRequestState({ - price_range_min_value: Math.floor(Number(templateData.minPrice)), - price_range_max_value: Math.ceil(Number(templateData.maxPrice)) - }); - } - currentSearchRequestState = getCurrentSearchRequestState(); - templateData.priceRangeFacet = { - start: currentSearchRequestState.price_range_min_value, - end: currentSearchRequestState.price_range_max_value - }; - if (!((_a = config === null || config === void 0 ? void 0 : config.search) === null || _a === void 0 ? void 0 : _a.infinite_scroll)) { - templateData.paginationData = buildPaginationData(templateData); - } - templateData.isFiltersPanelOpened = urlParameters.has(PARAMETER_NAME_FILTERS_PANEL); - templateData.defaultMaxColorSwatches = MAX_COLOR_SWATCHES; - templateData.mobileView = isMobileView; - templateData.escapeSpecialCharacters = escapeSpecialCharacters; - templateData.selectedColors = getSelectedColors(); - templateData.formatMoney = templateData.formatMoney || config.format_money; - return templateData; - } - function buildApiCallParameters() { - var _a, _b, _c, _d, _e; - const config = buildSearchConfig(); - const urlParameters = new URLSearchParams(window.location.search); - const currentSearchRequestState = getCurrentSearchRequestState(); - const apiParameters = Object.assign(Object.assign(Object.assign(Object.assign({}, ((_a = config.search) === null || _a === void 0 ? void 0 : _a.endpoint) ? { - endpoint: config.search.endpoint - } : {}), ((_b = config.search) === null || _b === void 0 ? void 0 : _b.groupby) ? { - groupby: config.search.groupby - } : {}), ((_c = config.search) === null || _c === void 0 ? void 0 : _c.group_limit) ? { - group_limit: config.search.group_limit - } : {}), { - q: urlParameters.get(config.default_search_parameter || '') || config.search.category_id || '', - rows: (_d = config.search) === null || _d === void 0 ? void 0 : _d.items_per_page, - sort: config === null || config === void 0 ? void 0 : config.sort, - start: config.start, - account_id: config.account_id, - domain_key: config.domain_key, - request_id: currentSearchRequestState.request_id, - _br_uid_2: config.tracking_cookie || '', - ref_url: config.ref_url, - url: config.url || '', - request_type: config.request_type, - search_type: config.search_type, - fl: (_e = config.search) === null || _e === void 0 ? void 0 : _e.fields, - 'facet.range': config['facet.range'], - 'stats.field': config['stats.field'] - }); - const pageUrlParameter = urlParameters.get(PARAMETER_NAME_PAGE); - if (pageUrlParameter) { - if (config.search.infinite_scroll && currentSearchRequestState.is_first_request) { - apiParameters.start = 0; - apiParameters.rows = Number.parseInt(pageUrlParameter, 10) * config.search.items_per_page; - } else { - apiParameters.start = (Number.parseInt(pageUrlParameter, 10) - 1) * config.search.items_per_page; - } - } - const facets = getFacetsFromUrl(); - if (Object.keys(facets).length) { - /* - And we're setting the 'fq' parameter value as: - 'colors:"gray" OR "black"&fq=reviews:"4.7" OR "5.0"' - so we can use multiple parameter instances in the API call - */ - apiParameters.fq = convertFacetsToQueryString(facets); - } - // add URL parameters - // eslint-disable-next-line functional/no-loop-statement - for (const [key, value] of urlParameters.entries()) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-unsafe-argument - if (!Object.keys(apiParameters).includes(key)) { - apiParameters[key] = value; - } - } - const segmentationData = extractSegmentationCookie(); - if (segmentationData) { - apiParameters.brSeg = `seg:${segmentationData}`; - apiParameters.segment = `customer_profile:${segmentationData}`; - apiParameters.cdp_segments = segmentationData; - } - // Clean out undefined values as they cause errors with the API - Object.keys(apiParameters).forEach(key => { - if (apiParameters[key] === void 0 || isString(apiParameters[key]) && apiParameters[key].length === 0) { - delete apiParameters[key]; - } - }); - return apiParameters; - } - function isString(value) { - return typeof value === 'string'; - } - - const productSearchModule = buildProductSearchModule(); - window.BloomreachModules = Object.assign(Object.assign({}, globalBloomreachModules), { - search: productSearchModule - }); - productSearchModule.load().catch(console.error); - -})(); +var t=i,n=b,r=y,a=!1,o=w,c="locals",s=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"],l=s.concat("cache"),u=/^\uFEFF/,d=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/;function p(n,r){var i;if(r.some((function(r){return i=e.resolveInclude(n,r,!0),t.existsSync(i)})))return i}function m(t,n){var r,i=t.filename,a=arguments.length>1;if(t.cache){if(!i)throw new Error("cache option requires a filename");if(r=e.cache.get(i))return r;a||(n=f(i).toString().replace(u,""))}else if(!a){if(!i)throw new Error("Internal EJS error: no file name or template provided");n=f(i).toString().replace(u,"")}return r=e.compile(n,t),t.cache&&e.cache.set(i,r),r}function f(t){return e.fileLoader(t)}function h(n,i){var a=r.shallowCopy(r.createNullProtoObjWherePossible(),i);if(a.filename=function(n,r){var i,a,o=r.views,c=/^[A-Za-z]+:\\|^\//.exec(n);if(c&&c.length)n=n.replace(/^\/*/,""),i=Array.isArray(r.root)?p(n,r.root):e.resolveInclude(n,r.root||"/",!0);else if(r.filename&&(a=e.resolveInclude(n,r.filename),t.existsSync(a)&&(i=a)),!i&&Array.isArray(o)&&(i=p(n,o)),!i&&"function"!=typeof r.includer)throw new Error('Could not find the include file "'+r.escapeFunction(n)+'"');return i}(n,a),"function"==typeof i.includer){var o=i.includer(n,a.filename);if(o&&(o.filename&&(a.filename=o.filename),o.template))return m(a,o.template)}return m(a)}function _(e,t,n,r,i){var a=t.split("\n"),o=Math.max(r-3,0),c=Math.min(a.length,r+3),s=i(n),l=a.slice(o,c).map((function(e,t){var n=t+o+1;return(n==r?" >> ":" ")+n+"| "+e})).join("\n");throw e.path=s,e.message=(s||"ejs")+":"+r+"\n"+l+"\n\n"+e.message,e}function g(e){return e.replace(/;(\s*$)/,"$1")}function v(t,n){var i=r.hasOwnOnlyObject(n),a=r.createNullProtoObjWherePossible();this.templateText=t,this.mode=null,this.truncate=!1,this.currentLine=1,this.source="",a.client=i.client||!1,a.escapeFunction=i.escape||i.escapeFunction||r.escapeXML,a.compileDebug=!1!==i.compileDebug,a.debug=!!i.debug,a.filename=i.filename,a.openDelimiter=i.openDelimiter||e.openDelimiter||"<",a.closeDelimiter=i.closeDelimiter||e.closeDelimiter||">",a.delimiter=i.delimiter||e.delimiter||"%",a.strict=i.strict||!1,a.context=i.context,a.cache=i.cache||!1,a.rmWhitespace=i.rmWhitespace,a.root=i.root,a.includer=i.includer,a.outputFunctionName=i.outputFunctionName,a.localsName=i.localsName||e.localsName||c,a.views=i.views,a.async=i.async,a.destructuredLocals=i.destructuredLocals,a.legacyInclude=void 0===i.legacyInclude||!!i.legacyInclude,a.strict?a._with=!1:a._with=void 0===i._with||i._with,this.opts=a,this.regex=this.createRegex()}e.cache=r.cache,e.fileLoader=t.readFileSync,e.localsName=c,e.promiseImpl=new Function("return this;")().Promise,e.resolveInclude=function(e,t,r){var i=n.dirname,a=n.extname,o=(0,n.resolve)(r?t:i(t),e);return a(e)||(o+=".ejs"),o},e.compile=function(e,t){return t&&t.scope&&(a||(console.warn("`scope` option is deprecated and will be removed in EJS 3"),a=!0),t.context||(t.context=t.scope),delete t.scope),new v(e,t).compile()},e.render=function(e,t,n){var i=t||r.createNullProtoObjWherePossible(),a=n||r.createNullProtoObjWherePossible();return 2==arguments.length&&r.shallowCopyFromList(a,i,s),m(a,e)(i)},e.renderFile=function(){var t,n,i,a=Array.prototype.slice.call(arguments),o=a.shift(),c={filename:o};return"function"==typeof arguments[arguments.length-1]&&(t=a.pop()),a.length?(n=a.shift(),a.length?r.shallowCopy(c,a.pop()):(n.settings&&(n.settings.views&&(c.views=n.settings.views),n.settings["view cache"]&&(c.cache=!0),(i=n.settings["view options"])&&r.shallowCopy(c,i)),r.shallowCopyFromList(c,n,l)),c.filename=o):n=r.createNullProtoObjWherePossible(),function(t,n,r){var i;if(!r){if("function"==typeof e.promiseImpl)return new e.promiseImpl((function(e,r){try{e(i=m(t)(n))}catch(e){r(e)}}));throw new Error("Please provide a callback function")}try{i=m(t)(n)}catch(e){return r(e)}r(null,i)}(c,n,t)},e.Template=v,e.clearCache=function(){e.cache.reset()},v.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"},v.prototype={createRegex:function(){var e="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)",t=r.escapeRegExpChars(this.opts.delimiter),n=r.escapeRegExpChars(this.opts.openDelimiter),i=r.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,i),new RegExp(e)},compile:function(){var e,t,i,a=this.opts,o="",c="",s=a.escapeFunction,l=a.filename?JSON.stringify(a.filename):"undefined";if(!this.source){if(this.generateSource(),o+=' var __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s }\n',a.outputFunctionName){if(!d.test(a.outputFunctionName))throw new Error("outputFunctionName is not a valid JS identifier.");o+=" var "+a.outputFunctionName+" = __append;\n"}if(a.localsName&&!d.test(a.localsName))throw new Error("localsName is not a valid JS identifier.");if(a.destructuredLocals&&a.destructuredLocals.length){for(var u=" var __locals = ("+a.localsName+" || {}),\n",p=0;p0&&(u+=",\n "),u+=m+" = __locals."+m}o+=u+";\n"}!1!==a._with&&(o+=" with ("+a.localsName+" || {}) {\n",c+=" }\n"),c+=" return __output;\n",this.source=o+this.source+c}e=a.compileDebug?"var __line = 1\n , __lines = "+JSON.stringify(this.templateText)+"\n , __filename = "+l+";\ntry {\n"+this.source+"} catch (e) {\n rethrow(e, __lines, __filename, __line, escapeFn);\n}\n":this.source,a.client&&(e="escapeFn = escapeFn || "+s.toString()+";\n"+e,a.compileDebug&&(e="rethrow = rethrow || "+_.toString()+";\n"+e)),a.strict&&(e='"use strict";\n'+e),a.debug&&console.log(e),a.compileDebug&&a.filename&&(e=e+"\n//# sourceURL="+l+"\n");try{if(a.async)try{i=new Function("return (async function(){}).constructor;")()}catch(e){throw e instanceof SyntaxError?new Error("This environment does not support async/await"):e}else i=Function;t=new i(a.localsName+", escapeFn, include, rethrow",e)}catch(e){throw e instanceof SyntaxError&&(a.filename&&(e.message+=" in "+a.filename),e.message+=" while compiling ejs\n\n",e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n",e.message+="https://github.com/RyanZim/EJS-Lint",a.async||(e.message+="\n",e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}var f=a.client?t:function(e){return t.apply(a.context,[e||r.createNullProtoObjWherePossible(),s,function(t,n){var i=r.shallowCopy(r.createNullProtoObjWherePossible(),e);return n&&(i=r.shallowCopy(i,n)),h(t,a)(i)},_])};if(a.filename&&"function"==typeof Object.defineProperty){var g=a.filename,v=n.basename(g,n.extname(g));try{Object.defineProperty(f,"name",{value:v,writable:!1,enumerable:!1,configurable:!0})}catch(e){}}return f},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")),this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var e=this,t=this.parseTemplateText(),n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter;t&&t.length&&t.forEach((function(a,o){var c;if(0===a.indexOf(r+n)&&0!==a.indexOf(r+n+n)&&(c=t[o+2])!=n+i&&c!="-"+n+i&&c!="_"+n+i)throw new Error('Could not find matching close tag for "'+a+'".');e.scanLine(a)}))},parseTemplateText:function(){for(var e,t=this.templateText,n=this.regex,r=n.exec(t),i=[];r;)0!==(e=r.index)&&(i.push(t.substring(0,e)),t=t.slice(e)),i.push(r[0]),t=t.slice(r[0].length),r=n.exec(t);return t&&i.push(t),i},_addOutput:function(e){if(this.truncate&&(e=e.replace(/^(?:\r\n|\r|\n)/,""),this.truncate=!1),!e)return e;e=(e=(e=(e=e.replace(/\\/g,"\\\\")).replace(/\n/g,"\\n")).replace(/\r/g,"\\r")).replace(/"/g,'\\"'),this.source+=' ; __append("'+e+'")\n'},scanLine:function(e){var t,n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter;switch(t=e.split("\n").length-1,e){case r+n:case r+n+"_":this.mode=v.modes.EVAL;break;case r+n+"=":this.mode=v.modes.ESCAPED;break;case r+n+"-":this.mode=v.modes.RAW;break;case r+n+"#":this.mode=v.modes.COMMENT;break;case r+n+n:this.mode=v.modes.LITERAL,this.source+=' ; __append("'+e.replace(r+n+n,r+n)+'")\n';break;case n+n+i:this.mode=v.modes.LITERAL,this.source+=' ; __append("'+e.replace(n+n+i,n+i)+'")\n';break;case n+i:case"-"+n+i:case"_"+n+i:this.mode==v.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=0===e.indexOf("-")||0===e.indexOf("_");break;default:if(this.mode){switch(this.mode){case v.modes.EVAL:case v.modes.ESCAPED:case v.modes.RAW:e.lastIndexOf("//")>e.lastIndexOf("\n")&&(e+="\n")}switch(this.mode){case v.modes.EVAL:this.source+=" ; "+e+"\n";break;case v.modes.ESCAPED:this.source+=" ; __append(escapeFn("+g(e)+"))\n";break;case v.modes.RAW:this.source+=" ; __append("+g(e)+")\n";break;case v.modes.COMMENT:break;case v.modes.LITERAL:this._addOutput(e)}}else this._addOutput(e)}this.opts.compileDebug&&t&&(this.currentLine+=t,this.source+=" ; __line = "+this.currentLine+"\n")}},e.escapeXML=r.escapeXML,e.__express=e.renderFile,e.VERSION=o,e.name="ejs","undefined"!=typeof window&&(window.ejs=e)}(r);var S="Invariant failed";function k(e,t){if(!e)throw new Error(S)}const E="cdp_segments",x="$",O=16,L="q",j=[{label:"Relevance",value:""},{label:"Price (low - high)",value:"price+asc"},{label:"Price (high - low)",value:"price+desc"},{label:"Name (A - Z)",value:"title+asc"},{label:"Name (Z - A)",value:"title+desc"}],A=0,R="price",q=4,N=2,C=2,I=5,P=6,T="fq",F="filterpanel",M="groupby",$="page",D="size",U="sort",z="search",V="category",W="keyword",J=".main-content";function B(){const e=`${E}=`;return(document.cookie.split("; ").find((t=>t.startsWith(e)))||"").replace(e,"")}const Q={method:"GET",headers:{"Content-Type":"application/json"}};function H(){const e=document.cookie.split("; ").find((e=>e.startsWith("_br_uid_2=")));return e?e.replace("_br_uid_2=",""):"uid%3D7797686432023%3Av%3D11.5%3Ats%3D1428617911187%3Ahc%3D55"}const X=(e,t="$",n=!0)=>`${n?t:""}${(e/100).toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:2})}${n?"":` ${t}`}`;const Z="https://core.dxpapi.com/api/v1/core/",G=["_br_uid_2","fq","sort"],Y="pid,title,brand,price,sale_price,thumb_image,sku_thumb_images,sku_swatch_images,sku_color_group,url,price_range,sale_price_range,description,is_live,score,skuid,group";function K(e){const t=Object.assign({},e),n=(null==t?void 0:t.endpoint)||Z;return(null==t?void 0:t.endpoint)&&(null==t||delete t.endpoint),(null==t?void 0:t.fl)||(t.fl=Y),`${n}${r=t,`?${Object.keys(r).reduce(((e,t)=>[...e,`${t}=${G.includes(t)?r[t]:encodeURIComponent(r[t])}`]),[]).join("&")}`}`;var r}async function ee(e){return async function(e,t){const n=await fetch(e,t);return await n.json()}(K(e),Q)}var te='<% if (did_you_mean.length) { %>\n \n<% } %>\n<% if (locals.keywordRedirect && keywordRedirect.redirected_query && did_you_mean.length === 0) { %>\n
\n
\n

Results for <%- keywordRedirect.redirected_query %>

\n
Redirected from "<%- keywordRedirect.original_query %>"
\n
\n
\n<% } %>\n
\n <% if (config.search.facets_included && facets.length) { %>\n \n <% } %>\n
\n
\n <%\n const haveUngroupedResults = locals.number_of_results && number_of_results > 0;\n const haveGroupedResults = locals.grouped_products && grouped_products.groups.length > 0;\n %>\n <% if (haveUngroupedResults || haveGroupedResults) { %>\n <% if (haveUngroupedResults) { %>\n

\n Showing <%- start + 1 %> - <%- Math.min(start + products.length, number_of_results) %> of <%- number_of_results %> products\n

\n <% } %>\n
\n <% if (config.search.groupby) { %>\n \n \n \n <% config.search.groupby_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n <% } %>\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n \n \n \n <% for (let i = (config.search.groupby ? 4 : 16); i <= (config.search.groupby ? 16 : 48); i += 4) { %>\n \n <% } %>\n \n \n <% } %>\n \n \n \n <% config.search.sorting_options.forEach(function(option) { %>\n \n <% }) %>\n \n \n
\n <% } else if (!(locals.grouped_products) || grouped_products.groups.length < 1) { %>\n

\n No results found\n

\n <% } %>\n\n
\n
class="blm-product-search__results"<% } %>>\n <% if (products.length || (locals.grouped_products && grouped_products.groups.length > 0)) { %>\n %%-PRODUCT_LIST_TEMPLATE-%%\n <% } %>\n
\n\n <% if (!config.search.infinite_scroll && paginationData.length > 0) { %>\n
\n
    \n <% paginationData.forEach(paginationNode => { %>\n
  • \n
  • \n <% }) %>\n
\n
\n <% } %>\n
\n
\n',ne='<% function printProduct(product) { %>\n
title="<%- product.variant_name %>"<% } %>>\n <%\n const matchingVariant = !Array.isArray(product.variants)\n ? null\n : \'variant_index\' in product\n ? product.variants[product.variant_index]\n : product.variants.find(variant => selectedColors.includes(variant.sku_color_group ? variant.sku_color_group.toLowerCase() : null))\n %>\n
\n <% if (product.variants && product.variants.length > 1) { %>\n <% product.variants.forEach(function(variant, index) { %>\n\n <%\n const isActiveVariant =\n !(\'variant_index\' in product) && !selectedColors.length\n ? index === 0\n : \'variant_index\' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n\n
style="display: block"<% } %>\n >\n \n
\n <% }); %>\n <% } else { %>\n
\n \n
\n <% } %>\n
\n \n\n <% if (product.variants && product.variants.length > 1) { %>\n
    \n <% product.variants.slice(0, defaultMaxColorSwatches || 0).forEach(function(variant, index) { %>\n <%\n const isActiveVariant =\n !(\'variant_index\' in product) && !selectedColors.length\n ? index === 0\n : \'variant_index\' in product\n ? product.variant_index === index\n : matchingVariant == variant\n %>\n \n <% }); %>\n
\n\n <% if (product.variants.length > defaultMaxColorSwatches || 0) { %>\n (Colors) <%- product.variants.length %>\n <% } %>\n <% } %>\n
\n<% } %>\n\n<% if (locals.grouped_products && grouped_products && grouped_products.groups) { %>\n\n <% grouped_products.groups.forEach(group => { %>\n
\n

<%- group.title %>

\n\n
\n <% group.products.forEach(printProduct); %>\n
\n
\n <% }); %>\n\n<% } else { %>\n\n <% products.forEach(printProduct); %>\n\n<% } %>\n';function re(){var e,t,n;const r=function(){var e;const t=null===(e=null===window||void 0===window?void 0:window.bloomreachConnector)||void 0===e?void 0:e.config;return Object.assign({default_search_parameter:L,url:window.location.href,ref_url:window.location.href,tracking_cookie:H(),format_money:e=>X(e,window.bloomreachDefaultCurrency||x),default_currency:window.bloomreachDefaultCurrency||x},t)}(),i=new URLSearchParams(window.location.search),a=At(),o=Object.assign({display_variants:!1,enabled:!0,endpoint:"",items_per_page:O,facets_included:!0,initial_number_of_facets:I,initial_number_of_facet_values:P,infinite_scroll:!1,selector:J,sorting_options:j,template:te,product_list_template:ne},(null==r?void 0:r.search)?r.search:{}),c=Object.assign(Object.assign({},r),{request_type:z,search_type:a.is_category_page?V:W,start:A,"facet.range":R,"stats.field":R,sort:i.get(U)||"",search:Object.assign(Object.assign(Object.assign({},o),(a.is_category_page?r.category:r.search)||{}),a.category_to_load?{category_id:a.category_to_load}:{})});return null===(n=null===(t=null===(e=c.search)||void 0===e?void 0:e.sorting_options)||void 0===t?void 0:t.sort)||void 0===n||n.call(t,((e,t)=>e.value>t.value?1:-1)),c.search&&(c.search=Object.assign(Object.assign({},c.search),{items_per_page:Number(i.has(D)?i.get(D):c.search.items_per_page),groupby:i.get(M)||c.search.groupby||""})),c}function ie(e){return"grouped_products"in e?function(e){var t;const n=Number(e.page||1),r=e.size||1,i=((null===(t=null==e?void 0:e.grouped_products)||void 0===t?void 0:t.groups)||[]).length;return[{value:"previous",label:"Previous",disabled:n<=1},{value:"next",label:"Next",disabled:it+1)).slice(-N),a=Array(r-n).fill(null).map(((e,t)=>t+(n+1))).slice(0,C);return[...n>1?[{value:"previous",label:"←"}]:[],...n-1>N?[{label:"…",value:(n-N-1).toString()}]:[],...i.map((e=>({value:e.toString()}))),{value:n.toString(),disabled:!0,active:!0},...a.map((e=>({value:e.toString()}))),...n+Ce.replace(/"/g,""").replace(/,/g,"%%-COMMA-%%"),oe=e=>Object.keys(e).map((t=>"price"===t?encodeURIComponent(`${t}:[${e[t].map((e=>`${e||"*"}`)).join(" TO ")}]`):encodeURIComponent(`${t}:${e[t].map((e=>`"${(e=>e.replace(/%%-COMMA-%%/g,",").replace(/"/g,'"'))(e)}"`)).join(" OR ")}`))).join("&fq=");function ce(e){var t;let n=0,r=0;const i=re(),a=Number(e||(null===(t=i.search)||void 0===t?void 0:t.initial_number_of_facets));document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').forEach((e=>{const t=e.querySelectorAll('.blm-product-search-filter-item:not([style*="display: none"]');n0&&e.setAttribute("style","display: block"),n++,r+=t.length>0?1:0}));const o=At(),c=document.querySelector(`.blm-load-more-facet--${o.request_id}`);0!==document.querySelectorAll('.blm-dynamic-filter:not([style*="display: block"])').length&&0!==r||null==c||c.classList.add("blm-hide")}function se(){const e=At(),t=document.querySelector(`.blm-load-more-facet--${e.request_id}`);return k(t),t}function le(){var e,t;const n=re(),r=Number(null===(e=n.search)||void 0===e?void 0:e.initial_number_of_facets),i=Number(null===(t=n.search)||void 0===t?void 0:t.initial_number_of_facet_values);[".blm-dynamic-filter",".blm-product-search-filter-item",".blm-product-search-load-more"].forEach((e=>{document.querySelectorAll(e).forEach((e=>{e.removeAttribute("style")}))})),ce(r-1),document.querySelectorAll(`.blm-product-search-filter-item:nth-child(-n+${i})`).forEach((e=>e.style.display="block")),se().removeAttribute("style")}function ue(){var e;const t=re();k(null===(e=t.search)||void 0===e?void 0:e.selector);return document.querySelector(t.search.selector)}function de(){const e=document.querySelector(".blm-scroll-indicator");if(e){e.innerHTML="";const t=document.createElement("div");t.classList.add("blm-scroll-indicator__loading"),e.appendChild(t)}}function pe(){const e=document.querySelectorAll(".blm-product-search-filter-item__checkbox:checked");return e?Array.from(e).reduce(((e,t)=>Object.assign(Object.assign({},e),{[t.name]:e[t.name]?[...e[t.name]||[],t.value]:[t.value]})),{}):{}}var me;!function(e){e.small="480px",e.medium="680px",e.large="750px",e.xlarge="875px",e.xxlarge="1000px",e.xxxlarge="1200px"}(me||(me={}));const fe=window.matchMedia(`(max-width: ${me.medium})`);function he(e){const t={};for(const n of e.entries())t[n[0]]=n[1];window.history.pushState(t,document.title,`?${e.toString()}`)}function _e(e,t,n){const r=Object.assign(Object.assign({},{valueSerializer:e=>e.toString().replace(/"/g,'\\"'),nameValueSeparator:":"}),n),i=new URLSearchParams(window.location.search);i.delete(e),Array.isArray(t)?t.forEach((t=>{i.append(e,r.valueSerializer(t))})):Object.keys(t).forEach((n=>{i.append(e,`${n}${r.nameValueSeparator}${r.valueSerializer(t[n])}`)})),he(i)}function ge(e,t){const n=new URLSearchParams(window.location.search);"function"==typeof t?n.set(e,t(n.get(e)).replace(/"/g,'\\"')):""===t?n.delete(e):n.set(e,t.replace(/"/g,'\\"')),he(n)}function ve(e){ge(e,(e=>{if(!e)return"2";let t=Number.parseInt(e,10);return(++t).toString()}))}function be(e){ge(e,(e=>{if(!e)return"1";let t=Number.parseInt(e,10);return(--t).toString()}))}function ye(){const e=At(),t=we(),n=document.querySelector(".blm-price-range-input--lower"),r=document.querySelector(".blm-price-range-input--upper");let i=parseFloat(n.value),a=parseFloat(r.value);return i>a&&([i,a]=[a,i]),i===a&&(i>e.price_range_min_value||aObject.assign(Object.assign({},e),{[t.split(":")[0]||""]:(t.split(":")[1]||"").split(",")})),{})}window.matchMedia(`(min-width:${me.medium}) and (max-width: ${me.xlarge})`);var Se=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)},ke="object"==typeof t&&t&&t.Object===Object&&t,Ee="object"==typeof self&&self&&self.Object===Object&&self,xe=ke||Ee||Function("return this")(),Oe=xe,Le=function(){return Oe.Date.now()},je=/\s/;var Ae=function(e){for(var t=e.length;t--&&je.test(e.charAt(t)););return t},Re=/^\s+/;var qe=function(e){return e?e.slice(0,Ae(e)+1).replace(Re,""):e},Ne=xe.Symbol,Ce=Ne,Ie=Object.prototype,Pe=Ie.hasOwnProperty,Te=Ie.toString,Fe=Ce?Ce.toStringTag:void 0;var Me=function(e){var t=Pe.call(e,Fe),n=e[Fe];try{e[Fe]=void 0;var r=!0}catch(e){}var i=Te.call(e);return r&&(t?e[Fe]=n:delete e[Fe]),i},$e=Object.prototype.toString;var De=Me,Ue=function(e){return $e.call(e)},ze=Ne?Ne.toStringTag:void 0;var Ve=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":ze&&ze in Object(e)?De(e):Ue(e)},We=function(e){return null!=e&&"object"==typeof e};var Je=qe,Be=Se,Qe=function(e){return"symbol"==typeof e||We(e)&&"[object Symbol]"==Ve(e)},He=/^[-+]0x[0-9a-f]+$/i,Xe=/^0b[01]+$/i,Ze=/^0o[0-7]+$/i,Ge=parseInt;var Ye=Se,Ke=Le,et=function(e){if("number"==typeof e)return e;if(Qe(e))return NaN;if(Be(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Be(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=Je(e);var n=Xe.test(e);return n||Ze.test(e)?Ge(e.slice(2),n?2:8):He.test(e)?NaN:+e},tt=Math.max,nt=Math.min;var rt=function(e,t,n){var r,i,a,o,c,s,l=0,u=!1,d=!1,p=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function m(t){var n=r,a=i;return r=i=void 0,l=t,o=e.apply(a,n)}function f(e){var n=e-s;return void 0===s||n>=t||n<0||d&&e-l>=a}function h(){var e=Ke();if(f(e))return _(e);c=setTimeout(h,function(e){var n=t-(e-s);return d?nt(n,a-(e-l)):n}(e))}function _(e){return c=void 0,p&&r?m(e):(r=i=void 0,o)}function g(){var e=Ke(),n=f(e);if(r=arguments,i=this,s=e,n){if(void 0===c)return function(e){return l=e,c=setTimeout(h,t),u?m(e):o}(s);if(d)return clearTimeout(c),c=setTimeout(h,t),m(s)}return void 0===c&&(c=setTimeout(h,t)),o}return t=et(t)||0,Ye(n)&&(u=!!n.leading,a=(d="maxWait"in n)?tt(et(n.maxWait)||0,t):a,p="trailing"in n?!!n.trailing:p),g.cancel=function(){void 0!==c&&clearTimeout(c),l=0,r=s=i=c=void 0},g.flush=function(){return void 0===c?o:_(Ke())},g};function it(e){var t,n,r;const i=re(),a=(null==e?void 0:e.facet_counts)?"facets"in e.facet_counts?function(e){var t,n;return Object.assign(Object.assign({facets:null!==(n=null===(t=e.facets)||void 0===t?void 0:t.filter((e=>"text"===e.type||"number"===e.type)).filter((e=>e.value.length)).map(st))&&void 0!==n?n:[]},function(e){var t;const n=null===(t=null==e?void 0:e.filter((e=>"number_range"===e.type)).find((e=>"price"===e.name.toLowerCase())))||void 0===t?void 0:t.value.map((e=>({count:e.count,start:e.start.toString(),end:e.end.toString()})));return n?{priceRanges:n}:{}}(e.facets)),function(e){var t;const n=null==e?void 0:e.filter((e=>"number_stats"===e.type)).map((e=>({name:e.name.toLowerCase(),value:e.value}))),r=null!==(t=null==n?void 0:n.find((e=>"sale price"===e.name||"sale_price"===e.name)))&&void 0!==t?t:null==n?void 0:n.find((e=>"price"===e.name));return(null==r?void 0:r.value)?{maxPrice:r.value.end,minPrice:r.value.start}:{}}(e.facets))}(e.facet_counts):function(e,t){var n,r;return Object.assign(Object.assign(Object.assign({facets:Object.entries(e.facet_fields||{}).filter((e=>e[1].length)).map(at)},function(e){if(null==e?void 0:e.price)return{priceRanges:e.price.map((e=>({count:e.count,start:e.start.toString(),end:e.end.toString()})))};return{}}(e.facet_ranges)),ct(null===(n=null==t?void 0:t.stats_fields)||void 0===n?void 0:n.price)),ct(null===(r=null==t?void 0:t.stats_fields)||void 0===r?void 0:r.sale_price))}(e.facet_counts,e.stats):{facets:[]};return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},a),{products:lt((null===(t=e.response)||void 0===t?void 0:t.docs)||[])}),(null==e?void 0:e.group_response)?{grouped_products:Object.keys(null==e?void 0:e.group_response).reduce(((t,n)=>{var r,i,a,o;return Object.assign(Object.assign({group_category_id:n},null===(r=e.group_response)||void 0===r?void 0:r[n]),{groups:(null===(o=null===(a=null===(i=e.group_response)||void 0===i?void 0:i[n])||void 0===a?void 0:a.groups)||void 0===o?void 0:o.map((e=>{var t;return{title:e.groupValue,products:lt((null===(t=null==e?void 0:e.doclist)||void 0===t?void 0:t.docs)||[])}})))||[]})}),{})}:{}),{did_you_mean:e.did_you_mean||[],number_of_results:Number(null===(n=e.response)||void 0===n?void 0:n.numFound),start:Number(null===(r=e.response)||void 0===r?void 0:r.start),config:i}),e.keywordRedirect?{keywordRedirect:{original_query:e.keywordRedirect["original query"],redirected_query:e.keywordRedirect["redirected query"],redirected_url:e.keywordRedirect["redirected url"]}}:{})}function at(e){return{original_title:e[0],title:e[0].replace("_"," ").replace(/\b\w/g,(e=>e.toUpperCase())),section:e[1].map(ot)}}function ot(e){var t,n,r,i,a;if("name"in e){let r=null!==(t=e.name)&&void 0!==t?t:"";return"true"===e.name?r="Yes":"false"===e.name&&(r="No"),{count:null!==(n=e.count)&&void 0!==n?n:0,name:r,id:r}}return{count:null!==(r=e.count)&&void 0!==r?r:0,name:null!==(i=e.cat_name)&&void 0!==i?i:"",id:null!==(a=e.cat_id)&&void 0!==a?a:""}}function ct(e){return e?{maxPrice:e.max,minPrice:e.min}:{}}function st(e){return{original_title:e.name,title:e.name.replace("_"," ").replace(/\b\w/g,(e=>e.toUpperCase())),section:e.value.map(ot)}}function lt(e){const t=re();return e.reduce(((e,n)=>[...e,...t.search.display_variants?ut(n):[dt(n)]]),[])}function ut(e){return e.variants&&e.variants.length?(dt(e).variants||[]).map(((t,n)=>Object.assign(Object.assign(Object.assign({},dt(e)),t),{variant_index:n}))):[dt(e)]}function dt(e){return Object.assign(Object.assign(Object.assign({},e),{title:e.title,image:e.thumb_image,link:e.url,id:e.pid,price:e.price,sale_price:e.sale_price}),e.variants?{variants:e.variants.map((e=>Object.assign(Object.assign({},e),{sku_color_group:e.sku_color_group,sku_swatch_images:e.sku_swatch_images,sku_thumb_images:e.sku_thumb_images,sku_sale_price:e.sku_sale_price,sku_price:e.sku_price,image:e.sku_thumb_images&&Array.isArray(e.sku_thumb_images)?e.sku_thumb_images[0]:e.sku_swatch_images[0],variant_name:e.sku_color_group})))}:{})}function pt(){const e=At(),t=document.querySelector(`.blm-range-slider__clear-values-button--${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("click",(()=>{de(),_e(T,Object.assign({},pe())),ge($,"1"),Rt({price_range_max_value:0,price_range_min_value:0}),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function mt(){document.querySelectorAll(".blm-product-search-selected-filter__clear").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",(e=>{var t,n,r,i;const a=null===(r=null===(n=null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.parentNode)||void 0===n?void 0:n.dataset)||void 0===r?void 0:r.filterCheckboxId;a&&(null===(i=document.getElementById(a))||void 0===i||i.click())})),e.setAttribute("hasListener","true"))}))}function ft(){const e=document.querySelector(".blm-product-search-selected-filters__clear-all");e&&(e.getAttribute("hasListener")||(e.addEventListener("click",(()=>{de(),_e(T,Object.assign({},ye())),ge($,"1"),Rt({price_range_min_value:0,price_range_max_value:0}),jt({toReplace:!0}).catch(console.error)})),e.setAttribute("hasListener","true")))}function ht(){const e=document.querySelectorAll(".blm-product-search-filter-item__checkbox");e&&e.forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("change",(()=>{de(),_e(T,Object.assign(Object.assign({},pe()),ye())),ge($,"1"),Rt({price_range_min_value:0,price_range_max_value:0}),jt({toReplace:!0}).catch(console.error)})),e.setAttribute("hasListener","true"))}))}function _t(){const e=document.querySelector("#blm-product-search-search-filters__input");e&&(e.getAttribute("hasInputListener")||(e.addEventListener("input",rt((e=>{var t;const n=((null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.value)||"").trim();document.querySelectorAll(".blm-dynamic-filter").forEach((e=>{let t=0;e.querySelectorAll(".blm-product-search-filter-item").forEach((e=>{var r;const i=(null===(r=e.querySelector("label"))||void 0===r?void 0:r.textContent)||"",a=!n||i.toLowerCase().includes(n.toLowerCase()),o=a?"block":"none";t+=a?1:0,e.style.display=o})),e.style.display=t?"block":"none"})),document.querySelectorAll(".blm-product-search-load-more").forEach((e=>{e.style.display="none"})),se().style.display="none",n||le()}),500)),e.setAttribute("hasInputListener","true")))}function gt(){const e=At(),t=document.querySelector(`#groupby-${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("change",(e=>{var t;ge(M,null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.value),de(),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function vt(){const e=se();e&&!e.getAttribute("hasListener")&&(e.addEventListener("click",(()=>{ce()})),e.setAttribute("hasListener","true"))}function bt(){document.querySelectorAll(".blm-product-search-load-more").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",function(){var e;const t=re(),n=Number(null===(e=t.search)||void 0===e?void 0:e.initial_number_of_facet_values);let r=n;const i=n;return e=>{const t=e.target.getAttribute("data-item"),n=document.getElementById(`blm-facet-block-item-${t}`).getElementsByTagName("li");for(let e=r;e=n.length&&(e.target.style.display="none")}}()),e.setAttribute("hasListener","true"))}))}function yt(){const e=At(),t=document.querySelector(`#sort-size-${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("change",(e=>{ge(D,e.target.value),ge($,"1"),de(),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function wt(){const e=At(),t=document.querySelector(`.blm-product-search-pagination__pages--${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("click",(e=>{de();const t=e.target.dataset.value;if(t){switch(e.target.dataset.value){case"previous":be($);break;case"next":ve($);break;default:ge($,t)}jt({toReplace:!0}).catch(console.error)}})),t.setAttribute("hasListener","true")))}function St(){return()=>{de(),_e(T,Object.assign(Object.assign({},pe()),ye())),ge($,"1"),jt({toReplace:!0}).catch(console.error)}}function kt(e){const t=re();return n=>{var r,i;const a=document.querySelector(e);a&&(a.innerHTML=null!==(i=null===(r=t.format_money)||void 0===r?void 0:r.call(t,100*Number(n.target.value)))&&void 0!==i?i:n.target.value)}}function Et(){var e,t;const n=re();if((null===(e=n.search)||void 0===e?void 0:e.infinite_scroll)&&!document.querySelector(".blm-scroll-indicator")){const e=ue(),r=document.createElement("div");r.classList.add("blm-scroll-indicator");const i=document.createElement("div");i.classList.add("blm-scroll-indicator__loading"),r.appendChild(i),null===(t=null==e?void 0:e.parentNode)||void 0===t||t.insertBefore(r,e.nextSibling);const a=document.querySelector(".blm-scroll-indicator"),o=new IntersectionObserver(function(e){return t=>{var n;if(t[0].intersectionRatio<=0)return;const r=(null===(n=null===window||void 0===window?void 0:window.bloomreachConnector)||void 0===n?void 0:n.config)||{},i=r.start||0;r.start=i+e.search.items_per_page,ve($),jt().catch((e=>{r.start=i,be($),console.error(e)}))}}(n));a&&o.observe(a)}}function xt(){document.querySelectorAll(".blm-product-search-control-button--sidebar").forEach((e=>{e.getAttribute("hasListener")||(e.addEventListener("click",(()=>{const e=document.querySelector(".blm-product-search-sidebar-content");(null==e?void 0:e.classList.contains("blm-open"))?(null==e||e.classList.remove("blm-open"),document.body.classList.remove("blm-out-of-view"),ge(F,"")):(document.body.classList.add("blm-out-of-view"),null==e||e.classList.add("blm-open"),ge(F,"on"))})),e.setAttribute("hasListener","true"))}))}function Ot(){const e=At(),t=document.querySelector(`#sort-by-${e.request_id}`);t&&(t.getAttribute("hasListener")||(t.addEventListener("change",(e=>{var t;ge(U,null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.value),de(),jt({toReplace:!0}).catch(console.error)})),t.setAttribute("hasListener","true")))}function Lt(){document.querySelectorAll(".blm-product-search__result").forEach((e=>{e.querySelectorAll(".blm-product-search-swatch-container").forEach((t=>{const n=t.querySelectorAll(".blm-product-search-swatch-container__swatch");n.forEach(((t,r)=>{t.getAttribute("hasListener")||(t.addEventListener("mouseover",function(e){const{result:t,swatchItems:n,swatchIndex:r}=e;return e=>{n.forEach((e=>{e.classList.remove("active")})),e.target.classList.add("active"),t.querySelectorAll(".blm-product-search-image-container").forEach((e=>{e.querySelectorAll(".blm-product-search-swatch-image").forEach(((e,t)=>{e.style.display="none",r===t&&(e.style.display="block")}))})),t.querySelectorAll(".blm-product-search-details-container__price").forEach(((e,t)=>{e.classList.remove("active"),r===t&&e.classList.add("active")}))}}({result:e,swatchItems:n,swatchIndex:r})),t.setAttribute("hasListener","true"))}))}))}))}async function jt(e={toReplace:!1}){var t,n,i,a;Rt({request_id:Math.floor(1e12+9e12*Math.random())});const o=re(),c=function(){var e,t,n,r,i;const a=re(),o=new URLSearchParams(window.location.search),c=At(),s=Object.assign(Object.assign(Object.assign(Object.assign({},(null===(e=a.search)||void 0===e?void 0:e.endpoint)?{endpoint:a.search.endpoint}:{}),(null===(t=a.search)||void 0===t?void 0:t.groupby)?{groupby:a.search.groupby}:{}),(null===(n=a.search)||void 0===n?void 0:n.group_limit)?{group_limit:a.search.group_limit}:{}),{q:o.get(a.default_search_parameter||"")||a.search.category_id||"",rows:null===(r=a.search)||void 0===r?void 0:r.items_per_page,sort:null==a?void 0:a.sort,start:a.start,account_id:a.account_id,domain_key:a.domain_key,request_id:c.request_id,_br_uid_2:a.tracking_cookie,ref_url:a.ref_url,url:a.url,request_type:a.request_type,search_type:a.search_type,fl:null===(i=a.search)||void 0===i?void 0:i.fields,"facet.range":a["facet.range"],"stats.field":a["stats.field"]}),l=o.get($);l&&(a.search.infinite_scroll&&c.is_first_request?(s.start=0,s.rows=Number.parseInt(l,10)*a.search.items_per_page):s.start=(Number.parseInt(l,10)-1)*a.search.items_per_page);const u=we();Object.keys(u).length&&(s.fq=oe(u));for(const[e,t]of o.entries())Object.keys(s).includes(e)||(s[e]=t);const d=B();d&&(s.brSeg=`seg:${d}`,s.segment=`customer_profile:${d}`,s.cdp_segments=d);a.search.force_v3_facets&&(s["facet.version"]="3.0");return s}(),s=await ee(c);if(null==s?void 0:s.keywordRedirect)return void function(e){var t;if(null==e?void 0:e.keywordRedirect){localStorage.setItem("keywordRedirect",JSON.stringify({original_query:e.keywordRedirect["original query"],redirected_query:e.keywordRedirect["redirected query"],redirected_url:e.keywordRedirect["redirected url"]}));const n=(null===(t=e.keywordRedirect)||void 0===t?void 0:t["redirected url"])||"";window.location.href=`${n.startsWith("http")?"":"https://"}${n}`}}(s);const l=function(e){var t;const n=re(),r=it(e),i=JSON.parse(localStorage.getItem("keywordRedirect")||"{}");(null==i?void 0:i.redirected_query)&&(r.keywordRedirect=i,localStorage.removeItem("keywordRedirect"));const a=new URLSearchParams(window.location.search);for(const[e,t]of a.entries())Object.keys(r).includes(e)||(r[e]=t);a.has(D)?r.size=Number.parseInt(a.get(D)||"",10):r.size=Number.parseInt(n.search.items_per_page.toString(),10);r.checkedFacets=we(),r.selectedFilterItems=((null==r?void 0:r.facets)||[]).reduce(((e,t)=>(t.section.length>0&&t.section.forEach((n=>{var i,a,o;r.checkedFacets&&t.original_title in r.checkedFacets&&(null===(o=null===(a=null===(i=r.checkedFacets)||void 0===i?void 0:i[t.original_title])||void 0===a?void 0:a.includes)||void 0===o?void 0:o.call(a,ae(n.id)))&&(e||[]).push({checkbox_id:`${t.original_title}[${ae(n.name)}]`,label:n.name})})),e)),[]);let o=At();"minPrice"in r&&"maxPrice"in r&&0===o.price_range_min_value&&0===o.price_range_max_value&&Rt({price_range_min_value:Math.floor(Number(r.minPrice)),price_range_max_value:Math.ceil(Number(r.maxPrice))});o=At(),r.priceRangeFacet={start:o.price_range_min_value,end:o.price_range_max_value},(null===(t=null==n?void 0:n.search)||void 0===t?void 0:t.infinite_scroll)||(r.paginationData=ie(r));return r.isFiltersPanelOpened=a.has(F),r.defaultMaxColorSwatches=q,r.mobileView=fe,r.escapeSpecialCharacters=ae,r.selectedColors=function(){const e=we();return Object.keys(e).reduce(((t,n)=>("color"===n.toLowerCase()&&(t=(e[n]||[]).map((e=>e.toLowerCase()))),t)),[])}(),r}(s),u=document.querySelector(".blm-scroll-indicator__loading"),d=(null==l?void 0:l.grouped_products)?((null===(t=null==l?void 0:l.grouped_products)||void 0===t?void 0:t.groups)||[]).length{t=e},getCurrentSearchRequestState:()=>t,load:async t=>{e&&t&&Rt({category_to_load:t}),function(){var e;const t=re();k(t.account_id),k(t.domain_key),k(t.default_search_parameter),k(null===(e=null==t?void 0:t.search)||void 0===e?void 0:e.selector),ue();const n=new URLSearchParams(window.location.search),r=t.search.is_search_page&&n.has(t.default_search_parameter),i=t.search.is_category_page&&(n.has(t.default_search_parameter)||t.search.category_id);return r||i}()&&(function(){const e=B();if(e){(window.br_data||{})[E]=e}}(),function(e){const t={childList:!0,subtree:!0};new MutationObserver((t=>{t.find((e=>"childList"===e.type&&Array.from(e.addedNodes).find((e=>e.classList&&e.classList.contains("blm-results")))))&&e()})).observe(ue(),t)}((()=>{ue().classList.add("blm-has-loaded"),window.onbeforeunload=function(){let e;void 0!==window.pageYOffset?e=window.pageYOffset:void 0!==document.compatMode&&"BackCompat"!==document.compatMode?e=document.documentElement.scrollTop:void 0!==document.body&&(e=document.body.scrollTop);const t=JSON.parse(window.localStorage.getItem("scrollPositions")||"{}");window.localStorage.setItem("scrollPositions",JSON.stringify(Object.assign(Object.assign({},t),{[encodeURI(window.location.href)]:{scrollPosition:e}})))},Et(),function(){window.onpopstate=async()=>{await jt({toReplace:!0})},function(){const e=At(),t=document.querySelector(`.blm-price-range-input--lower-${e.request_id}`),n=document.querySelector(`.blm-price-range-input--upper-${e.request_id}`);t&&n&&(t.getAttribute("hasListener")||(t.addEventListener("change",St()),t.addEventListener("input",kt(".blm-range-slider__values--min")),t.setAttribute("hasListener","true")),n.getAttribute("hasListener")||(n.addEventListener("change",St()),n.addEventListener("input",kt(".blm-range-slider__values--max")),n.setAttribute("hasListener","true")))}(),pt(),mt(),ft(),document.querySelector(".blm-product-search-sidebar")&&(xt(),ht(),vt(),bt(),_t(),le());yt(),Ot(),gt(),wt(),Lt()}()})),await jt(),function(){var e;const t=JSON.parse(window.localStorage.getItem("scrollPositions")||"{}"),n=encodeURI(window.location.href);if(n in t){const r=parseInt(null===(e=t[n])||void 0===e?void 0:e.scrollPosition,10);setTimeout((()=>{document.documentElement.scrollTop=r,document.body.scrollTop=r}),250)}delete t[encodeURI(window.location.href)],window.localStorage.setItem("scrollPositions",JSON.stringify(t))}())}}}();window.BloomreachModules=Object.assign(Object.assign({},e),{search:qt}),qt.load().catch(console.error)}(); //# sourceMappingURL=search.js.map