Validación de formulario – Parte 4: Validación del formulario de suscripción de MailChimp | Programar Plus

En los últimos artículos de esta serie, hemos aprendido a utilizar algunos tipos de entrada y atributos de validación para validar formularios de forma nativa.

Hemos aprendido a utilizar la API de validación de restricciones para mejorar el proceso de validación del navegador nativo para una mejor experiencia general del usuario. Y escribimos un polyfill para extender el soporte hasta IE9 (y tapar algunos agujeros de funciones en algunas versiones más nuevas).

Ahora, tomemos lo que hemos aprendido y aplíquelo a un ejemplo real: el formulario de registro de MailChimp.

Serie de artículos:

  1. Validación de restricciones en HTML
  2. La API de validación de restricciones en JavaScript
  3. Un Polyfill de API de estado de validez
  4. Validación del formulario de suscripción de MailChimp (¡está aquí!)

Una forma simple con una gran huella

Cuando inserta un formulario de registro de MailChimp en su sitio, viene con un script de validación de JavaScript llamado `mc-validate.js`.

Este archivo tiene 140 kb (minificado) e incluye la biblioteca jQuery completa, dos complementos de terceros y algunos códigos personalizados de MailChimp. ¡Podemos mejorar!

Quitando la hinchazón

Primero, tomemos un formulario de MailChimp sin nada de hinchazón.

En MailChimp, donde obtienes el código para tu formulario insertable, haz clic en la pestaña etiquetada como “Desnudo”. Esta versión no incluye nada de CSS o JavaScript de MailChimp.

<div id="mc_embed_signup">
    <form action="//us1.list-manage.com/subscribe/post?u=12345abcdef&id=abc123" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
            <h2>Subscribe to our mailing list</h2>
            <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
            <div class="mc-field-group">
                <label for="mce-FNAME">First Name </label>
                <input type="text" value="" name="FNAME" class="" id="mce-FNAME">
            </div>
            <div class="mc-field-group">
                <label for="mce-EMAIL">Email Address  <span class="asterisk">*</span></label>
                <input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
            </div>
                <div id="mce-responses" class="clear">
                    <div class="response" id="mce-error-response" style="display:none"></div>
                    <div class="response" id="mce-success-response" style="display:none"></div>
                </div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
                <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_f2d244c0df42a0431bd08ddea_aeaa9dd034" tabindex="-1" value=""></div>
                <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
</div>

Esto es mejor, pero aún incluye algunas marcas que no necesitamos. Recortemos esto tanto como sea posible.

  1. Podemos quitar el div#mc_embed_signup envoltorio alrededor del formulario.
  2. Del mismo modo, podemos eliminar el div#mc_embed_signup_scroll envoltorio alrededor de los campos dentro del formulario.
  3. También podemos eliminar el texto que informa a los visitantes que “* indica obligatorio”.
  4. Quitemos el .mc-field-group clases de alrededor de nuestros campos de formulario, y el vacío class atributos en los propios campos.
  5. También deberíamos eliminar el .required y .email clases de nuestro campo de correo electrónico, ya que solo se usaron como ganchos para el script de validación de MailChimp.
  6. Seguí adelante y quité el * de la etiqueta del correo electrónico. Sin embargo, depende totalmente de usted cómo desea etiquetar los campos obligatorios.
  7. Podemos borrar el div#mce-responses contenedor, que solo utiliza el archivo JavaScript de MailChimp.
  8. También podemos eliminar el .clear clase de la div alrededor del botón de enviar.
  9. Eliminemos todo lo vacío value atributos.
  10. Finalmente, deberíamos eliminar el novalidate atributo del form elemento. Dejaremos que nuestro script lo agregue cuando se cargue.

Todo esto nos deja con una forma mucho más limpia y modesta. Dado que se elimina el CSS de MailChimp, heredará los estilos de formulario predeterminados de su sitio.

<form action="//us1.list-manage.com/subscribe/post?u=12345abcdef&id=abc123" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
    <h2>Subscribe to our mailing list</h2>
    <div>
        <label for="mce-FNAME">First Name</label>
        <input type="text" name="FNAME" id="mce-FNAME">
    </div>
    <div>
        <label for="mce-EMAIL">Email Address</label>
        <input type="email" name="EMAIL" id="mce-EMAIL">
    </div>
    <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_f2d244c0df42a0431bd08ddea_aeaa9dd034" tabindex="-1" value=""></div>
    <div><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</form>

