(() => { const { pageHelper, EventManager, utils, actions, constants } = ShopbySkin; const { unescapeHTML } = utils; const { NOTICE_MODAL_TYPE, PAGE, HTTP_STATUS } = constants; const searchParams = new URLSearchParams(location.search); const productNo = Number(searchParams.get('productNo')); const channelType = searchParams.get('channelType'); const trackingKey = searchParams.get('trackingKey'); const sortType = searchParams.get('sortType'); const cartAction = actions.getCartAction(); const productOptionAction = actions.getProductOptionAction(); const extraProductOptionAction = actions.getExtraProductOptionAction(); const productOptionEl = document.querySelector('product-purchase-v2'); const selectProductOptionEl = document.querySelector('select-product-option'); const selectedOptionsEl = document.querySelector('selected-options'); const extraProductOptionEl = document.querySelector('extra-products'); const extraProductSelectedOptionsEl = document.querySelector('extra-product-selected-options'); const { productDetailHelper } = pageHelper; const { initialize, deleteProductInquiryBy, searchReviewsV2 } = productDetailHelper(); EventManager.on('QUERY_PRODUCT_DETAIL', async (product) => { await productOptionAction.fetchOptions(productNo, { productInfo: product, }); productOptionAction.fetchOptionSelector(); ShopbySkin.structuredData?.injectProductStructuredData(product); // 상품 상세 구조화 데이터(JSON-LD)
삽입 // 외부스크립트 등록 기능. 삭제금지 ShopbyExternalScript?.setGlobalObjectSb({ product }); }); EventManager.on('QUERY_EXTRA_PRODUCTS_BY_PRODUCT_NO', (product) => { extraProductOptionAction.fetchExtraProductOptions(productNo, product); extraProductOptionAction.fetchExtraProductOptionSelector(); }); EventManager.on('PRODUCT_DETAIL_CONTENT_LOADED', () => { const imgs = document.querySelector('product-detail').querySelectorAll('img'); utils.lazyLoad({ imgEls: imgs }); }); EventManager.on('PRODUCT_DETAIL_OPTION_IMAGES_LOADED', () => { const imgs = document.querySelector('[slot="optionImages"]')?.querySelectorAll('img'); if (!imgs) { return; } utils.lazyLoad({ imgEls: imgs }); }); initialize({ productNo, channelType, sortType, cartAction, productOptionAction, extraProductOptionAction, disableInitFetchProductOptions: true, }); const redirectLoginPage = () => { const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`; }; const productLike = (productNo, { onSuccess }) => { if (!utils.isSignIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); return; } ShopbySkin.actions.toggleLikeStatus({ productNo, onSuccess, }); }; const getController = (target) => { const controllerId = target.getAttribute('shopby-controller-id') || target.closest('[shopby-controller-id]').getAttribute('shopby-controller-id'); if (!controllerId) { return null; } const { data } = productOptionAction.fetchOptionSelector(controllerId); return data; }; const getExtraProductController = (target) => { const controllerId = target.closest('[shopby-controller-id]')?.getAttribute('shopby-controller-id'); if (!controllerId || !extraProductSelectedOptionsEl) { return null; } const { extraProductsControllers } = extraProductSelectedOptionsEl.store.state; return extraProductsControllers.find((controller) => controller.id === controllerId) || null; }; const isInvalidMinorPurchaseYn = (options) => { const hasMinorPurchaseYnProduct = options.some((option) => option.minorPurchaseYn === 'N'); return hasMinorPurchaseYnProduct && !utils.isAgeVerified(); }; /** * 본 상품 구매수량(N). 추가상품 구매 제한 수량 판정 기준이므로 shared 검증에 넘긴다. * * 필수 추가상품 검증(비회원 대상)을 자체 정책으로 대체하려면 아래처럼 옵트아웃 한다. * fetchExtraProductUserOptionSelections({ baseProductCount, skipRequiredExtraProductValidation: true }) * 판정 함수는 ShopbySkin.utils.validateRequiredExtraProducts 로 공개돼 있어 재사용할 수 있다. */ const getBaseProductCount = (baseProductOptions) => baseProductOptions.reduce((total, { count = 0 }) => total + count, 0) || 1; let shopbyCommonData = {}; EventManager.on('PAGE_LOAD_COMPLETED', (commonData) => { shopbyCommonData = commonData; // 외부스크립트 등록 기능. 삭제금지 ShopbyExternalScript?.setPageScriptType('PRODUCT'); }); const ACTION_HANDLER_MAP = { COUPON_DOWNLOAD: () => { if (!utils.isSignIn()) { ShopbySkin.EventManager.fire('MODAL_ALERT_OPEN', { message: '로그인 후 이용할 수 있습니다.', onClose: redirectLoginPage, }); return; } const { extraProducts } = document.querySelector('extra-products').store.state; const extraProductNos = extraProducts.map((product) => product.productNo); ShopbySkin.EventManager.fire('OPEN_LAYER_MODAL', { title: '쿠폰 다운받기', name: 'coupon-download', data: { productNo, channelType: utils.getChannelType(), extraProductNos, }, isFull: false, onClose: () => null, }); }, INQUIRY_DETAIL: (target) => { const readable = target.getAttribute('shopby-readable') === 'true'; if (!readable) { EventManager.fire('MODAL_ALERT_OPEN', { message: '비밀글 조회 권한이 없습니다.', }); return; } target.closest('[shopby-active]').classList.toggle('active'); }, PRODUCT_INQUIRY_WRITE: (target) => { if (!utils.isSignIn()) { EventManager.fire('MODAL_ALERT_OPEN', { message: '먼저 로그인을 해주세요.', onClose: redirectLoginPage, }); return; } const productName = target.closest('[shopby-product-name]')?.getAttribute('shopby-product-name'); const imageUrl = target.closest('[shopby-image-url]')?.getAttribute('shopby-image-url'); const imageType = target.closest('[shopby-image-type]')?.getAttribute('shopby-image-type'); const { inquiryTags } = document.querySelector('product-detail-inquiry-list').store.state; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-inquiry-form', title: '상품문의', modalAddClass: 'product-inquiry-form-modal', isFull: false, data: { productNo, productName, unescapedProductName: unescapeHTML(productName), imageUrl, imageType, isModify: false, commonData: shopbyCommonData, useSelectProduct: false, inquiryTags, }, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '상품문의가 등록됐습니다.', onClose: () => { location.reload(); }, }); } }, }); }, INQUIRY_DELETE: (target) => { const inquiryNo = target.getAttribute('shopby-inquiry-no'); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'warning', message: '삭제 시 복구가 불가능합니다.
정말 삭제하시겠습니까?
삭제 시 복구가 불가하며,
지급된 적립금이 차감됩니다.
정말 삭제하시겠습니까?
삭제 시 복구가 불가능합니다.
정말 삭제하시겠습니까?
상품이 장바구니에 담겼습니다. 바로 확인하시겠습니까?
', cancelLabel: '쇼핑계속하기', confirmLabel: '장바구니 가기', onConfirm: () => { location.href = '/pages/order/cart.html'; }, }); }, PRODUCT_ORDER: async () => { const { isSignedIn } = utils; const { data } = productOptionAction.fetchUserOptionSelections(); const { data: extraProductData } = extraProductOptionAction.fetchExtraProductUserOptionSelections({ baseProductCount: getBaseProductCount(data), }); const { requestOrderSheet } = pageHelper.productDetailHelper(); const baseProductNo = productNo; const baseProductOptions = data.map((item) => ({ ...item, productNo, orderCnt: item.count, additionalProductNo: 0, channelType, })); const extraProductOptions = extraProductData.map((item) => ({ ...item, baseProductNo, orderCnt: item.count, additionalProductNo: 0, channelType, })); const products = [...baseProductOptions, ...extraProductOptions]; if (isInvalidMinorPurchaseYn(products)) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '성인인증이 필요한 상품입니다.', noticeType: NOTICE_MODAL_TYPE.CAUTION, onConfirm: () => { const nextFromUrl = productNo ? `${constants.PAGE.PRODUCT_DETAIL}?productNo=${productNo}` : constants.PAGE.MAIN; const nextUrl = `${constants.PAGE.ADULT_CERTIFICATION}?from=${encodeURIComponent(nextFromUrl)}`; utils.moveTo({ url: nextUrl, }); }, }); return; } const { orderSheetNo } = await requestOrderSheet({ cartNos: null, channelType, productCoupons: null, trackingKey, products, }); const orderSheetNoURL = `${location.origin}/pages/order/order-sheet-form.html?ordersheetNo=${orderSheetNo}`; const nextUrl = isSignedIn() ? orderSheetNoURL : `${location.origin}/pages/sign-in/sign-in.html?from=${orderSheetNoURL}`; window.location.href = nextUrl; }, SORT_TAB: (target) => { const sortType = target.getAttribute('shopby-sort-type'); const params = new URLSearchParams({ productNo, sortType, }); EventManager.fire('CHANGE_SORT_REVIEWS', { value: sortType }); history.pushState(null, null, `?${params.toString()}#PRODUCT_REVIEW`); }, REVIEW_CONTENT_TEXT: (target) => { target.closest('[shopby-element]').classList.toggle('open'); }, TOGGLE_DISCOUNT_DETAIL: () => { document.querySelector("[shopby-element='discount-tooltip']").classList.toggle('active'); }, RECOMMEND: () => { if (!utils.isSignIn()) { ShopbySkin.EventManager.fire('MODAL_ALERT_OPEN', { message: '로그인 후 이용할 수 있습니다.', onClose: redirectLoginPage, }); } }, PRODUCT_LIKE: (event) => { event.preventDefault(); const { target } = event; productLike(productNo, { onSuccess: (isLiked) => { const el = target.closest('[type=button]'); const messageEl = document.querySelector('[shopby-element="like-action-message"]'); messageEl.classList.remove('like-message'); // 페이드 아웃 메시지 setTimeout(() => { const actionMessage = isLiked ? '상품이 좋아요 리스트에 추가되었습니다.' : '상품이 좋아요 리스트에 제거되었습니다.'; messageEl.innerText = actionMessage; messageEl.classList.add('like-message'); }, 20); if (isLiked) { el.classList.add('is-active'); return; } el.classList.remove('is-active'); }, }); }, RELATED_PRODUCT_LIKE: (event) => { event.preventDefault(); const { target } = event; const productNo = target.closest('[shopby-product-no]')?.getAttribute('shopby-product-no'); if (!productNo) { return; } productLike(productNo, { onSuccess: (isLiked) => { const el = target.closest('[type=button]'); if (isLiked) { el.classList.add('is-active'); return; } el.classList.remove('is-active'); }, }); }, WRITE_REVIEW_REPORT: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('OPEN_LAYER_MODAL', { name: 'report-form', title: '신고하기', isFull: false, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { location.reload(); } }, onConfirm: async ({ reportReasonType, content }) => { const { status } = await actions.postProductReviewReport({ productNo, reviewNo, reportReasonCd: reportReasonType, content, }); if (status === HTTP_STATUS.NO_CONTENT) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, CANCEL_REVIEW_REPORT: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '신고를 취소 하시겠습니까?', confirmLabel: '확인', onConfirm: async () => { const { status } = await actions.deleteProductReviewReport({ productNo, reviewNo, }); if (status === HTTP_STATUS.NO_CONTENT) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고가 취소되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, // 상품 문의 신고 WRITE_INQUIRY_REPORT: (target) => { const inquiryNo = target.closest('[shopby-inquiry-no]')?.getAttribute('shopby-inquiry-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('OPEN_LAYER_MODAL', { name: 'report-form', title: '신고하기', isFull: false, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { location.reload(); } }, onConfirm: async ({ reportReasonType, content }) => { const { status } = await actions.postProductInquiryReport({ productNo, inquiryNo, reportType: reportReasonType, reason: content, }); if (status === HTTP_STATUS.NO_CONTENT) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, // 상품 문의 신고 취소 CANCEL_INQUIRY_REPORT: (target) => { const inquiryNo = target.closest('[shopby-inquiry-no]')?.getAttribute('shopby-inquiry-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '신고를 취소 하시겠습니까?', confirmLabel: '확인', onConfirm: async () => { const { status } = await actions.deleteProductInquiryReport({ productNo, inquiryNo, }); if (status === HTTP_STATUS.NO_CONTENT) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고가 취소 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, NOTIFY_RESTOCK: () => { EventManager.fire('OPEN_LAYER_MODAL', { title: '상품 재입고 알림 신청', name: 'restock-notification-form', data: { productNo, }, isFull: false, onClose: () => null, }); }, }; const CLICK_ACTION_HANDLER_MAP = { HANDLE_COUNT_BTN_CLICK: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(controllerEl.getAttribute('shopby-count')); const incremental = target.getAttribute('shopby-variation') === 'INCREASE'; controller.changeCount({ optionId, count: incremental ? count + 1 : count - 1, }); productOptionAction.fetchOptionSelector(); }, HANDLE_EXTRA_PRODUCT_COUNT_BTN_CLICK: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(controllerEl.getAttribute('shopby-count')); const incremental = target.getAttribute('shopby-variation') === 'INCREASE'; controller.changeCount({ optionId, count: incremental ? count + 1 : count - 1, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, REMOVE_OPTION: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); controller.removeOption({ optionId }); productOptionAction.fetchOptionSelector(); }, REMOVE_EXTRA_PRODUCT_OPTION: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); controller.removeOption({ optionId }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, TOGGLE_TEXT_OPTIONS_BY_QUANTITY: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const type = controllerEl.getAttribute('shopby-text-option-type'); const count = Number(controllerEl.getAttribute('shopby-count')); controller.toggleTextOptionType({ optionId, inputNo, type, count, }); productOptionAction.fetchOptionSelector(); }, TOGGLE_EXTRA_PRODUCT_TEXT_OPTIONS_BY_QUANTITY: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const type = controllerEl.getAttribute('shopby-text-option-type'); const count = Number(controllerEl.getAttribute('shopby-count')); controller.toggleTextOptionType({ optionId, inputNo, type, count, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, }; const CHANGE_ACTION_HANDLER_MAP = { SELECT_OPTION: (target) => { const controller = getController(target); if (!controller) { return; } const labelId = target.getAttribute('shopby-label-id'); const index = Number(target.getAttribute('shopby-index')); const optionId = target.value; controller.selectOption({ labelId, optionId, index, }); productOptionAction.fetchOptionSelector(); }, SELECT_EXTRA_PRODUCT_OPTION: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const labelId = target.getAttribute('shopby-label-id'); const index = Number(target.getAttribute('shopby-index')); const optionId = target.value; controller.selectOption({ labelId, optionId, index, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, CHANGE_COUNT: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(target.value); controller.changeCount({ optionId, count, }); productOptionAction.fetchOptionSelector(); }, CHANGE_EXTRA_PRODUCT_COUNT: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(target.value); controller.changeCount({ optionId, count, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, INPUT_TEXT_OPTION: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const textOptionId = target.getAttribute('shopby-text-option-id'); const maxLength = target.getAttribute('shopby-max-length'); controller.inputTextOption({ value: target.value, optionId, inputNo, textOptionId, maxLength, }); productOptionAction.fetchOptionSelector(); }, EXTRA_PRODUCT_INPUT_TEXT_OPTION: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const textOptionId = target.getAttribute('shopby-text-option-id'); const maxLength = target.getAttribute('shopby-max-length'); controller.inputTextOption({ value: target.value, optionId, inputNo, textOptionId, maxLength, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, }; const INPUT_ACTION_HANDLER_MAP = { INPUT_TEXT_OPTION: (target) => { const counterEl = target.closest('[shopby-counter]'); const countEl = counterEl.querySelector('[shopby-count]'); const errorMessageEl = counterEl.querySelector('[shopby-error-message]'); countEl.textContent = target.value.length; if (target.value.length > 100) { errorMessageEl.textContent = '텍스트옵션 입력글자수를 초과하였습니다.'; } else { errorMessageEl.textContent = ''; } }, }; document.querySelector('product-summary')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(); }); document.querySelector('product-purchase-v2')?.addEventListener('click', (event) => { ACTION_HANDLER_MAP[event.target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(event); }); document.querySelector('product-detail-review-list')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('product-detail-board-button')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('product-detail-inquiry-list')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('related-product')?.addEventListener('click', (event) => { ACTION_HANDLER_MAP[event.target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(event); }); productOptionEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); productOptionEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); productOptionEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); selectedOptionsEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectedOptionsEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectedOptionsEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductOptionEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductOptionEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductOptionEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductSelectedOptionsEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductSelectedOptionsEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductSelectedOptionsEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectProductOptionEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectProductOptionEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectProductOptionEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); })();