async function boot() { let init = async () => { let [navigation, session] = await initializeService() getAsyncInfos(navigation, session) await initProcessSession(navigation, session) initProcessProduct(navigation, session) initProcessUser(navigation, session) initProcessRemoveCart(navigation, session) initProcessOrder(navigation, session) initCustomClicks(navigation, session, _cvConfig.custom_clicks) initPopPushs(navigation, session, _cvConfig.pushs) initProcessCheckout(navigation) initProcessCheckProducts(navigation) if (window['_cAddProductToWishlist']) _cAddProductToWishlist() if (window['_cvGetFormDependent']) _cvGetFormDependent(session) if (window['_cInfoInputs']) _cInfoInputs() if (window['_cInfoInputsSecond']) _cInfoInputsSecond() if (window['_cInfoInputsThird']) _cInfoInputsThird() if (window['_cGetNewsletter']) _cGetNewsletter() if (window['_cvResize']) _cvResize() } try { if (_cvConfig.windowLoad == true) { window.addEventListener("load", async () => { init() }) } else if (_cvConfig.singlePage == true) { if (_cvFlagSinglePage === false) init() // init first time if (_cvConfig.customerKey === '91658BAB23') { // beta _cvLoadSingleConfig(init) } else { let currentUrl = window.location.href setInterval(() => { let urlNow = window.location.href if (currentUrl != urlNow) { currentUrl = urlNow init() } }, 500) } } else { init() } } catch (err) { console.log('[ERRO] FlagSinglePage -->', err) } } let _cvFlagSinglePage = false function _cvLoadSingleConfig(initCallback) { try { if (_cvFlagSinglePage === false) { _cvFlagSinglePage = true // console.log('[DEBUG] chamou _cvLoadSingleConfig...') const generateId = () => Math.round(Math.random() * 8999 + 1000); const requestUrl = new Map(); const blacklist = ["sumo", "shopback", "/_next/data/"]; const isOnBlackList = (url) => blacklist.some((key) => new RegExp(key, "i").test(url)); // alteração do metodo fetch const { fetch: originalFetch } = window; window.fetch = (...args) => { const [url] = args; const id = generateId(); if (!isOnBlackList(url)) { requestUrl.set(id, url); // console.log("Começou uma requisição fetch", id, url); setTimeout(() => { requestUrl.delete(id); // console.log("Não concluiu a requisição", id, Array.from(requestUrl)); }, 5000); } else { // console.log("Está na blacklist", url); } const response = originalFetch(...args); response.finally(() => { requestUrl.delete(id); // console.log("Terminou uma requisição fetch", id, url); }); return response; }; // alteração da classe XMLHttpRequest const { send: originalSend, open: originalOpen } = XMLHttpRequest.prototype; XMLHttpRequest.prototype.open = function (...args) { const [, url] = args; new RegExp(`//`); if (!isOnBlackList(url)) { const id = generateId(); this.id = id; requestUrl.set(id, url); // console.log("Começou uma requisição xHttp", id, url); } else { // console.log("Está na blacklist", url); } originalOpen.call(this, ...args); }; XMLHttpRequest.prototype.send = function (...args) { // console.log("Começou uma requisição xHttp", this); const originalReadyStateChange = this.onreadystatechange?.bind(this); this.onreadystatechange = function (event) { if (this.readyState === 4) { requestUrl.delete(this.id); // console.log("Terminou uma requisição xHttp", this.id, this.responseURL); // console.log("Requisições restantes", Array.from(requestUrl)); } originalReadyStateChange?.(event); }; setTimeout(() => { if (this.readyState < 4) { requestUrl.delete(this.id); // console.log("Não concluiu a requisição", this.id, Array.from(requestUrl)); } }, 5000); originalSend.call(this, ...args); }; // alteração do método pushState const originalPushState = history.pushState; history.pushState = function (...args) { originalPushState.call(this, ...args); window.dispatchEvent(new Event("cv_changepage")); }; // alteração do método replaceState const originalReplaceState = history.pushState; history.replaceState = function (...args) { originalReplaceState.call(this, ...args); window.dispatchEvent(new Event("cv_changepage")); }; window.addEventListener("cv_changepage", () => { console.log("Mudou de URL"); const interval = setInterval(() => { if (requestUrl.size === 0) { console.log("[DEBUG] terminou as requisições..."); clearInterval(interval); initCallback() } else console.log('[DEBUG] requestUrl.size -->', requestUrl.size); }, 500); }); window.addEventListener("popstate", () => { const interval = setInterval(() => { if (requestUrl.size === 0) { console.log("[DEBUG] terminou as requisições..."); clearInterval(interval); initCallback() } else console.log('[DEBUG] requestUrl.size -->', requestUrl.size); }, 500); }); } } catch (err) { console.log('[ERRO] _cvLoadSingleConfig -->', err) } } async function initializeService() { return new Promise(async resolve => { let navigation = new _Navigation() let session = new _Session() let cart = new _Cart() let newSession let initNewSession = async () => { newSession = true let hashCookie = await getCookieCV('_cvhash') if (hashCookie != 0) { hashCookie = JSON.parse(hashCookie) session.hash = hashCookie.hash session.identified = hashCookie.identified } else { session.hash = await generateCVID() setCookieCV('_cvhash', JSON.stringify({ hash: session.hash, identified: session.identified }), 365) } session.session = await generateCVID() session.started_at = new Date() session.processTimeOut(_cvConfig.session_timeout) processTimeSpend() session.save() } if (localStorage._cvsession) { session.init() if (await session.processSessionTime() == true) { session = new _Session() await initNewSession() } else { newSession = false session.processTimeOut(_cvConfig.session_timeout) processTimeSpend() session.page_views++ } resolve([navigation, session]) } else { await initNewSession() resolve([navigation, session]) } if (localStorage._cvcart) { cart.init() if (newSession == true) { await cart.clearRemoved() if (cart.hasActiveProducts == true) { cart.cart_id = await generateCVID() cart.save() } else cart.clear() } if (cart.hasActiveProducts == true) { if (cart.record_duration != _cvConfig.cart_duration) cart.record_duration = _cvConfig.cart_duration await cart.processCartDuration() } } }) } async function initProcessSession(navigation, session) { await processForSession(navigation, _cvConfig.functions.forNavCategories, session, 'categories_view', [navigation, 'getPathCategories', _cvConfig.notValidCategories]) await processForSession(navigation, _cvConfig.functions.forNavProduct, session, 'products_view') await processForSession(navigation, _cvConfig.functions.forNavSearches, session, 'searches') let utms = await getUrlParameters(navigation.params, 'utm') if (Object.entries(utms).length > 0) { if (session.utms.length > 0) { await processForUtms(utms, session) } else session.utms.push(utms) } session.has_order = await initProcessOrder(navigation, session) new _PayloadNavigation(navigation, session).send() if (session.bis == false) session.bis = true if (navigation.geolocation != undefined || session.gls == false) session.gls = true await updateInterationLists(session) session.save() } async function updateInterationLists(session) { if (session.pushs) { // for pushs for (let i = 0; i < session.pushs.length; i++) { session.pushs[i].intervalAttempts++ } } } async function processForSession(navigation, functionName, objTo, paramTo, callbackElse) { if (functionName != 'default') { if (window[functionName]) { let values = await window[functionName](navigation).catch(err => { new _CVPROCESSBEAT('ERROR', functionName, `Erro na função de captação para sessão --> ${err}`) }) if (values) { let valuesList = await processListObjs(values, objTo[paramTo]) objTo[paramTo] = valuesList[0] navigation[paramTo] = valuesList[1] } } else new _CVPROCESSBEAT('ERROR', functionName, 'Função de captação para sessão não existe na tag') } else { objTo[paramTo] = await processListObjs(await callbackElse[0][callbackElse[1]](callbackElse[2]), objTo[paramTo]) } } async function processForUtms(utms, session) { let exist = false for (let i = 0; i < session.utms.length; i++) { if (session.utms[i].utm_campaign && utms.utm_campaign) if (await session.utms[i].utm_campaign == utms.utm_campaign) exist = true } if (!exist) session.utms.push(utms) } async function initProcessProduct(navigation) { if (window[_cvConfig.functions.isProductPage] && window[_cvConfig.functions.forProductInfos]) { if (await window[_cvConfig.functions.isProductPage](navigation) != undefined) { initProcessAddCart(navigation) let product = await window[_cvConfig.functions.forProductInfos](navigation).catch(err => { new _CVPROCESSBEAT('ERROR', _cvConfig.functions.isProductPage, `Erro na função de captação para produto --> ${err}`) }) if (product) { let productClass = new _Product(product) productClass.save() productClass.send() productClass.validate() } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.forProductInfos, 'Função de captação para produto não retornou o objeto esperado', product) } } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.isProductPage, 'Função de captação para produto não existe na tag') } async function initProcessAddCart(navigation) { if (window[_cvConfig.functions.addProductToCart]) { window[_cvConfig.functions.addProductToCart](navigation) } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.addProductToCart, 'Função de adicionar produto no carrinho não existe na tag') } async function initProcessRemoveCart(navigation) { if (window[_cvConfig.functions.removeProductToCart]) { window[_cvConfig.functions.removeProductToCart](navigation) } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.removeProductToCart, 'Função de remover produto do carrinho não existe na tag') } async function initProcessCheckProducts(navigation) { if (window[_cvConfig.functions.checkCartProducts]) { let objProducts = await window[_cvConfig.functions.checkCartProducts](navigation) if (objProducts != undefined) { let cart = new _Cart() if (localStorage._cvcart) cart.init() cart.checkProducts(objProducts[0], objProducts[1], objProducts[3]) } } else new _CVPROCESSBEAT('ERROR', 'initProcessCheckProducts', 'Função de validação de produtos no carrinho não existe na tag') } async function initProcessUser(navigation, session) { if (_cvConfig.optin_forms.length > 0) { let mapped = form => { if (form.default_visible == true) { let trigger = document.querySelector(form.trigger) if (trigger) addEvent(trigger, form) else new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Trigger ${form.trigger} cadastrada para form ${form.name} não existe`) } else { // let interval1 = form => { // let idI1 = setInterval(() => { // let trigger = document.querySelector(form.trigger) // if (trigger) { // clearInterval(idI1) // addEvent(trigger, form) // interval2(form) // } // }, 600) // } // let interval2 = form => { // let idI2 = setInterval(() => { // let trigger = document.querySelector(form.trigger) // if (trigger == undefined) { // clearInterval(idI2) // interval1(form) // } // }, 800) // } // interval1(form) let intervalId = setInterval(() => { let trigger = document.querySelector(form.trigger) if (trigger) { clearInterval(intervalId) addEvent(trigger, form) } }, 400) } } let addEvent = (element, form) => { element.addEventListener('click', () => { catchInfo(form) }) element.addEventListener('touchstart', () => { catchInfo(form) }) document.addEventListener('keydown', event => { if (event.key == 'Enter' || event.keyCode == 13) catchInfo(form) }) } let catchInfo = form => { let acceptTerm = async form => { let getVariants = async form => { let variantsToReturn = {} if (form.variants.length > 0) { for (let i = 0; i < form.variants.length; i++) { const variant = form.variants[i] let field = document.querySelector(variant.field) if (field) { let value = field.value if (await value.length > 0) { variantsToReturn[variant.name] = value } else { value = field.innerText if (await value.length > 0) { variantsToReturn[variant.name] = value } } } else if (variant.required == true) { new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Variante ${variant.field} para form ${form.name} não existe`) return undefined } } } return variantsToReturn } let email = document.querySelector(form.email) if (email) { email = email.innerText ? email.innerText : email.value if (await validateEmail(email) == true) { let variants = await getVariants(form) if (variants) { let user = new _User() user.email_address = email user.variants = variants user.origin = form.name if (form.optin_field == true) user.optin_field = true else { let optin_field = document.querySelector(form.optin_field) if (await optin_field) user.optin_field = optin_field.checked else { user.optin_field = false new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Campo de opt-in ${form.optin_field} para form ${form.name} não existe`) } } registerCvUser(user, session) } } } else new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Campo de email ${form.email} para form ${form.name} não existe`) } if (form.term_field == true) { acceptTerm(form) } else { let termField = document.querySelector(form.term_field) if (termField) { if (termField.checked == true) acceptTerm(form) else if (termField.value == 'true') acceptTerm(form) } else new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Termo de consentimento ${form.term_field} para form ${form.name} não existe`) } } for (let i = 0; i < _cvConfig.optin_forms.length; i++) { const form = _cvConfig.optin_forms[i] if (form.url == 'all') mapped(form) else if (form.url == navigation.cleanUrl) mapped(form) } } else new _CVPROCESSBEAT('ERROR', 'initProcessUser', 'Não existem formulários de opt-in para captação de usuários') } async function initProcessOrder(navigation, session) { if (window[_cvConfig.functions.isOrderPage]) { if (session.has_order == false) { if (await window[_cvConfig.functions.isOrderPage](navigation) == true) { if (localStorage._cvcart) { let cart = new _Cart() cart.init() cart.type = 2 new _PayloadCart(cart).send() cart.clear() } return true } else return false } else return true } else { new _CVPROCESSBEAT('ERROR', _cvConfig.functions.isOrderPage, 'Função de identificação de página de compra não existe na tag') return false } } async function initProcessCheckout(navigation) { if (window[_cvConfig.functions.forOriginCart]) { if (await window[_cvConfig.functions.forOriginCart](navigation) == 2) { if (localStorage._cvcart) { let cart = new _Cart() cart.init() cart.id_origin = 2 cart.save() cart.type = 1 new _PayloadCart(cart).send() } } } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.forOriginCart, 'Função de origem de carrinho não existe na tag') } async function registerCvUser(user, session) { let hash = await triggerRequest('post', user, _cvConfig.endpoints.user, true) if (hash) { let saveSession = async (session, hashCookie) => { session.identified = true session.hash = hashCookie setCookieCV('_cvhash', JSON.stringify({ hash: hashCookie, identified: true }), 365) await session.save() session = new _Session().init() let navigation = new _Navigation() new _PayloadNavigation(navigation, session, true).send() } if (session.identified == false) { saveSession(session, hash) } else if (session.hash != hash) { saveSession(session, hash) } } else new _CVPROCESSBEAT('ERROR', 'registerCvUser', 'Requisição para registro de usário não retornou a hash esperada') } async function initPopPushs(navigation, session, pushs) { let pushToProcess = [] for (let i = 0; i < pushs.length; i++) { let rules = pushs[i].rules let passHomolog = true if (rules.homologHashs != false) { passHomolog = false if (session.identified == true) { let index = await rules.homologHashs.findIndex(e => e == session.hash) if (index >= 0) passHomolog = true else passHomolog = false } } else { if (rules.identified == 'all') passHomolog = true else if (await rules.identified == true && session.identified == false) passHomolog = false else if (await rules.identified == false && session.identified == true) passHomolog = false } if (passHomolog == true) { let passPage = true for (let j = 0; j < rules.pagesToIgnore.length; j++) { if (await navigation.cleanUrl == rules.pagesToIgnore[j]) passPage = false } if (passPage == true) { if (rules.pagesToShow == 'all') { pushToProcess.push(pushs[i]) } else { let valid = false for (let j = 0; j < rules.pagesToShow.length; j++) { if (rules.pagesToShow[j] == '$product') { valid = await window[_cvConfig.functions.isProductPage](navigation) != undefined ? true : false if (valid == true) break } else if (rules.pagesToShow[j] == '$categorie') { valid = await window[_cvConfig.functions.isCategoriePage](navigation) if (valid == true) break } else if (navigation.cleanUrl == rules.pagesToShow[j]) { valid = true; break } } if (valid == true) { pushToProcess.push(pushs[i]) } } } } } if (pushToProcess.length > 0) processPopPushs(navigation, pushToProcess, 0, session) } async function processPopPushs(navigation, pushs, index, session) { let initPush = push => { let show = true if (push.rules.hasCart === true) { if (localStorage._cvcart) { let cart = new _Cart().init() if (cart.hasActiveProducts === true) show = true else show = false } else show = false } if (show == true) { if (push.rules.show.mouseLeave == true) { let lock = false document.addEventListener('mouseleave', () => { if (!lock) { new _Push(push).showPush(navigation) lock = true } }) } else if (push.rules.show.pageLoad == true) new _Push(push).showPush(navigation) else if (push.rules.show.clickSelectors != false) { // dev selectors } } else { if (index + 1 < pushs.length) { processPopPushs(navigation, pushs, index + 1, session) } } } let currentPush = pushs[index] if (session.pushs) { let sessionIndex = await session.pushs.findIndex(e => e.name == currentPush.name) if (sessionIndex >= 0) { if (currentPush.rules.oneTimeClick === false || (currentPush.rules.oneTimeClick === true && session.pushs[sessionIndex].clicks == 0)) { if (session.pushs[sessionIndex].attempts < currentPush.rules.maxTry) { if (currentPush.rules.intervalPagesToTry < session.pushs[sessionIndex].intervalAttempts) { initPush(currentPush) } else if (index + 1 < pushs.length) processPopPushs(navigation, pushs, index + 1, session) } else if (index + 1 < pushs.length) processPopPushs(navigation, pushs, index + 1, session) } else if (index + 1 < pushs.length) processPopPushs(navigation, pushs, index + 1, session) } else { initPush(currentPush) } } else { initPush(currentPush) } } async function processCartAddProduct(product, paramToCompare, send, isEquals, check) { let cart = new _Cart() if (localStorage._cvcart) { cart.init() await cart.insertProduct(product, paramToCompare, isEquals, check) if (send) { cart.type = 1 new _PayloadCart(cart).send() } } else { cart.cart_id = await generateCVID() cart.created_at = new Date() cart.record_duration = _cvConfig.cart_duration await cart.insertProduct(product, paramToCompare, isEquals, check) if (send) { cart.type = 1 new _PayloadCart(cart).send() } } } async function processCartRemoveProduct(paramToCompare, valueToCompare, send, isEquals) { let cart = new _Cart() if (localStorage._cvcart) { cart.init() await cart.deleteProduct(paramToCompare, valueToCompare, isEquals) if (send) new _PayloadCart(cart).send() } else new _CVPROCESSBEAT('INFO', 'processCartRemoveProduct', 'Objeto de persistência de carrinho não existe') } async function initCustomClicks(navigation, session, custom) { for (let i = 0; i < custom.length; i++) { if (custom[i].page == 'all') { processCustomClicks(custom[i], session) } else if (custom[i].page == navigation.cleanUrl) { processCustomClicks(custom[i], session) } } } async function processCustomClicks(custom, session) { let indexClick = session.custom_clicks.findIndex(e => e.name == custom.name) let mapedElements = async () => { let element if (await custom.unique === true) { element = document.querySelector(custom.selector) } else { element = document.querySelectorAll(custom.selector) if (await custom.index != 'all') element = element[custom.index] } if (element) { if (await custom.unique === true || custom.index != 'all') { element.addEventListener('click', countClick) } else { for (let i = 0; i < element.length; i++) { element[i].addEventListener('click', countClick) } } } else { new _CVPROCESSBEAT('ERROR', 'processCustomClicks', `Não foi possível mapear o elemento configurado no clique personalizado`, custom) } } let countClick = async () => { custom.clicked_at = new Date() if (indexClick >= 0) { session.custom_clicks[indexClick].countClick++ } else { if (await custom.count === true) custom.countClick = 1 session.custom_clicks.push(custom) } session.save() } if (custom.count === false) { if (indexClick >= 0) mapedElements() } else mapedElements() } async function getAsyncInfos(navigation, session) { if (_cvConfig.geolocation === true) { navigation.geolocation = await navigation.getGeolocation().catch(err => { }) } if (window[_cvConfig.functions.getLoged]) window[_cvConfig.functions.getLoged](navigation, session) } function triggerRequest(method, payload, endpoint, hasReturn) { // console.log('[DEBUG] triggerRequest -->', method, payload, endpoint, hasReturn) return new Promise((resolve, reject) => { let request = new XMLHttpRequest() request.open(method, endpoint, true) request.setRequestHeader('Authorization', _cvConfig.customerKey) if (payload) { request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8') request.send(JSON.stringify(payload)) } else { request.send() } request.onload = () => { if (request.status === 200 || request.status === 202) { if (hasReturn) resolve(request.responseText) else resolve() } else { new _CVPROCESSBEAT('INFO', 'triggerRequest', `Status ${request.status} para endpoint ${endpoint}`, payload) reject() } } request.onerror = () => { new _CVPROCESSBEAT('ERROR', 'triggerRequest', `Status ${request.status} para endpoint ${endpoint}`, payload) reject() } }) } async function setCookieCV(name, value, days) { let d = new Date() d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)) let expires = "expires=" + d.toUTCString() document.cookie = name + "=" + value + ";" + expires + ";path=/" } async function getCookieCV(cname) { return new Promise(async resolve => { let name = cname + "=" let decodedCookie = decodeURIComponent(document.cookie) let ca = decodedCookie.split(';') for (let i = 0; i < ca.length; i++) { let c = ca[i] while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { resolve(c.substring(name.length, c.length)) } } resolve(0) }) } async function generateCVID() { let s4 = () => { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1) } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() } async function replaceChain(s) { return await s.replaceAll('-', ' ').replaceAll('_', ' ').replaceAll(' ', ' ') .replaceAll('á', 'a').replaceAll('à', 'a').replaceAll('ã', 'a').replaceAll('â', 'a') .replaceAll('é', 'e').replaceAll('è', 'e').replaceAll('ê', 'e') .replaceAll('í', 'i').replaceAll('ì', 'i') .replaceAll('ó', 'o').replaceAll('ò', 'o').replaceAll('õ', 'o').replaceAll('ô', 'o') .replaceAll('ú', 'u').replaceAll('ù', 'u').replaceAll('û', 'u') .replaceAll('ç', 'c').trim().toLowerCase() } async function validateEmail(email) { if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/.test(email)) return true else return false } function processTimeSpend() { let startInterval = () => { setInterval(() => { let time = Number(localStorage._cvtime) time++ localStorage.setItem('_cvtime', time) }, 1000) } if (_cvConfig.singlePage == true) { if (!localStorage._cvtime) { _cvConfig.intervalStarts = true localStorage.setItem('_cvtime', '0') startInterval() } else if (!_cvConfig.intervalStarts) { _cvConfig.intervalStarts = true startInterval() } } else { if (!localStorage._cvtime) localStorage.setItem('_cvtime', '0') startInterval() } } async function getUrlParameters(params, compare) { if (!params) params = location.search let results = {} if (params) { let query = params.substring(1); query.split('&').forEach(p => { let item = p.split('=') if (compare) { if (item[0].indexOf(compare) >= 0) { results[item[0]] = decodeURIComponent(item[1]) } } else { results[item[0]] = decodeURIComponent(item[1]) } }) return results } else { return results } } async function processListObjs(values, list) { if (values.length > 0) { if (list.length > 0) { let listToNav = [] for (let i = 0; i < values.length; i++) { listToNav.push({ value: values[i], count: 1, level: i }) let index = await checkValueExists(values[i], list) if (index >= 0) { list[index].count++ } else { await list.push({ value: values[i], count: 1, level: i }) } } await orderCvList(list, 'count') return [list, listToNav] } else { let listReturn = [] for (let i = 0; i < values.length; i++) { listReturn.push({ value: values[i], count: 1, level: i }) } await orderCvList(listReturn, 'count') return [listReturn, listReturn] } } else { await orderCvList(list, 'count') return [list, undefined] } } async function checkValueExists(value, list) { for (let i = 0; i < list.length; i++) { if (await value == list[i].value) { return i } } return -1 } async function orderCvList(list, param) { if (list.length > 0) { let n = list.length for (let i = 1; i < n; ++i) { let key = list[i] let j = i - 1 while (j >= 0 && list[j][param] < key[param]) { list[j + 1] = list[j] j = j - 1 } list[j + 1] = key } } } class _Navigation { constructor() { this.urlBase = decodeURIComponent(window.location.origin + '/') this.url = decodeURIComponent(window.location.href) this.params = decodeURIComponent(window.location.search) this.cleanUrl = this.url.replace(this.params, '') this.pathsEncoded = window.location.pathname == '/' ? '' : window.location.pathname this.pathsDecoded = decodeURIComponent(this.pathsEncoded) this.geolocation = undefined this.browserInfos = this.getBrowserInfos(), this.categories_view = undefined this.products_view = undefined this.searches = undefined } getBrowserInfos() { let userAgentString = navigator.userAgent let chromeAgent = userAgentString.indexOf("Chrome") > -1 ? 'chrome' : undefined let IExplorerAgent = userAgentString.indexOf("MSIE") > -1 || userAgentString.indexOf("rv:") > -1 ? 'internet explorer' : undefined let firefoxAgent = userAgentString.indexOf("Firefox") > -1 ? 'firefox' : undefined let safariAgent = userAgentString.indexOf("Safari") > -1 ? 'safari' : undefined if ((chromeAgent) && (safariAgent)) safariAgent = undefined let operaAgent = userAgentString.indexOf("OP") > -1 ? 'opera' : undefined if ((chromeAgent) && (operaAgent)) chromeAgent = undefined return { userAgent: userAgentString, language: navigator.language, browser: safariAgent || chromeAgent || IExplorerAgent || operaAgent || firefoxAgent } } async getGeolocation() { return new Promise(resolve => { try { navigator.geolocation.getCurrentPosition(position => { resolve(position) }) } catch (e) { } }) } async getPathCategories(notValidCategories) { let validCategories = [] if (this.pathsEncoded != '') { let pathToCompare = this.pathsEncoded if (pathToCompare.slice(0, 1) == '/') pathToCompare = pathToCompare.slice(1) let pathCategories = pathToCompare.split('/') for (let i = 0; i < pathCategories.length; i++) { pathCategories[i] = decodeURIComponent(pathCategories[i]) let valid = true for (let j = 0; j < notValidCategories.length; j++) { if (await notValidCategories[j] == '$pagination') { if (isNaN(pathCategories[i]) == false) valid = false } else if (await notValidCategories[j] == pathCategories[i] || pathCategories[i] == '') valid = false } if (valid) validCategories.push(await replaceChain(pathCategories[i].toLowerCase())) } } return validCategories } } class _PayloadNavigation { constructor(navigation, session, hasChange) { this.url = navigation.url this.cleanUrl = navigation.cleanUrl this.params = navigation.params this.paths = navigation.pathsDecoded this.session = session.session this.hash = session.hash this.identified = session.identified this.page_views = session.page_views this.utms = session.utms.length > 0 ? session.utms : undefined this.permanence_time = Number(localStorage._cvtime) this.browserInfos = session.bis == false ? navigation.browserInfos : undefined this.categories_view = session.categories_view.length > 0 ? session.categories_view : undefined this.products_view = session.products_view.length > 0 ? session.products_view : undefined this.searches = session.searches.length > 0 ? session.searches : undefined this.navigation = { categories_view: navigation.categories_view, products_view: navigation.products_view, searches: navigation.searches } this.has_order = session.has_order this.custom_clicks = session.custom_clicks.length > 0 ? session.custom_clicks : undefined this.pushs = session.pushs this.shc = hasChange this.nps_answered = session.nps_answered this.geolocation = session.gls == false ? navigation.geolocation : undefined this.started_at = session.started_at } send() { triggerRequest('post', this, _cvConfig.endpoints.navigation, false) } } class _Session { constructor() { this.session = undefined this.hash = undefined this.identified = false this.page_views = 1 this.utms = [] this.categories_view = [] this.products_view = [] this.searches = [] this.custom_clicks = [] this.pushs = undefined this.nps_answered = undefined this.has_order = false this.started_at = undefined this.updated_at = undefined this.bis = false this.gls = false } init() { let session = JSON.parse(localStorage._cvsession) this.session = session.session this.hash = session.hash this.identified = session.identified this.page_views = session.page_views this.utms = session.utms this.categories_view = session.categories_view this.products_view = session.products_view this.searches = session.searches this.custom_clicks = session.custom_clicks this.pushs = session.pushs this.nps_answered = session.nps_answered this.has_order = session.has_order this.started_at = new Date(session.started_at) this.updated_at = new Date(session.updated_at) this.bis = session.bis this.gls = session.gls return this } save() { this.updated_at = new Date() localStorage.setItem('_cvsession', JSON.stringify(this)) } remove() { localStorage.removeItem('_cvsession') localStorage.removeItem('_cvtime') } async processSessionTime() { let now = new Date() let cloneUpdate = new Date(this.updated_at) cloneUpdate.setMinutes(cloneUpdate.getMinutes() + _cvConfig.session_timeout) if (now.getTime() >= cloneUpdate) { this.remove() return true } else return false } processTimeOut(sessionTimeOut) { let intervalId = setTimeout(() => { // triggerRequest('post', { session: this.session }, _cvConfig.endpoints.endsession, false) this.remove() clearInterval(intervalId) }, sessionTimeOut * 60000) } } class _Cart { constructor() { this.cart_id = undefined this.products = [] this.hasActiveProducts = false this.type = 1 this.id_origin = undefined this.created_at = undefined this.updated_at = undefined this.record_duration = undefined } init() { let cart = JSON.parse(localStorage._cvcart) this.cart_id = cart.cart_id this.products = cart.products this.hasActiveProducts = cart.hasActiveProducts this.type = cart.type this.id_origin = cart.id_origin this.created_at = new Date(cart.created_at) this.updated_at = new Date(cart.updated_at) this.record_duration = cart.record_duration return this } save() { this.updated_at = new Date() localStorage.setItem('_cvcart', JSON.stringify(this)) } async processCartDuration() { let now = new Date() let cloneUpdate = new Date(this.updated_at) cloneUpdate.setMinutes(cloneUpdate.getMinutes() + this.record_duration) if (now.getTime() >= cloneUpdate) { await this.clear() } } async clear() { localStorage.removeItem('_cvcart') } async clearRemoved() { this.hasActiveProducts = false for (let i = 0; i < this.products.length; i++) { if (await this.products[i].removed == true) { this.products.splice(i, 1) i-- } else this.hasActiveProducts = true } } async insertProduct(productToInsert, param, isEquals, check) { if (productToInsert[param]) { let index = false for (let i = 0; i < this.products.length; i++) { let product = this.products[i] try { if (isEquals == true) { if (await product[param] == productToInsert[param]) { index = i break } } else { if (await productToInsert[param].indexOf(product[param]) >= 0) { index = i break } } } catch (err) { new _CVPROCESSBEAT('ERROR', 'insertProduct', err) } } if (index === false) { this.products.push(productToInsert) this.hasActiveProducts = true this.save() } else { if (!check) { if (this.products[index].selectable) { this.products[index].selectable.qtd += productToInsert.selectable ? productToInsert.selectable.qtd : 1 if (productToInsert?.selectable?.sku_id) this.products[index].selectable.sku_id = productToInsert.selectable.sku_id } else this.products[index].selectable = productToInsert.selectable } if (this.products[index].removed == true) this.products[index].removed = false this.save() } } else { new _CVPROCESSBEAT('ERROR', 'insertProduct', 'Produto a ser inserido não possui parâmetro de comparação informado', productToInsert) } } async deleteProduct(param, valueToCompare, isEquals) { let exist = false for (let i = 0; i < this.products.length; i++) { let product = this.products[i] if (isEquals) { if (await product[param] == valueToCompare) { exist = true product.removed = true } } else { if (await valueToCompare.indexOf(product[param]) > -1) { exist = true product.removed = true } } } if (exist) { let active = this.products.findIndex(e => e.removed !== true) this.hasActiveProducts = active >= 0 ? true : false this.save() } else new _CVPROCESSBEAT('INFO', 'deleteProduct', 'Produto a ser deletado não foi encontrado no objeto de carrinho') } async checkProducts(currentProducts, param, isEquals) { let update = false for (let i = 0; i < currentProducts.length; i++) { // insert products in cart let exist = false for (let j = 0; j < this.products.length; j++) { if (isEquals == true) { if (await this.products[j][param] == currentProducts[i][param]) { exist = true break } } else { if (await currentProducts[i][param].indexOf(this.products[j][param]) >= 0) { exist = true break } } } if (!exist) { await processCartAddProduct(currentProducts[i], param, false, isEquals) update = true } else { await processCartAddProduct(currentProducts[i], param, false, isEquals, true) } } for (let i = 0; i < this.products.length; i++) { // delete products that are no longer in cart let exist = false for (let j = 0; j < currentProducts.length; j++) { if (isEquals == true) { if (await this.products[i][param] == currentProducts[j][param]) { exist = true break } } else { if (await currentProducts[j][param].indexOf(this.products[i][param]) >= 0) { exist = true break } } } if (!exist && this.products[i].removed != true) { update = true await processCartRemoveProduct(param, this.products[i][param], false, true) } } if (update) new _PayloadCart(this.init()).send() } } class _User { constructor() { this.email_address = undefined this.variants = {} this.origin = undefined this.optin_field = false } } class _Recommendation { constructor() { this.products = undefined } init() { let recommendation = JSON.parse(sessionStorage._cvrecommendation) this.products = recommendation.products return this } save() { sessionStorage.setItem('_cvrecommendation', JSON.stringify(this)) } } class _Product { constructor(product) { this.name = product.name this.sku = product.sku this.categories = product.categories this.url = product.url this.price = product.price this.selectable = product.selectable this.images = product.images this.defaultImage = product.defaultImage this.variants = product.variants this.removed = product.removed this.unavailable = product.unavailable } init() { if (sessionStorage._cvproduct) { let obj = JSON.parse(sessionStorage._cvproduct) this.name = obj.name this.sku = obj.sku this.categories = obj.categories this.url = obj.url this.price = obj.price this.selectable = obj.selectable this.images = obj.images this.defaultImage = obj.defaultImage this.variants = obj.variants this.removed = obj.removed this.unavailable = obj.unavailable return this } else return undefined } validate() { if (!this.name && !this.sku && this.categories.length > 0 && !this.price && !this.defaultImage) new _CVPROCESSBEAT('ERROR', 'validateProduct', 'Produto captado não atendeu os requisitos de validação', this) } save() { sessionStorage.setItem('_cvproduct', JSON.stringify(this)) } send() { triggerRequest('post', this, _cvConfig.endpoints.product, false) } } class _Push { constructor({ name, pushHTML, rules }) { this.name = name this.pushHTML = pushHTML this.rules = rules this.pushElement = undefined } showPush(navigation) { let alreadyPush = document.querySelector('#cv-push') if (!alreadyPush) { if (window.screen.width > 700) { let pushElement = document.createElement('section') pushElement.id = 'cv-push' pushElement.innerHTML = this.pushHTML this.pushElement = pushElement if (this.rules.recommendation === true) { this.processPushRecommendation(navigation) } else { document.body.appendChild(pushElement) if (this.rules.customCss) document.head.insertAdjacentHTML('beforeend', this.rules.customCss) this.addEvents() this.processShow(navigation) } } } } async processPushRecommendation(navigation) { if (sessionStorage._cvrecommendation) { let session = new _Session().init() let recommendation = new _Recommendation().init() this.showPushRecommendation(session, recommendation, navigation) } else { let session = new _Session().init() let payload = { hash: session.hash, categories: session.categories_view, rules: { limit_of_products: 5 } } let recCall = await triggerRequest('post', payload, _cvConfig.endpoints.recommendation, true).catch(err => { }) recCall = JSON.parse(recCall) if (recCall.recommended) { let recommendation = new _Recommendation() recommendation.products = recCall.recommended recommendation.save() this.showPushRecommendation(session, recommendation, navigation) }//else no products to recommended } } async showPushRecommendation(session, recommendation, navigation) { let indexRecom = 0 let productRecom = recommendation.products[indexRecom] if (session.products_view.length > 0) { for (let i = 0; i < session.products_view.length; i++) { if (session.products_view[i].value == productRecom.sku || productRecom.show == true) { indexRecom += 1 if (await recommendation.products[indexRecom] != undefined) { productRecom = recommendation.products[indexRecom] } else { productRecom = undefined; break } } else break } } if (productRecom) { this.pushElement.style = 'display: none' document.body.appendChild(this.pushElement) if (this.rules.customCss) document.head.insertAdjacentHTML('beforeend', this.rules.customCss) let titleElement = document.querySelector('.cv-push-box p') titleElement.innerText = productRecom.name let imgElement = document.querySelector('.cv-push-img img') imgElement.src = productRecom.defaultImage this.pushElement.style = '' recommendation.products[indexRecom].show = true recommendation.save() this.addEvents(productRecom.url + this.rules.params) this.processShow(navigation, productRecom) }//else no products to recommended } addEvents(redirect) { let closedElement = document.querySelector('.cv-push-closed img') closedElement.addEventListener('click', () => { this.pushElement.remove() }) let boxElement = document.querySelector('.cv-push-box') boxElement.addEventListener('click', () => { this.click(redirect) }) let imgElement = document.querySelector('.cv-push-img') imgElement.addEventListener('click', () => { this.click(redirect) }) } async processShow(navigation, product) { let session = new _Session().init() let createPush = exist => { let pushPayload = { name: this.name, attempts: 1, clicks: 0, intervalAttempts: 0, history: [{ url: navigation.cleanUrl, created_at: new Date(), click: 0, product: product ? { sku: product.sku } : undefined }] } if (exist) { session.pushs.push(pushPayload) } else { session.pushs = [pushPayload] } session.save() } if (session.pushs) { let index = await session.pushs.findIndex(e => e.name == this.name) if (index >= 0) { session.pushs[index].attempts++ session.pushs[index].intervalAttempts = 0 session.pushs[index].history.push({ url: navigation.cleanUrl, created_at: new Date(), click: 0, product: product ? { sku: product.sku } : undefined }) session.save() } else createPush(true) } else createPush(false) } async click(redirect) { let session = new _Session().init() let index = await session.pushs.findIndex(e => e.name == this.name) if (index >= 0) { session.pushs[index].clicks++ session.pushs[index].history[session.pushs[index].history.length - 1].click++ session.save() if (redirect) window.location.replace(redirect) else window.location.replace(this.rules.redirect) } else new _CVPROCESSBEAT('ERROR', 'clickPush', `Objeto push ${this.name} não existe na lista de pushs da sessão`) } } class _PayloadCart { constructor(cart) { let session = new _Session().init() this.session = session.session this.hash = session.hash this.instance = new _Navigation().cleanUrl this.identified = session.identified this.utms = session.utms.length > 0 ? session.utms : undefined this.cart_id = cart.cart_id this.products = cart.products this.type = cart.type this.id_origin = cart.id_origin this.created_at = cart.created_at this.updated_at = cart.updated_at this.pushs = session.pushs } send() { triggerRequest('post', this, _cvConfig.endpoints.cart, false) } } class _CVPROCESSBEAT { constructor(type, method, message, payload) { this.type = type this.method = method this.message = message this.payload = payload this.process() } process() { switch (this.type) { case 'INFO': console.log(`[CV.INFO.${this.method}] ${this.message}`) break case 'ERROR': // triggerRequest('POST', this, _cvConfig.endpoints.beat, false) break default: break } } }let _cvConfig = { "customerKey": "6259EEDMWW", "session_timeout": 5, "windowLoad": false, "cart_duration": 10080, "singlePage": true, "geolocation": false, "notValidCategories": [ "$pagination", "#", "checkout", "cart", "profile", "shipping", "account", "_secure", "orders", "addresses", "cards" ], "endpoints": { "navigation": "https://oci.claravista-api.com.br/register/navigation", "cart": "https://oci.claravista-api.com.br/register/cart", "product": "https://oci.claravista-api.com.br/register/product", "user": "https://oci.claravista-api.com.br/register/user", "beat": "https://oci.claravista-api.com.br/register/beat", "recommendation": "https://dashp5.claravista.com.br/core/api/v.2.2/recommendation/push" }, "functions": { "forNavCategories": "_cGetNavCategorie", "isProductPage": "_cIsProductPage", "isCategoriePage": "_cIsCategoriePage", "forNavProduct": "_cGetNavProduct", "forNavSearches": "_cGetSeachers", "forProductInfos": "_cGetProductInfo", "addProductToCart": "_cAddProductToCart", "removeProductToCart": "_cRemoveProductToCart", "forOriginCart": "_cOriginCartPage", "isOrderPage": "_cIsOrderPage", "getLoged": "_cGetLoged", "checkCartProducts": "_cCheckCartProducts" }, "custom_clicks": [], "pushs": [], "optin_forms": [ { "name": "login", "url": "all", "default_visible": false, "email": "#loginEmail", "trigger": "button.sc-vfpkh9-0.ejRJIs.sc-rx6fk7-3.WttEM", "term_field": true, "optin_field": true, "variants": [] }, { "name": "register", "url": "all", "default_visible": false, "email": "#registerEmail", "trigger": "button.sc-vfpkh9-0.ejRJIs.sc-1ixmrog-3.cSjseV", "term_field": true, "optin_field": true, "variants": [] }, { "name": "login_checkout", "url": "all", "default_visible": false, "email": "#client-pre-email", "trigger": "#btn-client-pre-email", "term_field": true, "optin_field": true, "variants": [] } ], "modals": [] } function _cIsProductPage() { return window.location.pathname.endsWith("/p"); // for (let i = 0; i < dataLayer.length; i++) { // if (dataLayer[i].pageCategory) // if (dataLayer[i].pageCategory === "Product") return dataLayer[i]; // } } async function _cIsCategoriePage() { for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].pageCategory) if ( dataLayer[i].pageCategory === "Category" || dataLayer[i].pageCategory === "Departament" ) { return true; } } if (!_cIsProductPage() && !(await _cIsSearchPage())) { return true; } return false; } async function _cIsSearchPage() { for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].pageCategory) if (dataLayer[i].pageCategory === "InternalSiteSearch") return dataLayer[i]; } } function getProductFromEvent() { return new Promise((resolve) => { let attempts = 0; const interval = setInterval(() => { const event = window.dataLayer.find((e) => e.event === "productDetail"); if (event || ++attempts >= 5) { const [product] = event?.ecommerce?.detail?.products || []; clearInterval(interval); return resolve(product); } }, 400); }); } //ok async function _cGetNavCategorie(navigation) { const categories = []; const product = await getProductFromEvent(); if (product?.category) { let prodCategories = product.category.toLowerCase() prodCategories = prodCategories.split('/') for (let i = 0; i < prodCategories.length; i++) { let category = prodCategories[i] categories.push(await replaceChain(category)) } } else { const isSearchPage = await _cIsSearchPage(navigation); const isOrderPage = await _cIsOrderPage(navigation); if (!isSearchPage && !isOrderPage) { const pathCategories = await navigation.getPathCategories( _cvConfig.notValidCategories ); for (let i = 0; i < pathCategories.length; i++) { categories.push(await replaceChain(pathCategories[i].toLowerCase())); } } } return categories; } //ok async function _cGetNavProduct() { const product = await getProductFromEvent(); return product ? [product.id] : []; } //ok async function _cGetSeachers(navigation) { let searchLayer = await _cIsSearchPage(navigation); if (searchLayer) { let search = searchLayer.siteSearchTerm.toLowerCase(); search = await replaceChain(search); return [search]; } else return []; } //ok function _cGetProductInfo(navigation) { return new Promise((resolve) => { let limit = 10; let tryTimes = 0; const interval = setInterval(async () => { if (++tryTimes >= limit) { clearInterval(interval); return resolve(); } const product = { variants: {}, categories: [], images: [] }; const productFromEvent = await getProductFromEvent(); const productName = document.querySelector( ".vtex-store-components-3-x-productNameContainer" )?.innerText; const productSku = document.querySelector( ".vtex-product-identifier-0-x-product-identifier--productId .vtex-product-identifier-0-x-product-identifier__value" )?.innerText; // base product.name = productFromEvent?.name || productName; product.sku = productFromEvent?.id || productSku; product.price = productFromEvent?.price; product.url = navigation.cleanUrl; product.unavailable = false; // categories const categoryElements = document.querySelectorAll( "[data-testid='breadcrumb'] a" ); for (const categoryElement of categoryElements) { const categoryText = await replaceChain( categoryElement.innerText.toLowerCase() ); if ( categoryText && categoryText !== "home" && !product.categories.includes(categoryText) ) { product.categories.push(categoryText); } } // old price let oldPrice = document.querySelector('.vtex-product-price-1-x-listPriceValue').innerText oldPrice = oldPrice.replaceAll('R$', '').replaceAll(' ', '').replaceAll(' ', '').replaceAll(',', '.').trim() oldPrice = Number(oldPrice) product.variants.oldPrice = oldPrice // variants from dataLayer if (productFromEvent?.dimension1) { product.variants.referenceId = productFromEvent?.dimension1; } if (productFromEvent?.brand) { product.variants.brandName = productFromEvent?.brand; } const urlParams = new URLSearchParams(window.location.search); let sku_id = urlParams.get('skuId') if (sku_id) product.variants.sku_id = sku_id // variants selectable const sizeButtons = document.querySelector( ".vtex-store-components-3-x-skuSelectorOptionsList" )?.children; if (sizeButtons?.length) { product.variants.fullSizes = []; product.variants.availableSizes = []; for (const button of sizeButtons) { const size = button.innerText?.toLowerCase(); const isUnavailable = !!button.querySelector( ".vtex-store-components-3-x-diagonalCross" ); product.variants.fullSizes.push(size); if (!isUnavailable) { product.variants.availableSizes.push(size); } } } // let elementColor = document.querySelectorAll(".sc-17wl8qo-0.hWDGRf a"); // if (elementColor.length > 0) { // productFromEvent.variants.colors = []; // for (let i = 0; i < elementColor.length; i++) { // let textColor = elementColor[i].title.toLowerCase(); // productFromEvent.variants.colors.push(textColor); // } // } // images const productImages = document.querySelectorAll( ".swiper-wrapper .swiper-slide img.vtex-store-components-3-x-thumbImg" ); if (productImages.length) { product.defaultImage = productImages[0].src; for (const image of productImages) { product.images.push(image.src); } } const isCompleteProduct = Object.values(product).every( (value) => value !== undefined ); if (isCompleteProduct) { clearInterval(interval); return resolve(product); } }, 400); }); } function _cvMappedClick(element, callback) { element.addEventListener("click", callback); element.addEventListener("touchstart", callback); } let _cvCurrentMapButton = undefined; //ok async function _cAddProductToCart() { if (_cvCurrentMapButton === undefined) { let buttons = [...document.querySelectorAll('*')].filter(element => element.childNodes?.[0]?.nodeValue?.match('ADICIONAR À SACOLA')) console.log('cv buttons', buttons) for (let i = 0; i < buttons.length; i++) { let element = buttons[i] if (element) { _cvCurrentMapButton = element; _cvMappedClick(element, () => { let product = new _Product({}).init(); if (product != undefined) { let elementSizes = document.querySelector(".vtex-store-components-3-x-skuSelectorItem--selected"); let elementColor = document.querySelector( "button.sc-vfpkh9-0.guZudH.sc-oxzjy6-1.fEqDaN" ); const urlParams = new URLSearchParams(window.location.search); let sku_id = urlParams.get('skuId') product.selectable = {}; if (sku_id) product.selectable.sku_id = sku_id if (elementSizes) product.selectable.size = elementSizes.innerText.toLowerCase(); if (elementColor) product.selectable.color = elementColor.innerText.toLowerCase(); product.selectable.qtd = 1; processCartAddProduct(product, "sku", true, true); } else new _CVPROCESSBEAT( "ERROR", "_cAddProductToCart", "Produto a ser adicionado no carrinho não existe" ); }); } } } } //ok async function _cOriginCartPage(navigation) { if (navigation.cleanUrl.indexOf("/cart") >= 0) { return 1; } else if (navigation.cleanUrl.indexOf("checkout") >= 0) { return 2; } else { return 0; } } //ok async function _cRemoveProductToCart(navigation) { let idOrigin = await _cOriginCartPage(navigation); if (idOrigin === 1) { let elements = document.querySelectorAll(".product-item .item-remove"); for (let i = 0; i < elements.length; i++) { _cvMappedClick(elements[i], () => { let mainElement = elements[i].parentNode; let sku = mainElement.getAttribute("data-sku"); processCartRemoveProduct("sku", sku, true, true); }); } } else if (idOrigin === 0) { let lock = false; setInterval(() => { let elements = document.querySelectorAll( ".x-minicart-content .sc-1r0f5ec-5.hGuawZ .sc-vfpkh9-0.dpcDmB" ); if (elements.length > 0) { if (lock === false) { lock = true; console.log("[DEBUG.CV] mapped remove elements ->", elements); for (let i = 0; i < elements.length; i++) { _cvMappedClick(elements[i], () => { let mainElement = elements[i].parentNode.parentNode; let elementName = mainElement.querySelector( ".sc-1r0f5ec-3.fXFRaS .sc-1ue9u14-0.dXsECi" ); let name = elementName.innerText.toLowerCase(); processCartRemoveProduct("name", name, true, false); }); } } } else { lock = false; } }, 1000); } } //ok async function _cIsOrderPage(navigation) { if (navigation.pathsDecoded.indexOf("/orderPlaced") >= 0) { return true; } else { return false; } } //ok async function _cGetLoged(navigation, session) { const orderForm = window.localStorage.getItem("orderform"); if (orderForm) { try { const orderFormJson = JSON.parse(orderForm); const email = orderFormJson?.clientProfileData?.email; const isValidEmail = email ? await validateEmail(email) : false; if (isValidEmail) { let user = new _User(); user.email_address = email; user.origin = "loged"; user.optin_field = true; registerCvUser(user, session); } } catch (error) { console.log( "[CV.ERROR._cGetLoged] Erro ao converter os dados de localStorage.orderForm para JSON!" ); } } _cGetNewsletter(session); } //ok function _cCheckCartProducts(navigation) { return new Promise((resolve) => { let limit = 10; let tryTimes = 0; let intervalId = setInterval(() => { let checkoutLayer; for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].ecommerce) if (dataLayer[i].ecommerce.items) { checkoutLayer = dataLayer[i].ecommerce.items break } } if (checkoutLayer) { let products = []; for (let i = 0; i < checkoutLayer.length; i++) { let product = checkoutLayer[i]; products.push({ sku: product.item_id, selectable: { sku_id: product.item_variant } }); } resolve([products, "sku", true]); } else { tryTimes++; if (tryTimes === limit) { clearInterval(intervalId); resolve(); } } }, 400); }); } async function _cGetNewsletter(session) { let limit = 10; let tryTimes = 0; let intervalId = setInterval(() => { let emailInput = document.querySelector(".malwee-appcustom-2-x-malNewsletterFieldEmail"); let newsButton = document.querySelector("button.malwee-appcustom-2-x-malNewsletterBtnSubmit"); if (emailInput && newsButton) { clearInterval(intervalId) let callback = async () => { let email = emailInput.value || emailInput.innerText; if (email) { if (await validateEmail(email)) { let user = new _User(); user.email_address = email; user.origin = "newsletter"; user.optin_field = true; user.variants = { categories: [] }; let categoriesSelected = document.querySelectorAll('.malwee-appcustom-2-x-malNewsletterCheckboxField:checked+label'); if (categoriesSelected.length > 0) { let categories = []; for (let i = 0; i < categoriesSelected.length; i++) { let element = categoriesSelected[i]; let category = element.innerText.toLowerCase(); categories.push(category); } user.variants.categories = categories; } registerCvUser(user, session); } } } _cvMappedClick(newsButton, callback) document.addEventListener("keydown", (event) => { if (event.key == "Enter" || event.keyCode == 13) callback() }) } else { tryTimes++; if (tryTimes === limit) clearInterval(intervalId) } }, 500) } console.log("[SUCCESS] Claravista Tag v1.1.10") boot()