1document.addEventListener("DOMContentLoaded", function () { 2 // 1. ANIMACIONES DE SCROLL (Intersection Observer) 3 const animatedBlocks = document.querySelectorAll('.animate-block'); 4 const observerOptions = { 5 root: null, 6 rootMargin: '0px', 7 threshold: 0.15 8 }; 9 const observer = new IntersectionObserver((entries, observer) => { 10 entries.forEach(entry => { 11 if (entry.isIntersecting) { 12 entry.target.classList.add('is-visible'); 13 observer.unobserve(entry.target); 14 } 15 }); 16 }, observerOptions); 17 animatedBlocks.forEach(block => { 18 observer.observe(block); 19 }); 20 21 // 2. EFECTO SCROLL DEL HEADER (Fondo Blanco) 22 const header = document.querySelector('.site-header'); 23 if (header) { 24 window.addEventListener('scroll', () => { 25 if (window.scrollY > 50) { 26 header.classList.add('is-scrolled'); 27 } else { 28 header.classList.remove('is-scrolled'); 29 } 30 }); 31 } 32 33 // 2b. AJUSTES DEL BUSCADOR DEL HEADER (medidos con JS para no depender de estimaciones) 34 function ajustarHeaderYBuscador() { 35 // a) Ancho del buscador de desktop = ancho real del menú de navegación 36 const nav = document.querySelector('.nav-search-wrap .main-navigation'); 37 const searchDesktop = document.querySelector('.header-search-desktop'); 38 if (nav && searchDesktop && nav.offsetWidth > 0) { 39 searchDesktop.style.width = nav.offsetWidth + 'px'; 40 } 41 42 // b) Altura real del header, para que el contenido de las páginas no quede tapado 43 if (header) { 44 document.documentElement.style.setProperty('--qntlc-header-h', header.offsetHeight + 'px'); 45 } 46 } 47 ajustarHeaderYBuscador(); 48 window.addEventListener('load', ajustarHeaderYBuscador); 49 window.addEventListener('resize', ajustarHeaderYBuscador); 50 51 // 3. LÃGICA DEL MENà MÃVIL 52 const mobileToggle = document.querySelector('.mobile-menu-toggle'); 53 const mainNav = document.querySelector('.main-navigation'); 54 const body = document.querySelector('body'); 55 if (mobileToggle && mainNav) { 56 mobileToggle.addEventListener('click', function () { 57 // Alterna las clases que abren y cierran el panel 58 mobileToggle.classList.toggle('is-active'); 59 mainNav.classList.toggle('is-active'); 60 61 if (header) header.classList.toggle('menu-open'); 62 if (body) body.classList.toggle('menu-open-body'); 63 }); 64 } 65 66 // 4. LÃGICA DEL CARRUSEL DE LIBROS (Solo se ejecuta si existe en la página) 67 const track = document.querySelector('.carousel-track'); 68 const prevBtn = document.querySelector('.prev-btn'); 69 const nextBtn = document.querySelector('.next-btn'); 70 if (track && prevBtn && nextBtn) { 71 const scrollAmount = 510; 72 nextBtn.addEventListener('click', () => { 73 track.scrollBy({ left: scrollAmount, behavior: 'smooth' }); 74 }); 75 prevBtn.addEventListener('click', () => { 76 track.scrollBy({ left: -scrollAmount, behavior: 'smooth' }); 77 }); 78 } 79}); 80 81// LÃGICA COPIAR LINK AL PORTAPAPELES 82function copiarAlPortapapeles(texto) { 83 navigator.clipboard.writeText(texto).then(() => { 84 const toast = document.getElementById('copy-toast'); 85 toast.classList.add('show'); 86 setTimeout(() => { 87 toast.classList.remove('show'); 88 }, 3000); 89 }).catch(err => { 90 console.error('Error al copiar: ', err); 91 }); 92} 93 94//LOGICA "ENVIANDO" MENSAJE DE CONTACTO 95document.getElementById('qntlc-contact-form')?.addEventListener('submit', function (e) { 96 e.preventDefault(); 97 const form = this; 98 const btn = document.getElementById('submit-btn'); 99 const btnText = document.getElementById('btn-text'); 100 const message = form.querySelector('.form-message'); 101 btn.disabled = true; 102 btnText.innerText = 'Enviando...'; 103 const formData = new FormData(form); 104 formData.append('action', 'procesar_contacto_qntlc'); 105 fetch(qntlc_ajax.ajax_url, { 106 method: 'POST', 107 body: formData 108 }) 109 .then(response => response.json()) 110 .then(data => { 111 btn.disabled = false;
112 btnText.innerText = 'Enviar Mensaje'; 113 if (message) { 114 message.textContent = data.data && data.data.message ? data.data.message : ''; 115 message.classList.toggle('is-error', !data.success); 116 message.classList.toggle('is-success', data.success); 117 } 118 if (data.success) { 119 form.reset(); 120 } 121 }) 122 .catch(error => { 123 btn.disabled = false; 124 btnText.innerText = 'Enviar Mensaje'; 125 if (message) { 126 message.textContent = 'Hubo un error. Intentá nuevamente más tarde.'; 127 message.classList.add('is-error'); 128 } 129 console.error('Error:', error); 130 }); 131}); 132 133// LÃGICA FORMULARIO DE SUSCRIPCIÃN (NEWSLETTER) 134document.querySelector('.newsletter-form')?.addEventListener('submit', function (e) { 135 e.preventDefault(); 136 const form = this; 137 const emailInput = form.querySelector('input[name="email"]'); 138 const btn = form.querySelector('button[type="submit"]'); 139 const message = form.parentElement.querySelector('.form-message'); 140 const btnTextOriginal = btn.innerText; 141 142 btn.disabled = true; 143 btn.innerText = 'Enviando...'; 144 145 const formData = new FormData(); 146 formData.append('action', 'qntlc_suscribir_newsletter'); 147 formData.append('email', emailInput.value); 148 149 fetch(qntlc_ajax.ajax_url, { 150 method: 'POST', 151 body: formData 152 }) 153 .then(response => response.json()) 154 .then(data => { 155 btn.disabled = false; 156 btn.innerText = btnTextOriginal; 157 if (message) { 158 message.textContent = data.data && data.data.message ? data.data.message : ''; 159 message.classList.toggle('is-error', !data.success); 160 message.classList.toggle('is-success', data.success); 161 } 162 if (data.success) { 163 form.reset(); 164 } 165 }) 166 .catch(error => { 167 btn.disabled = false; 168 btn.innerText = btnTextOriginal; 169 if (message) { 170 message.textContent = 'Hubo un error. Intentá nuevamente más tarde.'; 171 message.classList.add('is-error'); 172 } 173 console.error('Error:', error); 174 }); 175}); 176 177// LÃGICA FORMULARIOS DE "ENCARGAR MISAS" (Particular y Gregoriana) 178document.querySelectorAll('#qntlc-misa-particular-form, #qntlc-misa-gregoriana-form').forEach(function (form) { 179 form.addEventListener('submit', function (e) { 180 e.preventDefault(); 181 const btn = form.querySelector('button[type="submit"]'); 182 const btnText = btn.querySelector('.btn-text-misa'); 183 const message = form.querySelector('.form-message'); 184 const btnTextOriginal = btnText.innerText; 185 186 btn.disabled = true; 187 btnText.innerText = 'Enviando...'; 188 189 const formData = new FormData(form); 190 formData.append('action', 'procesar_misa_qntlc'); 191 192 fetch(qntlc_ajax.ajax_url, { 193 method: 'POST', 194 body: formData 195 }) 196 .then(response => response.json()) 197 .then(data => { 198 btn.disabled = false; 199 btnText.innerText = btnTextOriginal; 200 if (message) { 201 message.textContent = data.data && data.data.message ? data.data.message : ''; 202 message.classList.toggle('is-error', !data.success); 203 message.classList.toggle('is-success', data.success); 204 } 205 if (data.success) { 206 form.reset(); 207 } 208 }) 209 .catch(error => { 210 btn.disabled = false; 211 btnText.innerText = btnTextOriginal; 212 if (message) { 213 message.textContent = 'Hubo un error. Intentá nuevamente más tarde.'; 214 message.classList.add('is-error'); 215 } 216 console.error('Error:', error); 217 }); 218 }); 219});
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.