1/* Minimal Extras · ficha de producto: resumen en vivo de extras y total. */ 2(function () { 3 var cfg = window.mexPrecio || {}; 4 5 function formatear(n) { 6 var partes = n.toFixed(cfg.decimales || 0).split('.'); 7 partes[0] = partes[0].replace(/\B(?=(\d{3})+(?!\d))/g, cfg.miles || ''); 8 var numero = partes.join(cfg.dec || ','); 9 return (cfg.formato || '%2$s%1$s').replace('%1$s', cfg.simbolo || '').replace('%2$s', numero).replace(/ /g, ' '); 10 } 11 12 function formDe(caja) { 13 return caja.closest('form') || document.getElementById(caja.getAttribute('data-form') || ''); 14 } 15 16 /* El tema pone cantidad y botón en fila flex: la caja sale de esa fila y se coloca justo encima. */ 17 function recolocar(caja) { 18 var padre = caja.parentElement; 19 if (!padre || getComputedStyle(padre).display.indexOf('flex') === -1) return; 20 if (padre.tagName === 'FORM') { 21 // Fuera del <form>: lo marcado se copia a campos ocultos dentro, asà lo recibe cualquier envÃo (normal o ajax). 22 if (!padre.id) padre.id = 'mex-form-' + Math.random().toString(36).slice(2, 8); 23 caja.setAttribute('data-form', padre.id); 24 var espejo = document.createElement('div'); 25 espejo.hidden = true; 26 espejo.className = 'mex-espejo'; 27 padre.appendChild(espejo); 28 caja.querySelectorAll('.mex-extra input[type="checkbox"]').forEach(function (c) { c.removeAttribute('name'); }); 29 caja._mexEspejo = espejo; 30 } 31 padre.parentNode.insertBefore(caja, padre); 32 } 33 34 function copiarEspejo(caja) { 35 var espejo = caja._mexEspejo; 36 if (!espejo) return; 37 espejo.innerHTML = ''; 38 caja.querySelectorAll('.mex-extra input[type="checkbox"]:checked').forEach(function (c) { 39 var h = document.createElement('input'); 40 h.type = 'hidden'; 41 h.name = 'mex_extras[]'; 42 h.value = c.value; 43 espejo.appendChild(h); 44 }); 45 } 46 47 function cantidad(caja) { 48 var form = formDe(caja); 49 var input = form && form.querySelector('input.qty, input[name="quantity"]'); 50 var q = input ? parseFloat(input.value) : 1; 51 return q > 0 ? q : 1; 52 } 53 54 function actualizar(caja) { 55 copiarEspejo(caja); 56 var extras = 0; 57 caja.querySelectorAll('.mex-extra input[type="checkbox"]').forEach(function (c) { 58 c.closest('.mex-extra').classList.toggle('is-activo', c.checked); 59 if (c.checked) extras += parseFloat(c.dataset.precio) || 0; 60 }); 61 62 var resumen = caja.querySelector('.mex-extras__resumen'); 63 var q = cantidad(caja); 64 var base = parseFloat(caja.dataset.base); 65 resumen.hidden = extras <= 0; 66 if (extras <= 0) return; 67 68 caja.querySelector('[data-mex-extras]').textContent = '+' + formatear(extras * q); 69 caja.querySelector('[data-mex-etiqueta-extras]').textContent = q > 1 ? 'Extras (' + q + ' uds.)' : 'Extras'; 70 71 var filaTotal = caja.querySelector('[data-mex-fila-total]'); 72 filaTotal.hidden = isNaN(base); 73 if (!isNaN(base)) { 74 caja.querySelector('[data-mex-total]').textContent = formatear((base + extras) * q); 75 caja.querySelector('[data-mex-etiqueta-total]').textContent = q > 1 ? 'Total (' + q + ' uds.)' : 'Total'; 76 } 77 } 78 79 function iniciar() { 80 document.querySelectorAll('.mex-extras').forEach(function (caja) { 81 recolocar(caja); 82 var form = formDe(caja); 83 caja.addEventListener('change', function () { actualizar(caja); }); 84 if (form) { 85 form.addEventListener('input', function (ev) { 86 if (ev.target.matches('input.qty, input[name="quantity"]')) actualizar(caja); 87 }); 88 form.addEventListener('change', function (ev) { 89 if (ev.target.matches('input.qty, input[name="quantity"]')) actualizar(caja); 90 }); 91 } 92 // Productos variables: el precio base es el de la variación elegida. 93 if (form && window.jQuery) { 94 window.jQuery(form) 95 .on('found_variation', function (e, v) { 96 caja.dataset.base = v && v.display_price !== undefined ? v.display_price : ''; 97 actualizar(caja); 98 }) 99 .on('reset_data hide_variation', function () { 100 caja.dataset.base = ''; 101 actualizar(caja); 102 }); 103 } 104 // Botones +/- de algunos temas cambian la cantidad sin lanzar eventos. 105 if (form) { 106 form.addEventListener('click', function () { setTimeout(function () { actualizar(caja); }, 50); }); 107 } 108 actualizar(caja); 109 }); 110 } 111 112 if (document.readyState === 'loading') { 113 document.addEventListener('DOMContentLoaded', iniciar); 114 } else { 115 iniciar(); 116 } 117})(); 118 119 120/* Carrito: botón "Añadir" de las ofertas sin recargar la página. */ 121(function () { 122 document.addEventListener('click', function (ev) { 123 var boton = ev.target.closest && ev.target.closest('[data-mex-anadir-carrito]'); 124 if (!boton || !window.fetch) return; 125 ev.preventDefault(); 126 if (boton.getAttribute('aria-disabled') === 'true') return; 127 128 var oferta = boton.closest('.mex-oferta'); 129 var aviso = oferta.querySelector('.mex-oferta__aviso'); 130 if (aviso) aviso.remove(); 131 boton.setAttribute('aria-disabled', 'true'); 132 boton.classList.add('is-cargando'); 133 boton.textContent = 'Añadiendoâ¦'; 134 135 var url = boton.href + (boton.href.indexOf('?') === -1 ? '?' : '&') + 'mex_ajax=1'; 136 fetch(url, { credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } }) 137 .then(function (r) { return r.json(); }) 138 .then(function (res) { 139 if (!res || !res.ok) throw new Error(res && res.mensaje ? res.mensaje : ''); 140 boton.classList.remove('is-cargando'); 141 boton.classList.add('is-hecho'); 142 boton.textContent = 'Añadido'; 143 var $ = window.jQuery; 144 var lateral = document.getElementById('fkcart-modal'); 145 var pagina = document.querySelector('.woocommerce-cart-form'); 146 var checkout = document.querySelector('form.checkout, form.woocommerce-checkout'); 147 if ($ && checkout) $(document.body).trigger('update_checkout'); 148 if ($ && lateral) $(document.body).trigger('fkcart_update_side_cart'); 149 if ($ && pagina) $(document.body).trigger('wc_update_cart'); 150 if ($) $(document.body).trigger('wc_fragment_refresh'); 151 if (!$ || (!lateral && !pagina && !checkout)) { 152 setTimeout(function () { window.location.reload(); }, 300); 153 } 154 }) 155 .catch(function (err) { 156 boton.removeAttribute('aria-disabled'); 157 boton.classList.remove('is-cargando'); 158 boton.textContent = 'Añadir'; 159 var p = document.createElement('p'); 160 p.className = 'mex-oferta__aviso'; 161 p.setAttribute('role', 'alert'); 162 p.textContent = (err && err.message) || 'No se ha podido añadir la oferta. Inténtalo de nuevo.'; 163 oferta.appendChild(p); 164 }); 165 }); 166})();
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.