wickes-css2 2.105.0-develop.8 → 2.105.0-develop.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/Readme.md +1 -1
  2. package/build/css/category-main.css +1 -1
  3. package/build/css/homepage-main.css +1 -1
  4. package/build/css/kitchen-plp-main.css +1 -1
  5. package/build/css/main.css +1 -1
  6. package/build/css/my-account-main-v2.css +1 -1
  7. package/build/css/my-account-main.css +1 -1
  8. package/build/css/pages/my-account-v2.css +1 -1
  9. package/build/css/pages/page_product_search.css +1 -1
  10. package/build/css/pages/page_products-list-combined.css +1 -1
  11. package/build/css/pages/page_products-list.css +1 -1
  12. package/build/css/pages/tradePro-rewards.css +1 -1
  13. package/build/css/pdp-main-before-combine.css +1 -1
  14. package/build/css/pdp-main-non-critical.css +1 -1
  15. package/build/css/pdp-main.css +1 -1
  16. package/build/css/plp-main.css +1 -1
  17. package/build/css/store-locator-main.css +1 -1
  18. package/build/js/basket.min.js +2 -2
  19. package/build/js/bundle.min.js +1 -1
  20. package/build/js/checkout.min.js +2 -2
  21. package/build/js/emulation.min.js +12125 -11596
  22. package/build/js/general.bundle.min.js +1 -1
  23. package/build/js/kitchen/kitchen-plp.min.js +1 -9
  24. package/build/js/merged-checkout.min.js +2 -2
  25. package/build/js/mini-basket-slider.min.js +1 -1
  26. package/build/js/my-account.min.js +1 -1
  27. package/build/js/page/basket/basket-update-cart-action.js +59 -56
  28. package/build/js/page/basket/basket-update-cart.js +27 -27
  29. package/build/js/page/basket/basket-utils.js +40 -33
  30. package/build/js/page/basket/mini-basket-total.js +70 -66
  31. package/build/js/page/basket/quantity-change-handler.js +73 -55
  32. package/build/js/page/basket/update-quantity-operation.js +39 -30
  33. package/build/js/page/basket/update-quantity.js +62 -62
  34. package/build/js/page/basket-v2.js +362 -229
  35. package/build/js/page/billie-business-type.js +27 -27
  36. package/build/js/page/checkout-payment-details.js +301 -299
  37. package/build/js/page/components/discounts.js +39 -36
  38. package/build/js/page/components/mini-basket-slider.js +604 -545
  39. package/build/js/page/filters/desktop-nav.js +64 -0
  40. package/build/js/page/filters/mobile-nav.js +93 -0
  41. package/build/js/page/filters/plp-filters-chips.js +92 -0
  42. package/build/js/page/filters/plp-filters-mobile.js +150 -0
  43. package/build/js/page/filters/plp-filters-panel.js +123 -0
  44. package/build/js/page/filters/plp-filters-utils.js +66 -0
  45. package/build/js/page/filters/plp-filters.js +256 -0
  46. package/build/js/page/filters/sort-by.js +172 -0
  47. package/build/js/page/klarna-modal-scroll-disable.js +4 -4
  48. package/build/js/page/my-account.js +33 -33
  49. package/build/js/page/online-exclusive.js +28 -30
  50. package/build/js/page/search-filter.js +62 -0
  51. package/build/js/page/share-project-list.js +57 -0
  52. package/build/js/page/tradePro-rewards.js +69 -39
  53. package/build/js/page/utils/copy-to-clipboard.js +79 -47
  54. package/build/js/page/utils/helpers.js +14 -9
  55. package/build/js/page/utils/show-more-less.js +273 -0
  56. package/build/js/pdp.bundle.min.js +1 -1
  57. package/build/js/plp-filters.min.js +9 -0
  58. package/build/js/plp.bundle.min.js +1 -1
  59. package/build/js/project-list.min.js +143 -85
  60. package/build/js/search-filter.min.js +1 -0
  61. package/build/js/share-project-list.min.js +1 -0
  62. package/build/js/tradePro-rewards.min.js +1 -1
  63. package/package.json +2 -2
  64. package/src/components/.DS_Store +0 -0
  65. package/src/components/accordion.hbs +2 -2
  66. package/src/components/kitchen/dropdown.hbs +6 -3
  67. package/src/components/kitchen/filter-modal-content-kitchen.hbs +10 -0
  68. package/src/components/kitchen/filter-modal.hbs +10 -13
  69. package/src/components/kitchen/plp-filters.hbs +3 -1
  70. package/src/components/kitchen/sort-by.hbs +1 -1
  71. package/src/components/search-filter-modal-content.hbs +102 -0
  72. package/src/components/search-filter.hbs +121 -112
  73. package/src/data/data_plp_load-more.json +1 -1
  74. package/src/elements/btn.hbs +7 -0
  75. package/src/js/components/cards-swap.js +60 -58
  76. package/src/js/components/general/accordion.js +44 -33
  77. package/src/js/components/general/cart-slider.js +19 -16
  78. package/src/js/components/general/create-popup-slider.js +168 -173
  79. package/src/js/components/share-project-list.js +8 -5
  80. package/src/js/emulation/big-wins.js +1081 -904
  81. package/src/js/emulation/billie-modal.js +23 -19
  82. package/src/js/emulation/checkout-payment-details.js +47 -38
  83. package/src/js/emulation/custom-slider-emulation.js +17 -13
  84. package/src/js/emulation/filters-emulation.js +164 -0
  85. package/src/js/emulation/forms.js +360 -323
  86. package/src/js/emulation/mini-basket-data.js +1051 -923
  87. package/src/js/emulation/paymentLoader.js +17 -17
  88. package/src/js/emulation/pdf-file-loader.js +89 -91
  89. package/src/js/emulation/popover-mini-basket.js +246 -239
  90. package/src/js/emulation/product-counter.js +50 -0
  91. package/src/js/emulation/project-list-pdp.js +320 -316
  92. package/src/js/emulation/repayment-toggle.js +23 -24
  93. package/src/js/emulation/reset-filter-desktop.js +5 -0
  94. package/src/js/emulation/selectable.js +22 -18
  95. package/src/js/emulation/wismo-details.js +23 -31
  96. package/src/js/page/basket/basket-update-cart-action.js +59 -56
  97. package/src/js/page/basket/basket-update-cart.js +27 -27
  98. package/src/js/page/basket/basket-utils.js +40 -33
  99. package/src/js/page/basket/mini-basket-total.js +70 -66
  100. package/src/js/page/basket/quantity-change-handler.js +73 -55
  101. package/src/js/page/basket/update-quantity-operation.js +39 -30
  102. package/src/js/page/basket/update-quantity.js +62 -62
  103. package/src/js/page/basket-v2.js +362 -229
  104. package/src/js/page/billie-business-type.js +27 -27
  105. package/src/js/page/checkout-payment-details.js +301 -299
  106. package/src/js/page/components/discounts.js +39 -36
  107. package/src/js/page/components/mini-basket-slider.js +604 -545
  108. package/src/js/page/filters/desktop-nav.js +64 -0
  109. package/src/js/page/filters/mobile-nav.js +93 -0
  110. package/src/js/page/filters/plp-filters-chips.js +92 -0
  111. package/src/js/page/filters/plp-filters-mobile.js +150 -0
  112. package/src/js/page/filters/plp-filters-panel.js +123 -0
  113. package/src/js/page/filters/plp-filters-utils.js +66 -0
  114. package/src/js/page/filters/plp-filters.js +256 -0
  115. package/src/js/page/filters/sort-by.js +172 -0
  116. package/src/js/page/klarna-modal-scroll-disable.js +4 -4
  117. package/src/js/page/my-account.js +33 -33
  118. package/src/js/page/online-exclusive.js +28 -30
  119. package/src/js/page/search-filter.js +62 -0
  120. package/src/js/page/share-project-list.js +57 -0
  121. package/src/js/page/tradePro-rewards.js +69 -39
  122. package/src/js/page/utils/copy-to-clipboard.js +79 -47
  123. package/src/js/page/utils/helpers.js +14 -9
  124. package/src/js/page/utils/show-more-less.js +273 -0
  125. package/src/page_empty-shared-project-list-bicester-hub.html +4 -0
  126. package/src/page_empty-shopping-list_guest.html +1 -0
  127. package/src/page_kitchen-plp.html +2 -2
  128. package/src/page_my-shopping-list-add-notes.html +1 -0
  129. package/src/page_my-shopping-list-energy.html +1 -0
  130. package/src/page_my-shopping-list-hide-download.html +2 -1
  131. package/src/page_my-shopping-list-pdf.html +2 -0
  132. package/src/page_my-shopping-list-saved-ref.html +1 -0
  133. package/src/page_my-shopping-list-wisdom-oos-registered.html +1 -0
  134. package/src/page_my-shopping-list-wisdom-oos.html +1 -0
  135. package/src/page_my-shopping-list-wisdom-partial-registered.html +1 -0
  136. package/src/page_my-shopping-list-wisdom-registered.html +1 -0
  137. package/src/page_my-shopping-list-wisdom.html +1 -0
  138. package/src/page_my-shopping-list.html +1 -0
  139. package/src/page_my-shopping-list_not-register.html +3 -0
  140. package/src/page_plp-with-paint.html +2 -7
  141. package/src/page_plp.html +2 -7
  142. package/src/page_plp_v2-energy-efficiency.html +1 -6
  143. package/src/page_plp_v2-favourite-products.html +6 -7
  144. package/src/page_plp_v2-vat.html +2 -7
  145. package/src/page_plp_v2.html +22 -9
  146. package/src/page_product_search-vat.html +2 -7
  147. package/src/page_product_search.html +2 -7
  148. package/src/page_project-list-generate-project-list-ID.html +3 -0
  149. package/src/page_project-list-vat.html +4 -0
  150. package/src/page_project-list-with-new-share-popup-android.html +3 -1
  151. package/src/page_project-list-with-new-share-popup-ios.html +3 -1
  152. package/src/page_project-list-with-new-share-popup.html +2 -1
  153. package/src/page_search-results.html +2 -7
  154. package/src/page_shared-project-list-bicester-hub.html +3 -1
  155. package/src/scss/common/_common.scss +5 -4
  156. package/src/scss/components/_accordion.scss +1 -3
  157. package/src/scss/components/_custom-slider.scss +15 -14
  158. package/src/scss/components/_date-selection-add-new-styles.scss +6 -7
  159. package/src/scss/components/_date-selection.scss +1 -1
  160. package/src/scss/components/{kitchen/_filter-modal.scss → _filter-modal.scss} +55 -4
  161. package/src/scss/components/{kitchen/_plp-filters.scss → _plp-filters.scss} +31 -13
  162. package/src/scss/components/_popover-mini-basket.scss +3 -3
  163. package/src/scss/components/_search-filter.scss +95 -15
  164. package/src/scss/components/_sort-by.scss +190 -0
  165. package/src/scss/components/checkout-chip.scss +2 -2
  166. package/src/scss/components/checkout-payment-repayment-terms.scss +1 -1
  167. package/src/scss/components/my-account/_barcode.scss +1 -1
  168. package/src/scss/components/my-account/_cards-swap.scss +3 -1
  169. package/src/scss/components/my-account/_clipboard-code.scss +3 -3
  170. package/src/scss/components/my-account/_discount.scss +2 -2
  171. package/src/scss/globals/_global-components.scss +3 -0
  172. package/src/scss/helpers/_colors-semantic.scss +68 -68
  173. package/src/scss/helpers/_variables.scss +242 -196
  174. package/src/scss/kitchen-plp-main.scss +0 -3
  175. package/src/scss/main.scss +65 -65
  176. package/src/scss/pages/my-account-v2.scss +5 -5
  177. package/src/scss/pages/page_product-details-v2.scss +1 -4
  178. package/src/scss/pages/page_product_search.scss +9 -1
  179. package/src/scss/pages/page_products-list-combined.scss +28 -24
  180. package/src/scss/pages/page_products-list.scss +8 -0
  181. package/src/scss/pages/tradePro-rewards.scss +3 -4
  182. package/build/js/page/accordion.js +0 -35
  183. package/build/js/page/kitchen/plp-filters-chips.js +0 -90
  184. package/build/js/page/kitchen/plp-filters-mobile.js +0 -72
  185. package/build/js/page/kitchen/plp-filters-panel.js +0 -119
  186. package/build/js/page/kitchen/plp-filters-utils.js +0 -65
  187. package/build/js/page/kitchen/plp-filters.js +0 -205
  188. package/build/js/page/kitchen/sort-by.js +0 -157
  189. package/src/js/components/general/search-filter.js +0 -21
  190. package/src/js/page/accordion.js +0 -35
  191. package/src/js/page/kitchen/plp-filters-chips.js +0 -90
  192. package/src/js/page/kitchen/plp-filters-mobile.js +0 -72
  193. package/src/js/page/kitchen/plp-filters-panel.js +0 -119
  194. package/src/js/page/kitchen/plp-filters-utils.js +0 -65
  195. package/src/js/page/kitchen/plp-filters.js +0 -205
  196. package/src/js/page/kitchen/sort-by.js +0 -157
