ene 222013
 

Los dispositivos móviles tienen características claramente distintas de las de los ordenadores de sobremesa y portátiles, que deben ser tenidas en cuenta por el desarrollador de un sitio web dirigido a a este tipo de plataforma.

Por una parte, el tamaño de la pantalla es mucho más reducido, y el usuario puede cambiar la orientación de la misma.

Por otra parte, la cantidad de memoria RAM y la capacidad de proceso son mucho más reducidas.

Pero sobre todo, la interacción del usuario ya no se realiza mediante un teclado y ratón, sino a través de una pantalla táctil.

Este artículo es el primero de una serie en la que revisaremos el impacto de estas peculiaridades cuando se usa javascript para añadir funcionalidad a una página web dirigida a dispositivos móviles.

Soporte Javascript en navegadores para móviles

Tanto Safari para Apple iOS como el navegador de Android ofrecen soporte para javascript. Lo mismo ocurre la mayoría de los otros navegadores que pueden ser instalados sobre estas plataformas, como Internet Explorer u Opera Mobile.

Pero en algunos casos, como en “Opera Mini”, el cliente no es un navegador completo capaz de procesar un fichero XHTML o código javascript. En su lugar, un servidor intermedio (“servidor proxy”) procesa la página, compila y comprime su contenido, enviando al cliente el resultado de este proceso, por lo que el soporte a Javascript no es similar al de los otros navegadores.

Por otra parte, en algunas plataformas el cliente o la propia operadora pueden haber inhabilitado la ejecución de código javascript en el navegador. en estos casos deberemos utilizar el tag “noscript”. Por lo demás, el código javascript se incorpora en la página del mismo modo que para las demás plataformas, contenido entre los tags <script> y </script>, o con un tag <script> que hace referencia a un fichero externo que contiene el código:

<script type="text/javascript">
// El código javascript va aquí
</script>

<script src="miscript.js" type="text/javascript">

Nota: Hay que distinguir entre el caso de un dispositivo/navegador que es compatible con javascript pero lo tiene inhabilitado, y el de uno que no tiene soporte para javascript. En este último caso, el código javascript se le presenta al usuario como texto. Para evitar esto se pueden colocar los signos de apertura de comentario HTML “<!–” y de cierre de comentario HML “–>” englobando el código:

<script type="text/javascript">
<!--
// El código javascript va aquí
-->
</script>

Cómo determinar si un dispositivo/navegador tiene una funcionalidad determinada

Dada la enorme variedad de marcas y modelos de dispositivos móviles existentes, y de versiones del sistema operativo y navegadores utilizados, conviene hacer el programa más robusto, comprobando la disponibilidad en el cliente de las funcionalidades que vamos a necesitar, y programar una funcionalidad alternativa (“fallback”) si no están disponibles. La manera más sencilla de comprobar la disponibilidad de una funcionalidad es mediante una sentencia “if”. Por ejemplo:

if (document.getElementById) {
    // Es posible acceder al DOM
}

Atención: Como ya hemos comentado, incluso en dispositivos con soporte para javascript, el usuario  o la operadora pueden haberlo inhabilitado. Por ejemplo, en los dispositivos BlackBerry existe la opción de inhabilitar Javascript. Siempre hay que prever esta posibilidad y preparar una versión de la página que no utilice javascript, si es posible. En caso contrario hay que presentar un mensaje informando al usuario de que es necesario habilitar javascript para el correcto funcionamiento de la página.


Uso de cuadros de diálogo standard

Javascript implementa una serie de cuadros de diálogo:

  • alert – para mostrar un mensaje
  • confirm – Para pedir al usuario una respuesta Si/No
  • prompt – Para pedir al usuario una cadena de texto
  • print – para enviar la página a la impresora

Estos cuadros de diálogo han sido poco utilizados en los sitios web diseñados para ordenadores de sobremesa y portátiles, reemplazándolos por implementaciones basadas en HTML dinámico y librerías de UI (User Interface). Pero su implementación en dispositivos móviles es plenamente conforme a las reglas de estilo recomendadas por las correspondientes plataformas, haciendo que puedan ser utilizados para crear un interfaz de usuario con aspecto muy profesional sin necesidad de librerías adicionales.

android-javascript-dialogos

 

Utilización de document.write

Históricamente, la función document.write se utilizaba para escribir dinámicamente código HTML en la página durante su creación. Actualmente, se prefiere añadir este código mediante manipulación del DOM después de producirse el evento “onload” de modo que la percepción del usuario (y de los motores de búsqueda) es que el tiempo de carga es menor


