| @@ -1573,19 +1573,19 @@ | ||
| 1573 | 1573 | |
| 1574 | 1574 | /******/ }); |
| 1575 | 1575 | /************************************************************************/ |
| 1576 | 1576 | /******/ // The module cache |
| 1577 | -/******/ var __webpack_module_cache__ = {}; | |
| 1577 | +/******/ const __webpack_module_cache__ = {}; | |
| 1578 | 1578 | /******/ |
| 1579 | 1579 | /******/ // The require function |
| 1580 | 1580 | /******/ function __webpack_require__(moduleId) { |
| 1581 | 1581 | /******/ // Check if module is in cache |
| 1582 | -/******/ var cachedModule = __webpack_module_cache__[moduleId]; | |
| 1582 | +/******/ const cachedModule = __webpack_module_cache__[moduleId]; | |
| 1583 | 1583 | /******/ if (cachedModule !== undefined) { |
| 1584 | 1584 | /******/ return cachedModule.exports; |
| 1585 | 1585 | /******/ } |
| 1586 | 1586 | /******/ // Create a new module (and put it into the cache) |
| 1587 | -/******/ var module = __webpack_module_cache__[moduleId] = { | |
| 1587 | +/******/ const module = __webpack_module_cache__[moduleId] = { | |
| 1588 | 1588 | /******/ id: moduleId, |
| 1589 | 1589 | /******/ // no module.loaded needed |
| 1590 | 1590 | /******/ exports: {} |
| 1591 | 1591 | /******/ }; |
| @@ -1592,9 +1592,9 @@ | ||
| 1592 | 1592 | /******/ |
| 1593 | 1593 | /******/ // Execute the module function |
| 1594 | 1594 | /******/ if (!(moduleId in __webpack_modules__)) { |
| 1595 | 1595 | /******/ delete __webpack_module_cache__[moduleId]; |
| 1596 | -/******/ var e = new Error("Cannot find module '" + moduleId + "'"); | |
| 1596 | +/******/ const e = new Error("Cannot find module '" + moduleId + "'"); | |
| 1597 | 1597 | /******/ e.code = 'MODULE_NOT_FOUND'; |
| 1598 | 1598 | /******/ throw e; |
| 1599 | 1599 | /******/ } |
| 1600 | 1600 | /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); |
| @@ -1607,9 +1607,9 @@ | ||
| 1607 | 1607 | /******/ /* webpack/runtime/compat get default export */ |
| 1608 | 1608 | /******/ (() => { |
| 1609 | 1609 | /******/ // getDefaultExport function for compatibility with non-harmony modules |
| 1610 | 1610 | /******/ __webpack_require__.n = (module) => { |
| 1611 | -/******/ var getter = module && module.__esModule ? | |
| 1611 | +/******/ const getter = module && module.__esModule ? | |
| 1612 | 1612 | /******/ () => (module['default']) : |
| 1613 | 1613 | /******/ () => (module); |
| 1614 | 1614 | /******/ __webpack_require__.d(getter, { a: getter }); |
| 1615 | 1615 | /******/ return getter; |
| @@ -1617,14 +1617,29 @@ | ||
| 1617 | 1617 | /******/ })(); |
| 1618 | 1618 | /******/ |
| 1619 | 1619 | /******/ /* webpack/runtime/define property getters */ |
| 1620 | 1620 | /******/ (() => { |
| 1621 | -/******/ // define getter functions for harmony exports | |
| 1621 | +/******/ // define getter/value functions for harmony exports | |
| 1622 | 1622 | /******/ __webpack_require__.d = (exports, definition) => { |
| 1623 | -/******/ for(var key in definition) { | |
| 1624 | -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { | |
| 1625 | -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); | |
| 1623 | +/******/ if(Array.isArray(definition)) { | |
| 1624 | +/******/ var i = 0; | |
| 1625 | +/******/ while(i < definition.length) { | |
| 1626 | +/******/ var key = definition[i++]; | |
| 1627 | +/******/ var binding = definition[i++]; | |
| 1628 | +/******/ if(!__webpack_require__.o(exports, key)) { | |
| 1629 | +/******/ if(binding === 0) { | |
| 1630 | +/******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] }); | |
| 1631 | +/******/ } else { | |
| 1632 | +/******/ Object.defineProperty(exports, key, { enumerable: true, get: binding }); | |
| 1633 | +/******/ } | |
| 1634 | +/******/ } else if(binding === 0) { i++; } | |
| 1626 | 1635 | /******/ } |
| 1636 | +/******/ } else { | |
| 1637 | +/******/ for(var key in definition) { | |
| 1638 | +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { | |
| 1639 | +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); | |
| 1640 | +/******/ } | |
| 1641 | +/******/ } | |
| 1627 | 1642 | /******/ } |
| 1628 | 1643 | /******/ }; |
| 1629 | 1644 | /******/ })(); |
| 1630 | 1645 | /******/ |
| @@ -1629,9 +1644,9 @@ | ||
| 1629 | 1644 | /******/ })(); |
| 1630 | 1645 | /******/ |
| 1631 | 1646 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ |
| 1632 | 1647 | /******/ (() => { |
| 1633 | -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) | |
| 1648 | +/******/ __webpack_require__.o = (obj, prop) => (Object.hasOwn(obj, prop)) | |
| 1634 | 1649 | /******/ })(); |
| 1635 | 1650 | /******/ |
| 1636 | 1651 | /******/ /* webpack/runtime/make namespace object */ |
| 1637 | 1652 | /******/ (() => { |
| @@ -1636,9 +1651,9 @@ | ||
| 1636 | 1651 | /******/ /* webpack/runtime/make namespace object */ |
| 1637 | 1652 | /******/ (() => { |
| 1638 | 1653 | /******/ // define __esModule on exports |
| 1639 | 1654 | /******/ __webpack_require__.r = (exports) => { |
| 1640 | -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | |
| 1655 | +/******/ if(Symbol.toStringTag) { | |
| 1641 | 1656 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |
| 1642 | 1657 | /******/ } |
| 1643 | 1658 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); |
| 1644 | 1659 | /******/ }; |
| @@ -1649,9 +1664,9 @@ | ||
| 1649 | 1664 | /******/ __webpack_require__.nc = undefined; |
| 1650 | 1665 | /******/ })(); |
| 1651 | 1666 | /******/ |
| 1652 | 1667 | /************************************************************************/ |
| 1653 | -var __webpack_exports__ = {}; | |
| 1668 | +let __webpack_exports__ = {}; | |
| 1654 | 1669 | // This entry needs to be wrapped in an IIFE because it needs to be in strict mode. |
| 1655 | 1670 | (() => { |
| 1656 | 1671 | "use strict"; |
| 1657 | 1672 | /*!***************************************!*\ |
| @@ -1681,15 +1696,23 @@ | ||
| 1681 | 1696 | this.urlParams = new URLSearchParams(window.location.search); |
| 1682 | 1697 | } |
| 1683 | 1698 | static selectors = { |
| 1684 | 1699 | elAddonsPage: '.lp-addons-page', |
| 1700 | + elToolbar: '.lp-addons-toolbar', | |
| 1685 | 1701 | elLPAddons: '#lp-addons', |
| 1686 | 1702 | elAddonItem: '.lp-addon-item', |
| 1687 | 1703 | elBtnAction: '.btn-addon-action', |
| 1688 | 1704 | elNavTab: '.nav-tab', |
| 1689 | 1705 | elNavTabActive: '.nav-tab.nav-tab-active', |
| 1706 | + elFilter: '.lp-addons-filter', | |
| 1707 | + elFilterToggle: '.lp-addons-filter__toggle', | |
| 1708 | + elFilterMenu: '.lp-addons-filter__menu', | |
| 1690 | 1709 | elCategory: '.lp-addons-category', |
| 1691 | 1710 | elCategoryActive: '.lp-addons-category.active', |
| 1711 | + elSearch: '.lp-addons-search', | |
| 1712 | + elSearchBtn: '.lp-addons-search__btn', | |
| 1713 | + elSearchBtnClear: '.lp-addons-search__btn-clear', | |
| 1714 | + elSearchClose: '.lp-addons-search__close', | |
| 1692 | 1715 | elSearchInput: '#lp-search-addons__input', |
| 1693 | 1716 | elItemPurchase: '.lp-addon-item__purchase', |
| 1694 | 1717 | elPurchaseInstall: '.purchase-install', |
| 1695 | 1718 | elPurchaseCode: '.enter-purchase-code', |
| @@ -1701,9 +1724,40 @@ | ||
| 1701 | 1724 | this.elAddonsPage = document.querySelector(AdminAddons.selectors.elAddonsPage); |
| 1702 | 1725 | if (!this.elAddonsPage) { |
| 1703 | 1726 | return; |
| 1704 | 1727 | } |
| 1728 | + const selectors = AdminAddons.selectors; | |
| 1729 | + const urlTab = this.urlParams.get('tab'); | |
| 1730 | + if (urlTab) { | |
| 1731 | + const elMatchingTab = this.elAddonsPage.querySelector(`${selectors.elNavTab}[data-tab="${urlTab}"]`); | |
| 1732 | + if (elMatchingTab) { | |
| 1733 | + this.elAddonsPage.querySelectorAll(selectors.elNavTab).forEach(elTab => { | |
| 1734 | + elTab.classList.remove('nav-tab-active'); | |
| 1735 | + elTab.setAttribute('aria-pressed', 'false'); | |
| 1736 | + }); | |
| 1737 | + elMatchingTab.classList.add('nav-tab-active'); | |
| 1738 | + elMatchingTab.setAttribute('aria-pressed', 'true'); | |
| 1739 | + } | |
| 1740 | + } | |
| 1741 | + let elActiveTab = this.elAddonsPage.querySelector(selectors.elNavTabActive); | |
| 1742 | + if (!elActiveTab) { | |
| 1743 | + elActiveTab = this.elAddonsPage.querySelector(`${selectors.elNavTab}[data-tab="all"]`) || this.elAddonsPage.querySelector(selectors.elNavTab); | |
| 1744 | + if (elActiveTab) { | |
| 1745 | + elActiveTab.classList.add('nav-tab-active'); | |
| 1746 | + elActiveTab.setAttribute('aria-pressed', 'true'); | |
| 1747 | + } | |
| 1748 | + } | |
| 1749 | + let elActiveCategory = this.elAddonsPage.querySelector(selectors.elCategoryActive); | |
| 1750 | + if (!elActiveCategory) { | |
| 1751 | + elActiveCategory = this.elAddonsPage.querySelector(`${selectors.elCategory}[data-category="all"]`) || this.elAddonsPage.querySelector(selectors.elCategory); | |
| 1752 | + if (elActiveCategory) { | |
| 1753 | + elActiveCategory.classList.add('active'); | |
| 1754 | + elActiveCategory.setAttribute('aria-pressed', 'true'); | |
| 1755 | + } | |
| 1756 | + } | |
| 1705 | 1757 | this.filterAddons(); |
| 1758 | + this.updateSearchClearBtnState(); | |
| 1759 | + this.updateFilterToggleState(); | |
| 1706 | 1760 | this.events(); |
| 1707 | 1761 | }); |
| 1708 | 1762 | } |
| 1709 | 1763 | |
| @@ -1725,11 +1779,23 @@ | ||
| 1725 | 1779 | selector: AdminAddons.selectors.elCategory, |
| 1726 | 1780 | class: this, |
| 1727 | 1781 | callBack: this.handleCategoryClick.name |
| 1728 | 1782 | }, { |
| 1729 | - selector: AdminAddons.selectors.elPurchaseCode, | |
| 1783 | + selector: AdminAddons.selectors.elFilterToggle, | |
| 1730 | 1784 | class: this, |
| 1731 | - callBack: this.handlePurchaseCodeClick.name | |
| 1785 | + callBack: this.handleFilterToggleClick.name | |
| 1786 | + }, { | |
| 1787 | + selector: AdminAddons.selectors.elSearchBtn, | |
| 1788 | + class: this, | |
| 1789 | + callBack: this.handleSearchBtnClick.name | |
| 1790 | + }, { | |
| 1791 | + selector: AdminAddons.selectors.elSearchBtnClear, | |
| 1792 | + class: this, | |
| 1793 | + callBack: this.handleSearchClearClick.name | |
| 1794 | + }, { | |
| 1795 | + selector: AdminAddons.selectors.elSearchClose, | |
| 1796 | + class: this, | |
| 1797 | + callBack: this.handleSearchCloseClick.name | |
| 1732 | 1798 | }]); |
| 1733 | 1799 | lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.eventHandlers('input', [{ |
| 1734 | 1800 | selector: AdminAddons.selectors.elSearchInput, |
| 1735 | 1801 | class: this, |
| @@ -1738,8 +1804,29 @@ | ||
| 1738 | 1804 | selector: AdminAddons.selectors.elPurchaseCode, |
| 1739 | 1805 | class: this, |
| 1740 | 1806 | callBack: this.handlePurchaseCodeInput.name |
| 1741 | 1807 | }]); |
| 1808 | + lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.eventHandlers('keydown', [{ | |
| 1809 | + selector: AdminAddons.selectors.elSearchInput, | |
| 1810 | + class: this, | |
| 1811 | + callBack: this.handleSearchKeydown.name | |
| 1812 | + }]); | |
| 1813 | + document.addEventListener('click', e => { | |
| 1814 | + if (!this.elAddonsPage) { | |
| 1815 | + return; | |
| 1816 | + } | |
| 1817 | + const elToolbar = this.elAddonsPage.querySelector(AdminAddons.selectors.elToolbar); | |
| 1818 | + if (elToolbar && elToolbar.classList.contains('is-filter-open')) { | |
| 1819 | + if (!elToolbar.contains(e.target)) { | |
| 1820 | + this.toggleFilterMenu(false); | |
| 1821 | + } | |
| 1822 | + } | |
| 1823 | + }); | |
| 1824 | + document.addEventListener('keydown', e => { | |
| 1825 | + if ('Escape' === e.key) { | |
| 1826 | + this.toggleFilterMenu(false); | |
| 1827 | + } | |
| 1828 | + }); | |
| 1742 | 1829 | } |
| 1743 | 1830 | |
| 1744 | 1831 | /** |
| 1745 | 1832 | * Get addon data embedded on the item element. |
| @@ -1775,10 +1862,14 @@ | ||
| 1775 | 1862 | addon, |
| 1776 | 1863 | purchase_code: data.purchase_code || '', |
| 1777 | 1864 | id_url: 'addon-action' |
| 1778 | 1865 | }; |
| 1866 | + const releaseHandling = () => { | |
| 1867 | + lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); | |
| 1868 | + }; | |
| 1779 | 1869 | window.lpAJAXG.fetchAJAX(params, { |
| 1780 | 1870 | success: response => { |
| 1871 | + releaseHandling(); | |
| 1781 | 1872 | const { |
| 1782 | 1873 | status, |
| 1783 | 1874 | message, |
| 1784 | 1875 | data: resData |
| @@ -1795,12 +1886,11 @@ | ||
| 1795 | 1886 | } |
| 1796 | 1887 | } |
| 1797 | 1888 | |
| 1798 | 1889 | //this.filterAddons(); |
| 1799 | - lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); | |
| 1800 | 1890 | }, |
| 1801 | 1891 | error: error => { |
| 1802 | - lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); | |
| 1892 | + releaseHandling(); | |
| 1803 | 1893 | lpAssetsJsPath_lpToastify_js__WEBPACK_IMPORTED_MODULE_0__.show(`error js: ${error}`, 'error'); |
| 1804 | 1894 | } |
| 1805 | 1895 | }); |
| 1806 | 1896 | } |
| @@ -1873,28 +1963,8 @@ | ||
| 1873 | 1963 | }); |
| 1874 | 1964 | } |
| 1875 | 1965 | |
| 1876 | 1966 | /** |
| 1877 | - * Handle click events. | |
| 1878 | - * | |
| 1879 | - * @param {Object} args Click event arguments. | |
| 1880 | - * @return void | |
| 1881 | - */ | |
| 1882 | - handlePurchaseCodeClick(args) { | |
| 1883 | - const { | |
| 1884 | - target: el | |
| 1885 | - } = args; | |
| 1886 | - if (!el.value.startsWith('***')) { | |
| 1887 | - return; | |
| 1888 | - } | |
| 1889 | - el.value = ''; | |
| 1890 | - const elItemPurchase = el.closest(AdminAddons.selectors.elItemPurchase); | |
| 1891 | - if (elItemPurchase) { | |
| 1892 | - elItemPurchase.querySelector('input[name=purchase-code]').value = ''; | |
| 1893 | - } | |
| 1894 | - } | |
| 1895 | - | |
| 1896 | - /** | |
| 1897 | 1967 | * Handle addon action button click. |
| 1898 | 1968 | * |
| 1899 | 1969 | * @param {Object} args Click event arguments. |
| 1900 | 1970 | * @return void |
| @@ -1925,24 +1995,65 @@ | ||
| 1925 | 1995 | if (action === 'purchase' || action === 'update-purchase-code') { |
| 1926 | 1996 | const elPurchaseInstall = elItemPurchase.querySelector(selectors.elPurchaseInstall); |
| 1927 | 1997 | const elPurchaseCode = elPurchaseInstall.querySelector(selectors.elPurchaseCode); |
| 1928 | 1998 | const elPurchaseSubmit = elPurchaseInstall.querySelector('.lp-addon-purchase__submit'); |
| 1999 | + const elPurchaseClear = elPurchaseInstall.querySelector('.lp-addon-purchase__clear'); | |
| 2000 | + const elPurchaseCancelClear = elPurchaseInstall.querySelector('.lp-addon-purchase__cancel-clear'); | |
| 2001 | + let hasPurchaseCode = false; | |
| 1929 | 2002 | if (action === 'update-purchase-code') { |
| 1930 | 2003 | const elLicense = elAddonItem.querySelector(selectors.elLicense); |
| 1931 | 2004 | elPurchaseCode.value = elLicense ? elLicense.dataset.purchaseCodeMasked || '' : ''; |
| 2005 | + hasPurchaseCode = '' !== elPurchaseCode.value; | |
| 1932 | 2006 | elPurchaseSubmit.dataset.action = 'update-purchase'; |
| 1933 | 2007 | } else { |
| 1934 | 2008 | elPurchaseCode.value = ''; |
| 1935 | 2009 | elPurchaseSubmit.dataset.action = 'install'; |
| 1936 | 2010 | } |
| 2011 | + elPurchaseCode.disabled = hasPurchaseCode; | |
| 2012 | + elPurchaseSubmit.classList.toggle('lp-hidden', hasPurchaseCode); | |
| 2013 | + elPurchaseClear.classList.toggle('lp-hidden', !hasPurchaseCode); | |
| 2014 | + elPurchaseCancelClear.classList.add('lp-hidden'); | |
| 1937 | 2015 | elPurchaseCode.classList.remove('is-error'); |
| 1938 | 2016 | elPurchaseCode.removeAttribute('aria-invalid'); |
| 1939 | 2017 | elItemPurchase.querySelector('input[name=purchase-code]').value = ''; |
| 1940 | 2018 | elPurchaseInstall.style.display = 'flex'; |
| 1941 | 2019 | elItemPurchase.style.display = 'block'; |
| 2020 | + if (!hasPurchaseCode) { | |
| 2021 | + elPurchaseCode.focus(); | |
| 2022 | + } | |
| 2023 | + lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); | |
| 2024 | + return; | |
| 2025 | + } else if (action === 'clear-license') { | |
| 2026 | + const elPurchaseCode = elItemPurchase.querySelector(selectors.elPurchaseCode); | |
| 2027 | + const elPurchaseSubmit = elItemPurchase.querySelector('.lp-addon-purchase__submit'); | |
| 2028 | + const elPurchaseClear = elItemPurchase.querySelector('.lp-addon-purchase__clear'); | |
| 2029 | + const elPurchaseCancelClear = elItemPurchase.querySelector('.lp-addon-purchase__cancel-clear'); | |
| 2030 | + elPurchaseCode.value = ''; | |
| 2031 | + elPurchaseCode.disabled = false; | |
| 2032 | + elPurchaseCode.classList.remove('is-error'); | |
| 2033 | + elPurchaseCode.removeAttribute('aria-invalid'); | |
| 2034 | + elItemPurchase.querySelector('input[name=purchase-code]').value = ''; | |
| 2035 | + elPurchaseSubmit.classList.remove('lp-hidden'); | |
| 2036 | + elPurchaseClear.classList.add('lp-hidden'); | |
| 2037 | + elPurchaseCancelClear.classList.remove('lp-hidden'); | |
| 1942 | 2038 | elPurchaseCode.focus(); |
| 1943 | 2039 | lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); |
| 1944 | 2040 | return; |
| 2041 | + } else if (action === 'cancel-clear-license') { | |
| 2042 | + const elLicense = elAddonItem.querySelector(selectors.elLicense); | |
| 2043 | + const elPurchaseCode = elItemPurchase.querySelector(selectors.elPurchaseCode); | |
| 2044 | + const elPurchaseSubmit = elItemPurchase.querySelector('.lp-addon-purchase__submit'); | |
| 2045 | + const elPurchaseClear = elItemPurchase.querySelector('.lp-addon-purchase__clear'); | |
| 2046 | + elPurchaseCode.value = elLicense ? elLicense.dataset.purchaseCodeMasked || '' : ''; | |
| 2047 | + elPurchaseCode.disabled = true; | |
| 2048 | + elPurchaseCode.classList.remove('is-error'); | |
| 2049 | + elPurchaseCode.removeAttribute('aria-invalid'); | |
| 2050 | + elItemPurchase.querySelector('input[name=purchase-code]').value = ''; | |
| 2051 | + elPurchaseSubmit.classList.add('lp-hidden'); | |
| 2052 | + elPurchaseClear.classList.remove('lp-hidden'); | |
| 2053 | + el.classList.add('lp-hidden'); | |
| 2054 | + lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); | |
| 2055 | + return; | |
| 1945 | 2056 | } else if (action === 'cancel') { |
| 1946 | 2057 | elItemPurchase.style.display = 'none'; |
| 1947 | 2058 | elItemPurchase.querySelector(selectors.elPurchaseInstall).style.display = 'none'; |
| 1948 | 2059 | lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(el, 0); |
| @@ -1982,11 +2093,28 @@ | ||
| 1982 | 2093 | elTab.setAttribute('aria-pressed', 'false'); |
| 1983 | 2094 | }); |
| 1984 | 2095 | el.classList.add('nav-tab-active'); |
| 1985 | 2096 | el.setAttribute('aria-pressed', 'true'); |
| 2097 | + if (el.scrollIntoView) { | |
| 2098 | + el.scrollIntoView({ | |
| 2099 | + inline: 'center', | |
| 2100 | + block: 'nearest', | |
| 2101 | + behavior: 'smooth' | |
| 2102 | + }); | |
| 2103 | + } | |
| 1986 | 2104 | const tabName = el.dataset.tab; |
| 1987 | 2105 | const elSearch = this.elAddonsPage.querySelector(selectors.elSearchInput); |
| 1988 | - elSearch.value = ''; | |
| 2106 | + if (elSearch) { | |
| 2107 | + elSearch.value = ''; | |
| 2108 | + } | |
| 2109 | + const elSearchContainer = this.elAddonsPage.querySelector(selectors.elSearch); | |
| 2110 | + if (elSearchContainer) { | |
| 2111 | + elSearchContainer.classList.remove('is-open'); | |
| 2112 | + const btn = elSearchContainer.querySelector(selectors.elSearchBtn); | |
| 2113 | + if (btn) { | |
| 2114 | + btn.setAttribute('aria-expanded', 'false'); | |
| 2115 | + } | |
| 2116 | + } | |
| 1989 | 2117 | this.elAddonsPage.querySelectorAll(selectors.elCategory).forEach(elCategory => { |
| 1990 | 2118 | const isActive = 'all' === elCategory.dataset.category; |
| 1991 | 2119 | elCategory.classList.toggle('active', isActive); |
| 1992 | 2120 | elCategory.setAttribute('aria-pressed', isActive ? 'true' : 'false'); |
| @@ -1992,12 +2120,73 @@ | ||
| 1992 | 2120 | elCategory.setAttribute('aria-pressed', isActive ? 'true' : 'false'); |
| 1993 | 2121 | }); |
| 1994 | 2122 | this.urlParams.set('tab', tabName); |
| 1995 | 2123 | window.history.pushState({}, '', `${window.location.pathname}?${this.urlParams.toString()}`); |
| 2124 | + this.updateFilterToggleState(); | |
| 1996 | 2125 | this.filterAddons(); |
| 1997 | 2126 | } |
| 1998 | 2127 | |
| 1999 | 2128 | /** |
| 2129 | + * Handle filter toggle button click. | |
| 2130 | + * | |
| 2131 | + * @param {Object} args Click event arguments. | |
| 2132 | + * @return void | |
| 2133 | + */ | |
| 2134 | + handleFilterToggleClick(args) { | |
| 2135 | + const { | |
| 2136 | + e | |
| 2137 | + } = args; | |
| 2138 | + e.preventDefault(); | |
| 2139 | + e.stopPropagation(); | |
| 2140 | + this.toggleFilterMenu(); | |
| 2141 | + } | |
| 2142 | + | |
| 2143 | + /** | |
| 2144 | + * Toggle or set filter menu dropdown open state. | |
| 2145 | + * | |
| 2146 | + * @param {boolean|undefined} open Optional boolean to force state. | |
| 2147 | + * @return void | |
| 2148 | + */ | |
| 2149 | + toggleFilterMenu(open) { | |
| 2150 | + const selectors = AdminAddons.selectors; | |
| 2151 | + const elToolbar = this.elAddonsPage.querySelector(selectors.elToolbar); | |
| 2152 | + const elFilter = this.elAddonsPage.querySelector(selectors.elFilter); | |
| 2153 | + if (!elToolbar && !elFilter) { | |
| 2154 | + return; | |
| 2155 | + } | |
| 2156 | + const toggleBtn = this.elAddonsPage.querySelector(selectors.elFilterToggle); | |
| 2157 | + const shouldOpen = undefined !== open ? open : elToolbar ? !elToolbar.classList.contains('is-filter-open') : !elFilter.classList.contains('is-open'); | |
| 2158 | + if (elToolbar) { | |
| 2159 | + elToolbar.classList.toggle('is-filter-open', shouldOpen); | |
| 2160 | + } | |
| 2161 | + if (elFilter) { | |
| 2162 | + elFilter.classList.toggle('is-open', shouldOpen); | |
| 2163 | + } | |
| 2164 | + if (toggleBtn) { | |
| 2165 | + toggleBtn.setAttribute('aria-expanded', shouldOpen ? 'true' : 'false'); | |
| 2166 | + } | |
| 2167 | + } | |
| 2168 | + | |
| 2169 | + /** | |
| 2170 | + * Update filter toggle button has-filter state. | |
| 2171 | + * | |
| 2172 | + * @return void | |
| 2173 | + */ | |
| 2174 | + updateFilterToggleState() { | |
| 2175 | + const selectors = AdminAddons.selectors; | |
| 2176 | + const toggleBtn = this.elAddonsPage.querySelector(selectors.elFilterToggle); | |
| 2177 | + if (!toggleBtn) { | |
| 2178 | + return; | |
| 2179 | + } | |
| 2180 | + const elActiveTab = this.elAddonsPage.querySelector(selectors.elNavTabActive); | |
| 2181 | + const elActiveCategory = this.elAddonsPage.querySelector(selectors.elCategoryActive); | |
| 2182 | + const tabName = elActiveTab ? elActiveTab.dataset.tab : 'all'; | |
| 2183 | + const category = elActiveCategory ? elActiveCategory.dataset.category : 'all'; | |
| 2184 | + const hasFilter = 'all' !== tabName || 'all' !== category; | |
| 2185 | + toggleBtn.classList.toggle('has-filter', hasFilter); | |
| 2186 | + } | |
| 2187 | + | |
| 2188 | + /** | |
| 2000 | 2189 | * Handle category click. |
| 2001 | 2190 | * |
| 2002 | 2191 | * @param {Object} args Click event arguments. |
| 2003 | 2192 | * @return void |
| @@ -2013,8 +2202,9 @@ | ||
| 2013 | 2202 | const isActive = item === elCategory; |
| 2014 | 2203 | item.classList.toggle('active', isActive); |
| 2015 | 2204 | item.setAttribute('aria-pressed', isActive ? 'true' : 'false'); |
| 2016 | 2205 | }); |
| 2206 | + this.updateFilterToggleState(); | |
| 2017 | 2207 | this.filterAddons(); |
| 2018 | 2208 | } |
| 2019 | 2209 | |
| 2020 | 2210 | /** |
| @@ -2022,9 +2212,127 @@ | ||
| 2022 | 2212 | * |
| 2023 | 2213 | * @return void |
| 2024 | 2214 | */ |
| 2025 | 2215 | handleSearchInput() { |
| 2216 | + this.updateSearchClearBtnState(); | |
| 2026 | 2217 | this.filterAddons(); |
| 2218 | + } | |
| 2219 | + | |
| 2220 | + /** | |
| 2221 | + * Handle search button click to open search overlay. | |
| 2222 | + * | |
| 2223 | + * @param {Object} args Click event arguments. | |
| 2224 | + * @return void | |
| 2225 | + */ | |
| 2226 | + handleSearchBtnClick(args) { | |
| 2227 | + const { | |
| 2228 | + e | |
| 2229 | + } = args; | |
| 2230 | + e.preventDefault(); | |
| 2231 | + this.toggleFilterMenu(false); | |
| 2232 | + const selectors = AdminAddons.selectors; | |
| 2233 | + const elSearch = this.elAddonsPage.querySelector(selectors.elSearch); | |
| 2234 | + const elSearchInput = this.elAddonsPage.querySelector(selectors.elSearchInput); | |
| 2235 | + if (elSearch) { | |
| 2236 | + elSearch.classList.add('is-open'); | |
| 2237 | + const btn = elSearch.querySelector(selectors.elSearchBtn); | |
| 2238 | + if (btn) { | |
| 2239 | + btn.setAttribute('aria-expanded', 'true'); | |
| 2240 | + } | |
| 2241 | + } | |
| 2242 | + if (elSearchInput) { | |
| 2243 | + this.updateSearchClearBtnState(); | |
| 2244 | + elSearchInput.focus(); | |
| 2245 | + } | |
| 2246 | + } | |
| 2247 | + | |
| 2248 | + /** | |
| 2249 | + * Handle search clear button click. | |
| 2250 | + * | |
| 2251 | + * @param {Object} args Click event arguments. | |
| 2252 | + * @return void | |
| 2253 | + */ | |
| 2254 | + handleSearchClearClick(args) { | |
| 2255 | + const { | |
| 2256 | + e | |
| 2257 | + } = args; | |
| 2258 | + e.preventDefault(); | |
| 2259 | + const selectors = AdminAddons.selectors; | |
| 2260 | + const elSearchInput = this.elAddonsPage.querySelector(selectors.elSearchInput); | |
| 2261 | + if (elSearchInput) { | |
| 2262 | + elSearchInput.value = ''; | |
| 2263 | + this.updateSearchClearBtnState(); | |
| 2264 | + this.filterAddons(); | |
| 2265 | + elSearchInput.focus(); | |
| 2266 | + } | |
| 2267 | + } | |
| 2268 | + | |
| 2269 | + /** | |
| 2270 | + * Update disabled state of clear search button. | |
| 2271 | + * | |
| 2272 | + * @return void | |
| 2273 | + */ | |
| 2274 | + updateSearchClearBtnState() { | |
| 2275 | + const selectors = AdminAddons.selectors; | |
| 2276 | + const elSearchInput = this.elAddonsPage.querySelector(selectors.elSearchInput); | |
| 2277 | + const elClearBtn = this.elAddonsPage.querySelector(selectors.elSearchBtnClear); | |
| 2278 | + if (elClearBtn && elSearchInput) { | |
| 2279 | + elClearBtn.disabled = !elSearchInput.value.trim(); | |
| 2280 | + } | |
| 2281 | + } | |
| 2282 | + | |
| 2283 | + /** | |
| 2284 | + * Handle search close button click. | |
| 2285 | + * | |
| 2286 | + * @param {Object} args Click event arguments. | |
| 2287 | + * @return void | |
| 2288 | + */ | |
| 2289 | + handleSearchCloseClick(args) { | |
| 2290 | + const { | |
| 2291 | + e | |
| 2292 | + } = args; | |
| 2293 | + e.preventDefault(); | |
| 2294 | + this.closeSearch(); | |
| 2295 | + } | |
| 2296 | + | |
| 2297 | + /** | |
| 2298 | + * Handle search input keydown. | |
| 2299 | + * | |
| 2300 | + * @param {Object} args Keydown event arguments. | |
| 2301 | + * @return void | |
| 2302 | + */ | |
| 2303 | + handleSearchKeydown(args) { | |
| 2304 | + const { | |
| 2305 | + e | |
| 2306 | + } = args; | |
| 2307 | + if ('Escape' === e.key) { | |
| 2308 | + e.preventDefault(); | |
| 2309 | + this.closeSearch(); | |
| 2310 | + } | |
| 2311 | + } | |
| 2312 | + | |
| 2313 | + /** | |
| 2314 | + * Close search overlay and reset query if needed. | |
| 2315 | + * | |
| 2316 | + * @return void | |
| 2317 | + */ | |
| 2318 | + closeSearch() { | |
| 2319 | + const selectors = AdminAddons.selectors; | |
| 2320 | + const elSearch = this.elAddonsPage.querySelector(selectors.elSearch); | |
| 2321 | + const elSearchInput = this.elAddonsPage.querySelector(selectors.elSearchInput); | |
| 2322 | + if (elSearch) { | |
| 2323 | + elSearch.classList.remove('is-open'); | |
| 2324 | + const btn = elSearch.querySelector(selectors.elSearchBtn); | |
| 2325 | + if (btn) { | |
| 2326 | + btn.setAttribute('aria-expanded', 'false'); | |
| 2327 | + btn.focus(); | |
| 2328 | + } | |
| 2329 | + } | |
| 2330 | + if (elSearchInput && elSearchInput.value) { | |
| 2331 | + elSearchInput.value = ''; | |
| 2332 | + this.filterAddons(); | |
| 2333 | + } | |
| 2334 | + this.updateSearchClearBtnState(); | |
| 2027 | 2335 | } |
| 2028 | 2336 | |
| 2029 | 2337 | /** |
| 2030 | 2338 | * Handle purchase code input. |