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.
- package/build/css/pdp-main-before-combine.css +1 -1
- package/build/css/pdp-main-non-critical.css +1 -1
- package/build/css/pdp-main.css +1 -1
- package/build/js/basket.min.js +1 -1
- package/build/js/bloomreach-widget.min.js +1 -1
- package/build/js/bundle.min.js +1 -1
- package/build/js/checkout.min.js +1 -1
- package/build/js/emulation.min.js +360 -3222
- package/build/js/general.bundle.min.js +1 -1
- package/build/js/merged-checkout.min.js +1 -1
- package/build/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +318 -0
- package/build/js/page/bloomreach-widget/bloomreach-widget-core.js +370 -0
- package/build/js/page/bloomreach-widget/bloomreach-widget-tracking.js +16 -13
- package/build/js/page/bloomreach-widget/bloomreach-widget.js +8 -237
- package/build/js/page/bloomreach-widget/complete-your-project/cards.js +308 -0
- package/build/js/page/bloomreach-widget/complete-your-project/config.js +60 -0
- package/build/js/page/bloomreach-widget/complete-your-project/model.js +140 -0
- package/build/js/page/bloomreach-widget/complete-your-project/presenter.js +69 -0
- package/build/js/page/bloomreach-widget/complete-your-project/quantity.js +80 -0
- package/build/js/page/bloomreach-widget/complete-your-project/view.js +179 -0
- package/build/js/page/bloomreach-widget/complete-your-project/widget.js +185 -0
- package/build/js/page/bloomreach-widget/dont-forget-widget.js +15 -0
- package/build/js/page/bloomreach-widget/why-not-add-widget.js +10 -228
- package/build/js/pdp.bundle.min.js +1 -1
- package/build/js/plp.bundle.min.js +1 -1
- package/build/js/project-list.min.js +1 -1
- package/package.json +1 -1
- package/src/components/base/button.hbs +7 -0
- package/src/components/bloomreach/complete-your-project-skeleton.hbs +21 -0
- package/src/components/bloomreach/complete-your-project.hbs +6 -21
- package/src/components/bloomreach/why-not-add-card-skeleton.hbs +2 -2
- package/src/components/bloomreach/why-not-add-card.hbs +79 -60
- package/src/components/bloomreach/why-not-add-content.hbs +3 -3
- package/src/components/bloomreach/why-not-add.hbs +1 -1
- package/src/js/components/general/cart-slider.js +41 -4
- package/src/js/emulation/complete-your-project-loading.js +16 -0
- package/src/js/emulation/custom-slider-emulation.js +21 -8
- package/src/js/emulation/dont-forget-loading.js +36 -0
- package/src/js/emulation/just-added-scenarios-emulation.js +131 -0
- package/src/js/emulation/mini-basket.js +34 -34
- package/src/js/emulation/mock.js +429 -4
- package/src/js/emulation/why-not-add-loading.js +14 -3
- package/src/js/emulation/why-not-add.js +12 -14
- package/src/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +318 -0
- package/src/js/page/bloomreach-widget/bloomreach-widget-core.js +370 -0
- package/src/js/page/bloomreach-widget/bloomreach-widget-tracking.js +16 -13
- package/src/js/page/bloomreach-widget/bloomreach-widget.js +8 -237
- package/src/js/page/bloomreach-widget/complete-your-project/cards.js +308 -0
- package/src/js/page/bloomreach-widget/complete-your-project/config.js +60 -0
- package/src/js/page/bloomreach-widget/complete-your-project/model.js +140 -0
- package/src/js/page/bloomreach-widget/complete-your-project/presenter.js +69 -0
- package/src/js/page/bloomreach-widget/complete-your-project/quantity.js +80 -0
- package/src/js/page/bloomreach-widget/complete-your-project/view.js +179 -0
- package/src/js/page/bloomreach-widget/complete-your-project/widget.js +185 -0
- package/src/js/page/bloomreach-widget/dont-forget-widget.js +15 -0
- package/src/js/page/bloomreach-widget/why-not-add-widget.js +10 -228
- package/src/page_product-details-with-global-search-v2.html +4 -6
- package/src/page_product-details-with-why-not-add-single.html +1 -1
- package/src/scss/components/bloomreach/_bloomreach.scss +1 -0
- package/src/scss/components/bloomreach/_card-shared.scss +24 -0
- package/src/scss/components/bloomreach/_complete-card.scss +1 -9
- package/src/scss/components/bloomreach/_why-not-add-card.scss +137 -10
- package/src/scss/components/bloomreach/_why-not-add.scss +31 -2
- package/build/js/page/bloomreach-widget/complete-your-project-widget.js +0 -1100
- 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,
|
|
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(
|
|
23
|
+
const elements = Array.isArray(target) ? target : [target];
|
|
24
24
|
|
|
25
25
|
state.viewObserver = new IntersectionObserver(function (entries) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
) {
|
|
31
|
-
|
|
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
|
-
|
|
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(
|
|
76
|
-
observeView(state,
|
|
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
|
|
4
|
-
import
|
|
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:
|
|
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
|
+
};
|