PageSourceSearch

https://musicalsanfrancisco.es/wp-content/plugins/minimal-extras/assets/front.js?ver=0.4.2

js musicalsanfrancisco.es collected 2026-10-06 15:00:30 UTC 6,405 bytes, 166 lines download raw bytes

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.