Agregar validación de restricciones

Ahora, agreguemos algunos tipos de entrada y atributos de validación para que el navegador pueda validar el formulario de forma nativa.

El type porque el campo de correo electrónico ya está configurado en email, Lo cual es genial. Agreguemos también el required atributo, y un pattern para obligar a los correos electrónicos a incluir un TLD (el .com parte de una dirección). También deberíamos incluir un title informar a las personas que deben tener un TLD.

Suscríbase a nuestra lista de correo

Nombre Dirección de correo electrónico

Mejora con la API de validación de restricciones

Este es un excelente punto de partida, pero podemos mejorar la experiencia del usuario agregando el script de validación de formularios que escribimos anteriormente en esta serie.

Nuestro script de validación tiene solo 6.7kb antes de la minificación, lo que lo hace 20 veces más pequeño que el que proporciona MailChimp. Sin embargo, si queremos asegurar la compatibilidad con IE9, debemos incluir nuestro polyfill Validity State y el polyfill classList.js de Eli Grey.

Eso hace que nuestro tamaño de archivo total sea de hasta 15,5 kb sin reducir, aún 9 veces más pequeño que el script de validación de MailChimp.

Enviar el formulario con Ajax

El mc-validate.js El script proporcionado por MailChimp no solo valida el formulario. También lo envía con Ajax y muestra un mensaje de estado.

Cuando hace clic en enviar en nuestro formulario modificado, redirige al visitante al sitio de MailChimp. Esa es una forma totalmente válida de hacer las cosas.

Pero también podemos recrear el envío de formularios Ajax de MailChimp sin jQuery para una mejor experiencia de usuario.

Lo primero que queremos hacer es evitar que el formulario se envíe a través de una recarga de página como lo haría normalmente. En nuestro submit oyente de eventos, estamos llamando event.preventDefault si hay errores. En cambio, llamémoslo sin importar cómo.

// Check all fields on submit
document.addEventListener('submit', function (event) {

    // Only run on forms flagged for validation
    if (!event.target.classList.contains('validate')) return;

    // Prevent form from submitting
    event.preventDefault();

    ...

}, false);

Usando JSONP

El mc-validate.js El script usa JSONP para sortear errores de seguridad entre dominios.

JSONP funciona cargando los datos devueltos como un elemento de secuencia de comandos en el document, que luego pasa esos datos a una función de devolución de llamada que hace todo el trabajo pesado.

Configuración de nuestra URL de envío

Primero, configuremos una función que podamos ejecutar cuando nuestro formulario esté listo para ser enviado, y llamémoslo en nuestro submit oyente de eventos.

// Submit the form
var submitMailChimpForm = function (form) {
    // Code goes here...
};

// Check all fields on submit
document.addEventListener('submit', function (event) {

    ...

    // Otherwise, let the form submit normally
    // You could also bolt in an Ajax form submit process here
    submitMailChimpForm(event.target);

}, false);

Lo primero que debemos hacer es obtener la URL del formulario action atributo.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');

};

En el script `mc-validate.js`, el /post?u=' en la URL se reemplaza con /post-json?u=. Podemos hacerlo con bastante facilidad con el replace() método.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');

};

Serializar los datos de nuestro formulario

A continuación, queremos tomar todos los datos del campo del formulario y crear una cadena de consulta de pares clave / valor a partir de ellos. Por ejemplo, FNAME=Freddie%20Chimp&[email protected].

Creemos otra función para manejar esto por nosotros.

// Serialize the form data into a query string
var serialize = function (form) {
    // Code goes here...
};

Ahora, queremos recorrer todos nuestros campos de formulario y crear pares clave / valor. Me basaré en el trabajo realizado por Simon Steinberger para esto.

Primero, crearemos un serialized variable configurada como una cadena vacía.

// Serialize the form data into a query string
// Forked and modified from https://stackoverflow.com/a/30153391/1293256
var serialize = function (form) {

    // Setup our serialized data
    var serialized = '';

};