Nota: Si el script de una página no utiliza document.write, es conveniente añadir al tag <script> el atributo defer=”defer”. Esto indica a los navegadores que no necesitan esperar a que el script se descargue ejecuta para continuar la creación del documento.


Pero en un dispositivo móvil, sobre todo si es de gama baja, el uso de document.write puede suponer una mejora considerable del rendimiento en comparación con la manipulación del DOM. Esta técnica funciona en los principales navegadores para plataforma móvil, como se puede ver en la siguiente tabla:

Tabla de compatibilidad de  document.write
Browser/platform soporte a document.write
Safari Si
Android browser Si
Symbian/S60 Si
Nokia Series 40 Antes de la sexta edición, no después del evento onload
webOS Si
BlackBerry En versiones anteriores a la 4.6, no después del evento onload
NetFront Si
Internet Explorer Si
Motorola Internet Browser Si, no después del evento onload
Opera Mobile Si
Opera Mini Se ejecuta en el servidor

Por ejemplo, se puede utilizar esta técnica para crear de forma dinámica una lista para seleccionar un año determinado, como se ve en el siguiente código:

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
    "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Document Write</title>
<script type="text/javascript">
function createNumericSelect(name, from, to) {
    var html = "<select name='" + name + "'>";
    for (var i=from; i<to; i++) {
        html += "<option>" + i + "</option>";
    }
    html += "</select>";
    document.write(html);
}
</script>
</head>

<body>
<form action="send">
    <script type="text/javascript">
    createNumericSelect('year', 1990, 2020);
    </script>
</form>
</body>
</html>

Atención: document.write no debe ser utilizado en un manejador de eventos, como onload o onclick. Una vez cargada la página, se debe utilizar el DOM para añadir código HTML dinámicamente.

Detección de la plataforma

En JavaScript existe un objeto “navigator” que representa el navegador del cliente en el cual se está ejecutando. Con los atributos de este objeto podemos determinar el tipo de dispositivo en el que se ejecuta y tomar decisiones en base a ello.

Las propiedades más útiles del objeto navigator son:

  • appName – el nombre del navegador
  • appVersion – la versión del navegador
  • mimeTypes – array de tipos MIME soportados
  • plugin – array de plugins soportados
  • platform – el sistema operativo
  • userLanguage – el idioma preferido establecido en la configuración del navegador

Normalmente, utilizaremos la función indexOf para ver si alguno de estos atributos contiene el valor que nos interesa. Por ejemplo:

// Detectar si es un dispositivo Android
var android = (navigator.platform.indexOf("android")>=0);
if (android) {
   // Hacer algo
}

En la siguiente tabla vemos los valores de estas propiedades en los distintos navegadores.

propiedades del objeto navigator
Navegador/ Plataforma appName appVersion mimeTypes platform
Safari Netscape 5.0 (<User Agent>) Array iPhone, iPod, or iPad
Android browser Netscape 5.0 (<User Agent>) Array null
Symbian/S60 Netscape 5.0 (<User Agent>) Array S60
Nokia Series 40 before 6thedition Nokia Empty string Undefined Undefined
Nokia Series 40 6th edition Netscape 2.0 Undefined Nokia_Series_40
webOS Netscape 5.0 (<User Agent>) Array webOS
BlackBerry Netscape <Platform version> Array BlackBerry
NetFront ACCESS NetFront <Browser version> Array Unknown
Internet Explorer Microsoft IE Mobile Empty string Undefined WinCE
Motorola Internet Browser Netscape 5.0 Array WiderWeb
Opera Mobile Opera <opera engine version> (Symbian or Windows) Array Symbian or Windows
Opera Mini Opera <opera engine version> Array Pike

Tamaño de la ventana

En JavaScript hay dos objetos relacionados con el tamaño de la ventana de visualización: document.documentElement se refiere al tamaño del “viewport”, y screen se refiere al tamaño de la pantalla del disositivo. En dispositivos móviles, actualmente no hay navegadores que permitan una ventana de tamaño inferior al de la pantalla completa. En muchos de ellos, se pueden crear “web widgets” para la pantalla home.


Nota: Los dispositivos BlackBerry tienen una objeto global “blackberry” con dos atributos: “location” y “network”. El atributo “network” permite saber el tipo de conectividad con la cual se está accediendo a internet: WiFi, GPRS, EDGE, CDMA, o algún otro tipo de red. El navegador Android, a partir de la versión 2.2, tiene una propiedad “navigator.connection.type” que alberga la misma información.


