wickes-css2 2.106.0-develop.1 → 2.106.0-develop.10

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 (143) hide show
  1. package/Readme.md +2 -3
  2. package/build/css/category-main.css +1 -1
  3. package/build/css/components/checkout-payment-details-v2.css +1 -1
  4. package/build/css/components/global-search.css +1 -1
  5. package/build/css/homepage-main.css +1 -1
  6. package/build/css/kitchen-plp-main.css +1 -1
  7. package/build/css/main.css +1 -1
  8. package/build/css/my-account-main-v2.css +1 -1
  9. package/build/css/my-account-main.css +1 -1
  10. package/build/css/pages/page_checkout_delivery-new.css +1 -1
  11. package/build/css/pages/page_products-list-combined.css +1 -1
  12. package/build/css/pdp-main-before-combine.css +1 -1
  13. package/build/css/pdp-main-critical.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/img/billie-pay-later.svg +13 -0
  19. package/build/img/giftcard.svg +28 -0
  20. package/build/js/account-members.min.js +1 -1
  21. package/build/js/add-project-list-id.min.js +1 -1
  22. package/build/js/address-book.min.js +1 -1
  23. package/build/js/basket.min.js +2 -2
  24. package/build/js/bundle.min.js +1 -1
  25. package/build/js/change-password.min.js +1 -1
  26. package/build/js/checkout.min.js +2 -2
  27. package/build/js/emulation.min.js +2175 -1857
  28. package/build/js/general.bundle.min.js +1 -1
  29. package/build/js/gift-cards.min.js +1 -0
  30. package/build/js/merged-checkout.min.js +2 -2
  31. package/build/js/mini-basket-slider.min.js +1 -1
  32. package/build/js/page/basket/basket-update-cart-action.js +4 -1
  33. package/build/js/page/basket/klarna.js +13 -3
  34. package/build/js/page/basket-v2.js +11 -7
  35. package/build/js/page/components/billie-modal.js +20 -20
  36. package/build/js/page/components/gift-cards.js +927 -0
  37. package/build/js/page/components/order-summary.js +57 -28
  38. package/build/js/page/components/toggle-password-visibility.js +22 -0
  39. package/build/js/page/components/voucher.js +52 -47
  40. package/build/js/page/count-stepper/pdp-count-stepper.js +29 -0
  41. package/build/js/page/filters/plp-filters-mobile.js +4 -7
  42. package/build/js/page/filters/plp-filters-utils.js +9 -0
  43. package/build/js/page/filters/plp-filters.js +13 -5
  44. package/build/js/page/kitchen/colour-swatches.js +152 -152
  45. package/build/js/page/quick-filter.js +106 -103
  46. package/build/js/page/share-project-list.js +151 -33
  47. package/build/js/page/utils/create-count-stepper.js +141 -0
  48. package/build/js/page/utils/gift-cards-utils.js +242 -0
  49. package/build/js/page/utils/input-handling.js +104 -0
  50. package/build/js/page/utils/show-hide-input.js +31 -0
  51. package/build/js/page/utils/validation.js +146 -96
  52. package/build/js/pdp-count-stepper.min.js +1 -0
  53. package/build/js/pdp.bundle.min.js +1 -1
  54. package/build/js/personal-details.min.js +1 -1
  55. package/build/js/plp-filters.min.js +2 -2
  56. package/build/js/plp.bundle.min.js +1 -1
  57. package/build/js/project-list.min.js +57 -14
  58. package/build/js/quiz.min.js +1 -1
  59. package/build/js/share-project-list.min.js +1 -1
  60. package/build/js/track-my-order.min.js +1 -1
  61. package/package.json +3 -3
  62. package/src/components/card_product_v2.hbs +6 -1
  63. package/src/components/checkout-payment-details-v2.hbs +4 -3
  64. package/src/components/gift-cards-hint.hbs +9 -0
  65. package/src/components/gift-cards.hbs +90 -0
  66. package/src/components/giftcard-chip.hbs +23 -0
  67. package/src/components/giftcard-summary.hbs +6 -0
  68. package/src/components/home-movers/form.hbs +1 -1
  69. package/src/components/price-block-v2.hbs +17 -16
  70. package/src/data/data_search-results_v2.json +2 -1
  71. package/src/elements/count-button.hbs +10 -0
  72. package/src/elements/form-row.hbs +1 -1
  73. package/src/elements/input.hbs +31 -2
  74. package/src/img/billie-pay-later.svg +13 -0
  75. package/src/img/giftcard.svg +28 -0
  76. package/src/js/components/general/notification.js +60 -40
  77. package/src/js/components/general/switchVat.js +151 -154
  78. package/src/js/components/pdp-billie-modal-scroll-reset.js +46 -42
  79. package/src/js/emulation/basket-data.js +2126 -2038
  80. package/src/js/emulation/billie-modal.js +6 -6
  81. package/src/js/emulation/checkLocalEnv.js +6 -5
  82. package/src/js/emulation/checkout-data.js +33 -0
  83. package/src/js/emulation/checkout-payment-details.js +23 -21
  84. package/src/js/emulation/forms.js +9 -2
  85. package/src/js/emulation/gift-cards.js +216 -0
  86. package/src/js/emulation/mock.js +98 -21
  87. package/src/js/emulation/plp-load-more.js +19 -13
  88. package/src/js/emulation/validity-emulation.js +33 -0
  89. package/src/js/page/basket/basket-update-cart-action.js +4 -1
  90. package/src/js/page/basket/klarna.js +13 -3
  91. package/src/js/page/basket-v2.js +11 -7
  92. package/src/js/page/components/billie-modal.js +20 -20
  93. package/src/js/page/components/gift-cards.js +927 -0
  94. package/src/js/page/components/order-summary.js +57 -28
  95. package/src/js/page/components/toggle-password-visibility.js +22 -0
  96. package/src/js/page/components/voucher.js +52 -47
  97. package/src/js/page/count-stepper/pdp-count-stepper.js +29 -0
  98. package/src/js/page/filters/plp-filters-mobile.js +4 -7
  99. package/src/js/page/filters/plp-filters-utils.js +9 -0
  100. package/src/js/page/filters/plp-filters.js +13 -5
  101. package/src/js/page/kitchen/colour-swatches.js +152 -152
  102. package/src/js/page/quick-filter.js +106 -103
  103. package/src/js/page/share-project-list.js +151 -33
  104. package/src/js/page/utils/create-count-stepper.js +141 -0
  105. package/src/js/page/utils/gift-cards-utils.js +242 -0
  106. package/src/js/page/utils/input-handling.js +104 -0
  107. package/src/js/page/utils/show-hide-input.js +31 -0
  108. package/src/js/page/utils/validation.js +146 -96
  109. package/src/layouts/checkout.hbs +1 -5
  110. package/src/page_my-account_change-password.html +1 -0
  111. package/src/page_payment-details-with-gift-card.html +8 -5
  112. package/src/page_plp-with-paint.html +1 -1
  113. package/src/page_plp_v2-energy-efficiency.html +1 -1
  114. package/src/page_plp_v2-favourite-products.html +1 -1
  115. package/src/page_plp_v2-vat.html +31 -26
  116. package/src/page_plp_v2.html +1 -1
  117. package/src/page_product-details-cnc-success-notification-vat.html +3 -2
  118. package/src/page_product_search-vat.html +1 -1
  119. package/src/page_product_search.html +1 -1
  120. package/src/page_search-results.html +1 -1
  121. package/src/partials/scripts.hbs +4 -0
  122. package/src/scss/components/_custom-slider.scss +7 -6
  123. package/src/scss/components/_gift-cards.scss +359 -0
  124. package/src/scss/components/_input-counter.scss +65 -0
  125. package/src/scss/components/_quick-filter.scss +32 -10
  126. package/src/scss/components/checkout-payment-details-v2.scss +6 -2
  127. package/src/scss/components/kitchen/_price-tooltip.scss +3 -2
  128. package/src/scss/components/kitchen/_price.scss +2 -2
  129. package/src/scss/helpers/_variables.scss +7 -16
  130. package/src/scss/pages/page_checkout_delivery-new.scss +30 -6
  131. package/src/scss/pages/page_products-list-combined.scss +34 -2
  132. package/src/scss/pdp-main.scss +1 -0
  133. package/build/js/page/plp-img-v2.js +0 -25
  134. package/src/components/.DS_Store +0 -0
  135. package/src/img/.DS_Store +0 -0
  136. package/src/img/placeholders/.DS_Store +0 -0
  137. package/src/js/.DS_Store +0 -0
  138. package/src/js/components/share-project-list.js +0 -56
  139. package/src/js/components/toggle-password-visibility.js +0 -58
  140. package/src/js/page/.DS_Store +0 -0
  141. package/src/js/page/plp-img-v2.js +0 -25
  142. package/src/scss/.DS_Store +0 -0
  143. package/src/scss/pages/.DS_Store +0 -0
