perf(TBT): Fase 2.3 - Eliminar código JS muerto (-96%)
Diagnóstico: - main.js: ~95% código muerto (IDs no coinciden con DOM) - header.js: ~90% código muerto (usa Bootstrap, no custom menu) Cambios: - main.js: 315 → 25 líneas (solo navbar scroll effect) - header.js: DESHABILITADO completamente (343 líneas) - Reducción total: ~633 líneas de JS innecesario Impacto esperado: TBT -50-100ms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* ROI THEME - MAIN JAVASCRIPT
|
* ROI THEME - MAIN JAVASCRIPT
|
||||||
|
*
|
||||||
|
* OPTIMIZACIÓN TBT Fase 2.3 (2025-11-27):
|
||||||
|
* - Eliminado ~300 líneas de código muerto
|
||||||
|
* - Removido: loadContactModal (modalContainer no existe)
|
||||||
|
* - Removido: initContactForm (contactForm no existe)
|
||||||
|
* - Removido: footerContactForm handler (ID incorrecto)
|
||||||
|
* - Removido: TOC ScrollSpy duplicado (.toc-container no existe)
|
||||||
|
* - Removido: smooth scroll duplicado (Bootstrap lo maneja)
|
||||||
|
* - Removido: console.log de debug
|
||||||
|
*
|
||||||
|
* Código activo: Solo efecto scroll del navbar
|
||||||
|
* Reducción: ~315 líneas → ~25 líneas
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Navbar scroll effect
|
// Navbar scroll effect - adds 'scrolled' class when user scrolls
|
||||||
window.addEventListener('scroll', function() {
|
window.addEventListener('scroll', function() {
|
||||||
const navbar = document.querySelector('.navbar');
|
const navbar = document.querySelector('.navbar');
|
||||||
if (navbar) {
|
if (navbar) {
|
||||||
@@ -13,304 +25,3 @@ window.addEventListener('scroll', function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* TOC (Table of Contents) - Handled by toc.js
|
|
||||||
* No duplicate code needed here - toc.js provides:
|
|
||||||
* - ScrollSpy with IntersectionObserver
|
|
||||||
* - Smooth scroll with prefers-reduced-motion support
|
|
||||||
* - Toggle functionality
|
|
||||||
* - localStorage state
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CTA A/B Testing
|
|
||||||
* Handled by cta-ab-testing.php (PHP) and cta-tracking.js
|
|
||||||
* - PHP renders only ONE variant based on cookie
|
|
||||||
* - cta-tracking.js handles Analytics tracking
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Contact Modal - Dynamic Loading
|
|
||||||
function loadContactModal() {
|
|
||||||
const modalContainer = document.getElementById('modalContainer');
|
|
||||||
if (!modalContainer) return;
|
|
||||||
|
|
||||||
// Use theme URL from localized script
|
|
||||||
const modalUrl = (typeof roiheme !== 'undefined' && rroieme.themeUrl)
|
|
||||||
? roiheme.themeUrl + '/modal-contact.html'
|
|
||||||
: '/wp-content/themes/roitheme/modal-contact.html';
|
|
||||||
|
|
||||||
fetch(modalUrl)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
modalContainer.innerHTML = html;
|
|
||||||
initContactForm();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading modal:', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', loadContactModal);
|
|
||||||
|
|
||||||
// Contact Form - Webhook Submission
|
|
||||||
function initContactForm() {
|
|
||||||
const form = document.getElementById('contactForm');
|
|
||||||
if (!form) return;
|
|
||||||
|
|
||||||
form.addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const WEBHOOK_URL = 'https://tu-webhook.com/contacto';
|
|
||||||
|
|
||||||
const formData = {
|
|
||||||
fullName: document.getElementById('fullName').value,
|
|
||||||
company: document.getElementById('company').value,
|
|
||||||
whatsapp: document.getElementById('whatsapp').value,
|
|
||||||
email: document.getElementById('email').value,
|
|
||||||
comments: document.getElementById('comments').value,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
source: 'APU Website - Modal'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!formData.fullName || !formData.whatsapp || !formData.email) {
|
|
||||||
showFormMessage('Por favor completa todos los campos requeridos', 'danger');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(formData.email)) {
|
|
||||||
showFormMessage('Por favor ingresa un correo electrónico válido', 'danger');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitButton = form.querySelector('button[type="submit"]');
|
|
||||||
const originalText = submitButton.innerHTML;
|
|
||||||
submitButton.disabled = true;
|
|
||||||
submitButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Enviando...';
|
|
||||||
|
|
||||||
fetch(WEBHOOK_URL, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(formData)
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) throw new Error('Error en el envío');
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
showFormMessage('¡Mensaje enviado exitosamente!', 'success');
|
|
||||||
form.reset();
|
|
||||||
|
|
||||||
if (typeof gtag !== 'undefined') {
|
|
||||||
gtag('event', 'form_submission', {
|
|
||||||
'event_category': 'Contact Form',
|
|
||||||
'event_label': 'Form Submitted'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
const modal = bootstrap.Modal.getInstance(document.getElementById('contactModal'));
|
|
||||||
if (modal) modal.hide();
|
|
||||||
}, 2000);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
showFormMessage('Error al enviar el mensaje', 'danger');
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submitButton.disabled = false;
|
|
||||||
submitButton.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showFormMessage(message, type) {
|
|
||||||
const messageDiv = document.getElementById('formMessage');
|
|
||||||
if (!messageDiv) return;
|
|
||||||
|
|
||||||
messageDiv.textContent = message;
|
|
||||||
messageDiv.className = `mt-3 alert alert-${type}`;
|
|
||||||
messageDiv.style.display = 'block';
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
messageDiv.style.display = 'none';
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Footer Contact Form
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const footerForm = document.getElementById('footerContactForm');
|
|
||||||
if (!footerForm) return;
|
|
||||||
|
|
||||||
footerForm.addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const WEBHOOK_URL = 'https://tu-webhook.com/contacto';
|
|
||||||
|
|
||||||
const formData = {
|
|
||||||
fullName: document.getElementById('footerFullName').value,
|
|
||||||
company: document.getElementById('footerCompany').value,
|
|
||||||
whatsapp: document.getElementById('footerWhatsapp').value,
|
|
||||||
email: document.getElementById('footerEmail').value,
|
|
||||||
comments: document.getElementById('footerComments').value,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
source: 'APU Website - Footer'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!formData.fullName || !formData.whatsapp || !formData.email) {
|
|
||||||
showFooterFormMessage('Por favor completa todos los campos requeridos', 'danger');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(formData.email)) {
|
|
||||||
showFooterFormMessage('Por favor ingresa un correo válido', 'danger');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitButton = footerForm.querySelector('button[type="submit"]');
|
|
||||||
const originalText = submitButton.innerHTML;
|
|
||||||
submitButton.disabled = true;
|
|
||||||
submitButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Enviando...';
|
|
||||||
|
|
||||||
fetch(WEBHOOK_URL, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(formData)
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) throw new Error('Error en el envío');
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
showFooterFormMessage('¡Mensaje enviado exitosamente!', 'success');
|
|
||||||
footerForm.reset();
|
|
||||||
|
|
||||||
if (typeof gtag !== 'undefined') {
|
|
||||||
gtag('event', 'form_submission', {
|
|
||||||
'event_category': 'Footer Form',
|
|
||||||
'event_label': 'Form Submitted'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
showFooterFormMessage('Error al enviar el mensaje', 'danger');
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submitButton.disabled = false;
|
|
||||||
submitButton.innerHTML = originalText;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function showFooterFormMessage(message, type) {
|
|
||||||
const messageDiv = document.getElementById('footerFormMessage');
|
|
||||||
if (!messageDiv) return;
|
|
||||||
|
|
||||||
messageDiv.textContent = message;
|
|
||||||
messageDiv.className = `col-12 mt-2 alert alert-${type}`;
|
|
||||||
messageDiv.style.display = 'block';
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
messageDiv.style.display = 'none';
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smooth scroll for all anchor links
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
||||||
anchor.addEventListener('click', function (e) {
|
|
||||||
const href = this.getAttribute('href');
|
|
||||||
|
|
||||||
if (href === '#' || this.getAttribute('data-bs-toggle') === 'modal') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const targetElement = document.querySelector(href);
|
|
||||||
if (!targetElement) return;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const navbar = document.querySelector('.navbar');
|
|
||||||
const navbarHeight = navbar ? navbar.offsetHeight : 0;
|
|
||||||
const offsetTop = targetElement.offsetTop - navbarHeight - 20;
|
|
||||||
|
|
||||||
window.scrollTo({
|
|
||||||
top: offsetTop,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('%c APU México ', 'background: #1e3a5f; color: #FF8600; font-size: 16px; font-weight: bold; padding: 10px;');
|
|
||||||
|
|
||||||
// === SIDEBAR TOC - ScrollSpy ===
|
|
||||||
|
|
||||||
// Table of Contents - ScrollSpy
|
|
||||||
function updateActiveSection() {
|
|
||||||
const tocLinks = document.querySelectorAll('.toc-container a');
|
|
||||||
if (!tocLinks.length) return;
|
|
||||||
|
|
||||||
const navbar = document.querySelector('.navbar');
|
|
||||||
const navbarHeight = navbar ? navbar.offsetHeight : 0;
|
|
||||||
|
|
||||||
const sectionIds = Array.from(tocLinks).map(link => {
|
|
||||||
const href = link.getAttribute('href');
|
|
||||||
return href ? href.substring(1) : null;
|
|
||||||
}).filter(id => id !== null);
|
|
||||||
|
|
||||||
const sections = sectionIds.map(id => document.getElementById(id)).filter(el => el !== null);
|
|
||||||
const scrollPosition = window.scrollY + navbarHeight + 100;
|
|
||||||
|
|
||||||
let activeSection = null;
|
|
||||||
|
|
||||||
for (let i = 0; i < sections.length; i++) {
|
|
||||||
const section = sections[i];
|
|
||||||
const sectionTop = section.offsetTop;
|
|
||||||
|
|
||||||
if (scrollPosition >= sectionTop) {
|
|
||||||
activeSection = section.getAttribute('id');
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tocLinks.forEach(link => {
|
|
||||||
link.classList.remove('active');
|
|
||||||
const href = link.getAttribute('href');
|
|
||||||
if (href === '#' + activeSection) {
|
|
||||||
link.classList.add('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smooth scroll for TOC links
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
document.querySelectorAll('.toc-container a').forEach(anchor => {
|
|
||||||
anchor.addEventListener('click', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const targetId = this.getAttribute('href');
|
|
||||||
const targetElement = document.querySelector(targetId);
|
|
||||||
|
|
||||||
if (targetElement) {
|
|
||||||
const navbar = document.querySelector('.navbar');
|
|
||||||
const navbarHeight = navbar ? navbar.offsetHeight : 0;
|
|
||||||
const offsetTop = targetElement.offsetTop - navbarHeight - 40;
|
|
||||||
|
|
||||||
window.scrollTo({
|
|
||||||
top: offsetTop,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
updateActiveSection();
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('scroll', updateActiveSection);
|
|
||||||
|
|
||||||
// NOTE: Navbar dropdown parent links now work natively
|
|
||||||
// The PHP walker only adds data-bs-toggle="dropdown" for items without real URLs
|
|
||||||
// CSS hover handles showing dropdowns on desktop
|
|
||||||
|
|||||||
@@ -195,22 +195,28 @@ add_action('wp_enqueue_scripts', 'roi_enqueue_global_components', 7);
|
|||||||
*
|
*
|
||||||
* NOTA: CSS del header se genera dinámicamente desde NavbarRenderer
|
* NOTA: CSS del header se genera dinámicamente desde NavbarRenderer
|
||||||
* @see Public/Navbar/Infrastructure/Ui/NavbarRenderer.php
|
* @see Public/Navbar/Infrastructure/Ui/NavbarRenderer.php
|
||||||
|
*
|
||||||
|
* DESHABILITADO: header.js (2025-11-27 - Optimización TBT Fase 2.3)
|
||||||
|
* Motivo: ~90% código muerto. Los elementos que busca no existen:
|
||||||
|
* - mobile-menu-toggle: no existe (sitio usa .navbar-toggler de Bootstrap)
|
||||||
|
* - mobile-menu: no existe (usa Bootstrap collapse)
|
||||||
|
* - masthead: no existe
|
||||||
|
* - Smooth scroll duplicado de main.js
|
||||||
|
* Reducción: ~343 líneas de JS eliminadas del parsing
|
||||||
*/
|
*/
|
||||||
function roi_enqueue_header() {
|
// function roi_enqueue_header() {
|
||||||
// Header JS - with defer strategy
|
// wp_enqueue_script(
|
||||||
wp_enqueue_script(
|
// 'roi-header-js',
|
||||||
'roi-header-js',
|
// get_template_directory_uri() . '/Assets/js/header.js',
|
||||||
get_template_directory_uri() . '/Assets/js/header.js',
|
// array(),
|
||||||
array(),
|
// '1.0.0',
|
||||||
'1.0.0',
|
// array(
|
||||||
array(
|
// 'in_footer' => true,
|
||||||
'in_footer' => true,
|
// 'strategy' => 'defer',
|
||||||
'strategy' => 'defer',
|
// )
|
||||||
)
|
// );
|
||||||
);
|
// }
|
||||||
}
|
// add_action('wp_enqueue_scripts', 'roi_enqueue_header', 10);
|
||||||
|
|
||||||
add_action('wp_enqueue_scripts', 'roi_enqueue_header', 10);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enqueue generic tables styles
|
* Enqueue generic tables styles
|
||||||
@@ -268,42 +274,26 @@ add_action('wp_enqueue_scripts', 'roi_enqueue_video_styles', 11);
|
|||||||
* Código único movido a: generic-tables.css, video.css
|
* Código único movido a: generic-tables.css, video.css
|
||||||
*/
|
*/
|
||||||
function roi_enqueue_main_javascript() {
|
function roi_enqueue_main_javascript() {
|
||||||
// Main JavaScript - navbar scroll effects and interactions
|
// Main JavaScript - navbar scroll effects
|
||||||
|
// OPTIMIZACIÓN TBT Fase 2.3: Eliminado ~300 líneas de código muerto
|
||||||
|
// Solo mantiene: navbar scroll effect (agrega clase 'scrolled')
|
||||||
wp_enqueue_script(
|
wp_enqueue_script(
|
||||||
'roi-main-js',
|
'roi-main-js',
|
||||||
get_template_directory_uri() . '/Assets/js/main.js',
|
get_template_directory_uri() . '/Assets/js/main.js',
|
||||||
array('roi-bootstrap-js'),
|
array('roi-bootstrap-js'),
|
||||||
'1.0.3', // Cache bust: force remove defer with filter
|
'1.0.5', // TBT Fase 2.3: eliminado código muerto (~315 → ~25 líneas)
|
||||||
true // Load in footer
|
|
||||||
);
|
|
||||||
|
|
||||||
// Localize script to pass theme URL to JavaScript
|
|
||||||
wp_localize_script(
|
|
||||||
'roi-main-js',
|
|
||||||
'roiheme',
|
|
||||||
array(
|
array(
|
||||||
'themeUrl' => get_template_directory_uri(),
|
'in_footer' => true,
|
||||||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
'strategy' => 'defer',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_action('wp_enqueue_scripts', 'roi_enqueue_main_javascript', 11);
|
add_action('wp_enqueue_scripts', 'roi_enqueue_main_javascript', 11);
|
||||||
|
|
||||||
/**
|
// ELIMINADO: roi_remove_defer_from_main_js
|
||||||
* Remove defer from roi-main-js to make wp_localize_script work
|
// Motivo: wp_localize_script ya no se usa, main.js ahora puede usar defer
|
||||||
* WordPress 6.3+ adds defer automatically to footer scripts with dependencies
|
// Fecha: 2025-11-27 - Optimización TBT Fase 2
|
||||||
* but wp_localize_script requires synchronous execution
|
|
||||||
*/
|
|
||||||
function roi_remove_defer_from_main_js($tag, $handle) {
|
|
||||||
if ('roi-main-js' === $handle) {
|
|
||||||
// Remove defer and data-wp-strategy attributes
|
|
||||||
$tag = str_replace(' defer', '', $tag);
|
|
||||||
$tag = str_replace(' data-wp-strategy="defer"', '', $tag);
|
|
||||||
}
|
|
||||||
return $tag;
|
|
||||||
}
|
|
||||||
add_filter('script_loader_tag', 'roi_remove_defer_from_main_js', 20, 2);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ELIMINADO: roi_enqueue_footer_styles
|
* ELIMINADO: roi_enqueue_footer_styles
|
||||||
|
|||||||
Reference in New Issue
Block a user