El uso de la etiqueta meta viewport

En el mundo de la web móvil la etiqueta meta viewport se ha convertido en un elemento esencial, básico en los últimos tiempos. Inicialmente introducida por Apple en su navegador Safari para iPhone, rápidamente fue adoptada por otros navegadores hasta hacerse habitual en todos los OS móviles. Esta etiqueta busca dar una serie de directrices a los navegadores para que rendericen adecuadamente la web.

Hay que ponerse un poco en situación: cuando aparecieron los primeros smartphones no había webs adaptadas para dispositivos móviles, y pasó tiempo hasta que las hubo (a día de hoy todavía hay muchas páginas que no se visualizan correctamente). ¿Solución? Que el teléfono “emule” una pantalla más grande y la web original se redimensione a ese tamaño. La idea es buena ¿El problema? Bueno, que era una solución temporal para aquel momento, pero que en la actualidad se queda coja. Este sistema que nos muestra una pantalla reducida hace que si hemos hecho una maquetación responsiva con media queries la cosa no acabe de funcionar. Para eso está meta viewport, para establecer el ancho, el alto o el zoom de la página.

La meta viewport utiliza una serie de pares de claves=valores para definir diversos comportamientos del navegador a la hora de renderizar la web:

<meta name="viewport" content="
	width = [tamaño en pixels | device-width ],
	height = [tamaño en pixels | device-height],
	initial-scale = float mayor que 0.1,
	minimum-scale = float mayor que 0.1,
	maximum-scale = float mayor que 0.1,
	user-scalable = [yes | no]
">

<!--Un ejemplillo real tras la teoría-->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

Muy bien ¿y para qué vale cada una?:

Bueno, width lógicamente para definir el ancho de la pantalla. Podéis definir un ancho fijo, lo cual en términos generales viene a ser un epic fail. En cambio si usáis device-width esta ya se adaptará directamente al dispositivo.

Sobre heigth lo mismo, sólo que en este caso se define el alto. En la práctica no se me ocurre quién querría definir un alto estático, pero existir existe.

Para regular qué zoom tendrá por defecto la página está initial-scale, a la cual le tienes que dar un valor a partir de 0.1, siendo el valor 1 el equivalente a no tener zoom (es decir, menos de uno reduce y más de 1 amplía).

La pareja maximum-scale y minimum-scale nos permiten definir cual será el zoom máximo y el mínimo que pueda aplicar el usuario. Como arriba, 1 es igual a que se vea tal cual, sin zoom.

Finalmente user-scalable lo que nos permite es definir si queremos que el usario pueda hacer zoom o no. Lo mejor es dejarlo en yes, ya que no es buena idea poner limitaciones al user, y mucho menos en el caso del zoom, ya que podría tratarse de alguien con problemas de visión que necesite ampliar la página para poder leerla. Con el maximum y el minimum scale tres cuartos de lo mismo, piensa bien qué hace si vas a poner límites.

En fin, con esto ya tienes otro paso para mejorar tus diseños web adaptados a dispositivos móviles.

Análisis de eMobc Lander, servicio para crear webs móviles con html5

Creo que alguna vez en el pasado hablé del framework libre para desarrollo móvil eMobc. Basado en plantillas, cuya estructura y contenido se definen a través de un xml, nos permite crear de forma sencilla y sin conocimientos de programación apps móbiles en HTML5 o nativas para Android e iOS.

Ahora ofrecen un nuevo servicio, eMobc Lander. Este nos permite crear apps móviles en HTML5 y alojarlas en su nube.

El sistema de creación es sencillísimo, en serio, tanto como hacerse un blog en WordPress o Blogger. Tras registrarte llegas a un panel donde puedes crear varias páginas, con cuatro pasos definidos:

  1. Configuration: A su vez tiene cuatro secciones. En Social Media podéis incluir enlaces a redes sociales, en Templates elegir una plantilla, en SEO añadir título, descripción, palabras clave, autor… y en Domain elegís el dominio de vuestra app.
  2. Content: Aquí está la chicha, desde este paso metéis contenido a vuestra app. Puede ser de todo tipo: audio, video, fotos, html local, una web, una fuente rss… incluso tiene un chat.
  3. Appearance: Elige tu icono, el logo, fotos, colores de fuentes, fondos, menús… en fin, desde aquí puedes meterle mano a la maquetación para modificar tu plantilla.
  4. Statistics: Este paso ya no forma parte de redacción, simplemente es un módulo con estadísticas donde podremos ver el número de visitas, qué pantallas han visto y cuántas conversiones hemos obtenido.

