Exportar (0) Imprimir
Expandir todo

Cómo detectar características en lugar de exploradores

Actualización: diciembre de 2013

Tradicionalmente, muchos desarrolladores web han usado la detección de exploradores en un intento de proporcionar una experiencia coherente entre exploradores. La implementación típica realiza una única operación de comparación que, normalmente, incluye la cadena de agente de usuario, y después realiza varias suposiciones de diseño acerca de las características compatibles con ese explorador. Sin embargo, en la práctica, la detección de características ha demostrado ser una técnica más efectiva y que requiere menos mantenimiento. En este artículo, se muestra cómo usar la detección de características para comprobar la compatibilidad de características basadas en estándares y demostrar diferentes maneras de detectar características de forma eficaz.

Argumentos contra la detección de exploradores

Tal y como se implementa normalmente, la detección de exploradores presenta varias desventajas, entre ellas:

  • Cuando se lanza un explorador nuevo o se actualiza uno existente, debes tener en cuenta el nuevo explorador en el código de detección de exploradores. Los exploradores actualizados podrían ser compatibles con estándares y características que no eran compatibles cuando se diseñó el código de detección de exploradores.
  • Las conclusiones acerca de la compatibilidad de características podrían no ser correctas o apropiadas.
  • A medida de que se dispone de nuevos dispositivos, con frecuencia se incluyen nuevas versiones de exploradores; en consecuencia, el código de detección de exploradores se debe revisar y, posiblemente, modificar para admitir nuevos exploradores. En algunos casos resulta más complicado crear implementaciones personalizadas para cada explorador.
  • Una técnica de detección de exploradores podría no identificar de forma precisa un explorador determinado. Por ejemplo, muchos exploradores son compatibles con la capacidad de modificar la cadena de agente de usuario.

Para ilustrar esto, considera la siguiente muestra de código (no válida) que intenta de manera inadecuada usar técnicas específicas del explorador para asignar un controlador de eventos.


function getInternetExplorerVersion()
// Returns the version of Internet Explorer or a -1
// (indicating the use of another browser).
{
  var rv = -1; // Default value assumes failure. 
  var ua = navigator.userAgent;

  // If user agent string contains "MSIE x.y", assume
  // Internet Explorer and use "x.y" to determine the
  // version.
 
  var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
  if (re.exec(ua) != null) 
    rv = parseFloat( RegExp.$1 );
  return rv;

}

function registerEvent( sTargetID, sEventName, fnHandler ) 
{
  var oTarget = document.getElementById( sTargetID );
  if ( oTarget != null ) { 

     // This is not an optimal example; it demonstrates 
     // techniques that you should not follow. 

     if ( getInternetExplorerVersion() > -1 ) { 
       oTarget.attachEvent( "on" + sEventName, fnHandler );
     } else {
       oTarget.addEventListener( sEventName, fnHandler ); 
     }
  }
}

En este ejemplo, se intenta usar la cadena de agente de usuario para determinar si el explorador es Windows Internet Explorer. Si bien el ejemplo funciona en Internet Explorer y en la mayoría de los otros exploradores, presenta varios problemas, entre otros:

  • Esta muestra de código se centra en el explorador (Internet Explorer), no en la característica (registro del controlador de eventos de DOM de nivel 3). Como resultado, si se usa Internet Explorer para ver la página web, el ejemplo usa attachEvent para registrar los controladores de eventos aunque la versión de Internet Explorer admita el método addEventListener. Además, este ejemplo debería probarse con todas las versiones nuevas (hipotéticas) de Internet Explorer.
  • En este ejemplo se da por sentado que Internet Explorer no admite el método addEventListener, lo que es una suposición incorrecta en el caso de Internet Explorer 9. Muchas implementaciones de detección de exploradores realizan suposiciones similares.
  • Aunque este ejemplo en particular no intenta distinguir entre las versiones de Internet Explorer, ha habido cambios en la manera en que Internet Explorer administra la cadena de agente de usuario. Las aplicaciones diseñadas según el comportamiento de una versión anterior pueden ofrecer resultados incorrectos para las páginas web mostradas en la Vista de compatibilidad, que se presentó en Internet Explorer 8. Para obtener más información, consulta Información acerca de las cadenas de agente de usuario e Información acerca de la lista de vista de compatibilidad.

