Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=8f51a0d7-c40d-4031-bc3b-3e0af91b8036

Modernizr: Cómo sustituir funcionalidad no soportada con polyfills (Parte 2)

Icono de advertencia ATENCIÓN: este contenido tiene más de 2 años de antigüedad y, debido a su temática, podría contener información desactualizada o inexacta en la actualidad.

En la anterior entrega de esta serie sobre Modernizr habíamos visto qué es, cómo funciona y cómo nos permite averiguar si una determinada característica de HTML5, CSS3 o una API de HTML5 están disponibles en el navegador actual.

Pero el nombre "Modernizr" nos puede llevar a engaño. Aparentemente, parece dar a entender que la librería "moderniza" nuestra página permitiéndonos usar funciones modernas en navegadores antiguos. En realidad, Modernizr no aporta por sí solo ninguna nueva funcionalidad, con la excepción de los tags semánticos en Internet Explorer que vimos en el artículo anterior. El nombre proviene de la intención original de los autores de "modernizar" las técnicas de desarrollo.

Lo que hace Modernizr es detectar la presencia o ausencia de las distintas funcionalidades, y permite cargar o ejecutar scripts adicionales diseñados para suplir las funcionalidades ausentes que deseemos emplear en la página. En general, este tipo de scripts son conocidos como Polyfills.

Por ejemplo, un polyfill para la funcionalidad de WebSockets podría crear una variable global llamada window.WebSocket con las mismas propiedades y métodos que la implementación nativa de WebSockets. De esta manera, podríamos escribir nuestro propio código dentro de la página haciendo llamadas a WebSockets sin preocuparnos de si el navegador los soporta o no. Si los soporta, los usamos. Si no los soporta, detectamos esta circunstancia mediante Modernizr y en ese caso cargamos la librería externa que aporta los mismos métodos, con lo que nuestro código sigue funcionando aunque sea usando por debajo otro método de comunicación diferente.

Veamos un ejemplo sencillo de uso

En HTML5 se dispone de varios atributos para los controles de tipo <input>, tales como autofocus, que le pone el foco al campo correspondiente al cargar la página, o required, que impide que se haga un submit del formulario si se ha dejado en blanco el campo correspondiente.

Campo 1: <input name="campo1" autofocus /><br />
Campo 2: <input name="campo2" required /><br />
Campo 3: <input name="campo3" required /><br />

La siguiente figura muestra el mensaje presentado en un navegador que soporta el atributo required:

Campos requeridos

Sin embargo, si la misma página se presentase en un navegador que no soporte esta opción, el submit se realizaría sin advertir al usuario de la falta de estos datos obligatorios. Desde luego, en todos los casos deberíamos añadir una validación en el código servidor para detectar la falta de datos obligatorios, pero eso no quita el que preveamos alguna funcionalidad en el lado cliente para que el usuario reciba respuesta inmediata, sin esperar al viaje de ida y vuelta al servidor.

Aquí es donde interviene el Polyfill. Podemos escribir un fragmento de JavaScript que sea capaz de recorrer los elementos input del formulario buscando los que tienen el atributo required. Y se puede interceptar el submit para presentar un mensaje de error en el caso de que alguno de esos campos no se haya rellenado. De la misma manera, se pueden buscar otros atributos tales como autofocus y programar el comportamiento correspondiente.

Campos requeridos en un navegador no soportado, con Polyfill

Evidentemente, dicho código sólo debería cargarse en el caso de que el navegador no tenga ya incluido el soporte para la funcionalidad requerida. Utilizando Modernizr podríamos ejecutar el código de manera condicional:

if (!Modernizr.input.required) {
    //Ejecutar aquí el código que busca y procesa los atributos required
}

Carga de Polyfills según necesidades

El inconveniente de trabajar de esta manera es que ese código siempre debe transmitirse al navegador, incluso aunque no se utilice. Esto resulta especialmente grave en los casos en los que no se trata de una rutina trivial, como el required que nos ocupa, sino que es un código de un volumen considerable, como por ejemplo un simulador de <canvas>.