En fin, hasta aquí la parte buena: es muy fácil de usar y logra resultados muy atractivos en poco tiempo, es muy productivo. En cosa de media hora hice esto esta mañana.

Claro está, tenía que haber puntos negros como en cualquier servicio: el primero es que al trabajar con plantillas se pierde flexibilidad respecto a un desarrollo puro y duro, cosa que era de esperar. El segundo… que el servicio gratuito está limitado a 1000 visitas al mes. Pagando 19 euros al mes podrás conseguir aumentar el límite hasta las 5000 visitas mensuales y además podrás usar tu propio dominio. Y finalmente hay un plan de 39 euros mensuales que te permite visitas ilimitadas, eliminar el branding de eMobc e insertar publicidad para monetizar tu aplicación.

Llegados a este punto debes analizar si te interesa pagar un plan, si vas a superar o no el número de visitas y si te será más rentable pagar el precio de uno de sus planes o, por contra, encargar un app a una empresa. Todo depende del uso que quieras dar a tu aplicación web. En todo caso se trata de una herramienta cómoda que no está de más probar y que para ciertas cosas es muy válida.

Tres consejos para el diseño responsivo

Había dejado un poco tiradas las traducciones de Web Designer Wall tras haber hecho dos sobre diseño responsivo y media queries. Ahora voy con el tercer artículo (que curiosamente era el primero que leí) sobre cómo hacer una página con diseño responsivo en tres cómodos pasos.

El primer paso es desactivar la propiedad que hace que en algunos navegadores móviles el tamaño de la página se reduzca al de la pantalla (se reduzca a saco, sin adaptar nada más, dando como resultado muchas veces páginas inusables):

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

Bueno, se me olvidaba comentar que como en todas las entradas de esta web hay una demo. Lo siguiente para el diseño es usar adecuadamente la estructura de HTML5, que en el ejemplo sería:

<div id="pagewrap">
  <header></header>
  <content></content>
  <sidebar></sidebar>
  <footer></footer>
</div>

En un principio la altura del header sería de 180 px, la anchura del content de 600 px y la del sidebar de 300.

Y finalmente toca la hora de las media queries para que el diseño se adapte.

Por ejemplo, para una dispositivo con una resolución máxima de 980px pasamos a tamaños relativos:

@media screen and (max-width:980px){
 #pagewrap{
    width:94%;
 }
 content{
    width:65%;
 }
 sidebar{
    width:30%;
 }
}

Para una de menos de 700px modificamos la hoja de estilos para que se posicione la sidebar debajo del contenido:

@media screen and (max-width:700px){
 content{
    width:auto;
    float: none;
 }
 sidebar{
    width:auto;
    float:none;
 }
}

Y para una pantalla de un móvil (máximo de 480 px) reducimos el tamaño de los títulos, dejamos que el ancho de la cabecera (header) se ajuste automáticamente y directamente quitamos la sidebar:

@media screen and (max-width:480px){
 header{
    height:auto;
 }
 h1{
    font-size:24px;
 }
 sidebar{
    display:none;
 }
}

Concluye el artículo remitiendo al de diseño con media queries que yo también traduje en este blog y referencié antes.

Espero que esta pequeña guía tutorial que he traducido, junto a las otras dos traducciones sobre media queries, os hayan servido de ayuda en la edición de vuestros proyectos web. Y si no… jQueryMobile siempre es una ayuda.

Creando un menú de navegación con jQueryMobile

Crear un menú de navegación con jQueryMobile, adaptando la web para una mayor usabiliad en dispositivos móviles, no es complicado.

El primer paso consiste en declarar el atributo data-role del div como navbar. Dentro de este metemos una lista desordenada (ul) y en cada elemento (li) de la misma añadimos un enlace, apuntando a la página a la que tiene que ir. A los enlaces no hay que definirles data-role.

