#GeekStuff: Ya pueden navegar por mi blog usando gestos táctiles para cambiar de post

Actualizado por hace 3 años

Ayer sábado aproveche para dormir mucho, porque me sentí mal de tanto comer ayer que nos juntamos a jugar Super Smash Bros. for Wii U mis carnales Marzo, Blinker y yo. Básicamente no pude dormir bien en toda la madrugada y en la mañana me sentía muy, muy mal. Náuseas, vómito, sudor frío, etc. ― It sucked.

Y bueno, después de sufrir tanto, por fin pude conciliar el sueño y casi les puedo asegurar que a ustedes también les ha pasado que duermen y sueñan con la solución de algún problema o se les ocurre alguna buena idea mientras sueñan, pues a mi se me ocurrió mientras soñaba que podía mejorar la experiencia al leer mi blog especialmente en dispositivos móviles.1

Introducción

Pues la solución para mejorar la experiencia al leer mi blog a todos los usuarios móviles es darles la capacidad de navegar entre posts usando gestos táctiles, en este caso el gesto táctil que usé fue swipe.

¿Apoco no es mucho más fácil swippear a la izquierda o derecha para cambiar de post en lugar de tener que ir a los links de navegación que tengo en mi footer? A mi me parece mucho mejor, fácil, rápido y sobre todo ― cómodo.

Para lograrlo fue necesario hacer uso de una librería open-source llamada Hammer.js, que hace posible el reconocimiento de gestos táctiles en el DOM. Lo mejor de todo es que es extremadamente ligera, solo pesa 3.96 kB minificada y con gzip.

A continuación les explico paso a paso lo que hice para poder lograrlo.

Paso 1: Agregamos los scripts a nuestro proyecto

Primero que nada es necesario agregar Hammer.js a nuestro proyecto, para ello hay que bajar el archivo hammer.min.js y subirlo a nuestra carpeta js para tenerlo en nuestro propio servidor, o podemos tomarlo directamente de la URL http://hammerjs.github.io/dist/hammer.min.js haciendo referencia a él al momento de registrar el script. Aquí ejemplifico la segunda opción:

  
     <script src="http://hammerjs.github.io/dist/hammer.min.js"></script>
  

Después solamente tenemos que crear un archivo js en blanco que podamos usar para meter el código que hará toda la magia. En mi caso yo ya cuento con un archivo main.js que uso para meter todos mis scripts, ese mismo archivo usé para meter el jQuery que hará el trabajo.

En mi caso, el archivo main.js ya lo tenía registrado:

  
     <script src="js/main.js"></script>
  

Paso 2: Definimos nuestra navegación

Ahora es necesario definir links de anterior y siguiente, eso dependerá del CMS que utilicen ya que cada uno tiene su manera de imprimir la navegación entre posts. Este fragmento de código va en el archivo que les imprime el post, este es el markup que tienen que tener en sí:

  
     <div class="primary_navigation">
          <p>
               <span class="nav-previous">
                    <?php previous_post('← %', '', 'yes'); ?>
               </span>
          </p>
          <p>
               <span class="nav-next">
                    <?php next_post('% →', '', 'yes'); ?>
               </span>
          </p>
     </div>
  

Metemos los links en un div y le damos una clase para poder darle estilos (si es que quieren ocultar la navegación, por ejemplo), en el snippet de arriba se le dio de nombre primary_navigation, pero ustedes póngale como quieran.

Luego es muy importante poner los links de navegación2 adentro de unos spans para poderles poner las clases nav-previous y nav-next respectivamente. Esto nos servirá más adelante para poder apuntar hacia ellos cuando lleguemos a la parte divertida.

Luego, pongámosle la clase gesture a nuestro <body>, para que nos quede así:

  
     <body class="gesture">
  

Esto nos servirá más adelante para poder detectar cuando los usuarios entren a través de un dispositivo móvil. 🙂

Paso 3: Creamos nuestro script para detectar los gestos táctiles

En este punto ya podemos navegar entre posts usando la navegación que creamos arriba, pero todavía no hacemos posible la navegación con gestos táctiles. Ahora si hay que poner manos a la obra en el archivo js que creamos al principio. Recuerden que mi archivo se llama main.js.