Ahora tomemos todos los campos en nuestro formulario usando form.elements y recorrerlos.
Si el campo no tiene un nombre, es un botón o enviar, está deshabilitado o es un archivo o una entrada de restablecimiento, lo omitiremos.

Si no es un checkbox o radio (un buen catchall para select, textarea, y los varios input tipos) o lo está y está marcado, lo convertiremos en un par clave / valor, agregaremos un & al principio y añádalo a nuestro serialized cuerda. También nos aseguraremos de codificar la clave y el valor para su uso en una URL.

Finalmente, devolveremos la cadena serializada.

// Serialize the form data into a query string
// Forked and modified from https://stackoverflow.com/a/30153391/1293256
var serialize = function (form) {

    // Setup our serialized data
    var serialized = '';

    // Loop through each field in the form
    for (i = 0; i < form.elements.length; i++) {

        var field = form.elements[i];

        // Don't serialize fields without a name, submits, buttons, file and reset inputs, and disabled fields
        if (!field.name || field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') continue;

        // Convert field data to a query string
        if ((field.type !== 'checkbox' && field.type !== 'radio') || field.checked) {
            serialized += '&' + encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value);
        }
    }

    return serialized;

};

Ahora que tenemos nuestros datos de formulario serializados, podemos agregarlos a nuestra URL.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form);

};

Agregar una devolución de llamada

Una parte clave de cómo funciona JSONP es la devolución de llamada.

Las solicitudes tradicionales de Ajax le devuelven datos. JSONP, en cambio, pasa datos a una función de devolución de llamada. Esta función tiene que ser global (como en, adjunta a la window en lugar de dentro de otra función).

Creemos una función de devolución de llamada y registremos los datos devueltos en la consola para que podamos ver lo que envía MailChimp.

// Display the form status
var displayMailChimpStatus = function (data) {
    console.log(data);
};

Ahora podemos agregar esta devolución de llamada a nuestra URL. La mayor parte del uso de JSONP callback como clave de cadena de consulta para esto, pero MailChimp usa c.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form) + '&c=displayMailChimpStatus';

};

Inyectando nuestro script en el DOM

Ahora estamos listos para inyectar nuestro script en el DOM. Primero, crearemos un nuevo elemento de secuencia de comandos y asignaremos nuestra URL como está src.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form) + '&c=displayMailChimpStatus';

    // Create script with url and callback (if specified)
    var script = window.document.createElement( 'script' );
    script.src = url;

};

A continuación, tomaremos el primero <script> elemento que encontramos en el DOM, e inyectamos nuestro nuevo justo antes usando el insertBefore() método.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form) + '&c=displayMailChimpStatus';

    // Create script with url and callback (if specified)
    var script = window.document.createElement( 'script' );
    script.src = url;

    // Insert script tag into the DOM (append to <head>)
    var ref = window.document.getElementsByTagName( 'script' )[ 0 ];
    ref.parentNode.insertBefore( script, ref );

};

Finalmente, lo eliminaremos del DOM después de que nuestro script se cargue correctamente.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form) + '&c=displayMailChimpStatus';

    // Create script with url and callback (if specified)
    var script = window.document.createElement( 'script' );
    script.src = url;

    // Insert script tag into the DOM (append to <head>)
    var ref = window.document.getElementsByTagName( 'script' )[ 0 ];
    ref.parentNode.insertBefore( script, ref );

    // After the script is loaded (and executed), remove it
    script.onload = function () {
        this.remove();
    };

};

Procesando la respuesta de envío

En este momento, nuestro método de devolución de llamada está registrando lo que MailChimp responda en la consola.

// Display the form status
var displayMailChimpStatus = function (data) {
    console.log(data);
};

Si observa los datos devueltos, es un objeto JSON con dos claves: result y msg. El result el valor es error o success, y el msg El valor es una cadena corta que explica el result.

{
    msg: '[email protected] is already subscribed to list Bananas Are Awesome. Click here to update your profile.'
    result: 'error'
}

// Or...

{
    msg: 'Almost finished... We need to confirm your email address. To complete the subscription process, please click the link in the email we just sent you.'
    result: 'success'
}