Para cambiar el color de los botones usaremos el atributo data-theme (en el ejemplo data-theme=b para ponerlos de color azul), si no lo hacemos serán del mismo color que la cabecera. Una de las ventajas de jQueryMobile es que definiendo la clase ui-btn-active se un estilo más claro al botón seleccionado, sin que tengamos que currarnos un CSS para ello.

Recuerda también definir el data-icon para que el botón quede más bonito.

<header data-role="header"> 
    <h1>SJV Town Hall</h1>
    <div data-role="navbar">
        <ul>
             <li>
                 <a href="#inicio" class="ui-btn-active" data-icon="home" data-theme="b">Inicio</a>
             </li>

             <li>
                 <a href="#favourites" data-icon="star" data-theme="b">Favoritos</a>
             </li>

             <li>
                 <a href="#contactos data-icon="grid" data-theme="b">Contactos</a>
             </li>
         </ul>
       </div>
</header>

En el ejemplo puedes ver un poco de todo lo que hemos comentado arriba.

URI schemes en HTML 5

Al hablar de URI schemes hablamos de recursos que invocan aplicaciones ya instaladas en un dispositivo móvil y que nos permiten volcar ciertas funcionalidades en ellas, haciendo así más natural y fluída la navegación para el usuario. Aquí vamos a ver el uso de dos de las más básicas: hacer uso del sistema de SMS del teléfono y llamar a un número de teléfono.

  • SMS: Permite enviar rápidamente un mensaje de texto, indicando en el enlace un número e incluso el cuerpo del mensaje. Recuerda que debes poner el código del país antes del ńúmero, por aquello de la internacionalización. El marcado html sería:
    <a href="sms:666777888">Cuerpo del mensaje</a>
    
  • Teléfono: En este caso el enlace nos permitirá hacer una llamada a un número. Como en el anterior acuérdate del código del país antes del número. El marcado sería:
    <a href="tel:666777888">666777888</a>

Esto son ejemplos muy básicos, pero hay gran variedad de opciones: schemes para Facebook, Twitter, Pinterest… Existen múltiples schemes ya creados para iPhone, Android o HTML5 que podéis buscar en la web.

En fin, espero que os sirva de ayuda a los que como yo os estéis iniciando en la programación para dispositivos móviles

Listas en jQueryMobile: ordenadas y desordenadas

A la hora de trabajar tanto con listas ordenadas o listas desordenadas con jQueryMobile no hay mucha ciencia, es como trabajar con listas en html clásico.

Mayormente hay que usar la etiqueta ul para listas desordenadas y ol para ordenadas, como en cualquier página. La única diferencia es añadir el atributo data-role=”listview”. Esto es lo único que necesitas en jQueryMobile para aplicar el estilo “móvil” a la lista. Te pongo un ejemplillo


<ol data-role="listview" data-inset="true" data-filter="true">
   <li><a href="#">El Resplandor</a></li>
   <li><a href="#">La Naranja Mecánica</a></li>
   <li><a href="#">Barry Lyndon</a></li>
   <li><a href="#">La Chaqueta Metálica</a></li>
</ol>

<ul data-role="listview" data-inset="true">
   <li><a href="#">Gran Torino</a></li>
   <li><a href="#">Mystic River</a></li>
   <li><a href="#">Million Dollar Baby</a></li>
   <li><a href="#">Sin Perdón</a></li>
</ul>

Sep, la lista ordenada son películas de Kubrick y la sin índices son de Clint Eastwood. Y no hay más que hablar, sólo el atributo data-role=”listview”, por el resto HTML de toda la vida.

Formularios HTML5 con jQueryMobile

Tras la iniciación a la maquetación con jQueryMobile que publiqué ayer, toca complementarla con una introducción a los formularios.

Como es habitual en todo formulario HTML, los campos estarán encerrados entre etiquetas form, con su action y su method definidos. Existen varios tipos de controles, que son mas que suficientes para poder crear formularios complejos, que puedes consultar aquí.

Una de las opciones que nos reporta jQueryMobile es la de poder crear formularios “mini”, con una versión más pequeña de sus controles para facilitar la visualización en las pantallas de los móviles. Para ello debemos añadir el atributo data-mini=”true” en el controlgroup.