@@ -0,0 +1,62 @@
1
+ // import { createShowMoreLess } from './utils/show-more-less';
2
+
3
+ var Wick = Wick || {};
4
+
5
+ Wick.Overlay = (function () {
6
+ var filterMobile = $('.filter-results_mobile');
7
+ $('#open-overlay').click(function (event) {
8
+ event.preventDefault();
9
+ $('body').addClass('is-filters-visible');
10
+ filterMobile.toggleClass('show');
11
+ });
12
+
13
+ $('#close-overlay, .filter-results__btn-close').click(function (event) {
14
+ event.preventDefault();
15
+ if (filterMobile.hasClass('show')) {
16
+ $('body').removeClass('is-filters-visible');
17
+ filterMobile.removeClass('show');
18
+ }
19
+ });
20
+
21
+ $('.filter-results_desktop .filter__item input[type="checkbox"]').click(function () {
22
+ $(this).closest('form').submit();
23
+ });
24
+ })();
25
+
26
+ Wick.SearchFilter = (function () {
27
+ const SEL = {
28
+ CATEGORY: '.category-filter',
29
+ FILTER_MOBILE: '.filter-results_mobile',
30
+ OPEN: '.filter-modal-cta',
31
+ CLOSE: '.close',
32
+ FILTER_RESULT: '.filter-results_desktop',
33
+ DESKTOP_CHECKBOX: '.filter-results_desktop .filter__item input[type="checkbox"]',
34
+ BODY_ACTIVE: 'is-filters-visible',
35
+ };
36
+
37
+ // removed show more/show less logic from frontend (will be implemented on backend)
38
+ // const SRPShowMoreLess = createShowMoreLess({
39
+ // excludeGroup: ($group) => $group.hasClass(SEL.CATEGORY),
40
+ // });
41
+
42
+ // const $fm = $(SEL.FILTER_MOBILE);
43
+ // SRPShowMoreLess.init($(SEL.FILTER_RESULT));
44
+ // SRPShowMoreLess.init($fm);
45
+
46
+ $(SEL.OPEN).on('click', function (event) {
47
+ event.preventDefault();
48
+ // removed show more/show less logic from frontend (will be implemented on backend)
49
+ // SRPShowMoreLess.init($fm);
50
+ // SRPShowMoreLess.resetAll($fm);
51
+ });
52
+
53
+ $(document).on('click', SEL.CLOSE, function (event) {
54
+ event.preventDefault();
55
+ // removed show more/show less logic from frontend (will be implemented on backend)
56
+ // SRPShowMoreLess.resetAll($fm);
57
+ });
58
+
59
+ $(document).on('click', SEL.DESKTOP_CHECKBOX, function () {
60
+ $(this).closest('form').submit();
61
+ });
62
+ })();
@@ -0,0 +1,57 @@
1
+ import { copyToClipboard } from './utils/copy-to-clipboard';
2
+
3
+ var Wick = Wick || {};
4
+ Wick.ShareProjectList = (function () {
5
+ function init() {
6
+ var $input = $('#share-list-modal #shopping-list-link');
7
+ var linkContainer = $('#copy-link');
8
+ var $actualLink = linkContainer.find('a');
9
+ var copyClass = 'copy-link_hovered';
10
+
11
+ $actualLink.on('click', function (e) {
12
+ e.preventDefault();
13
+ });
14
+
15
+ function focusAndSelectInput() {
16
+ if (!$input.length) return;
17
+
18
+ var el = $input.get(0);
19
+
20
+ $input.removeAttr('disabled');
21
+
22
+ el.focus();
23
+
24
+ var len = (el.value || '').length;
25
+ if (typeof el.setSelectionRange === 'function') {
26
+ el.setSelectionRange(0, len);
27
+ } else if (typeof el.select === 'function') {
28
+ el.select();
29
+ }
30
+ }
31
+
32
+ linkContainer.on('click', function (e) {
33
+ e.preventDefault();
34
+
35
+ focusAndSelectInput();
36
+
37
+ var value = ($input.val() || '').trim();
38
+ if (!value) return;
39
+
40
+ copyToClipboard(value, linkContainer[0], { noUpperCase: true })
41
+ .then(function () {
42
+ $actualLink.addClass(copyClass);
43
+ })
44
+ .catch(function (e) {
45
+ console.error(e);
46
+ });
47
+ });
48
+
49
+ $input.on('click', function (e) {
50
+ e.preventDefault();
51
+ focusAndSelectInput();
52
+ $actualLink.removeClass(copyClass);
53
+ });
54
+ }
55
+
56
+ init();
57
+ })();
@@ -1,46 +1,76 @@
1
- import {copyToClipboard} from "./utils/copy-to-clipboard";
1
+ import { copyToClipboard } from './utils/copy-to-clipboard';
2
2
 