Debemos verificar para asegurarnos de que nuestros datos devueltos tengan ambas claves. De lo contrario, lanzaremos un error de JavaScript cuando vayamos a usarlos.

// Display the form status
var displayMailChimpStatus = function (data) {

    // Make sure the data is in the right format
    if (!data.result || !data.msg ) return;

};

Mostrar un mensaje de estado

Agreguemos un <div> a nuestro formulario, justo antes del botón enviar, que usaremos para agregar nuestro mensaje de error o éxito. Le daremos una clase de .mc-status.

<form action="//us1.list-manage.com/subscribe/post?u=12345abcdef&id=abc123" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
    /* ... */
    <div class="mc-status"></div>
    <div><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</form>

En nuestro displayMailChimpStatus() función, queremos encontrar la .mc-status contenedor y agregue nuestro msg lo.

// Display the form status
var displayMailChimpStatus = function (data) {

    // Get the status message content area
    var mcStatus = document.querySelector('.mc-status');
    if (!mcStatus) return;

    // Update our status message
    mcStatus.innerHTML = data.msg;

};

Podemos diseñar el mensaje de manera diferente dependiendo de si el envío fue exitoso o no.

Ya tenemos algunos estilos configurados para nuestros mensajes de error con el .error-message, así que reutilicemos esos. Crearemos una nueva clase .success-message, para presentaciones exitosas.

.success-message {
    color: green;
    font-style: italic;
    margin-bottom: 1em;
}

Ahora, podemos agregar condicionalmente una de nuestras clases (y eliminar la otra) en función de la result.

// Display the form status
var displayMailChimpStatus = function (data) {

    // Get the status message content area
    var mcStatus = document.querySelector('.mc-status');
    if (!mcStatus) return;

    // Update our status message
    mcStatus.innerHTML = data.msg;

    // If error, add error class
    if (data.result === 'error') {
        mcStatus.classList.remove('success-message');
        mcStatus.classList.add('error-message');
        return;
    }

    // Otherwise, add success class
    mcStatus.classList.remove('error-message');
    mcStatus.classList.add('success-message');

};

Una importante mejora de la accesibilidad

Si bien nuestro mensaje será detectado fácilmente por los usuarios videntes, es posible que las personas que utilizan tecnología de asistencia, como lectores de pantalla, no sepan de manera inherente que se ha agregado un mensaje al DOM.

Usaremos JavaScript para enfocar nuestro mensaje. Para hacerlo, también necesitaremos agregar un tabindex de -1, como <div> los elementos no son enfocables naturalmente.

// Display the form status
var displayMailChimpStatus = function (data) {

    // Get the status message content area
    var mcStatus = document.querySelector('.mc-status');
    if (!mcStatus) return;

    // Update our status message
    mcStatus.innerHTML = data.msg;

    // Bring our status message into focus
    mcStatus.setAttribute('tabindex', '-1');
    mcStatus.focus();

    // If error, add error class
    if (data.result === 'error') {
        mcStatus.classList.remove('success-message');
        mcStatus.classList.add('error-message');
        return;
    }

    // Otherwise, add success class
    mcStatus.classList.remove('error-message');
    mcStatus.classList.add('success-message');

};

Es muy probable que esto agregue un contorno azul a nuestro mensaje de estado. Esta es una característica de accesibilidad realmente importante para enlaces, botones y otras áreas de contenido que se pueden enfocar naturalmente, pero no es necesaria para nuestro mensaje. Podemos eliminarlo con un poco de CSS.

.mc-status:focus {
    outline: none;
}

El final resulto

Ahora tenemos un script ligero y sin dependencias que valida nuestro formulario MailChimp y lo envía de forma asincrónica.

Nuestro guión completo pesa 19 kb sin modificar. Cuando se minimiza, el guión pesa solo 9 kb. Eso es 15,5 veces más pequeño que la versión que proporciona MailChimp.

¡Nada mal!

Serie de artículos:

  1. Validación de restricciones en HTML
  2. La API de validación de restricciones en JavaScript
  3. Un Polyfill de API de estado de validez
  4. Validación del formulario de suscripción de MailChimp (¡está aquí!)
(Visited 4 times, 1 visits today)