Este ejemplo ilustra muchos puntos débiles en la detección de exploradores como técnica para determinar las características compatibles con un explorador web. Un enfoque más efectivo es detectar directamente la compatibilidad de la característica, como se muestra en la muestra de código siguiente.


function registerEvent( sTargetID, sEventName, fnHandler ) 
{
   var oTarget = document.getElementById( sTargetID );
   if ( oTarget != null ) 
   {
      if ( oTarget.addEventListener ) {   
         oTarget.addEventListener( sEventName, fnToBeRun, false );
      } else {
        var sOnEvent = "on" + sEventName; 
        if ( oTarget.attachEvent ) 
        {
           oTarget.attachEvent( sOnEvent, fnHandler );
        }
      }
   }
}

Este ejemplo proporciona dos mejoras respecto al anterior:

  • Se concentra en la característica en lugar del explorador. Si el usuario usa un explorador que es compatible con el método addEventListener (como Internet Explorer 9 y muchos otros exploradores), ese método se usa para definir el controlador de eventos.
  • Pone énfasis en la técnica basada en estándares en lugar de ponerlo en la técnica propietaria. En este caso, el ejemplo comprueba la compatibilidad con la técnica preferida (el método addEventListener) antes de intentar usar la técnica alternativa.

Este ejemplo es efectivo debido a que no da por sentado el comportamiento de ningún explorador. La técnica no necesita actualizarse para ser compatible con las nuevas versiones (hipotéticas) de Internet Explorer ni necesita expandirse para ser compatible con nuevos exploradores o dispositivos. El ejemplo simplemente se concentra en si la característica está disponible. Esta es la diferencia principal entre la detección de características y la detección de exploradores.

Sería ideal que todos los exploradores fueran compatibles con los mismos estándares e implementaran dichos estándares exactamente de la misma manera. Sin embargo, en la práctica existen numerosas variaciones entre los exploradores y su respectiva implementación de los distintos estándares.

Para los desarrolladores web, la mejor defensa es confiar en las características que están definidas según estándares estables y de amplia aceptación, como HTML5, Hojas de estilo CSS de nivel 3 (CSS3), Scalable Vector Graphics (SVG), etc. Detecta la compatibilidad de las características que quieres usar y proporciona enfoques alternativos únicamente si necesitas hacerlo.

Existe una cantidad de maneras de detectar características, por ejemplo:

  • Buscar objetos o propiedades de Document Object Model (DOM) relacionados con la característica.
  • Intentar crear un objeto o un atributo relacionados con la característica.
  • Usar el método hasFeature para determinar si la implementación del DOM admite la característica.

Para obtener más información, consulta Cómo crear estrategias de reserva efectivas.

Detección de objetos y propiedades DOM

La manera más común de detectar características es examinar el DOM en busca de objetos o propiedades relacionados con la característica que quieres usar. Por ejemplo, la muestra de código siguiente establece cómo determinar si el explorador admite el método addEventListener para definir un controlador de eventos.


function registerEvent( sTargetID, sEventName, fnHandler ) 
{
   var oTarget = document.getElementById( sTargetID );
   if ( oTarget != null ) 
   {
      if ( oTarget.addEventListener ) {   
         oTarget.addEventListener( sEventName, fnToBeRun, false );
      } else {
        var sOnEvent = "on" + sEventName; 
        if ( oTarget.attachEvent ) 
        {
           oTarget.attachEvent( sOnEvent, fnHandler );
        }
      }
   }
}

En este ejemplo, el código de registro de eventos comprueba que el objeto que controla el evento proporciona compatibilidad para el método addEventListener antes de invocar el método para registrar el controlador de eventos. Esto impide errores de sintaxis de tiempo de ejecución y ayuda a ofrecer un enfoque alternativo (también denominado estrategia de reserva) para el caso de que la técnica preferida no sea compatible.

Para determinar si existen objetos, propiedades, atributos o métodos que ayuden a detectar una característica, consulta la especificación que define la característica que quieres usar.

Por ejemplo, Internet Explorer 9 admite el objeto performance de la especificación Tiempo de navegación. En el momento de redactar este tema, esta especificación define el atributo "window.performance". Como resultado, puedes usar la presencia de una propiedad performance en el objeto window para determinar si el explorador web actual admite la especificación Tiempo de navegación, como se presenta en la muestra de código siguiente.


if ( window.performance ) {
   showLoadTimes( window.performance );
}

En este ejemplo, la función showLoadTimes() solo se invoca cuando el objeto window admite una propiedad performance.

