Ajuste para jQuery.validationEngine

Uno de mis plugins favoritos de siempre para jQuery, es el jQuery.validationEngine. Un muy completo plugin para validación de formularios, muy customizable, desde el tipo de validación hasta donde debe aparecer el warning de error.

Pero hoy me pidieron algo que si el plugin lo trae por defecto, no lo encontré. El plugin ejecuta la validación de cada campo no sólo cuando el usuario hace un submit del formulario, sino cuando termina de completar un campo y pasa al siguiente. De esta manera, le permite al usuario corregir en el momento los datos erróneos.

Si se desea evitar esa validación, uno debe hacer lo siguiente:


$(".registerform").validationEngine({
   bind: false
});

De esta manera, la validación la realizará sólo cuando se haga submit del formulario.

Pero hoy me pidieron que la validación de los campos se haga sólo si el usuario empezó a escribir algo en el campo. Por defecto, si un campo es requerido, el usuario hace foco, no lo completa, y pasa al siguiente, el sistema le muestra un error, ya que el campo es obligatorio y lo dejó sin completar.

Pero el pedido tiene sentido. No hace falta ejecutar esa validación del campo antes de siquiera empezar a completarlo. Al mismo tiempo, no debo perder la validación de campo vacío al hacer submit.

La mejor manera que encontré de hacer esta excepción fue editar jquery.validationEngine.js. Viendo el código, llegué a donde necesitaba editar:

_onFieldEvent: function(event) {
   var field = $(this);
   var form = field.closest('form');
   var options = form.data('jqv');
   options.eventTrigger = "field";
   // validate the current field

   window.setTimeout(function() {
      methods._validateField(field, options);
      if (options.InvalidFields.length == 0 && options.onSuccess) {
         options.onSuccess();
      } else if (options.InvalidFields.length > 0 && options.onFailure) {
         options.onFailure();
      }
   }, (event.data) ? event.data.delay : 0);
},

Aquí veo que se ejecuta la validación ante un evento del input (el cual se puede configurar mediante las opciones del plugin). Entonces, sólo debo ejecutar una verificación antes de validar:

_onFieldEvent: function(event) {
   var field = $(this);
   var form = field.closest('form');
   var options = form.data('jqv');
   options.eventTrigger = "field";
   // validate the current field

   if(field.val().length > 0){

      window.setTimeout(function() {
      methods._validateField(field, options);
      if (options.InvalidFields.length == 0 && options.onSuccess) {
         options.onSuccess();
      } else if (options.InvalidFields.length > 0 && options.onFailure) {
         options.onFailure();
      }
      }, (event.data) ? event.data.delay : 0);

   }
},

Y listo. De esta manera, primero chequeo que haya en verdad algo que verificar antes de entrar al proceso de validación. Y como esto está atado sólo a eventos del input, al hacer submit del formulario se ejecutan siempre las reglas de validación.

Desarrollando para mobile

En las últimas semanas estuve desarrollando un sitio web mobile. Desde mi punto de vista, lo mejor que tiene el desarrollar/maquetar para mobile es que se pueden usar (y de hecho se fomenta) las ventajas de HTML5.

Con lo que me encontré a la hora de hacer esta webapp, es con pequeños yeites, que paso a poner a disposición de todos.

Un CSS para todos

Hace unos meses Jakob Nielsen, en contra de cualquier práctica realista, propuso que en lo que a desarrollo web mobile se refiere, lo mejor es olvidar las mediaqueries al hacer un único sitio que se adapta a todos los dispositivos, y en su lugar hacer sitios mobiles por separado del sitio full, tantos como hagan falta, e inclusive, crear tantos generadores de contenido como sean necesarios para permitir, justamente, esta proliferación de sitios.

Ridículo.

Yo uso mediaqueries por todos los motivos que se pueden encontrar googleando, y porque mis clientes y los de la agencia para la que trabajo no tienen presupuestos tan grandes para lograr lo que Nielsen propone. Entonces, un CSS con mediaqueries para todos.

Y la mejor manera que por el momento encontré para apuntar a las distintas pantallas, es la siguiente:


/* generales */
@media only screen and (min-width: 420px) and (max-width: 767px) {
}
/* iPad */
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
}
/* iPhone */
@media only screen and (max-device-width: 480px) {
}

Cabe notar que el de iPhone se superpone con el de dispositivos mobiles en general, por lo que esta diferenciación pocas veces hará falta, pero no está de más el saberla.

iPhone/iPad reescala al rotar

Este es un curioso problema, cuya solución, si bien la entiendo, no me gusta al 100%. El problema es que al cargar una página en un iPad, y luego cambiar la rotación, la escala “cambia” y nos vemos forzados a hacer el ajuste, que si bien el gesto con los dedos lo hace facilísimo, no deja de ser molesto. El problema se origina en código que se suele encontrar incompleto, como el siguiente:

<meta name ="viewport" content="initial-scale=1.0, width=device-width">

En la ardua tarea de copypastear código hasta que funciona, pocas veces nos detenemos a pensar para qué realmente sirve cada parámetro. El meta “viewport” nos permite indicarle al browser cómo se debe comportar nuestro contenido respecto del dispositivo. Podríamos entonces setear content=”width=200px”, que lo que hará será forzar el ancho del contenido a un máximo de 200px. No se me ocurre un ejemplo práctico en donde querramos setear un ancho de esta manera, pero lo que si sabemos es que si podemos setear ese ancho de forma proporcional, entonces podemos poner nuestra web al ancho de cualquier dispositivo. Y eso es lo que hace width=device-width.

También se puede setear la escala a la que se debe ver el contenido con initial-scale=1.0. Pero lo que en verdad necesitamos para corregir las rotaciones de iPhones/iPods/iPads es lo siguiente:

<meta name ="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width">
<meta name="apple-mobile-web-app-capable" content="yes"/>

De este modo seteamos la escala incial, la escala máxima, y le quitamos la posibilidad al usuario de reescalar, al mismo tiempo que seteamos nuestro ancho de página a todo el dispositivo. Y con la instrucción que sigue le indicamos al dispositivo que nuestra aplicación corre en full screen.

Lo que veo de negativo de esto es que se le quita la posibilidad al usuario de escalar, y eso no me gusta. Pero se trata de equilibrio, si como usuario voy a estar cambiando la escala, entonces no puedo pretender que la rotación de mi dispositivo me recalcule todos los tamaños a como me es a gusto. O quizás debiera? en fin… será problema de los ingenieros.

Por nuestra parte, nos queda saber diseñar/maquetar para que los usuarios roten y puedan tener la mejor experiencia posible.

Les dejo un link a stackoverflow, de donde pude empezar a ilustrarme sobre el tema, y otro a la documentación oficial de Safari, de donde pueden leer sobre “apple-mobile-web-app-capable”.

Favicons

El tema con los favicons en mobile se reduce a crear un archivo .png por cada tipo de pantalla que puede guardar la webapp como favorito. No me voy a extender demasiado en esto, porque simplemente seguí el paso a paso que encontré en esta página. El único tip que sí voy a dar es que los .png no pueden tener transparencia en IOS (android si los lee), confirmado esta vez en la documentación para desarrolladores de Apple.

Debugging

Por último, un plugin que no conocía, y permite cambiar el user agent en el Firefox o Chrome. Es algo que parece tonto, hasta que te das cuenta que todos los sitios usan el user agent para detectar si es o no un dispositivo móvil el que se conecta.

Diseñador Multimedial