/** * 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

Rodamientos sueltos ISB ABEC 9 Rodamientos sueltos ISB ABEC 9 2
  • Nuevo
Consultar entrega.
Rodamientos

Rodamientos sueltos ISB ABEC 9

ISB
30.004.1
1,35 €
Rodamientos 627-2RS Abec 9 Blue ISB · Aros y Bolas de acero Chrome Steel 100 Cr6 · Tapa guardapolvos en un lateral · Lubricación: Aceite Mobil · 2RS: Junta de goma (tapa) en un lateral del rodamiento · Tapas color VERDE · Precisión Abec 9 ATENCION: EL NUMERO DE RODAMIENTOS PARA UN CONJUNTO DE PATINES COMPLETO ES DE 16 UNIDADES. POR...
Aceite ISB para Rodamientos
  • Nuevo
Consultar entrega.
Accesorios En Línea

Aceite ISB para Rodamientos

ISB
30.201
3,50 €
Lubricante de alto rendimiento. Aceite para rodamientos. Botella de 10 ml.
Cordones Hockey AZEMAD Cordones Hockey AZEMAD 2
  • Nuevo
Consultar entrega.
Hockey sobre Patines

Cordones Hockey AZEMAD

Azemad
1.70001
3,00 €
Los cordones AZEMAD están diseñados para ofrecer una gran durabilidad y adaptarse al diseño de las botas Eclipse. Sin embargo, pueden utilizarse en cualquier tipo de bota. Con un aspecto de primera calidad y un tamaño adecuado para mantener los cordones apretados y seguros, los cordones -que a menudo se infravaloran- acaban teniendo una función muy...
Cintas para Sticks TAPE AZEMAD Cintas para Sticks TAPE AZEMAD 2
  • Nuevo
Consultar entrega.
Hockey sobre Patines

Cintas para Sticks TAPE AZEMAD

Azemad
1.11003
8,00 €
Cinta Adhesiva para Palos | Agarre y Control Óptimos Cinta Adhesiva para Palos ¡Pon tu agarre al máximo! Las cintas adhesivas AZEMAD Sticks son la solución ideal para jugadores que buscan mayor agarre y control en su stick, permitiendo una experiencia de juego más...
Rodilleras AZEMAD ECLIPSE (S/M/L/XL) Rodilleras AZEMAD ECLIPSE (S/M/L/XL) 2
  • Nuevo
Consultar entrega.
Hockey sobre Patines

Rodilleras AZEMAD ECLIPSE (S/M/L/XL)

Azemad
1.80004
55,00 €
Rodilleras Eclipse Protégete de las caídas Las Rodilleras AZEMAD Eclipse proporcionan un gran confort y seguridad para tus rodillas. Diseñadas ergonómicamente para adaptarse a diferentes anatomías, su geometría más ovalada hace que la rodillera se sienta como una prolongación natural...
Stick AZEMAD SUPER
  • Nuevo
Consultar entrega.
Azemad

Stick AZEMAD SUPER

Azemad
1.10003
73,00 €
El modelo AZEMAD Super es un stick para hockey sobre patines constituido por un mango fino y ligero. Con una pala laminada en madera revestida con material compuesto, tiene 90º de curvatura manteniendo la geometría convencional adaptada al estilo de juego moderno. Más flexibilidad, más destreza! El cable Super permite un dominio del stick cómodo sin...
Stick AZEMAD FLASH
  • Nuevo
Consultar entrega.
Azemad

Stick AZEMAD FLASH

Azemad
1.10025
72,00 €
El modelo FLASH Ferran Font tiene un diseño único, pero realmente destaca por su rigidez y equilibrio en comparación con el modelo estándar FLASH. Al igual que el modelo AZEMAD SPECIAL, tiene las mejores especificaciones de compromiso dado. Lo palo está hecho de un mango delgado y rígido con un vástago de madera laminado reforzado compuesto de 90º.
RODAMIENTOS ABEC 9 BLACK/BLUE RS ISB - 8 mm RODAMIENTOS ABEC 9 BLACK/BLUE RS ISB - 8 mm 2
  • Nuevo
Consultar entrega.
35,00 €
Rodamientos 608-2RS Abec 9 Black Inner RS Blue ISB Aros de color negro, con tratamiento Black Oxyde Coating Lubricación: Grasa Mobile 2RS: Junta de goma (tapas) a ambos lados del rodamiento Tapas color azul Precisión ABEC 9 Conjunto de 16 rodamientos + 4 UNIDADES GRATIS Medidas: Interior: 8 mm Exterior: 22 mm...
Frenos AZEMAD Hockey Frenos AZEMAD Hockey 2
  • Nuevo
Consultar entrega.
Frenos Hockey

Frenos AZEMAD Hockey

Azemad
1.50001
23,00 €
Frenos para Patines | Seguridad y Control en tu Patinaje Frenos para Patines ¡Un detalle esencial para controlar tu patinaje! Los frenos para patines AZEMAD fueron diseñados para ofrecer al patinador un buen agarre y capacidad de respuesta al frenar. Desarrollados...
Stick AZEMAD AZEX SPECIAL
  • Nuevo
Consultar entrega.
Azemad

Stick AZEMAD AZEX SPECIAL

Azemad
1.10013
75,00 €
¡Más comodidad, más equilibrio, más alcance! El mango SPECIAL permite una rigidez superior sin perjudicar al peso y dimensión del stick. Su geometría equilibrada aporta más confort al mango. La pala laminada en madera de 96º, recubierta con material compuesto, permite un control de bola igualmente rápido y con mayor amplitud. Su geometría...
Stick AZEMAD RV66 ELITE
  • Nuevo
Consultar entrega.
Azemad

Stick AZEMAD RV66 ELITE

Azemad
1.10028
79,00 €
¡Un clásico entre clásicos! Reinaldo Ventura se ha ganado el respetoy la admiración de todos nosotros, siendo su palmarés y larga carrera prueba de ello. Con AZEMAD el RV66 ELITE ha sido desarrollado para que el jugador obtenga un stick  con el equilibrio y manejo deseados. Mango súper delgado y rígido ofrece una mejorergonomía de agarre más...
Juego de ruedas AZEMAD DRIVE 92 A
  • Nuevo
Consultar entrega.
Hockey sobre Patines

Juego de ruedas AZEMAD DRIVE 92 A

Azemad
1.40002
83,00 €
Juego de Ruedas Drive 92A | Adaptabilidad y Rendimiento Óptimo Juego de Ruedas Drive 92A ¡Se adapta a todas las realidades! Las ruedas Drive 92A destacan por su capacidad de adaptarse a todo tipo de terrenos. En comparación con los modelos estándar, una de sus grandes...
Product added to wishlist
Product added to compare.