El atributo placeholder (del que también hablamos en este blog) juega un papel importante aquí. Si quieres ocultar la etiqueta label por motivos de accesibilidad pero que los lectores de pantalla puedan leerla, podras servirte de la clase ui-hidden-accessible y, con el atributo placeholder, usar el elemento de formulario con la etiqueta dentro.

Para deshabilitar un elemento del formulario usaremos el atributo disabled. En el caso de que necesitemos aplicar el estilo disabled a un elemento que no sea un control de formulario, podemos utilizar la clase ui-disabled sobre el elemento.

Ahora un ejemplo de un formulario con las etiquetas como placeholder y controles mini, para ilustrar lo explicado.

<form action="procesar.php" method="post" id="formEjemplo">
    <div data-role="fieldcontain">
        <fieldset data-role="controlgroup" data-mini="true">
            <legend>Login ejemplo:</legend>
            <label for="user" class="ui-hidden-accessible">Usero:</label>
            <input type="text" name="user" id="user" value="" placeholder="User" />
            <label for="password" class="ui-hidden-accessible">Usuario:</label>
            <input type="password" name="password" id="password" value="" placeholder="password" />
        </fieldset>
    </div>
</form>

Si usas un contenedor para controles de formularios (que es un elemento de jQueryMobile) y quieres ocultar la etiqueta y usar el texto placeholder, tienes que ocultarla en los atributos del div con class=”ui-hide-label” en lugar de en los del label, como en este ejemplo:

<div data-role="fieldcontain" class="ui-hide-label">
    <label for="user">Usero:</label>
    <input type="text" name="user" id="user" value="" placeholder="User" />
</div>

Y con esto ya puedes empezar a hacer tus formularios optimizados para móviles.

Iniciación a jQueryMobile: Maquetando web para móviles con HTML5

A la hora de programar webs para móvil el framework de javascript jQueryMobile, basado en jQuery, nos ofrece una gran productividad, simplificando profundamente las cuestiones de maquetación. Si ya conoces jQuery y jQueryUI la curva de aprendizaje será muy pequeña.

Este framework es compatible con todos los navegadores y sistemas operativos móviles actuales, es ligero (20kb), casi no utiliza imágenes, se puede combinar con PhoneGAP para realizar aplicaciones nativas y es libre y gratuito.

A la hora de crear la estructura, como en cualquier web, lo primero es empezar por la cabecera (la etiqueta HEAD). Ahí agregamos las referencias necesarias a jQuery, jQuery Mobile y el theme básico de CSS. Para definir el ancho de pantalla utilizamos meta viewport, lo dejaremos definido con la constante width=device-width y la escala mínima y máxima a 1; initial-scale=1.0 maximum-scale=1.0.

Una vez que hemos terminado de referenciar las librerías necesarias, creamos la estructura de la plantilla principal de la página utilizando HTML5, y luego definimos las areas de contenido (content region) que proporciona jQueryMobile. El atributo data-role nos permitirá maquetar con comodidad y estructurar la página. Especificaremos la página (data-role=”page”), el encabezado (data-role=”header”), el contenido (data-role=”content”) y el pié (data-role=”footer”). Estos data-role los utiliza jQueryMobile para en Widgets funcionales y con los estilos del theme utilizado las secciones definidas.

Creo que lo mejor es un ejemplo que ilustre lo comentado:

<!DOCTYPE html>
<html>
<head>
    <title>Página prueba</title>
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0-rc.1/jquery.mobile-1.1.0-rc.1.min.css" />
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.1.0-rc.1/jquery.mobile-1.1.0-rc.1.min.js"></script>
</head>
<body> 
 
<!-- Página principal -->
<section data-role="page" data-title="Página de inicio">
 
    <header data-role="header">
        <h1>HW</h1>
    </header>
    <!-- end header -->
 
    <section data-role="content">
        <p>Hello world!</p>
    </section>
    <!-- end content -->
 
    <footer data-role="footer">
        <p>DonnieRock 2012</p>
    </footer>
    <!-- end footer -->  
 
</section>
<!-- end page -->
 
</body>
</html>

Pero el verdadero cambio respecto a la programación web tradicional es el concepto “page within page”. Dentro del mismo documento están incrustadas todas las páginas. De ahí que en el ejemplo de arriba utilizaramos el atributo data-role=page, porque tendremos que definir varias páginas, que se diferenciarán entre ellas por su atributo id, que será obligatorio para poder navegar entre ellas.