3
3
  var Wick = window.Wick || {};
4
4
 
5
5
  Wick.TradeProRewards = {
6
- el: {
7
- $tradeProRewards: $('.page_tradePro-rewards'),
8
- buttonSelector: '.copy-tradePro-barcode',
9
- },
10
- message: 'Code copied to clipboard',
11
- copyToClipboardInit() {
12
- Wick.SnackBar.init();
13
- $(Wick.TradeProRewards.el.buttonSelector).on('click', function (e) {
14
- e.preventDefault();
15
- e.stopPropagation();
16
- var discountCode = $(this).parent().find('input');
17
- var discountCodeValue = discountCode.val().trim();
18
- discountCode.removeAttr('disabled').attr('readonly', 'readonly');
19
-
20
- copyToClipboard(discountCodeValue, e.currentTarget, { noUpperCase: true });
21
-
22
- discountCode.attr('disabled', 'disabled').removeAttr('readonly');
23
- window.getSelection().removeAllRanges();
24
-
25
- Wick.SnackBar.show(
26
- {
27
- text: Wick.TradeProRewards.message,
28
- type: Wick.SnackBar.types.SUCCESS,
29
- withCloseButton: false,
30
- autoClose: true,
31
- delayBeforeClose: 3000
32
- }
33
- );
34
- return false;
35
- });
36
- },
37
- init() {
38
- Wick.TradeProRewards.copyToClipboardInit();
39
- }
40
- }
6
+ el: {
7
+ $tradeProRewards: $('.page_tradePro-rewards'),
8
+ buttonSelector: '.copy-tradePro-barcode',
9
+ },
10
+
11
+ message: 'Code copied to clipboard',
12
+ errorMessage: 'Unable to copy. Please copy manually',
13
+
14
+ copyToClipboardInit() {
15
+ Wick.SnackBar.init();
16
+
17
+ $(document).on('click', Wick.TradeProRewards.el.buttonSelector, async function (e) {
18
+ e.preventDefault();
19
+ e.stopPropagation();
20
+
21
+ const $btn = $(this);
22
+ const $input = $btn.parent().find('input');
23
+
24
+ if (!$input.length) return false;
25
+
26
+ const discountCodeValue = ($input.val() || '').trim();
27
+ if (!discountCodeValue) return false;
28
+
29
+ $input.removeAttr('disabled').attr('readonly', 'readonly');
30
+
31
+ try {
32
+ await copyToClipboard(discountCodeValue, e.currentTarget, { noUpperCase: true });
33
+
34
+ Wick.SnackBar.show({
35
+ text: Wick.TradeProRewards.message,
36
+ type: Wick.SnackBar.types.SUCCESS,
37
+ withCloseButton: false,
38
+ autoClose: true,
39
+ delayBeforeClose: 3000,
40
+ });
41
+ } catch (err) {
42
+ try {
43
+ const el = $input.get(0);
44
+ el.focus();
45
+ el.select();
46
+ el.setSelectionRange(0, 999999);
47
+ } catch (e) {
48
+ console.error(e);
49
+ }
50
+
51
+ Wick.SnackBar.show({
52
+ text: Wick.TradeProRewards.errorMessage,
53
+ type: Wick.SnackBar.types.ERROR,
54
+ withCloseButton: false,
55
+ autoClose: true,
56
+ delayBeforeClose: 4000,
57
+ });
58
+ }
59
+
60
+ $input.attr('disabled', 'disabled').removeAttr('readonly');
61
+ window.getSelection()?.removeAllRanges?.();
62
+
63
+ return false;
64
+ });
65
+ },
66
+
67
+ init() {
68
+ Wick.TradeProRewards.copyToClipboardInit();
69
+ },
70
+ };
41
71
 
