wickes-css2 2.113.0-develop.2 → 2.113.0-develop.5

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 (65) hide show
  1. package/build/css/pdp-main-before-combine.css +1 -1
  2. package/build/css/pdp-main-non-critical.css +1 -1
  3. package/build/css/pdp-main.css +1 -1
  4. package/build/js/basket.min.js +1 -1
  5. package/build/js/bloomreach-widget.min.js +1 -1
  6. package/build/js/bundle.min.js +1 -1
  7. package/build/js/checkout.min.js +1 -1
  8. package/build/js/emulation.min.js +360 -3222
  9. package/build/js/general.bundle.min.js +1 -1
  10. package/build/js/merged-checkout.min.js +1 -1
  11. package/build/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +318 -0
  12. package/build/js/page/bloomreach-widget/bloomreach-widget-core.js +370 -0
  13. package/build/js/page/bloomreach-widget/bloomreach-widget-tracking.js +16 -13
  14. package/build/js/page/bloomreach-widget/bloomreach-widget.js +8 -237
  15. package/build/js/page/bloomreach-widget/complete-your-project/cards.js +308 -0
  16. package/build/js/page/bloomreach-widget/complete-your-project/config.js +60 -0
  17. package/build/js/page/bloomreach-widget/complete-your-project/model.js +140 -0
  18. package/build/js/page/bloomreach-widget/complete-your-project/presenter.js +69 -0
  19. package/build/js/page/bloomreach-widget/complete-your-project/quantity.js +80 -0
  20. package/build/js/page/bloomreach-widget/complete-your-project/view.js +179 -0
  21. package/build/js/page/bloomreach-widget/complete-your-project/widget.js +185 -0
  22. package/build/js/page/bloomreach-widget/dont-forget-widget.js +15 -0
  23. package/build/js/page/bloomreach-widget/why-not-add-widget.js +10 -228
  24. package/build/js/pdp.bundle.min.js +1 -1
  25. package/build/js/plp.bundle.min.js +1 -1
  26. package/build/js/project-list.min.js +1 -1
  27. package/package.json +1 -1
  28. package/src/components/base/button.hbs +7 -0
  29. package/src/components/bloomreach/complete-your-project-skeleton.hbs +21 -0
  30. package/src/components/bloomreach/complete-your-project.hbs +6 -21
  31. package/src/components/bloomreach/why-not-add-card-skeleton.hbs +2 -2
  32. package/src/components/bloomreach/why-not-add-card.hbs +79 -60
  33. package/src/components/bloomreach/why-not-add-content.hbs +3 -3
  34. package/src/components/bloomreach/why-not-add.hbs +1 -1
  35. package/src/js/components/general/cart-slider.js +41 -4
  36. package/src/js/emulation/complete-your-project-loading.js +16 -0
  37. package/src/js/emulation/custom-slider-emulation.js +21 -8
  38. package/src/js/emulation/dont-forget-loading.js +36 -0
  39. package/src/js/emulation/just-added-scenarios-emulation.js +131 -0
  40. package/src/js/emulation/mini-basket.js +34 -34
  41. package/src/js/emulation/mock.js +429 -4
  42. package/src/js/emulation/why-not-add-loading.js +14 -3
  43. package/src/js/emulation/why-not-add.js +12 -14
  44. package/src/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +318 -0
  45. package/src/js/page/bloomreach-widget/bloomreach-widget-core.js +370 -0
  46. package/src/js/page/bloomreach-widget/bloomreach-widget-tracking.js +16 -13
  47. package/src/js/page/bloomreach-widget/bloomreach-widget.js +8 -237
  48. package/src/js/page/bloomreach-widget/complete-your-project/cards.js +308 -0
  49. package/src/js/page/bloomreach-widget/complete-your-project/config.js +60 -0
  50. package/src/js/page/bloomreach-widget/complete-your-project/model.js +140 -0
  51. package/src/js/page/bloomreach-widget/complete-your-project/presenter.js +69 -0
  52. package/src/js/page/bloomreach-widget/complete-your-project/quantity.js +80 -0
  53. package/src/js/page/bloomreach-widget/complete-your-project/view.js +179 -0
  54. package/src/js/page/bloomreach-widget/complete-your-project/widget.js +185 -0
  55. package/src/js/page/bloomreach-widget/dont-forget-widget.js +15 -0
  56. package/src/js/page/bloomreach-widget/why-not-add-widget.js +10 -228
  57. package/src/page_product-details-with-global-search-v2.html +4 -6
  58. package/src/page_product-details-with-why-not-add-single.html +1 -1
  59. package/src/scss/components/bloomreach/_bloomreach.scss +1 -0
  60. package/src/scss/components/bloomreach/_card-shared.scss +24 -0
  61. package/src/scss/components/bloomreach/_complete-card.scss +1 -9
  62. package/src/scss/components/bloomreach/_why-not-add-card.scss +137 -10
  63. package/src/scss/components/bloomreach/_why-not-add.scss +31 -2
  64. package/build/js/page/bloomreach-widget/complete-your-project-widget.js +0 -1100
  65. package/src/js/page/bloomreach-widget/complete-your-project-widget.js +0 -1100
