1/** 2 * mkt-cookies.js 3 * 4 * Gestiona el consentimiento de cookies y llama a las funciones de carga 5 * definidas en `mkt-cookies-load.js`. 6 */ 7 8jQuery(document).ready(function ($) { 9 const $bannerWrapper = $("#mkt-privacy-overlay"); 10 const $trigger = $("#mkt-privacy-trigger"); 11 const cookieConfig = window.mkt_cookies_obj || {}; 12 const persistentConsentKey = "cookie_consent"; 13 const sessionConsentKey = "cookie_consent_session"; 14 const persistentConsentDuration = 365 * 24 * 60 * 60 * 1000; 15 let pageConsent = null; 16 let visibilityTimer = null; 17 18 // Algunos filtros ocultan únicamente el panel mediante CSS, incluso después 19 // de cargar la página. Retirar el fondo no equivale a aceptar ni a rechazar. 20 function checkPanelVisibility() { 21 const panel = document.getElementById("mkt-privacy-panel"); 22 if (!panel || !panel.isConnected) { 23 hideBanner(); 24 return; 25 } 26 27 const style = window.getComputedStyle(panel); 28 const rect = panel.getBoundingClientRect(); 29 const fullyClipped = /^inset\(\s*100%/i.test(style.clipPath); 30 if (panel.hidden || style.display === "none" || style.visibility === "hidden" || 31 style.visibility === "collapse" || Number(style.opacity) === 0 || 32 fullyClipped || rect.width === 0 || rect.height === 0) { 33 hideBanner(); 34 } 35 } 36 37 function normalizeConsentData(consentData) { 38 return { 39 analytics: !!(consentData && consentData.analytics === true), 40 marketing: !!(consentData && consentData.marketing === true), 41 }; 42 } 43 44 function getConsentData() { 45 if (pageConsent) return pageConsent; 46 47 try { 48 const rawPersistentConsent = localStorage.getItem(persistentConsentKey); 49 50 if (rawPersistentConsent) { 51 const persistentConsent = JSON.parse(rawPersistentConsent); 52 const isValidConsent = persistentConsent && 53 typeof persistentConsent.analytics === "boolean" && 54 typeof persistentConsent.marketing === "boolean"; 55 56 if (isValidConsent && persistentConsent.analytics && persistentConsent.marketing) { 57 // Actualizar sin interrumpir a quienes ya habÃan aceptado antes de 58 // incorporar una caducidad explÃcita. 59 if (typeof persistentConsent.expiresAt !== "number") { 60 persistentConsent.expiresAt = Date.now() + persistentConsentDuration; 61 localStorage.setItem(persistentConsentKey, JSON.stringify(persistentConsent)); 62 } 63 64 if (persistentConsent.expiresAt > Date.now()) { 65 return normalizeConsentData(persistentConsent); 66 } 67 } else if (isValidConsent) { 68 // Las decisiones antiguas que no aceptaban ambas categorÃas dejan 69 // de ser permanentes y se respetan únicamente en la sesión actual. 70 sessionStorage.setItem(sessionConsentKey, JSON.stringify(normalizeConsentData(persistentConsent))); 71 } 72 73 localStorage.removeItem(persistentConsentKey); 74 } 75 76 const rawSessionConsent = sessionStorage.getItem(sessionConsentKey); 77 if (!rawSessionConsent) return null; 78 79 const sessionConsent = JSON.parse(rawSessionConsent); 80 if (!sessionConsent || typeof sessionConsent.analytics !== "boolean" || 81 typeof sessionConsent.marketing !== "boolean") { 82 sessionStorage.removeItem(sessionConsentKey); 83 return null; 84 } 85 86 return normalizeConsentData(sessionConsent); 87 } catch (error) { 88 console.warn("No se puede leer cookie_consent", error); 89 return null; 90 } 91 } 92 93 function saveConsentData(consentData) { 94 pageConsent = normalizeConsentData(consentData); 95 96 try { 97 if (pageConsent.analytics && pageConsent.marketing) { 98 localStorage.setItem(persistentConsentKey, JSON.stringify({ 99 analytics: true, 100 marketing: true, 101 expiresAt: Date.now() + persistentConsentDuration, 102 })); 103 sessionStorage.removeItem(sessionConsentKey); 104 } else { 105 sessionStorage.setItem(sessionConsentKey, JSON.stringify(pageConsent)); 106 localStorage.removeItem(persistentConsentKey); 107 } 108 } catch (error) { 109 // Mantener la decisión durante esta página si el navegador bloquea el almacenamiento. 110 console.warn("No se puede guardar cookie_consent; decisión válida para esta página", error); 111 } 112 } 113 114 function hasConsentChanged(previousConsent, nextConsent) { 115 if (!previousConsent) { 116 return true; 117 } 118 119 return previousConsent.analytics !== nextConsent.analytics || previousConsent.marketing !== nextConsent.marketing; 120 } 121 122 function applyConsentChange(nextConsent) { 123 const previousConsent = getConsentData();
124 const normalizedConsent = normalizeConsentData(nextConsent); 125 126 saveConsentData(normalizedConsent); 127 // La interfaz no depende de que un proveedor de tracking termine sin errores. 128 hideBanner(); 129 130 // Si el usuario cambia su decisión después de una carga previa, recargamos para 131 // garantizar que los scripts queden alineados con el consentimiento actual. 132 if (previousConsent && hasConsentChanged(previousConsent, normalizedConsent)) { 133 window.location.reload(); 134 return; 135 } 136 137 check_cookies(); 138 } 139 140 function showBanner() { 141 $trigger.stop(true, true).prop("hidden", true).hide(); 142 $bannerWrapper.stop(true, true).prop("hidden", false).css({ display: "flex", opacity: 1 }); 143 window.clearInterval(visibilityTimer); 144 // Solo comprobar mientras esté abierto. Incluye reglas CSS inyectadas tarde. 145 visibilityTimer = window.setInterval(checkPanelVisibility, 500); 146 checkPanelVisibility(); 147 } 148 149 function hideBanner() { 150 window.clearInterval(visibilityTimer); 151 visibilityTimer = null; 152 $bannerWrapper.stop(true, true).prop("hidden", true).hide(); 153 $trigger.stop(true, true).prop("hidden", false).css({ display: "inline-flex", opacity: 1 }); 154 } 155 156 function syncInitialState() { 157 const consentData = getConsentData(); 158 159 // Ver el banner no constituye una decisión: seguirá visible al navegar o 160 // recargar hasta que el usuario guarde expresamente una elección. 161 if (!consentData) { 162 showBanner(); 163 return; 164 } 165 166 hideBanner(); 167 } 168 169 function syncChoiceControls() { 170 const banner = document.getElementById("mkt-privacy-panel"); 171 172 if (banner && window.mktEnhanceChoiceControls) { 173 try { 174 window.mktEnhanceChoiceControls(banner); 175 } catch (error) { 176 console.warn("No se pudieron mejorar los controles de cookies", error); 177 } 178 } 179 } 180 181 function showOptionalChoices() { 182 const $analyticsChoice = $("#cookie-type-analytics"); 183 const $marketingChoice = $("#cookie-type-marketing"); 184 185 $analyticsChoice.prop("checked", false).trigger("change"); 186 $marketingChoice.prop("checked", false).trigger("change"); 187 $bannerWrapper.addClass("is-customizing"); 188 $("#customize-cookies").attr("aria-expanded", "true"); 189 syncChoiceControls(); 190 } 191 192 // Aceptar cookies 193 $("#accept-cookies").on("click", function () { 194 const isCustomizing = $bannerWrapper.hasClass("is-customizing"); 195 196 // El botón principal acepta expresamente ambas categorÃas. Cuando el 197 // usuario abre la personalización, guarda exactamente su selección. 198 applyConsentChange({ 199 analytics: isCustomizing ? $("#cookie-type-analytics").is(":checked") : true, 200 marketing: isCustomizing ? $("#cookie-type-marketing").is(":checked") : true, 201 }); 202 }); 203 204 // Mostrar las preferencias opcionales partiendo de una elección conservadora. 205 $("#customize-cookies").on("click", function () { 206 showOptionalChoices(); 207 }); 208 209 // Abrir banner de cookies 210 $("#mkt-privacy-trigger").on("click", function () { 211 const consentData = getConsentData(); 212 213 $bannerWrapper.removeClass("is-customizing"); 214 $("#customize-cookies").attr("aria-expanded", "false"); 215 216 if (!consentData) { 217 $("#cookie-type-analytics").prop("checked", true); 218 $("#cookie-type-marketing").prop("checked", true); 219 } else { 220 // Preparar checks de consenimiento 221 $("#cookie-type-analytics").prop("checked", !!consentData.analytics); 222 $("#cookie-type-marketing").prop("checked", !!consentData.marketing); 223 } 224 225 syncChoiceControls(); 226 227 showBanner(); 228 }); 229 230 function check_cookies() { 231 const consentData = getConsentData(); 232 233 if (!consentData) { 234 return; 235 } 236 237 try { 238 // Comunicar primero la decisión. El contenedor procesará estos comandos 239 // antes de sus eventos de inicio porque se añaden previamente a dataLayer. 240 if (typeof update_google_consent === "function") { 241 update_google_consent(consentData); 242 } 243 244 if (consentData.analytics || consentData.marketing) { 245 // Cargar Google Tag Manager si hay ID y consentimiento 246 if (cookieConfig.gtm_id && typeof load_gtm_script === "function") { 247 load_gtm_script(cookieConfig.gtm_id); 248 } 249 } 250
251 if (consentData.analytics && typeof load_analytics_cookies === "function") { 252 // Cargar scripts de analÃtica 253 load_analytics_cookies(); 254 } 255 256 if (consentData.marketing && typeof load_marketing_cookies === "function") { 257 // Cargar scripts de marketing 258 load_marketing_cookies(); 259 } 260 } catch (error) { 261 console.warn("No se pudo cargar el tracking autorizado", error); 262 } 263 } 264 265 syncInitialState(); 266 syncChoiceControls(); 267 check_cookies(); 268});
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.