La navegación entre distintas páginas de un mismo documento es bastante sencilla, tenemos que poner en el ‘href’ del enlace el ‘id’ de la página destino y ya está. Podemos especificar el tipo de transición con el atributo data-transition, la transición por defecto es slide pero existen varias que puedes consultar en la página de jQuery. También podemos definir la dirección de la transición con el atributo data-direction.

Recuperaré el código del primer ejemplo, con alguna modificacación, para explicar esto:

<!DOCTYPE html>
<html>
<head>
    <title>Página prueba</title>
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0-rc.1/jquery.mobile-1.1.0-rc.1.min.css" />
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.1.0-rc.1/jquery.mobile-1.1.0-rc.1.min.js"></script>
</head>
<body> 
 
<!-- Página principal -->
<section data-role="page" id="page1" data-title="Página de inicio">
 
    <header data-role="header">
        <h1>HW</h1>
    </header>
    <!-- end header -->
 
    <section data-role="content">
        <p>Hello world!</p>
    </section>
    <!-- end content -->

    <footer data-role="footer">
        <p>
            DonnieRock 2012 
           <a href="#page2" data-role="button" data-transition="slidedown">Ir a la página 2</a>
        </p>
    </footer>
    <!-- end footer -->  
 
</section>
<!-- end page 1-->

<!-- Segunda página -->
<section data-role="page" id="page2" data-title="Página 2">
 
    <header data-role="header">
        <h1>HW2</h1>
    </header>
    <!-- end header -->
 
    <section data-role="content">
        <p>Hello, again, world!</p>
    </section>
    <!-- end content -->
 
    <footer data-role="footer">
        <p>
            DonnieRock 2012 
           <a href="#page1" data-role="button" data-transition="slidedown" data-direction="reverse">Ir a la página 1</a>
        </p>
    </footer>
    <!-- end footer -->  
 
</section>
<!-- end page 2-->
 
</body>
</html>

Finalmente nos queda por elegir el “theme”. Podemos crearlo fácilmente con el ThemeRoller que hay en la web de jQueryMobile, con multitud de themes que podemos crear y asignar a cada componente que usemos en nuestra aplicación. También hay themes ya predefinidos, si no queremos rompernos la cabeza. Los themes son diferenciados por una letra identificativa, gracias a la cual podemos identificar el theme y aplicarlo a cualquier componente que queramos, usando el atributo data-theme. Tienes información sobre los distintos themes en la página de jQueryMobile. El theme además puede ser modificado con facilidad tocando los archivos css.

<section data-role="page" id="page1" data-title="Página de inicio" data-theme="b">
 
    <header data-role="header">
        <h1>HW</h1>
    </header>
    <!-- end header -->
 
    <section data-role="content">
        <p>Hello world!</p>
    </section>
    <!-- end content -->

    <footer data-role="footer">
        <p>
            DonnieRock 2012 
           <a href="#page2" data-role="button" data-transition="slidedown">Ir a la página 2</a>
        </p>
    </footer>
    <!-- end footer -->  
 
</section>

Bueno, espero con esto ya tienes unas nociones básicas de cómo empezar. Más adelante tocaré otros temas, como los formularios o la integración con PhoneGAP, de momento podéis ir ojeando esto.

Placeholder: texto dentro de los inputs en HTML5

Placeholder es una nuevo atributo y que te permite introducir un texto dentro de un input, siempre y cuando el campo esté vacío o no esté senalado. En la barra de búsqueda de Opera o de Firefox puedes ver algo similar. Si pulsas sobre el campo (o llegas a él mediante el uso del tabulador) el texto se borrará.

Este atributo está soportado ya por casi todos los navegadores, al menos por Firefox, Opera, Chrome y Safari, me ha dado problemas con IE7 e IE8 y no he podido probarlo con IE9. Y… no tiene mucha más ciencia esto. Tiene utilidad sobre todo a la hora de maquetar webs para dispositivos móviles, ya que así te puedes ahorrar la etiqueta y ganas en espacio en pantalla. Un ejemplillo simple para terminar:

      <form>
      	<input placeholder="Prueba" />
      </form>

