https://ardene.com/cdn/shop/t/239/assets/snippet.sort-by-dropdown.js?v=35690426143889497741790728944
1(function(){"use strict";var __webpack_modules__={
1"./src/snippets/snippet.sort-by-dropdown.js":function(__unused_webpack___webpack_module__,__webpack_exports__,__webpack_require__){eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _sort_by_dropdown_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./sort-by-dropdown.css */ \"./src/snippets/sort-by-dropdown.css\");\n\n\nconst ATTR = {\n SORT_DROPDOWN_TRIGGER: 'data-sort-dropdown-trigger',\n SORT_DROPDOWN: 'data-sort-dropdown',\n SORT_OPTION: 'data-sort-option',\n SORT_CURRENT: 'data-sort-current',\n ARIA_EXPANDED: 'aria-expanded',\n ARIA_SELECTED: 'aria-selected',\n ARIA_LABEL: 'aria-label',\n TABINDEX: 'tabindex',\n HIDDEN: 'hidden',\n};\n\nconst SELECTORS = {\n SORT_DROPDOWN_TRIGGER: '[data-sort-dropdown-trigger]',\n SORT_DROPDOWN: '[data-sort-dropdown]',\n SORT_OPTIONS: '[data-sort-option]',\n SORT_CURRENT: '[data-sort-current]',\n};\n\nconst CLASSES = {\n ACTIVE: 'active',\n HAS_SELECTION: 'sortby-dropdown--has-selection',\n};\n\nconst KEYS = {\n ENTER: 'Enter',\n SPACE: ' ',\n ARROW_DOWN: 'ArrowDown',\n ARROW_UP: 'ArrowUp',\n ESCAPE: 'Escape',\n TAB: 'Tab',\n};\n\nconst TIMING = {\n PROCESSING_DELAY: 1000,\n URL_UPDATE_DELAY: 10,\n};\n\nconst DEFAULTS = {\n SORT_VALUE: 'created-descending',\n TABINDEX_ACTIVE: '0',\n TABINDEX_INACTIVE: '-1',\n};\n\nconst STYLES = {\n LOADING_OPACITY: '0.6',\n NORMAL_OPACITY: '1',\n POINTER_EVENTS_NONE: 'none',\n POINTER_EVENTS_AUTO: 'auto',\n};\n\nconst URL_PARAMS = {\n SORT_BY: 'sort_by',\n PAGE: 'page',\n};\n\n/**\n * SortbyDropdown Component\n *\n * Handles sort dropdown functionality including:\n * - Dropdown open/close behavior\n * - Sort option selection and URL updates\n * - Keyboard navigation and accessibility\n * - Loading states and visual feedback\n */\nclass SortbyDropdownComponent extends HTMLElement {\n constructor() {\n super();\n this.sortDropdownTrigger = this.querySelector(SELECTORS.SORT_DROPDOWN_TRIGGER);\n this.sortDropdown = this.querySelector(SELECTORS.SORT_DROPDOWN);\n this.sortOptions = this.querySelectorAll(SELECTORS.SORT_OPTIONS);\n this.sortCurrent = this.querySelector(SELECTORS.SORT_CURRENT);\n this.currentSortValue = null;\n this.isProcessing = false;\n }\n\n /**\n * Called when the component is connected to the DOM\n * @public\n */\n connectedCallback() {\n this.init();\n this.setupEventListeners();\n }\n\n /**\n * Called when the component is disconnected from the DOM\n * @public\n */\n disconnectedCallback() {\n this.cleanup();\n }\n\n /**\n * Initialize the sort dropdown component\n * @private\n */\n init() {\n // Load saved sort preference from URL\n this.loadSavedSort();\n }\n\n /**\n * Set up all event listeners for the sort dropdown\n * @private\n */\n setupEventListeners() {\n // Bind methods to preserve context and store references for cleanup\n this.boundToggleSortDropdown = this.toggleSortDropdown.bind(this);\n this.boundHandleTriggerKeydown = this.handleTriggerKeydown.bind(this);\n this.boundHandleSortChange = this.handleSortChange.bind(this);\n this.boundHandleOptionKeydown = this.handleOptionKeydown.bind(this);\n this.boundHandleOutsideClick = this.handleOutsideClick.bind(this);\n this.boundHandleDocumentKeydown = this.handleDocumentKeydown.bind(this);\n\n // Trigger button events\n if (this.sortDropdownTrigger) {\n this.sortDropdownTrigger.addEventListener('click', this.boundToggleSortDropdown);\n this.sortDropdownTrigger.addEventListener('keydown', this.boundHandleTriggerKeydown);\n }\n\n // Option events\n this.sortOptions.forEach((option) => {\n option.addEventListener('click', this.boundHandleSortChange);\n option.addEventListener('keydown', this.boundHandleOptionKeydown);\n });\n\n // Document events for outside clicks and escape key\n document.addEventListener('click', this.boundHandleOutsideClick);\n document.addEventListener('keydown', this.boundHandleDocumentKeydown);\n }\n\n /**\n * Clean up event listeners when component is removed\n * @private\n */\n cleanup() {\
1n if (this.sortDropdownTrigger && this.boundToggleSortDropdown) {\n this.sortDropdownTrigger.removeEventListener('click', this.boundToggleSortDropdown);\n this.sortDropdownTrigger.removeEventListener('keydown', this.boundHandleTriggerKeydown);\n }\n\n if (this.boundHandleSortChange && this.boundHandleOptionKeydown) {\n this.sortOptions.forEach((option) => {\n option.removeEventListener('click', this.boundHandleSortChange);\n option.removeEventListener('keydown', this.boundHandleOptionKeydown);\n });\n }\n\n if (this.boundHandleOutsideClick) {\n document.removeEventListener('click', this.boundHandleOutsideClick);\n }\n if (this.boundHandleDocumentKeydown) {\n document.removeEventListener('keydown', this.boundHandleDocumentKeydown);\n }\n }\n\n /**\n * Toggle the sort dropdown open/closed state\n * @private\n * @param {Event} event - Click event\n */\n toggleSortDropdown(event) {\n event.preventDefault();\n event.stopPropagation();\n\n const isExpanded = this.sortDropdownTrigger.getAttribute(ATTR.ARIA_EXPANDED) === 'true';\n\n if (isExpanded) {\n this.closeSortDropdown();\n } else {\n this.openSortDropdown();\n }\n }\n\n /**\n * Open the sort dropdown\n * @private\n */\n openSortDropdown() {\n this.sortDropdownTrigger.setAttribute(ATTR.ARIA_EXPANDED, 'true');\n this.sortDropdown.removeAttribute(ATTR.HIDDEN);\n }\n\n /**\n * Close the sort dropdown\n * @private\n */\n closeSortDropdown() {\n this.sortDropdownTrigger.setAttribute(ATTR.ARIA_EXPANDED, 'false');\n this.sortDropdown.setAttribute(ATTR.HIDDEN, '');\n }\n\n /**\n * Handle clicks outside the dropdown to close it\n * @private\n * @param {Event} event - Click event\n */\n handleOutsideClick(event) {\n if (!this.contains(event.target)) {\n this.closeSortDropdown();\n }\n }\n\n /**\n * Handle sort option selection\n * @private\n * @param {Event} event - Click event on sort option\n */\n handleSortChange(event) {\n // Prevent multiple clicks while processing\n if (this.isProcessing) {\n event.preventDefault();\n return;\n }\n\n const option = event.currentTarget;\n const sortValue = option?.getAttribute(ATTR.SORT_OPTION);\n const sortText = option?.textContent?.trim();\n\n // Validate that we have the required data\n if (!sortValue || !sortText) {\n console.warn('Invalid sort option clicked:', option);\n return;\n }\n\n // Always apply sort, even if it's the same value (to handle initial state issues)\n this.isProcessing = true;\n this.setLoadingState(true);\n this.setSortOption(sortValue, sortText, true);\n this.applySortToURL(sortValue);\n\n // Reset processing flag after a short delay to prevent accidental double-clicks\n setTimeout(() => {\n this.isProcessing = false;\n this.setLoadingState(false);\n }, TIMING.PROCESSING_DELAY);\n\n this.closeSortDropdown();\n }\n\n /**\n * Set loading state visual feedback\n * @private\n * @param {boolean} isLoading - Whether component is in loading state\n */\n setLoadingState(isLoading) {\n if (this.sortDropdownTrigger) {\n this.sortDropdownTrigger.style.opacity = isLoading\n ? STYLES.LOADING_OPACITY\n : STYLES.NORMAL_OPACITY;\n this.sortDropdownTrigger.style.pointerEvents = isLoading\n ? STYLES.POINTER_EVENTS_NONE\n : STYLES.POINTER_EVENTS_AUTO;\n }\n\n this.sortOptions.forEach((option) => {\n option.style.opacity = isLoading ? STYLES.LOADING_OPACITY : STYLES.NORMAL_OPACITY;\n option.style.pointerEvents = isLoading\n ? STYLES.POINTER_EVENTS_NONE\n : STYLES.POINTER_EVENTS_AUTO;\n });\n }\n\n /**\n * Set the active sort option and update UI state\n * @private\n * @param {string} value - Sort value\n * @param {string} text - Display text for sort option\n * @param {boolean} showText - Whether to show the selection text\n */\n setSortOption(value, text, showText = true) {\n this.currentSortValue = value;\n\n // Determine if we should show selection state - show text when explicitly selected\n const hasSelection = showText;\n\n // Update CSS class for visual state\n if (hasSelection) {\n this.classList.add(CLASSES.HAS_SELECTION);\n } else {\n this.classList.remove(CLASSES.HAS_SELECTION);\n }\n\n // Update current sort display - show text when explicitly selected\n if (this.sortCurrent) {\n if (hasSelection) {\n this.sortCurrent.textContent = text;\n } else {\n this.sortCurrent.textContent = '';\n }\n }\n\n // Update aria-label for trigger button\n if (this.sortDropdownTrigger) {\n const sortByLabel = this.sortDropdownTrigger.getAttribute(ATTR.ARIA_LABEL).split(',')[0];\n if (hasSelection) {\n this.sortDropdownTrigger.setAttribute(ATTR.ARIA_LABEL, `${sortByLabel}, ${text}`);\n } else {\n this.sortDropdownTrigger.setAttribute(ATTR.ARIA_LABEL, sortByLabel);\n }\n }\n\n // Update active state and ARIA attributes\n this.sortOptions.forEach((option) =>
1 {\n option.classList.remove(CLASSES.ACTIVE);\n option.setAttribute(ATTR.ARIA_SELECTED, 'false');\n option.setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_INACTIVE);\n });\n\n const activeOption = this.querySelector(`[${ATTR.SORT_OPTION}=\"${value}\"]`);\n if (activeOption) {\n activeOption.classList.add(CLASSES.ACTIVE);\n activeOption.setAttribute(ATTR.ARIA_SELECTED, 'true');\n activeOption.setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_ACTIVE);\n }\n }\n\n /**\n * Apply sort selection to URL and trigger sort change event\n * @private\n * @param {string} sortValue - Selected sort value\n */\n applySortToURL(sortValue) {\n try {\n const url = new URL(window.location.href);\n\n // Always set the sort parameter explicitly, even for default sort\n url.searchParams.set(URL_PARAMS.SORT_BY, sortValue);\n\n // Reset to first page when sort changes\n url.searchParams.delete(URL_PARAMS.PAGE);\n\n // Update browser URL first\n window.history.pushState({}, '', url.toString());\n\n // Small delay to ensure URL is updated, then trigger event\n setTimeout(() => {\n document.dispatchEvent(\n new CustomEvent('sort-changed', {\n detail: { sortValue, url: url.toString() },\n bubbles: true,\n }),\n );\n }, TIMING.URL_UPDATE_DELAY);\n } catch (error) {\n console.error('Error applying sort to URL:', error);\n this.isProcessing = false;\n }\n }\n\n /**\n * Load saved sort preference from URL parameters\n * @private\n */\n loadSavedSort() {\n const urlParams = new URLSearchParams(window.location.search);\n const urlSort = urlParams.get(URL_PARAMS.SORT_BY);\n\n // Determine if sort was explicitly set\n let sortValue = DEFAULTS.SORT_VALUE; // Default fallback\n let showText = false;\n\n if (urlSort) {\n // URL parameter exists, show the selected option\n sortValue = urlSort;\n showText = true;\n } else {\n // No URL parameter, use default but don't show text initially\n showText = false;\n }\n\n // Set current value\n this.currentSortValue = sortValue;\n\n // Find the option and set it as active\n const option = this.querySelector(`[${ATTR.SORT_OPTION}=\"${sortValue}\"]`);\n if (option) {\n const sortText = option.textContent.trim();\n this.setSortOption(sortValue, sortText, showText);\n }\n }\n\n /**\n * Reset the sort dropdown to default state (no selection shown)\n * @public\n */\n reset() {\n const defaultOption = this.querySelector(`[${ATTR.SORT_OPTION}=\"${DEFAULTS.SORT_VALUE}\"]`);\n if (defaultOption) {\n const sortText = defaultOption.textContent.trim();\n this.setSortOption(DEFAULTS.SORT_VALUE, sortText, false);\n }\n }\n\n /**\n * Handle keyboard navigation on trigger button\n * @private\n * @param {KeyboardEvent} event - Keyboard event\n */\n handleTriggerKeydown(event) {\n switch (event.key) {\n case KEYS.ENTER:\n case KEYS.SPACE:\n case KEYS.ARROW_DOWN:\n case KEYS.ARROW_UP:\n event.preventDefault();\n this.openSortDropdown();\n this.focusFirstOption();\n break;\n case KEYS.ESCAPE:\n this.closeSortDropdown();\n break;\n }\n }\n\n /**\n * Handle keyboard navigation on dropdown options\n * @private\n * @param {KeyboardEvent} event - Keyboard event\n */\n handleOptionKeydown(event) {\n switch (event.key) {\n case KEYS.ENTER:\n case KEYS.SPACE:\n event.preventDefault();\n this.handleSortChange(event);\n this.sortDropdownTrigger.focus();\n break;\n case KEYS.ARROW_DOWN:\n event.preventDefault();\n this.focusNextOption(event.target);\n break;\n case KEYS.ARROW_UP:\n event.preventDefault();\n this.focusPreviousOption(event.target);\n break;\n case KEYS.ESCAPE:\n event.preventDefault();\n this.closeSortDropdown();\n this.sortDropdownTrigger.focus();\n break;\n case KEYS.TAB:\n this.closeSortDropdown();\n break;\n }\n }\n\n /**\n * Handle document-level keyboard events (escape key)\n * @private\n * @param {KeyboardEvent} event - Keyboard event\n */\n handleDocumentKeydown(event) {\n if (event.key === KEYS.ESCAPE && !this.sortDropdown.hasAttribute(ATTR.HIDDEN)) {\n this.closeSortDropdown();\n this.sortDropdownTrigger.focus();\n }\n }\n\n /**\n * Focus the first option in the dropdown\n * @private\n */\n focusFirstOption() {\
1n // Set all options to tabindex -1\n this.sortOptions.forEach((option) =>\n option.setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_INACTIVE),\n );\n\n const firstOption = this.sortOptions[0];\n if (firstOption) {\n firstOption.setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_ACTIVE);\n firstOption.focus();\n }\n }\n\n /**\n * Focus the next option in the dropdown\n * @private\n * @param {HTMLElement} currentOption - Currently focused option\n */\n focusNextOption(currentOption) {\n const currentIndex = Array.from(this.sortOptions).indexOf(currentOption);\n const nextIndex = (currentIndex + 1) % this.sortOptions.length;\n\n // Update tabindex\n this.sortOptions.forEach((option) =>\n option.setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_INACTIVE),\n );\n this.sortOptions[nextIndex].setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_ACTIVE);\n this.sortOptions[nextIndex].focus();\n }\n\n /**\n * Focus the previous option in the dropdown\n * @private\n * @param {HTMLElement} currentOption - Currently focused option\n */\n focusPreviousOption(currentOption) {\n const currentIndex = Array.from(this.sortOptions).indexOf(currentOption);\n const previousIndex = currentIndex === 0 ? this.sortOptions.length - 1 : currentIndex - 1;\n\n // Update tabindex\n this.sortOptions.forEach((option) =>\n option.setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_INACTIVE),\n );\n this.sortOptions[previousIndex].setAttribute(ATTR.TABINDEX, DEFAULTS.TABINDEX_ACTIVE);\n this.sortOptions[previousIndex].focus();\n }\n}\n\nif (!customElements.get('sortby-dropdown-component')) {\n customElements.define('sortby-dropdown-component', SortbyDropdownComponent);\n}\n\n\n//# sourceURL=webpack://ardene-theme/./src/snippets/snippet.sort-by-dropdown.js?\n}")},
1"./src/snippets/sort-by-dropdown.css":function(__unused_webpack_module,__webpack_exports__,__webpack_require__){eval("{__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://ardene-theme/./src/snippets/sort-by-dropdown.css?\n}")}
1},__webpack_module_cache__={};function __webpack_require__(moduleId){var cachedModule=__webpack_module_cache__[moduleId];if(cachedModule!==void 0)return cachedModule.exports;var module=__webpack_module_cache__[moduleId]={exports:{}};return __webpack_modules__[moduleId](module,module.exports,__webpack_require__),module.exports}(function(){__webpack_require__.r=function(exports){typeof Symbol!="undefined"&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})}})();var __webpack_exports__=__webpack_require__("./src/snippets/snippet.sort-by-dropdown.js")})(); 2//# sourceMappingURL=/cdn/shop/t/239/assets/snippet.sort-by-dropdown.js.map?v=35690426143889497741790728944
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.