Primero, lo primero, creamos una función. En este ejemplo yo le puse de nombre runGesture();:

  
     $(document).ready(function($) {
          function runGesture() {
               //Aquí dentro irá el código que hará que la magia suceda.
          }
     }
  

Luego declaramos algunas variables, una que se llame url que almacenará la URL anterior o siguiente de la navegación que creamos arriba. Después declaramos otra que se llamará gestureContainer que obtendrá el <body> gracias a la clase gesture:

  
     $(document).ready(function($) {
          function runGesture() {
               var url = false;
               var gestureContainer = $('body.gesture');
          }
     }
  

Enseguida y justo como se indica en la documentación de Hammer.js, hay que inicializar el plugin, almacenando la nueva función en otra variable, en mi caso le puse mc:

  
     $(document).ready(function($) {
          function runGesture() {
               var url = false;
               var gestureContainer = $('body.gesture');
               var mc = new Hammer(gestureContainer);
          }
     }
  

Ahora si, el código que hará lo hermoso de este asunto. Haremos uso de los eventos swipeleft y swiperight3. Dentro de las dos nuevas funciones creadas pondremos url = $('.nav-next a').attr('href'); y url = $('.nav-previous a').attr('href'); para almacenar el valor de cada link en url cuando se dispare cada evento. En la variable url dentro de swipeleft almacenaremos el valor de .nav-next a porque se siente más natural hacer swipe a la izquierda para avanzar o cambiar de página hacia adelante, de igual manera pasa lo contrario en swiperight, donde almacenaremos el valor de .nav-previous a dentro de url para ir a la página anterior haciendo swipe a la derecha.

Después de obtener las URLs luego de disparar el evento, haremos el cambio de URL con window.location = url;. Shall we?

En este punto, su código tendría que verse de la siguiente manera:

  
     $(document).ready(function($) {
          function runGesture() {
               var url = false;
               var gestureContainer = $('body.gesture');
               var mc = new Hammer(gestureContainer);

               // esta función detecta el swipe a la izquierda
               mc.on('swipeleft', function(ev) {
                  url = $('.nav-next a').attr('href');
                  if ( url ) {
                     window.location = url;
                  }
               });

               // esta función detecta el swipe a la derecha
               mc.on('swiperight', function(ev) {
                  url = $('.nav-previous a').attr('href');
                  if ( url ) {
                     window.location = url;
                  }
               });
          }
     }
  

En este punto, las cosas ya deberían de funcionar si lo prueban en sus teléfonos, solo que todavía hay un problema, esto que acabamos de hacer también funcionará en desktop y no queremos eso, ¿verdad?

Paso 4: Detección del browser

¿Se acuerdan de <body class="gesture">? Pues ahí es cuando la clase gesture nos será de utilidad y nos servirá para saber cuando algún usuario nos visite desde un dispositivo móvil.

WordPress afortunadamente me permite detectar con body_class qué página se está visualizando en determinado momento. Pues bien, es hora de llevar esa funcionalidad un poco más allá para detectar el browser e inyectarle una nueva clase a mi <body class="gesture"> dependiendo del browser utilizado.

Para poder hacerlo tuve que agregar el siguiente fragmento de código a mi functions.php:

  
     function browser_body_class($classes) {
          global $is_lynx, $is_gecko, $is_IE, $is_opera, $is_NS4, $is_safari, $is_chrome, $is_iphone;
 
          if($is_lynx) $classes[] = 'lynx';
          elseif($is_gecko) $classes[] = 'gecko';
          elseif($is_opera) $classes[] = 'opera';
          elseif($is_NS4) $classes[] = 'ns4';
          elseif($is_safari) $classes[] = 'safari';
          elseif($is_chrome) $classes[] = 'chrome';
          elseif($is_IE) $classes[] = 'ie';
          else $classes[] = 'unknown';
 
          if($is_iphone) $classes[] = 'iphone';
 
          return $classes;
     }
 
     add_filter( 'body_class', 'browser_body_class' );
  

Paso 5: Inicializamos la función mágica

Por último solo nos queda regresar a nuestro main.js para indicar cuando será necesario iniciar runGesture();. El código final tiene que quedar de la siguiente manera:

  
     $(document).ready(function($) {
          function runGesture() {
               var url = false;
               var gestureContainer = $('body.gesture');
               var mc = new Hammer(gestureContainer);

               // esta función detecta el swipe a la izquierda
               mc.on('swipeleft', function(ev) {
                  url = $('.nav-next a').attr('href');
                  if ( url ) {
                     window.location = url;
                  }
               });

               // esta función detecta el swipe a la derecha
               mc.on('swiperight', function(ev) {
                  url = $('.nav-previous a').attr('href');
                  if ( url ) {
                     window.location = url;
                  }
               });
          }

         // solo corremos runGesture(); si gesture tiene la clase iphone, por ejemplo
         if ( $('.gesture').hasClass( 'iphone' ) ) {
            runGesture();
         }
     }
  

Ese último fragmento de código detectará si se está usando un dispositivo móvil y si es así corra la función runGesture(); en móviles solamente. Ya no afectará al desktop. 🙂

¡Y eso es todo! La funcionalidad ya está implementada en mi blog. 😉 Si sienten curiosidad y quieren saber como funciona, visiten esta misma página desde un celular y muevan sus dedos para cambiar de post.

Muchas gracias a quienes se tomen la molestia de leer este tutorial y si tienen preguntas pueden hacérmelas en los comentarios, trataré de ayudar en lo que se pueda.

Peace.

  1. No tengo mucho tráfico en mi blog todavía, pero según los reportes en mi Google Analytics, el 30.36% del tráfico que recibo en mi sitio es con dispositivos móviles y cada vez más sigue en aumento.
  2. Las funciones previous_post y next_post que yo utilicé para imprimir mis links son nativas de WordPress, en su caso será diferente dependiendo del CMS que utilicen.
  3. Justo como viene indicado en la documentación muchachos.