Creación de objetos para admitir características

Algunas características no pueden detectarse en el DOM hasta que el explorador las representa. Por ejemplo, Internet Explorer 9 solo admite el elemento audio cuando una página web se muestra en el modo estándar de IE9. Si una página web que contiene un elemento audio se muestra en el modo de IE5 (no estándar), o se muestra en una versión anterior de Internet Explorer, el elemento audio se representa como un elemento desconocido (genérico).

De acuerdo con la sección anterior, la siguiente muestra de código podría parecer suficiente para determinar si un explorador admite el elemento audio.


<!doctype html>
<head>
<title>Simple Audio Support Test</title>

<script type="text/javascript">

   function supportsAudio() 
   {
     var d = document;
     var o = d.getElementById( "audio1" );
     return ( o != null ); 
   }

   function checkAudioSupport() 
   {
      var s = ( supportsAudio() == true ) ? 
              "supports " : "does not support ";
      var o = document.getElementById( "dOutput" );
      o.outerText = "Your browser " + s + "the audio element.";
   }

</script>

</head>
<body>
   <audio id="audio1" src="audiofile.mp3" />

    <button onclick="checkAudioSupport();">
        Click to test audio support.
    </button>
    <br />
    <div id="dOutput">Please click a button</div>

</body>
</html>

En este ejemplo, se intenta crear un elemento audio y la evaluación de su compatibilidad con características se basa en si se creó el objeto. Aunque este ejemplo podría indicar correctamente que Internet Explorer 9 admite el elemento audio cuando la página se muestra en modo IE9, notificaría incorrectamente lo mismo cuando la misma página web se muestre en modo IE5. La función supportsAudio() presupone que la capacidad para obtener una referencia a un objeto creado por un elemento audio es, de hecho, un elemento audio que admite la reproducción de música. Esto representa un problema cuando se supone que los exploradores web crean referencias genéricas a elementos HTML no compatibles.


   function supportsAudio() 
   {
     var o = document.createElement( 'audio' );
     return ( o.canPlayType ); 
   }

Además, este ejemplo no requiere que la página web contenga un elemento audio para poder determinar si admite el elemento audio.

En casos en los que el DOM no contiene un objeto o propiedad DOM integrado para la característica que quieres detectar, usa createElement o un método similar para crear un objeto temporal, y después comprueba que el objeto temporal es el tipo de objeto que te interesa.

Nota  Para obtener mejores resultados, evita suposiciones sobre los exploradores en diferentes dispositivos. Un explorador de escritorio podría admitir características diferentes que la versión para dispositivos móviles del mismo explorador que, a su vez, podría diferir del mismo explorador en un dispositivo diferente. Con la detección de características, puedes probar las características que necesites en todos los exploradores.

Búsqueda de características DOM

El método hasFeature indica la compatibilidad para especificaciones individuales o conjuntos de características definidas por una especificación. Por ejemplo, la muestra de código siguiente especifica cómo determinar si un explorador admite SVG.


bResult = document.implementation.hasFeature("org.w3c.svg", "1.0")

Las cadenas de características específicas están definidas por la especificación que define la característica. Por ejemplo, la especificación de Document Object Model (DOM) de nivel 2 del World Wide Web Consortium (W3C) admite varias cadenas de características que corresponden a los módulos de la especificación general.

Ten en cuenta que, si bien el método hasFeature puede indicar que un explorador determinado es compatible con una característica específica, también es posible que el explorador no admita todos los aspectos de la característica. Si tienes dudas, tómate un momento para investigar la implementación de una característica determinada en los exploradores conocidos.

Para obtener más información sobre el estado de una especificación determinada o un conjunto de características, consulta los recursos proporcionados por la organización que promueve la especificación. Por ejemplo, el sitio web del World Wide Web Consortium (W3C) contiene una sección Participación que destaca los recursos relativos al desarrollo de estándares W3C, e incluye áreas de discusión, actualizaciones de estado e información relacionada.

Existen muchas maneras de detectar características compatibles con un explorador web. Asegúrate de usar las técnicas de detección que se relacionan directamente con la característica que quieres usar. Por ejemplo, no es adecuado evaluar el color de un cuadro de texto para determinar la fuente usada para mostrar el contenido. Este tipo de relaciones tiende a causar problemas con el tiempo.

 

 

Mostrar:
© 2014 Microsoft