@@ -0,0 +1,31 @@
1
+ export function initializeInputToggle($container) {
2
+ const $input = $container.find('input');
3
+ const $toggle = $container.find('.toggle-show');
4
+
5
+ if (!$input.length || !$toggle.length) return;
6
+
7
+ const handleToggleClick = (e) => {
8
+ e.preventDefault();
9
+
10
+ const isPassword = String($input.attr('type')) === 'password';
11
+ $input.attr('type', isPassword ? 'text' : 'password');
12
+ const $icon = $toggle.find('svg, i').first();
13
+
14
+ if ($icon.length) {
15
+ $icon
16
+ .removeClass('fa-eye fa-eye-slash')
17
+ .addClass(isPassword ? 'fa-eye' : 'fa-eye-slash');
18
+ }
19
+ };
20
+
21
+ const updateToggleVisibility = () => {
22
+ $toggle.toggle(($input.val() || '').length > 0);
23
+ };
24
+
25
+ $toggle
26
+ .off('click.passwordToggle mousedown.passwordToggle')
27
+ .on('mousedown.passwordToggle', handleToggleClick);
28
+
29
+ $input.off('input.passwordToggle').on('input.passwordToggle', updateToggleVisibility);
30
+ updateToggleVisibility();
31
+ }
@@ -1,97 +1,91 @@
1
1
  const validationEl = {
2
- idsOfInputsWithNoNeedToUpdateDuringTyping: ['address-lookup-query', 'modal-address-lookup-query']
3
- }
2
+ idsOfInputsWithNoNeedToUpdateDuringTyping: [
3
+ 'address-lookup-query',
4
+ 'modal-address-lookup-query',
5
+ ],
6
+ };
4
7
 
