> Manuales > HTML5 e Internet Explorer 9

Buenas prácticas de programación en Javascript que nos permitirán trabajar con prefijos de fabricante sin complicarnos la vida ni el código fuente.

Como quizás todos sabemos, los prefijos de fabricante permiten a los desarrolladores web experimentar con estándares nuevos antes de que lleguen a la fase de Recomendación candidata. Muchas veces, trabajar con prefijos de fabricante complica bastante nuestro código, generando muchas líneas que son casi repetición de otras realizadas anteriormente. En este artículo veremos algunas prácticas recomendables en nuestro código Javascript, útiles cuando queremos aplicar propiedades con distintos prefijos de fabricante.

Hace poco escribí un artículo en el que explicaba cómo estos prefijos son también una forma que tienen los fabricantes de navegadores para salvar el tiempo que media entre el momento en que disponen de sus implementaciones y las fechas en que se publican especificaciones definitivas. A la hora de desarrollar demos de las nuevas funcionalidades en nuestro sitio web IE Test Drive y en algunas presentaciones para eventos, muchos de nosotros en el equipo de IE hemos tenido que trabajar de forma muy habitual con prefijos de fabricante.

En este artículo explicaré un modelo de trabajo que he aplicado a algunas demos recientes y que hace mucho más fáciles las cosas y se ha convertido en una buena práctica. Me gustaría que lo probaseis y me dierais vuestras opiniones sobre esta cuestión o cualquier otro asunto que consideréis que puede tener la categoría de una "buena práctica".

Código propenso a los errores

Cuando utilizamos scripting para acceder a las propiedades CSS utilizando prefijos de fabricante, es fácil que acabemos teniendo un código como este:

var elm = document.getElementById("myElement");
elm.style.msTransitionProperty = "all";
elm.style.msTransitionDuration = "3s";
elm.style.msTransitionDelay = "0s";
elm.style.webkitTransitionProperty = "all";
elm.style.webkitTransitionDuration = "3s";
elm.style.webkitTransitionDelay = "0s";
elm.style.MozTransitionProperty = "all";
elm.style.MozTransitionDuration = "3s";
elm.style.MozTransitionDelay = "0s";
elm.style.OTransitionProperty = "all";
elm.style.OTransitionDuration = "3s";
elm.style.OTransitionDelay = "0s";

Aunque funciona, es farragoso, feo y muy propenso a errores.

Consolidación de las propiedades con prefijo de fabricante en un mismo nombre

Una alternativa mejor consiste en definir un método que realice una búsqueda iterativa sobre una lista de nombres de propiedad y devuelva la primera propiedad soportada, o bien el valor null si el navegador no soporta ninguna de ellas.

function FirstSupportedPropertyName(prefixedPropertyNames) {
   var tempDiv = document.createElement("div");
    for (var i = 0; i < prefixedPropertyNames.length; ++i) {
       if (typeof tempDiv.style[prefixedPropertyNames[i]] != 'undefined')
          return prefixedPropertyNames[i];
    }
    return null;
}

Cuando inicializamos una variable para cada propiedad con prefijo de fabricante que utilizamos, le pasamos un array con todas las propiedades posibles en el orden que prefiramos.

var transformName = FirstSupportedPropertyName(["transform", "msTransform", "MozTransform", "WebkitTransform", "OTransform"]);
var backfaceVisibilityName = FirstSupportedPropertyName(["backfaceVisibility", "msBackfaceVisibility", "MozBackfaceVisibility", "WebkitBackfaceVisibility", "OBackfaceVisibility"]);
var transitionName = FirstSupportedPropertyName(["transition", "msTransition", "MozTransition", "WebkitTransition", "OTransition"]);
var animationName = FirstSupportedPropertyName(["animation", "msAnimation", "MozAnimation", "WebkitAnimation", "OAnimation"]);
var gridName = FirstSupportedPropertyName(["gridRow", "msGridRow", "MozGridRow", "WebkitGridRow", "OGridRow"]);
var regionsName = FirstSupportedPropertyName(["flowFrom", "msFlowFrom", "MozFlowFrom", "WebkitFlowFrom", "OFlowFrom"]);
var hyphensName = FirstSupportedPropertyName(["hyphens", "msHyphens", "MozHyphens", "WebkitHyphens", "OHyphens"]);
var columnName = FirstSupportedPropertyName(["columnCount", "msColumnCount", "MozColumnCount", "WebkitColumnCount", "OColumnCount"]);

