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 + ' ' + 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(' '+ getFormattedPrice(obj.simulation.down_payment_amount)); 2161 jQuery('.oney3times').show(); 2162 } 2163 if(index == 1){ 2164 jQuery('strong.oney4times').html(' '+ 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.