@@ -15,22 +15,24 @@ function disconnectViewObserver(state) {
15
15
  state.viewObserver = null;
16
16
  }
17
17
 
18
- function observeView(state, elements) {
19
- if (!window.IntersectionObserver) {
18
+ function observeView(state, target) {
19
+ if (!target || !window.IntersectionObserver) {
20
20
  return;
21
21
  }
22
22
 
23
- elements = Array.isArray(elements) ? elements : [elements];
23
+ const elements = Array.isArray(target) ? target : [target];
24
24
 
25
25
  state.viewObserver = new IntersectionObserver(function (entries) {
26
- if (
27
- entries.some(function (entry) {
28
- return entry.isIntersecting;
29
- })
30
- ) {
31
- pushDataLayerEvent(EVENT_NAMES.view, state.widgetData);
32
- disconnectViewObserver(state);
26
+ const isVisible = entries.some(function (entry) {
27
+ return entry.isIntersecting;
28
+ });
29
+
30
+ if (!isVisible) {
31
+ return;
33
32
  }
33
+
34
+ pushDataLayerEvent(EVENT_NAMES.view, state.widgetData);
35
+ disconnectViewObserver(state);
34
36
  });
35
37
 
36
38
  elements.forEach(function (element) {
@@ -56,13 +58,14 @@ function trackAddToCart(state, items) {
56
58
 
57
59
  export function createBloomreachWidgetTracking() {
58
60
  const state = {
59
- initWidgetPayload: null,
61
+ widgetData: null,
60
62
  viewObserver: null,
61
63
  };
62
64
 
63
65
  return {
64
66
  setPayload(payloadData) {
65
67
  disconnectViewObserver(state);
68
+
66
69
  const metadata = payloadData.widgetMetadata;
67
70
 
68
71
  state.widgetData = {
@@ -72,8 +75,8 @@ export function createBloomreachWidgetTracking() {
72
75
  };
73
76
  },
74
77
 
75
- observeView(element) {
76
- observeView(state, element);
78
+ observeView(target) {
79
+ observeView(state, target);
77
80
  },
78
81
 
79
82
  trackClick(itemId) {
@@ -1,250 +1,21 @@
1
1
  var Wick = window.Wick || {};
2
2
 
3
- import { isApp } from '../utils/helpers';
4
- import { createEvent } from '../utils/create-event';
5
- import CompleteYourProjectWidget from './complete-your-project-widget';
3
+ import './bloomreach-widget-core';
4
+ import Widget from './complete-your-project/widget';
6
5
  import WhyNotAddWidget from './why-not-add-widget';
7
-
8
- Wick.BloomreachWidget = {
9
- widgets: {},
10
-
11
- el: {
12
- loadingButtonText: '.loading-button__text',
13
- loadingButtonLoader: '.loading-button__loader',
14
- ratingOverlay: '.rating-overlay',
15
- starOverlay: '.star-overlay',
16
- vatInc: '.including-vat-inherit',
17
- vatExc: '.excluding-vat-inherit',
18
- },
19
-
20
- registerWidgets(widgetList) {
21
- widgetList.forEach(function ({ type, widget }) {
22
- Wick.BloomreachWidget.widgets[type] = widget;
23
- });
24
- },
25
-
26
- getWidget(type) {
27
- return Wick.BloomreachWidget.widgets[type];
28
- },
29
-
30
- init(type, payloadData) {
31
- const widget = Wick.BloomreachWidget.getWidget(type);
32
-
33
- if (!widget || typeof widget.init !== 'function') {
34
- return;
35
- }
36
-
37
- widget.init(payloadData, Wick.BloomreachWidget);
38
- },
39
-
40
- normalizePayload(payloadData) {
41
- if (Array.isArray(payloadData)) {
42
- return payloadData;
43
- }
44
-
45
- if (payloadData && Array.isArray(payloadData.recommendedProducts)) {
46
- return payloadData.recommendedProducts;
47
- }
48
-
49
- return [];
50
- },
51
-
52
- hasRecommendations(payloadData) {
53
- return Wick.BloomreachWidget.normalizePayload(payloadData).length > 0;
54
- },
55
-
56
- getDisplayPrice(product) {
57
- return product.displayPrice || product.price || {};
58
- },
59
-
60
- getDisplayPriceExcVat(product) {
61
- return product.displayPriceExclusiveVat || product.priceExclusiveVat || null;
62
- },
63
-
64
- getPriceValue(price) {
65
- return price && typeof price.value === 'number' ? price.value : 0;
66
- },
67
-
68
- getPriceFormattedValue(price) {
69
- if (!price) {
70
- return '';
71
- }
72
-
73
- if (price.formattedValue) {
74
- return price.formattedValue;
75
- }
76
-
77
- if (typeof price.value === 'number') {
78
- return Wick.BloomreachWidget.formatPrice(price.value);
79
- }
80
-
81
- return '';
82
- },
83
-
84
- removeBlankTargets($root) {
85
- if (!isApp()) {
86
- return;
87
- }
88
-
89
- $root.find('a[target="_blank"]').removeAttr('target');
90
- },
91
-
92
- getWasPrice(product) {
93
- const displayPrice = Wick.BloomreachWidget.getDisplayPrice(product);
94
-
95
- return displayPrice && displayPrice.wasPrice ? displayPrice.wasPrice : null;
96
- },
97
-
98
- getWasPriceFormatted(product) {
99
- const displayPrice = Wick.BloomreachWidget.getDisplayPrice(product);
100
- const wasPrice = Wick.BloomreachWidget.getWasPrice(product);
101
-
102
- if (wasPrice && wasPrice.formattedValue) {
103
- return wasPrice.formattedValue;
104
- }
105
-
106
- if (typeof wasPrice === 'number') {
107
- return Wick.BloomreachWidget.formatPrice(wasPrice);
108
- }
109
-
110
- if (wasPrice) {
111
- return `${displayPrice.currencySymbol || '£'}${wasPrice}`;
112
- }
113
-
114
- return '';
115
- },
116
-
117
- getExcVatWasPrice(product) {
118
- const priceExclusiveVat = product.priceExclusiveVat || null;
119
- const displayPriceExclusiveVat = product.displayPriceExclusiveVat || null;
120
- const wasPrice =
121
- (displayPriceExclusiveVat && displayPriceExclusiveVat.wasPrice) ||
122
- (priceExclusiveVat && priceExclusiveVat.wasPrice);
123
-
124
- if (wasPrice && wasPrice.formattedValue) {
125
- return wasPrice.formattedValue;
126
- }
127
-
128
- if (typeof wasPrice === 'number') {
129
- return Wick.BloomreachWidget.formatPrice(wasPrice);
130
- }
131
-
132
- return wasPrice || '';
133
- },
134
-
135
- getProductImage(product, fallbackProduct) {
136
- const productImages = product.images || [];
137
- const fallbackImages = fallbackProduct ? fallbackProduct.images || [] : [];
138
- const images = productImages.length ? productImages : fallbackImages;
139
-
140
- return (
141
- images.find(function (item) {
142
- return item.format === 'product';
143
- }) ||
144
- images.find(function (item) {
145
- return item.imageType === 'PRIMARY';
146
- }) ||
147
- images[0] ||
148
- {}
149
- );
150
- },
151
-
152
- getProductRenderData(product, options = {}) {
153
- const displayPrice = Wick.BloomreachWidget.getDisplayPrice(product);
154
- const displayPriceExcVat = Wick.BloomreachWidget.getDisplayPriceExcVat(product);
155
- const wasPriceFormatted = Wick.BloomreachWidget.getWasPriceFormatted(product);
156
- const excVatWasPriceFormatted = Wick.BloomreachWidget.getExcVatWasPrice(product);
157
- const isSwitchVat = !!(window.ACC && window.ACC.app && window.ACC.app.isVatToggleAvailable);
158
-
159
- return {
160
- ...product,
161
- price: displayPrice,
162
- image:
163
- options.image ||
164
- Wick.BloomreachWidget.getProductImage(product, options.fallbackProduct),
165
- wasPriceFormatted,
166
- 'switch-vat': isSwitchVat,
167
- incVatFormattedValue: Wick.BloomreachWidget.getPriceFormattedValue(displayPrice),
168
- incVatValue: Wick.BloomreachWidget.getPriceValue(displayPrice),
169
- excVatFormattedValue: Wick.BloomreachWidget.getPriceFormattedValue(displayPriceExcVat),
170
- excVatValue: Wick.BloomreachWidget.getPriceValue(displayPriceExcVat),
171
- incVatWasPriceFormatted: wasPriceFormatted,
172
- excVatWasPriceFormatted: Wick.BloomreachWidget.getExcVatWasPrice(product),
173
- };
174
- },
175
-
176
- drawRating($root) {
177
- const { ratingOverlay, starOverlay } = Wick.BloomreachWidget.el;
178
-
179
- $root.find(ratingOverlay).each(function () {
180
- let rating = parseFloat($(this).attr('data-rating')) || 0;
181
- const $stars = $(this).children(starOverlay);
182
-
183
- $stars.each(function () {
184
- const $star = $(this);
185
-
186
- if (rating >= 1) {
187
- rating--;
188
- } else if (rating > 0) {
189
- const width = Math.asin(2 * rating - 1) / Math.PI + 0.5;
190
- $star.css('width', width + 'rem');
191
- rating = 0;
192
- } else {
193
- $star.css('width', '0rem');
194
- }
195
- });
196
- });
197
- },
198
-
199
- dispatchWidgetEvent(eventName, payload) {
200
- return new Promise(function (resolve, reject) {
201
- const eventDetail = { resolve, reject };
202
- const event = createEvent(eventName, payload, eventDetail);
203
-
204
- window.dispatchEvent(event);
205
- });
206
- },
207
-
208
- reapplyVatDisplay() {
209
- if (!Wick.VatToggle || typeof Wick.VatToggle.isActive !== 'function') {
210
- return;
211
- }
212
-
213
- const { vatInc, vatExc } = Wick.BloomreachWidget.el;
214
- const hiddenClassName = Wick.VatToggle.HIDDEN_CLASS_NAME || 'd-none';
215
- const isExcVatActive = Wick.VatToggle.isActive();
216
-
217
- $(vatInc).toggleClass(hiddenClassName, isExcVatActive);
218
- $(vatExc).toggleClass(hiddenClassName, !isExcVatActive);
219
- },
220
-
221
- bindVatToggle(namespace) {
222
- if (!Wick.VatToggle || !Wick.VatToggle.TOGGLE_VAT_EVENT_NAME) {
223
- return;
224
- }
225
-
226
- const eventName = `${Wick.VatToggle.TOGGLE_VAT_EVENT_NAME}.${namespace}`;
227
-
228
- $(window).off(eventName).on(eventName, Wick.BloomreachWidget.reapplyVatDisplay);
229
- },
230
-
231
- formatPrice(value) {
232
- return new Intl.NumberFormat('en-GB', {
233
- style: 'currency',
234
- currency: 'GBP',
235
- minimumFractionDigits: 2,
236
- maximumFractionDigits: 2,
237
- }).format(value);
238
- },
239
- };
6
+ import DontForgetWidget from './dont-forget-widget';
240
7
 
241
8
  Wick.BloomreachWidget.registerWidgets([
242
9
  {
243
10
  type: 'completeYourProject',
244
- widget: CompleteYourProjectWidget,
11
+ widget: Widget,
245
12
  },
246
13
  {
247
14
  type: 'whyNotAdd',
248
15
  widget: WhyNotAddWidget,
249
16
  },
17
+ {
18
+ type: 'dontForget',
19
+ widget: DontForgetWidget,
20
+ },
250
21
  ]);
@@ -0,0 +1,308 @@
1
+ import { createDropdown } from '../../utils/custom-dropdown';
2
+ import {
3
+ COMPLETE_YOUR_PROJECT_EL as EL,
4
+ COMPLETE_YOUR_PROJECT_TEMPLATES as TEMPLATES,
5
+ } from './config';
6
+ import { createCompleteYourProjectQuantity } from './quantity';
7
+
8
+ export function createCompleteYourProjectCards({
9
+ model,
10
+ presenter,
11
+ view,
12
+ tracking,
13
+ calculateTotal,
14
+ }) {
15
+ let dropdownCurrent = {};
16
+
17
+ function resetDropdownState() {
18
+ dropdownCurrent = {};
19
+ }
20
+
21
+ function getDropdownCard($dropdown) {
22
+ return $dropdown.closest(EL.completeCard);
23
+ }
24
+
25
+ function getDropdownCheckbox($dropdown) {
26
+ return getDropdownCard($dropdown).find(EL.cardCheckbox);
27
+ }
28
+
29
+ function setDropdownCheckboxState($dropdown, isChecked, shouldTriggerChange = true) {
30
+ const $checkbox = getDropdownCheckbox($dropdown);
31
+
32
+ if (!$checkbox.length) {
33
+ return;
34
+ }
35
+
36
+ $checkbox.prop('checked', isChecked);
37
+
38
+ if (shouldTriggerChange) {
39
+ $checkbox.trigger('change');
40
+ }
41
+ }
42
+
43
+ function setDropdownError($dropdown, hasError) {
44
+ $dropdown.toggleClass(EL.dropdownErrorClass, hasError);
45
+ }
46
+
47
+ function validateDropdown($dropdown, options = {}) {
48
+ const isValid = Boolean($dropdown.data(EL.selectedValueData));
49
+
50
+ setDropdownError($dropdown, !isValid);
51
+
52
+ if (!isValid && options.uncheck) {
53
+ setDropdownCheckboxState($dropdown, false, false);
54
+ getDropdownCard($dropdown).removeClass(EL.selectedClass);
55
+ }
56
+
57
+ return isValid;
58
+ }
59
+
60
+ function validateCardDropdown($card, options = {}) {
61
+ const $dropdown = $card.find(EL.dropdownRoot);
62
+
63
+ if (!$dropdown.length) {
64
+ return true;
65
+ }
66
+
67
+ return validateDropdown($dropdown, options);
68
+ }
69
+
70
+ function reinitCard($card) {
71
+ $card.find(EL.countBtn).remove();
72
+ quantity.initQuantityFields($card);
73
+ Wick.BloomreachWidget.drawRating($card);
74
+ view.alignCardBlocks($card.closest(EL.completeWidget));
75
+ Wick.BloomreachWidget.reapplyVatDisplay();
76
+ }
77
+
78
+ function replaceCard($card, recommendationIndex, product, renderOptions = {}, state = {}) {
79
+ const productData = presenter.getProductRenderData(
80
+ product,
81
+ recommendationIndex,
82
+ renderOptions
83
+ );
84
+ const $newCard = $(TEMPLATES.card(productData));
85
+
86
+ $newCard.attr(EL.recommendationIndexAttr, recommendationIndex);
87
+ $newCard.toggleClass(EL.selectedClass, Boolean(state.checked));
88
+
89
+ const $newDropdown = $newCard.find(EL.dropdownRoot);
90
+
91
+ if ($newDropdown.length && state.selectedValue) {
92
+ $newDropdown.data(EL.selectedValueData, state.selectedValue);
93
+ }
94
+
95
+ if (state.dropdownError) {
96
+ $newDropdown.addClass(EL.dropdownErrorClass);
97
+ }
98
+
99
+ $card.replaceWith($newCard);
100
+ $newCard.find(EL.cardCheckbox).prop('checked', Boolean(state.checked));
101
+ quantity.resetCardQuantity($newCard);
102
+ reinitCard($newCard);
103
+
104
+ return $newCard;
105
+ }
106
+
107
+ function replaceCardWithBaseProduct($dropdown, options = {}) {
108
+ const $card = getDropdownCard($dropdown);
109
+ const recommendationIndex = model.getRecommendationIndex($card);
110
+ const recommendation = model.getRecommendations()[recommendationIndex];
111
+
112
+ if (!recommendation || !recommendation.baseProduct) {
113
+ return null;
114
+ }
115
+
116
+ return replaceCard(
117
+ $card,
118
+ recommendationIndex,
119
+ recommendation.baseProduct,
120
+ {
121
+ dropdownError: options.dropdownError || false,
122
+ checked: false,
123
+ },
124
+ {
125
+ checked: false,
126
+ dropdownError: options.dropdownError || false,
127
+ }
128
+ );
129
+ }
130
+
131
+ function replaceCardWithVariant($dropdown, selectedValue) {
132
+ const $card = getDropdownCard($dropdown);
133
+ const recommendationIndex = model.getRecommendationIndex($card);
134
+ const recommendation = model.getRecommendations()[recommendationIndex];
135
+
136
+ if (!recommendation) {
137
+ return null;
138
+ }
139
+
140
+ const variantProduct = model.findVariantProduct(recommendation, selectedValue);
141
+
142
+ if (!variantProduct) {
143
+ return null;
144
+ }
145
+
146
+ return replaceCard(
147
+ $card,
148
+ recommendationIndex,
149
+ {
150
+ ...variantProduct,
151
+ variantOptions: recommendation.baseProduct.variantOptions,
152
+ },
153
+ {
154
+ fallbackProduct: recommendation.baseProduct,
155
+ checked: true,
156
+ selectedDropdownValue: selectedValue,
157
+ },
158
+ {
159
+ checked: true,
160
+ selectedValue,
161
+ }
162
+ );
163
+ }
164
+
165
+ function handleDropdownSelect($dropdown, selectedValue) {
166
+ const $card = getDropdownCard($dropdown);
167
+ const recommendationIndex = $card.attr(EL.recommendationIndexAttr);
168
+ const currentValue = dropdownCurrent[recommendationIndex];
169
+
170
+ if (`${currentValue}` === `${selectedValue}`) {
171
+ return;
172
+ }
173
+
174
+ dropdownCurrent[recommendationIndex] = selectedValue;
175
+
176
+ const $completeWidget = $dropdown.closest(EL.completeWidget);
177
+ const isPlaceholder = !selectedValue;
178
+
179
+ if (isPlaceholder) {
180
+ setDropdownError($dropdown, true);
181
+ setDropdownCheckboxState($dropdown, false, false);
182
+ replaceCardWithBaseProduct($dropdown, { dropdownError: true });
183
+
184
+ if ($completeWidget.length) {
185
+ calculateTotal($completeWidget);
186
+ }
187
+
188
+ return;
189
+ }
190
+
191
+ setDropdownError($dropdown, false);
192
+ setDropdownCheckboxState($dropdown, true, false);
193
+ replaceCardWithVariant($dropdown, selectedValue);
194
+
195
+ if ($completeWidget.length) {
196
+ calculateTotal($completeWidget);
197
+ }
198
+ }
199
+
200
+ function bindDropdowns() {
201
+ const dropdown = createDropdown({
202
+ root: EL.dropdownRoot,
203
+ toggle: EL.dropdownToggle,
204
+ value: EL.dropdownValue,
205
+ option: EL.dropdownOption,
206
+ openClass: EL.dropdownOpenClass,
207
+ selectedClass: EL.dropdownOptionSelectedClass,
208
+ namespace: 'bloomreachDropdown',
209
+ onSelect($dropdown, $option, selectedValue) {
210
+ handleDropdownSelect($dropdown, selectedValue);
211
+ },
212
+ });
213
+
214
+ dropdown.bind();
215
+ }
216
+
217
+ function bindCardSelection($root) {
218
+ const $firstCard = $root.find(EL.completeCard).first();
219
+
220
+ $firstCard.find(EL.cardCheckbox).prop('checked', true);
221
+ $firstCard.addClass(EL.selectedClass);
222
+
223
+ $root.off('change.bloomreachCardSelection', EL.cardCheckbox);
224
+ $root.on('change.bloomreachCardSelection', EL.cardCheckbox, function () {
225
+ const $checkbox = $(this);
226
+ const $card = $checkbox.closest(EL.completeCard);
227
+ const $dropdown = $card.find(EL.dropdownRoot);
228
+
229
+ if (!$checkbox.prop('checked') && $dropdown.hasClass(EL.dropdownErrorClass)) {
230
+ $card.removeClass(EL.selectedClass);
231
+ return;
232
+ }
233
+
234
+ if (
235
+ $checkbox.prop('checked') &&
236
+ !validateCardDropdown($card, {
237
+ uncheck: true,
238
+ })
239
+ ) {
240
+ $checkbox.prop('checked', false);
241
+ $card.removeClass(EL.selectedClass);
242
+ return;
243
+ }
244
+
245
+ $card.toggleClass(EL.selectedClass, this.checked);
246
+ calculateTotal($root);
247
+ });
248
+ }
249
+
250
+ function bindDropdownValidation($root) {
251
+ $root.off('click.bloomreachDropdownValidation', EL.cardCheckbox);
252
+ $root.on('click.bloomreachDropdownValidation', EL.cardCheckbox, function () {
253
+ const $checkbox = $(this);
254
+ const $card = $checkbox.closest(EL.completeCard);
255
+
256
+ if (
257
+ $checkbox.prop('checked') &&
258
+ !validateCardDropdown($card, {
259
+ uncheck: true,
260
+ })
261
+ ) {
262
+ $checkbox.prop('checked', false);
263
+ $card.removeClass(EL.selectedClass);
264
+ }
265
+ });
266
+ }
267
+
268
+ function bindProductTracking($root) {
269
+ $root.off('click.bloomreachWidgetTracking', EL.titleEl);
270
+ $root.on('click.bloomreachWidgetTracking', EL.titleEl, function () {
271
+ const $card = $(this).closest(EL.completeCard);
272
+ const recommendationIndex = model.getRecommendationIndex($card);
273
+
274
+ if (recommendationIndex === 0) {
275
+ return;
276
+ }
277
+
278
+ const recommendation = model.getRecommendations()[recommendationIndex];
279
+ const baseProduct = recommendation && recommendation.baseProduct;
280
+
281
+ tracking.trackClick(baseProduct && baseProduct.code);
282
+ });
283
+ }
284
+
285
+ function resetBackForwardState() {
286
+ $(EL.completeWidget).each(function () {
287
+ const $widget = $(this);
288
+
289
+ view.resetWidgetState($widget);
290
+ bindCardSelection($widget);
291
+ });
292
+ }
293
+
294
+ const quantity = createCompleteYourProjectQuantity({
295
+ validateCardDropdown,
296
+ calculateTotal,
297
+ });
298
+
299
+ return {
300
+ resetDropdownState,
301
+ bindDropdowns,
302
+ bindCardSelection,
303
+ bindDropdownValidation,
304
+ bindProductTracking,
305
+ initQuantityFields: quantity.initQuantityFields,
306
+ resetBackForwardState,
307
+ };
308
+ }
@@ -0,0 +1,60 @@
1
+ const Handlebars = require('hbsfy/runtime');
2
+
3
+ Handlebars.registerPartial('checkbox', require('../../../../elements/checkbox.hbs'));
4
+ Handlebars.registerPartial('loader', require('../../../../elements/loader.hbs'));
5
+ Handlebars.registerPartial('button', require('../../../../components/base/button.hbs'));
6
+ Handlebars.registerPartial(
7
+ 'bloomreach/complete-card-dropdown',
8
+ require('../../../../components/bloomreach/complete-card-dropdown.hbs')
9
+ );
10
+ Handlebars.registerPartial('notifications', require('../../../../elements/notifications.hbs'));
11
+ Handlebars.registerPartial('reviews-rating', require('../../../../components/reviews-rating.hbs'));
12
+
13
+ export const COMPLETE_YOUR_PROJECT_EVENTS = {
14
+ calculateTotal: 'calculateProductBundleTotal',
15
+ addToCart: 'bulkAddToCart',
16
+ };
17
+
18
+ export const COMPLETE_YOUR_PROJECT_EL = {
19
+ cardCheckbox: '.complete-card__select input[type="checkbox"]',
20
+ completeCard: '.complete-card',
21
+ completeWidget: '.complete-widget',
22
+ countBtn: '.count-btn',
23
+ countMinusBtn: '.count-btn--minus',
24
+ countStepperInitializedData: 'count-stepper-initialized',
25
+ countStepperRoot: '.count-stepper',
26
+ ctaButton: '.complete-widget__cta .btn',
27
+ summaryPriceValue: '.complete-widget__price-value',
28
+ summarySalePrice: '.complete-widget__sale-price',
29
+ summaryTotal: '.complete-widget__total',
30
+
31
+ dropdownErrorClass: 'complete-card-dropdown--error',
32
+ dropdownOpenClass: 'complete-card-dropdown--open',
33
+ dropdownOption: '[data-complete-card-dropdown-option]',
34
+ dropdownOptionSelectedClass: 'complete-card-dropdown__option--selected',
35
+ dropdownRoot: '[data-complete-card-dropdown]',
36
+ dropdownToggle: '[data-complete-card-dropdown-toggle]',
37
+ dropdownValue: '[data-complete-card-dropdown-value]',
38
+
39
+ optionsEl: '.complete-card__options',
40
+ previousQuantityData: 'previous-quantity',
41
+ quantityInput: '.tbx_quantity',
42
+ quantityReadyData: 'quantity-ready',
43
+
44
+ recommendationIndexAttr: 'data-recommendation-index',
45
+ selectedClass: 'complete-card--selected',
46
+ selectedValueData: 'selected-value',
47
+ titleEl: '.complete-card__title',
48
+
49
+ widgetContainer: '[data-complete-widget]',
50
+ widgetContent: '[data-complete-widget-content]',
51
+ widgetWrapper: '[data-complete-widget-wrapper]',
52
+ };
53
+
54
+ export const COMPLETE_YOUR_PROJECT_TEMPLATES = {
55
+ notification: require('../../../../elements/notifications.hbs'),
56
+ wrapper: require('../../../../components/bloomreach/complete-wrapper.hbs'),
57
+ divider: require('../../../../components/bloomreach/complete-divider.hbs'),
58
+ card: require('../../../../components/bloomreach/complete-card.hbs'),
59
+ summary: require('../../../../components/bloomreach/complete-summary.hbs'),
60
+ };