Crear una tabla HTML con cabecera fija, usando CSS3

Si bien los elementos table suenan a cosa del pasado, a aquellos tiempos en los que todo se hacía con tablas y de vez en cuando algo de flash o similar, todavía siguen utilizándose tablas en el mundo de la programación y diseño web, ya no como elemento central y básico de la maquetación, pero sí para por ejemplo presentar datos en ese formato de filas/columnas.

Si tenemos una tabla muy larga la solución tradicional ha sido siempre la paginación, que con el tiempo fue sustituída por elementos que van insertando nuevas filas de forma asíncrona mientras hacemos scroll. En estos casos puede pasar que hayamos bajado mucho, la cabecera ya no esté visible y no tengamos muy claro a qué corresponde cada columna. Una solución podría ser repetir la cabecera cada x filas, pero se puede hacer visualmente incómodo. Otra posibilidad es hacer fijas estas cabeceras de forma que siempre estén visibles en pantalla y bajen mientras hacemos scroll.

Parece que lo lo lógico sería que pudiésemos hacer fijos los elementos thead o tr, ya que queremos que toda la línea quede fijada, pero aunque nos parezca lo elemental no será posible. Para fijar un elemento de esta forma tenemos que ponerle position:relative y esta característica no se aplica a esos elementos, esto implica que tendremos que usarlo obligatoriamente sobre las celdas, sobre los elementos th o td.

Supongamos que tenemos una tabla como esta (bueno, con cientos de registros para que tenga sentido la cabecera fija):

<table>
  <thead>
    <tr>
       <th>Nombre</th>
       <th>Edad</th>
       <th>Salario</th>
       <th>Rango</th>
       <th>Area</th>
     </tr>
    </thead>
   <tbody>
    <tr>
       <td>Manuela Z.</td>
       <td>43</td>
       <td>24000</td>
       <td>Analista</td>
       <td>Big Data</td>
     </tr>
  </tbody>
</table>

Si queremos fijar la cabecera el CSS, lo más básico posible, sería tal que así:

table {
  position: relative;
  border-collapse: collapse; 
}
th, td {
  padding: 6%;
}

th {  
  position: sticky;
  top: 0; 
}

Hay tres puntos clave en ese CSS: el position:relative de la tabla, el position:sticky del elemento th y la posición top:0 también del elemento th. De esta forma le decimos que todas las celdas de la cabecera se queden fijas en la parte superior de la tabla, así al bajar el scroll estas bajarán con él.

Acceder a los atributos data de HTML5 desde javascript

Si eres lector habitual de este blog recordarás que no hace mucho vimos cómo hacer esto con jQuery. Vamos ahora a ver cómo hacerlo con javascript a pelo, sin tirar de esas librerías. Repitamos los mismos ejemplos pero sólo con javascript:

<div id='fruta' data-fruta='fresa'></div>

En el div con Idfruta” vamos a guardar un dato: que es una fresa (mismo ejemplo que en artículo anterior). ¿Cómo accedo a este valor usando javascript?

//opción A. A lo bruto
//funciona, pero no es elegante
window.alert(document.getElementById("fruta").getAttribute('data-fruta'));
//opción B. La buena
window.alert(document.getElementById("fruta").dataset.fruta);

Ahí tienes dos ejemplos en los que hacemos un alert() de los datos guardados en el atributo data. El primero, usando getAttribute(), en teoría es la opción «bruta» ya que en principio debería accederse a estos datos como en el segundo ejemplo, que se supone que sería el método correcto. El problema es que el acceso a dataset no está bien implementado en todos los navegadores, así que la opción de usar getAttribute() hoy por hoy, aunque no sea la correcta en la teoría, es la funcional.

¿Y cómo queda el tema de los guiones que habíamos visto en el ejemplo en jQuery? Bueno. Si usamos getAttribute() ponemos el nombre del atributo tal cual, si usamos dataset hacemos como en jQuery y quitamos los guiones (y el prefijo data) usando también notación camelCase:

<div id='fruta' data-fruta-oferta='pera'></div>
<script type="javascript">
//con getAttribtue
window.alert(document.getElementById("fruta").getAttribute("data-fruta-oferta"));
//mediante dataset
window.alert(document.getElementById("fruta").dataset.frutaOferta);
</script>

Usando rel=»noopener» para evitar ataques crossdomain en páginas abiertas con target=»_blank»