42
72
  $(document).ready(function () {
43
- if (Wick.TradeProRewards.el.$tradeProRewards.length) {
44
- Wick.TradeProRewards.init();
45
- }
73
+ if (Wick.TradeProRewards.el.$tradeProRewards.length) {
74
+ Wick.TradeProRewards.init();
75
+ }
46
76
  });
@@ -1,56 +1,88 @@
1
1
  export function copyToClipboard(copyValue, currentSelector, options = {}) {
2
- const $temp = $('<textarea>').css({
3
- position: 'absolute',
4
- top: 0,
5
- left: 0,
6
- opacity: 0
7
- });
8
-
9
- $(currentSelector).parent().append($temp);
10
-
11
- let str;
12
- if (options.noUpperCase) {
13
- str = copyValue;
14
- } else {
15
- str = copyValue.replace(/(^\w|\s\w)/g, function (m) {
16
- return m.toUpperCase()
17
- });
18
- }
2
+ const textTrimmed = normalizeCopyText(copyValue, options);
19
3
 
20
- const textFiltered = str.split(' ').filter(function (value) {
21
- return value !== ''
22
- });
4
+ if (!textTrimmed) return Promise.reject(new Error('Empty text'));
23
5
 
24
- const textTrimmed = textFiltered.join(' ');
6
+ // 1) iOS app bridge (WKWebView)
7
+ if (window.webkit?.messageHandlers?.copy) {
8
+ try {
9
+ window.webkit.messageHandlers.copy.postMessage(textTrimmed);
10
+ return Promise.resolve(true);
11
+ } catch (e) {
12
+ console.error(e);
13
+ }
14
+ }
25
15
 
26
- $temp.val(textTrimmed);
16
+ // 2) Android app bridge
17
+ if (window.Android?.copyToClipboard && typeof window.Android.copyToClipboard === 'function') {
18
+ try {
19
+ window.Android.copyToClipboard(textTrimmed);
20
+ return Promise.resolve(true);
21
+ } catch (e) {
22
+ console.error(e);
23
+ }
24
+ }
27
25
 
28
- if (navigator.userAgent.match(/TradeProMobile_iOS|DIYMobile_iOS/i)) {
29
- iosCopyToClipboard($temp);
30
- } else if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
31
- $temp.select();
32
- $temp[0].setSelectionRange(0, 999999);
33
- } else {
34
- $temp.select();
35
- }
26
+ if (navigator.clipboard?.writeText) {
27
+ return navigator.clipboard.writeText(textTrimmed).then(() => true);
28
+ }
36
29
 
