PageSourceSearch

https://www.somfy.es/ecommerce/js/addOnsEcommerce.js?1790170684940

js somfy.es collected 2026-09-29 15:28:28 UTC 112,336 bytes, 2,538 lines download raw bytes

1var startTime = new Date().getTime();
2function onLoadEventHandler(labelEvent) {
3	var latency = new Date().getTime() - startTime;
4	//console.log('Latency ' + labelEvent + ' = ' + latency + 'ms');
5}
6var intervalTcPlp;
7
8$(document).ready(function () {
9	onLoadEventHandler("doc ready global");
10	// use localstorage to quicker display of cart badge
11	if (localStorage && localStorage.getItem("sfyCartItems") > 0) {
12		setCartItems(localStorage.getItem("sfyCartItems"));
13		onLoadEventHandler("cart items set");
14	}
15
16	initSelectors();
17	/*if(jQuery(".product-main-info .ref-product").length > 0) {
18		var sku = jQuery(".product-main-info .ref-product").data("reference");
19		getPrice(sku);
20	}*/
21
22	//open customize bundle panel if hash #customize in url
23	if (jQuery(".product-main-info").length > 0 && window.location.hash == '#customize' && $(globalOptions.primarySelector + '[aria-controls=aside-panel-product]').length) {
24		$(globalOptions.primarySelector + '[aria-controls=aside-panel-product]').click();
25	};
26
27	loadPricesForVisibleProducts();
28	displayWishlistIconsThumbnails();
29
30	if ($(globalOptions.qtyBundleFieldSelector).length) {
31		$('#product-qty').change(function () {
32			if (isV6) {
33				$(globalOptions.qtyBundleFieldSelector).val($(this).val()).change();
34			} else {
35				$(globalOptions.qtyBundleFieldSelector).val($(this).val());
36				$(globalOptions.qtyBundleFieldSelector).next().attr('title', $(this).val());
37				$(globalOptions.qtyBundleFieldSelector).next().find('.filter-option-inner-inner').text($(this).val());
38			}
39			loadOney();
40		});
41
42		$(globalOptions.qtyBundleFieldSelector).change(function () {
43			if (isV6) {
44				$('#product-qty').val($(this).val()).change();
45			} else {
46				$('#product-qty').val($(this).val());
47				$('#product-qty').next().attr('title', $(this).val());
48				$('#product-qty').next().find('.filter-option-inner-inner').text($(this).val());
49			}
50			loadOney();
51		});
52	} else {
53		$('#product-qty').change(function () {
54			loadOney();
55		});
56	}
57
58	$(globalOptions.productBundleSelector).on("change", onBundleOptionChanged);
59	$(globalOptions.qtyProductBundleSelector).on("change", function () {
60		updatePrice($(this));
61		updateSummary($(this));
62	});
63
64	//update price on click on customize in case some optional options are auto selectionned/checked (attribute is_default in elastic) 
65	$('a[data-target=".product-perso"]').on("click", function () {
66		updatePrice($(globalOptions.productBundleSelector));
67		updateSummary($(globalOptions.productBundleSelector));
68	});
69
70	if ($('[data-add-to-wishlist-on-load="true"]').length) {
71		$('[data-add-to-wishlist-on-load="true"]').click();
72	}
73
74	if ($('.product-main-info .product-fav .btAddToMyWishList').length) {
75		sku = $('.product-main-info .product-fav .btAddToMyWishList').data("product-sku");
76		var ajaxR = { dataType: "json", url: "/eCatalogue/ajax.cfc", method: "GET" };
77		ajaxR.data = { method: "isProductInMyWishList", sitename: pageSitename, language: pageLanguage, sku: sku };
78		ajaxR.success = function (data, status, xhr) {
79			if (data.isProductInMyWishList) {
80				$('.product-main-info .product-fav .btAddToMyWishList').hide();
81				$('.product-main-info .product-fav .btRemoveFromMyWishList').show();
82			} else {
83				$('.product-main-info .product-fav .btRemoveFromMyWishList').hide();
84				$('.product-main-info .product-fav .btAddToMyWishList').show();
85			}
86		};
87		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
88			console.log(jqXHR);
89			console.log(textStatus);
90			console.log(errorThrown);
91		};
92		jQuery.ajax(ajaxR);
93	}
94
95	$(".header-message > button").click(function() { //to hide message added/removed to wishlist when clicking on the cross
96		$(this).parent().hide();
97	})
98
99	initReviews();
100});
101
102var userCartId = 0;
103
104var userCartError = '';
105var cartItems = new Array();
106getCartId();
107
108var isV6 = false;
109var isPlp = false;
110var globalOptions = {};
111var productTags = {};
112var stockClass = {};
113
114function initSelectors() {
115	isV6 = (jQuery("#somfy.-v6").length);
116	isPlp = $(".plp-products").length > 0;
117
118	globalOptions = {
119		productBundleSelector: 'input.bundle.option, select.bundle.option, textarea.bundle.option',
120		qtyProductBundleSelector: 'select.qty',
121		qtyBundleFieldSelector: '#product-qty-bundle',
122		priceSelector: (isV6 ? '.product-item' : '.product-new__item__reference'),
123		pricePdpSelector: (isV6 ? '.product-main-info .product-item' : '.product-main-info .product-new__item__reference'),
124		pricePlpSelector: (isV6 ? '.product .product-item' : '.product-new__item .product-new__item__reference'),
125		plpBlocSelector: (isV6 ? '.product' : '.product-new__item'),
126		primarySelector: (isV6 ? '.-primary' : '.primary'),
127		stickyNavSelector: (isV6 ? '.pdp-nav' : '.subnav_entries_buy'),
128		stickyBarMobile: ('.sticky-bar-mobile'),
129		pdpTagsSelector: (isV6 ? '.product-tags' : '.product__item__tags'),
130		productTagsSelector: (isV6 ? '.product-tags' : '.product-new__item__tags'),
131		plpPriceWrapperSelector: (isV6 ? '.product-price-wrapper' : '.product-new__item__price'),
132		stockSelector: (isV6 ? 'p.status' : 'div.product-new__item__stock'),
133		priceStartingFromSelector: (isV6 ? '.product-price-start' : '.product-new__item__start-from'),
134		bundleSummaryAdditionalClasses: (isV6 ? 'product-desc t-14 wysiwyg' : ''),
135		btnAddToCartBundleAsidePanelSelector: (isV6 ? '.perso-footer .-primary' : '.perso-footer .btnClassic')
136		/* ,priceBoxSelector:'.price-box' */
137	};
138	productTags = {
139		promoPdpSelector: (isV6 ? 'li.tag.promo' : 'li.black'),
140		promoPlpSelector: (isV6 ? 'li.tag.promo' : 'li.promo'),
141		promoPdpClass: (isV6 ? 'tag promo -pink' : 'black'),
142		promoPlpClass: (isV6 ? 'tag promo -pink' : 'promo')
143	};
144	stockClass = {
145		instock: (isV6 ? '-available' : 'stock'),
146		outofstock: (isV6 ? '-unavailable' : 'no-stock'),
147		stockwarning: (isV6 ? '-pending' : '')
148	};
149}
150
151function loadPricesForVisibleProducts(ignoreMainProduct = false, onlySuggestedProducts = false, onlyNostoProducts = false) {
152	var localPSelector = globalOptions.priceSelector;
153	
154	if(isV6 && onlySuggestedProducts) {
155		localPSelector = '.header-search-products .product-item'
156	}
157	if(isV6 && onlyNostoProducts) {
158		localPSelector = '.nosto_element .product-item'
159	}
160
161	if (jQuery(globalOptions.priceSelector).length > 0) {
162		if (useElasticPriceLoading) {
163			var skus = jQuery(localPSelector).map(function () {
164				return jQuery(this).data('m-product-id');
165			}).get();
166		}
167		else {
168			var skus = jQuery(localPSelector).map(function () {
169				return jQuery(this).data('reference');
170			}).get();
171		}
172
173		var references = jQuery(localPSelector).map(function () {
174				return jQuery(this).data('reference');
175			}).get();
176		console.log("references:", references);
177		skus = [...new Set(skus)]; //remove duplicates
178		references = [...new Set(references)]; //remove duplicates
179
180		//console.log("skus:", skus);
181
182		if (ignoreMainProduct) {
183			if (useElasticPriceLoading) {
184				refMainProduct = $(".product-main-info " + localPSelector).attr("data-m-product-id");
185			} else {
186				refMainProduct = $(".product-main-info " + localPSelector).attr("data-reference");
187			}
188
189			if (typeof refMainProduct !== "undefined") {
190				const indexMainProduct = skus.indexOf(parseInt(refMainProduct));
191				if (indexMainProduct > -1) {
192					skus.splice(indexMainProduct, 1);
193				}
194			}
195		}
196
197		fetchStockId().then(function(stockId) {
198			console.log("Stock ID:", stockId); // 2 or 0
199			getPrices(skus.toString(), localPSelector, stockId);
200			getStocks(references.toString(), localPSelector, stockId);
201		}).catch(function(err) {
202			console.error("Error fetching stockId:", err);
203		});
204		
205	}
206}
207
208function displayWishlistIconsThumbnails() {
209	arrayProductsInWishList = JSON.parse(localStorage.getItem('arrayWishList'));	
210
211	if(arrayProductsInWishList) {
212		var localPSelector = globalOptions.priceSelector;
213	
214		/* if(onlySuggestedProducts) {
215			localPSelector = '.header-search-products .product-item'
216		} */
217	
218		if (jQuery(globalOptions.priceSelector).length > 0) {
219			if (useElasticPriceLoading) {
220				var skus = jQuery(localPSelector).map(function () {
221					return jQuery(this).data('reference');
222				}).get();
223	
224				skus = [...new Set(skus)]; //remove duplicates
225			}
226		}
227	
228		//ignore main product
229		/*refMainProduct = $(".product-main-info " + localPSelector).attr("data-m-product-id");
230		if (typeof refMainProduct !== "undefined") {
231			const indexMainProduct = skus.indexOf(parseInt(refMainProduct));
232			if (indexMainProduct > -1) {
233				skus.splice(indexMainProduct, 1);
234			}
235		}*/
236
237		if(typeof skus !== "undefined" && skus.length) {
238			for(sku of skus) {
239				if(arrayProductsInWishList.length && arrayProductsInWishList.indexOf(sku.toString()) >= 0) {
240					$(".btRemoveFromMyWishList[data-product-sku="+sku+"]").show();
241				} else {
242					$(".btAddToMyWishList[data-product-sku="+sku+"]").show();
243				}
244			}
245		}
246	} else {
247		$(".btAddToMyWishList").each(function(){
248			if(!$(this).parent().hasClass('product-fav')) { //si ce n'est pas un bouton fav de la pdp
249				$(this).hide();
250			} 
251		});
252		$(".btRemoveFromMyWishList").each(function(){
253			if(!$(this).parent().hasClass('product-fav')) { //si ce n'est pas un bouton fav de la pdp
254				$(this).hide();
255			} 
256		})
257	}
258}
259
260function bindNostoEvents(nostoEl) {
261	$('#' +nostoEl+ ' .tc_event_product').on('click', function (e) {
262		var mProductId = $(this).find(".product-item").data("m-product-id");
263		//console.log("bindNostoEvents >>");
264		//console.log(mProductId);
265		//console.log(nostoEl);
266		/*nostojs(function(api) {
267			var request = api.createRecommendationRequest()
268			.setProducts([{product_id: mProductId}], nostoEl)
269			.load();
270		});*/
271
272		// add event tagcommander
273		try {
274			console.log("click on nosto bloc");
275			console.log($(this));
276			tc_product_event_click($(this));
277			//tc_product_event_click($('.product-title', this));
278		} catch (error) {
279			console.log(error);
280		}
281	});
282
283
284	$('#' +nostoEl+ ' .product .btn.-primary').on('click', function (e) {
285		if($(this).data("action") == 'addto_cart') {
286			var mProductId = $(this).data("m-product-id");
287			console.log(mProductId);
288			nostojs(function(api) {
289				api.recommendedProductAddedToCart(mProductId, nostoEl);
290			});
291		}
292	});
293}
294
295function setCartItems(itemsQty) {
296	jQuery(".cart-items").text(itemsQty);
297	if (itemsQty > 0) {
298		jQuery(".cart-items").removeClass("d-none");
299		jQuery(".cart-show span").text(jQuery(".cart-show").data("cart-label"));
300		if (typeof jQuery(".cart-show").attr('data-target') === 'undefined' || jQuery(".cart-show").attr('data-target') === false) {
301			jQuery(".cart-show").attr({
302				"data-target": ".basket",
303				"aria-controls": "aside-panel",
304				"aria-expanded": "false"
305			});
306			try { somfy.instantiateBlocIfNecessary(somfy.els.$asidePanel, AsidePanel); } catch (err) { }
307		}
308		jQuery("a.cart_mobile").attr("href", jQuery("a.cart_mobile").data("checkout-link"));
309	}
310	else {
311		jQuery(".cart-items").addClass("d-none");
312		jQuery(".cart-show span").text(jQuery(".cart-show").data("emptyCart-label"));
313		if (jQuery(".cart-show").attr('data-target') == '.basket') {
314			jQuery(".cart-show").removeAttr('data-target aria-controls aria-expanded');
315			jQuery('.cart-show').unbind('click');
316		}
317		jQuery("a.cart_mobile").attr("href", jQuery("a.cart_mobile").data("shop-link"));
318	}
319}
320
321/*
322function updateTotalCartInModal(cartData) {
323	if (typeof cartData.total !== 'undefined' && jQuery(".addToCartLayerModal .product-price strong").length > 0) {
324		var selectElement = jQuery("#product-qty-layerModal");
325		var currentItemId = selectElement.attr('data-itemId');
326		var priceToDisplay = cartData.total;
327		var qtyToDisplay = cartData.items_qty;
328
329		//in case there is more than 1 items in the cart
330		if (typeof cartData.items_count !== 'undefined' && cartData.items_count > 1 && typeof cartData.items !== 'undefined' && currentItemId) {
331			// Find the item that matches the data-itemId
332			var matchedItem = null;
333			for (var i = 0; i < cartData.items.length; i++) {
334				if (cartData.items[i].item_id == currentItemId) {
335					matchedItem = cartData.items[i];
336					break;
337				}
338			}
339
340			// If we found the matching item, use its specific price and qty
341			if (matchedItem !== null) {
342				priceToDisplay = matchedItem.row_total; // or matchedItem.price * matchedItem.qty
343				qtyToDisplay = matchedItem.qty;
344			}
345		}
346
347		var formattedPrice = getFormattedPrice(priceToDisplay);
348		if(formattedPrice != '' && priceToDisplay != 0) {
349			jQuery(".addToCartLayerModal .product-price strong").html(formattedPrice);
350			if (typeof qtyToDisplay !== 'undefined' && qtyToDisplay > 0) {
351				//update the quantity select in the modal to
352				var dropdownButton = jQuery("#product-qty-layerModal-current");
353				if (dropdownButton.length) {
354					dropdownButton.text(qtyToDisplay).attr('data-index', qtyToDisplay);
355				}
356			}
357		}
358		if (userCartError !== 'undefined' && userCartError != '') {
359			jQuery("#addToCartLayerModalLabelError .message").html( userCartError );
360			jQuery("#addToCartLayerModalLabelSuccess").hide();
361			jQuery("#addToCartLayerModalLabelError").show();
362		} else {
363			jQuery("#addToCartLayerModalLabelSuccess").show();
364			jQuery("#addToCartLayerModalLabelError").hide();
365		}
366		jQuery(".content-loader").hide();
367	}
368}
369*/
370
371function loadCart() {
372	onLoadEventHandler("start function loadCart");
373	var varnishBlocker = Math.random();
374	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" };
375	var cartId = userCartId; //jQuery("#cartId").val();
376	ajaxR.data = { method: "getCart", sitename: pageSitename, cartId: cartId, language: pageLanguage };
377	if (isV6) ajaxR.data.version = 'v6';
378	ajaxR.success = function (data, status, xhr) {
379		onLoadEventHandler("success ajax loadCart");
380		$(document).ready(function () {
381			setCartItems(data.items_qty);
382			// add localstorage for faster display
383			if (localStorage) {
384				if (data.items_qty > 0) {
385					localStorage.setItem("sfyCartItems", data.items_qty);
386				} else {
387					localStorage.removeItem('sfyCartItems');
388				}
389			}
390			//hook to upate total in add to cart modal
391			//updateTotalCartInModal(data);
392			jQuery(".basket-footer .basket-total span").text(data.total + " " + data.currency.quote_currency_code);
393			var cartHTML = data.renderedItems;
394			cartItems = data.items;
395			jQuery(".basket-body").html(cartHTML);
396			jQuery(".basket .panel-error").html('');
397			if (userCartError != '') { jQuery(".basket .panel-error").html("<p>" + userCartError + "</p>") }
398			userCartError = '';
399			jQuery(".cart-loader,.basket .content-loader").hide();
400
401			// nosto tagging
402			if (data.items_qty > 0 && ("nostojs" in window)) {
403				//console.log("nosto cart tagging");
404				nostojs(function (api) {
405					api.resendCartTagging();
406					api.loadRecommendations();
407					nostoRecoLoading = true;
408				});
409			}
410		});
411	};
412	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
413		console.log(jqXHR);
414		console.log(textStatus);
415		console.log(errorThrown);
416	};
417	jQuery.ajax(ajaxR);
418}
419
420function getProductHtml(productItem, currencyCode) {
421	var html = '<li><div class="row">';
422	html += '<div class="col-2">' + productItem.qty + ' </div>';
423	html += '<div class="col-6">' + productItem.name + ' (' + productItem.sku + ')</div>';
424	html += '<div class="col-4">' + productItem.price + '&nbsp;' + currencyCode + '</div>';
425	html += '</div></li>';
426	return html;
427}
428
429
430function addToCart(sku, price) {
431	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
432	var cartId = userCartId; //jQuery("#cartId").val();
433	var qty = jQuery("#product-qty").val();
434	if (!qty) { qty = 1; }
435
436	jQuery("#addToCartLayerModal .modal-body .product .product-visual img").attr("src", jQuery(".product-main-info img.img-product").attr("src"));
437	jQuery("#addToCartLayerModal .modal-body .product .product-title").text(jQuery(".product-main-info .product-title").text());
438	//jQuery("#addToCartLayerModal .modal-body .product .product-ref").text(jQuery(".product-main-info .ref-product").text()); // productDetail.ecommerce.ref
439	jQuery("#addToCartLayerModal .modal-body .product .product-qty span").text(qty) // ecommerce.cart.quantity
440	jQuery('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').remove();
441	jQuery('#addToCartLayerModal .modal-body .content-loader').show();
442	jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
443	jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelWaiting").show();
444
445	showAddToCartLayer();
446
447	ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: jQuery(".product-main-info .product_price").attr('data-numeric-price') * qty };
448	ajaxR.success = function (data, status, xhr) {
449		if (isV6) {
450			jQuery("#addToCartLayerModal .modal-body .product .product-price").html("<strong>" + data.formattedPrice + "</strong>");
451		} else {
452			jQuery("#addToCartLayerModal .modal-body .product .product-price").html(data.formattedPrice);
453		}
454	};
455	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
456		console.log(jqXHR);
457		console.log(textStatus);
458		console.log(errorThrown);
459	};
460	jQuery.ajax(ajaxR);
461
462	ajaxR.data = { method: "addToCart", sitename: pageSitename, cartId: cartId, quantity: qty, sku: sku, items: JSON.stringify(cartItems) };
463	ajaxR.success = function (data, status, xhr) {
464		jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
465
466		if (data.cart_id) {
467			loadCart();
468		}
469		if (data.message == undefined) {
470			// Populate quantity select dynamically based on cart item data
471			populateModalQuantitySelect(data.item_id, data.qty);
472
473			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelSuccess").show();
474		} else {
475			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelError .message").html(data.message);
476			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelError").show();
477		}
478		jQuery('#addToCartLayerModal .modal-body .content-loader').hide();
479	};
480	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
481		console.log(jqXHR);
482		console.log(textStatus);
483		console.log(errorThrown);
484		jQuery('#addToCartLayerModal .modal-body .content-loader').hide();
485		jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
486		jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelSystemError").show();
487	};
488	jQuery.ajax(ajaxR);
489}
490
491function addToCartThumbnail(sku, price, name, picture, quantity) {
492	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
493	var cartId = userCartId; //jQuery("#cartId").val();
494	var qty = 1;
495	if (quantity !== undefined) {
496		qty = quantity;
497	}
498
499	jQuery("#addToCartLayerModal .modal-body .product .product-visual img").attr("src", picture);
500	jQuery("#addToCartLayerModal .modal-body .product .product-title").text(name);
501	//jQuery("#addToCartLayerModal .modal-body .product .product-ref").text(jQuery(".product-main-info .ref-product").text()); // productDetail.ecommerce.ref
502	jQuery("#addToCartLayerModal .modal-body .product .product-qty span").text(qty) // ecommerce.cart.quantity
503	jQuery('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').remove();
504	var elmtsPrice = jQuery(globalOptions.priceSelector + "[data-reference='" + sku + "'] .price");
505	if (elmtsPrice.length > 1) {
506		_priceToDisplay = jQuery(elmtsPrice.get(0)).text();
507	} else {
508		_priceToDisplay = elmtsPrice.text();
509	}
510	if (_priceToDisplay == '') { _priceToDisplay = price }
511	if (isV6) {
512		jQuery("#addToCartLayerModal .modal-body .product .product-price").html("<strong>" + _priceToDisplay + "</strong>");
513	} else {
514		jQuery("#addToCartLayerModal .modal-body .product .product-price").text(_priceToDisplay);
515	}
516	jQuery('#addToCartLayerModal .modal-body .content-loader').show();
517	jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
518	jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelWaiting").show();
519
520	showAddToCartLayer();
521	ajaxR.data = { method: "addToCart", sitename: pageSitename, cartId: cartId, quantity: qty, sku: sku, items: JSON.stringify(cartItems) };
522	ajaxR.success = function (data, status, xhr) {
523		
524		jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
525		if (data.cart_id) {
526			loadCart();
527		}
528		if (data.message == undefined) {
529			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelSuccess").show();
530		} else {
531			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelError").html(data.message).show();
532		}
533		jQuery('#addToCartLayerModal .modal-body .content-loader').hide();
534	};
535	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
536		console.log(jqXHR);
537		console.log(textStatus);
538		console.log(errorThrown);
539	};
540	jQuery.ajax(ajaxR);
541}
542
543function addBundleToCart(sku, price) {
544	var bundleOptions = getBundleOptions(sku);
545	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
546	var cartId = userCartId;
547
548	updateSummary($(".bundle-options .perso-body"));
549
550	if ($(globalOptions.btnAddToCartBundleAsidePanelSelector).hasClass("disabled")) {
551		return;
552	}
553
554	$('#aside-panel-product').find('.close').click();
555	jQuery("#addToCartLayerModal .modal-body .product .product-visual img").attr("src", jQuery(".product-main-info img.img-product").attr("src"));
556	jQuery("#addToCartLayerModal .modal-body .product .product-title").text(jQuery(".product-main-info .product-title").text());
557	jQuery("#addToCartLayerModal .modal-body .product .product-qty span").text($(globalOptions.qtyBundleFieldSelector).val()) // ecommerce.cart.quantity
558	//jQuery("#addToCartLayerModal .modal-body .product .product-price").html($("#aside-panel-product .perso-total span.price").html());
559	$('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').remove();
560	$('#addToCartLayerModal .modal-body .product .product-infos').append('<div class="bundle-summary ' + globalOptions.bundleSummaryAdditionalClasses + '"></div>');
561	if (typeof jQuery(".product-main-info .product-actions " + globalOptions.primarySelector).attr('data-bundle-options') !== 'undefined' && jQuery(".product-main-info .product-actions " + globalOptions.primarySelector).attr('data-bundle-options') !== false
562		&& typeof jQuery(".product-main-info .product-actions " + globalOptions.primarySelector).attr('data-extended-bundle-options') !== 'undefined' && jQuery(".product-main-info .product-actions " + globalOptions.primarySelector).attr('data-extended-bundle-options') !== false) {
563		//for closed bundle construct summary with attributes on addtocart button
564		$('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').html(getClosedBundleSummary(jQuery(".product-main-info .product-actions " + globalOptions.primarySelector).data('bundle-options'), jQuery(".product-main-info .product-actions " + globalOptions.primarySelector).data('extended-bundle-options')));
565	} else {
566		//for open bundle construct summary with .bundleSummary updated when changing a bundle option
567		$('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').html($('.bundleSummary').html());
568	}
569	jQuery('#addToCartLayerModal .modal-body .content-loader').show();
570	jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
571	jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelWaiting").show();
572
573	ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: jQuery(".product-main-info .product_price").attr('data-numeric-price') * $(globalOptions.qtyBundleFieldSelector).val() };
574	ajaxR.success = function (data, status, xhr) {
575		jQuery("#addToCartLayerModal .modal-body .product .product-price .price").html(data.formattedPrice);
576	};
577	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
578		console.log(jqXHR);
579		console.log(textStatus);
580		console.log(errorThrown);
581	};
582	jQuery.ajax(ajaxR);
583
584	if (parseInt(jQuery(".product-main-info .product_price").attr('data-numeric-price')) < parseInt(jQuery(".product-main-info .product_price").attr('data-original-price'))) {
585		ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: jQuery(".product-main-info .product_price").attr('data-original-price') * $(globalOptions.qtyBundleFieldSelector).val() };
586		ajaxR.success = function (data, status, xhr) {
587			jQuery("#addToCartLayerModal .modal-body .product .product-price .product-new__item__action del").html(data.formattedPrice);
588		};
589		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
590			console.log(jqXHR);
591			console.log(textStatus);
592			console.log(errorThrown);
593		};
594		jQuery.ajax(ajaxR);
595	}
596
597	showAddToCartLayer();
598
599	ajaxR.data = { method: "addBundleToCart", sitename: pageSitename, cartId: cartId, quantity: $(globalOptions.qtyBundleFieldSelector).val(), sku: sku, bundleOptions: bundleOptions };
600	ajaxR.success = function (data, status, xhr) {
601		
602		jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
603		if (data.cart_id) {
604			loadCart();
605		}
606		if (data.message == undefined) {
607			//populateModalQuantitySelect(data.item_id);
608			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelSuccess").show();
609		} else {
610			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelError").html(data.message).show();
611		}
612		//console.log(data);
613		jQuery('#addToCartLayerModal .modal-body .content-loader').hide();
614	};
615	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
616		console.log(jqXHR);
617		console.log(textStatus);
618		console.log(errorThrown);
619		jQuery('#addToCartLayerModal .modal-body .content-loader').hide();
620		jQuery("#addToCartLayerModal .modal-header .modal-title").hide();
621		jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelSystemError").show();
622	};
623	jQuery.ajax(ajaxR);
624}
625
626function addBundleToCartThumbnail(sku, price, name, picture, mId, quantity) {
627	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
628	var cartId = userCartId;
629	var qty = 1;
630	if (quantity !== undefined) {
631		qty = quantity;
632	}
633
634	jQuery("#addToCartLayerModal .modal-body .product .product-visual img").attr("src", picture);
635	jQuery("#addToCartLayerModal .modal-body .product .product-title").text(name);
636	jQuery("#addToCartLayerModal .modal-body .product .product-qty span").text(qty) // ecommerce.cart.quantity
637	var elmtsPrice = jQuery(globalOptions.priceSelector + "[data-m-product-id=" + mId + "] .price");
638	if (elmtsPrice.length > 1) {
639		_priceToDisplay = jQuery(elmtsPrice.get(0)).text();
640	} else {
641		_priceToDisplay = elmtsPrice.text();
642	}
643	
644	if (isV6) {
645		jQuery("#addToCartLayerModal .modal-body .product .product-price").html("<strong class=\"price\">" + _priceToDisplay + "</strong>");
646	} else {
647		jQuery("#addToCartLayerModal .modal-body .product .product-price").html("<span class=\"price\">" + _priceToDisplay + "</span>");
648	}
649
650	if (jQuery(globalOptions.priceSelector + "[data-m-product-id=" + mId + "] .product-new__item__action del").length) {
651		var elmtsPriceDiscount = jQuery(globalOptions.priceSelector + "[data-m-product-id=" + mId + "] .product-new__item__action del");
652		if (elmtsPriceDiscount.length > 1) {
653			_priceDiscountToDisplay = jQuery(elmtsPriceDiscount.get(0)).text();
654		} else {
655			_priceDiscountToDisplay = elmtsPriceDiscount.text();
656		}
657		jQuery("#addToCartLayerModal .modal-body .product .product-price").append("<div class=\"product-new__item__action\"><del>" + _priceDiscountToDisplay + "</del></div>");
658	}
659
660	if (isV6) {
661		var bundleOptions = jQuery(".btn.-primary[data-m-product-id=" + mId + "]").data("bundle-options");
662		var extendedBundleOptions = jQuery(".btn.-primary[data-m-product-id=" + mId + "]").data("extended-bundle-options");
663	} else {
664		var bundleOptions = jQuery("a.btnCompact[data-m-product-id=" + mId + "]").data("bundle-options");
665		var extendedBundleOptions = jQuery("a.btnCompact[data-m-product-id=" + mId + "]").data("extended-bundle-options");
666	}
667
668	$('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').remove();
669	$('#addToCartLayerModal .modal-body .product .product-infos').append('<div class="bundle-summary ' + globalOptions.bundleSummaryAdditionalClasses + '"></div>');
670	$('#addToCartLayerModal .modal-body .product .product-infos .bundle-summary').html(getClosedBundleSummary(bundleOptions, extendedBundleOptions));
671	showAddToCartLayer();
672
673	ajaxR.data = { method: "addBundleToCart", sitename: pageSitename, cartId: cartId, quantity: qty, sku: sku, bundleOptions: getClosedBundleOptions(bundleOptions) };
674	ajaxR.success = function (data, status, xhr) {
675		if (data.cart_id) {
676			loadCart();
677
678			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelWaiting").hide();
679			jQuery("#addToCartLayerModal .modal-header .modal-title#addToCartLayerModalLabelSuccess").show();
680		}
681		//console.log(data);
682	};
683	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
684		console.log(jqXHR);
685		console.log(textStatus);
686		console.log(errorThrown);
687	};
688	jQuery.ajax(ajaxR);
689}
690
691
692/**
693 * Populate the modal quantity select dropdown with options based on cart item data
694 * @param {number} itemId - The cart item ID
695 *  @param {number} maxQty - The maximum quantity in cart
696 */
697function populateModalQuantitySelect(itemId, maxQty) {
698	if (!itemId || !maxQty) {
699		return;
700	}
701
702	var selectElement = jQuery("#product-qty-layerModal");
703	selectElement.empty(); // Clear existing options
704
705	// Generate options from 1 to maxQty
706	for (var i = 1; i <= maxQty; i++) {
707		selectElement.append('<option value="' + i + '">' + i + '</option>');
708	}
709
710	// Set current quantity as selected
711	selectElement.val(maxQty);
712
713	// Update the onchange handler with actual item_id
714	selectElement.attr('onchange', 'javascript:jQuery(".content-loader").show();updateQtyFromCart(' + itemId + ', $(\'#product-qty-layerModal\').val())');
715
716}
717
718function removeFromCart(itemId) {
719	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
720	var cartId = userCartId; //jQuery("#cartId").val();
721	jQuery(".basket .content-loader").show();
722	ajaxR.data = { method: "removeFromCart", sitename: pageSitename, cartId: cartId, itemId: itemId }; //add , items : JSON.stringify(cartItems) ?
723	ajaxR.success = function (data, status, xhr) {
724		if (data) {
725			loadCart();
726		}
727		//console.log(data);
728	};
729	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
730		console.log(jqXHR);
731		console.log(textStatus);
732		console.log(errorThrown);
733	};
734	jQuery.ajax(ajaxR);
735}
736
737function updateQtyFromCart(itemId, quantity) {
738	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
739	var cartId = userCartId; //jQuery("#cartId").val();
740	jQuery(".basket .content-loader").show();
741	ajaxR.data = { method: "updateQtyFromCart", sitename: pageSitename, cartId: cartId, itemId: itemId, quantity: quantity }; //add , items : JSON.stringify(cartItems) ?
742	ajaxR.success = function (data, status, xhr) {
743		if (data) {
744			loadCart();
745		}
746		if (data.message != undefined) {
747			userCartError = data.message;
748		}
749		//console.log(data);
750	};
751	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
752		console.log(jqXHR);
753		console.log(textStatus);
754		console.log(errorThrown);
755	};
756	jQuery.ajax(ajaxR);
757}
758
759function getCartId() {
760	onLoadEventHandler("start function getCartId");
761
762	// todo load url from config and depending on Magento version
763	var varnishBlocker = Math.random();
764	//var host =  ecommerceHost;
765	var endpoint = quoteIdEndpoint;
766	if (!endpoint) {
767		console.log("global variable ecommerceHost is not defined !")
768	}
769	var ajaxR = {
770		dataType: "json", url: endpoint + "?_=" + varnishBlocker,
771		method: "GET",
772		xhrFields: { withCredentials: true },
773		crossDomain: true
774	}; //
775
776	if (quoteIdToken && quoteIdToken != '') {
777		/*ajaxR.beforeSend = function (xhr) {
778			xhr.setRequestHeader('Authorization', 'Bearer '+quoteIdToken);
779		};*/
780		ajaxR.headers = { 'Authorization': 'Bearer ' + quoteIdToken };
781	}
782	ajaxR.success = function (data, status, xhr) {
783		onLoadEventHandler("success ajax getCartId");
784		if (data.success == true) {
785			userCartId = data.quote_id;
786			//console.log(userCartId);
787			loadCart();
788		}
789		else if (Number.isInteger(data)) {
790			// m2 return only the cartId
791			userCartId = data;
792			//console.log(userCartId);
793			loadCart();
794		}
795		//console.log(data);
796	};
797	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
798		console.log(jqXHR);
799		console.log(textStatus);
800		console.log(errorThrown);
801	};
802	jQuery.ajax(ajaxR);
803}
804
805function showAddToCartLayer() {
806	jQuery(".modal-cross-selling.nosto_element").addClass("d-none"); // avoid flicker on reloading
807	if(jQuery(".modal-cross-selling.nosto_element").next(".nosto-placeholder").length)
808		jQuery(".modal-cross-selling.nosto_element").next(".nosto-placeholder").fadeIn(); // display loader again
809	if (isV6) {
810		document.getElementById('addToCartLayerModal')?.__component?.open();
811	} else {
812		$("#addToCartLayerModal").modal("show");
813	}
814}
815
816/* function getPrice(sku) {
817	var varnishBlocker =  Math.random();
818	var ajaxR = {dataType:"json", url:"/eCatalogue/ajax.cfc?_="+varnishBlocker,method:"GET"};
819	ajaxR.data = {method:"getPrice",sitename:pageSitename, sku: sku, language:pageLanguage};
820	if(isV6)  ajaxR.data.version = 'v6';
821	ajaxR.success = function(data, status, xhr) {
822		if(data.displayPrice) {
823			jQuery("div.product_price").html(data.displayPrice);
824			if(!isV6) jQuery('[data-toggle="tooltip"]').tooltip();
825		}
826		console.log(data);
827	};
828	ajaxR.error = function(jqXHR, textStatus, errorThrown){
829		console.log(jqXHR);
830		console.log(textStatus);
831		console.log(errorThrown);
832	};
833	jQuery.ajax(ajaxR);
834}*/
835
836function getPrices(skus, localPricePlpSelector = globalOptions.pricePlpSelector, stockId ) {
837	if (skus == "") return;
838	var varnishBlocker = Math.random();
839	var priceLoaderUrl = (useElasticPriceLoading) ? "/ecommerce/ajax.cfc?_=" : "/eCatalogue/ajax.cfc?_=";
840	var ajaxR = { dataType: "json", url: priceLoaderUrl + varnishBlocker, method: "GET" };
841	ajaxR.data = { method: "getPrices", sitename: pageSitename, skus: skus, language: pageLanguage };
842	if (isV6) ajaxR.data.version = 'v6';
843	ajaxR.success = function (data, status, xhr) {
844		for (const ref in data) {
845			if (data[ref].displayPrice) {
846				setPrice(ref, data, stockId);
847				//to display discount percentage
848				if (typeof data[ref].originalPrice !== "undefined" && data[ref].numericPrice < data[ref].originalPrice && typeof data[ref].strikethrough === 'undefined') {
849					//to not display discount on bundle out of stock
850					if(typeof data[ref].isBundle === "undefined" || data[ref].isBundle == false || (data[ref].isBundle == true && data[ref].hasStock == true)) {
851						discountPercentage = 100 - (data[ref].numericPrice * 100 / data[ref].originalPrice);
852						//to not display discount percentage under 1%
853						if (discountPercentage >= 1) {
854							const refAttr = useElasticPriceLoading ? 'data-m-product-id' : 'data-reference';
855							const priceSelector = `${globalOptions.priceSelector}[${refAttr}='${ref}']`;
856							const pricePdpSelector = `${globalOptions.pricePdpSelector}[${refAttr}='${ref}']`;
857							const pricePlpSelector = `${localPricePlpSelector}[${refAttr}='${ref}']`;
858
859							const $productMainInfoPdp = $(pricePdpSelector).closest('.product-main-info');
860							const $elemTagsPdp = $productMainInfoPdp.find(globalOptions.pdpTagsSelector);
861							const $elemPriceDiscountPercentagePdp = $productMainInfoPdp.find('.product-price-discount-percentage');
862							const $elemsPriceSticky = $('.sticky-bar-mobile, .nav-bar-product').find();
863							const $elemOriginalPricePdp = $productMainInfoPdp.find('.product-original-price');
864							const $elemPricePlp = $(pricePlpSelector).closest(globalOptions.plpBlocSelector);
865							const $elemsPriceDiscountPercentagePdp = $(priceSelector).find('.product-price-discount-percentage');
866							
867							// add class -sales (to put the price in red) if the price is not custom (defined by a message) and the product doesn't have the productsWithNewPriceLabel config
868							if(typeof data[ref].hasNewPrice === "undefined") {
869								jQuery(priceSelector).addClass('-sales'); 
870								jQuery(globalOptions.stickyNavSelector +' '+priceSelector).addClass('-sales');
871								jQuery(globalOptions.stickyBarMobile +' '+priceSelector).addClass('-sales');
872							// else if the price is custom or the product have the productsWithNewPriceLabel config, add the class -newprice to not put the old price in grey
873							} else {
874								if(!jQuery(priceSelector).hasClass('-newprice')) {
875									jQuery(priceSelector).addClass('-newprice');
876								}
877								if(!jQuery(globalOptions.stickyNavSelector + ' ' + priceSelector).hasClass('-newprice')) {
878									jQuery(globalOptions.stickyNavSelector + ' ' + priceSelector).addClass('-newprice');
879								}
880								if(!jQuery(globalOptions.stickyBarMobile + ' ' + priceSelector).hasClass('-newprice')) {
881									jQuery(globalOptions.stickyBarMobile + ' ' + priceSelector).addClass('-newprice');
882								}
883							}
884
885							
886							//add prices percentage and display prices strike through pdp for main product
887							/*if ($elemsPriceDiscountPercentagePdp && $elemsPriceDiscountPercentagePdp.length) {
888								$elemsPriceDiscountPercentagePdp.each(function() {
889									const $elemPriceDiscountPercentagePdp = $(this);
890
891									// add prices percentage (in product-main-info + price sticky header + price sticky bar mobile)
892									$elemPriceDiscountPercentagePdp.text(`-${Math.floor(discountPercentage)}%`);
893									
894									// display prices strike through (in price sticky header + price sticky bar mobile, not in product-main-info because it's not displayed there, but <del> already removed there in setPrice function)
895									const $elemPriceWrapperSticky = $elemPriceDiscountPercentagePdp.parents(".sticky-bar-mobile, .nav-bar-product").find(priceSelector);
896									const $elemPriceStrikeThrough = $elemPriceWrapperSticky.find("del");
897									if ($elemPriceStrikeThrough && $elemPriceStrikeThrough.length) {
898										$elemPriceStrikeThrough.removeClass("d-none");
899									}
900
901									// reorder elements in price sticky header + price sticky bar mobile
902									let $spanPriceWrapper = $elemPriceWrapperSticky.find('span'); 
903									if (!$spanPriceWrapper.length) {
904										$spanPriceWrapper = jQuery('<span></span>');
905										$spanPriceWrapper.insertBefore($elemPriceWrapperSticky.find('strong'));
906										$spanPriceWrapper.append($elemPriceWrapperSticky.find('del'));
907										$spanPriceWrapper.append(" ");
908										$spanPriceWrapper.append($elemPriceWrapperSticky.find('sup'));
909									}
910								});
911							}*/
912
913							// update original price 
914							if(typeof $elemOriginalPricePdp !== "undefined" && $elemOriginalPricePdp.length && typeof data[ref].originalPrice_formatted !== "undefined") {
915								$elemOriginalPricePdp.html(data[ref].originalPrice_formatted);
916							} 
917
918							//on pdp display discount percentage on tag promo
919							if (typeof $elemTagsPdp !== "undefined" && $elemTagsPdp.length) {
920								if ($elemTagsPdp.find(productTags.promoPdpSelector).length) {
921									if (typeof $elemTagsPdp.find(productTags.promoPdpSelector).attr('data-discount-added') === 'undefined' || $elemTagsPdp.find(productTags.promoPdpSelector).attr('data-discount-added') === false) {
922										if (!$elemTagsPdp.hasClass('discount-loaded')) {
923											$elemTagsPdp.addClass('discount-loaded');
924											$elemTagsPdp.find(productTags.promoPdpSelector).append(" -" + Math.floor(discountPercentage) + "%").attr("data-discount-added", "true");
925											if(isV6 && $elemTagsPdp.find(productTags.promoPdpSelector).text().toLowerCase().search("black") > -1) $elemTagsPdp.find(productTags.promoPdpSelector).removeClass('-pink').addClass('-black');
926										}
927									}
928								} else {
929									if (!$elemTagsPdp.hasClass('discount-loaded')) {
930										$elemTagsPdp.addClass('discount-loaded');
931										//$elemTagsPdp.append("<li class='" + productTags.promoPdpClass + "'>-" + Math.floor(discountPercentage) + "%</li>");
932									}
933								}
934							}
935
936							//on plp display discount percentage on each product
937							if (typeof $elemPricePlp !== "undefined" && $elemPricePlp.length) { 
938								//show del element only if old price exists
939								if(typeof data[ref].displayPrice_old_price !== "undefined") {
940									$elemPricePlp.find('del').removeClass("d-none");
941								}
942								// display on the top now 
943								$elemTagsPlp = $elemPricePlp.closest(globalOptions.plpBlocSelector).find('.product-new__item__tags--desc'); // ???
944								if ($elemTagsPlp.length && $elemTagsPlp.find("li").length == 0) { // only add li
945									if (!$elemTagsPlp.hasClass('discount-loaded')) {
946										$elemTagsPlp.addClass('discount-loaded');
947										$elemTagsPlp.prepend("<li class='" + productTags.promoPlpClass + "'>-" + Math.floor(discountPercentage) + "%</li>");
948									}
949								} else if ($elemTagsPlp.find(productTags.promoPlpSelector).length > 0) {
950									if (!$elemTagsPlp.hasClass('discount-loaded')) {
951										$elemTagsPlp.addClass('discount-loaded');
952										$elemTagsPlp.find(productTags.promoPlpSelector).each(function() {
953											// Remove any existing discount percentage from the end
954											var currentText = $(this).text().replace(/-[0-9]*%$/g, '');
955											$(this).text(currentText + " -" + Math.floor(discountPercentage) + "%");
956											if (isV6 && currentText.toLowerCase().search("black") > -1) {
957												$(this).removeClass('-pink').addClass('-black');
958											}
959										});
960										// remove discount if already added (_product_item.cfm)
961										//$elemTagsPlp.find(productTags.promoPlpSelector).text($elemTagsPlp.find(productTags.promoPlpSelector).text().replace(/-[0-9]*%$/g, ''));
962										//$elemTagsPlp.find(productTags.promoPlpSelector).append(" -" + Math.floor(discountPercentage) + "%");
963										//if(isV6 && $elemTagsPlp.find(productTags.promoPlpSelector).text().toLowerCase().search("black") > -1) $elemTagsPlp.find(productTags.promoPlpSelector).removeClass('-pink').addClass('-black');
964									}
965								}
966								/* $elemTagsPlp = $elemPricePlp.find(globalOptions.productTagsSelector); //exists only if there is one promo
967								if ($elemTagsPlp.length && $elemTagsPlp.find(productTags.promoPlpSelector).length) {
968									if (!$elemTagsPlp.hasClass('discount-loaded')) {
969										$elemTagsPlp.addClass('discount-loaded');
970									}
971								} else {
972									if (!$elemPricePlp.find(globalOptions.productTagsSelector).hasClass('discount-loaded')) {
973										$elemPricePlp.find(globalOptions.productTagsSelector).addClass('discount-loaded');
974									}
975								} */
976							}
977						}
978					}
979				}
980			}
981
982			// display maximum of 1 label (cf displayLabels()) per product (priority order : Obselete - Discount (+ personalized label)​ - Top​ - New​ - Personalized label)
983			if (useElasticPriceLoading) {
984				$elemProductPdp = $(globalOptions.pricePdpSelector + "[data-m-product-id=" + ref + "]").closest('.product-main-info');
985			} else {
986				$elemProductPdp = $(globalOptions.pricePdpSelector + "[data-reference='" + ref + "']").closest('.product-main-info');
987			}
988			if (useElasticPriceLoading) {
989				$elemProductPlp = $(localPricePlpSelector + "[data-m-product-id=" + ref + "]").closest(globalOptions.plpBlocSelector);
990			} else {
991				$elemProductPlp = $(localPricePlpSelector + "[data-reference='" + ref + "']").closest(globalOptions.plpBlocSelector);
992			}
993
994			if (typeof $elemProductPdp !== "undefined" && $elemProductPdp.length) {
995				displayLabels($elemProductPdp);
996			} else if (typeof $elemProductPlp !== "undefined" && $elemProductPlp.length) {
997				displayLabels($elemProductPlp);
998			}
999		}
1000
1001		if (typeof intervalTcPlp === "undefined") {
1002			intervalTcPlp = setInterval(function (e) {
1003				//console.log(">>> user_returning intervalTcPlp:" + tc_vars['user_returning']);
1004				if (typeof tc_vars['user_returning'] !== "undefined" && tc_vars['user_returning'] !== "") {
1005					//console.log("sendTags getPrices datas:");
1006					//console.log(tc_vars);
1007					sendTags(tc_vars, false); //to be send after the initial sendTags of tagCommanderV5.js
1008					clearInterval(intervalTcPlp);
1009					//console.log("clear interval");
1010				}
1011			}, 200);
1012		}
1013
1014		if (!isV6) jQuery('[data-toggle="tooltip"]').tooltip();
1015		loadOney();
1016		loadSplittedPrice();
1017		loadPercentSaving(data);
1018	};
1019	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1020		console.log(jqXHR);
1021		console.log(textStatus);
1022		console.log(errorThrown);
1023	};
1024	jQuery.ajax(ajaxR);
1025}
1026function fetchStockId() {
1027    return new Promise(function(resolve, reject) {
1028        var varnishBlocker = Math.random();
1029        var priceLoaderUrl = "/ecommerce/ajax.cfc?_=";
1030        var ajaxR = {
1031            dataType: "json",
1032            url: priceLoaderUrl + varnishBlocker,
1033            method: "GET",
1034            data: { method: "getStockId", sitename: pageSitename },
1035            success: function(data) {
1036                if (data && typeof data.stockId !== "undefined") {
1037                    resolve(data.stockId);
1038                } else {
1039                    reject("stockId not found in response");
1040                }
1041            },
1042            error: function(jqXHR, textStatus, errorThrown) {
1043                reject(errorThrown || textStatus);
1044            }
1045        };
1046        jQuery.ajax(ajaxR);
1047    });
1048}
1049
1050function getStocks(references, localPricePlpSelector = globalOptions.pricePlpSelector, stockId = 0) {
1051	if (stockId == 0) return;
1052	if (references == "") return;
1053	var varnishBlocker = Math.random();
1054	var priceLoaderUrl = (useElasticPriceLoading) ? "/ecommerce/ajax.cfc?_=" : "/eCatalogue/ajax.cfc?_=";
1055	var ajaxR = { dataType: "json", url: priceLoaderUrl + varnishBlocker, method: "GET" };
1056	ajaxR.data = { method: "getStocks", sitename: pageSitename, references: references, language: pageLanguage };
1057	if (isV6) ajaxR.data.version = 'v6';
1058	ajaxR.success = function (data, status, xhr) {
1059		console.log('success getStocks', data);
1060		for (const ref in data) {
1061			setStock(ref, data);
1062		}
1063		
1064	};
1065	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1066		console.log(jqXHR);
1067		console.log(textStatus);
1068		console.log(errorThrown);
1069	};
1070	jQuery.ajax(ajaxR);
1071}
1072
1073function setStock(pId, data) {
1074	var pSelector = "data-reference=" + pId;
1075	var productData = data[pId];
1076
1077	var $priceElement = jQuery(globalOptions.priceSelector + "[" + pSelector + "]");
1078	var $productInfo = $priceElement.closest(".product-info");
1079	var $productMainInfo = $priceElement.closest(".product-main-info");
1080	var $priceWrapperPlpElement = $priceElement.closest(globalOptions.plpPriceWrapperSelector);
1081	var $elemAfterIndicatorStock = $priceWrapperPlpElement.find("div.btn-group");
1082
1083	var $pdpStockContainer = $productInfo.find('.product-stock');
1084	var $pdpStockInfos = $pdpStockContainer.find(".product-stock-basic-infos");
1085	var $pdpPrimaryAction = $productInfo.find('.product-actions ' + globalOptions.primarySelector);
1086	var $pdpActionButtons = $productInfo.find('.product-actions .primary,.product-actions .-primary');
1087	var $pdpAvailabilityHeader = $productInfo.find('.product-availability_header');
1088	var $pdpProductPersoLink = $productInfo.find('a[data-target=".product-perso"]');
1089
1090	/*console.log("SET STOCK DEBUG", {
1091		pId: pId,
1092		data: productData,
1093		salable: productData && productData.salable,
1094		stockInfos: productData && productData.stockInfos,
1095		rootFound: $priceElement.length,
1096		productInfoFound: $productInfo.length,
1097		stockContainerFound: $pdpStockContainer.length,
1098		stockElementFound: $pdpStockInfos.length,
1099		beforeText: $pdpStockInfos.text()
1100	});*/
1101
1102	if (isV6) {
1103		if ($elemAfterIndicatorStock.prev(".status").length == 0) {
1104			$elemAfterIndicatorStock.before('<p class="status"></p>');
1105		}
1106	} else {
1107		if ($elemAfterIndicatorStock.prev(".product-new__item__stock").length == 0) {
1108			$elemAfterIndicatorStock.before('<div class="product-new__item__stock"></div>');
1109		}
1110	}
1111
1112	if (productData.salable) { //has a stock
1113		//display CTA add to cart if stock available
1114		jQuery(".primary.d-none[" + pSelector + "], .-primary.d-none[" + pSelector + "]").removeClass('d-none');
1115
1116		/*console.log($priceWrapperPlpElement.find(globalOptions.stockSelector).length, "stock selector length " + pId + "plp");
1117		console.log($pdpStockContainer.length, "stock selector length " + pId + "pdp");*/
1118
1119		if ($priceWrapperPlpElement.find(globalOptions.stockSelector).length) {
1120			//add class stock products plp - hide on plp if stock available
1121			$priceWrapperPlpElement.find(globalOptions.stockSelector).addClass('d-none');
1122
1123			//set data-product_stock Instock on CTAs PLP (for tracking)
1124			$priceElement
1125				.closest(globalOptions.plpPriceWrapperSelector)
1126				.find(".btn-group a.tc_event_product")
1127				.attr('data-product_stock', 'Instock');
1128		}
1129
1130		if ($pdpStockContainer.length) {
1131			//add class in-stock main product pdp
1132			//$productInfo.find('.product-stock').removeClass(stockClass.outofstock).addClass(stockClass.instock).find(".product-stock-basic-infos").html(productData.stockInfos);
1133			var $stockElement = $pdpStockContainer
1134				.removeClass(stockClass.outofstock)
1135				.addClass(stockClass.instock)
1136				.find(".product-stock-basic-infos");
1137
1138			var customStockInfo = $stockElement.attr('data-customstockinfos');
1139			var stockText = productData.stockInfos;
1140
1141			if (typeof customStockInfo !== 'undefined' && customStockInfo !== false && customStockInfo.length) {
1142				stockText += ' - ' + customStockInfo;
1143			}
1144
1145			$stockElement.html(stockText);
1146			$pdpStockContainer.removeClass('d-none');
1147
1148			// hide product-unavailability on pdp if stock available
1149			$productInfo.find('.product-unavailability').addClass('d-none');
1150
1151			//show info delivery
1152			$productInfo.find('.product-freedelivery').removeClass('d-none');
1153			$productInfo.find('.product-infodelivery').removeClass('d-none');
1154
1155			//display remaining stock on pdp if display_remaining_stock=1
1156			//if ($pdpStockContainer.data('display-remaining-stock') && typeof productData.displayQtyStock !== "undefined") {
1157			//	$productInfo.find('.product-stock.' + stockClass.instock).prepend(productData.displayQtyStock);
1158			//}
1159
1160			//set datalayer Instock product pdp
1161			if (typeof tc_vars["product_stock"] !== 'undefined' && tc_vars["product_stock"] !== false && tc_vars["product_stock"] != "") {
1162				tc_vars['product_stock'] = 'Instock';
1163			}
1164		}
1165
1166		//set data-product_stock Instock main product pdp in product-main-info
1167		$productMainInfo.attr('data-product_stock', 'Instock');
1168
1169		//enable CTA buy to cart pdp
1170		if (
1171			$pdpPrimaryAction.length &&
1172			typeof $pdpPrimaryAction.attr('data-url-stock') !== 'undefined' &&
1173			typeof $pdpPrimaryAction.attr('data-url-stock') !== false
1174		) {
1175			var url_stock = $pdpActionButtons.attr('data-url-stock');
1176
1177			$pdpActionButtons
1178				.removeClass('disabled')
1179				.attr({
1180					"href": url_stock,
1181					"data-url": url_stock,
1182					"data-product_stock": "Instock"
1183				})
1184				.removeAttr("disabled");
1185
1186			$pdpActionButtons.unbind('click');
1187
1188			jQuery(globalOptions.stickyNavSelector + " .primary," + globalOptions.stickyNavSelector + " .-primary")
1189				.removeClass('disabled')
1190				.attr({
1191					"href": url_stock,
1192					"data-url": url_stock,
1193					"data-product_stock": "Instock"
1194				})
1195				.removeAttr("disabled");
1196		}
1197
1198		/*if (jQuery("#product-qty[data-qty-reference='" + productData.sku + "']").length) {
1199			jQuery("#product-qty[data-qty-reference='" + productData.sku + "']").removeAttr("disabled");
1200
1201			if (productData.qtyStock > 0) { // avoid manage_stock = false case
1202				jQuery("#product-qty[data-qty-reference='" + productData.sku + "'] option").each(function (index) {
1203					if ($(this).val() > productData.qtyStock) { $(this).hide(); }
1204				});
1205			}
1206		}*/
1207
1208	} else {
1209		if ($priceWrapperPlpElement.find(globalOptions.stockSelector).length) {
1210			//add class no-stock products plp
1211			$priceWrapperPlpElement.find(globalOptions.stockSelector)
1212				.addClass(stockClass.outofstock)
1213				.html(productData.stockInfos);
1214
1215			//set data-product_stock Outofstock on CTAs PLP (for tracking)
1216			$priceElement
1217				.closest(globalOptions.plpPriceWrapperSelector)
1218				.find(".btn-group a.tc_event_product")
1219				.attr('data-product_stock', 'Outofstock');
1220		} else if ($pdpStockContainer.length) {
1221			//add class no-stock main product pdp
1222			$pdpStockContainer
1223				.removeClass(stockClass.instock)
1224				.addClass(stockClass.outofstock)
1225				.find("> span")
1226				.html(productData.stockInfos);
1227
1228			// show product-unavailability on pdp 
1229			$productInfo.find('.product-unavailability').removeClass('d-none');
1230
1231			//show info delivery
1232			$productInfo.find('.product-freedelivery').addClass('d-none');
1233			$productInfo.find('.product-infodelivery').addClass('d-none');
1234
1235			//display button Receive an alert if no stock and config useEmailAlert true
1236			if ($productInfo.find('.btnReceiveAlert').length) {
1237				$productInfo.find('.btnReceiveAlert').removeClass('d-none');
1238			}
1239
1240			//set datalayer Outofstock product pdp
1241			if (typeof tc_vars["product_stock"] !== 'undefined' && tc_vars["product_stock"] !== false && tc_vars["product_stock"] != "") {
1242				tc_vars['product_stock'] = 'Outofstock';
1243			}
1244		}
1245
1246		//remove product quantity main product pdp
1247		if (isV6) {
1248			$productInfo.find('[data-id="product-qty"]').remove();
1249		} else {
1250			$productInfo.find('#product-qty').parent().remove();
1251		}
1252
1253		//set data-product_stock OutStock main product pdp in product-main-info
1254		$productMainInfo.attr('data-product_stock', 'OutStock');
1255
1256		//disable CTA buy to cart pdp
1257		if ($pdpActionButtons.length) {
1258			$pdpActionButtons
1259				.addClass('disabled')
1260				.attr({
1261					"href": "javascript:void(0)",
1262					"data-url": "javascript:void(0)",
1263					"data-product_stock": "OutStock",
1264					"disabled": "disabled"
1265				});
1266
1267			$pdpActionButtons.unbind('click');
1268
1269			jQuery(".subnav_entries_buy .primary,.buyButton_mobile .primary, .nav-bar-product .-primary,.sticky-bar-mobile .-primary")
1270				.addClass('disabled')
1271				.unbind('click')
1272				.attr({
1273					"href": "javascript:void(0)",
1274					"data-url": "javascript:void(0)",
1275					"data-product_stock": "OutStock",
1276					"disabled": "disabled"
1277				});
1278		}
1279
1280		if (useElasticPriceLoading) {
1281			if (jQuery(".products .product-new__item__link_dealerlocator[data-product-sku='" + productData.sku + "']").length) {
1282				jQuery(".products .product-new__item__link_dealerlocator[data-product-sku='" + productData.sku + "']").removeClass('d-none');
1283			}
1284		} else {
1285			if (jQuery(".products .product-new__item__link_dealerlocator[data-product-sku=" + pId + "]").length) {
1286				jQuery(".products .product-new__item__link_dealerlocator[data-product-sku=" + pId + "]").removeClass('d-none');
1287			}
1288		}
1289	}
1290
1291	//show stock message
1292	/*console.log(">>> stockInfos:" + productData.stockInfos);
1293	console.log(">>> show product-availability_header setStock");*/
1294	$pdpAvailabilityHeader.removeClass('d-none');
1295
1296	if (productData.stockInfos.length) {
1297		$priceWrapperPlpElement.find(globalOptions.stockSelector).attr("data-original-title", productData.stockInfos);
1298	}
1299
1300	//update price of bundle pdp if #customize is in url in case some optional options are auto selectionned/checked (attribute is_default in elastic) 
1301	if (
1302		jQuery(".product-main-info").length > 0 &&
1303		window.location.hash == '#customize' &&
1304		$(globalOptions.primarySelector + '[aria-controls=aside-panel-product],.-primary[aria-controls=aside-panel-product]').length &&
1305		$pdpProductPersoLink.length
1306	) {
1307		updatePrice($(globalOptions.productBundleSelector));
1308		updateSummary($(globalOptions.productBundleSelector));
1309	}
1310
1311	//set variable stock in datalayer for product in PLP
1312	if (typeof tc_vars["listing_products"] !== 'undefined' && tc_vars["listing_products"] !== false && tc_vars["listing_products"] != "") {
1313		for (const product_key of Object.keys(tc_vars["listing_products"])) {
1314			const objProduct = tc_vars["listing_products"][product_key];
1315			if (objProduct.listing_product_id == pId) {
1316				if (productData.salable) {
1317					objProduct['listing_product_stock'] = 'Instock';
1318				} else {
1319					objProduct['listing_product_stock'] = 'Outofstock';
1320				}
1321			}
1322		}
1323	}
1324}
1325
1326function setPrice(pId, data, stockId) {
1327	var pSelector = "data-reference=" + pId;
1328	if (useElasticPriceLoading) {
1329		pSelector = "data-m-product-id=" + pId;
1330	}
1331
1332	/*** Set price item ***/
1333	jQuery(globalOptions.priceSelector + "[" + pSelector + "]").prev(globalOptions.priceStartingFromSelector).remove(); //remove starting from
1334	jQuery(globalOptions.priceSelector + "[" + pSelector + "]").replaceWith(data[pId].displayPrice); //replace the price
1335	if(typeof data[pId].displayPrice_sup !== "undefined") {
1336		// if you want to display the sup tag (decimals) separately + have to update all product_item templates 
1337		const refAttr = useElasticPriceLoading ? 'data-m-product-id' : 'data-reference';
1338		const pricePdpSelector = `${globalOptions.pricePdpSelector}[${refAttr}='${pId}']`;
1339		const priceSelector = `${globalOptions.priceSelector}[${refAttr}='${pId}']`;
1340		jQuery(pricePdpSelector).replaceWith(data[pId].displayPrice_sup); 
1341		jQuery(pricePdpSelector+ ' .product-price-start').remove(); //remove starting from on pdp
1342		jQuery(globalOptions.stickyNavSelector +' '+priceSelector).replaceWith(data[pId].displayPrice_sup);
1343		jQuery(globalOptions.stickyNavSelector +' '+priceSelector + ' .product-price-start').remove(); //remove starting from on sticky nav
1344		jQuery(globalOptions.stickyBarMobile +' '+priceSelector).replaceWith(data[pId].displayPrice_sup); 
1345		jQuery(globalOptions.stickyBarMobile +' '+priceSelector+ ' .product-price-start').remove(); //remove starting from on sticky bar mobile 
1346		/*console.log('>>:' + refAttr + ' pId:' + pId, 'pricePdpSelector:' + pricePdpSelector);
1347		console.log('>>:' + refAttr + ' stickyNavSelector selector:' + globalOptions.stickyNavSelector +' '+priceSelector);
1348		console.log('>>:' + refAttr + ' stickyBarMobile selector:' + globalOptions.stickyBarMobile +' '+priceSelector);*/
1349	}
1350	jQuery(globalOptions.priceSelector + "[" + pSelector + "]").next("p.product-price-vat").remove(); //remove the vat message
1351
1352	// sticky price items
1353	//jQuery(globalOptions.stickyNavSelector + " span.price[" + pSelector + "]").html(data[pId].displayPrice);
1354	//jQuery(globalOptions.stickyBarMobile + " span.price[" + pSelector + "]").html(data[pId].displayPrice);
1355	jQuery(".buyButton_mobile p[" + pSelector + "]").html(data[pId].displayPrice); // v5 only
1356
1357	// set other data attributes - not longer required on v6 done in getDisplayPrice
1358	jQuery(globalOptions.priceSelector + "[" + pSelector + "]").parent("div.product-price.product_price").attr('data-numeric-price', data[pId].numericPrice);
1359	if (parseInt(data[pId].numericPrice) < parseInt(data[pId].originalPrice) && typeof data[pId].strikethrough === 'undefined') {
1360		jQuery(globalOptions.priceSelector + "[" + pSelector + "]").parent("div.product-price.product_price").attr('data-original-price', data[pId].originalPrice);
1361	}
1362
1363	// use buttons as reference instead of price
1364	/* if(jQuery(".products "+globalOptions.priceSelector+"["+pSelector+"]").find("span.price").next().hasClass('product-new__item__action')) {
1365		$elemBeforeIndicatorStock = jQuery(".products "+globalOptions.priceSelector+"["+pSelector+"]").find("span.price").next(); // case with special price
1366	} else {
1367		$elemBeforeIndicatorStock = jQuery(".products "+globalOptions.priceSelector+"["+pSelector+"]").find("span.price"); // case without special price
1368	}
1369	$elemBeforeIndicatorStock.after('<div class="product-new__item__stock"></div>');*/
1370
1371	const pricePdpSelector = `${globalOptions.pricePdpSelector}[${pSelector}]:not(.sticky-bar-mobile *)`;
1372	const $pricePdpElement = jQuery(pricePdpSelector).not();
1373	const $priceWrapperPlpElement = jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(globalOptions.plpPriceWrapperSelector);
1374	
1375	if($pricePdpElement.length) {
1376		//remove discount (<del>) next to price for main product on pdp (to avoid margins arround price)
1377		//if($pricePdpElement.find("del").length) {
1378		//	$pricePdpElement.find("del").remove();
1379		//}
1380	}
1381
1382	//remove discount percentage next to price on plp if exists (discount percentage not displayed on plp)
1383	if($priceWrapperPlpElement.find('.product-price-discount-percentage').length) {
1384		$priceWrapperPlpElement.find('.product-price-discount-percentage').remove();
1385	}
1386
1387	$elemAfterIndicatorStock = $priceWrapperPlpElement.find("div.btn-group");
1388	if (isV6) {
1389		if($elemAfterIndicatorStock.prev(".status").length == 0) {
1390			$elemAfterIndicatorStock.before('<p class="status"></p>');
1391		}
1392	} else {
1393		if($elemAfterIndicatorStock.prev(".product-new__item__stock").length == 0) {
1394			$elemAfterIndicatorStock.before('<div class="product-new__item__stock"></div>');
1395		}
1396	}
1397	if(stockId == "0") { 
1398		if (data[pId].hasStock) {
1399			//display CTA add to cart if stock available
1400			jQuery(".primary.d-none[" + pSelector + "], .-primary.d-none[" + pSelector + "]").removeClass('d-none');
1401			if ($priceWrapperPlpElement.find(globalOptions.stockSelector).length) {
1402				//add class stock products plp - hide on plp if stock available
1403				$priceWrapperPlpElement.find(globalOptions.stockSelector).addClass('d-none');
1404				//set data-product_stock Instock on CTAs PLP (for tracking)
1405				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(globalOptions.plpPriceWrapperSelector).find(".btn-group a.tc_event_product").attr('data-product_stock', 'Instock');
1406			} else if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').length) {
1407				//add class in-stock main product pdp
1408				//jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').removeClass(stockClass.outofstock).addClass(stockClass.instock).find(".product-stock-basic-infos").html(data[pId].stockInfos);
1409				var $stockElement = jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').removeClass(stockClass.outofstock).addClass(stockClass.instock).find(".product-stock-basic-infos");
1410				var customStockInfo = $stockElement.attr('data-customstockinfos');
1411				var stockText = data[pId].stockInfos;
1412				if (typeof customStockInfo !== 'undefined' && customStockInfo !== false && customStockInfo.length) {
1413					stockText += ' - ' + customStockInfo;
1414				}
1415				$stockElement.html(stockText);
1416
1417				console.log("SET STOCK AFTER", {
1418					pId: pId,
1419					afterText: jQuery(globalOptions.priceSelector + "[data-reference=" + pId + "]")
1420						.closest(".product-info")
1421						.find('.product-stock')
1422						.find(".product-stock-basic-infos")
1423						.text()
1424				});
1425
1426				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').removeClass('d-none');
1427				// hide product-unavailability on pdp if stock available
1428				if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-unavailability').length) {
1429					jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-unavailability').addClass('d-none');
1430				}
1431				//display remaining stock on pdp if display_remaining_stock=1
1432				if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').data('display-remaining-stock') && typeof data[pId].displayQtyStock !== "undefined") {
1433					jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock.' + stockClass.instock).prepend(data[pId].displayQtyStock);
1434				}
1435				//set datalayer Instock product pdp
1436				if (typeof tc_vars["product_stock"] !== 'undefined' && tc_vars["product_stock"] !== false && tc_vars["product_stock"] != "") {
1437					tc_vars['product_stock'] = 'Instock';
1438				}
1439			}
1440			//set data-product_stock Instock main product pdp in product-main-info
1441			jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-main-info").attr('data-product_stock', 'Instock');
1442			//enable CTA buy to cart pdp
1443			if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions ' + globalOptions.primarySelector).length && typeof jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions ' + globalOptions.primarySelector).attr('data-url-stock') !== 'undefined' && typeof jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions ' + globalOptions.primarySelector).attr('data-url-stock') !== false) {
1444				url_stock = jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions .primary,.product-actions .-primary').attr('data-url-stock');
1445				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions .primary,.product-actions .-primary').removeClass('disabled').attr({
1446					"href": url_stock,
1447					"data-url": url_stock,
1448					"data-product_stock": "Instock"
1449				}).removeAttr("disabled");
1450				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions .primary,.product-actions .-primary').unbind('click');
1451				jQuery(globalOptions.stickyNavSelector + " .primary," + globalOptions.stickyNavSelector + " .-primary").removeClass('disabled').attr({
1452					"href": url_stock,
1453					"data-url": url_stock,
1454					"data-product_stock": "Instock"
1455				}).removeAttr("disabled");
1456			}
1457
1458			if (jQuery("#product-qty[data-qty-reference='" + data[pId].sku + "']").length) {
1459				jQuery("#product-qty[data-qty-reference='" + data[pId].sku + "']").removeAttr("disabled");
1460
1461				if (data[pId].qtyStock > 0) { // avoid manage_stock = false case
1462					jQuery("#product-qty[data-qty-reference='" + data[pId].sku + "'] option").each(function (index) {
1463						if ($(this).val() > data[pId].qtyStock) { $(this).hide(); }
1464					});
1465				}
1466			}
1467
1468		} else {
1469			if ($priceWrapperPlpElement.find(globalOptions.stockSelector).length) {
1470				//add class no-stock products plp
1471				$priceWrapperPlpElement.find(globalOptions.stockSelector).addClass(stockClass.outofstock).html(data[pId].stockInfos);
1472				//set data-product_stock Outofstock on CTAs PLP (for tracking)
1473				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(globalOptions.plpPriceWrapperSelector).find(".btn-group a.tc_event_product").attr('data-product_stock', 'Outofstock');
1474			} else if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').length) {
1475				//add class no-stock main product pdp
1476				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-stock').removeClass(stockClass.instock).addClass(stockClass.outofstock).find("> span").html(data[pId].stockInfos);
1477				//display button Receive an alert if no stock and config useEmailAlert true
1478				if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.btnReceiveAlert').length) {
1479					jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.btnReceiveAlert').removeClass('d-none');
1480				}
1481				//set datalayer Outofstock product pdp
1482				if (typeof tc_vars["product_stock"] !== 'undefined' && tc_vars["product_stock"] !== false && tc_vars["product_stock"] != "") {
1483					tc_vars['product_stock'] = 'Outofstock';
1484				}
1485			}
1486
1487			//remove product quantity main product pdp
1488			if (isV6) jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('[data-id="product-qty"]').remove();
1489			else jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('#product-qty').parent().remove();
1490			//set data-product_stock OutStock main product pdp in product-main-info
1491			jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-main-info").attr('data-product_stock', 'OutStock');
1492			//disable CTA buy to cart pdp
1493			if (jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions .primary,.product-actions .-primary').length) {
1494				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions .primary,.product-actions .-primary').addClass('disabled').attr({
1495					"href": "javascript:void(0)",
1496					"data-url": "javascript:void(0)",
1497					"data-product_stock": "OutStock",
1498					"disabled": "disabled"
1499				});
1500				jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-actions .primary,.product-actions .-primary').unbind('click');
1501				jQuery(".subnav_entries_buy .primary,.buyButton_mobile .primary, .nav-bar-product .-primary,.sticky-bar-mobile .-primary").addClass('disabled').unbind('click').attr({
1502					"href": "javascript:void(0)",
1503					"data-url": "javascript:void(0)",
1504					"data-product_stock": "OutStock",
1505					"disabled": "disabled"
1506				});
1507			}
1508			if (useElasticPriceLoading) {
1509				if (jQuery(".products .product-new__item__link_dealerlocator[data-product-sku='" + data[pId].sku + "']").length) {
1510					jQuery(".products .product-new__item__link_dealerlocator[data-product-sku='" + data[pId].sku + "']").removeClass('d-none');
1511				}
1512			}
1513			else {
1514				if (jQuery(".products .product-new__item__link_dealerlocator[data-product-sku=" + pId + "]").length) {
1515					jQuery(".products .product-new__item__link_dealerlocator[data-product-sku=" + pId + "]").removeClass('d-none');
1516				}
1517			}
1518
1519		}
1520		//show stock message
1521		console.log(">>> show product-availability_header setPrice");
1522		jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('.product-availability_header').removeClass('d-none');
1523		if (data[pId].stockInfos.length) {
1524			$priceWrapperPlpElement.find(globalOptions.stockSelector).attr("data-original-title", data[pId].stockInfos);
1525		}
1526	} // end if stockId==0 
1527	
1528	//update price of bundle pdp if #customize is in url in case some optional options are auto selectionned/checked (attribute is_default in elastic) 
1529	if (jQuery(".product-main-info").length > 0 && window.location.hash == '#customize' && $(globalOptions.primarySelector + '[aria-controls=aside-panel-product],.-primary[aria-controls=aside-panel-product]').length && jQuery(globalOptions.priceSelector + "[" + pSelector + "]").closest(".product-info").find('a[data-target=".product-perso"]').length) {
1530		updatePrice($(globalOptions.productBundleSelector));
1531		updateSummary($(globalOptions.productBundleSelector));
1532	}
1533
1534	//set variable stock in datalayer for product in PLP
1535	if (typeof tc_vars["listing_products"] !== 'undefined' && tc_vars["listing_products"] !== false && tc_vars["listing_products"] != "") {
1536		for (const product_key of Object.keys(tc_vars["listing_products"])) {
1537			const objProduct = tc_vars["listing_products"][product_key];
1538			if (objProduct.listing_product_id == pId) {
1539				if (data[pId].hasStock) {
1540					objProduct['listing_product_stock'] = 'Instock';
1541				} else {
1542					objProduct['listing_product_stock'] = 'Outofstock';
1543				}
1544			}
1545		}
1546	}
1547}
1548
1549function displayLabels($elemProduct) {
1550	nb_tags_displayed = 0;
1551	max_tags_displayed = 1; //	44121: Tag marketing priority : only 1 tag display 
1552
1553	if ($elemProduct.find('[data-tag-type=obselete]').length) {
1554		nb_tags_displayed++;
1555	}
1556	if ($elemProduct.find('.discount-loaded').length) {
1557		if ($elemProduct.find('.discount-loaded').find(productTags.promoPlpSelector).length) {
1558			$elemProduct.find('.discount-loaded').find(productTags.promoPlpSelector).show();
1559			nb_tags_displayed++;
1560		} else if ($elemProduct.find('.discount-loaded').find(productTags.promoPdpSelector).length) {
1561			$elemProduct.find('.discount-loaded').find(productTags.promoPdpSelector).show();
1562			nb_tags_displayed++;
1563		}
1564	}
1565	if ($elemProduct.find('[data-tag-type=top]').length) {
1566		if (nb_tags_displayed < max_tags_displayed) {
1567			$elemProduct.find('[data-tag-type=top]').show();
1568			nb_tags_displayed++;
1569		}
1570	}
1571	if ($elemProduct.find('[data-tag-type=new]').length) {
1572		if (nb_tags_displayed < max_tags_displayed) {
1573			$elemProduct.find('[data-tag-type=new]').show();
1574			nb_tags_displayed++;
1575		}
1576	}
1577	if ($elemProduct.find('[data-tag-type=promolabel]').length && $elemProduct.find('.discount-loaded').length == 0) {
1578		if (nb_tags_displayed < max_tags_displayed) {
1579			$elemProduct.find('[data-tag-type=promolabel]').show();
1580		}
1581	}
1582	if ($elemProduct.find('[data-tag-type=flashsell]').length) {
1583		if (nb_tags_displayed < max_tags_displayed) {
1584			$elemProduct.find('[data-tag-type=flashsell]').show();
1585		}
1586	}
1587}
1588
1589function deleteCustomerWishList(customer_id, sku, deleted_from_pdp_or_plp = false) {
1590	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
1591	ajaxR.data = { method: "deleteWishList", sitename: pageSitename, customer_id: customer_id, sku: sku };
1592	ajaxR.success = function (data, status, xhr) {
1593		//console.log(data);
1594		if (deleted_from_pdp_or_plp) {
1595			/* if (jQuery('.product-wishlist-message').length) {
1596				jQuery('.product-wishlist-message .product-wishlist-message-added').hide();
1597				jQuery('.product-wishlist-message .product-wishlist-message-removed').show();
1598			} else { */
1599				$(".header-message").hide();
1600				$(".header-message.removed-from-wishlist").show();
1601			/* } */
1602			/* if ($('.product-main-info .product-fav[data-product-sku="' + sku + '"]').length) {
1603				jQuery('.product-fav[data-product-sku="' + sku + '"] .btRemoveFromMyWishList').hide();
1604				jQuery('.product-fav[data-product-sku="' + sku + '"] .btAddToMyWishList').show();
1605			} else { */
1606				jQuery('.btRemoveFromMyWishList[data-product-sku="' + sku + '"]').hide();
1607				jQuery('.btAddToMyWishList[data-product-sku="' + sku + '"]').show();
1608			/* } */
1609			if (localStorage && localStorage.getItem("arrayWishList")) {
1610				arrayLocalStorageWishList = JSON.parse(localStorage.getItem("arrayWishList"));
1611				const indexSku = arrayLocalStorageWishList.indexOf(sku.toString());
1612				if (indexSku > -1) { 
1613					arrayLocalStorageWishList.splice(indexSku, 1);
1614					localStorage.setItem("arrayWishList", JSON.stringify(arrayLocalStorageWishList));
1615				}
1616			}
1617			$(".content-loader").hide();
1618		} else {
1619			location.reload(); //reload page
1620		}
1621	};
1622	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1623		console.log(jqXHR);
1624		console.log(textStatus);
1625		console.log(errorThrown);
1626	};
1627	jQuery.ajax(ajaxR);
1628}
1629
1630function deleteAllCustomerWishList(customer_id) {
1631	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "GET" }; //
1632	ajaxR.data = { method: "deleteWishList", sitename: pageSitename, customer_id: customer_id };
1633	ajaxR.success = function (data, status, xhr) {
1634		//console.log(data);
1635	};
1636	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1637		console.log(jqXHR);
1638		console.log(textStatus);
1639		console.log(errorThrown);
1640	};
1641	jQuery.ajax(ajaxR);
1642}
1643
1644
1645function getLoginStatusWithMagentoAndDoWishListAction(sku, action, target) {
1646	var loginR = { dataType: "json", url: "/ajax.cfm?targetFunction=getLoginStatusWithMagento&targetComponent=loginStatus&sitename=" + pageSitename + "&plugin=Extranet", method: "POST" };
1647
1648	loginR.success = function (data) {
1649		if (data.connected) {
1650			//console.log(data);
1651			if (data.customer_id !== "undefined") {
1652				if (action == 'addItoMyWishList') {
1653					addItoMyWishList(data.customer_id, sku)
1654				} else if (action == 'removeItFromMywhishList') {
1655					deleteCustomerWishList(data.customer_id, sku, true);
1656				}
1657			}
1658
1659		} else {
1660			console.log("login required !");
1661			window.location.replace($(target).data('url-login-redirect'));
1662		}
1663	};
1664	loginR.error = function (err) {
1665
1666	};
1667	$(".content-loader").show();
1668	jQuery.ajax(loginR);
1669}
1670
1671function addItoMyWishList(customer_id, sku) {
1672	if (jQuery(".product-actions #product-qty").length) {
1673		var qty = jQuery(".product-actions #product-qty").val();
1674	} else {
1675		var qty = 1;
1676	}
1677
1678	var comment = ' ';
1679	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc", method: "POST" }; //
1680
1681	ajaxR.data = { method: "updateWishList", sitename: pageSitename, customer_id: customer_id, sku: sku, qty: qty, description: comment };
1682
1683	ajaxR.success = function (data, status, xhr) {
1684		//console.log(data);
1685		/* if (jQuery('.product-wishlist-message').length) {
1686			jQuery('.product-wishlist-message .product-wishlist-message-removed').hide();
1687			jQuery('.product-wishlist-message .product-wishlist-message-added').show();
1688		} else { */
1689			$(".header-message").hide();
1690			$(".header-message.added-to-wishlist").show();
1691		/* } */
1692		/* if ($('.product-main-info .product-fav[data-product-sku="' + sku + '"]').length) {
1693			jQuery('.product-fav[data-product-sku="' + sku + '"] .btAddToMyWishList').hide();
1694			jQuery('.product-fav[data-product-sku="' + sku + '"] .btRemoveFromMyWishList').show();
1695		} else { */
1696			jQuery('.btAddToMyWishList[data-product-sku="' + sku + '"]').hide();
1697			jQuery('.btRemoveFromMyWishList[data-product-sku="' + sku + '"]').show();
1698		/* } */
1699		if (localStorage) {
1700			if(localStorage.getItem("arrayWishList")) {
1701				arrayLocalStorageWishList = JSON.parse(localStorage.getItem("arrayWishList"));
1702			} else {
1703				arrayLocalStorageWishList = [];
1704			}
1705			arrayLocalStorageWishList.push(sku.toString());
1706			localStorage.setItem("arrayWishList", JSON.stringify(arrayLocalStorageWishList));
1707		}
1708		$(".content-loader").hide();
1709	};
1710	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1711		console.log(jqXHR);
1712		console.log(textStatus);
1713		console.log(errorThrown);
1714	};
1715
1716	jQuery.ajax(ajaxR);
1717}
1718function getClosedBundleOptions(bundleOptions) {
1719	var bundleSelection = [];
1720	for (const field of bundleOptions) {
1721		var optionId = field.option_id;
1722		var optionQty = field.product_links[0].qty;
1723		var option_selections = [field.product_links[0].id];
1724
1725		var structOption = { "option_id": optionId, "option_selections": option_selections, "option_qty": optionQty };
1726
1727		bundleSelection.push(structOption);
1728	}
1729	var bundleFormDataString = JSON.stringify(bundleSelection);
1730	return bundleFormDataString;
1731}
1732
1733function getBundleOptions(sku, extendedInfos = false) {
1734	$formBundleOptions = $("[data-sku='" + sku + "'] .bundle-options").find(globalOptions.productBundleSelector);
1735	var bundleFormData = [];
1736
1737	for (const field of $formBundleOptions) {
1738		var optionId = getOptionId(field.id);
1739		var $optionObj = $("#" + field.id);
1740		var optionQty = $("#bundle-option-" + optionId + "-qty-input").val();
1741		if (parseInt(optionQty) > 0 || $(".test-bundle-qty").length) {
1742			var structOption = { "option_id": optionId, "option_selections": [], "option_qty": parseInt(optionQty) };
1743			if (field.value == '') {
1744				option_selections = [];
1745			} else {
1746				if (Array.isArray($optionObj.val())) {
1747					for (const v of $optionObj.val()) {
1748						option_selections = [parseInt(v)];
1749						structOption = { "option_id": optionId, "option_selections": option_selections, "option_qty": parseInt(optionQty) };
1750
1751						if (extendedInfos) {
1752							if (typeof $optionObj.attr('value') !== 'undefined' && $optionObj.attr('value') !== false) {
1753								var $productObj = $optionObj;
1754							} else {
1755								var $productObj = $optionObj.find("[value='" + field.value + "']");
1756							}
1757							structOption["product_name"] = $productObj.data('option-name');
1758							structOption["product_sku"] = $productObj.data('option-sku');
1759							structOption["product_price"] = $productObj.data('price');
1760						}
1761
1762						if ($optionObj.children().length > 1 || $optionObj.prop("checked")) {
1763							bundleFormData.push(structOption);
1764						}
1765					}
1766				} else {
1767					option_selections = [parseInt(field.value)];
1768					structOption = { "option_id": optionId, "option_selections": option_selections, "option_qty": parseInt(optionQty) };
1769
1770					if (extendedInfos) {
1771						if (typeof $optionObj.attr('value') !== 'undefined' && $optionObj.attr('value') !== false) {
1772							var $productObj = $optionObj;
1773						} else {
1774							var $productObj = $optionObj.find("[value='" + field.value + "']");
1775						}
1776						structOption["product_name"] = $productObj.data('option-name');
1777						structOption["product_sku"] = $productObj.data('option-sku');
1778						structOption["product_price"] = $productObj.data('price');
1779					}
1780					if ($optionObj.children().length > 1 || $optionObj.prop("checked")) {
1781						bundleFormData.push(structOption);
1782					}
1783				}
1784			}
1785		}
1786	}
1787
1788	bundleFormDataString = JSON.stringify(bundleFormData);
1789	return bundleFormDataString;
1790}
1791
1792function onBundleOptionChanged(event) {
1793	var $bundleOption = $(event.target);
1794	var canChangeQty = false;
1795	var defaultQty = 0;
1796	var optionId = 0;
1797
1798	if ($bundleOption.find(":selected").length > 0) { /* select */
1799		canChangeQty = $bundleOption.find(":selected").data("can-change-qty");
1800		//isRequired = $bundleOption.data("is-required");
1801		defaultQty = $bundleOption.find(":selected").data("qty");
1802		optionId = getOptionId($bundleOption[0].id);
1803		productIdSelected = $bundleOption.val();
1804	}
1805	else if ($bundleOption.prop("checked") == true || $bundleOption.prop("checked") == false) { /* radio or checkbox */
1806		canChangeQty = $bundleOption.data("can-change-qty");
1807		//isRequired = false;
1808		defaultQty = $bundleOption.data("qty");
1809		optionId = getOptionId($bundleOption[0].id);
1810		productIdSelected = $bundleOption.val();
1811
1812		if ($bundleOption.prop("checked") == false && $($bundleOption).closest('.options-list').find('input
1812:checked').length == 0) {
1813			canChangeQty = undefined;
1814		}
1815	}
1816
1817	var $qtyField = $("#bundle-option-" + optionId + "-qty-input");
1818
1819	// set Quantity
1820	if (canChangeQty == true) {
1821		if (defaultQty == 0) {
1822			newQty = 1;
1823		} else {
1824			newQty = defaultQty;
1825		}
1826
1827		$qtyField.removeAttr("disabled");
1828		if(isV6) {
1829			$qtyField.val(newQty).change();
1830			$qtyField.closest('.form-line').removeClass("-disabled");
1831		} else {
1832			$qtyField.val(newQty);
1833			$qtyField.next().attr('title', newQty);
1834			$qtyField.next().find('.filter-option-inner-inner').text(newQty);
1835			$qtyField.next().removeClass('disabled').attr('aria-disabled', 'false');
1836
1837			/* $qtyField.parent().find('ul.dropdown-menu li').removeClass('selected').removeClass('active');
1838			$qtyField.parent().find('ul.dropdown-menu li a').removeClass('selected').removeClass('active').attr('aria-selected', 'false'); */
1839
1840			/* if(isRequired) {
1841				console.log('IF');
1842				console.log($qtyField.parent().find('ul.dropdown-menu li:first-child'));
1843				$qtyField.parent().find('ul.dropdown-menu li:first-child').addClass('selected').addClass('active');
1844				$qtyField.parent().find('ul.dropdown-menu li:first-child a').addClass('selected').addClass('active').attr('aria-selected', 'true');
1845			} else {
1846				console.log('ELSE');
1847				console.log($qtyField.parent().find('ul.dropdown-menu li:nth-child(2)'));
1848				$qtyField.parent().find('ul.dropdown-menu li:nth-child(2)').addClass('selected').addClass('active');
1849				$qtyField.parent().find('ul.dropdown-menu li:nth-child(2) a').addClass('selected').addClass('active').attr('aria-selected', 'true');
1850			} */
1851
1852			//$qtyField.removeClass("form-control-plaintext");
1853		}
1854	}
1855	else if (canChangeQty == false) {
1856		$qtyField.attr("disabled", true);
1857		if(isV6) {
1858			$qtyField.val(defaultQty).change();
1859			$qtyField.closest('.form-line').addClass("-disabled");
1860		} else {
1861			$qtyField.val(defaultQty);
1862			$qtyField.next().attr('title', defaultQty);
1863			$qtyField.next().find('.filter-option-inner-inner').text(defaultQty);
1864			$qtyField.next().addClass('disabled').attr('aria-disabled', 'true');
1865			//$qtyField.removeClass("form-control-plaintext");
1866		}
1867	}
1868	else {
1869		//Select option "Choose an option"
1870		$qtyField.attr("disabled", true);
1871		if(isV6) {
1872			$qtyField.val(0).change();
1873			$qtyField.closest('.form-line').addClass("-disabled");
1874		} else {
1875			$qtyField.val(0);
1876			$qtyField.next().attr('title', 0);
1877			$qtyField.next().find('.filter-option-inner-inner').text(0);
1878			$qtyField.next().addClass('disabled').attr('aria-disabled', 'true');
1879			//$qtyField.addClass("form-control-plaintext");
1880		}
1881	}
1882
1883	if ($bundleOption.attr('type') == 'checkbox') {
1884		if ($bundleOption.prop("checked") == true) {
1885			$bundleOption.closest('li').find('#product-visual-' + productIdSelected).removeClass('d-none');
1886			$bundleOption.closest('li').find('#product-name-' + productIdSelected).removeClass('d-none');
1887		} else {
1888			$bundleOption.closest('li').find('#product-visual-' + productIdSelected).addClass('d-none');
1889			$bundleOption.closest('li').find('#product-name-' + productIdSelected).addClass('d-none');
1890		}
1891	}
1892	if ($bundleOption.attr('type') == 'multi') {
1893		$bundleOption.closest('li').find('.product-visual').addClass('d-none');
1894		$bundleOption.closest('li').find('.product-visual.empty').removeClass('d-none');
1895		$bundleOption.closest('li').find('.product-name').addClass('d-none');
1896		$bundleOption.find(":selected").each(function (index) {
1897			$bundleOption.closest('li').find('#product-visual-' + $(this).val()).removeClass('d-none');
1898			$bundleOption.closest('li').find('#product-name-' + $(this).val()).removeClass('d-none');
1899		});
1900	}
1901	if ($bundleOption.attr('type') == 'select' || $bundleOption.attr('type') == 'radio') {
1902		$bundleOption.closest('li').find('.product-visual').addClass('d-none');
1903		$bundleOption.closest('li').find('#product-visual-' + productIdSelected).removeClass('d-none');
1904		$bundleOption.closest('li').find('.product-name').addClass('d-none');
1905		$bundleOption.closest('li').find('#product-name-' + productIdSelected).removeClass('d-none');
1906	}
1907
1908	updatePrice($bundleOption);
1909	updateSummary($bundleOption);
1910}
1911
1912function updatePrice(target) {
1913	var $formBundleOptions = $(target).closest(".bundle-options").find(globalOptions.productBundleSelector);
1914	var curOptionId = $(target).data("optionid");
1915	var bundlePrice = 0;
1916	var bundleOriginalPrice = 0;
1917	var groupPrice = 0;
1918
1919	for (const field of $formBundleOptions) {
1920		var optionId = getOptionId(field.id);
1921		var $optionObj = $("#" + field.id);
1922		var optionQty = getOptionQty(optionId);
1923
1924		if ($optionObj.children().length > 1) {
1925			// select box
1926			for (const selectedOption of $optionObj.find(":selected")) {
1927				if ($(selectedOption).val() !== "") {
1928					var sOption = $("#bundle-option-" + optionId + "-qty-input").find('option:selected');
1929					if(sOption.attr('data-tierprice') !== undefined){ // if data-tierprice is defined use it
1930						//console.log('data-tierprice found :'+sOption.attr('data-tierprice') );
1931						$(selectedOption).attr('data-price', sOption.attr('data-tierprice') );
1932						$(selectedOption).data('price', sOption.attr('data-tierprice') );
1933					} else {
1934						//console.log('data-tierprice NOT found ');
1935					}
1936					bundlePrice = bundlePrice + parseFloat($(selectedOption).data("price")) * parseInt(optionQty);
1937					bundleOriginalPrice = bundleOriginalPrice + parseFloat($(selectedOption).data("original-price")) * parseInt(optionQty);
1938					if (curOptionId == optionId) { groupPrice = groupPrice + parseFloat($(selectedOption).data("price")) * parseInt(optionQty); }
1939				}
1940			}
1941		}
1942		else {
1943			if ($optionObj.prop("checked")) {
1944				var sOption = $("#bundle-option-" + optionId + "-qty-input").find('option:selected');
1945				if(sOption.attr('data-tierprice') !== undefined){ // if data-tierprice is defined use it
1946					//console.log('data-tierprice found 2:'+sOption.attr('data-tierprice') );
1947					$optionObj.attr('data-price', sOption.attr('data-tierprice') );
1948					$optionObj.data('price', sOption.attr('data-tierprice'));
1949				} else {
1950					//console.log('data-tierprice 2 NOT found ');
1951				}
1952				bundlePrice = bundlePrice + parseFloat($optionObj.data("price")) * parseInt(optionQty);
1953				bundleOriginalPrice = bundleOriginalPrice + parseFloat($optionObj.data("original-price")) * parseInt(optionQty);
1954				if (curOptionId == optionId) { groupPrice = groupPrice + parseFloat($optionObj.data("price")) * parseInt(optionQty); }
1955			}
1956		}
1957	}
1958
1959	// display updated total price of bundle in : bundle panel footer, subnav_entries_buy and main price pdp
1960	var varnishBlocker = Math.random();
1961	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" };
1962	jQuery(".product-info .product-price").attr('data-numeric-price', bundlePrice);
1963	if (bundlePrice <= bundleOriginalPrice && bundleOriginalPrice > 0) {
1964		jQuery(".product-info .product-price").attr('data-original-price', bundleOriginalPrice);
1965
1966		ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: bundlePrice,specificFormat:'sup' };
1967		ajaxR.success = function (data, status, xhr) {
1968			//$('.product-info .product-price span.product-new__item__action del').html(data.formattedPrice);
1969			$('.product-info .product-price').html('<strong>'+data.formattedPrice+'</strong>');
1970		};
1971		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1972			console.log(jqXHR);
1973			console.log(textStatus);
1974			console.log(errorThrown);
1975		};
1976		jQuery.ajax(ajaxR);
1977	} else {
1978		//$('.product-info .product-price span.product-new__item__action del').text("");
1979		//$('.product-info .product-price').text("");
1980	}
1981	loadOney();
1982	ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: bundlePrice};
1983	ajaxR.success = function (data, status, xhr) {
1984		target.closest(".product-perso").find(".perso-footer .product-price").html(data.formattedPrice); //bundlePrice.toFixed(2)
1985		target.closest(".product-perso").find(".perso-footer span.product-new__item__action").addClass('d-none'); // hide old price when starting config
1986		$('.subnav_entries_buy .price').html(data.formattedPrice);
1987		$('.product-info .product-price .price').html(data.formattedPrice);
1988		//$('.product-info .product-price span.product-new__item__action').addClass('d-none'); // hide old price when starting config
1989		$(globalOptions.priceStartingFromSelector).addClass('d-none');
1990
1991	};
1992	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
1993		console.log(jqXHR);
1994		console.log(textStatus);
1995		console.log(errorThrown);
1996	};
1997	jQuery.ajax(ajaxR);
1998
1999	// display price of option updated in bundle panel next to the option (if only one option is passed in param of the function)
2000	if (target.length == 1) {
2001		varnishBlocker = Math.random();
2002		ajaxG = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" };
2003		ajaxG.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: groupPrice };
2004		ajaxG.success = function (data, status, xhr) {
2005			target.closest("li").find(".product-price").html(data.formattedPrice); //bundlePrice.toFixed(2)
2006		};
2007		ajaxG.error = function (jqXHR, textStatus, errorThrown) {
2008			console.log(jqXHR);
2009			console.log(textStatus);
2010			console.log(errorThrown);
2011		};
2012		jQuery.ajax(ajaxG);
2013	}
2014}
2015
2016function updateSummary(target) {
2017	var $formBundleOptions = $(target).closest(".bundle-options").find(globalOptions.productBundleSelector);
2018	var bundleSummary = "";
2019	var configIssue = false;
2020	var groupOptions = {};
2021
2022	for (const field of $formBundleOptions) {
2023		var optionId = getOptionId(field.id);
2024		var $optionObj = $("#" + field.id);
2025		var optionQty = getOptionQty(optionId);
2026		var optionRequired = getOptionRequired(optionId);
2027		var hasChoice = false;
2028
2029
2030		if ($optionObj.children().length > 1 || $optionObj.prop("checked")) {
2031			if (field.value != "") {
2032				hasChoice = true;
2033				if (optionQty > 0 && bundleSummary.indexOf($optionObj.closest(".product-infos").find(".product-title").html()) == -1) { bundleSummary = bundleSummary + "<li><strong>" + $optionObj.closest(".product-infos").find(".product-title").html() + ":</strong><br/>"; }
2034			}
2035		}
2036
2037		if ($optionObj.children().length > 1) {
2038			for (const selectedOption of $optionObj.find(":selected")) {
2039				if ($(selectedOption).val() !== "") {
2040					if (optionQty > 0) { bundleSummary = bundleSummary + "" + optionQty + "x " + $(selectedOption).data("option-name") + "<br/>"; }
2041				}
2042			}
2043		}
2044		else if ($optionObj.prop("checked")) {
2045			if (optionQty > 0) { bundleSummary = bundleSummary + "" + optionQty + "x " + $optionObj.data("option-name") + "<br/>"; }
2046		}
2047
2048		if ($optionObj.children().length > 1 || $optionObj.prop("checked")) {
2049			if (field.value != "") {
2050				if (optionQty > 0) { bundleSummary = bundleSummary + "</li>"; }
2051			}
2052		}
2053
2054		if ((optionRequired == "1" || optionRequired == "required") && ($optionObj.attr("type") == "radio" || $optionObj.attr("type") == "checkbox")) {
2055			if (groupOptions.hasOwnProperty(optionId)) {
2056				groupOptions[optionId]["hasChoice"] = groupOptions[optionId]["hasChoice"] || hasChoice;
2057			} else {
2058				groupOptions[optionId] = { obj: $optionObj, hasChoice: hasChoice };
2059			}
2060		}
2061
2062		if ((optionRequired == "1" || optionRequired == "required") && !hasChoice && $optionObj.attr("type") !== "radio" && $optionObj.attr("type") !== "checkbox") {
2063			configIssue = configIssue || true;
2064			$optionObj.closest(".product-infos").find(".product-message").removeClass("d-none");
2065		} else {
2066			$optionObj.closest(".product-infos").find(".product-message").addClass("d-none");
2067		}
2068	}
2069
2070	for (var rad in groupOptions) {
2071		if (!groupOptions[rad].hasChoice) {
2072			configIssue = configIssue || true;
2073			groupOptions[rad].obj.closest(".product-infos").find(".product-message").removeClass("d-none");
2074		} else {
2075			groupOptions[rad].obj.closest(".product-infos").find(".product-message").addClass("d-none");
2076		}
2077	}
2078
2079	if (configIssue) {
2080		$(globalOptions.btnAddToCartBundleAsidePanelSelector).addClass("disabled");
2081		$(".perso-footer .error-message").removeClass("d-none");
2082	} else {
2083		$(globalOptions.btnAddToCartBundleAsidePanelSelector).removeClass("disabled");
2084		$(".perso-footer .error-message").addClass("d-none");
2085	}
2086	target.closest(".product-perso").find(".bundleSummary ul").html(bundleSummary);
2087}
2088
2089function getClosedBundleSummary(bundleOptions, extendedBundleOptions) {
2090	htmlSummary = "";
2091
2092	htmlSummary += "<ul>";
2093	for (const option of bundleOptions) {
2094		if (option.required) {
2095			htmlSummary += "<li data-option-id='" + option.option_id + "'><strong>" + option.title + " : </strong>";
2096			for (const productOption of option.product_links) {
2097				htmlSummary += "<div class='product-option' data-product-option-id='" + productOption.id + "'>" + productOption.qty + " x " + extendedBundleOptions[option.option_id][productOption.id].name + " <span></span></div>";
2098				/* varnishBlocker =  Math.random();
2099				var ajaxR = {dataType:"json", url:"/ecommerce/ajax.cfc?_="+varnishBlocker ,method:"GET"};
2100				ajaxR.data = {method:"formatPrice",sitename:pageSitename,language:pageLanguage,price:productOption.price};
2101				ajaxR.success = function(data, status, xhr) {
2102					htmlSummary += data.formattedPrice;
2103					$('.bundle-summary li[data-option-id=' + option.option_id + '] .product-option[data-product-option-id=' + productOption.id + '] span').html(data.formattedPrice);
2104				};
2105				ajaxR.error = function(jqXHR, textStatus, errorThrown){
2106					console.log(jqXHR);
2107					console.log(textStatus);
2108					console.log(errorThrown);
2109				};
2110				jQuery.ajax(ajaxR); */
2111			}
2112			htmlSummary += "</li>";
2113		}
2114	}
2115	htmlSummary += "</ul>";
2116
2117	return htmlSummary;
2118}
2119
2120function updateAvailability() {
2121
2122}
2123
2124function getOptionId(fieldId) {
2125	var optionId = fieldId.split('-')[2]; /* fieldId format: bundle-option-[optionId]-[id] */
2126	return optionId;
2127}
2128
2129function getOptionQty(optionId) {
2130	return $("#bundle-option-" + optionId + "-qty-input").val();
2131}
2132function getOptionRequired(optionId) {
2133	return $("#bundle-option-" + optionId + "-qty-input").attr("item-required");
2134}
2135
2136function loadOney() {
2137	if (jQuery("#oney-buttons").length != 0) {
2138		var varnishBlocker = Math.random();
2139		var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" }; //
2140		var priceForSimulation = jQuery(".product-actions .product-price").attr('data-numeric-price') * $('#product-qty').val();
2141		$('#oney-price').html(Math.round(priceForSimulation * 100) / 100);
2142		ajaxR.data = { method: "getOneyPrices", sitename: pageSitename, price: priceForSimulation, language: pageLanguage };
2143		if (isV6) ajaxR.data.version = 'v6';
2144		ajaxR.success = function (data, status, xhr) {
2145			onLoadEventHandler("success ajax loadCart");
2146			$(document).ready(function () {
2147				var htmlButtons = data.HTMLBUTTONS;
2148				var contents = data.CONTENTS;
2149				var jsonData = data.JSON;
2150				function hasDownPaymentAmount(obj) {
2151					return obj?.simulation?.down_payment_amount !== undefined;
2152				}
2153				
2154				
2155				if (contents != '') {
2156					// Loop over jsonData.JSON and test each object
2157					jsonData.forEach(function(obj, index) {
2158						if (hasDownPaymentAmount(obj)) {
2159							if(index == 0){
2160								jQuery('strong.oney3times').html('&nbsp;'+ getFormattedPrice(obj.simulation.down_payment_amount));
2161								jQuery('.oney3times').show();
2162							}
2163							if(index == 1){
2164								jQuery('strong.oney4times').html('&nbsp;'+ getFormattedPrice(obj.simulation.down_payment_amount));
2165								jQuery('.oney4times').show();
2166							}
2167						}
2168					});
2169					jQuery("#oney-buttons").html(htmlButtons);
2170					jQuery("#oney-contents").html(contents);
2171					jQuery(".product-info .vcentered").removeClass('vcentered');
2172					jQuery(".product-info .oney").addClass('d-none');
2173					jQuery(".product-info .oney").last().removeClass('d-none');
2174					try { window.somfy.instantiateBlocIfNecessary(window.somfy.els.$asidePanel, AsidePanel); } catch (err) { }
2175				} else {
2176					jQuery(".product-info .oney").addClass('d-none');
2177					if (jQuery(".product-info .product-new__item__start-from.w-100.mb-0").length == 0) {
2178						jQuery(".product-info .oney").prev().addClass('vcentered');
2179					}
2180				}
2181			});
2182		};
2183		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2184			console.log(jqXHR);
2185			console.log(textStatus);
2186			console.log(errorThrown);
2187		};
2188		jQuery.ajax(ajaxR);
2189	}
2190}
2191
2192function getFormattedPrice( price) {
2193	var formatedPrice = '';
2194	var varnishBlocker = Math.random();
2195	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" , async: false }; //
2196	ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: price };
2197	ajaxR.success = function (data, status, xhr) {
2198		formatedPrice = data.formattedPrice ; 
2199	};
2200	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2201		console.log(jqXHR);
2202		console.log(textStatus);
2203		console.log(errorThrown);
2204	};
2205	jQuery.ajax(ajaxR);
2206	return formatedPrice;
2207}
2208
2209/*On PDP change displayed price if tier price is available */
2210function onChangeTierPrice() {
2211	var varnishBlocker = Math.random();
2212	var _price  =  $('#product-qty').find(':selected').attr('data-tierprice');
2213	var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" }; //
2214	$('.product-main-info .product_price').attr('data-numeric-price', _price );
2215	ajaxR.data = { method: "formatPrice", sitename: pageSitename, language: pageLanguage, price: _price };
2216	ajaxR.success = function (data, status, xhr) {
2217		$('.product-main-info .product_price').find('.price').html(data.formattedPrice);
2218		$('.pdp .nav-bar-wrapper .product-price').find('strong').html(data.formattedPrice);
2219		$('.pdp .sticky-bar-mobile .product-price').find('strong').html(data.formattedPrice);
2220	};
2221	ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2222		console.log(jqXHR);
2223		console.log(textStatus);
2224		console.log(errorThrown);
2225	};
2226	jQuery.ajax(ajaxR);
2227}
2228
2229var reviewData = new Array();
2230var reviewAggs = new Array();
2231
2232function initReviews() {
2233	var varnishBlocker = Math.random();
2234	var sku = $('.product-main-info .mainBuyButton').data("product-sku");
2235	if($('.product-main-info .mainBuyButton').length == 0 && (typeof sfy_product_reference !== 'undefined')) {
2236		sku = sfy_product_reference;
2237	}
2238	if(sku) {
2239		var ajaxR = { dataType: "json", url: "/eCatalogue/ajax.cfc?_=" + varnishBlocker, method: "GET" }; //
2240		ajaxR.data = { method: "getProductReviews", sitename: pageSitename, language: pageLanguage, sku: sku };
2241		ajaxR.success = function (data, status, xhr) {
2242			reviewData = data.items;
2243			reviewData.sort(function (a, b) {
2244				return b.rating - a.rating  || new Date(b.createdAt) - new Date(a.createdAt);
2245			  });
2246			initReviewAggs(reviewData);
2247			showReviews();
2248		};
2249		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2250			console.log(jqXHR);
2251			console.log(textStatus);
2252			console.log(errorThrown);
2253		};
2254		jQuery.ajax(ajaxR);
2255
2256		jQuery("[name='reviews-sort']").on( "change",function() {
2257			showReviews();
2258		});
2259		jQuery("[name='reviews-reset']").on( "click",function() {
2260			showReviews();
2261		});
2262	}
2263
2264	// load service reviews for footer
2265	if($(".footer-infos .grade").length > 0) {
2266		var ajaxR = { dataType: "json", url: "/eCatalogue/ajax.cfc?_=" + varnishBlocker, method: "GET" }; //
2267		ajaxR.data = { method: "getServiceReviews", sitename: pageSitename, language: pageLanguage };
2268		ajaxR.success = function (data, status, xhr) {
2269			//console.log(data);
2270			const totalCount = data["overall"].count;
2271			$(".footer-infos .grade strong").html(data["365days"].rating);
2272	
2273			const rating = Math.round((parseFloat(data["365days"].rating) || 0) * 10) / 10;
2274
2275			$(".footer-infos .stars-new .star").each(function (index) {
2276				const starIndex = index + 1;
2277				let nbPart = 0;
2278
2279				if (starIndex <= Math.floor(rating)) {
2280					nbPart = 10;
2281				} else if (starIndex === Math.floor(rating) + 1) {
2282					nbPart = Math.round((rating - Math.floor(rating)) * 10);
2283				}
2284
2285				$(this).removeClass(function (i, className) {
2286					return (className.match(/(^|\s)-part-\d+/g) || []).join(" ");
2287				}).addClass("-part-" + nbPart);
2288			});
2289
2290			$(".footer-infos p.customer-reviews").prepend(totalCount.toLocaleStr
2290ing("fr-FR")+ " ");
2291		};
2292		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2293			console.log(jqXHR);
2294			console.log(textStatus);
2295			console.log(errorThrown);
2296		};
2297		jQuery.ajax(ajaxR);
2298	}
2299}
2300
2301function renderReviews(arrayReviews, total, pageSize = 5, from = 0) {
2302	var varnishBlocker = Math.random();
2303
2304	if(arrayReviews) {
2305		var pagination = {nbResults: total, displayedResults: pageSize, from: from};
2306		var ajaxR = { dataType: "json", url: "/eCatalogue/ajax.cfc?_=" + varnishBlocker, method: "POST" }; //
2307		ajaxR.data = { method: "renderProductReviews", sitename: pageSitename, language: pageLanguage, reviewData: JSON.stringify(arrayReviews), paginationData: JSON.stringify(pagination) };
2308		ajaxR.success = function (data, status, xhr) {
2309			$('#pdp-reviews .reviews-wrapper').html(data.html);
2310			$(".content-loader").hide();
2311
2312			// insert structured data review into structured data product 
2313			let countUsers = 1;
2314			const structuredDataReviews = arrayReviews.map(r => {
2315				let title = r.title?.trim();
2316				const comment = r.comment?.replace(/[\r\n\t]+/g, ' ').trim();
2317				let reviewBody = "";
2318
2319				if(title && comment) {
2320					if(title.endsWith("...")) {
2321						title = title.slice(0, -3);
2322					}
2323
2324					if (comment.startsWith(title)) {
2325						reviewBody = comment;
2326					} else {
2327						reviewBody = `${title} — ${comment}`;
2328					}
2329				} else if(title && !comment) {
2330					reviewBody = title;
2331				} else if(!title && comment) {
2332					reviewBody = comment;
2333				}
2334
2335				reviewBody = reviewBody.replace(/\s+/g, ' ').trim();
2336								
2337				return {
2338					"@type": "Review",
2339					"author": { "@type": "Person", "name": "User "+countUsers++ },
2340					"datePublished": r.createdAt,
2341					...(reviewBody ? { "reviewBody": reviewBody } : {}), // don't define reviewBody if empty
2342					"reviewRating": {
2343						"@type": "Rating",
2344						"ratingValue": r.rating,
2345						"bestRating": 5
2346					}
2347				}
2348			});
2349
2350			//insert reviews of the current page of the reviews in the structured data Product
2351			const structuredDataProduct = document.getElementById('structured-data-product');
2352			if(structuredDataProduct) {
2353				const structStructuredDataProduct = JSON.parse(structuredDataProduct.text);
2354				structStructuredDataProduct["review"] = structuredDataReviews;
2355				console.log(structStructuredDataProduct);
2356				const structuredDataProductWithReviews = JSON.stringify(structStructuredDataProduct);
2357				structuredDataProduct.text = structuredDataProductWithReviews;
2358			}
2359
2360			/*const structuredDataReviewsScriptId = 'structured-reviews-jsonld';
2361
2362			// remove old <script> for structured data reviews when changing reviews page
2363			const oldScriptStructuredDataReviews = document.getElementById(structuredDataReviewsScriptId);
2364			if (oldScriptStructuredDataReviews) oldScriptStructuredDataReviews.remove();
2365
2366			const script = document.createElement('script');
2367			script.type = 'application/ld+json';
2368			script.id = structuredDataReviewsScriptId;
2369			script.text = JSON.stringify({ "@context": "https://schema.org", "@type": "Product", "review": structuredDataReviews });
2370			document.head.appendChild(script);*/
2371		};
2372		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2373			console.log(jqXHR);
2374			console.log(textStatus);
2375			console.log(errorThrown);
2376			$(".content-loader").hide();
2377		};
2378		$(".content-loader").show();
2379		jQuery.ajax(ajaxR);
2380	}
2381}
2382
2383function initReviewAggs(data) {
2384	reviewAggs = data.reduce((aggs, review) => {
2385		// get the value of both the keys
2386		const aggValue = review["rating"];
2387
2388		// if there is already a key present
2389		// merge its value
2390		if(aggs[aggValue]) {
2391			aggs[aggValue] += 1
2392		}
2393		// create a new entry on the key
2394		else{
2395			aggs[aggValue] = 1;
2396		}
2397
2398		// return the aggregation
2399		return aggs;
2400	}, {});
2401
2402	const totalReviews = data.length;
2403	// $('#pdp-reviews .pdp-reviews-summary').data("ratingcount");
2404	// update HTML here
2405	for (var a in reviewAggs) {
2406		$('#pdp-reviews span.ratingCount'+ a).html("(" + reviewAggs[a] +")");
2407		$('#pdp-reviews span.ranking-percent'+ a).html(Math.round(reviewAggs[a]*100/totalReviews)+"%");
2408		$('#pdp-reviews span.ranking-percent'+ a).prev(".ranking-bar").css("--value",Math.round(reviewAggs[a]*100/totalReviews)+'');
2409	}
2410}
2411
2412function showReviews(from = 0) {
2413	var displayedReviews = new Array();
2414	var pageSize = 5;
2415	var limit = pageSize + from;
2416
2417	var filteredReviews = new Array();
2418
2419	// filter reviews without content
2420	filteredReviews = jQuery.grep(reviewData, function(rw) {
2421		return (typeof rw.title !== "undefined" && rw.title.trim() != "");
2422	});
2423
2424	var selectedGrades = jQuery("[name='reviews-sort']").val();
2425	if(selectedGrades.length > 0) {
2426		switch(selectedGrades) {
2427			case "top_review":{
2428				filteredReviews = reviewData.sort(function (a, b) {
2429					return b.rating - a.rating || new Date(b.createdAt) - new Date(a.createdAt);
2430				  });
2431				
2432				break;
2433			}
2434			case "bad_review":{
2435				filteredReviews = reviewData.sort(function (a, b) {
2436					return a.rating - b.rating || new Date(b.createdAt) - new Date(a.createdAt);
2437				  });
2438				break;
2439			}
2440			case "recent_review":{
2441				filteredReviews = reviewData.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt) || b.rating - a.rating);
2442				break;
2443			}
2444			case "old_review":{
2445				filteredReviews = reviewData.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt) || b.rating - a.rating);
2446				break;
2447			}
2448		}
2449		/*filteredReviews = jQuery.grep(filteredReviews, function(rw) {
2450			return (selectedGrades.indexOf(String(rw.rating)) >= 0);
2451		});*/
2452	}
2453
2454	if(filteredReviews.length < limit) limit = filteredReviews.length;
2455
2456	for (var i = from; i < limit; i++) {
2457		displayedReviews.push(filteredReviews[i]);
2458	}
2459
2460	renderReviews(displayedReviews, filteredReviews.length, pageSize, from);
2461}
2462
2463
2464function loadSplittedPrice() {
2465	if (jQuery("#split4payment").length != 0 && !(jQuery("#split4payment").hasClass('isloaded'))) {
2466		var varnishBlocker = Math.random();
2467		var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" }; //
2468		var priceForSimulation = jQuery(".product-prise-group .product-price").attr('data-numeric-price');
2469		ajaxR.data = { method: "getSplit4Price", sitename: pageSitename, price: priceForSimulation, language: pageLanguage };
2470		if (isV6) ajaxR.data.version = 'v6';
2471		ajaxR.success = function (data, status, xhr) {
2472			$(document).ready(function () {
2473				console.log('getSplit4Price', data);
2474				if(priceForSimulation !== undefined && priceForSimulation > 0 && data.message !== '')  {
2475					jQuery("#split4payment").html(data.message);
2476					jQuery("#split4payment").addClass('isloaded');
2477				}else{
2478					jQuery("#split4payment").hide();
2479				}
2480			});
2481		};
2482		ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2483			console.log(jqXHR);
2484			console.log(textStatus);
2485			console.log(errorThrown);
2486		};
2487		jQuery.ajax(ajaxR);
2488	}
2489}
2490
2491function loadPercentSaving(_data) {
2492	if (jQuery("#percent_saved").length != 0  && !(jQuery("#percent_saved").hasClass('isloaded')) ) {
2493		//console.log(_data);
2494		var varnishBlocker = Math.random();
2495		var ajaxR = { dataType: "json", url: "/ecommerce/ajax.cfc?_=" + varnishBlocker, method: "GET" }; //
2496		var priceEcommerce = jQuery(".product-prise-group .product-price").attr('data-numeric-price');
2497		var pId = jQuery(".product-prise-group .product-price").attr('data-m-product-id');
2498
2499		if (_data && _data[pId]) { 
2500			var oldPrice = (typeof _data[pId].originalPrice !== "undefined") ? _data[pId].originalPrice : null;
2501
2502			if(_data[pId].hasNewPrice !== true) {// don't show the percent saving if the price is custom (defined by a message) or the product has the productsWithNewPriceLabel config
2503				//jQuery("#percent_saved").addClass('d-none');
2504				if(	priceEcommerce !== undefined && priceEcommerce != null &&  priceEcommerce > 0 && 
2505					oldPrice !== undefined && oldPrice != null &&  oldPrice > 0 && 
2506					oldPrice > priceEcommerce) {
2507					
2508					ajaxR.data = { method: "loadPercentSaving", sitename: pageSitename, priceEcommerce: priceEcommerce, oldPrice: oldPrice, language: pageLanguage };
2509				
2510					if (isV6) ajaxR.data.version = 'v6';
2511					ajaxR.success = function (data, status, xhr) {
2512						$(document).ready(function () {
2513							//console.log('loadPercentSaving', data);
2514							if(	 data.message !== '')  {
2515								jQuery("#percent_saved").html(data.message);
2516								jQuery("#percent_saved").addClass('isloaded');
2517								jQuery("#percent_saved").removeClass('d-none');	
2518							} else {
2519								jQuery("#percent_saved").addClass('d-none');
2520							}
2521						});
2522					};
2523					ajaxR.error = function (jqXHR, textStatus, errorThrown) {
2524						console.log(jqXHR);
2525						console.log(textStatus);
2526						console.log(errorThrown);
2527					};
2528					jQuery.ajax(ajaxR);
2529				}
2530		
2531				// show original price if originalPrice is greater than current price ("Prix le plus bas sur 30 jours 199 €" par exemple)
2532				if(priceEcommerce !== undefined &&  oldPrice !== undefined && !isNaN(priceEcommerce) && !isNaN(oldPrice) && parseFloat(priceEcommerce) < parseFloat(oldPrice)) {
2533					jQuery('.product-main-info .product-price-details .originalprice').removeClass('d-none');
2534				}
2535			}
2536		}
2537	}
2538}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.