Pues era un tema que desconocía hasta que lo vi ayer en el blog de Chema Alonso, pero por lo que veo lleva rulando al menos desde el mes de mayo. ¿De qué estoy hablando? Te comento con un ejemplo (aunque puedes leerlo mejor explicado en los links previos): supongamos que quieres que un link se abra en una nueva pestaña, así que le pones target=»_blank». Al hacerlo de esta forma la página que has abierto en la nueva pestaña, mediante el selector window.opener puede modificar cosas a base de Javascript en la página desde la que se abrió el enlace. La mayoría de navegadores modernos limitan las posibilidades de esto y bloquean muchas de las acciones invocadas desde la ventaja hija sobre la padre, pero lo que se han dejado sin proteger es que dicha ventana hija puede acceder a la propiedad window.opener.location, y de esta forma mandarnos a una página desde la que hacer un ataque de phising.

¿Solución? Bueno, si es un enlace basta con el modificador noopener y el noreferrer:

<a href="paginanueva.html" target="_blank" rel="noopener noreferrer"/>

El noreferrer es necesario porque Mozilla Firefox no soporta noopener.

¿Y qué pasa si abrimos la ventana mediante Javascript utilizando el método window.open()? Pues que nos encontramos la misma vulnerabilidad. ¿Cómo la solucionamos? Tal que así (copio este ejemplo):

var newWnd = window.open();
newWnd.opener = null;

Redirección WWW con .htaccess

Bueno, no es la primera vez que hablamos por aquí del fichero .htaccess. Hoy vamos a ver cómo utilizarlo para redireccionar nuestro dominio a www siempre, o viceversa. Esto nos permitirá mejorar nuestro SEO y nuestro PageRank.

La cuestión ahora es editar nuestro .htaccess con un editor de texto. Si lo que quieres es redireccionar del dominio sin www al que sí la tiene sería el siguiente código:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^aquitudominio.loquesea [NC]
RewriteRule ^(.*)$ http://www.aquitudominio.loquesea/$1 [L,R=301]

Y para lo contrario, para que siempre entre sin las www, entonces sería:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.aquitudominio.loquesea [NC]
RewriteRule ^(.*)$ http://aquitudominio.loquesea/$1 [L,R=301]

Cambiando aquitodominio.loquesea por lo que corresponda para vuestra web.

HTML5: Lograr que un campo number acepte decimales

Una de las características de HTML5 era que permitía definir campos de tipos variados que ampliaban las opciones respecto al tradicional tipo text del HTML clásico.  Estos campos, además tienen la capacidad de autovalidarse.

Estos nuevos campos, por otra parte, requieren conocer todas sus opciones para exprimirlos a tope. Por ejemplo, si declaras un campo como el siguiente:

<input type="number" name="numero" />

En este caso te encontrarás con que si pones un número decimal la validación del navegador te dirá que está incorrecto. Pero tú sabes que no lo está ¿por qué pasa esto? Bueno, puedes arreglarlo de una forma muy simple: con el atributo step.

La mayoría de los navegadores mostrarán dos flechas en los campos de tipo number, para aumentar y decrecentar su valor. En step podemos definir cuánto queremos que este valor suba o baje en cada click. Por ejemplo:

<input type="number" step="5" name="numero" />

De esa form el valor irá cambiando de 5 en 5.

Pero esto de momento no nos soluciona el problema ¿cómo logramos que trague un decimal? Pues definiendo en step que el valor sea decimal.Si ponemos el valor de step como «0.01» nos permitirá meter decimales con dos cifras. Entonces si ponemos nuestro campo:

<input type="number" step="0.01" name="numero" />

Así tenemos un campo que admite dos cifras decimales, que suele ser lo más habitual. Si queremos más precisión entonces metemos más decimales en el step. Otra opción es añadir directamente el valor any a step. De esta forma permitirá meter tantos decimales como queramos.

<input type="number" step="any" name="numero" />

Hacer un triángulo con CSS3

¿Cómo puedo insertar la imagen de un triángulo en mi web sin usar imágenes? ¿Es posible hacerlo sólo con CSS3? En el pasado vimos como hacer un exágono o un octógono, y el triángulo es todavía más fácil:

Vamos a crear cuatro divs, cada uno de ellos para un triángulo en una dirección. Este sería el marcado HTML:

<div id="triangulo"></div>
<br/>
<div id="trianguloinvertido"></div>
<br/>
<div id="trianguloizquierda"></div>
<br />
<div id="trianguloderecha"></div>

Y ahora veamos el CSS:

#trianguloizquierda{
	  width: 0;
	  height: 0;
	  border-top: 50px solid transparent;
	  border-bottom: 50px solid transparent;
	  border-right:50px solid black;
	}

#trianguloderecha {
	  width: 0;
	  height: 0;
	  border-top: 50px solid transparent;
	  border-bottom: 50px solid transparent;
	  border-left: 50px solid black;
	}

#triangulo {
	  width: 0;
	  height: 0;
	  border-left: 50px solid transparent;
	  border-right: 50px solid transparent;
	  border-bottom: 50px solid black;
	}