Con esto tendrías una etiqueta input con el texto “prueba” por dentro.

Detectando navegadores de móviles (PHP y Javascript)

Es habitual en los tiempos que correr desarrollar una página web para navegadores de escritorio y otras optimizadas para el uso en navegadores móviles (smartphone, tablet). Una maquetación puede parecer cojonuda para una pantalla grande, de un sobremesa, pero ser incómoda en una pantalla de cuatro pulgadas.

En ese caso tenéis dos posibilidades: detectar el dispositivo móvil en el servidor (PHP) o en el cliente (javascript). El ejemplo para PHP sería el siguiente:

<?php
$mobile_browser = ’0';

//$_SERVER['HTTP_USER_AGENT'] -> el agente de usuario que está accediendo a la página.
//preg_match -> Realizar una comparación de expresión regular
if(preg_match(‘/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone)/i’,strtolower($_SERVER['HTTP_USER_AGENT']))){
	$mobile_browser++;
}

//$_SERVER['HTTP_ACCEPT'] -> Indica los tipos MIME que el cliente puede recibir.
if((strpos(strtolower($_SERVER['HTTP_ACCEPT']),’application/vnd.wap.xhtml+xml’)>0) or
((isset($_SERVER['HTTP_X_WAP_PROFILE']) or isset($_SERVER['HTTP_PROFILE'])))){

	$mobile_browser++;
}

$mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));
$mobile_agents = array(
‘w3c ‘,’acs-’,'alav’,'alca’,'amoi’,'audi’,'avan’,'benq’,'bird’,'blac’,
‘blaz’,'brew’,'cell’,'cldc’,'cmd-’,'dang’,'doco’,'eric’,'hipt’,'inno’,
‘ipaq’,'java’,'jigs’,'kddi’,'keji’,'leno’,'lg-c’,'lg-d’,'lg-g’,'lge-’,
‘maui’,'maxo’,'midp’,'mits’,'mmef’,'mobi’,'mot-’,'moto’,'mwbp’,'nec-’,
‘newt’,'noki’,'oper’,'palm’,'pana’,'pant’,'phil’,'play’,'port’,'prox’,
‘qwap’,'sage’,'sams’,'sany’,'sch-’,'sec-’,'send’,'seri’,'sgh-’,'shar’,
‘sie-’,'siem’,'smal’,'smar’,'sony’,'sph-’,'symb’,'t-mo’,'teli’,'tim-’,
‘tosh’,'tsm-’,'upg1',’upsi’,'vk-v’,'voda’,'wap-’,'wapa’,'wapi’,'wapp’,
‘wapr’,'webc’,'winw’,'winw’,'xda’,'xda-’);
//buscar agentes en el array de agentes
if(in_array($mobile_ua,$mobile_agents)){
	$mobile_browser++;
}

//$_SERVER['ALL_HTTP'] -> Todas las cabeceras HTTP
//strpos -> Primera aparición de una cadena dentro de otra

if(strpos(strtolower($_SERVER['ALL_HTTP']),’OperaMini’)>0) {
	$mobile_browser++;
}

if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']),’windows’)>0) {
	$mobile_browser=0;
}

if($mobile_browser>0){
//Aquí redireccionamos hacia la aplicación móvil
}else{
//Aquí nos vamos a la versión para escritorio
}
?>

Se trata de una vieja función que econtré hace tiempo y detecta todo tipo de navegadores. La utilicé en mi proyecto de fin de curso y funcionaba. Utiliza un array con referencias a muchos navegadores de dispositivos móviles. La función de javascript por su parte es más sencillita y detectará el SO:

 var ua = navigator.userAgent.toLowerCase();
 var isAndroid = ua.indexOf("android") > -1; // && ua.indexOf("mobile");
 var isiPhone = ua.indexOf("iphone") > -1;
 var isiPod = ua.indexOf("ipod") > -1;
 var isiPad = ua.indexOf("ipad") > -1;
 if(!isiPad) isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);
 var isWPx = ua.indexOf("windows phone") > -1;

En este caso detecta si se trata de Android, un dispositivo Apple o WindowsPhone.

En último caso, en el siguiente enlace tenéis ejemplos de código actualizados para varios lenguajes. Os puede servir de mucha ayuda.