// Web Scraper Ultra Robusto - JavaScript document.addEventListener('DOMContentLoaded', function() { // Elementos del DOM const form = document.getElementById('scraper-form'); const urlInput = document.getElementById('url-input'); const nameInput = document.getElementById('name-input'); const formatRadios = document.querySelectorAll('input[name="formato"]'); const exampleItems = document.querySelectorAll('.example-item'); const statusContainer = document.getElementById('status-container'); const statusText = document.getElementById('status-text'); const resultsSection = document.getElementById('results-section'); const resultsContainer = document.getElementById('results-container'); const pdfFilename = document.getElementById('pdf-filename'); const txtFilename = document.getElementById('txt-filename'); const processBtn = form.querySelector('.btn-process'); // Estado de la aplicación let isProcessing = false; // Inicialización init(); function init() { // Configurar event listeners form.addEventListener('submit', handleFormSubmit); exampleItems.forEach(item => { item.addEventListener('click', handleExampleClick); }); // Configurar botones de descarga const downloadButtons = document.querySelectorAll('.btn-download'); downloadButtons.forEach(btn => { btn.addEventListener('click', handleDownload); }); console.log('🚀 Web Scraper Ultra Robusto inicializado correctamente'); } // Manejar envío del formulario function handleFormSubmit(e) { e.preventDefault(); if (isProcessing) return; const formData = getFormData(); if (!validateForm(formData)) { showError('Por favor, ingresa una URL válida'); return; } startProcessing(formData); } // Obtener datos del formulario function getFormData() { const selectedFormat = document.querySelector('input[name="formato"]:checked'); return { url: urlInput.value.trim(), formato: selectedFormat ? selectedFormat.value : 'Ambos', nombre: nameInput.value.trim() || generateDefaultName() }; } // Validar formulario function validateForm(data) { if (!data.url) return false; // Agregar protocolo si no existe if (!data.url.startsWith('http://') && !data.url.startsWith('https://')) { data.url = 'https://' + data.url; urlInput.value = data.url; } try { new URL(data.url); return true; } catch { return false; } } // Generar nombre por defecto function generateDefaultName() { const timestamp = new Date().toISOString().slice(0, 19).replace(/[:\-]/g, '').replace('T', '_'); return `scraping_${timestamp}`; } // Manejar clic en ejemplos function handleExampleClick(e) { if (isProcessing) return; const item = e.currentTarget; const url = item.dataset.url; const formato = item.dataset.formato; const nombre = item.dataset.nombre; // Llenar campos del formulario urlInput.value = url; nameInput.value = nombre; // Seleccionar radio button correspondiente const formatRadio = document.getElementById(`format-${formato.toLowerCase()}`); if (formatRadio) { formatRadio.checked = true; } // Efecto visual item.style.transform = 'scale(0.98)'; setTimeout(() => { item.style.transform = ''; }, 150); // Feedback visual showStatus('success', `✅ Ejemplo cargado: ${nombre}`); setTimeout(() => { showStatus('ready', 'Listo para procesar'); }, 2000); } // Iniciar procesamiento async function startProcessing(data) { isProcessing = true; processBtn.disabled = true; processBtn.textContent = '⏳ Procesando...'; try { // Fase 1: Conectando showStatus('processing', '🔄 Conectando con el servidor...'); await delay(800); // Fase 2: Analizando URL showStatus('processing', '🔍 Analizando URL y contenido...'); await delay(1200); // Fase 3: Extrayendo contenido showStatus('processing', '📥 Extrayendo contenido de la página...'); await delay(1000); // Fase 4: Generando archivos if (data.formato === 'PDF' || data.formato === 'Ambos') { showStatus('processing', '📄 Generando archivo PDF...'); await delay(1500); } if (data.formato === 'Texto' || data.formato === 'Ambos') { showStatus('processing', '📝 Generando archivo de texto...'); await delay(1000); } // Fase 5: Finalizando showStatus('processing', '✨ Finalizando procesamiento...'); await delay(600); // Éxito showProcessingSuccess(data); } catch (error) { showError('❌ Error durante el procesamiento: ' + error.message); } finally { isProcessing = false; processBtn.disabled = false; processBtn.textContent = '🚀 Procesar Página Web'; } } // Mostrar éxito del procesamiento function showProcessingSuccess(data) { showStatus('success', '🎉 ¡Procesamiento completado exitosamente!'); // Mostrar resultados updateResults(data); resultsContainer.style.display = 'block'; // Scroll suave a resultados resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); // Efecto de aparición resultsContainer.style.opacity = '0'; resultsContainer.style.transform = 'translateY(20px)'; setTimeout(() => { resultsContainer.style.transition = 'all 0.5s ease'; resultsContainer.style.opacity = '1'; resultsContainer.style.transform = 'translateY(0)'; }, 100); } // Actualizar resultados function updateResults(data) { const cleanName = sanitizeFilename(data.nombre); // Actualizar nombres de archivos pdfFilename.textContent = `${cleanName}.pdf`; txtFilename.textContent = `${cleanName}.txt`; // Mostrar/ocultar archivos según formato const resultItems = document.querySelectorAll('.result-item'); if (data.formato === 'PDF') { resultItems[0].style.display = 'block'; // PDF resultItems[1].style.display = 'none'; // Texto } else if (data.formato === 'Texto') { resultItems[0].style.display = 'none'; // PDF resultItems[1].style.display = 'block'; // Texto } else { resultItems[0].style.display = 'block'; // Ambos resultItems[1].style.display = 'block'; } // Simular tamaños de archivo aleatorios pero realistas const pdfSize = generateFileSize(1.5, 5.0, 'MB'); const txtSize = generateFileSize(20, 150, 'KB'); document.querySelector('.result-item:nth-child(1) .file-size').textContent = pdfSize; document.querySelector('.result-item:nth-child(2) .file-size').textContent = txtSize; } // Generar tamaño de archivo simulado function generateFileSize(min, max, unit) { const size = (Math.random() * (max - min) + min).toFixed(1); return `${size} ${unit}`; } // Limpiar nombre de archivo function sanitizeFilename(name) { return name.replace(/[^a-zA-Z0-9_\-]/g, '_').toLowerCase(); } // Manejar descarga function handleDownload(e) { const button = e.currentTarget; const originalText = button.textContent; // Simular descarga button.textContent = '⬇️ Descargando...'; button.disabled = true; setTimeout(() => { button.textContent = '✅ Descargado'; setTimeout(() => { button.textContent = originalText; button.disabled = false; }, 2000); }, 1500); // Mostrar mensaje de éxito showStatus('success', '✅ Archivo descargado correctamente'); setTimeout(() => { showStatus('ready', 'Listo para procesar'); }, 3000); } // Mostrar estado function showStatus(type, message) { const statusIcon = statusContainer.querySelector('.status-icon'); // Remover clases de estado anteriores statusContainer.classList.remove('status-processing', 'status-success', 'status-error'); switch (type) { case 'processing': statusContainer.classList.add('status-processing'); statusIcon.textContent = '⏳'; break; case 'success': statusContainer.classList.add('status-success'); statusIcon.textContent = '✅'; break; case 'error': statusContainer.classList.add('status-error'); statusIcon.textContent = '❌'; break; default: statusIcon.textContent = '⏳'; } statusText.textContent = message; // Efecto de pulso statusContainer.style.transform = 'scale(1.02)'; setTimeout(() => { statusContainer.style.transform = ''; }, 200); } // Mostrar error function showError(message) { showStatus('error', message); // Auto-ocultar después de 5 segundos setTimeout(() => { showStatus('ready', 'Listo para procesar'); }, 5000); } // Función de delay para simular procesamiento function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Validación en tiempo real de URL urlInput.addEventListener('input', function() { const url = this.value.trim(); if (url.length > 0) { try { // Agregar protocolo si no existe para validación let testUrl = url; if (!testUrl.startsWith('http://') && !testUrl.startsWith('https://')) { testUrl = 'https://' + testUrl; } new URL(testUrl); this.style.borderColor = 'var(--verde-exito)'; } catch { this.style.borderColor = 'var(--rojo-principal)'; } } else { this.style.borderColor = ''; } }); // Efectos hover mejorados para botones principales processBtn.addEventListener('mouseenter', function() { if (!this.disabled) { this.style.transform = 'translateY(-2px)'; } }); processBtn.addEventListener('mouseleave', function() { this.style.transform = ''; }); // Easter egg - Konami code let konamiCode = []; const konamiSequence = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]; // ↑↑↓↓←→←→BA document.addEventListener('keydown', function(e) { konamiCode.push(e.keyCode); if (konamiCode.length > konamiSequence.length) { konamiCode.shift(); } if (JSON.stringify(konamiCode) === JSON.stringify(konamiSequence)) { showStatus('success', '🎮 ¡Código Konami activado! Ultra modo desbloqueado 🚀'); document.body.style.animation = 'rainbow 2s ease-in-out'; setTimeout(() => { document.body.style.animation = ''; }, 2000); } }); // Animación rainbow para easter egg const style = document.createElement('style'); style.textContent = ` @keyframes rainbow { 0% { filter: hue-rotate(0deg); } 25% { filter: hue-rotate(90deg); } 50% { filter: hue-rotate(180deg); } 75% { filter: hue-rotate(270deg); } 100% { filter: hue-rotate(360deg); } } `; document.head.appendChild(style); console.log('🎯 Todas las funcionalidades cargadas correctamente'); console.log('💡 Tip: Prueba el código Konami para un easter egg'); });