37
- document.execCommand("copy");
38
- $temp.remove();
30
+ return legacyExecCommandCopy(textTrimmed, currentSelector);
39
31
  }
40
32
 
41
- function iosCopyToClipboard($input) {
42
- const el = $input.get(0);
43
- const editable = el.contentEditable;
44
- const readOnly = el.readOnly;
45
- const range = document.createRange();
46
- const sel = window.getSelection();
47
-
48
- el.contentEditable = true;
49
- el.readOnly = false;
50
- range.selectNodeContents(el);
51
- sel.removeAllRanges();
52
- sel.addRange(range);
53
- el.setSelectionRange(0, 999999);
54
- el.contentEditable = editable;
55
- el.readOnly = readOnly;
33
+ function normalizeCopyText(copyValue, options) {
34
+ let raw = copyValue == null ? '' : copyValue + '';
35
+
36
+ const str = options.noUpperCase ? raw : raw.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase());
37
+
38
+ return str
39
+ .split(' ')
40
+ .filter((v) => v !== '')
41
+ .join(' ')
42
+ .trim();
43
+ }
44
+
45
+ function legacyExecCommandCopy(text, currentSelector) {
46
+ return new Promise(function (resolve, reject) {
47
+ try {
48
+ let $parent = $(currentSelector).parent();
49
+
50
+ let $temp = $('<textarea>').val(text).attr('readonly', 'readonly').css({
51
+ position: 'fixed',
52
+ top: 0,
53
+ left: '-9999px',
54
+ opacity: 0,
55
+ width: '1px',
56
+ height: '1px',
57
+ padding: 0,
58
+ border: 0,
59
+ margin: 0,
60
+ });
61
+
62
+ $parent.append($temp);
63
+
64
+ let el = $temp.get(0);
65
+
66
+ el.focus();
67
+ let len = (el.value || '').length;
68
+ if (typeof el.setSelectionRange === 'function') {
69
+ el.setSelectionRange(0, len);
70
+ } else {
71
+ $temp.select();
72
+ }
73
+
74
+ let ok = document.execCommand('copy');
75
+
76
+ $temp.remove();
77
+
78
+ if (window.getSelection) {
79
+ let sel = window.getSelection();
80
+ if (sel && sel.removeAllRanges) sel.removeAllRanges();
81
+ }
82
+
83
+ ok ? resolve(true) : reject(new Error('execCommand failed'));
84
+ } catch (e) {
85
+ reject(e);
86
+ }
87
+ });
56
88
  }
