{"version":3,"file":"search-module-BYfcom36.js","sources":["../../../../node_modules/core-js/internals/validate-arguments-length.js","../../../../node_modules/core-js/modules/web.url-search-params.delete.js","../../../../node_modules/core-js/modules/web.url-search-params.has.js","../../../../node_modules/core-js/modules/web.url-search-params.size.js","../../../../src/main/js/navigation/global/components/search/searchMetrics.js","../../../../src/main/js/navigation/global/components/search/search.js","../../../../src/main/js/navigation/global/components/search/filterResults.js","../../../../src/main/js/navigation/global/components/search/constants.js","../../../../src/main/js/navigation/global/components/search/listboxUtil.js","../../../../src/main/js/navigation/global/components/search/AriaLiveHandler.js","../../../../src/main/js/navigation/global/components/search/suggest.js","../../../../src/main/js/navigation/global/components/search/recents.js","../../../../src/main/js/navigation/global/components/search/entry/main.js","../../../../src/main/js/navigation/global/components/search/entry/search-module.js"],"sourcesContent":["'use strict';\nvar $TypeError = TypeError;\n\nmodule.exports = function (passed, required) {\n if (passed < required) throw new $TypeError('Not enough arguments');\n return passed;\n};\n","'use strict';\nvar defineBuiltIn = require('../internals/define-built-in');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toString = require('../internals/to-string');\nvar validateArgumentsLength = require('../internals/validate-arguments-length');\n\nvar $URLSearchParams = URLSearchParams;\nvar URLSearchParamsPrototype = $URLSearchParams.prototype;\nvar append = uncurryThis(URLSearchParamsPrototype.append);\nvar $delete = uncurryThis(URLSearchParamsPrototype['delete']);\nvar forEach = uncurryThis(URLSearchParamsPrototype.forEach);\nvar push = uncurryThis([].push);\nvar params = new $URLSearchParams('a=1&a=2&b=3');\n\nparams['delete']('a', 1);\n// `undefined` case is a Chromium 117 bug\n// https://bugs.chromium.org/p/v8/issues/detail?id=14222\nparams['delete']('b', undefined);\n\nif (params + '' !== 'a=2') {\n defineBuiltIn(URLSearchParamsPrototype, 'delete', function (name /* , value */) {\n var length = arguments.length;\n var $value = length < 2 ? undefined : arguments[1];\n if (length && $value === undefined) return $delete(this, name);\n var entries = [];\n forEach(this, function (v, k) { // also validates `this`\n push(entries, { key: k, value: v });\n });\n validateArgumentsLength(length, 1);\n var key = toString(name);\n var value = toString($value);\n var index = 0;\n var dindex = 0;\n var found = false;\n var entriesLength = entries.length;\n var entry;\n while (index < entriesLength) {\n entry = entries[index++];\n if (found || entry.key === key) {\n found = true;\n $delete(this, entry.key);\n } else dindex++;\n }\n while (dindex < entriesLength) {\n entry = entries[dindex++];\n if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value);\n }\n }, { enumerable: true, unsafe: true });\n}\n","'use strict';\nvar defineBuiltIn = require('../internals/define-built-in');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toString = require('../internals/to-string');\nvar validateArgumentsLength = require('../internals/validate-arguments-length');\n\nvar $URLSearchParams = URLSearchParams;\nvar URLSearchParamsPrototype = $URLSearchParams.prototype;\nvar getAll = uncurryThis(URLSearchParamsPrototype.getAll);\nvar $has = uncurryThis(URLSearchParamsPrototype.has);\nvar params = new $URLSearchParams('a=1');\n\n// `undefined` case is a Chromium 117 bug\n// https://bugs.chromium.org/p/v8/issues/detail?id=14222\nif (params.has('a', 2) || !params.has('a', undefined)) {\n defineBuiltIn(URLSearchParamsPrototype, 'has', function has(name /* , value */) {\n var length = arguments.length;\n var $value = length < 2 ? undefined : arguments[1];\n if (length && $value === undefined) return $has(this, name);\n var values = getAll(this, name); // also validates `this`\n validateArgumentsLength(length, 1);\n var value = toString($value);\n var index = 0;\n while (index < values.length) {\n if (values[index++] === value) return true;\n } return false;\n }, { enumerable: true, unsafe: true });\n}\n","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar defineBuiltInAccessor = require('../internals/define-built-in-accessor');\n\nvar URLSearchParamsPrototype = URLSearchParams.prototype;\nvar forEach = uncurryThis(URLSearchParamsPrototype.forEach);\n\n// `URLSearchParams.prototype.size` getter\n// https://github.com/whatwg/url/pull/734\nif (DESCRIPTORS && !('size' in URLSearchParamsPrototype)) {\n defineBuiltInAccessor(URLSearchParamsPrototype, 'size', {\n get: function size() {\n var count = 0;\n forEach(this, function () { count++; });\n return count;\n },\n configurable: true,\n enumerable: true\n });\n}\n","import { analyticsCustomClickHandler } from '../../../../_shared-components/navigationMetrics';\n\nconst conditionalAnalytics = {\n searchHistory: {\n searchTermType: 'autosuggest-recentquery',\n linkName: 'searchbox-_-text-_-autosuggest',\n searchRecentQuerySource: 'product',\n },\n autosuggest: {\n searchTermType: 'autosuggest',\n linkName: 'searchbox-_-text-_-autosuggest',\n },\n natural: {\n searchTermType: 'natural',\n linkName: 'searchbox-_-text-_-searchbutton',\n },\n};\n\n/**\n * Determines the search type based on the aria-activedescendant value.\n *\n * @param {string} [ariaAD] - The aria-activedescendant value\n * from the search field.\n * @returns {'searchHistory' | 'autosuggest' | 'natural'} - the type of\n * search sumbission, listbox selection or text entry (natural)\n */\nconst getSearchType = (ariaAD) => {\n if (ariaAD) {\n if (ariaAD.startsWith('search-history')) return 'searchHistory';\n if (ariaAD.startsWith('autosuggest')) return 'autosuggest';\n }\n return 'natural';\n};\n\n/**\n * Extracts the index number from an aria-activedescendant value.\n *\n * @param {string} [ariaAD=''] - The aria-activedescendant attribute value.\n * @returns {string | null} - The extracted index if found, otherwise null.\n */\nconst getTermIndex = (ariaAD = '') => {\n const match = ariaAD.match(/-([^-]*)$/);\n const lastString = match?.[1];\n const isNumber = lastString && !Number.isNaN(Number(lastString));\n return isNumber ? lastString : null;\n};\n\n/**\n * Retrieves the appropriate analytics object for a given search type.\n *\n * @param {string} ariaAD - The aria-activedescendant value.\n * @param {'searchHistory' | 'autosuggest' | 'natural'} searchType\n * The detected search type (see getSearchType)\n * @param {object} [condAnalytics=conditionalAnalytics] - additional analytics\n * object, specific to the search type (see conditionalAnalytics above)\n * @returns {object} - The resolved analytics object, with position added.\n */\nconst getConditionalAnalytics = (\n ariaAD,\n searchType,\n condAnalytics = conditionalAnalytics\n) => {\n const analytics = condAnalytics[searchType];\n if (searchType !== 'natural' && analytics) {\n // this is the position indicator regardless of which listbox\n analytics.autoSuggestPosition = getTermIndex(ariaAD);\n }\n return analytics || {};\n};\n\n/**\n * The finalized analtyics object\n *\n * @param {string} ariaAD - The aria-activedescendant value.\n * @param {string} searchTerm - The submitted search term.\n * @returns {object} - The complete analytics data for submission.\n */\nconst getSumbitAnalytics = (ariaAD, searchTerm) => {\n if (!searchTerm) return null;\n const searchType = getSearchType(ariaAD);\n\n return {\n events: 'event1',\n searchTermClicked: searchTerm,\n ...getConditionalAnalytics(ariaAD, searchType),\n };\n};\n\n/**\n * gets finalized analytics and submits them\n * also includes convenience logging for env without metrics available\n *\n * @param {string} ariaAD - The aria-activedescendant value.\n * @param {string} searchTerm - The submitted search term.\n */\nconst handleSearchFormSubmissionAnalytics = (ariaAD, searchTerm) => {\n const config = getSumbitAnalytics(ariaAD, searchTerm);\n if (!config) return;\n\n // help with reviewing analytics locally or on try server\n if (document?.location?.hostname !== 'www.rei.com') {\n /* eslint-disable no-console */\n console.group('Metrics link config - searchMetrics');\n Object.entries(config).forEach(([key, value]) => {\n console.log(`${key}: ${value}`);\n });\n console.groupEnd();\n /* eslint-enable no-console */\n }\n\n analyticsCustomClickHandler(config);\n};\n\nexport {\n getSearchType,\n getTermIndex,\n getConditionalAnalytics,\n getSumbitAnalytics,\n handleSearchFormSubmissionAnalytics,\n};\n","/**\n * Search Form, input field, clear button, and search button\n *\n * Separation of concerns is very important here, as the JS and templates\n * here have to work alongside external components (namely, autosuggest,\n * and eventually search history).\n *\n * Code here should only apply to the elements above(e.g. the basic search\n * form). Nothing that applies to a supplemental search form package should\n * be included here (for example: adjusting Search History state)\n *\n * This file is also the sole source of handling analytics events on\n * form submission. Outside components should send a 'termSelected' custom\n * event rather than calling submit() directly on the search form.\n */\nimport { getDomElems } from '../../../../_shared-components/getDomElems';\nimport { handleSearchFormSubmissionAnalytics } from './searchMetrics';\n\n/**\n * Retrieves a search query parameter from the current URL.\n *\n * @param {string} param - The name of the query parameter to retrieve.\n * @returns {string|null} The value of the query parameter, or null if not found.\n */\nconst getSearchParam = (param) => {\n const params = new URLSearchParams(window.location.search);\n return params.get(param);\n};\n\n/**\n * Displays the clear button and adjusts the search field's margin.\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n * @param {HTMLElement} clearButton - The clear button element.\n */\nconst showClearButton = (searchField, clearButton) => {\n clearButton.removeAttribute('aria-hidden');\n clearButton.setAttribute('data-visible', 'visible');\n searchField.setAttribute('style', 'margin-right: -44px;');\n};\n\n/**\n * Hides the clear button and resets the search field's margin.\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n * @param {HTMLElement} clearButton - The clear button element.\n */\nconst hideClearButton = (searchField, clearButton) => {\n clearButton.setAttribute('aria-hidden', 'true');\n clearButton.setAttribute('data-visible', 'hidden');\n searchField.setAttribute('style', 'margin-right: 0;');\n};\n\n/**\n * Toggles the visibility of the clear button based on the search field's value.\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n * @param {HTMLElement} clearButton - The clear button element.\n */\nconst setClearButtonVisibility = (searchField, clearButton) => {\n if (!searchField.value) {\n hideClearButton(searchField, clearButton);\n } else {\n showClearButton(searchField, clearButton);\n }\n};\n\n/**\n * Enables or disables the search button based on the search field's value.\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n * @param {HTMLButtonElement} searchButton - The search button element.\n */\nconst enableSearchButton = (searchField, searchButton) => {\n if (searchField.value.trim().length === 0) {\n searchButton.classList.add('search__search-button--disabled');\n searchButton.setAttribute('aria-disabled', 'true');\n searchButton.setAttribute('disabled', 'disabled');\n } else if (searchField.value.trim().length > 0) {\n searchButton.classList.remove('search__search-button--disabled');\n searchButton.setAttribute('aria-disabled', 'false');\n searchButton.removeAttribute('disabled');\n }\n};\n\n/**\n * Clears the search field's value and refocuses it.\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n */\nconst clearSearchField = (searchField) => {\n const inputElem = searchField;\n inputElem.value = '';\n searchField.focus();\n};\n\n// used to ensure analytics don't send twice\nlet analyticsLogged = false;\n\n/**\n * handle sending analytics\n * triggered on either natural search (term in box, enter/searchbutton)\n * Or when \"termSelected\" event is dispatched by autosuggest or recents\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n */\nconst handleAnalytics = (searchField) => {\n if (analyticsLogged) return;\n const searchTerm = searchField.value;\n const ariaActivedescendant = searchField.getAttribute('aria-activedescendant');\n handleSearchFormSubmissionAnalytics(ariaActivedescendant, searchTerm);\n analyticsLogged = true;\n};\n\n/**\n * Handles the \"termSelected\" event, triggering analytics tracking,\n * and submitting the search form.\n *\n * @param {HTMLInputElement} searchField - The search input field element.\n * @param {HTMLFormElement} searchForm - The search form element.\n * @param {Event} e\n */\nconst handleTermSelected = (searchField, searchForm, e) => {\n e.preventDefault();\n handleAnalytics(searchField);\n searchForm.submit();\n};\n\n/**\n * Initializes the search form event listeners and sets up analytics tracking.\n *\n * @param {Object} selectors - The object containing CSS selectors for various form elements.\n * @param {string} selectors.searchForm - Selector for the search form element.\n * @param {string} selectors.searchField - Selector for the search input field.\n * @param {string} selectors.clearButton - Selector for the search clear button.\n * @param {string} selectors.searchButton - Selector for the search submit button.\n */\nconst init = (selectors) => {\n // check that all needed elements are available\n const searchElems = getDomElems(selectors);\n if (searchElems === null) return;\n\n analyticsLogged = false;\n\n const {\n searchForm,\n searchField,\n clearButton,\n searchButton,\n } = searchElems;\n\n // if we're on a search page with a query, populate the search field with it\n searchField.value = getSearchParam('q');\n // set initial clear button visibility based on above\n setClearButtonVisibility(searchField, clearButton);\n // enable or disable search button based on above\n enableSearchButton(searchField, searchButton);\n\n // Clear button event listeners\n clearButton.addEventListener('click', () => {\n clearSearchField(searchField);\n setClearButtonVisibility(searchField, clearButton);\n enableSearchButton(searchField, searchButton);\n });\n searchField.addEventListener('keyup', () => {\n setClearButtonVisibility(searchField, clearButton);\n });\n\n // search button event listener\n searchField.addEventListener('input', () => {\n enableSearchButton(searchField, searchButton);\n });\n\n // term submission/analytics event listeners\n document.addEventListener('termSelected', (e) => {\n handleTermSelected(searchField, searchForm, e);\n });\n searchForm.addEventListener('submit', (e) => {\n handleAnalytics(searchField, searchForm, e);\n });\n};\n\nexport default init;\n","const sliceSize = 10;\n\nexport const cleanSearchResult = (item) => item.replace(/\\s?-?'?/gi, '');\n\nexport const getStartsWithData = (data, cleanedSearchTerm) => data\n .filter((item) => cleanSearchResult(item).startsWith(cleanedSearchTerm));\n\nexport const getIncludesData = (data, cleanedSearchTerm) => data\n .filter((item) => !cleanSearchResult(item).startsWith(cleanedSearchTerm)\n && cleanSearchResult(item).includes(cleanedSearchTerm));\n\nexport const partitionData = (data, cleanSearchTerm) => data.map((term) => {\n // Build a regular expression pattern with optional special characters\n // in-between each letter of the search term\n let optionalSpecialCharacterPattern = '';\n for (let i = 0, len = cleanSearchTerm.length; i < len; i += 1) {\n optionalSpecialCharacterPattern += `${cleanSearchTerm[i]}\\\\W*`;\n }\n\n // Create the regular expression, ignoring case and matching only the first occurrence\n const optionalSpecialCharacterRegExp = new RegExp(optionalSpecialCharacterPattern, 'i');\n\n // Match the search term with optional special characters to the item in the term list\n const matches = term.match(optionalSpecialCharacterRegExp);\n\n // Define the parameters that allow search term highlighting in the term\n // list, note there should only ever be one occurrence\n const displayTerm = matches ? matches[0] : cleanSearchTerm;\n\n return {\n searchTerm: displayTerm,\n resultTitle: term,\n };\n});\n\nexport const cleanSearchTerm = (term) => {\n // Regular expression to match all non-word (special) characters\n const specialCharacterRegExp = term.length > 1 ? /\\W/g : '';\n\n return term.toLowerCase().replace(/[^a-z\\d]/gi, '').replace(specialCharacterRegExp, '');\n};\n\nexport const cleanFetchedItems = (fetchedItems) => [...fetchedItems]\n .map((item) => item.term.toLowerCase());\n\n/** @param {function} filterResults takes @param {array} fetchedItems and filters it by using\n * the current value from the input box, as well as multiple steps of regex that return\n * matched string characters to allow for dynamic styling\n */\nexport default (value = '', state = {}) => {\n const newState = state;\n /** @param {function} filterResults takes @param {array} fetchedItems and filters it by using\n * the current value from the input box, as well as multiple steps of regex that return\n * matched string characters to allow for dynamic styling\n */\n const cleanedSearchTerm = cleanSearchTerm(value);\n\n if (!newState.fetchedItems.length) return [];\n // Grab all the values from fetchedItems and map over them to produce a\n // new array that has them lowercased and with only their term\n let data = cleanFetchedItems(newState.fetchedItems);\n\n // Grabs data that starts with search term\n const startsWithData = getStartsWithData(data, cleanedSearchTerm);\n\n // Grabs data that contains, but doesn't start with search term\n const includesData = getIncludesData(data, cleanedSearchTerm);\n\n // Combines data sets, if needed\n data = (startsWithData.length < sliceSize) ? startsWithData.concat(includesData) : startsWithData;\n\n // partition search results into the entered chars and remaining chars\n data = partitionData(data, cleanedSearchTerm);\n\n newState.filteredResults = data.slice(0, sliceSize);\n return newState.filteredResults;\n};\n","const SEARCH_HISTORY = {\n LI_ID: (index) => `search-history-entry-${index}`,\n UL_ID: 'gnav-recent-search-list',\n LOCAL_STORAGE_KEY: 'savedSearches',\n SELECTOR: '[data-js=recent-search-box]',\n RECENTLY_SELECTED: 'recentSearchTermSelected',\n DELETE: {\n ID: 'search-history-delete',\n CSS: 'search-history__button',\n TEXT: 'Clear History',\n },\n TITLE: {\n CSS: 'search-history__title',\n TEXT: 'Search History',\n },\n};\n\nconst AUTOSUGGEST = {\n LI_ID: (index) => `autosuggest-result-${index}`,\n UL_ID: 'gnav-suggestion-list',\n SELECTOR: '[data-js=suggestion-box]',\n URL: {\n FALLBACK: 'https://www.rei.com/autosuggest/online/details',\n },\n};\n\nconst LISTBOX = {\n CSS: {\n VISUAL_FOCUS: 'searchbox-term',\n LIST_ITEM: 'searchbox-result',\n },\n ARIA_LIVE: {\n DIRECTIONS: 'Keyboard users, use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.',\n SELECTOR: '[data-js=\"feedback-holder\"]',\n },\n ALL_LI: {\n SELECTOR: `[id^=${AUTOSUGGEST.LI_ID('')}], [id^=${SEARCH_HISTORY.LI_ID('')}]`,\n },\n URL: {\n DOMAIN: 'https://www.rei.com/',\n },\n};\n\nexport {\n AUTOSUGGEST,\n SEARCH_HISTORY,\n};\nexport default LISTBOX;\n","/**\n * Listbox Utils | Search History & Autosuggest\n * Search History and Autosuggest are very similar in functionality, but must be able to work\n * independently of one another. This module is for methods that are used in both recents and\n * autosuggest listboxes.\n * @see [Definition of listbox]{@link https://www.w3.org/TR/wai-aria-practices/#Listbox}.\n * Used in reference to [combo box]{@link https://www.w3.org/TR/wai-aria-practices/#combobox}\n */\nimport { code, getKeyCode, keyCode } from '../../../../_shared-components/keyCode';\nimport LISTBOX from './constants';\n\n/**\n * Keys whose default action should be ignored on a keydown event.\n * @param {KeyboardEvent} e\n */\nconst preventDefaultOnKeyDown = (e) => {\n const keyCodeVal = getKeyCode(e);\n switch (keyCodeVal) {\n case code.ARROW_DOWN:\n case keyCode.ARROW_DOWN:\n case code.ARROW_UP:\n case keyCode.ARROW_UP:\n case code.END:\n case keyCode.END:\n e.preventDefault();\n break;\n default:\n break;\n }\n};\n\nconst getUpdatedIndexOnArrowDown = (currentIndex, length) => (\n (currentIndex < length - 1 && currentIndex > -1) ? currentIndex + 1 : 0\n);\n\nconst getUpdatedIndexOnArrowUp = (currentIndex, length) => (\n (currentIndex <= length && currentIndex > 0) ? currentIndex - 1 : length - 1\n);\n\n/**\n * Sets the input field with the value.\n * @param {HTMLInputElement} searchField\n * @param {string} value\n */\nconst setSearchField = (searchField, value = '') => {\n const search = searchField;\n search.value = value;\n};\n\n/**\n * Iterates through list entries and removes css indicating visual focus.\n * @param {HTMLLIElement[]} listEntries\n */\nconst cleanListEntries = (listEntries) => {\n [...listEntries].forEach((elem) => {\n elem.classList.remove(LISTBOX.CSS.VISUAL_FOCUS);\n elem.removeAttribute('aria-selected');\n });\n};\n\nconst resetListbox = (searchField, listEntries) => {\n searchField.setAttribute('aria-activedescendant', '');\n cleanListEntries(listEntries);\n};\n\n/**\n * Index for the list item element is the last substring of the id when split on '-'.\n * @param {HTMLLIElement} elem\n * @returns {number|number}\n */\nconst getIndexFromElement = (elem) => {\n const { id = null } = elem || {};\n const wordsArr = !id ? [] : id.split('-');\n return wordsArr.length < 1 ? -1 : (wordsArr[wordsArr.length - 1] * 1);\n};\n\n/**\n * Adds visual focus to a single listItem and updates aria-live region with descriptive context.\n * @param {HTMLInputElement} searchField\n * @param {HTMLLIElement} listItem - entry to add visual focus to\n * @param {HTMLLIElement[]} listEntries - button element only for clear history\n */\nconst setVisualFocus = (searchField, listItem, listEntries) => {\n cleanListEntries(listEntries);\n searchField.setAttribute('aria-activedescendant', listItem.id);\n listItem.setAttribute('aria-selected', 'true');\n listItem.classList.add(LISTBOX.CSS.VISUAL_FOCUS);\n};\n\n/**\n * @param {HTMLDivElement} listboxElem - which contains the data-visible attribute which may\n * need to be updated\n * @param {boolean} newValue - most recent result of logic determining if listbox should visible\n * (true) or hidden (false)\n * @returns {boolean} - true if a difference exists between the previous and newValue\n */\nconst shouldUpdateVisibility = (listboxElem, newValue) => {\n const { dataset: { visible: visibleValue } } = listboxElem;\n const oldValue = visibleValue === 'visible';\n return oldValue !== newValue;\n};\n\nconst addMouseMoveEventListeners = (dynamicElem, enterCallback, leaveCallback) => {\n dynamicElem.addEventListener('mouseenter', enterCallback);\n dynamicElem.addEventListener('mouseleave', leaveCallback);\n};\n\n/**\n * A custom event for when a search term is selected.\n * Used to indicate to search.js to handle the search input submit event\n * and send analytics. This keeps the submission/analytics concern\n * housed ONLY in search.js\n *\n * @constant {CustomEvent} termSelectedEvent\n * @event termSelected\n */\nconst termSelectedEvent = new CustomEvent(\n 'termSelected',\n {\n bubbles: true,\n cancelable: true,\n },\n);\n\n/**\n * Retrieves the `id` and `textContent` of a list item (`
  • `).\n * Used for updating the search field when an autosuggest or\n * search history term is selected\n *\n * @param {HTMLElement} li - The
  • element to extract data from.\n * @returns {{ id: string, selectedText: string } | null}\n * An object containing the `id` and trimmed `selectedText`,\n * or null if li is not an
  • .\n */\nconst getTextAndIdFromListEl = (li) => {\n if (li instanceof HTMLLIElement) {\n return {\n id: li.id,\n selectedText: li.textContent.trim(),\n };\n }\n return null;\n};\n\n/**\n * Retrieves the currently selected
  • element using the\n * aria-activedescendant attribute.\n *\n * Because the aria-activedescendant value is set to the currently\n * selected list item `id` in a combobox's listbox, you can use that\n * as a selector to find the selected item.\n *\n * NOTE: this does rely on proper management of focus/hover states by\n * the JS managing the listbox (e.g. that aria-activedescendant is properly\n * updated).\n *\n * Refer to the combobox pattern for details:\n * https://www.w3.org/WAI/ARIA/apg/patterns/combobox/#wai-ariaroles,states,andproperties\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @param {HTMLElement} listbox - The listbox element containing the options.\n * (search history or autosuggest)\n * @returns {HTMLLIElement | null} - The selected
  • element, or null\n */\nconst getSelectedListElementByAria = (searchField, listbox) => {\n const id = searchField?.getAttribute('aria-activedescendant');\n const li = id ? listbox?.querySelector(`#${id}`) : null;\n return li && li instanceof HTMLLIElement ? li : null;\n};\n\n/**\n * Determines the type of listbox (search history or autosuggest)\n * based on the aria-activedescendant value.\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @returns {'search-history' | 'autosuggest' | null} - The type of listbox,\n * or `null` if unknown.\n */\nconst getListboxType = (searchField) => {\n const id = searchField?.getAttribute('aria-activedescendant');\n if (id?.startsWith('search-history')) return 'search-history';\n if (id?.startsWith('autosuggest')) return 'autosuggest';\n return null;\n};\n\n/**\n * Updates the aria-activedescendant attribute and sets the search field value.\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @param {string} selectedText - The text to set in the search field.\n * @param {string} [id=''] - The ID of the selected listbox item.\n */\nconst updateAriaAndSearchTerm = (\n searchField,\n selectedText,\n id = '',\n) => {\n setSearchField(searchField, selectedText);\n searchField.setAttribute('aria-activedescendant', id);\n};\n\n/**\n * Updates the aria-activedescendant attribute and sets the search field value.\n * and dispatches a `termSelected` event when a search term is chosen\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @param {string} selectedText - The selected search term.\n * @param {string} [id=''] - The ID of the selected item.\n */\nconst dispatchTermSelectedEvent = (\n searchField,\n selectedText,\n id = '',\n) => {\n if (selectedText && searchField) {\n updateAriaAndSearchTerm(searchField, selectedText, id);\n document.dispatchEvent(termSelectedEvent);\n }\n};\n\nexport {\n addMouseMoveEventListeners,\n getUpdatedIndexOnArrowDown,\n getUpdatedIndexOnArrowUp,\n getIndexFromElement,\n preventDefaultOnKeyDown,\n resetListbox,\n shouldUpdateVisibility,\n setSearchField,\n setVisualFocus,\n termSelectedEvent,\n getTextAndIdFromListEl,\n getSelectedListElementByAria,\n getListboxType,\n updateAriaAndSearchTerm,\n dispatchTermSelectedEvent,\n};\n","import { getDomElems } from '../../../../_shared-components/getDomElems';\n\n/**\n * Manages aria-live regions to announce updates for screen readers.\n * Handles polite announcements, prevents overlapping messages, and debounces\n * updates to avoid excessive chatter.\n *\n * This is based on the example at https://alphagov.github.io/accessible-autocomplete/examples/\n * Which is from the UK's Government Digital Service\n *\n * Notably:\n * * it uses two swapping boxes (same as in the @rei/aria-announcer package) - this\n * reduces the liklihood of announcements being skipped\n * * it uses a long delay - this is necessary due to the extremely long default\n * screen reader chatter that occurs upon first focusing a combobox, and when\n * typing in one. Without the delay, the only options are to interrupt that,\n * and cause the user to use expected/critical information, or to chance losing\n * the announcement (this was happening every time on first focus of the box\n * for search history).\n *\n * This Handler requires three elements to initialize: The search input field\n * and the two feedback holders.\n * In main.js, it also is only set to initialize if either Search History or\n * Autosuggest is enabled\n * !Important: @private methods should not be used directly, eslint is unhappy\n * with # for private methods (not sure why, it should support, but out of scope\n * for current ticket)\n */\nclass AriaLiveHandler {\n constructor() {\n this.instance = null;\n this.enabled = false;\n this.debounceTimer = null;\n this.searchFieldEl = null;\n // Ensure 'this' is preserved for event callbacks\n this.abortPendingUpdate = this.abortPendingUpdate.bind(this);\n\n this.box1 = {\n hasText: false,\n el: null,\n setText(text) {\n this.el.textContent = text;\n this.hasText = true;\n },\n clearText() {\n this.el.textContent = '';\n this.hasText = false;\n },\n };\n\n this.box2 = {\n hasText: false,\n el: null,\n setText(text) {\n this.el.textContent = text;\n this.hasText = true;\n },\n clearText() {\n this.el.textContent = '';\n this.hasText = false;\n },\n };\n }\n\n static getInstance() {\n if (!AriaLiveHandler.instance) {\n AriaLiveHandler.instance = new AriaLiveHandler();\n }\n return AriaLiveHandler.instance;\n }\n\n /**\n * Initializes the aria-live handler by locating DOM elements and\n * attaching event listeners.\n *\n * @param {Object} selectors - keyed selectors for required elements (noted at top)\n * @param {string} selectors.ariaBox1 - Selector for the first aria-live element.\n * @param {string} selectors.ariaBox2 - Selector for the second aria-live element.\n * @param {string} selectors.searchField - Selector for the input field triggering updates.\n */\n init(selectors) {\n // returns null if selectors don't all return HTML el\n const ariaElems = getDomElems(selectors);\n\n // if any els missing, leave AriaLiveHandlers.enabled as false, exit\n if (!ariaElems) return;\n\n // otherwise, enable and track dom els in state\n this.enabled = true;\n this.box1.el = ariaElems.ariaBox1;\n this.box2.el = ariaElems.ariaBox2;\n this.searchFieldEl = ariaElems.searchField;\n\n // and add shared event listeners\n this.searchFieldEl.addEventListener('blur', this.abortPendingUpdate);\n }\n\n /**\n * Clears the text content of both aria-live boxes if they have text.\n * @private\n */\n clearAllBoxes() {\n if (this.box1.hasText) this.box1.clearText();\n if (this.box2.hasText) this.box2.clearText();\n }\n\n /**\n * Updates the appropriate aria-live region while ensuring debounce behavior.\n * Ensures that if a message queue exists, only the latest text is announced.\n *\n * @param {string} boxToSet - The key ('box1' or 'box2') of the box to update.\n * @param {string} otherBox - The key ('box1' or 'box2') of the box to clear.\n * @param {string} text - The text to announce.\n * @private\n */\n setTextByBox(boxToSet, otherBox, text) {\n clearTimeout(this.debounceTimer);\n\n if (!text) {\n this.clearAllBoxes();\n return;\n }\n\n this[otherBox].clearText();\n\n this.debounceTimer = setTimeout(() => {\n this[boxToSet].setText(text);\n }, 1000);\n }\n\n /**\n * Aborts any pending updates and clears the aria-live regions.\n * Prevents stale messages from being announced.\n */\n abortPendingUpdate() {\n if (!this.enabled) return;\n // This essentially clears the \"aria-live\" queue\n this.clearAllBoxes();\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n\n /**\n * Updates the aria-live region with new text, alternating between two boxes.\n * Ensures that screen readers announce updates reliably without repeating old messages.\n *\n * @param {string} text - The text to announce via aria-live.\n */\n updateAriaLiveRegion(text) {\n if (!this.enabled) return;\n if (typeof text !== 'string') return;\n\n if (!this.box1.hasText) {\n this.setTextByBox('box1', 'box2', text);\n } else {\n this.setTextByBox('box2', 'box1', text);\n }\n }\n}\n\nexport default AriaLiveHandler;\n","/**\n * Autosuggest\n * Contains main functionality for the search autosuggest.\n */\nimport { getDomElems } from '../../../../_shared-components/getDomElems';\nimport filterResults from './filterResults';\nimport getScriptData from '../../util/getScriptData';\nimport { getKeyCode, code } from '../../../../_shared-components/keyCode';\nimport LISTBOX, { AUTOSUGGEST } from './constants';\nimport * as listbox from './listboxUtil';\nimport AriaLiveHandler from './AriaLiveHandler';\n\nlet ariaLiveInstance;\n\n/**\n * State holds the values for autosuggest and includes\n * @param {array} fetchedItems which is the result of the fetch call,\n * @param {array} filteredResults is an array of ten results,\n*/\nconst state = {\n fetchedItems: [],\n filteredResults: [],\n};\n\n/**\n * Determines whether the autosuggest listbox is open.\n *\n * - Checks if the `suggestionBox` element exists in the state.\n * - Retrieves its `data-visible` attribute.\n * - Returns true if the value is 'visible', otherwise false.\n *\n * @returns {boolean} - true if the autosuggest listbox is open.\n */\nconst autosuggestListboxIsOpen = () => {\n const { suggestionBox } = state;\n const { dataset: { visible } } = suggestionBox;\n return visible === 'visible';\n};\n\n/**\n * Grabs Autosuggest data JSON from #gnav-data blob. If not found uses absolute url fallback value\n * @returns {string} url\n */\nconst getAutosuggestTarget = () => {\n const {\n autosuggestTarget: targetUrl = null,\n } = getScriptData('gnav-data') || {};\n return targetUrl === null ? AUTOSUGGEST.URL.FALLBACK : targetUrl;\n};\n\n/**\n * Pings an endpoint and assigns the results to state's fetchedItems property. If an error occurs,\n * it is logged to the dev console and fetchedItems is set to an empty array.\n * @param {string} fetchPoint: url to ping\n */\nexport const fetchData = (fetchPoint) => {\n fetch(fetchPoint)\n .then((response) => {\n const { ok, status, url } = response || {};\n if (!ok) {\n // eslint-disable-next-line no-console\n console.error(`url: ${url} is responding with status code: ${status}`);\n }\n return ok ? response.json() : [];\n })\n .then((response) => {\n state.fetchedItems = response;\n })\n // eslint-disable-next-line no-console\n .catch((e) => console.error(e));\n};\n\n/**\n * If resultTitle exists then returns string containing bolded substring via markup.\n * Otherwise returns unchanged searchTerm string.\n * @param {string} searchTerm\n * @param {string} resultTitle\n * @returns {*}\n */\nconst getInnerHtml = (searchTerm, resultTitle) => (\n resultTitle.replace(searchTerm, `${searchTerm}`)\n);\n\n/**\n * @param {number} resultCount - current number of available autosuggest options\n * @param {string} searchTerm - the characters contained within the search input\n * @returns {string} - description of available autosuggest options for a searchTerm,\n * including directions on how to navigation the open listbox.\n */\nconst updateAriaLiveText = (resultCount, searchTerm) => {\n // let the user know if there are no suggestions for that term\n if (resultCount === 0) {\n ariaLiveInstance.updateAriaLiveRegion(\n `There are ${resultCount} results available that contain ${searchTerm}.`\n );\n }\n if (resultCount === 1) {\n ariaLiveInstance.updateAriaLiveRegion(\n `There is 1 result available that contains ${searchTerm}. ${LISTBOX.ARIA_LIVE.DIRECTIONS}`\n );\n }\n if (resultCount > 1) {\n ariaLiveInstance.updateAriaLiveRegion(\n `There are ${resultCount} results available that contain ${searchTerm}. ${LISTBOX.ARIA_LIVE.DIRECTIONS}`\n );\n }\n};\n\n/**\n * Will remove visual focus for autosuggest list item when mouse leaves element.\n * Updates aria-live text to total result count\n * @param e\n */\nconst onMouseLeave = (e) => {\n const { target } = e;\n const { suggestionBox, searchField } = state;\n const listEntries = suggestionBox.querySelectorAll(LISTBOX.ALL_LI.SELECTOR);\n /* only remove visual focus if target has it, otherwise do nothing */\n if (target.classList.contains(LISTBOX.CSS.VISUAL_FOCUS)) {\n listbox.resetListbox(searchField, listEntries);\n }\n};\n\n/**\n * Add visual focus to autosuggest list item.\n * @param e\n */\nconst onMouseEnter = (e) => {\n const { target } = e;\n const { suggestionBox, searchField } = state;\n const listEntries = suggestionBox.querySelectorAll(LISTBOX.ALL_LI.SELECTOR);\n listbox.setVisualFocus(searchField, target, listEntries);\n};\n\n/**\n * Creates and appends markup to the DOM containing the list of autosuggest options with the\n * relevant characters bolded.\n * @param {object[]} results Array of (at most 10) options\n *\n * About data-cnstrc-item-section and data-cnstrc-item-name attributes:\n * https://docs.constructor.com/docs/integrating-with-constructor-behavioral-tracking-data-driven-event-tracking#result-item\n * https://docs.constructor.com/docs/faq-api-what-is-a-section-as-referenced-in-the-api\n */\nexport const appendResults = (results) => {\n const { suggestionList } = state;\n /* remove contents from ul element */\n const ul = suggestionList;\n ul.innerHTML = '';\n /* add list items to ul */\n [...results].forEach(({ searchTerm, resultTitle }, index) => {\n const li = document.createElement('li');\n li.className = LISTBOX.CSS.LIST_ITEM;\n /* id with index used for tracking focus & building metrics */\n li.id = AUTOSUGGEST.LI_ID(index);\n li.innerHTML = getInnerHtml(searchTerm, resultTitle);\n li.setAttribute('role', 'option');\n li.setAttribute('aria-label', resultTitle);\n /* Add Constructor search beacon tracking attributes */\n li.setAttribute('data-cnstrc-item-section', 'Search Suggestions');\n li.setAttribute('data-cnstrc-item-name', resultTitle);\n listbox.addMouseMoveEventListeners(li, onMouseEnter, onMouseLeave);\n ul.appendChild(li);\n });\n};\n\n/**\n * Controls visibility / expand-collapse of autosuggestion listbox\n * @param {HTMLDivElement} suggestionBox - element that contains the list entries of recent\n * searches or filtered results\n * @param {HTMLInputElement} searchField - input element of search field\n * @param {boolean} isVisible - boolean used to determine state of visibility / expansion\n */\nexport const setSuggestionBoxVisibility = (suggestionBox, searchField, isVisible = false) => {\n if (!isVisible) {\n listbox.resetListbox(searchField, [...suggestionBox.querySelectorAll(LISTBOX.ALL_LI.SELECTOR)]);\n }\n searchField.setAttribute('aria-expanded', `${isVisible}`);\n suggestionBox.setAttribute('data-visible', isVisible ? 'visible' : 'hidden');\n};\n\nconst onFocus = (suggestionBox, e) => {\n const { target: searchField } = e;\n const searchTerm = searchField.value.trim();\n if (searchTerm.length > 0) {\n /* update state */\n state.filteredResults = filterResults(searchTerm, state);\n const { filteredResults } = state;\n appendResults(filteredResults);\n const isVisible = (filteredResults && filteredResults.length > 0);\n if (listbox.shouldUpdateVisibility(suggestionBox, isVisible)) {\n setSuggestionBoxVisibility(suggestionBox, searchField, isVisible);\n }\n updateAriaLiveText(filteredResults.length, searchTerm);\n }\n};\n\nconst onBlur = (suggestionBox, e) => {\n const { target: searchField } = e;\n setSuggestionBoxVisibility(suggestionBox, searchField);\n};\n\n/**\n * Handles mouse down events on the autosuggest listbox.\n *\n * - Retrieves the currently selected
  • element.\n * - If no item is selected, the function exits.\n * - If the selected item has valid text, it dispatches a termSelected event.\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @param {HTMLElement} suggestionList - The autosuggest listbox.\n */\nconst onMouseDown = (searchField, suggestionList) => {\n const li = listbox.getSelectedListElementByAria(searchField, suggestionList);\n if (!li) return;\n const { id, selectedText } = listbox.getTextAndIdFromListEl(li);\n if (!selectedText) return;\n listbox.dispatchTermSelectedEvent(searchField, selectedText, id);\n};\n\n/**\n * Handles the keyboard logic for list entries in SuggestionBox\n * @param e\n */\nexport const onKeyUp = (e) => {\n const {\n suggestionBox,\n searchField,\n } = state;\n if (!autosuggestListboxIsOpen()) return;\n\n const listEntries = suggestionBox.querySelectorAll(`.${LISTBOX.CSS.LIST_ITEM}`);\n const currentIndex = listbox.getIndexFromElement(suggestionBox.querySelector(`.${LISTBOX.CSS.VISUAL_FOCUS}`));\n const keyCodeVal = getKeyCode(e);\n const searchTerm = searchField.value?.trim();\n switch (keyCodeVal) {\n case code.ARROW_DOWN: {\n const updatedIndex = listbox.getUpdatedIndexOnArrowDown(currentIndex, listEntries.length);\n listbox.setVisualFocus(searchField, listEntries[updatedIndex], listEntries);\n }\n break;\n case code.ARROW_UP: {\n const updatedIndex = listbox.getUpdatedIndexOnArrowUp(currentIndex, listEntries.length);\n listbox.setVisualFocus(searchField, listEntries[updatedIndex], listEntries);\n }\n break;\n case code.ESCAPE:\n listbox.setSearchField(searchField);\n searchField.focus();\n setSuggestionBoxVisibility(suggestionBox, searchField);\n\n break;\n case code.END:\n searchField.focus();\n /* places cursor at the end text in field (if any) */\n searchField.setSelectionRange(searchField.value.length, searchField.value.length);\n listbox.resetListbox(searchField, listEntries);\n\n break;\n case code.HOME:\n searchField.focus();\n listbox.resetListbox(searchField, listEntries);\n\n break;\n case code.ARROW_LEFT:\n case code.ARROW_RIGHT:\n listbox.resetListbox(searchField, listEntries);\n\n break;\n default:\n if (searchTerm?.length < 1) {\n ariaLiveInstance.abortPendingUpdate();\n }\n break;\n }\n};\n\n/**\n * Handles keydown events for the autosuggest listbox.\n *\n * - Exits immediately if the autosuggest listbox is not open.\n * - If the key pressed is not \"Enter\", calls the listbox\n * preventDefaultOnKeyDown and exits.\n * - Retrieves the currently selected list item:\n * - If no item is selected, the function exits.\n * - If the selected item has no valid text, the function exits.\n * - Otherwise, it dispatches a termSelected event.\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @param {HTMLElement} suggestionList - The autosuggest listbox.\n * @param {KeyboardEvent} e - The keydown event object.\n */\nconst onKeyDown = (searchField, suggestionList, e) => {\n if (!autosuggestListboxIsOpen()) return;\n const keyCodeVal = getKeyCode(e);\n\n // handler for navigation key events\n // see listbox - this only applies to certain keys\n if (keyCodeVal !== code.ENTER && keyCodeVal !== code.NUMPAD_ENTER) {\n listbox.preventDefaultOnKeyDown(e);\n return;\n }\n\n // handler for potential selection of search terms\n // we can use aria to determine if this is a listbox selection\n const li = listbox.getSelectedListElementByAria(searchField, suggestionList);\n if (!li) return;\n\n const { id, selectedText } = listbox.getTextAndIdFromListEl(li);\n if (!selectedText) return;\n\n e.preventDefault();\n listbox.dispatchTermSelectedEvent(searchField, selectedText, id);\n};\n\n/**\n * Updates filteredResults, DOM, and/or toggles visibility as needed before invoking\n * onKeyUp method.\n * @param {HTMLDivElement} suggestionBox\n * @param {HTMLInputElement} searchField\n * @param {KeyboardEvent} e\n */\nconst onInput = (suggestionBox, searchField) => {\n const searchTerm = searchField.value.trim();\n\n // if there's still a search history announcement pending,\n // clear it when the first character is typed\n if (searchTerm?.length === 1) {\n ariaLiveInstance.abortPendingUpdate();\n }\n\n /* only update DOM when necessary */\n state.filteredResults = filterResults(searchTerm, state);\n appendResults(state.filteredResults);\n\n const resultLength = state.filteredResults?.length;\n const isVisible = (searchTerm !== '' && (resultLength > 0));\n if (listbox.shouldUpdateVisibility(suggestionBox, isVisible)) {\n setSuggestionBoxVisibility(suggestionBox, searchField, isVisible);\n }\n\n // we only really need to update this on input\n if (searchTerm.length > 0) {\n updateAriaLiveText(resultLength, searchTerm);\n }\n};\n\n/* init */\nconst init = (selectors) => {\n const searchElems = getDomElems(selectors);\n if (searchElems === null) return;\n /* build state */\n const {\n searchField,\n suggestionBox,\n suggestionList,\n } = searchElems;\n ariaLiveInstance = AriaLiveHandler.getInstance();\n searchField.setAttribute('aria-activedescendant', '');\n Object.assign(state, searchElems);\n /* Add Event Listeners */\n searchField.addEventListener('focus', onFocus.bind(null, suggestionBox));\n searchField.addEventListener('blur', onBlur.bind(null, suggestionBox));\n searchField.addEventListener(\n 'keydown',\n onKeyDown.bind(null, searchField, suggestionList)\n );\n searchField.addEventListener('keyup', onKeyUp);\n searchField.addEventListener('input', onInput.bind(null, suggestionBox, searchField));\n suggestionList.addEventListener(\n 'mousedown',\n onMouseDown.bind(null, searchField, suggestionList)\n );\n fetchData(getAutosuggestTarget());\n};\n\nexport { state as suggestState };\nexport default init;\n","/**\n * Recent Searches | Search History\n * Contains main functionality for \"Recent Searches\" (aka user search history).\n * Is only visible when the input for search has focus, is empty (no text), and at least one\n * entry / previously saved search exists. The only exception is if the user presses \"escape\".\n * Only then the search field will be empty, with focus, and NOT display Recent Searches.\n *\n * NOT AVAILABLE to 3rd party sites as window.localStorage cannot cross domains (as coded).\n */\nimport { getDomElems } from '../../../../_shared-components/getDomElems';\nimport { code, getKeyCode, keyCode } from '../../../../_shared-components/keyCode';\nimport LISTBOX, { SEARCH_HISTORY } from './constants';\nimport * as listbox from './listboxUtil';\nimport getScriptData from '../../util/getScriptData';\nimport AriaLiveHandler from './AriaLiveHandler';\n\nlet ariaLiveInstance;\n\nconst recentSearchState = {\n maxCapacity: 10,\n recentSearches: [],\n};\n/* Resets state on init */\nconst setStateOnInit = () => {\n recentSearchState.maxCapacity = 10;\n recentSearchState.recentSearches = [];\n recentSearchState.recentHistoryBox = {};\n};\n\n/**\n * Retrieves the recentSearches from localStorage stored under the key 'savedSearches'\n * @param {Window} win\n */\nconst getRecentSearches = (win = window) => (\n JSON.parse(win.localStorage.getItem(SEARCH_HISTORY.LOCAL_STORAGE_KEY)) || []\n);\n\n/**\n * Removes the savedSearches localStorage key and data\n * @param {Window} win - global window\n */\nconst clearSearchHistory = (win = window) => {\n win.localStorage.removeItem(SEARCH_HISTORY.LOCAL_STORAGE_KEY);\n};\n\n/**\n * Sets search history to local storage.\n * @param {object[]} searchHistory - array of objects with a single property: \"searchTerm\"\n * @param win\n */\nconst setRecentSearches = (searchHistory, win = window) => {\n win.localStorage.setItem(SEARCH_HISTORY.LOCAL_STORAGE_KEY, JSON.stringify(searchHistory));\n};\n\n/**\n * Calls getRecentSearches to see if there are any recentSearches, checks to see if the current\n * searchTerm is empty, removes a recentSearch if there is are more than ten and then sets the\n * current searchTerm\n * @param {string} searchTerm\n * @param {Window} win\n */\nconst addToSearchHistory = (searchField, win = window) => {\n const searchTerm = searchField?.value?.trim();\n const { maxCapacity } = recentSearchState;\n if (!searchTerm) return;\n\n const recentSearches = getRecentSearches(win)\n .filter((search) => search.searchTerm.toLowerCase() !== searchTerm.toLowerCase());\n\n if (recentSearches.length >= maxCapacity) {\n recentSearches.pop();\n }\n setRecentSearches([{ searchTerm }, ...recentSearches]);\n};\n\n/**\n * Checks if element is the clear search history button by id\n * @param {HTMLLIElement} elemToCheck\n * @returns {boolean} - true if element is the clear search history button\n */\nconst isDeleteSearchHistoryButton = (elemToCheck) => (\n elemToCheck && elemToCheck.firstElementChild\n && elemToCheck.firstElementChild.id === SEARCH_HISTORY.DELETE.ID\n);\n\n/**\n * @param {number} listEntryCount Current count clickable list items in recent searches.\n * Number will always be greater than one because the delete history button is included.\n * @returns {string} describing the current number of Recent Search History entries, including\n * directions on how to navigation the open listbox.\n */\nconst updateAriaLiveText = (listEntryCount) => {\n if (listEntryCount >= 1) {\n ariaLiveInstance.updateAriaLiveRegion(\n `Recent Search History has ${listEntryCount} options available. ${LISTBOX.ARIA_LIVE.DIRECTIONS}`\n );\n }\n};\n\nconst getAllListEntries = () => (\n recentSearchState.recentHistoryBox.querySelectorAll(LISTBOX.ALL_LI.SELECTOR)\n);\n\n/**\n * Creates List Entry with a child element whose tagName and properties are\n * specified in the params. Used to build the title and delete button list entries.\n * @param {string} childTagName: string tagName. Ex. 'button', 'div', 'span'.\n * @param {object} elemPropsToSet: properties to set for the child element\n * @returns {HTMLLIElement}\n */\nconst createListEntryWithChildElem = (childTagName, elemPropsToSet) => {\n const listEntry = document.createElement('li');\n listEntry.className = 'search-history__entry';\n const elem = document.createElement(childTagName);\n Object.keys(elemPropsToSet).forEach((key) => {\n elem[key] = elemPropsToSet[key];\n });\n listEntry.appendChild(elem);\n return listEntry;\n};\n\nconst onMouseLeave = (e) => {\n const { target } = e;\n const { searchField } = recentSearchState;\n const listEntries = getAllListEntries();\n if (target.classList.contains(LISTBOX.CSS.VISUAL_FOCUS)) {\n listbox.resetListbox(searchField, listEntries);\n }\n};\n\nconst onMouseEnter = (e) => {\n const { target } = e;\n const { searchField } = recentSearchState;\n const listEntries = getAllListEntries();\n listbox.setVisualFocus(searchField, target, listEntries);\n};\n\n/**\n * Creates, adds mouseEventListeners, and appends markup to the DOM with the Search History list.\n * First entry is read-only title (unclickable, unfocusable). The last entry is a delete button\n * so user can clear their recent search history.\n * @param {HTMLDivElement} recentHistoryBox listbox and parent element of ul\n * @param {object[]} results: Array of previously saved searches\n */\nconst appendRecentSearches = (recentHistoryBox, results = []) => {\n const ul = recentHistoryBox.querySelector(`#${SEARCH_HISTORY.UL_ID}`);\n ul.innerHTML = '';\n /* First entry of recent searches results is title */\n ul.appendChild(createListEntryWithChildElem('div', {\n className: SEARCH_HISTORY.TITLE.CSS,\n textContent: SEARCH_HISTORY.TITLE.TEXT,\n }));\n\n [...results].forEach(({ searchTerm }, index) => {\n const li = document.createElement('li');\n li.className = LISTBOX.CSS.LIST_ITEM;\n li.textContent = searchTerm;\n li.setAttribute('aria-label', searchTerm);\n li.setAttribute('role', 'option');\n /* id with index used for building metrics.link config */\n li.setAttribute('id', `${SEARCH_HISTORY.LI_ID(index)}`);\n /* Add MouseEnter, MouseLeave listeners */\n listbox.addMouseMoveEventListeners(li, onMouseEnter, onMouseLeave);\n ul.appendChild(li);\n });\n /* Last entry of recent searches is clear search history button */\n const clearHistoryListItem = createListEntryWithChildElem('button', {\n className: SEARCH_HISTORY.DELETE.CSS,\n id: SEARCH_HISTORY.DELETE.ID,\n textContent: SEARCH_HISTORY.DELETE.TEXT,\n type: 'button',\n tabIndex: '-1',\n });\n clearHistoryListItem.setAttribute('role', 'option');\n clearHistoryListItem.setAttribute('id', `${SEARCH_HISTORY.LI_ID(results.length)}`);\n clearHistoryListItem.setAttribute('aria-label', `${SEARCH_HISTORY.DELETE.TEXT}, button`);\n /* add listener to button (not li) */\n listbox.addMouseMoveEventListeners(clearHistoryListItem, onMouseEnter, onMouseLeave);\n ul.appendChild(clearHistoryListItem);\n};\n\n/**\n * Controls visibility / expand-collapse of recentSearchBox for both recent searches and\n * filtered results (aka autocomplete).\n * @param {HTMLDivElement} recentHistoryBox - element that contains the list entries of recent\n * searches or filtered results\n * @param {HTMLInputElement} searchField - input element of search field\n * @param {boolean} isVisible - boolean used to determine state of visibility / expansion\n */\nconst setRecentSearchBoxVisibility = (recentHistoryBox, searchField, isVisible = false) => {\n const searchTerm = searchField.value.trim();\n if (!isVisible || searchTerm.length > 0) {\n listbox.resetListbox(searchField, [...getAllListEntries()]);\n recentHistoryBox.setAttribute('data-visible', 'hidden');\n }\n if (searchTerm.length === 0) {\n searchField.setAttribute('aria-expanded', `${isVisible}`);\n recentHistoryBox.setAttribute('data-visible', isVisible ? 'visible' : 'hidden');\n }\n};\n\n/**\n * Resets search history state, visibility, and focus when user deletes all recent searches\n * @param {HTMLDivElement} recentHistoryBox\n * @param {HTMLInputElement} searchField\n */\nconst deleteAllRecentSearches = (recentHistoryBox, searchField) => {\n clearSearchHistory();\n recentSearchState.recentSearches = [];\n setRecentSearchBoxVisibility(recentHistoryBox, searchField);\n};\n\n/**\n * Determines whether the recent search listbox should be open.\n *\n * The listbox is considered open if:\n * - `recentSearches` exists and contains at least one search term.\n * - The search input field is empty (i.e., no user input).\n *\n * @returns {boolean} - true if the recent search listbox should be open\n */\nconst recentSearchListboxShouldShow = () => {\n const { recentSearches, searchField } = recentSearchState;\n const searchTerm = searchField.value.trim();\n return (\n recentSearches\n && recentSearches.length > 0\n && searchTerm.length === 0\n );\n};\n\n/**\n * Handles the keyboard logic for list entries in RecentSearchBox\n * @param e\n */\nconst handleKeyUp = (e) => {\n const {\n recentHistoryBox,\n searchField,\n } = recentSearchState;\n /* limit results to current list */\n const listEntries = recentHistoryBox.querySelectorAll(LISTBOX.ALL_LI.SELECTOR);\n const currentIndex = listbox.getIndexFromElement(recentHistoryBox.querySelector(`.${LISTBOX.CSS.VISUAL_FOCUS}`));\n const keyCodeVal = getKeyCode(e);\n\n switch (keyCodeVal) {\n case code.ARROW_DOWN:\n case keyCode.ARROW_DOWN: {\n const updatedIndex = listbox.getUpdatedIndexOnArrowDown(currentIndex, listEntries.length);\n listbox.setVisualFocus(searchField, listEntries[updatedIndex], listEntries);\n localStorage.setItem(\n SEARCH_HISTORY.RECENTLY_SELECTED,\n listEntries[updatedIndex]?.innerText.trim()\n );\n break;\n }\n case code.ARROW_UP:\n case keyCode.ARROW_UP: {\n const updatedIndex = listbox.getUpdatedIndexOnArrowUp(currentIndex, listEntries.length);\n listbox.setVisualFocus(searchField, listEntries[updatedIndex], listEntries);\n localStorage.setItem(\n SEARCH_HISTORY.RECENTLY_SELECTED,\n listEntries[updatedIndex]?.innerText.trim()\n );\n break;\n }\n case code.ESCAPE:\n case keyCode.ESCAPE:\n searchField.focus();\n /* close search history. Only case where searchField has focus and does\n * NOT display search history */\n setRecentSearchBoxVisibility(recentHistoryBox, searchField);\n break;\n case code.END:\n case keyCode.END:\n case code.HOME:\n case keyCode.HOME:\n searchField.focus();\n listbox.resetListbox(searchField, listEntries);\n break;\n case code.ARROW_LEFT:\n case keyCode.ARROW_LEFT:\n case code.ARROW_RIGHT:\n case keyCode.ARROW_RIGHT:\n listbox.resetListbox(searchField, listEntries);\n break;\n default:\n // no-op\n break;\n }\n};\n\nconst onKeyUp = (recentHistoryBox, e) => {\n const {\n recentSearches,\n searchForm,\n searchField,\n } = recentSearchState;\n // if we have recent searches, and there's no search term in the input field\n const isVisible = recentSearchListboxShouldShow();\n\n // Determining if we need to show or hide it\n const visibilityChanged = listbox.shouldUpdateVisibility(recentHistoryBox, isVisible);\n\n if (visibilityChanged) {\n setRecentSearchBoxVisibility(recentHistoryBox, searchField, isVisible);\n /* If autosuggest is not enabled then set aria-expanded */\n if (!isVisible && searchForm.querySelectorAll('[role=\"listbox\"]').length === 1) {\n searchField.setAttribute('aria-expanded', 'false');\n }\n }\n if (isVisible) {\n /* update DOM only when necessary */\n if (visibilityChanged) {\n appendRecentSearches(recentHistoryBox, recentSearches);\n /* increment length to include delete history button */\n updateAriaLiveText(recentSearches.length + 1);\n }\n handleKeyUp(e);\n }\n};\n\n/**\n * Handles keydown events for the recent search history listbox.\n *\n * - If the search history listbox is not open, we exit\n * - If the key pressed is not \"Enter\" we pass to the preventDefault\n * funciton, and exit\n * - If an item is selected in the listbox:\n * - If it's a \"Clear History\" button, it clears recent searches.\n * - Otherwise, it dispatches a `termSelected` event.\n *\n * @param {HTMLInputElement} searchField - The search input field.\n * @param {HTMLElement} recentHistoryBox - The search history listbox.\n * @param {KeyboardEvent} e - The keydown event object.\n */\nconst onKeyDown = (searchField, recentHistoryBox, e) => {\n if (!recentSearchListboxShouldShow()) return;\n const keyCodeVal = getKeyCode(e);\n\n // handler for navigation key events\n // see listbox - this only applies to certain keys\n if (keyCodeVal !== code.ENTER && keyCodeVal !== code.NUMPAD_ENTER) {\n listbox.preventDefaultOnKeyDown(e);\n return;\n }\n\n // handler for potential selection of search terms\n // we can use aria to determine if this is a listbox selection\n const li = listbox.getSelectedListElementByAria(searchField, recentHistoryBox);\n if (!li) return;\n\n e.preventDefault();\n if (isDeleteSearchHistoryButton(li)) {\n deleteAllRecentSearches(recentHistoryBox, searchField);\n } else {\n const { id, selectedText } = listbox.getTextAndIdFromListEl(li);\n if (!selectedText) return;\n listbox.dispatchTermSelectedEvent(searchField, selectedText, id);\n }\n};\n\nconst onFocus = (recentHistoryBox, e) => {\n const { target: searchField } = e;\n const searchTerm = searchField.value.trim();\n const { recentSearches = [] } = recentSearchState;\n if (recentSearches && recentSearches.length > 0 && searchTerm.length === 0) {\n setRecentSearchBoxVisibility(recentHistoryBox, searchField, true);\n appendRecentSearches(recentHistoryBox, recentSearches);\n /* increment recentSearches length to include delete history button */\n updateAriaLiveText(recentSearches.length + 1);\n }\n};\n\nconst onBlur = (recentHistoryBox, e) => {\n const { target: searchField } = e;\n setRecentSearchBoxVisibility(recentHistoryBox, searchField);\n};\n\n/**\n * Handles mouse down events on the recent search history listbox.\n *\n * - If no
  • is selected, we exit.\n * - If the selected item is a \"Clear History\" button, it:\n * - Registers a mouseup event listener to return focus to the search field.\n * - Calls deleteAllRecentSearches() to clear the history.\n * - Otherwise, it dispatches a termSelected event.\n *\n * @param {HTMLInputElement} searchField - the search input field.\n * @param {HTMLElement} recentHistoryBox - the search history listbox\n */\nconst onMouseDown = (searchField, recentHistoryBox) => {\n const li = listbox.getSelectedListElementByAria(searchField, recentHistoryBox);\n if (!li) return;\n\n const { id, selectedText } = listbox.getTextAndIdFromListEl(li);\n if (!selectedText) return;\n\n if (isDeleteSearchHistoryButton(li)) {\n // this is only needed in mouseup, keydown is already in input field\n document.addEventListener(\n 'mouseup',\n () => { searchField.focus(); },\n { once: true }\n );\n deleteAllRecentSearches(recentHistoryBox, searchField);\n } else {\n listbox.dispatchTermSelectedEvent(searchField, selectedText, id);\n }\n};\n\n/**\n * Helper method that retrieves the configured property for number of saved recent search entries.\n * Range of the configured value (x) is 0 < x < 26.\n * capacity cannot be set to null, 0, or > 25 entries via configuration.\n * @returns {number} Configured number within the range of . Has default value of 10\n */\nconst getCustomMaxCapacityOrDefault = () => {\n const { recentSearchMaxSize = 10 } = getScriptData('gnav-data') || {};\n const useFallback = recentSearchMaxSize === null\n || (recentSearchMaxSize * 1) < 1\n || (recentSearchMaxSize * 1) > 25;\n return useFallback ? 10 : (recentSearchMaxSize * 1);\n};\n\n/* init */\nconst init = (selectors) => {\n const searchElems = getDomElems(selectors);\n if (searchElems === null) return;\n setStateOnInit();\n ariaLiveInstance = AriaLiveHandler.getInstance();\n /* build state */\n let recentSearches = getRecentSearches();\n const maxCapacity = getCustomMaxCapacityOrDefault();\n /* Handles edge case if the capacity is lowered, but user has previous history */\n if (recentSearches.length > maxCapacity) {\n setRecentSearches(recentSearches.slice(0, maxCapacity));\n recentSearches = getRecentSearches();\n }\n /* find and set up related elems */\n const { searchForm, recentHistoryBox } = searchElems;\n const searchField = searchForm.querySelector('[data-js=search-field]');\n searchField.setAttribute('aria-activedescendant', '');\n Object.assign(recentSearchState, searchElems, {\n recentSearches, searchField, maxCapacity,\n });\n /* Event Listeners */\n // all keyboard events occur in the input field (focus is visual only)\n searchField.addEventListener('focus', onFocus.bind(null, recentHistoryBox));\n searchField.addEventListener('blur', onBlur.bind(null, recentHistoryBox));\n searchField.addEventListener('keyup', onKeyUp.bind(null, recentHistoryBox));\n searchField.addEventListener(\n 'keydown',\n onKeyDown.bind(null, searchField, recentHistoryBox)\n );\n // mouse events occur on the actual listbox\n recentHistoryBox.addEventListener(\n 'mousedown',\n onMouseDown.bind(null, searchField, recentHistoryBox)\n );\n // in either scenario, make search the search term gets added to history\n searchForm.addEventListener('submit', () => {\n addToSearchHistory(searchField, window);\n });\n document.addEventListener('termSelected', () => {\n addToSearchHistory(searchField, window);\n });\n};\nexport default init;\n","/**\n * Search Field in Masthead\n * Optional part of Global Navigation. Includes conditional initialization of autosuggest,\n * and recent search history.\n */\n\nimport searchInit from '../search';\nimport suggestInit from '../suggest';\nimport recentSearchInit from '../recents';\nimport AriaLiveHandler from '../AriaLiveHandler';\nimport getScriptData from '../../../util/getScriptData';\n\nexport function app(win) {\n const {\n enableAutosuggest = false,\n enableRecentSearch = false,\n showSearch = false,\n searchAction = '',\n useConstructorAutosuggest = false,\n } = getScriptData('gnav-data') || {};\n\n // conditions for showing legacy vs constructor autosuggest\n const legacyAutosuggestShouldInit = enableAutosuggest && !(useConstructorAutosuggest && searchAction === '/search');\n\n // if showSearch is not true, none of this should happen\n if (!showSearch) return win;\n\n /* init the search bar (expand / contract) */\n searchInit({\n masthead: '[data-js=masthead]',\n searchForm: '[data-js=search-form]',\n searchField: '[data-js=search-field]',\n clearButton: '[data-js=clear-button]',\n searchButton: '[data-js=search-button]',\n searchCancel: '[data-js=search-cancel]',\n });\n if (legacyAutosuggestShouldInit || enableRecentSearch) {\n const ariaLiveInstance = AriaLiveHandler.getInstance();\n ariaLiveInstance.init({\n ariaBox1: '[data-js=feedback-holder-1]',\n ariaBox2: '[data-js=feedback-holder-2]',\n searchField: '[data-js=search-field]',\n });\n }\n if (legacyAutosuggestShouldInit) {\n /* init listboxes - autosuggest & recent search history */\n suggestInit({\n searchField: '[data-js=search-field]',\n suggestionBox: '[data-js=suggestion-box]',\n suggestionList: '[data-js=suggestion-list]',\n searchForm: '[data-js=search-form]',\n });\n }\n if (enableRecentSearch) {\n recentSearchInit({\n recentHistoryBox: '[data-js=recent-search-box]',\n searchForm: '[data-js=search-form]',\n });\n }\n return win;\n}\n\nexport function main(win = window) {\n if (win.document.readyState === 'loading') {\n // Loading hasn't finished yet\n win.document.addEventListener('DOMContentLoaded', app.bind(null, win));\n } else {\n // `DOMContentLoaded` has already fired\n app(win);\n }\n}\n","import '../../../../../util/global-shim';\nimport { main } from './main';\nimport '../../../../../../style/navigation/global/components/search/base-search.scss';\n/**\n * This is the main js entry point for search component(s)\n *\n * @param win Window object. Pass in to allow for window stubbing.\n * @returns {Window}\n */\nmain(window);\n"],"names":["$TypeError","validateArgumentsLength","passed","required","defineBuiltIn","require$$0","uncurryThis","require$$1","toString","require$$2","require$$3","$URLSearchParams","URLSearchParamsPrototype","append","$delete","forEach","push","params","name","length","$value","entries","v","k","key","value","index","dindex","found","entriesLength","entry","getAll","$has","values","DESCRIPTORS","defineBuiltInAccessor","count","conditionalAnalytics","searchHistory","searchTermType","linkName","searchRecentQuerySource","autosuggest","natural","getSearchType","ariaAD","startsWith","getTermIndex","match","lastString","Number","isNaN","getConditionalAnalytics","searchType","condAnalytics","analytics","autoSuggestPosition","getSumbitAnalytics","searchTerm","events","searchTermClicked","handleSearchFormSubmissionAnalytics","config","document","location","hostname","console","group","Object","log","groupEnd","analyticsCustomClickHandler","getSearchParam","param","URLSearchParams","window","search","get","showClearButton","searchField","clearButton","removeAttribute","setAttribute","hideClearButton","setClearButtonVisibility","enableSearchButton","searchButton","trim","classList","add","remove","clearSearchField","inputElem","focus","analyticsLogged","handleAnalytics","ariaActivedescendant","getAttribute","handleTermSelected","searchForm","e","preventDefault","submit","init","selectors","searchElems","getDomElems","addEventListener","sliceSize","cleanSearchResult","item","replace","getStartsWithData","data","cleanedSearchTerm","filter","getIncludesData","includes","partitionData","cleanSearchTerm","map","term","optionalSpecialCharacterPattern","i","len","optionalSpecialCharacterRegExp","RegExp","matches","resultTitle","specialCharacterRegExp","toLowerCase","cleanFetchedItems","fetchedItems","filterResults","state","newState","startsWithData","includesData","concat","filteredResults","slice","SEARCH_HISTORY","LI_ID","UL_ID","LOCAL_STORAGE_KEY","SELECTOR","RECENTLY_SELECTED","DELETE","ID","CSS","TEXT","TITLE","AUTOSUGGEST","URL","FALLBACK","LISTBOX","VISUAL_FOCUS","LIST_ITEM","ARIA_LIVE","DIRECTIONS","ALL_LI","preventDefaultOnKeyDown","getKeyCode","code","ARROW_DOWN","keyCode","ARROW_UP","END","getUpdatedIndexOnArrowDown","currentIndex","getUpdatedIndexOnArrowUp","setSearchField","cleanListEntries","listEntries","elem","resetListbox","getIndexFromElement","id","wordsArr","split","setVisualFocus","listItem","shouldUpdateVisibility","listboxElem","newValue","dataset","visible","visibleValue","addMouseMoveEventListeners","dynamicElem","enterCallback","leaveCallback","termSelectedEvent","CustomEvent","bubbles","cancelable","getTextAndIdFromListEl","li","HTMLLIElement","selectedText","textContent","getSelectedListElementByAria","listbox","querySelector","updateAriaAndSearchTerm","dispatchTermSelectedEvent","dispatchEvent","AriaLiveHandler","constructor","instance","enabled","debounceTimer","searchFieldEl","abortPendingUpdate","bind","box1","hasText","el","setText","text","clearText","box2","getInstance","ariaElems","ariaBox1","ariaBox2","clearAllBoxes","setTextByBox","boxToSet","otherBox","clearTimeout","setTimeout","updateAriaLiveRegion","ariaLiveInstance","autosuggestListboxIsOpen","suggestionBox","getAutosuggestTarget","autosuggestTarget","targetUrl","getScriptData","fetchData","fetchPoint","fetch","then","response","ok","status","url","error","json","catch","getInnerHtml","updateAriaLiveText","resultCount","onMouseLeave","target","querySelectorAll","contains","onMouseEnter","appendResults","results","suggestionList","ul","innerHTML","createElement","className","appendChild","setSuggestionBoxVisibility","isVisible","onFocus","onBlur","onMouseDown","onKeyUp","keyCodeVal","updatedIndex","ESCAPE","setSelectionRange","HOME","ARROW_LEFT","ARROW_RIGHT","onKeyDown","ENTER","NUMPAD_ENTER","onInput","resultLength","assign","recentSearchState","maxCapacity","recentSearches","setStateOnInit","recentHistoryBox","getRecentSearches","win","JSON","parse","localStorage","getItem","clearSearchHistory","removeItem","setRecentSearches","setItem","stringify","addToSearchHistory","pop","isDeleteSearchHistoryButton","elemToCheck","firstElementChild","listEntryCount","getAllListEntries","createListEntryWithChildElem","childTagName","elemPropsToSet","listEntry","keys","appendRecentSearches","clearHistoryListItem","type","tabIndex","setRecentSearchBoxVisibility","deleteAllRecentSearches","recentSearchListboxShouldShow","handleKeyUp","innerText","visibilityChanged","once","getCustomMaxCapacityOrDefault","recentSearchMaxSize","app","enableAutosuggest","enableRecentSearch","showSearch","searchAction","useConstructorAutosuggest","legacyAutosuggestShouldInit","searchInit","masthead","searchCancel","suggestInit","recentSearchInit","main","readyState"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}