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>
Anuncios

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).