(function () { 'use strict'; /* * ========================================================= * CRMB2B - Web Form Plugin * ========================================================= * * Compatible con: * - Formularios HTML normales * - Formularios Wix * * El plugin NO bloquea ni modifica el envío original * del formulario. * ========================================================= */ console.log('[CRMB2B] Plugin cargando...'); /* * --------------------------------------------------------- * 1. CONFIGURACIÓN * --------------------------------------------------------- */ const currentScript = document.currentScript || document.querySelector( 'script[src*="crm_form_plugin"][data-token]' ) || document.querySelector('script[data-token]'); if (!currentScript) { console.warn( '[CRMB2B] No se ha encontrado el script del plugin.' ); return; } const token = currentScript.getAttribute('data-token'); const formSelector = currentScript.getAttribute('data-form') || currentScript.getAttribute('data-formulario'); const formIdentifier = currentScript.getAttribute('data-form-identifier') || null; const API_URL = 'https://www.crmb2b.es/api/v1/web-forms/submit'; /* * --------------------------------------------------------- * 2. LOG INICIAL * --------------------------------------------------------- */ console.log('[CRMB2B] Plugin cargado correctamente.'); console.log('[CRMB2B] Token configurado:', !!token); console.log( '[CRMB2B] Selector de formulario:', formSelector ); console.log( '[CRMB2B] Identificador de formulario:', formIdentifier ); console.log( '[CRMB2B] API:', API_URL ); if (!token) { console.warn( '[CRMB2B] No se ha encontrado data-token.' ); return; } if (!formSelector) { console.warn( '[CRMB2B] No se ha encontrado data-form.' ); return; } /* * --------------------------------------------------------- * 3. DETECTAR WIX * --------------------------------------------------------- */ function isWixForm(form) { if (!(form instanceof HTMLFormElement)) { return false; } return !!form.querySelector( '[data-hook="submit-button"]' ); } /* * --------------------------------------------------------- * 4. OBTENER CLAVE DE CAMPO WIX * --------------------------------------------------------- * * Ejemplo: * * data-hook="form-field-first_name_e1b5" * * devuelve: * * first_name_e1b5 * --------------------------------------------------------- */ function getWixFieldKey(field) { if (!field) { return null; } const hook = field.getAttribute('data-hook'); if (!hook) { return null; } const prefix = 'form-field-'; if (hook.indexOf(prefix) === 0) { return hook.substring(prefix.length); } return hook; } /* * --------------------------------------------------------- * 5. AÑADIR VALOR AL PAYLOAD * --------------------------------------------------------- */ function addFieldValue(data, key, value) { if (!key) { return; } if (value === null || value === undefined) { return; } if (value instanceof File) { return; } value = String(value).trim(); if (value === '') { return; } if ( Object.prototype.hasOwnProperty.call( data, key ) ) { if (!Array.isArray(data[key])) { data[key] = [data[key]]; } data[key].push(value); } else { data[key] = value; } } /* * --------------------------------------------------------- * 6. FORMULARIO HTML NORMAL * --------------------------------------------------------- * * Esta parte mantiene el comportamiento original. * --------------------------------------------------------- */ function getStandardFormData(form) { const formData = new FormData(form); const data = {}; formData.forEach(function (value, key) { if (value instanceof File) { return; } if ( Object.prototype.hasOwnProperty.call( data, key ) ) { if (!Array.isArray(data[key])) { data[key] = [data[key]]; } data[key].push(value); } else { data[key] = value; } }); return data; } /* * --------------------------------------------------------- * 7. FORMULARIO WIX * --------------------------------------------------------- */ function getWixFormData(form) { const data = {}; const fields = form.querySelectorAll( '[data-hook^="form-field-"]' ); console.log( '[CRMB2B] Wix: campos encontrados:', fields.length ); fields.forEach(function (field) { const key = getWixFieldKey(field); if (!key) { return; } /* * No enviar el botón submit. */ const fieldType = field.getAttribute('data-field-type'); if ( fieldType === 'SUBMIT_BUTTON' || key.toLowerCase().indexOf('submit') !== -1 ) { return; } /* * Buscar control real. */ const control = field.querySelector( 'input, textarea, select' ); if (!control) { return; } /* * Checkbox */ if ( control.type === 'checkbox' ) { if (control.checked) { addFieldValue( data, key, control.value || '1' ); } return; } /* * Radio */ if ( control.type === 'radio' ) { if (control.checked) { addFieldValue( data, key, control.value ); } return; } /* * Select múltiple */ if ( control.tagName === 'SELECT' && control.multiple ) { Array.from(control.selectedOptions) .forEach(function (option) { addFieldValue( data, key, option.value ); }); return; } /* * Input / textarea / select normal. */ addFieldValue( data, key, control.value ); }); return data; } /* * --------------------------------------------------------- * 8. OBTENER DATOS DEL FORMULARIO * --------------------------------------------------------- */ function getFormData(form) { if (isWixForm(form)) { console.log( '[CRMB2B] Formulario Wix detectado.' ); return getWixFormData(form); } console.log( '[CRMB2B] Formulario HTML estándar detectado.' ); return getStandardFormData(form); } /* * --------------------------------------------------------- * 9. COMPROBAR VALIDACIÓN WIX * --------------------------------------------------------- * * No enviamos al CRM si Wix muestra un campo inválido. * --------------------------------------------------------- */ function isWixFormValid(form) { /* * Si Wix ya ha marcado algún campo como inválido, * no enviamos. */ const invalidField = form.querySelector( '[aria-invalid="true"]' ); if (invalidField) { console.log( '[CRMB2B] Wix: formulario inválido.' ); return false; } /* * Comprobar controles HTML requeridos. */ const requiredControls = form.querySelectorAll( 'input[required], textarea[required], select[required]' ); for ( let i = 0; i < requiredControls.length; i++ ) { const control = requiredControls[i]; if (control.disabled) { continue; } if ( typeof control.checkValidity === 'function' && !control.checkValidity() ) { console.log( '[CRMB2B] Wix: campo requerido/ inválido:', control ); return false; } } return true; } /* * --------------------------------------------------------- * 10. EVITAR DUPLICADOS * --------------------------------------------------------- */ function canSendSubmission(form) { const now = Date.now(); const last = parseInt( form.dataset.crmb2bLastSubmission || '0', 10 ); /* * Evitamos dobles clicks inmediatos. */ if ( last && now - last < 2000 ) { console.log( '[CRMB2B] Envío duplicado ignorado.' ); return false; } form.dataset.crmb2bLastSubmission = String(now); return true; } /* * --------------------------------------------------------- * 11. ENVIAR AL CRM * --------------------------------------------------------- */ function sendToCRM(form, data) { if (!canSendSubmission(form)) { return; } const payload = Object.assign( {}, data ); if (formIdentifier) { payload._form_identifier = formIdentifier; } /* * No enviamos el token dentro del payload. */ console.log( '[CRMB2B] =============================' ); console.log( '[CRMB2B] ENVIANDO FORMULARIO AL CRM' ); console.log( '[CRMB2B] Payload:', payload ); console.log( '[CRMB2B] URL:', API_URL ); console.log( '[CRMB2B] =============================' ); fetch(API_URL, { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(payload), keepalive: true }) .then(function (response) { console.log( '[CRMB2B] Respuesta HTTP:', response.status, response.statusText ); return response.text() .then(function (text) { let result = null; try { result = text ? JSON.parse(text) : null; } catch (error) { console.warn( '[CRMB2B] La respuesta no es JSON:', text ); } console.log( '[CRMB2B] Respuesta CRM:', result || text ); if (!response.ok) { console.warn( '[CRMB2B] El CRM ha rechazado el formulario.' ); return; } if ( result && result.success ) { console.log( '[CRMB2B] ✓ Formulario enviado correctamente.', result ); } else { console.warn( '[CRMB2B] El CRM respondió pero no confirmó el envío.', result ); } }); }) .catch(function (error) { console.error( '[CRMB2B] ✗ Error enviando formulario al CRM:', error ); }); } /* * --------------------------------------------------------- * 12. PROCESAR FORMULARIO * --------------------------------------------------------- */ function processForm(form, source) { if ( !(form instanceof HTMLFormElement) ) { return; } console.log( '[CRMB2B] Procesando formulario. Origen:', source ); /* * Comprobar que corresponde al selector * configurado en el CRM. */ let configuredForm; try { configuredForm = document.querySelector( formSelector ); } catch (error) { console.error( '[CRMB2B] Selector de formulario inválido:', formSelector, error ); return; } if ( !configuredForm || configuredForm !== form ) { console.log( '[CRMB2B] El formulario no coincide con el configurado.' ); return; } /* * Wix: comprobar validación. */ if ( isWixForm(form) && !isWixFormValid(form) ) { console.log( '[CRMB2B] Wix: no se envía porque el formulario no es válido.' ); return; } let data; try { data = getFormData(form); } catch (error) { console.error( '[CRMB2B] Error recogiendo datos del formulario:', error ); return; } console.log( '[CRMB2B] Datos capturados:', data ); if ( !data || Object.keys(data).length === 0 ) { console.warn( '[CRMB2B] No se han encontrado datos para enviar.' ); return; } sendToCRM( form, data ); } /* * --------------------------------------------------------- * 13. FORMULARIOS HTML NORMALES * --------------------------------------------------------- */ function initializeStandardForm(form) { if ( !(form instanceof HTMLFormElement) ) { return; } /* * Wix se procesa mediante el click del botón. */ if (isWixForm(form)) { console.log( '[CRMB2B] Formulario Wix omitido del listener submit.' ); return; } if ( form.dataset.crmb2bInitialized === '1' ) { return; } form.dataset.crmb2bInitialized = '1'; form.addEventListener( 'submit', function () { console.log( '[CRMB2B] Evento submit detectado en formulario estándar.' ); /* * NO preventDefault(). * * El formulario continúa con su envío normal. */ try { processForm( form, 'standard-submit' ); } catch (error) { console.warn( '[CRMB2B] Error procesando formulario estándar:', error ); } }, false ); console.log( '[CRMB2B] Listener estándar instalado:', form ); } /* * --------------------------------------------------------- * 14. WIX * --------------------------------------------------------- * * Wix utiliza: * *