Para evitarlo, las versiones antiguas de Modernizr disponían de un método load(). Se trataba de un "cargador de scripts", que era capaz de evaluar una condición booleana y en función del resultado descargar un script u otro e incorporarlo a la página.

La descarga se realizaba de manera asíncrona, por lo que la página seguía siendo "responsiva" mientras se procedía a descargar los scripts. Opcionalmente, era posible incluir una retrollamada (callback) que se ejecutaba al terminar la descarga, y que típicamente se usaba para llamar al código de inicialización del script que se ha descargado. Era algo así:

Modernizr.load({
    test: Modernizr.input.required,
    nope: 'scripts/Ejemplo4/Required.js',
    complete: function () {
        init();
    }
});

En el ejemplo anterior, la propiedad test indica la expresión booleana que se evalúa (en este caso, una llamada a Modernizr). Si el resultado es true, se descarga el código indicado en la propiedad yep (no utilizada en el ejemplo), mientras que si es false se descarga el código indicado en nope (en nuestro caso, un pequeño script incluido dentro de una carpeta en nuestro propio servidor web). La propiedad complete indica la función que se ejecutará al completar la carga, y en nuestro ejemplo resulta ser una llamada al código de inicialización que hay dentro de Required.js.

El resultado es que el contenido de Required.js solo se descargaba al navegador en caso de que éste no soportase el atributo required en los campos input.

La verdad es que este método era muy cómodo y funcionaba muy bien (incluso se entrega como una biblioteca externa, para usarlo de manera independiente, llamada yepnope.js), pero ambos métodos se han marcado como obsoletos y se recomienda mejor utilizar otras técnicas.

El motivo es que hoy en día es muy común utilizar algún sistema de carga asíncrona de scripts o de inyección de dependencias, por lo que es mejor no interferir con éstos usando el método load() o yepnope.js.

Por ejemplo, si usas jQuery podrías simular una funcionalidad similar con un código como el siguiente:

if (!Modernizr.input.required) {
    jQuery.getScript("./scripts/Ejemplo4/Required.js")
        .done(function(){ //Si funciona lo inicializamos
            init();
        });
}

El cual hace uso de Modernizr para detectar funcionalidades, y luego emplea el método getScript() de jQuery para cargar asíncronamente el polyfill y ejecutarlo. Con el método .done de la promesa de jQuery (o con un segundo parámetro opcional de getScript, llamado success, que toma una función de callback) ejecutamos el código de inicialización en caso de que cargue correctamente el polyfill. Si quisiésemos hacer algo en caso de que la funcionalidad estuviese soportada (método yep del antiguo Modernizr.load), podríamos simplemente usar el else del condicional para ello.

Como puedes ver es igual de sencillo y realmente casi cualquier biblioteca de desarrollo JavaScript hoy en día ofrece una funcionalidad similar.

¿Dónde consigo Polyfills?

Todo lo anterior está muy bien, pero ¿cómo consigo Polyfills para suplir funcionalidad moderna en navegadores antiguos que no la tienen?

GitHub es un mundo maravilloso en el que podemos buscar y aparecerán multitud de bibliotecas útiles. Pero por suerte el propio proyecto Modernizr mantiene una página allí con enlaces a gran cantidad de polyfills para todo tipo de funcionalidades de HTML5 y CSS3, con comentarios acerca de cada una de ellas.

Puedes acceder a esta lista desde HTML5 Cross Browser Polyfills.

Existen decenas de ellas: desde soporte para SVG o Canvas (gráficos) hasta cuestiones sencillas como estilos CSS o características muy avanzadas como Geolocalización, WebSockets o la API de archivos. Merece la pena darle un repaso.

Fecha de publicación:
Alberto Población Alberto es MVP de C#, y lleva varias décadas desarrollando software. Cuenta entre otras con las certificaciones MCSE, MCDBA, MCITP, MCSD, MCPD. En la actualidad trabaja como consultor independiente dedicándose también a la formación. Es instructor certificado por Microsoft. Ver todos los posts de Alberto Población
Archivado en: Desarrollo Web

Boletín campusMVP.es

Solo cosas útiles. Una vez al mes.

🚀 Únete a miles de desarrolladores

DATE DE ALTA

x No me interesa | x Ya soy suscriptor

La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.