1var combinedPurchaseJS = []; 2 3/** 4 * Configurações de atributos necessárias para a execução do combined purchase na loja 5 * 6 * @var Object 7 */ 8const combinedPurchaseSettings = { 9 combinedPurchaseContainer: "[combinedPurchaseContainer]", 10 combinedPurchaseContainerCss: "combined-purchase", 11 productAttribute: "product-attribute", 12 mainProductContainer: "[combinedPurchaseMainProduct]", 13 carouselContainer: ".combined-purchase__carousel", 14 pricesContainer: "[combinedPurchasePrices]", 15 finalPrice: "[combinedPurchaseFinalPrice]", 16 installments: "[buyTogheterInstallments]", 17 productsJson: "#skuProducts", 18 mainProduct: "mainProduct", 19 productCarousel: "productCarousel", 20 imageItemCss: "combined-purchase__image", 21 optionItemCss: "combined-purchase__option", 22 sizeContainerItemCss: "combined-purchase__size-container", 23 sizeItemCss: "combined-purchase__size", 24 buyButton: "[combinedPurchaseBuyButton]", 25 buyButtonDisabled: "[combinedPurchaseBuyDisabledButton]", 26 buyButtonCss: "combined-purchase__buy-button", 27 sizeType: "div", 28 showUnitsOutOfStock: true, 29 installmentsNumber: 6, 30}; 31 32/** 33 * Inicializa o combined purchase, pegando o Json inserido no código a partir do atributo "productsJson" 34 * 35 * @returns void 36 */ 37combinedPurchaseJS.initilizeCombinedPurchase = function () { 38 let productsJson = document.querySelector(combinedPurchaseSettings.productsJson); 39 40 if (!productsJson) { 41 return; 42 } 43 44 productsJson = productsJson.innerHTML; 45 46 if (!productsJson) { 47 hideProductTogether(); 48 return; 49 } 50 51 productsJson = JSON.parse(productsJson); 52 createCombinedPurchase(productsJson); 53}; 54 55/** 56 * Oculta o compre junto 57 */ 58const hideProductTogether = () => { 59 let combinedPurchaseContainer = document.querySelector(combinedPurchaseSettings.combinedPurchaseContainer); 60 combinedPurchaseContainer.classList.add(`${combinedPurchaseSettings.combinedPurchaseContainerCss}--hidden`); 61}; 62 63/** 64 * Cria o combined purchase, utilizando o array recebido na inicialização 65 * 66 * @param {Array} productsJson 67 */ 68const createCombinedPurchase = (productsJson) => { 69 let products = productsJson.produtos; 70 let productsCombinedPurchase = products.compreJunto; 71 72 if (!productsCombinedPurchase || productsCombinedPurchase.length < 1) { 73 hideProductTogether(); 74 return; 75 } 76 77 generateMainProduct(products); 78 let productsCreated = generateCombinedPurchaseProducts(productsCombinedPurchase); 79 80 if (!productsCreated) { 81 hideProductTogether(); 82 return; 83 } 84 85 initializeCombinedPurchaseCarousel(); 86 getProdutsToAddEvents(); 87 let optionsCombinedPurchase = document.querySelectorAll('.combined-purchase__options-data .combined-purchase__info'); 88 optionsCombinedPurchase.forEach(container => { 89 enableDraggableCombinedPurchase(container); 90 }); 91 92 let sizesCombinedPurchase = document.querySelectorAll('.combined-purchase__sizes-data .combined-purchase__size-container'); 93 sizesCombinedPurchase.forEach(container => { 94 enableDraggableCombinedPurchase(container); 95 }); 96}; 97 98/** 99 * Gera todo o conteúdo do produto principal 100 * 101 * @param {Array} products 102 */ 103const generateMainProduct = (products) => { 104 let productId = Object.keys(products)[0]; 105 let product = products[productId]; 106 let attribute = combinedPurchaseSettings.mainProduct; 107 108 let productHtml = getProductHtml(product, productId, attribute); 109 let productContainer = document.querySelector(combinedPurchaseSettings.mainProductContainer); 110 111 productContainer.innerHTML = productHtml; 112}; 113 114/** 115 * Gera todo o conteudo dos produtos listados em compre junto 116 * 117 * @param {Array} productsCombinedPurchase 118 * @returns {Boolean} retorna se a criação dos produtos foi um sucesso ou não 119 */ 120const generateCombinedPurchaseProducts = (productsCombinedPurchase) => { 121 let attribute = combinedPurchaseSettings.productCarousel; 122 let productContainer = document.querySelector(combinedPurchaseSettings.carouselContainer); 123 124 productsCombinedPurchase.forEach((products) => { 125 let productId = Object.keys(products)[0]; 126 let product = products[productId]; 127 128 let productHtml = getProductHtml(product, productId, attribute); 129
130 productContainer.innerHTML += productHtml; 131 }); 132 133 if (!productContainer) { 134 return false; 135 } 136 137 return true; 138}; 139 140/** 141 * Inicializa o carrossel do compre junto 142 */ 143const initializeCombinedPurchaseCarousel = () => { 144 const productsCarousel = document.querySelector(combinedPurchaseSettings.carouselContainer); 145 146 new Glider(productsCarousel, { 147 slidesToShow: 1, 148 dots: '#dots', 149 draggable: true, 150 arrows: { 151 prev: '.combined-purchase__arrows--left', 152 next: '.combined-purchase__arrows--right' 153 } 154 }); 155 156 productsCarousel.addEventListener(('glider-animated','glider-slide-visible'), function (event) { 157 let products = document.querySelectorAll(`[${combinedPurchaseSettings.productCarousel}-item].active.visible`); 158 159 if (products.length > 0) { 160 clickOnFirstOption(products[0], combinedPurchaseSettings.productCarousel); 161 updateTotalPrice(); 162 } 163 }); 164}; 165 166/** 167 * Atualiza o preço total com base no produto principal e no produto combinado 168 */ 169const updateTotalPrice = () => { 170 let mainProductPrice = document.querySelector(`[${combinedPurchaseSettings.mainProduct}-priceinput]`).value; 171 let combinedProductPrice = document.querySelector(`[${combinedPurchaseSettings.productCarousel}-priceinput]`).value; 172 173 let totalPrice = parseFloat(mainProductPrice) + parseFloat(combinedProductPrice); 174 let finalPriceContainer = document.querySelector(combinedPurchaseSettings.finalPrice); 175 finalPriceContainer.innerHTML = `R$ ${totalPrice.toFixed(2).replace('.', ',')}`; 176}; 177 178/** 179 * Inicializa todos os carrosséis de opções do compre junto 180 */ 181const initializeCombinedPurchaseOptionsCarousel = () => { 182 let carousel = document.querySelector(".combined-purchase__options-data .combined-purchase__info"); 183 184 new Glider(carousel, { 185 slidesToShow: 1, 186 draggable: true, 187 arrows: false, 188 }); 189}; 190 191/** 192 * Inicializa todos os carrosséis de tamanhos do compre junto 193 */ 194const initializeCombinedPurchaseSizeCarousel = () => { 195 let carousel = document.querySelector(".combined-purchase__sizes-data .combined-purchase__size-container"); 196 197 new Glider(carousel, { 198 slidesToShow: 1, 199 draggable: true, 200 arrows: false, 201 }); 202}; 203 204const enableDraggableCombinedPurchase = (element, speed = 2) => { 205 if (!element) { 206 return 207 } 208 let isDragging = false; 209 let startX; 210 let scrollLeft; 211 212 element.addEventListener('mousedown', (e) => { 213 isDragging = true; 214 startX = e.pageX - element.offsetLeft; 215 scrollLeft = element.scrollLeft; 216 element.style.cursor = 'grabbing'; 217 }); 218 219 element.addEventListener('mouseleave', () => { 220 isDragging = false; 221 element.style.cursor = 'grab'; 222 }); 223 224 element.addEventListener('mouseup', () => { 225 isDragging = false; 226 element.style.cursor = 'grab'; 227 }); 228 229 element.addEventListener('mousemove', (e) => { 230 if (!isDragging) return; 231 e.preventDefault(); 232 const x = e.pageX - element.offsetLeft; 233 const walk = (x - startX) * speed; 234 element.scrollLeft = scrollLeft - walk; 235 }); 236} 237 238/** 239 * Clica na primeira opção do produto 240 * 241 * @param {HTMLElement} product 242 * @param {String} attribute 243 */ 244const clickOnFirstOption = (product, attribute) => { 245 if (product) { 246 const options = product.querySelectorAll(`[${attribute}-option]`); 247 const availableOptions = Array.from(options).filter(option => { 248 const stock = option.getAttribute(`${attribute}-stock`); 249 return stock && parseInt(stock) > 0; 250 }); 251 252 if (availableOptions.length > 0) { 253 availableOptions[0].click(); 254 } else if (options.length > 0) { 255 options[0].click(); 256 } 257 } 258}; 259 260/** 261 * Clica no primeiro tamanho que possui estoque 262 * 263 * @param {Array} sizes 264 * @param {String} attribute 265 * @returns 266 */ 267const clickOnFirstSizeInStock = (sizes, attribute) => { 268 let sizeSelected = null; 269
270 sizes.forEach((size) => { 271 let stock = size.getAttribute(`${attribute}-stock`); 272 273 if (stock > 0 && !sizeSelected) { 274 sizeSelected = size; 275 } 276 }); 277 278 if (combinedPurchaseSettings.sizeType == "select") { 279 if (!sizeSelected) { 280 sizeSelected = sizes[0]; 281 } 282 283 let optionSelected = sizeSelected.getAttribute(`${attribute}-option-selected`); 284 let sizeContainer = document.querySelector(`[${attribute}-size-container="${optionSelected}"]`); 285 286 sizeContainer.value = sizeSelected.value; 287 288 sizeContainer.dispatchEvent(new Event("change")); 289 } else { 290 if (!sizeSelected) { 291 sizes[0].click(); 292 return; 293 } 294 295 sizeSelected.click(); 296 } 297}; 298 299/** 300 * Adiciona a primeira imagem no seu respectivo produto 301 * 302 * @param {String} productId 303 * @param {String} attribute 304 */ 305const addFirstImageToProduct = (productId, attribute) => { 306 let item = document.querySelector(`[${attribute}-item="${productId}"]`); 307 let imageContainer = document.querySelector(`[${attribute}-image-container="${productId}"]`); 308 309 let image = item.querySelector(`[${attribute}-image]`); 310 311 if (!image) { 312 return; 313 } 314 315 imageContainer.innerHTML = image.innerHTML; 316}; 317 318/** 319 * Busca os produtos para adicionar os event listeners 320 */ 321const getProdutsToAddEvents = () => { 322 let products = document.querySelectorAll(`[${combinedPurchaseSettings.productAttribute}]`); 323 324 products.forEach((product) => { 325 let attribute = product.getAttribute(combinedPurchaseSettings.productAttribute); 326 let productId = product.getAttribute(`${attribute}-item`); 327 328 addFirstImageToProduct(productId, attribute); 329 addEventsToProduct(productId, attribute); 330 }); 331 332 let mainProduct = document.querySelector(`[${combinedPurchaseSettings.mainProduct}-item]`); 333 clickOnFirstOption(mainProduct, combinedPurchaseSettings.mainProduct); 334 335 let productCarousel = document.querySelector(`[${combinedPurchaseSettings.productCarousel}-item]`); 336 clickOnFirstOption(productCarousel, combinedPurchaseSettings.productCarousel); 337}; 338 339/** 340 * Adiciona todos os eventos de clique ao respectivo produto 341 * 342 * @param {String} productId 343 * @param {String} attribute 344 */ 345const addEventsToProduct = (productId, attribute) => { 346 let item = document.querySelector(`[${attribute}-item="${productId}"]`); 347 let imageContainer = document.querySelector(`[${attribute}-image-container="${productId}"]`); 348 let options = item.querySelectorAll(`[${attribute}-option]`); 349 let sizes = item.querySelectorAll(`[${attribute}-size]`); 350 351 let allOptions = document.querySelectorAll(`[${attribute}-option]`); 352 let allSizes = document.querySelectorAll(`[${attribute}-size]`); 353 let allSizesContainer = document.querySelectorAll(`[${attribute}-size-container]`); 354 355 options.forEach((option) => { 356 option.addEventListener("click", (optionClicked) => { 357 let optionAttributeValue = optionClicked.target.getAttribute(`${attribute}-option`); 358 359 allOptions.forEach((optionNotClicked) => { 360 optionNotClicked.classList.remove(`${combinedPurchaseSettings.optionItemCss}--active`); 361 }); 362 363 allSizesContainer.forEach((sizeData) => { 364 sizeData.classList.remove(`${combinedPurchaseSettings.sizeContainerItemCss}--active`); 365 }); 366 367 optionClicked.target.classList.add(`${combinedPurchaseSettings.optionItemCss}--active`); 368 369 let image = item.querySelector(`[${attribute}-image="${optionAttributeValue}"]`); 370 371 if (image) { 372 imageContainer.innerHTML = image.innerHTML; 373 } 374 375 let sizeContainer = item.querySelector(`[${attribute}-size-container="${optionAttributeValue}"]`); 376 sizeContainer.classList.add(`${combinedPurchaseSettings.sizeContainerItemCss}--active`); 377 378 let sizes = sizeContainer.querySelectorAll(`[${attribute}-size]`); 379 clickOnFirstSizeInStock(sizes, attribute); 380 381 updateTotalPrice(); 382 383 optionClicked.preventDefault(); 384 }); 385 }); 386 387 if (combinedPurchaseSettings.sizeType == "select") { 388 allSizesContainer.forEach((sizeContainer) => { 389 sizeContainer.addEventListener("change", (sizeContainerChanged) => { 390 let sizeValue = sizeContainerChanged.target.value; 391 let sizeClicked = document.querySelector(`[${attribute}-size="${sizeValue}"]`); 392 let price = sizeClicked.getAttribute(`${attribute}-price`); 393 addProductToForm(sizeClicked, attribute); 394 getPrice(price, attribute); 395 checkBuyButtonEnabled(); 396 397 sizeContainerChanged.preventDefault(); 398 }); 399 });
400 } else { 401 sizes.forEach((size) => { 402 size.addEventListener("click", (sizeClicked) => { 403 allSizes.forEach((sizeData) => { 404 sizeData.classList.remove(`${combinedPurchaseSettings.sizeItemCss}--active`); 405 }); 406 407 sizeClicked.target.classList.add(`${combinedPurchaseSettings.sizeItemCss}--active`); 408 409 let price = sizeClicked.target.getAttribute(`${attribute}-price`); 410 addProductToForm(sizeClicked.target, attribute); 411 getPrice(price, attribute); 412 checkBuyButtonEnabled(); 413 414 sizeClicked.preventDefault(); 415 }); 416 }); 417 } 418}; 419 420/** 421 * Adiciona dados do produto no form do compre junto 422 * 423 * @param {HTMLElement} sizeHtml 424 * @param {String} attribute 425 */ 426const addProductToForm = (sizeHtml, attribute) => { 427 let productIds = sizeHtml.getAttribute(`${attribute}-size`); 428 let inputFormContainer = document.querySelector(`[${attribute}-form]`); 429 let inputName = inputFormContainer.getAttribute(`${attribute}-form`); 430 let stock = sizeHtml.getAttribute(`${attribute}-stock`); 431 let [product, option, size] = productIds.split("-"); 432 433 let html = ` 434 <input type="hidden" name="produto${inputName}" value="${product}"> 435 <input type="hidden" name="opcao${inputName}" value="${option}"> 436 <input type="hidden" name="tamanho${inputName}" value="${size}"> 437 <span combinedpurchase-stock-data="${stock}"></span> 438 `; 439 440 inputFormContainer.innerHTML = html; 441}; 442 443/** 444 * Verifica se o botão de compra vai estar ativo ou não a partir do estoque dos produtos 445 */ 446const checkBuyButtonEnabled = () => { 447 let stocks = document.querySelectorAll(`[combinedpurchase-stock-data]`); 448 let buyButton = document.querySelector(combinedPurchaseSettings.buyButton); 449 let buyButtonDisabled = document.querySelector(combinedPurchaseSettings.buyButtonDisabled); 450 let buttonEnabled = true; 451 452 if (!stocks) { 453 return; 454 } 455 456 stocks.forEach((stock) => { 457 let quantity = stock.getAttribute(`combinedpurchase-stock-data`); 458 459 if (quantity < 1) { 460 buttonEnabled = false; 461 } 462 }); 463 464 if (!buttonEnabled) { 465 buyButton.classList.add(`${combinedPurchaseSettings.buyButtonCss}--hidden`); 466 buyButtonDisabled.classList.remove(`${combinedPurchaseSettings.buyButtonCss}--hidden`); 467 } else { 468 buyButton.classList.remove(`${combinedPurchaseSettings.buyButtonCss}--hidden`); 469 buyButtonDisabled.classList.add(`${combinedPurchaseSettings.buyButtonCss}--hidden`); 470 } 471}; 472 473/** 474 * Recebe o valor do produto e adiciona no input correspondente 475 * 476 * @param {String} priceString 477 * @param {String} attribute 478 */ 479const getPrice = (priceString, attribute) => { 480 let price = priceString.replace("R$ ", "").replace(".", "").replace(",", "."); 481 let priceInput = document.querySelector(`[${attribute}-priceinput]`); 482 priceInput.setAttribute("value", price); 483 484 calculateFinalPrice(); 485}; 486 487/** 488 * Calcula o preço final do compre junto e apresenta ao usuário 489 */ 490const calculateFinalPrice = () => { 491 let mainProductPrice = document.querySelector(`[${combinedPurchaseSettings.mainProduct}-priceinput]`); 492 let combinedPurchasePrice = document.querySelector(`[${combinedPurchaseSettings.productCarousel}-priceinput]`); 493 494 let finalPriceContainer = document.querySelector(combinedPurchaseSettings.finalPrice); 495 let installmentsContainer = document.querySelector(combinedPurchaseSettings.installments); 496 497 mainProductPrice = parseFloat(mainProductPrice.value); 498 combinedPurchasePrice = parseFloat(combinedPurchasePrice.value); 499 500 let finalPrice = mainProductPrice + combinedPurchasePrice; 501 finalPrice = finalPrice.toFixed(2); 502 503 let installments = finalPrice / combinedPurchaseSettings.installmentsNumber; 504 installments = installments.toFixed(2); 505 506 let finalPriceString = "R$ " + finalPrice.replace(".", ","); 507 let installmentsString = "R$ " + installments.replace(".", ","); 508 509 finalPriceContainer.innerHTML = finalPriceString; 510 installmentsContainer.innerHTML = installmentsString; 511}; 512 513/** 514 * Calcula o estoque total disponÃvel para uma opção especÃfica de produto. 515 * 516 * @param {Object} units - Um objeto contendo as unidades do produto, onde cada unidade possui informações como estoque e opção. 517 * @param {String} optionId - O ID da opção para a qual o estoque total deve ser calculado. 518 * @returns {Number} O estoque total disponÃvel para a opção especificada. 519 */ 520const getTotalStockForOption = (units, optionId) => { 521 return Object.values(units).reduce((total, unit) => { 522 if (unit.opcao.id === optionId) { 523 return total + parseInt(unit.estoque, 10); 524 } 525 return total; 526 }, 0); 527}; 528 529/** 530 * Gera todo o código HTML do respectivo produto 531 * 532 * @param {Object} product 533 * @param {String} productId 534 * @param {String} attribute 535 * @returns 536 */ 537const getProductHtml = (product, productId, attribute, atributeDiscount) => { 538 const url = document.querySelector("#urlsite").value; 539 540 let units = product.unidades; 541 542 let unitsIds = Object.keys(units); 543 let unitsOptions = []; 544 let unitsSizes = []; 545 546 unitsIds.forEach(function (unitId) { 547 if ( 548 !combinedPurchaseSettings.showUnitsOutOfStock && 549 units[unitId].estoque < 1 550 ) { 551 return; 552 } 553 554 let splittedUnitId = unitId.split("/"); 555 let option = splittedUnitId[0]; 556 let size = splittedUnitId[1]; 557 558 if (!unitsOptions.includes(option)) { 559 unitsOptions.push(option); 560 } 561 562 if (!unitsSizes.includes(size)) { 563 unitsSizes.push(size); 564 } 565 }); 566 567 let optionContainerDisplayClass = unitsOptions.length < 2 ? " hidden" : ""; 568 let sizeContainerDisplayClass = unitsSizes.length < 2 ? " hidden" : ""; 569 let descriptionContainerText = product.descricaoCurta ? product.descricaoCurta : ''; 570 571 let verifyContainersDisplay = 572 optionContainerDisplayClass === " hidden" && 573 sizeContainerDisplayClass === " hidden" && 574 descriptionContainerText === "" 575 ? " combined-purchase__name--only" 576 : ""; 577 578 let options = []; 579 let optionsHtml = ""; 580 let imagesHtml = ""; 581 let sizesHtml = []; 582 583 imagesHtml += getProductImagesHtml(product, productId, attribute); 584 585 for (let unitId in units) { 586 let unit = units[unitId];
587 let optionId = unit.opcao.id; 588 let sizeHtml = getSizeHtml(unit, productId, attribute, product); 589 590 if (!sizeHtml && !combinedPurchaseSettings.showUnitsOutOfStock) { 591 continue; 592 } 593 594 const totalStockForOption = getTotalStockForOption(units, optionId); 595 596 if (options.indexOf(optionId) < 0) { 597 options.push(optionId); 598 599 sizesHtml[optionId] = sizeHtml; 600 601 imagesHtml += getUnitImagesHtml(unit.opcao, productId, attribute); 602 optionsHtml += getOptionHtml(unit.opcao, productId, attribute, totalStockForOption ); 603 } else { 604 sizesHtml[optionId] += getSizeHtml(unit, productId, attribute, product); 605 } 606 } 607 608 if (sizesHtml.length < 1) { 609 return ""; 610 } 611 612 let sizesContentHtml = getSizesContentHtml(sizesHtml, productId, attribute); 613 let urlProduct = `${url}/produto/${productId}`; 614 615 return ` 616 <div class="combined-purchase__item" product-attribute-discount="${atributeDiscount}" product-attribute="${attribute}" ${attribute}-item="${productId}"> 617 <a href="${urlProduct}" class="combined-purchase__image-container" ${attribute}-image-container="${productId}"> 618 </a> 619 <div class="combined-purchase__content"> 620 <div class="combined-purchase__name${verifyContainersDisplay}">${product.nome}</div> 621 <div class="combined-purchase__description"> 622 ${descriptionContainerText} 623 </div> 624 <div class="combined-purchase__options-data${optionContainerDisplayClass}"> 625 <span>Cor</span> 626 <div class="combined-purchase__info"> 627 ${optionsHtml} 628 </div> 629 </div> 630 <div class="combined-purchase__sizes-data${sizeContainerDisplayClass}"> 631 <span>Tamanho</span> 632 <div class="combined-purchase__info"> 633 ${sizesContentHtml} 634 </div> 635 </div> 636 </div> 637 <div class="combined-purchase__image-data"> 638 ${imagesHtml} 639 </div> 640 </div> 641 `; 642}; 643 644/** 645 * Gera o código Html das imagens do produto 646 * 647 * @param {Object} product 648 * @param {String} productId 649 * @param {String} attribute 650 * @returns {String} 651 */ 652const getProductImagesHtml = (product, productId, attribute) => { 653 let images = product.imagens; 654 let html = ""; 655 656 if (!images) { 657 return html; 658 } 659 660 images.forEach((image) => { 661 html += ` 662 <div ${attribute}-image="${productId}"> 663 <img class="combined-purchase__image" alt="image" src=${image} width="300" height="300" style="height: auto" loading="lazy"/> 664 </div> 665 `; 666 }); 667 668 return html; 669}; 670 671/** 672 * Gera o código Html das imagens da unidade 673 * 674 * @param {Object} option 675 * @param {String} productId 676 * @param {String} attribute 677 * @returns {String} 678 */ 679const getUnitImagesHtml = (option, productId, attribute) => { 680 if (!option.imagem) { 681 return ""; 682 } 683 684 return ` 685 <div ${attribute}-image="${productId}-${option.id}"> 686 <img class="combined-purchase__image" alt="image" src=${option.imagem} width="300" height="300" style="height: auto" loading="lazy"/> 687 </div> 688 `; 689}; 690 691/** 692 * Gera o código Html das opcções 693 * 694 * @param {Object} option 695 * @param {String} productId 696 * @param {String} attribute 697 * @returns {String} 698 */ 699const getOptionHtml = (option, productId, attribute, totalStock) => { 700 let html = ""; 701 702 var imagemCor = option.imagemCor ? option.imagemCor : ""; 703 var imagem = option.imagem ? option.imagem : ""; 704 705 if (imagemCor || imagem) { 706 html = ` 707 <img 708 class="combined-purchase__option" 709 ${attribute}-option="${productId}-${option.id}" 710 ${attribute}-stock="${totalStock}" 711 src="${imagemCor || imagem}" 712 alt="${option.descricao}" 713 title="${option.descricao}" 714 loading="lazy" width="60" height="60" 715 /> 716 `; 717 } else if (option.corHexa != null && option.corHexa != "") { 718 html = ` 719 <a 720 class="combined-purchase__option" 721 style="background-color: #${option.corHexa}" 722 alt="${option.descricao}" 723 ${attribute}-option="${productId}-${option.id}" 724 ${attribute}-stock="${totalStock}" 725 ></a> 726 `; 727 } else { 728 let optionImage = $("#urlsite").val() + "/static/img/semimagem.jpg"; 729 730 html = ` 731 <img 732 class="combined-purchase__option" 733 ${attribute}-option="${productId}-${option.id}" 734 ${attribute}-stock="${totalStock}" 735 src="${optionImage}" 736 alt="${option.descricao}" 737 title="${option.descricao}" 738 loading="lazy" width="60" height="60" 739 /> 740 `; 741 } 742 743 return html; 744}; 745 746/** 747 * Gera o código Html dos tamanhos 748 * 749 * @param {Object} size 750 * @param {String} productId 751 * @param {String} attribute 752 * @returns {String} 753 */ 754const getSizeHtml = (unit, productId, attribute) => { 755 let size = unit.tamanho; 756 let option = unit.opcao; 757 let unitNotAllowed = ""; 758 759 if (!combinedPurchaseSettings.showUnitsOutOfStock && unit.estoque < 1) { 760 return ""; 761 } 762 763 if (unit.estoque < 1) { 764 unitNotAllowed = "combined-purchase__size--disabled"; 765 } 766 767 return ` 768 <a 769 value="${productId}-${option.id}-${size.id}" 770 class="combined-purchase__size ${unitNotAllowed}" 771 ${attribute}-price="${unit.por}" 772 ${attribute}-option-selected="${productId}-${option.id}" 773 ${attribute}-size="${productId}-${option.id}-${size.id}" 774 ${attribute}-stock="${unit.estoque}" 775 > 776 ${size.descricao} 777 </a> 778 `; 779}; 780 781/** 782 * Gera o código Html do container dos tamanhos e adiciona o HTML dos tamanhos dentro dele 783 * 784 * @param {String} sizesHtml 785 * @param {String} productId 786 * @param {String} attribute 787 * @returns {String} 788 */ 789const getSizesContentHtml = (sizesHtml, productId, attribute) => { 790 let html = ""; 791 792 sizesHtml.map((sizes, optionId) => { 793 html += ` 794 <div class="combined-purchase__size-container" ${attribute}-size-container="${productId}-${optionId}"> 795 ${sizes} 796 </div> 797 `; 798 }); 799 800 return html; 801}; 802 803/** 804 * Executa a aplicação após o DOM estar pronto 805 */ 806lazyLoadService.addFunctionToQueueAfterInteraction(combinedPurchaseJS.initilizeCombinedPurchase);
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.