Después, el código de tu sitio web que utilice estas propiedades quedaría más o menos así:

var elm = document.getElementById("myElement");
if (transitionName) {
    elm.style[transitionName + "Property"] = "all";
    elm.style[transitionName + "Duration"] = "3s";
    elm.style[transitionName + "Delay"] = "0s";
}
else {
    // fallback for browsers without CSS3 transitions
}

Como ves, de una forma sencilla tenemos una detección de funcionalidad al devolver null en FirstSupportedPropertyName.

Este modelo funciona también cuando las propiedades CSS tienen prefijos de fabricante. Podemos aplicar un patrón ligeramente distinto en el caso en el que sea el valor de CSS (por ejemplo linear-gradient) el que lleva el prefijo:

function FirstSupportedFunctionName(property, prefixedFunctionNames, argString) {
    var tempDiv = document.createElement("div");
    for (var i = 0; i < prefixedFunctionNames.length; ++i) {
       tempDiv.style[property] = prefixedFunctionNames[i] + argString;
       if (tempDiv.style[property] != "")
       return prefixedFunctionNames[i];
    }
    return null;
}
var linearGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-linear-gradient", "-moz-linear-gradient", "-webkit-linear-gradient", "-o-linear-gradient"], "(top, black, white)");
var radialGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-radial-gradient", "-moz-radial-gradient", "-webkit-radial-gradient", "-o-radial-gradient"], "(50% 50%, circle cover, black, white)");

Prueba de sitios web que utilizan propiedades con prefijo de fabricante

Una pregunta frecuente es qué nombres de propiedades podemos utilizar si algunos navegadores aún no soportan la propiedad o cuando ningún navegador soporta la propiedad basada en estándares sin un prefijo. Aquí podemos aplicar un par de técnicas, cada una con sus ventajas:
  1. Incluir siempre todos los nombres esperados, aunque no funcionen aún en los navegadores de uso público. La ventaja de esta estrategia es que a medida que los navegadores van añadiendo soporte con su propio prefijo de fabricante o para la propiedad sin prefijo, tu sitio web seguirá funcionando bien sin cambios. El riesgo es que el sitio pueda empezar a hacer cosas que nunca antes has podido probar. Un prefijo de fabricante indica que este comportamiento aún no está totalmente definido y todas las propiedades con prefijo y la propiedad sin él pueden no hacer lo mismo, de modo que podría ocurrir que en el momento en que el navegador sí tenga soporte para la propiedad sin prefijo, tu sitio en realidad deje de funcionar.
  2. Incluir solo los nombres de propiedades que puedes comprobar. La ventaja en este caso es que el sitio siempre va a funcionar igual que la primera vez que escribiste el código incluso si, con el tiempo, el navegador dispone ya de soporte para nuevas propiedades. El riesgo ahora es que vas a tener una funcionalidad degradada innecesariamente. En sitios de ejemplo o demostración, la gente podría interpretar esto como que el navegador no tiene esa funcionalidad en absoluto
Tienes que elegir una estrategia adecuada para tu sitio web. En muchas de nuestras demos queremos mostrar las nuevas funcionalidades de la plataforma Web en todos los navegadores que las soportan. Y puesto que algunos errores de menor entidad en esas demos no suponen grandes problemas para los usuarios, generalmente optamos por la solución 1. Por otra parte, si tienes un sitio en producción donde un cambio en su funcionamiento puede ocasionar un problema a la empresa, probablemente es mejor optar por la alternativa menos arriesgada

Con independencia de cuál de ellas elijas, lo que siempre hay que hacer es probarlo. Cuando utilizas propiedades con prefijo de fabricante en una fase inicial, a menudo son funcionalidades inestables que pueden cambiar incluso después de que el navegador empiece a ofrecer soporte para una propiedad definitiva, de modo que es imprescindible y crítico el probar cada actualización de cada navegador para asegurarnos de que todo funciona como estaba previsto.

John Hrvatin

Lead Program Manager, Internet Explorer

Manual