/** * Script de validación directa para campos de DNI/documento * Versión: 1.0.1 */ // Iniciar cuando el DOM esté cargado document.addEventListener('DOMContentLoaded', inicializarValidador); // También intentar inicializar después de que la página esté completamente cargada window.addEventListener('load', inicializarValidador); // Definir variable global para controlar inicialización window.dniValidatorInitialized = window.dniValidatorInitialized || false; /** * Inicializa el validador de documentos */ function inicializarValidador() { // Evitar inicializar múltiples veces if (window.dniValidatorInitialized) return; console.log("Iniciando validador de documentos..."); // Inicializar la validación para los campos específicos const campos = [ document.getElementById('delivery_dni'), document.getElementById('field-dni'), ...Array.from(document.getElementsByName('dni')), ...Array.from(document.querySelectorAll('[data-validation*="isDniLite"]')) ].filter(campo => campo !== null); // Si no encontramos ningún campo, intentar una búsqueda más amplia if (campos.length === 0) { console.log("No se encontraron campos de DNI con los selectores principales. Buscando alternativas..."); // Buscar campos por sus atributos const camposAdicionales = [ ...Array.from(document.querySelectorAll('input[placeholder*="Identificaci"]')), ...Array.from(document.querySelectorAll('input[placeholder*="DNI"]')), ...Array.from(document.querySelectorAll('input[id*="dni"]')), ...Array.from(document.querySelectorAll('input[id*="DNI"]')), ...Array.from(document.querySelectorAll('input[name*="dni"]')), ...Array.from(document.querySelectorAll('input[name*="DNI"]')) ].filter(campo => campo !== null); campos.push(...camposAdicionales); } // Eliminar duplicados const camposUnicos = Array.from(new Set(campos)); console.log(`Se encontraron ${camposUnicos.length} campos para validar:`, camposUnicos); if (camposUnicos.length > 0) { camposUnicos.forEach(configurarCampoDNI); window.dniValidatorInitialized = true; // Configurar también la validación para campos que puedan cargarse dinámicamente configurarObservadorMutaciones(); // Integración con el sistema de validación existente if (window.$ && window.$.formUtils) { window.$.formUtils.addValidator({ name: 'isDniLite', validatorFunction: function(value) { return validarDocumento(value).valido; }, errorMessage: 'Documento de identidad no válido', errorMessageKey: 'badDNI' }); console.log("Integración con jQuery Form Validator completada"); } } else { console.log("No se encontraron campos de DNI/documento en la página actual"); } } /** * Configura un observador de mutaciones para detectar cambios en el DOM * y aplicar la validación a nuevos campos que puedan aparecer */ function configurarObservadorMutaciones() { // Crear un observador de mutaciones const observer = new MutationObserver((mutations) => { let newNodes = false; // Revisar si se han añadido nuevos nodos mutations.forEach(mutation => { if (mutation.addedNodes.length) { newNodes = true; } }); // Si hay nuevos nodos, buscar campos de DNI if (newNodes) { const nuevosCampos = [ ...Array.from(document.querySelectorAll('#delivery_dni:not([data-dni-validator])')), ...Array.from(document.querySelectorAll('#field-dni:not([data-dni-validator])')), ...Array.from(document.querySelectorAll('input[name="dni"]:not([data-dni-validator])')), ...Array.from(document.querySelectorAll('[data-validation*="isDniLite"]:not([data-dni-validator])')) ].filter(campo => campo !== null); if (nuevosCampos.length > 0) { console.log(`Se encontraron ${nuevosCampos.length} nuevos campos para validar`); nuevosCampos.forEach(configurarCampoDNI); } } }); // Iniciar la observación observer.observe(document.body, { childList: true, subtree: true }); console.log("Observador de mutaciones configurado para detectar nuevos campos"); } /** * Configura un campo de DNI con los eventos necesarios */ function configurarCampoDNI(campo) { // Marcar el campo como configurado campo.setAttribute('data-dni-validator', 'true'); console.log("Configurando campo:", campo.id || campo.name || "sin id/nombre"); // Validar al perder el foco campo.addEventListener('blur', function() { const resultado = validarDocumento(this.value); console.log("Resultado validación:", resultado); mostrarResultadoValidacion(this, resultado); }); // Convertir a mayúsculas durante la escritura campo.addEventListener('input', function() { if (/[a-zA-Z]/.test(this.value)) { const start = this.selectionStart; const end = this.selectionEnd; this.value = this.value.toUpperCase(); this.setSelectionRange(start, end); } }); // Configurar validación en el formulario const form = campo.closest('form'); if (form && !form.hasAttribute('data-dni-validator')) { form.setAttribute('data-dni-validator', 'true'); form.addEventListener('submit', function(e) { // Validar todos los campos de documento en este formulario const camposDNI = form.querySelectorAll('[data-dni-validator]'); let formValido = true; camposDNI.forEach(campoDNI => { // Solo validar campos visibles if (campoDNI.offsetParent !== null) { const resultado = validarDocumento(campoDNI.value); if (!resultado.valido) { formValido = false; e.preventDefault(); mostrarResultadoValidacion(campoDNI, resultado); campoDNI.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } }); return formValido; }); } // Añadir icono de información si es necesario // (Comentado para evitar posibles problemas de diseño) /* if (!campo.nextElementSibling || !campo.nextElementSibling.classList.contains('info-icon')) { const infoIcon = document.createElement('span'); infoIcon.className = 'info-icon'; infoIcon.innerHTML = ''; infoIcon.title = 'Ver formatos aceptados'; campo.insertAdjacentElement('afterend', infoIcon); infoIcon.addEventListener('click', function() { alert('Documentos aceptados:\\n\n' + '• Personas físicas (España):\n' + ' - DNI: 12345678Z\n' + ' - NIE: X1234567L\n' + ' - Pasaporte: AAA000000\n\n' + '• Empresas:\n' + ' - CIF español: B70915004\n' + ' - VAT europeo: ESB70915004, FR12345678901\n\n' + '• Otros países:\n' + ' - Portugal, Italia, Francia, Reino Unido, etc.'); }); } */ // Validación inicial const resultado = validarDocumento(campo.value); if (campo.value) { mostrarResultadoValidacion(campo, resultado); } } /** * Muestra el resultado de la validación */ function mostrarResultadoValidacion(inputElement, resultado) { // Crear ID único para el mensaje const mensajeId = (inputElement.id ? inputElement.id : 'dni') + '-validation-message'; // Buscar o crear elemento para mensajes let mensajeElement = document.getElementById(mensajeId); if (!mensajeElement) { mensajeElement = document.createElement('div'); mensajeElement.id = mensajeId; mensajeElement.style.fontSize = '12px'; mensajeElement.style.marginTop = '5px'; mensajeElement.style.marginBottom = '5px'; // Insertar después del campo o su contenedor más cercano if (inputElement.parentNode) { inputElement.parentNode.appendChild(mensajeElement); } } // Actualizar mensaje según resultado if (!resultado.valido) { // DNI incompleto if (resultado.tipo === 'DNI_incompleto') { mensajeElement.textContent = resultado.mensaje || 'DNI incompleto. Añade la letra.'; // Calcular letra correcta if (/^\d{8}$/.test(inputElement.value.trim())) { const letras = 'TRWAGMYFPDXBNJZSQVHLCKE'; const letraCalculada = letras.charAt(parseInt(inputElement.value.trim()) % 23); mensajeElement.textContent += ' La letra correcta es: ' + letraCalculada; } } // DNI con letra incorrecta else if (resultado.tipo === 'DNI_letra_incorrecta') { const numero = inputElement.value.trim().substring(0, 8); const letras = 'TRWAGMYFPDXBNJZSQVHLCKE'; const letraCalculada = letras.charAt(parseInt(numero) % 23); mensajeElement.textContent = 'La letra del DNI no es correcta. Debería ser: ' + letraCalculada; } // NIE con letra incorrecta else if (resultado.tipo === 'NIE_letra_incorrecta') { const valor = inputElement.value.trim().toUpperCase(); const primera = valor.charAt(0); const numero = valor.substring(1, 8); let numeroCompleto; switch (primera) { case 'X': numeroCompleto = '0' + numero; break; case 'Y': numeroCompleto = '1' + numero; break; case 'Z': numeroCompleto = '2' + numero; break; } const letras = 'TRWAGMYFPDXBNJZSQVHLCKE'; const letraCalculada = letras.charAt(parseInt(numeroCompleto) % 23); mensajeElement.textContent = 'La letra del NIE no es correcta. Debería ser: ' + letraCalculada; } // Formato similar a un DNI pero incorrecto else if (resultado.tipo === 'formato_similar_dni') { mensajeElement.textContent = 'Formato similar a un DNI/NIE pero incorrecto. Verifica el documento.'; } // Otros errores else { mensajeElement.textContent = 'Documento no válido. Verifica el formato.'; } // Aplicar estilos para errores mensajeElement.style.color = '#d9534f'; // Rojo inputElement.style.borderColor = '#d9534f'; // Añadir clases de error según el tema de PrestaShop inputElement.classList.add('is-invalid'); inputElement.classList.remove('valid'); inputElement.classList.add('error'); } else { // Documento válido let tipoDocumento = getTipoDocumentoNombre(resultado.tipo); mensajeElement.textContent = 'Documento válido: ' + tipoDocumento; mensajeElement.style.color = '#5cb85c'; // Verde inputElement.style.borderColor = '#5cb85c'; // Añadir clases de validez según el tema de PrestaShop inputElement.classList.remove('is-invalid', 'error'); inputElement.classList.add('is-valid', 'valid'); } } /** * Validar documento de identidad */ function validarDocumento(value) { if (!value) return { valido: false, tipo: 'desconocido' }; value = value.trim().toUpperCase(); // Caso especial: DNI incompleto (8 dígitos) if (/^\d{8}$/.test(value)) { return { valido: false, tipo: 'DNI_incompleto', mensaje: 'Parece un DNI español sin letra. Añade la letra correcta.' }; } // Validar CIF de empresa española if (validarCIF(value)) { return { valido: true, tipo: 'CIF_ESP' }; } // Validar VAT europeo if (validarVAT(value)) { return { valido: true, tipo: 'VAT_EU' }; } // Caso especial: formato similar a DNI (7 dígitos + 1 letra) if (/^\d{7}[A-Z]$/.test(value)) { return { valido: false, tipo: 'formato_similar_dni', mensaje: 'Formato similar a un DNI pero incorrecto (7 dígitos + letra).' }; } // Validar DNI español if (validarDNI(value)) { return { valido: true, tipo: 'DNI_ESP' }; } else if (/^\d{8}[A-Z]$/.test(value)) { // DNI con letra incorrecta return { valido: false, tipo: 'DNI_letra_incorrecta', mensaje: 'La letra del DNI no es correcta.' }; } // Validar NIE if (validarNIE(value)) { return { valido: true, tipo: 'NIE_ESP' }; } else if (/^[XYZ]\d{7}[A-Z]$/.test(value)) { // NIE con letra incorrecta return { valido: false, tipo: 'NIE_letra_incorrecta', mensaje: 'La letra del NIE no es correcta.' }; } // Validar pasaporte español if (validarPasaporteEspanol(value)) { return { valido: true, tipo: 'pasaporte_ESP' }; } // Validar NIF Portugal if (validarNIFPortugal(value)) { return { valido: true, tipo: 'NIF_PT' }; } // Validar Codice Fiscale Italia if (validarCodiceFiscaleItalia(value)) { return { valido: true, tipo: 'CF_IT' }; } // Validar Carte Nationale d'Identité Francia if (validarCNIFrancia(value)) { return { valido: true, tipo: 'CNI_FR' }; } // Validar National Insurance Number UK if (validarNINOReinoUnido(value)) { return { valido: true, tipo: 'NINO_UK' }; } // Validar pasaporte extranjero if (validarPasaporteExtranjero(value)) { return { valido: true, tipo: 'pasaporte_extranjero' }; } return { valido: false, tipo: 'desconocido' }; } // Resto de funciones (validaciones específicas) /** * Validar DNI español */ function validarDNI(dni) { dni = dni.toUpperCase(); const dniRegex = /^(\d{8})([A-Z])$/; if (!dniRegex.test(dni)) return false; const match = dni.match(dniRegex); const numero = match[1]; const letra = match[2]; // Calcular letra correcta const letras = 'TRWAGMYFPDXBNJZSQVHLCKE'; const letraCalculada = letras.charAt(parseInt(numero) % 23); return letra === letraCalculada; } /** * Validar NIE */ function validarNIE(nie) { nie = nie.toUpperCase(); const nieRegex = /^([XYZ])(\d{7})([A-Z])$/; if (!nieRegex.test(nie)) return false; const match = nie.match(nieRegex); const primera = match[1]; const numero = match[2]; const letra = match[3]; // Reemplazar la primera letra con su equivalente numérico let numeroCompleto; switch (primera) { case 'X': numeroCompleto = '0' + numero; break; case 'Y': numeroCompleto = '1' + numero; break; case 'Z': numeroCompleto = '2' + numero; break; } // Calcular letra correcta const letras = 'TRWAGMYFPDXBNJZSQVHLCKE'; const letraCalculada = letras.charAt(parseInt(numeroCompleto) % 23); return letra === letraCalculada; } /** * Validar CIF español */ function validarCIF(cif) { cif = cif.toUpperCase(); // Si es un VAT español, quitar el prefijo ES if (/^ES[A-Z0-9]{9}$/.test(cif)) { cif = cif.substring(2); } // Comprobar formato del CIF const cifRegex = /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/; if (!cifRegex.test(cif)) return false; const match = cif.match(cifRegex); const letra = match[1]; const numero = match[2]; const control = match[3]; // Calcular dígito de control let suma = 0; // Suma dígitos pares for (let i = 1; i < 7; i += 2) { suma += parseInt(numero.charAt(i)); } // Suma dígitos impares (multiplicados por 2) for (let i = 0; i < 7; i += 2) { let temp = parseInt(numero.charAt(i)) * 2; if (temp > 9) { temp = Math.floor(temp/10) + (temp % 10); } suma += temp; } // Calcular el dígito de control let controlCalculado = (10 - (suma % 10)) % 10; // Para ciertos tipos de entidades, el control es numérico const letrasCifNumero = 'ABCDEFGHJUV'; if (letrasCifNumero.indexOf(letra) >= 0) { return controlCalculado.toString() === control; } else { // Para el resto, el control es una letra const letrasControl = 'JABCDEFGHI'; return letrasControl.charAt(controlCalculado) === control; } } /** * Validar VAT europeo */ function validarVAT(vat) { vat = vat.toUpperCase(); // España (ESB12345678) if (/^ES[A-Z0-9]{9}$/.test(vat)) { return validarCIF(vat.substring(2)); } // Portugal (PT123456789) if (/^PT\d{9}$/.test(vat)) { return validarNIFPortugal(vat.substring(2)); } // Francia (FR12345678901) if (/^FR[A-Z0-9]{11}$/.test(vat)) { return true; // Validación simplificada } // Italia (IT12345678901) if (/^IT\d{11}$/.test(vat)) { return true; // Validación simplificada } // Reino Unido (GB123456789, GB123456789012) if (/^GB(\d{9}|\d{12})$/.test(vat)) { return true; // Validación simplificada } // Alemania (DE123456789) if (/^DE\d{9}$/.test(vat)) { return true; // Validación simplificada } return false; } /** * Validar pasaporte español */ function validarPasaporteEspanol(pasaporte) { pasaporte = pasaporte.toUpperCase(); const pasaporteRegex = /^[A-Z]{3}\d{6}$/; return pasaporteRegex.test(pasaporte); } /** * Validar NIF Portugal */ function validarNIFPortugal(nif) { const nifRegex = /^(\d{9})$/; if (!nifRegex.test(nif)) return false; // Algoritmo de validación const numero = nif.substring(0, 8); const control = parseInt(nif.charAt(8), 10); let suma = 0; for (let i = 0; i < 8; i++) { suma += parseInt(numero.charAt(i)) * (9 - i); } let resto = suma % 11; let checkDigit; if (resto === 0 || resto === 1) { checkDigit = 0; } else { checkDigit = 11 - resto; } return control === checkDigit; } /** * Validar Codice Fiscale Italia */ function validarCodiceFiscaleItalia(cf) { cf = cf.toUpperCase(); const cfRegex = /^[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]$/; return cfRegex.test(cf); } /** * Validar Carte Nationale d'Identité Francia */ function validarCNIFrancia(cni) { const cniRegex = /^\d{12}$/; return cniRegex.test(cni); } /** * Validar National Insurance Number UK */ function validarNINOReinoUnido(nino) { nino = nino.toUpperCase(); const ninoRegex = /^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]\d{6}[A-D]$/; return ninoRegex.test(nino); } /** * Validar pasaporte extranjero */ function validarPasaporteExtranjero(pasaporte) { pasaporte = pasaporte.toUpperCase(); // 1. Longitud 7-9 caracteres if (pasaporte.length < 7 || pasaporte.length > 9) return false; // 2. Patrón alfanumérico const pasaporteExtRegex = /^[A-Z0-9]{7,9}$/; if (!pasaporteExtRegex.test(pasaporte)) return false; // 3. No confundir con DNI y formatos similares if (/^\d{8}$/.test(pasaporte)) return false; if (/^\d{7}[A-Z]$/.test(pasaporte)) return false; if (/^\d{8}[A-Z]$/.test(pasaporte)) return false; // 4. No confundir con NIE o CIF if (/^[A-Z]\d{7}[A-Z]$/.test(pasaporte)) { // Si primera letra es X, Y, Z (NIE) o letras de CIF const primeraLetra = pasaporte.charAt(0); if ('XYZ'.includes(primeraLetra)) return false; if ('ABCDEFGHJKLMNPQRSUVW'.includes(primeraLetra) && validarCIF(pasaporte)) return false; } // 5. Otros casos especiales if (/^\d{9}$/.test(pasaporte)) { const primeros8 = pasaporte.substring(0, 8); if (/^[0-7]\d{7}$/.test(primeros8)) return false; } return true; } /** * Obtener nombre descriptivo del tipo de documento */ function getTipoDocumentoNombre(tipo) { switch(tipo) { case 'DNI_ESP': return 'DNI español'; case 'NIE_ESP': return 'NIE'; case 'pasaporte_ESP': return 'Pasaporte español'; case 'CIF_ESP': return 'CIF de empresa española'; case 'VAT_EU': return 'VAT Number europeo'; case 'NIF_PT': return 'NIF portugués'; case 'CF_IT': return 'Codice Fiscale italiano'; case 'CNI_FR': return 'Carte d\'identité francesa'; case 'NINO_UK': return 'National Insurance Number británico'; case 'pasaporte_extranjero': return 'Pasaporte extranjero'; default: return 'Documento válido'; } } // Iniciar validador en caso de que el evento DOMContentLoaded ya haya ocurrido if (document.readyState === 'complete' || document.readyState === 'interactive') { setTimeout(inicializarValidador, 1); }

Los más vendidos

Juego de ruedas SPEED MAX 89A Juego de ruedas SPEED MAX 89A 2
  • Nuevo
Consultar entrega.
En Línea

Juego de ruedas SPEED MAX 89A

SNOW WHITE
100.2.001
33,00 €
Las ruedas para calle/exterior de Snow White InLines. Han sido creadas para rodar suavemente y con gran velocidad en superficies exteriores como pistas de cemento y terrazo. Reduce la fricción en las piruetas. Aportan la amortiguación, agarre y rebote ideal que todo patinador busca. Su composición permite un excelente agarre y control de los filos,...
Juego de ruedas SPIRAL 84A Juego de ruedas SPIRAL 84A 2
  • Nuevo
Consultar entrega.
En Línea

Juego de ruedas SPIRAL 84A

100.2.002
33,00 €
Las Ruedas SPIRAL utilizan poliuretano SHR (Super High Rebound) de alto grado de BASF con una fórmula especial creada por el laboratorio de ruedas en California, EE. UU. El porcentaje de rebote mide hasta un 80% para compensar la absorción de impactos en el parquet. Aunque tiene una dureza de 84A, Spiral ® todavía ofrece un excelente agarre y control de...
Product added to wishlist
Product added to compare.