{"version":3,"file":"tag.js","mappings":"yBAAA,MAAMA,eAAiB,CACrBC,OAAQC,OAAOC,YACfC,WAAY,CACVC,SAAU,sBACVC,KAAM,gBAERC,gBAAiBC,SAASC,iBAAiB,0BAA0B,GACrEC,eAAgBF,SAASC,iBAAiB,kBAAkB,GAC5DE,OAAQH,SAASI,cAAc,oBAC/BC,YAAa,WACX,MAAMF,OAASG,KAAKH,OAEN,MAAVA,QAAgBA,OAAOI,cAAcC,YAAYL,OACvD,EACAM,eAAgB,SAAUC,SACxB,MAAMC,WAAaL,KAAKb,OAAOkB,WAE/B,GAAID,SAAWC,aACbL,KAAKb,OAAOmB,YAAcF,QAEtBJ,KAAKb,OAAOmB,aAAeD,YAAYL,KAAKD,cAE5CK,QAAUC,YACZ,OAAQL,KAAKb,OAAOoB,QAAUP,KAAKb,OAAOqB,MAAMJ,SAASK,GAE/D,EAEAC,UAAW,SAAUC,QACnB,MAAMC,UAAYlB,SAASmB,cAAc,UAEzC,OADAD,UAAUE,UAAYH,OAAOG,UACtBpB,SAASqB,KAAKC,YAAYJ,UACnC,EAEAK,aAAcC,iBACZ,MAAMX,QAAUP,KAAKb,OAAOoB,QACtBY,eAAiBC,MAAMb,SACvBc,WAAaF,SAASG,OAGtBC,KADS,IAAIC,WACAC,gBAAgBJ,KAAM,aAInCK,SAHSH,IAAIzB,cAAc,2BAGjByB,IAAI5B,iBAAiB,2BAMrC,OALI+B,QAAQC,OAAS,GACnBD,QAAQE,SAASjB,SACfzB,eAAewB,UAAUC,OAAO,IAG7BY,IAAI5B,iBAAiB,iBAC9B,EACAkC,YAAa,WACXzC,OAAO0C,KAAKC,UAAUC,MAAMC,QAC9B,EACAC,YAAahB,iBACX,MAAMZ,YAAcN,KAAKb,OAAOmB,YAC1B6B,QAAUnC,KAAKP,gBACfG,eAAiBI,KAAKJ,eAE5B,IAAKuC,QAAQC,UAAUC,SAAS,cAAe,CAC7CrC,KAAKP,gBAAgB2C,UAAUE,IAAI,cACnCtC,KAAKH,OAAOuC,UAAUE,IAAI,qBAEAtC,KAAKiB,gBAEnBW,SAASW,UACnB3C,eAAeoB,YAAYuB,QAAQ,IAGrCvC,KAAKG,eAAeG,YAAc,GAElClB,OAAOoD,gBAAgBC,MAAK,GAC5BC,iBAAiBT,SACjBjC,KAAK6B,cAELM,QAAQC,UAAUO,OAAO,cACzB3C,KAAKH,OAAOuC,UAAUO,OAAO,aAC/B,CACF,EAEAF,KAAM,WACJ,MAAM5C,OAASG,KAAKH,OAEM+C,aAAf5C,KAAKb,QACA,MAAVU,QACFA,OAAOgD,iBACL,SACA,KACE7C,KAAKkC,aAAa,GAEpB,CAAEY,SAAS,GAInB,GAGF,kCC9FA,MAAMC,SACE,YCuHD,WACL,MAAMC,SAAWtD,SAASC,iBAAiB,qBAE3B,MAAZqD,UAEJA,SAASpB,SAASqB,UAChB,MAAMC,SAAWD,QAAQE,QAAQC,gBAEjCH,QAAQI,cAAc,IAAIC,MAAM,WAGhB,KAAZJ,UACFD,QAAQM,MAAMC,YAAY,aAAc,KAAKN,aAC/C,GAEJ,CDrIIO,GACA,eAAehB,MACjB,EAGFrD,OAAOyD,iBAAiB,oBAAoB,KAC1CE,UAAU,G","sources":["webpack://build/../tchocolath/assets/javascripts/components/infinityScroll.js","webpack://build/../tchocolath/assets/javascripts/pages/tag.js","webpack://build/../tchocolath/assets/javascripts/components/utilities.js"],"sourcesContent":["const InfinityScroll = {\r\n params: window._pagination,\r\n priceProds: {\r\n selector: '[data-update-price]',\r\n attr: 'update-price',\r\n },\r\n productsWrapper: document.querySelectorAll('.section-list-products')[0],\r\n productWrapper: document.querySelectorAll('.list-products')[0],\r\n button: document.querySelector('[data-load-more]'),\r\n stopLoading: function () {\r\n const button = this.button;\r\n\r\n if (button != null) button.parentElement.removeChild(button);\r\n },\r\n setCurrentPage: function (_number) {\r\n const totalPages = this.params.totalPages;\r\n\r\n if (_number <= totalPages) {\r\n this.params.currentPage = _number;\r\n\r\n if (this.params.currentPage >= totalPages) this.stopLoading();\r\n\r\n if (_number < totalPages)\r\n return (this.params.nextUrl = this.params.pages[_number].url);\r\n }\r\n },\r\n\r\n setScript: function (script) {\r\n const newScript = document.createElement('script');\r\n newScript.innerText = script.innerText;\r\n return document.body.appendChild(newScript);\r\n },\r\n\r\n loadProducts: async function () {\r\n const nextUrl = this.params.nextUrl;\r\n const response = await fetch(nextUrl);\r\n const data = await response.text();\r\n\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(data, 'text/html');\r\n const script = doc.querySelector('[data-product-variants]');\r\n\r\n // Busca por scripts para compra rápida\r\n const scripts = doc.querySelectorAll('[data-variants-script]');\r\n if (scripts.length > 0)\r\n scripts.forEach((script) => {\r\n InfinityScroll.setScript(script);\r\n });\r\n\r\n return doc.querySelectorAll('.product-block');\r\n },\r\n updatePrice: function () {\r\n window.Vnda.Component.Price.update();\r\n },\r\n getNextPage: async function () {\r\n const currentPage = this.params.currentPage;\r\n const wrapper = this.productsWrapper;\r\n const productWrapper = this.productWrapper;\r\n\r\n if (!wrapper.classList.contains('-searching')) {\r\n this.productsWrapper.classList.add('-searching');\r\n this.button.classList.add('-searching');\r\n\r\n const newProducts = await this.loadProducts();\r\n\r\n newProducts.forEach((product) => {\r\n productWrapper.appendChild(product);\r\n });\r\n\r\n this.setCurrentPage(currentPage + 1);\r\n\r\n window.ProductPurchase.init(true);\r\n lazyLoadInstance.update();\r\n this.updatePrice();\r\n\r\n wrapper.classList.remove('-searching');\r\n this.button.classList.remove('-searching');\r\n }\r\n },\r\n\r\n init: function () {\r\n const button = this.button;\r\n\r\n if (typeof this.params != undefined) {\r\n if (button != null) {\r\n button.addEventListener(\r\n 'click',\r\n () => {\r\n this.getNextPage();\r\n },\r\n { passive: true }\r\n );\r\n }\r\n }\r\n },\r\n};\r\n\r\nexport default InfinityScroll;\r\n","import InfinityScroll from '../components/infinityScroll';\r\nimport { updatePriceBlock } from '../components/utilities.js';\r\n\r\nconst Tag = {\r\n init: function () {\r\n updatePriceBlock();\r\n InfinityScroll.init();\r\n },\r\n};\r\n\r\nwindow.addEventListener('DOMContentLoaded', () => {\r\n Tag.init();\r\n});\r\n","// ===============================================================\r\n// ADIÇÃO MANUAL DE ASSET\r\n// ===============================================================\r\n// Usado para incluir assets no código de forma manual, conforme a necessidade\r\nexport function addAsset(source, onloadCallback) {\r\n\r\n if (!source || source === '') return console.error(`addAsset: caminho não definido.`)\r\n\r\n if (source.includes('.js')) {\r\n const scriptTag = document.createElement('script')\r\n scriptTag.setAttribute('src', source);\r\n\r\n if (onloadCallback && typeof onloadCallback === 'function') {\r\n scriptTag.onload = onloadCallback\r\n }\r\n\r\n return document.body.appendChild(scriptTag)\r\n\r\n } else if (source.includes('.css')) {\r\n const linkTag = document.createElement('link')\r\n linkTag.setAttribute('rel', 'stylesheet')\r\n linkTag.setAttribute('type', 'text/css')\r\n linkTag.setAttribute('href', source)\r\n return document.head.appendChild(linkTag)\r\n\r\n } else {\r\n const error = `addAsset: Erro ao criar o asset. Tipo de script não definido, ou não possui tratamento para este tipo de asset.`\r\n return console.error(error, source)\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// BUSCA O CARRINHO ATIVO\r\n// ===============================================================\r\nexport async function getCart() {\r\n try {\r\n const response = await fetch('/carrinho', {\r\n headers: { 'accept': 'application/json' }\r\n });\r\n const cart = await response.json();\r\n return cart;\r\n } catch (error) {\r\n console.error('Erro ao buscar os dados do carrinho');\r\n console.error(error);\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// SERIALIZE ARRAY\r\n// ===============================================================\r\nexport function serializeArray(form) {\r\n\r\n const formData = new FormData(form);\r\n const data = {};\r\n\r\n for (const [name, value] of formData) {\r\n data[name] = value\r\n }\r\n\r\n const formBody = [];\r\n\r\n for (const key in data) {\r\n const encodeKey = encodeURIComponent(key)\r\n const encodeValue = encodeURIComponent(data[key])\r\n formBody.push(`${encodeKey}=${encodeValue}`)\r\n }\r\n\r\n return formBody = formBody.join('&')\r\n \r\n}\r\n\r\n// ===============================================================\r\n// URL ENCODE FORM DATA\r\n// ===============================================================\r\nexport function urlencodeFormData(formData) {\r\n let string = '';\r\n\r\n function encode(s) {\r\n return encodeURIComponent(s).replace(/%20/g, '+');\r\n }\r\n\r\n for (const pair of formData.entries()) {\r\n if (typeof pair[1] == 'string') {\r\n string += (string ? '&' : '') + encode(pair[0]) + '=' + encode(pair[1]);\r\n }\r\n }\r\n return string;\r\n}\r\n\r\n// ===============================================================\r\n// SLIDE TOGGLE\r\n// ===============================================================\r\nexport function slideToggle(contentWrapper, content, duration = 500) {\r\n let initialHeight = window.getComputedStyle(contentWrapper).height;\r\n\r\n if (initialHeight == '0px') {\r\n return slideDown(contentWrapper, content, duration);\r\n } else {\r\n return slideUp(contentWrapper, duration);\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// SLIDE UP\r\n// ===============================================================\r\nexport function slideUp(contentWrapper, duration = 500) {\r\n contentWrapper.style.height = '0px';\r\n contentWrapper.style.transition = `height ${duration} ease`;\r\n}\r\n\r\n// ===============================================================\r\n// SLIDE DOWN\r\n// ===============================================================\r\nexport function slideDown(contentWrapper, content, duration = 500) {\r\n let innerHeight = content.clientHeight;\r\n\r\n contentWrapper.style.height = `${innerHeight}px`;\r\n contentWrapper.style.transition = `height ${duration} ease`;\r\n}\r\n\r\n// ===============================================================\r\n// UPDATE DISCOUNT IN PRODUCT BLOCK\r\n// ===============================================================\r\nexport function updatePriceBlock() {\r\n const priceEls = document.querySelectorAll('[data-init-price]');\r\n\r\n if (priceEls == null) return;\r\n\r\n priceEls.forEach((priceEl) => {\r\n const discount = priceEl.dataset.discountPercent;\r\n\r\n priceEl.dispatchEvent(new Event('change'));\r\n\r\n // discount\r\n if (discount != '0') {\r\n priceEl.style.setProperty('--discount', `'-${discount}%'`);\r\n }\r\n });\r\n}\r\n\r\n// ===============================================================\r\n// PREÇO POR AJAX\r\n// ===============================================================\r\nexport function getPriceProd() {\r\n var selectors = document.querySelectorAll('[data-update-price]');\r\n var attr = 'update-price';\r\n\r\n if (selectors.length() > 0) {\r\n selectors.forEach((selector) => {\r\n var prodId = selector.dataset(attr);\r\n var url = '/produto/preco/' + prodId;\r\n\r\n if (prodId != '' && prodId != null) {\r\n $.ajax({\r\n url: url,\r\n type: 'GET',\r\n })\r\n .done((resp) => {\r\n selector.innerHTML = resp;\r\n })\r\n .fail((resp) => {\r\n console.error(resp);\r\n });\r\n }\r\n });\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// DEBOUNCE\r\n// ===============================================================\r\n/*\r\n Debounce retorna uma função que enquanto continuar sendo chamada não é executada\r\n A função só será executada quando para de ser chamada por N milisegundos\r\n Útil para melhorar a performance de códigos que são executados muitas vezes por segundo, como o $(window).resize()\r\n\r\n Ex:\r\n \r\n $(window).resize(debounce(function() {\r\n // código a ser executado\r\n }, 500))\r\n \r\n No exemplo acima a função só será executada 500ms depois do último resize\r\n Abra o link abaixo e redimensione a janela branca e acompanhe o output do console\r\n Exemplo codepen: https://codepen.io/valkervieira/pen/oNgqyWY\r\n\r\n Um caso comum de uso é em lojas onde a seleção de um filtro na página de tag recarrega automáticamente a página\r\n Com o debounce o usuário pode escolher vários filtros rapidamente e a página só recarrega quando parar de escolher\r\n*/\r\n\r\nexport function debounce(func, wait, immediate) {\r\n var timeout;\r\n immediate || (immediate = true);\r\n\r\n return function () {\r\n var context = this,\r\n args = arguments;\r\n\r\n var later = function () {\r\n timeout = null;\r\n if (!immediate) func.apply(context, args);\r\n };\r\n\r\n var callNow = immediate && !timeout;\r\n\r\n clearTimeout(timeout);\r\n\r\n timeout = setTimeout(later, wait);\r\n\r\n if (callNow) func.apply(context, args);\r\n };\r\n}\r\n\r\n// ===============================================================\r\n// THROTTLE\r\n// ===============================================================\r\n/*\r\n Throttle diminui a frequencia que uma função é executada\r\n Enquanto no debounce a função só é executada quando para de ser chamada, no throttle ela\r\n continua sendo executada só que em um intervalo mínimo de N milisegundos (default = 250)\r\n\r\n Ex:\r\n\r\n $(window).resize(throttle() {\r\n // código a ser executado\r\n }, 500)\r\n\r\n No exemplo acima a função resize é chamada várias vezes por segundo mas só é executada 1 vez a cada 500ms\r\n Abra o link abaixo, redimensione a janela branca e acompanhe o console\r\n Exemplo codepen: https://codepen.io/valkervieira/pen/yLyKEPW\r\n\r\n Um caso comum de uso é checar se o scroll passou de um determinado ponto, para fixar um header ou alterar algum elemento do DOM\r\n*/\r\nexport function throttle(fn, threshhold, scope) {\r\n threshhold || (threshhold = 250);\r\n var last, deferTimer;\r\n return function () {\r\n var context = scope || this;\r\n\r\n var now = +new Date(),\r\n args = arguments;\r\n if (last && now < last + threshhold) {\r\n // hold on to it\r\n clearTimeout(deferTimer);\r\n deferTimer = setTimeout(function () {\r\n last = now;\r\n fn.apply(context, args);\r\n }, threshhold);\r\n } else {\r\n last = now;\r\n fn.apply(context, args);\r\n }\r\n };\r\n}\r\n\r\n// ===============================================================\r\n// FORMAT MONEY\r\n// ===============================================================\r\nexport function formatMoney(value) {\r\n // FORMATA UM VALOR\r\n return (\r\n 'R$ ' +\r\n value\r\n .toFixed(2)\r\n .replace('.', ',')\r\n .replace(/(\\d)(?=(\\d{3})+\\,)/g, '$1.')\r\n );\r\n}\r\n\r\n// ===============================================================\r\n// FORMAT VALUE\r\n// ===============================================================\r\n\r\nexport const formatValue = function (value = '') {\r\n let parsedValue = value;\r\n if (typeof value === 'number') {\r\n parsedValue = value.toFixed(2).toString();\r\n }\r\n return parsedValue.replace('.', ',');\r\n};\r\n\r\n// ===============================================================\r\n// VALIDA QUANTIDADE\r\n// ===============================================================\r\nexport function validateQuantity(_val) {\r\n // VALIDA SE A QUANTIDADE INFORMADA É UM NÚMERO\r\n if (!isNaN(_val)) {\r\n if (parseInt(_val) > 0) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ===============================================================\r\n// CLEAR NUMBER\r\n// ===============================================================\r\nexport function getClearNumber(_val) {\r\n // RETORNA UM NÚMERO LIMPO COMO INT\r\n if (!isNaN(_val)) {\r\n var clearNumber = parseInt(_val);\r\n\r\n return clearNumber;\r\n }\r\n\r\n return false;\r\n}\r\n"],"names":["InfinityScroll","params","window","_pagination","priceProds","selector","attr","productsWrapper","document","querySelectorAll","productWrapper","button","querySelector","stopLoading","this","parentElement","removeChild","setCurrentPage","_number","totalPages","currentPage","nextUrl","pages","url","setScript","script","newScript","createElement","innerText","body","appendChild","loadProducts","async","response","fetch","data","text","doc","DOMParser","parseFromString","scripts","length","forEach","updatePrice","Vnda","Component","Price","update","getNextPage","wrapper","classList","contains","add","product","ProductPurchase","init","lazyLoadInstance","remove","undefined","addEventListener","passive","Tag","priceEls","priceEl","discount","dataset","discountPercent","dispatchEvent","Event","style","setProperty","updatePriceBlock"],"sourceRoot":""}