#trianguloinvertido {
	  width: 0;
	  height: 0;
	  border-left: 50px solid transparent;
	  border-right: 50px solid transparent;
	  border-top: 50px solid black;
	}

En este jsfiddle le puedes echar un ojo al resultado.

Con este simple truco de CSS podrás crear botones en forma de flecha o triángulo que darán una mejor imagen a tu proyecto,pudiendo jugar con los tamaños y los colores para adaptarlos mejor a tu maquetación.

ECMAScript 6: Funciones flecha gruesa

Seguimos la serie de artículos dedicados a ECMAScript 6, en este caso con las funciones arrow, funciones flecha o funciones de flecha gruesa. Esta novedad consiste en una sintaxis abreviada para la expresión de función. Además vinculan el valor this contextualmente.

La cuestión de la sintaxist abreviada es simple si vemos un ejemplo:

var a = [
  "Peras",
  "Manzanas",
  "Naranjas",
  "Melones"
];

//Sintaxis de toda la vida
var a2 = a.map(function(t){ return t.length });

//Sintaxis con flecha
var a2 = a.map( s => s.length );

El tema del this contextual es algo más complejo. Seguramente recuerdes que la variable this daba a veces muchos dolores de cabeza ya que pertenecía sólo a un contexto, es decir, cada función definía su propio valor de this. Vamos con un ejemplo de como sería el código old-school:

function Miembro() {
   // Este this es una instancia del constructor Miembro()
   this.experiencia = 0;
   setInterval(function aprender() {
      // Y este this de debajo sería
      //una instancia de la función aprender(),
      //por tanto no podemos usarlo fuera de
      //la función de callback
      //y nos podría generar errores
      this.experiencia++;
   }, 5000);
} 

Teníais la opción de cachear el this dentro de una variable:

function Miembro() {
   var that = this;
   that.experiencia = 0;
   setInterval(function aprender() {
      // Y este this de debajo sería
      //una instancia de la función aprender(),
      //por tanto no podemos usarlo fuera de
      //la función de callback
      that.experiencia++;
   }, 5000);
} 

Otra opción era usar la función bind() para vincular dicha función a this.

Pero con la función de flecha gruesa la cosa es mucho más simple:

function Miembro(){
  this.experiencia = 0;
  //y aquí va la magiar!!!!
  setInterval(() => {
    this.aexperiencia++; //no es un this nuevo, sino que
                       //hace referencia al this de Miembro()
  }, 5000);
}

Etiquetas para convertir webs en web-apps Android

No hace mucho os hablaba aquí de una serie de etiquetas creadas por Apple que permitían hacer que una web luciera como una aplicación nativa de iOS, y comentaba que era una pena que no hubiera algo así para Android… pero lo cierto es que lo hay. A partir de la salida de Chrome 31 para Android el sistema operativo de Google también da opción a hacer esto mismo, aunque he de admitir que no dan tanto juego como las de Apple, y como estos se han dedicado (como es su filosofía de empresa hermética/cabrona/malvada) a no documentar ni compartir una mierda hay que andar buscándose la vida. Por cierto que Mozilla también nos permite crear web-apps facilitas tanto para su sistema operativo FirefoxOS como para Amazon Kindle Fire y Android si usas Firefox.

De primeras no hay una etiqueta especial para el título del app, deberéis utilizar la meta etiqueta title normal. Tampoco existe un equivalente de la propiedad navigator.standalone de iOS, que nos devuelve un boolean si estamos ejecutando el app a pantalla completa. En todo caso, con este truquito podemos lograr lo mismo:

navigator.standalone = navigator.standalone || (screen.height-document.documentElement.clientHeight<40)

El Javascript ejecutadlo siempre después de que la página esté totalmente cargada (tras el evento onload()), por si los scrolls.

Vamos ahora con los puntos fundamentales. El primero: forzar el modo web-app, que se consigue con la siguiente etiqueta:

<meta name="mobile-web-app-capable" content="yes">

Vamos, lo mismo que la de iOS quitándole el prefijo «apple». El segundo punto clave ¿cómo añadir al escritorio el app? Bueno, la primera vez que llegáis a la página, en el menú del navegador os encontráis una opción que será “Add to homescreen” (lo he probado en emulador y tengo Chrome en inglés, no estoy seguro de cómo se llama la opción en castellano). En cuanto al icono, si habéis puesto el de Apple Touch lo cogerá por defecto, si bien la especificación de google recomienda incluir uno cuadrado de 196*196, tal que aśi:

<link rel="shortcut icon" sizes="196x196" href="vuestroIcono.png">