El objeto “screen” tiene cuatro atributos: width, height, availWidth, y availHeight. Los dos últimos indican el tamaño disponible no ocupado por las barras de herramientas del sistema operativo. En un dispositivo móvil, los valores de availWidth y availHeight coinciden normalmente con los valores de width y height.

El tamaño de la ventana se obtiene mediante document.documentElement.clientWidth y document.documentElement.clientHeight. Estos valores pueden cambiar si se produce un cambio de orientación del dispositivo, en aquellos que lo permiten.

En el momento de producirse un cambio de orientación se genera normalmente un evento “onresize”, y en algunos casos un evento “onorientationchange”.

La siguiente tabla resume el comportamiento de los distintos navegadores en lo relacionado con el tamaño de la ventana:

Propiedades y eventos relacionados con el Tamaño de la pantalla
Browser/platform Screen size Window size Orientation change
Safari Yes Yes onorientationchange and onresize
Android browser Yes Yes onresize
Symbian/S60 Yes, different in full-screen mode Yes onresize
Nokia Series 40 No before 6th edition No before 6thedition No
webOS Yes Viewport size onresize
BlackBerry No before 4.6 No document.onresize in some devices
NetFront Yes No No
Internet Explorer Yes No No
Motorola Internet Browser Yes Yes No
Opera Mobile Yes Yes No
Opera Mini Yes Yes No

Historial de navegación y gestión de URLs