@@ -3,7 +3,7 @@ export function highlightCharacter(str, char, charClass) {
3
3
  return str;
4
4
  }
5
5
 
6
- const pattern = new RegExp(`\\${char}+`, "g");
6
+ const pattern = new RegExp(`\\${char}+`, 'g');
7
7
  const replacement = `<span class="${charClass}">$&</span>`;
8
8
 
9
9
  return str.replace(pattern, replacement);
@@ -12,7 +12,7 @@ export function highlightCharacter(str, char, charClass) {
12
12
  export function createImageElements(images, alt) {
13
13
  return images.map((link) => {
14
14
  return $('<img>').attr('src', link).attr('alt', alt);
15
- })
15
+ });
16
16
  }
17
17
 
18
18
  export function countLetters(str) {
@@ -35,15 +35,17 @@ export function isKeyboardOpen() {
35
35
  return screenHeight !== screenHeightWithoutKeyboard;
36
36
  }
37
37
 
38
- export function isTouchDevice () {
38
+ export function isTouchDevice() {
39
39
  return 'ontouchstart' in window;
40
40
  }
41
41
 
42
- export function isApp () {
43
- return navigator.userAgent.match(/TradeProMobile_iOS|TradeProMobile_Android|DIYMobile_iOS|DIYMobile_Android|DIYApp_Guest_Mobile_iOS|DIYApp_Guest_Mobile_Android|AGENT_PLACEHOLDER/i);
42
+ export function isApp() {
43
+ return navigator.userAgent.match(
44
+ /TradeProMobile_iOS|TradeProMobile_Android|DIYMobile_iOS|DIYMobile_Android|DIYApp_Guest_Mobile_iOS|DIYApp_Guest_Mobile_Android|AGENT_PLACEHOLDER/i
45
+ );
44
46
  }
45
47
 
46
- export function trimFields () {
48
+ export function trimFields() {
47
49
  const fields = Wick.AddressBook.getFieldsConfigurations();
48
50
  fields.forEach((field) => {
49
51
  const trimmedValue = field.input.val().trim();
@@ -55,8 +57,11 @@ export function scrollToElement(element, offset = 20) {
55
57
  const targetElement = $(element);
56
58
 
57
59
  if (targetElement.length > 0) {
58
- $('html, body').animate({
59
- scrollTop: targetElement.offset().top - offset
60
- }, 300);
60
+ $('html, body').animate(
61
+ {
62
+ scrollTop: targetElement.offset().top - offset,
63
+ },
64
+ 300
65
+ );
61
66
  }
62
67
  }
@@ -0,0 +1,273 @@
1
+ import btn from '../../../elements/btn.hbs';
2
+
3
+ // ===== HELPERS =====
4
+
5
+ function normalizeOptions(options) {
6
+ return {
7
+ groupSel: '.accordion.filter',
8
+ panelSel: '.accordion__content-inner',
9
+ itemSel: '.filter__item',
10
+
11
+ ctaAppendToSel: '.accordion__content-inner',
12
+ ctaClass: 'filter__facet-cta',
13
+ ctaAction: 'more',
14
+ ctaActionAttr: 'data-action',
15
+
16
+ toggleSel: '.accordion__header',
17
+
18
+ stateKey: 'showMoreLessState',
19
+ stepAttr: 'data-facet-step',
20
+ defaultStep: 5,
21
+
22
+ excludeGroup: null,
23
+
24
+ moreText: 'Show more',
25
+ lessText: 'Show less',
26
+
27
+ ...options,
28
+ };
29
+ }
30
+
31
+ function makeSelectors(opt) {
32
+ return {
33
+ GROUP: opt.groupSel,
34
+ PANEL: opt.panelSel,
35
+ ITEM: opt.itemSel,
36
+ TOGGLE: opt.toggleSel || null,
37
+
38
+ CTA: `.${opt.ctaClass}`,
39
+ CTA_APPEND_TO: opt.ctaAppendToSel,
40
+ };
41
+ }
42
+
43
+ function isExcluded($group, excludeFn) {
44
+ return typeof excludeFn === 'function' ? !!excludeFn($group) : false;
45
+ }
46
+
47
+ function getPanel($group, sel) {
48
+ return $group.find(sel.PANEL).first();
49
+ }
50
+
51
+ function getItems($group, sel) {
52
+ const $panel = getPanel($group, sel);
53
+ if (!$panel.length) return $();
54
+
55
+ const $direct = $panel.children(sel.ITEM);
56
+ return $direct.length ? $direct : $panel.find(sel.ITEM);
57
+ }
58
+
59
+ function getStep($group, stepAttr, defaultStep) {
60
+ const raw = ($group.attr(stepAttr) || '').trim();
61
+ const n = parseInt(raw, 10);
62
+ return Number.isFinite(n) && n > 0 ? n : defaultStep;
63
+ }
64
+
65
+ function getState($group, stateKey, total, step) {
66
+ let state = $group.data(stateKey);
67
+
68
+ if (!state) state = { visible: step, total };
69
+
70
+ state.total = total;
71
+
72
+ if (!state.visible || state.visible < step) state.visible = step;
73
+ if (state.visible > total) state.visible = total;
74
+
75
+ $group.data(stateKey, state);
76
+ return state;
77
+ }
78
+
79
+ function setInitialState($group, stateKey, total, step) {
80
+ $group.data(stateKey, { visible: step, total });
81
+ }
82
+
83
+ function getGroups($root, groupSel) {
84
+ const $scope = $root && $root.length ? $root : $(document);
85
+ const $self = $scope.is(groupSel) ? $scope : $();
86
+ const $found = $scope.find(groupSel);
87
+ return $self.add($found);
88
+ }
89
+
90
+ // ===== CTA helpers =====
91
+
92
+ function getCta($group, sel) {
93
+ return $group.find(sel.CTA).first();
94
+ }
95
+
96
+ function removeCta($group, sel) {
97
+ const $cta = getCta($group, sel);
98
+ if ($cta.length) $cta.remove();
99
+ }
100
+
101
+ function ensureCta($group, sel, opt) {
102
+ let $cta = getCta($group, sel);
103
+ if ($cta.length) return $cta;
104
+
105
+ const $appendTo = $group.find(sel.CTA_APPEND_TO).first();
106
+ if (!$appendTo.length) return $();
107
+
108
+ const html = btn({
109
+ text: opt.moreText,
110
+ class: opt.ctaClass,
111
+ action: opt.ctaAction,
112
+ });
113
+
114
+ $appendTo.append(html);
115
+
116
+ $cta = getCta($group, sel);
117
+
118
+ if ($cta.length && !$cta.attr(opt.ctaActionAttr)) {
119
+ $cta.attr(opt.ctaActionAttr, opt.ctaAction);
120
+ }
121
+
122
+ return $cta;
123
+ }
124
+
125
+ function setCtaState($cta, mode, opt) {
126
+ if (!$cta || !$cta.length) return;
127
+
128
+ if (mode === 'less') {
129
+ $cta.text(opt.lessText).attr(opt.ctaActionAttr, 'less').show();
130
+ } else {
131
+ $cta.text(opt.moreText).attr(opt.ctaActionAttr, 'more').show();
132
+ }
133
+ }
134
+
135
+ // ===== CORE ACTIONS =====
136
+
137
+ function applyGroup($group, opt, sel) {
138
+ if (!$group || !$group.length) return;
139
+
140
+ // excluded -> CTA never exists
141
+ if (isExcluded($group, opt.excludeGroup)) {
142
+ removeCta($group, sel);
143
+ return;
144
+ }
145
+
146
+ const $items = getItems($group, sel);
147
+ const total = $items.length;
148
+ const step = getStep($group, opt.stepAttr, opt.defaultStep);
149
+
150
+ // 0 items -> no CTA
151
+ if (total === 0) {
152
+ removeCta($group, sel);
153
+ return;
154
+ }
155
+
156
+ const state = getState($group, opt.stateKey, total, step);
157
+
158
+ // show/hide items
159
+ $items.each(function (idx) {
160
+ $(this).toggle(idx < state.visible);
161
+ });
162
+
163
+ // <= step -> CTA not needed
164
+ if (total <= step) {
165
+ removeCta($group, sel);
166
+ return;
167
+ }
168
+
169
+ // > step -> ensure CTA exists and update it
170
+ const $cta = ensureCta($group, sel, opt);
171
+ if (!$cta.length) return;
172
+
173
+ if (state.visible >= total) setCtaState($cta, 'less', opt);
174
+ else setCtaState($cta, 'more', opt);
175
+ }
176
+
177
+ function expandGroup($group, opt, sel) {
178
+ if (!$group || !$group.length) return;
179
+ if (isExcluded($group, opt.excludeGroup)) return;
180
+
181
+ const total = getItems($group, sel).length;
182
+ if (!total) return;
183
+
184
+ const step = getStep($group, opt.stepAttr, opt.defaultStep);
185
+ const state = getState($group, opt.stateKey, total, step);
186
+
187
+ state.visible = Math.min(state.visible + step, total);
188
+ $group.data(opt.stateKey, state);
189
+
190
+ applyGroup($group, opt, sel);
191
+ }
192
+
193
+ function collapseGroupToInitial($group, opt, sel) {
194
+ if (!$group || !$group.length) return;
195
+
196
+ if (isExcluded($group, opt.excludeGroup)) {
197
+ removeCta($group, sel);
198
+ return;
199
+ }
200
+
201
+ const total = getItems($group, sel).length;
202
+ const step = getStep($group, opt.stepAttr, opt.defaultStep);
203
+
204
+ setInitialState($group, opt.stateKey, total, step);
205
+ applyGroup($group, opt, sel);
206
+ }
207
+
208
+ // ===== MAIN FACTORY =====
209
+
210
+ export function createShowMoreLess(options = {}) {
211
+ const OPT = normalizeOptions(options);
212
+ const SEL = makeSelectors(OPT);
213
+
214
+ if (!SEL.GROUP || !SEL.PANEL || !SEL.ITEM) {
215
+ throw new Error('[createShowMoreLess] Missing required selectors');
216
+ }
217
+
218
+ // namespace for delegated events (avoid duplicates if factory created multiple times)
219
+ const NS = `.sml_${Math.random().toString(16).slice(2)}`;
220
+
221
+ function init($root) {
222
+ getGroups($root, SEL.GROUP).each(function () {
223
+ const $group = $(this);
224
+
225
+ if (isExcluded($group, OPT.excludeGroup)) {
226
+ removeCta($group, SEL);
227
+ return;
228
+ }
229
+
230
+ const total = getItems($group, SEL).length;
231
+ const step = getStep($group, OPT.stepAttr, OPT.defaultStep);
232
+
233
+ setInitialState($group, OPT.stateKey, total, step);
234
+ applyGroup($group, OPT, SEL);
235
+ });
236
+ }
237
+
238
+ function resetAll($root) {
239
+ getGroups($root, SEL.GROUP).each(function () {
240
+ collapseGroupToInitial($(this), OPT, SEL);
241
+ });
242
+ }
243
+
244
+ // CTA click
245
+ $(document)
246
+ .off(`click${NS}`, SEL.CTA)
247
+ .on(`click${NS}`, SEL.CTA, function (e) {
248
+ e.preventDefault();
249
+
250
+ const $cta = $(this);
251
+ const $group = $cta.closest(SEL.GROUP);
252
+
253
+ if (!$group.length || isExcluded($group, OPT.excludeGroup)) return;
254
+
255
+ const action = ($cta.attr(OPT.ctaActionAttr) || 'more').toLowerCase();
256
+
257
+ if (action === 'less') collapseGroupToInitial($group, OPT, SEL);
258
+ else expandGroup($group, OPT, SEL);
259
+ });
260
+
261
+ // Toggle/header click -> collapse to initial
262
+ if (SEL.TOGGLE) {
263
+ $(document)
264
+ .off(`click${NS}`, SEL.TOGGLE)
265
+ .on(`click${NS}`, SEL.TOGGLE, function () {
266
+ const $group = $(this).closest(SEL.GROUP);
267
+ if (!$group.length || isExcluded($group, OPT.excludeGroup)) return;
268
+ collapseGroupToInitial($group, OPT, SEL);
269
+ });
270
+ }
271
+
272
+ return { init, resetAll };
273
+ }