Un último punto, los enlaces se abrirán por defecto en el contexto de la aplicación, si queréis abrir un enlace concreto en una ventana de Chrome (por ejemplo una referencia a una web externa) insertad el atributo target=»_blank» en el link.Otro punto, no tenéis el botón de recargar del navegador (al estar en ese contexto sin marco), así que si queréis tener una opción de «refresh» tendréis que implementar una solución en javascript.

En fin, queda mucho por andar en este terreno, pero parece que Google se pone al fin las pilas, y Mozilla ya lleva mucho currando (y al contrario que Apple ellos sí hacen las cosas de forma abierta).

Clases para imágenes en Twitter Bootstrap

Hacía tiempo que no tocaba un post «por encargo», pero me han comentado por Twitter que hable de las clases que el framework Bootstrap nos ofrece para trabajar con imágenes. No son muchas, la verdad, y de hecho están recogidas en su documentación oficial. Pero en fin, allá vamos.

Básicamente, en cuanto a la forma de la imagen, Bootstrap nos ofrece tres clases para tres resultados distintos: rounded, circle y thumbnail. La primera hará que la imagen tenga bordes redondeados, la segunda que esta sea circular y la tercera le pondrá un marco alrededor. El ejemplillo en código sería:`

<!--Bordes redondeados-->
<img src="carpeta/archivo.extension" alt="Texto1" class="img-rounded">
<!--Circular-->
<img src="carpeta/otroarchivo.extension" alt="Texto3" class="img-circle">
<!--Thumbnail con marco-->
<img src="otracarpeta/archivo.extension" alt="Texto5" class="img-thumbnail">

También hay una clase para imágenes responsivas, que básicamente aplica un max-width del 100% y un height automático, lo que hace que su tamaño se adapte al de su elemento padre. En ese caso se usar la clase img-responsive:

<img src="carpeta/imagen.extension" class="img-responsive" alt="Imagen de tamaño adaptable">

Y ya está todo el pescao vendido, no hay más que rascar en este tema (aunque sí en Bootstrap, un estupendo framework para el desarrollo de front end)

Mobsyte: Generador de webs móviles en HTML5

Hace un par de días contactaron conmigo los creadores de la web Mobsyte invitándome a probar su nuevo producto por si me interesaba reseñarlo por aquí. Tras los excesos de fin de año y la recuperación en año nuevo me he decidido a probar un plan gratis de este generador de webs mobile first, todavía en fase beta, y plasmar mis impresiones.

Mobsyte

El mercado móvil cada vez es más importante dada la proliferación de estos dispositivos, cuyas ventas poco a poco van superando a los ordenadores, convirtiéndose en algo fundamental a la hora de plantear un proyecto de comunicación on-line. Lo que Mobsyte nos ofrece es una evolución del ya comentado en este blog eMobc Lander, un generador basado en el framework eMobc, con varios planes de precios, uno gratis (aunque un pelín limitado, todo hay que decirlo, ya que sólo permite 1000 visitas mensuales, además de no limitarte los mensajes, permitir dominio propio sino uno .mobsyte.com y de hacerte llevar el logotipo de Mobsyte) y dos de pago (9 euros al mes limitado a 5000 visitas, con la publicidad limitada, dominio propio y pero con branding de Mobsite, y otro de 19 euros mensuales sin límite de visitas y sin logo de Mobsyte).

Mobsyte Home Page

Mobsyte no te permitirá crear una aplicación web compleja, pero sí desarrollar una landing page o un microsite que te pueda servir como flyer on-line para una promoción. Desde un generador basado en plantillas podrás añadir secciones de texto, fotos, galerías de imágenes, enlaces, vídeos, fragmentos de HTML, mapas, calendario… las opciones son múltiples. El estar centrado en plantillas también limita más la personalización del sitio. En cuanto a temas de SEO o de conectividad con redes sociales Mobsyte te permitirá optimizarlo de forma sencilla, sólo cubriendo un par de formularios, y además incluye un módulo de estadísticas para conocer cuántos visitantes tienes, cuando te visitan y como.

La versión pro te da opciones como vender on-line, insertar encuestas o un formulario de búsqueda.

En resumen, fácil de usar y muy configurable, pero con limitaciones. Como ocurre siempre en estos casos, es el usuario quien debe pensar si le interesa o no, quien debe valorar si Mobsyte puede darle lo que necesita y si el precio de los programas de pago le sale rentable o si, por contra, cubrirá mejor sus necesidades contratando a una empresa que le haga una web personalizada.

Como ejemplo, en sólo 10 minutos y siguiendo pasoa paso los tutoriales hice una pequeña landing page que podéis ver en su versión para pc y aquí para móvil, que no es gran cosa, pero que demuestra lo rápido que se puede hacer una pequeña paginilla por medio de este servicio.