JavaScript implementa los objetos “location” y “history” para gestionar el historial de navegación. El objeto “location” tiene varios atributos relacionados con la dirección de la página, tales como “href” para obtener la URL completa, y “hash” para obtener el “anchor” de la URL si está presente ( el símbolo # y todo lo que hay a su derecha). En javascript, se puede dirigir el navegador hacia otra página asignando la url de destino como valor de location.href. Por otra parte, el objeto “location” implementa los métodos reload() para refrescar la página, y replace(url), que carga otra página sin crear una entrada en el historial.

El objeto “history” implementa los métodos back(), go(número), y forward(). Una llamada al método back() es equivalente a pulsar el botón “Atrás” del navegador:

<!-- En forma de botón -->
<input type="button" onclick="history.back()" value="Back" />
<!-- En forma de enlace -->
<a href="javascript:history.back()">Back</a>

En un diseño de interfaz de usuario para móviles, puede ser interesante incluir un botón para ir a la página anterior, ya que los botones del navegador pueden no estar visibles, al contrario de lo que ocurre en ordenadores de sobremesa o portátiles.

Manipulación de las ventanas

window.open es una manera habitual de abrir ventanas de pop-up en páginas diseñadas para ordenadores de sobremesa.

Sin embargo, esta funcionalidad tiene una implementación distinta en la mayoría de los navegadores de disposivos móviles. Por una parte, algunos navegadores no permiten abrir varias ventanas. además los popups ocuparán toda la pantalla. Los mecanismos de comunicación entre la ventana de popup y la página que la ha creado tampoco funcionan igual. En algunos casos, el popup no se puede cerrar con una llamada a window.close.

Por estas razones, es preferible evitar el uso de popups.  En su lugar, se pueden utilizar enlaces con target=”_blank”. Esto abrirá una nueva ventana. Si el navegador no soporta ventanas múltiples, la nueva ventana sustituye simplemente a la ventana llamante.

Gestión del foco y del scroll

En cualquier elemento sobre el que sea posible hacer click (una entrada de formulario, un enlace o un botón,…) se puede utilizar la función “focus” del DOM para activarlo. El uso más común de esta posibilidad es la activación de una entrada de formulario (“input”) para solicitar al usuario la introducción de datos. Si la página a la que ha accedido el usuario es básicamente un formulario, como puede ser una página para realizar una búsqueda, o un formulario de contacto, es deseable por razones de usabilidad activar automáticamente el primero de los elementos de entrada de texto. De este modo se reduce la cantidad de navegación que el usuario tiene que realizar en la página.

Por otra parte, en algunos dispositivos el objeto “window” implementa una función “scrollTo(x,y)” que permite desplazar el contenido de la página para que las coordenadas especificadas se sitúen en la esquina superior izquierda de la pantalla. En páginas diseñadas para dispositivos móviles, es habitual utilizar la siguiente llamada dentro del evento onload, para esconder la barra de herramientas del navegador:

window.scrollTo(0, 1);

También se puede utilizar esta llamada para crear links que lleven al comienzo de la página:

<a href="javascript:window.scrollTo(0, 1);">Ir al comienzo</a>

Alternativamente, se puede conseguir este mismo comportamiento utilizando “anchors”.

Temporizadores

En JavaScript existen dos tipos de temporizadores: setTimeout and setInterval. El primero se ejecuta una única vez, y el segundo se ejecuta cada n milisegundos, hasta que es cancelado con una llamada a clearInterval. Se pueden utilizar los temporizadores para crear una animación, para realizar una actualización periódica del contenido de la página utilizando Ajax, o para controlar el tiempo límite de una operación.


Atención: En navegadores de móviles, el uso de temporizadores puede aumentar significativamente el consumo de batería. Si la aplicación requiere el uso de muchos temporizadores simultáneos, hay que evaluar la posibilidad de sustituirlos por un único temporizador que ejecute distintas operaciones según corresponda.


En dispositivos móviles hay que tener en cuenta el comportamiento de los temporizadores cuando el usuario cambia a otra aplicación, o el teléfono se pone en modo de reposo. Por otra parte, los temporizadores utilizan el mismo hilo de ejecución que el script principal. Si el tiempo de proceso de éste es elevado, puede ocurrir que un temporizador con una frecuencia de repetición elevada (por ejemplo, cada 10 ms) no pueda llevar el ritmo adecuadamente.

Con el siguiente ejemplo podemos analizar lo que ocurre en condiciones normales, y cuando una página pasa a ejecutarse en background.

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
    "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Utilizando temporizadores</title>
</head>

<body>
<script type="text/javascript">
var timer = setInterval(timerHit, 200);
var q = 0;
var lastTime = new Date().getTime();

function timerHit() {
    q++;
    var currentTime = new Date().getTime();
    var deltaTime = currentTime - lastTime;
    lastTime = currentTime;
    document.getElementById("content").innerHTML += q + ": " +
               deltaTime + "<br />";

    // Repetir hasta 10 veces
    if (q==10) {
        clearInterval(timer);
    }
}
</script>

<div id="content">
</div>

</body>
</html>
android-javascript-timers

Como podemos ver en la figura, la frecuencia real con la que se ejecuta un timer puede ser muy distinta de la que hemos programado.

 

Tabla de soporte a temporizadores javascript
Browser/platform Timers available Timers in background
Safari Yes Stopped. From iOS 4.0: continue working while in other browser’s window.
Android browser Yes Stopped.
Symbian/S60 Yes Stopped. From 2.2: continue working while in other browser’s window.
Nokia Series 40 No
webOS Yes Continue working.
BlackBerry No
NetFront Yes No multitasking.
Internet Explorer Yes Stopped.
Motorola Internet Browser No
Opera Mobile Yes Continue working.
Opera Mini No

La conclusión es que en dispositivos móviles es preferible prescindir si es posible de los temporizadores de frecuencia elevada (inferior a un segundo), mientras que los de baja frecuencia no presentan problemas.

Activación de una página que estaba en background

Como hemos visto, en casi todos los dispositivos los temporizadores se quedan inactivos cuando la página deja de estar en primer plano o el dispositivo se pone en modo de reposo. Esto permite escribir un código que detecta la activación de una página que estaba inactiva, comparando el tiempo entre dos ejecuciones de una función asociada a un temporizador:

// The time, in ms, that must be "missed" before we
// assume the app has been put to sleep.
var THRESHOLD = 10000;

var lastTick_;
var detectWakeFromSleep_ = function() {
  var now = new Date().getTime();
  var delta = now - this.lastTick_;
  if (delta > THRESHOLD) {
    // The app probably just woke up after being asleep.
    notifyWakeFromSleep(delta/1000);
  }
  lastTick_ = now;
};

Una explicación más detallada de este procedimiento se puede consultar en http://www.mobilexweb.com/go/timers


Atención: Si el dispositivo se está quedando sin memoria y nuestra página está en background, puede ocurrir que el navegador borre la página para liberar memoria, y cuando el usuario regrese a ella, la página se volverá a cargar del servidor, comenzando una nueva sesión a partir de cero.


Cookies

En principio, los cookies pueden ser utilizados en dispositivos móviles de la misma forma que en equipos de sobremesa o portátiles. Pero hay que tener en cuenta que el tiempo de vida de un cookie puede ser mucho más corto en un dispositivo móvil, ya que cuando la memoria disponible disminuye el dispositivo puede eliminar esta información para recuperarla.

 Publicado por en 3:38 pm

 Deja un comentario

(requerido)

(requerido)


nueve − 6 =