5
8
  const formElements = {
6
9
  formInvalid: 'form_invalid',
7
10
  fieldRow: '.form-row[data-row-required]',
8
11
  rowValidationError: 'form-row_validation-error',
9
- }
12
+ };
10
13
 
11
14
  const patterns = {
12
15
  guidPattern: /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i,
13
16
  userFriendlyIdPattern: /^[A-Za-z]{2,3}\d{6}$/,
14
- }
17
+ };
15
18
 
16
19
  export function addFieldValidation(fieldSelector, validationFunction) {
17
- $(fieldSelector).each(function(index, element) {
18
- $(element).blur(function() {
20
+ $(fieldSelector).each(function (index, element) {
21
+ $(element).blur(function () {
19
22
  updateInputValueBeforeValidation(this);
20
- validationFunction(this);
21
- if (!validationEl.idsOfInputsWithNoNeedToUpdateDuringTyping.includes(element.id)) {
22
- $(this).keyup(function() {
23
+ validationFunction(this);
24
+ if (!validationEl.idsOfInputsWithNoNeedToUpdateDuringTyping.includes(element.id)) {
25
+ $(this).keyup(function () {
23
26
  updateInputValueBeforeValidation(this);
24
27
  validationFunction(this);
25
28
  });
26
- }
29
+ }
27
30
  });
28
31
  });
29
32
  }
30
33
 
31
- export function updateInputValueBeforeValidation (element) {
34
+ export function updateInputValueBeforeValidation(element) {
32
35
  $(element).val($.trim($(element).val()));
33
36
  }
34
37
 
35
38
  export function validateEmail(element) {
36
- updateStylingError(element.id,
37
- isValidEmail(element.value),
38
- invalidEmailAddress);
39
- }
40
-
41
- export function isValidEmail (value) {
42
- const ipAddressPattern = "(?:(?:25[0-5]|2[0-4][\\d]|[01]?[\\d][\\d]?)\\.){3}(?:25[0-5]|2[0-4][\\d]|[01]?[\\d][\\d]?)",
43
- emailPattern = new RegExp("^(?=.{1,64}@)[\\w\\+-]+(\\.[\\w\\+-]+)*@(([A-Za-z\\d]+[A-Za-z\\d-]*\\.){1,3}[A-Za-z]{2,16}|" + ipAddressPattern + ")$"),
44
- charactersLimit = 254,
45
- isCharactersLimitReached = value.length <= charactersLimit;
39
+ updateStylingError(element.id, isValidEmail(element.value), invalidEmailAddress);
40
+ }
41
+
42
+ export function isValidEmail(value) {
43
+ const ipAddressPattern =
44
+ '(?:(?:25[0-5]|2[0-4][\\d]|[01]?[\\d][\\d]?)\\.){3}(?:25[0-5]|2[0-4][\\d]|[01]?[\\d][\\d]?)',
45
+ emailPattern = new RegExp(
46
+ '^(?=.{1,64}@)[\\w\\+-]+(\\.[\\w\\+-]+)*@(([A-Za-z\\d]+[A-Za-z\\d-]*\\.){1,3}[A-Za-z]{2,16}|' +
47
+ ipAddressPattern +
48
+ ')$'
49
+ ),
50
+ charactersLimit = 254,
51
+ isCharactersLimitReached = value.length <= charactersLimit;
46
52
  return emailPattern.test(value) && isCharactersLimitReached;
47
53
  }
48
54
 
49
- export function validatePassword (element) {
50
- updateStylingError(element.id,
51
- isValidPassword(element.value),
52
- invalidPassword);
55
+ export function validatePassword(element) {
56
+ updateStylingError(element.id, isValidPassword(element.value), invalidPassword);
53
57
  }
54
58
 
55
- export function isValidPassword (value) {
59
+ export function isValidPassword(value) {
56
60
  return value.length > 0;
57
61
  }
58
62
 
59
- export function validateTitle (element) {
60
- updateStylingError(element.id,
61
- isValidTitle(element.value),
62
- invalidTitle);
63
+ export function validateTitle(element) {
64
+ updateStylingError(element.id, isValidTitle(element.value), invalidTitle);
63
65
  }
64
66
 
65
- export function isValidTitle (value) {
67
+ export function isValidTitle(value) {
66
68
  return value.length > 0;
67
69
  }
68
70
 
69
- export function isValidOrderNumber (value) {
71
+ export function isValidOrderNumber(value) {
70
72
  return value.length >= 9;
71
73
  }
72
74
 
73
- export function validateFirstName (element) {
74
- updateStylingError(element.id,
75
- isValidInputTextField(element.value),
76
- invalidFirstName);
75
+ export function validateFirstName(element) {
76
+ updateStylingError(element.id, isValidInputTextField(element.value), invalidFirstName);
77
77
  }
78
78
 
79
- export function validateLastName (element) {
80
- updateStylingError(element.id,
81
- isValidInputTextField(element.value),
82
- invalidLastName);
79
+ export function validateLastName(element) {
80
+ updateStylingError(element.id, isValidInputTextField(element.value), invalidLastName);
83
81
  }
84
82
 
85
- export function validateAddress1 (element) {
86
- updateStylingError(element.id,
87
- isValidInputTextField(element.value),
88
- invalidAddressOne);
83
+ export function validateAddress1(element) {
84
+ updateStylingError(element.id, isValidInputTextField(element.value), invalidAddressOne);
89
85
  }
90
86
 
91
87
  export function validateCity(element) {
92
- updateStylingError(element.id,
93
- isValidInputTextField(element.value),
94
- invalidTownCity);
88
+ updateStylingError(element.id, isValidInputTextField(element.value), invalidTownCity);
95
89
  }
96
90
 
97
91
  export function isValidFieldSize(value) {
@@ -107,23 +101,27 @@ export function isValidInputTextField(value) {
107
101
  return isValidFieldSize(value) && regExp.test(value);
108
102
  }
109
103
 
110
- export function validateMobile (element, allowEmptyValue) {
111
- updateStylingError(element.id,
104
+ export function validateMobile(element, allowEmptyValue) {
105
+ updateStylingError(
106
+ element.id,
112
107
  isValidPhoneNumber(element.value, allowEmptyValue),
113
- invalidMobile);
108
+ invalidMobile
109
+ );
114
110
  }
115
111
 
116
112
  export function validatePhone(element) {
117
- updateStylingError(element.id,
118
- isValidPhoneNumber(element.value, true),
119
- invalidTelephone);
113
+ updateStylingError(element.id, isValidPhoneNumber(element.value, true), invalidTelephone);
120
114
  }
121
115
 
122
- export function isValidPhoneNumber(value, allowEmptyValue) {
123
- value = value.replace(/\s+/g, "");
116
+ export function isValidPhoneNumber(value, allowEmptyValue) {
117
+ value = value.replace(/\s+/g, '');
124
118
 
125
- var phonePatterElevenDigit = new RegExp("^0{1}\\d{10}$|^0{1}\\d{5}\\s{1}\\d{5}$|^0{1}\\d{4}\\s{1}\\d{6}$|^0{1}\\d{3}\\s{1}\\d{3}\\s{1}\\d{4}$|^0{1}\\d{2}\\s{1}\\d{4}\\s{1}\\d{4}$|^0{1}\\d{3}\\s{1}\\d{7}$");
126
- var phonePatternTenDigit = new RegExp("^0{1}\\d{9}$|^0{1}\\d{5}\\s{1}\\d{4}$|^0{1}\\d{4}\\s{1}\\d{5}$");
119
+ var phonePatterElevenDigit = new RegExp(
120
+ '^0{1}\\d{10}$|^0{1}\\d{5}\\s{1}\\d{5}$|^0{1}\\d{4}\\s{1}\\d{6}$|^0{1}\\d{3}\\s{1}\\d{3}\\s{1}\\d{4}$|^0{1}\\d{2}\\s{1}\\d{4}\\s{1}\\d{4}$|^0{1}\\d{3}\\s{1}\\d{7}$'
121
+ );
122
+ var phonePatternTenDigit = new RegExp(
123
+ '^0{1}\\d{9}$|^0{1}\\d{5}\\s{1}\\d{4}$|^0{1}\\d{4}\\s{1}\\d{5}$'
124
+ );
127
125
  var result = phonePatterElevenDigit.test(value) || phonePatternTenDigit.test(value);
128
126
 
129
127
  if (allowEmptyValue) {
@@ -137,22 +135,26 @@ export function validatePostcode(element, ifConvert) {
137
135
  var elementValue = element.value;
138
136
  var isValid = isValidPostcodeField(elementValue);
139
137
  if (ifConvert && isValid) {
140
- elementValue = elementValue.replace(/\s/g, "");
141
- $('#' + $.escapeSelector(element.id))
142
- .val(elementValue.substr(0, elementValue.length-3) + " " + elementValue.substr(elementValue.length-3));
138
+ elementValue = elementValue.replace(/\s/g, '');
139
+ $('#' + $.escapeSelector(element.id)).val(
140
+ elementValue.substr(0, elementValue.length - 3) +
141
+ ' ' +
142
+ elementValue.substr(elementValue.length - 3)
143
+ );
143
144
  }
144
145
  updateStylingError(element.id, isValid, invalidPostCode);
145
146
  }
146
147
 
147
148
  export function isValidPostcodeField(value) {
148
149
  const transformedValue = value.toUpperCase().replaceAll(' ', '');
149
- const regExp = new RegExp("^(GIR 0AA)|((([A-PR-UWYZ][0-9][0-9]?)|([A-PR-UWYZ][A-HK-Y][0-9][0-9]?)|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))[0-9][A-BD-HJLNP-UW-Z]{2})$");
150
- return transformedValue.replace(/\s+/g, "").length > 4 && regExp.test(transformedValue);
150
+ const regExp = new RegExp(
151
+ '^(GIR 0AA)|((([A-PR-UWYZ][0-9][0-9]?)|([A-PR-UWYZ][A-HK-Y][0-9][0-9]?)|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))[0-9][A-BD-HJLNP-UW-Z]{2})$'
152
+ );
153
+ return transformedValue.replace(/\s+/g, '').length > 4 && regExp.test(transformedValue);
151
154
  }
152
155
 
153
156
  export function validateHouseName(element) {
154
157
  updateStylingError(element.id, isValidHouseName(element.value));
155
-
156
158
  }
157
159
 
158
160
  export function isValidHouseName(value) {
@@ -161,30 +163,24 @@ export function isValidHouseName(value) {
161
163
  }
162
164
 
163
165
  export function validateAddressSelection(element) {
164
- updateStylingError(element.id,
165
- isValidAddressSelection(element),
166
- selectAddressMessage);
166
+ updateStylingError(element.id, isValidAddressSelection(element), selectAddressMessage);
167
167
  }
168
168
 
169
169
  export function isValidAddressSelection(element) {
170
- return !$('#' + $.escapeSelector(element.id)).is(":visible");
170
+ return !$('#' + $.escapeSelector(element.id)).is(':visible');
171
171
  }
172
172
 
173
173
  export function validateAddress2(element) {
174
- updateStylingError(element.id,
175
- isValidAddress2(element.value),
176
- invalidAddressTwo);
174
+ updateStylingError(element.id, isValidAddress2(element.value), invalidAddressTwo);
177
175
  }
178
176
 
179
177
  export function isValidAddress2(value) {
180
178
  var regExp = new RegExp("^[\\w ().,'-]+$|^$");
181
- return value.length === 0 || regExp.test( value);
179
+ return value.length === 0 || regExp.test(value);
182
180
  }
183
181
 
184
182
  export function validateVoucher(element) {
185
- updateStylingErrorForElement(element,
186
- isValidVoucher(element.value),
187
- invalidVoucherCode);
183
+ updateStylingErrorForElement(element, isValidVoucher(element.value), invalidVoucherCode);
188
184
  }
189
185
 
190
186
  export function isValidVoucher(value) {
@@ -198,9 +194,9 @@ export function validateNameOnCard(element) {
198
194
  if (fieldSizeIsValid) {
199
195
  if (element.value.length > nameOnCardMaxLength) {
200
196
  updateStylingError(element.id, false, invalidNameOnCardLength);
201
- } else if(isNameOnCardContainsOnly16Digits(element.value)) {
197
+ } else if (isNameOnCardContainsOnly16Digits(element.value)) {
202
198
  updateStylingError(element.id, false, invalidCustomNameOnCard);
203
- } else if(isNameOnCardContainsAtLeast14Digits(element.value)) {
199
+ } else if (isNameOnCardContainsAtLeast14Digits(element.value)) {
204
200
  updateStylingError(element.id, false, validationWarnNameOnCard);
205
201
  }
206
202
  } else {
@@ -208,21 +204,18 @@ export function validateNameOnCard(element) {
208
204
  }
209
205
  }
210
206
 
211
-
212
207
  export function isNameOnCardContainsOnly16Digits(value) {
213
- var regExp = new RegExp("^\\d{16}$");
208
+ var regExp = new RegExp('^\\d{16}$');
214
209
  return regExp.test(value);
215
210
  }
216
211
 
217
212
  export function isNameOnCardContainsAtLeast14Digits(value) {
218
- var regExp = new RegExp("^(.*\\d){14,}.*$");
213
+ var regExp = new RegExp('^(.*\\d){14,}.*$');
219
214
  return regExp.test(value);
220
215
  }
221
216
 
222
217
  export function validateStoreId(element) {
223
- updateStylingError(element.id,
224
- isValidStoreId(element.value),
225
- invalidStoreId);
218
+ updateStylingError(element.id, isValidStoreId(element.value), invalidStoreId);
226
219
  }
227
220
 
228
221
  export function isValidStoreId(value) {
@@ -236,13 +229,13 @@ export function updateStylingError(elementId, isValid, errorMessage) {
236
229
 
237
230
  export function updateStylingErrorForElement(element, isValid, errorMessage) {
238
231
  var parentElem = $(element).closest('.form-row');
239
- if (!parentElem.is(":visible")) {
232
+ if (!parentElem.is(':visible')) {
240
233
  return;
241
234
  }
242
235
  removeErrorStyling(parentElem);
243
236
  if (!isValid) {
244
- wrapWithError(parentElem);
245
- addErrorMessage(parentElem, errorMessage);
237
+ wrapWithError(parentElem);
238
+ addErrorMessage(parentElem, errorMessage);
246
239
  }
247
240
  }
248
241
 
@@ -251,13 +244,10 @@ export function removeErrorStyling(element) {
251
244
  element.find('.form-row__error').remove();
252
245
  }
253
246
 
254
-
255
247
  export function wrapWithError(element) {
256
248
  $(element).addClass('form-row_validation-error');
257
-
258
249
  }
259
250
 
260
-
261
251
  export function addErrorMessage(element, errorMessage) {
262
252
  if (errorMessage) {
263
253
  $(element).append('<div class="form-row__error">' + errorMessage + '</div>');
@@ -268,7 +258,11 @@ export function showValidationErrors(form, errorMsg) {
268
258
  var $form = $(form);
269
259
  if (!$form.hasClass(formElements.formInvalid)) {
270
260
  $form.find('.form-row__error').remove();
271
- $form.addClass(formElements.formInvalid).find(formElements.fieldRow).append(validationError(errorMsg)).addClass(formElements.rowValidationError);
261
+ $form
262
+ .addClass(formElements.formInvalid)
263
+ .find(formElements.fieldRow)
264
+ .append(validationError(errorMsg))
265
+ .addClass(formElements.rowValidationError);
272
266
  } else {
273
267
  $form.find(formElements.fieldRow).find('.form-row__error').text(errorMsg);
274
268
  }
@@ -279,7 +273,7 @@ export function showValidationErrors(form, errorMsg) {
279
273
  $scrollableEl = inModal ? $firstMsg.closest('.modal') : $('html, body'),
280
274
  y = inModal ? 0 : $firstMsg.offset().top - 30;
281
275
 
282
- $scrollableEl.animate({scrollTop: y}, 300);
276
+ $scrollableEl.animate({ scrollTop: y }, 300);
283
277
  }
284
278
  }
285
279
 
@@ -297,22 +291,78 @@ function isElementInViewport(el) {
297
291
  }
298
292
 
299
293
  function validationError(errorMsg) {
300
- return `<div class="form-row__error"> ${errorMsg || 'Error message here'}</div>`
294
+ return `<div class="form-row__error"> ${errorMsg || 'Error message here'}</div>`;
301
295
  }
302
296
 
303
297
  export function clearValidationErrors(form) {
304
298
  const $form = $(form);
305
299
  if ($form.hasClass('form_invalid')) {
306
- $form.removeClass('form_invalid')
307
- .find('.form-row[data-row-required]').removeClass('form-row_validation-error')
308
- .find('.form-row__error').remove();
300
+ $form
301
+ .removeClass('form_invalid')
302
+ .find('.form-row[data-row-required]')
303
+ .removeClass('form-row_validation-error')
304
+ .find('.form-row__error')
305
+ .remove();
309
306
  }
310
307
  }
311
308
 
312
- export function validateGuidPattern (value) {
309
+ export function validateGuidPattern(value) {
313
310
  return patterns.guidPattern.test(value);
314
311
  }
315
312
 
316
- export function validateUserFriendlyIdPattern (value) {
313
+ export function validateUserFriendlyIdPattern(value) {
317
314
  return patterns.userFriendlyIdPattern.test(value);
318
315
  }
316
+
317
+ export function showErrorText(
318
+ $input,
319
+ message,
320
+ fieldSelector,
321
+ errorTextClass,
322
+ errorClass,
323
+ ariaInvalidAttr
324
+ ) {
325
+ const $field = $input.closest(fieldSelector);
326
+ $field.addClass(errorClass);
327
+ $input.attr(ariaInvalidAttr, 'true');
328
+
329
+ let $err = $field.find(errorTextClass);
330
+ if (!$err.length) {
331
+ $err = $(`<div class="${errorTextClass.slice(1)}" />`).appendTo($field);
332
+ }
333
+ $err.text(message);
334
+ }
335
+
336
+ export function clearErrorText($input, fieldSelector, errorTextClass, errorClass, ariaInvalidAttr) {
337
+ const $field = $input.closest(fieldSelector);
338
+ $field.removeClass(errorClass);
339
+ $input.removeAttr(ariaInvalidAttr);
340
+ $field.find(errorTextClass).remove();
341
+ }
342
+
343
+ function digitsOnly(value) {
344
+ return String(value || '').replace(/\D/g, '');
345
+ }
346
+
347
+ function hasExactDigits(value, n) {
348
+ return digitsOnly(value).length === Number(n);
349
+ }
350
+
351
+ function validateByPredicate(
352
+ $input,
353
+ predicate,
354
+ message,
355
+ { fieldSelector, errorText: errorTextClass, fieldError: errorClass, ariaInvalidAttr }
356
+ ) {
357
+ const ok = !!predicate(String($input.val() || ''));
358
+ if (!ok) {
359
+ showErrorText($input, message, fieldSelector, errorTextClass, errorClass, ariaInvalidAttr);
360
+ } else {
361
+ clearErrorText($input, fieldSelector, errorTextClass, errorClass, ariaInvalidAttr);
362
+ }
363
+ return ok;
364
+ }
365
+
366
+ export function validateExactDigits($input, n, message, cfg) {
367
+ return validateByPredicate($input, (v) => hasExactDigits(v, n), message, cfg);
368
+ }
@@ -22,14 +22,10 @@
22
22
  {{/block}}
23
23
  <a id="skip-to-content"></a>
24
24
  <main {{#if fullWidth}}class="full-width-content"{{/if}}>
25
- <div class="globalMessages">
26
- <div class="container">
27
- {{#block "notification"}}{{/block}}
28
- </div>
29
- </div>
30
25
  <div class="container">
31
26
  <div class="row">
32
27
  {{#block "steps"}}{{/block}}
28
+ {{#block "notification"}}{{/block}}
33
29
  <div class="content">
34
30
  {{#block "main"}}{{/block}}
35
31
  </div>
@@ -62,5 +62,6 @@
62
62
  }}
63
63
  <script src="./js/pstrength.min.js"></script>
64
64
  <script src="./js/change-password.min.js"></script>
65
+ <script src="./js/toggle-password-visibility.min.js"></script>
65
66
  {{/content}}
66
67
  {{/extend}}
@@ -8,13 +8,15 @@
8
8
 
9
9
  <script src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"></script>
10
10
  {{/content}}
11
- {{#content "notification"}}
12
- {{> notifications notification-page.error text="Sorry, there are errors on this page. Please review the information you've entered and update sections marked in red."}}
13
- {{/content}}
14
11
  {{#content "steps"}}
15
12
  {{> steps-three-steps active-step-index="2"}}
16
13
  {{/content}}
17
14
 
15
+ {{#content "notification"}}
16
+ <div class="globalMessages container">
17
+ </div>
18
+ {{/content}}
19
+
18
20
  {{#content "aside"}}
19
21
  {{> order-summary delivery-address-v2.summary no-action=true id=1 basket-id=true clearPayIcon=clearPayIcon billieIcon=true paymentsCheckoutV2=true checkout=true}}
20
22
  {{/content}}
@@ -46,7 +48,7 @@
46
48
  <div class="billing-payment-block">
47
49
  <h3 class="billing-payment-block__heading">Billing & Payment</h3>
48
50
  <div class="billing-payment-block__wrapper">
49
- {{> checkout-payment-details-v2 apple-pay=true google-pay=true clear-pay=true billie=true}}
51
+ {{> checkout-payment-details-v2 apple-pay=true google-pay=true clear-pay=true klarna-method=true}}
50
52
  </div>
51
53
  </div>
52
54
 
@@ -61,7 +63,8 @@
61
63
  <script defer src="./js/page/checkout-payment-details.js"></script>
62
64
  <script defer src="./js/page/klarna-modal-scroll-disable.js"></script>
63
65
  <script defer src="./js/page/billie-business-type.js"></script>
66
+ <script defer src="./js/gift-cards.min.js"></script>
64
67
  {{> checkout-terms-and-conditions-modal }}
65
- {{> payment-loader hidden=true spinnerTypes=(array "billie-logo" "clearpay-logo" "paypal-logo")}}
68
+ {{> loader hidden=true modifier="page-loader"}}
66
69
  {{/content}}
67
70
  {{/extend}}
@@ -63,7 +63,7 @@
63
63
  {{/content}}
64
64
  {{#content "foot" mode="append"}}
65
65
  <script defer src="./js/page/plp.js"></script>
66
- <script defer src="./js/page/plp-img-v2.js"></script>
66
+
67
67
  <script defer src="./js/page/plp-cards-v2.js"></script>
68
68
  <script defer src="./js/search-filter.min.js"></script>
69
69
  {{/content}}
@@ -70,7 +70,7 @@
70
70
 
71
71
  <script defer src="./js/plp.bundle.min.js"></script>
72
72
  <script defer src="./js/energy-efficiency.min.js"></script>
73
- <script defer src="./js/page/plp-img-v2.js"></script>
73
+
74
74
  <script defer src="./js/page/plp-cards-v2.js"></script>
75
75
  <script defer src="./js/search-filter.min.js"></script>
76
76
  {{/content}}
@@ -69,7 +69,7 @@
69
69
  {{/content}}
70
70
  {{#content "foot" mode="append"}}
71
71
  <script defer src="./js/page/plp.js"></script>
72
- <script defer src="./js/page/plp-img-v2.js"></script>
72
+
73
73
  <script defer src="./js/page/plp-cards-v2.js"></script>
74
74
  <script defer src="./js/plp-favourite-product.bundle.min.js"></script>
75
75
  <script defer src="./js/plp-filters.min.js"></script>
@@ -1,19 +1,20 @@
1
- {{#extend "base" hybrisClass="hybris-class" pageClass="products-list-page" title="Products list" pagePlp=true switch-vat=true}}
2
- {{#content "head" mode="append" pagePlp=true}}
3
- <link type="text/css" rel="stylesheet" href="./css/pages/page_products-list.css">
4
- {{/content}}
1
+ {{#extend "base" hybrisClass="hybris-class" pageClass="products-list-page retail-media category-seo-config" title="Products list" globalSearchV2="true" pagePlp=true switch-vat=true bundle="plp"}}
2
+ {{#content "head" mode="append" pagePlp=true}}
3
+ <link type="text/css" rel="stylesheet" href="./css/components/global-search.css">
4
+ {{/content}}
5
+ <style></style>
5
6
  {{#content "body"}}
6
7
  <main>
7
8
  <div class="container">
8
-
9
9
  <div class="page-header page-header_border-all">
10
10
  <h1 class="page-header__title">
11
11
  Fire Doors
12
12
  </h1>
13
-
14
13
  {{> srp-injected}}
15
14
  </div>
16
15
 
16
+ {{> color-picker-plp }}
17
+
17
18
  <div class="row">
18
19
  <aside class="left-aside">
19
20
  {{> search-filter collapsed="accordion_collapsed" hidden="hidden-state"}}
@@ -21,35 +22,39 @@
21
22
 
22
23
  <div class="content">
23
24
  <div class="sort-products-list">
24
- <div class="sort-products-list__section sort-products-list__items-per-page">
25
- {{> form-row dropdown="true" ddn-mod="ddn_small" id="d1-top" label="Products per page" label-hidden="true" placeholder="All products per page"}}
26
- </div>
27
- <div class="sort-products-list__section sort-products-list__pagination">
28
- {{> pagination pagination1="true" }}
29
- {{> pagination pagination2="true" }}
25
+ <input id="numberOfPagesPLP" value="3" type="hidden">
26
+ <div class="sort-products-list__total">
27
+ <span>{{plp_load-more.pagination.totalNumberOfResults}} products</span>
30
28
  </div>
31
29
  <div class="sort-products-list__section sort-products-list__sort-by">
32
- {{> form-row dropdown="true" ddn-mod="ddn_small" id="d2" label="Sort by" label-hidden="true" placeholder="Name (descending)"}}
30
+ {{> form-row dropdown="true" ddn-mod="ddn_small" id="#sort_form1" label="Sort by" label-hidden="true" placeholder="Name (descending)"}}
33
31
  </div>
34
32
  </div>
35
33
 
36
34
  <div class="products-list products-list-v2">
37
- {{#if search-result_v2.product-banner}}
38
- {{>card_product_banner_v2}}
39
- {{/if}}
40
35
  {{#each search-result_v2.products}}
41
36
  {{>card_product_v2 switch-vat=true}}
42
37
  {{/each}}
38
+ {{#if search-result_v2.product-banner}}
39
+ {{#each search-result_v2.product-banner}}
40
+ {{>card_product_banner_v2}}
41
+ {{/each}}
42
+ {{/if}}
43
+ {{#if search-result_v2.sponsor-banner}}
44
+ {{#each search-result_v2.sponsor-banner}}
45
+ {{>card_sponsor_banner}}
46
+ {{/each}}
47
+ {{/if}}
48
+ {{#if search-result_v2.sponsor-product}}
49
+ {{#each search-result_v2.sponsor-product}}
50
+ {{>card_sponsor_product}}
51
+ {{/each}}
52
+ {{/if}}
43
53
  </div>
44
-
45
- <div class="sort-products-list">
46
- <div class="sort-products-list__section sort-products-list__items-per-page is-hidden">
47
- {{> form-row dropdown="true" ddn-mod="ddn_small" id="d1-bottom" label="Products per page" label-hidden="true" placeholder="All products per page"}}
48
- </div>
49
- <div class="sort-products-list__section sort-products-list__pagination">
50
- {{> pagination pagination1="true" }}
51
- {{> pagination pagination2="true" }}
52
- </div>
54
+ <div class="load-more-wrap">
55
+ <button class="btn btn-primary btn_full btn-load-more">
56
+ Load more
57
+ </button>
53
58
  </div>
54
59
  </div>
55
60
  <!-- ./content -->
@@ -66,8 +71,8 @@
66
71
  {{/content}}
67
72
  {{#content "foot" mode="append"}}
68
73
  <script defer src="./js/page/plp.js"></script>
69
- <script defer src="./js/page/plp-img-v2.js"></script>
70
74
  <script defer src="./js/page/plp-cards-v2.js"></script>
71
75
  <script defer src="./js/search-filter.min.js"></script>
76
+ <script defer src="./js/plp-filters.min.js"></script>
72
77
  {{/content}}
73
78
  {{/extend}}
@@ -83,7 +83,7 @@
83
83
  {{#content "foot" mode="append"}}
84
84
  {{> kitchen/filter-modal isKitchenMode=false modalTitle="Filter by" }}
85
85
  <script defer src="./js/plp.bundle.min.js"></script>
86
- <script defer src="./js/page/plp-img-v2.js"></script>
86
+
87
87
  <script defer src="./js/page/plp-cards-v2.js"></script>
88
88
  <script defer src="./js/search-filter.min.js"></script>
89
89
  <script defer src="./js/plp-filters.min.js"></script>
@@ -1,12 +1,13 @@
1
1
  {{#extend "base" pageClass="page-product-details" title="Product details page WisDOM VAT"
2
2
  isDiscount=true
3
3
  isSQM=true
4
- isDescription=false
4
+ isDescription=true
5
5
  isCashback=false
6
6
  isSize=true
7
7
  isGuide=true
8
8
  hourly-delivery=true
9
- badge-text='15% off'
9
+ badge-text='2 for £47'
10
+ badge-text-exc='2 for £46'
10
11
  badge-color='yellow'
11
12
  badge-text-color='gray'
12
13
  currentlyInStock=true