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

Eliminar un elemento de un array dando su valor en Javascript

Vamos con una función de Javascript, en la cual le pasaremos un array y una cadena con el valor que queremos eliminar. De esta forma podremos eliminar dicho valor sin saber el índice en el que está almacenado en el array.

//le pasamos a la función el array
//y el valor
function borraItemValor(array, valor){
    for(var i in array){
        if(array[i]==valor){
            array.splice(i,1);
            break;
        }
    }
}

Puedes probarla con algo como esto:

var unarray = ["uno", "dos", "tres", "cuatro"];
borraItemValor(unarray, "dos");

Calcular el IMC con Javascript

Esta semana en el trabajo me encontraba con una petición de un cliente. En un formulario donde insertaba peso y talla de una persona quería que hubiera un campo con el índice de masa corporal, que debía rellenarse solo. ¿Esto cómo va? Pues lo arreglamos con una función de javascript:

function calculaIMC(){
  //declaramos las variables
  var peso, altura, imc;
  //recogemos los datos.
  //Suponemos que los campos
  //tienen esos Id.
  //El peso en KG y la altura en cm
  //para operar mejor
  peso=document.getElementById("peso").value;
  altura=document.getElementById("altura").value;
  //comprobamos que los campos
  //no vengan vacíos
  if(peso!="" && altura!=""){
    //aplicamos la fórmula
    altura = parseInt(altura)/100;
    imc=peso/(altura*altura);
    document.getElementById("imc").value=imc.toFixed(2);
  }
}

Recuerda que queremos que los datos se introduzcan como tipos enteros: puedes poner una validación por javascript para que no metan comas, usar un campo numeric de HTML5 (hoy por hoy ya todos los navegadores modernos lo soportan) o hasta tirar de una vieja librería de jQuery (que servía para asegurarnos el funcionamiento en navegadores viejos, aunque hoy por hoy ya no tenga mucho sentido).

Javascript: convertir Array en CSV

Vamos con un tip rápido de javascript ¿cómo convertimos un array en una cadena de valores separados por comas? Es bastante sencillo lograrlo, y así obtener un formato válido para crear un fichero CSV más adelante:

var sabbath = ['ozzy', 'iommi', 'bill', 'geezer'];

var sabbathCsv = sabbath.valueOf();

Si lo que queremos son comas como separador el método valueOf() ya nos hace el trabajo, pero ¿si queremos otro separador? Entonces recurriremos a join().

var icada = ['drogas', 'boni', 'alf', 'fer'];

var icadaCsv = icada.join("#");

En el ejemplo de arriba usará el caracter # como separador en lugar de las comas.

Javascript: convertir una string en un número.

La función parseFloat() de Javascript nos permite recoger un dato de tipo string y convertirlo en un número con decimales, mientras que la función parseInt() nos devuelve un entero. ¿Así de simple? Sí, pero con matices. Vamos a profundizar un poco:

En el caso de parseInt() se trata de una función que recibe dos valores: el primero es obligatorio y es la cadena que queremos convertir a entero, el segundo sería un entero entre 2 y 36 para definir la base en que queremos que esté representado el entero devuelto, y es un parámetro opcional que por defecto tomará el valor 10 (base decimal). En implementaciones en navegadores antiguos (por ejemplo IE8) si el número empieza por 0 lo devolverá en base octal, así que ojo. Con los navegadores modernos ya no pasa, pero es importante recordarlo. Si le pasamos una cadena con espacios los obviará y devolverá el número (si hay varios números devolverá el primero que se encuentre). Si le pasamos una cadena con letras y números dependerá de la posición del número: si este está al inicio entonces devolverá el número hasta que encuentre un caracter extraño. Si empieza por letras devolverá un valor NaN. Ejemplos:

parseInt("10"); //devuelve 10
parseInt("10 años"); //devuelve 10
parseInt("10 54"); //devuelve 10
parseInt("10.50"); //devuelve 10
parseInt("casi 10"); //devuelve NaN
parseInt("10",16); //devuelve 16

Si quieres evitar problemas y que te devuelva un 0 cuando el resultado sea NaN ya te lo contamos en su día por aquí.

En el caso de parseFloat() la función sólo recibe la cadena que debe convertir a número decimal. Al igual que parseInt() si recibe una cadena con espacios los ignorará para devolver el número, y si recibe una cadena con caracteres actuará también igual que esa función: si este está al inicio entonces devolverá el número hasta que encuentre un caracter extraño. Si empieza por letras devolverá un valor NaN. En este caso ojo al formato numérico, sólo acepta el anglosajón. Es decir, el separador decimal tiene que ser un punto, interpretará la una coma como un caracter extraño.

parseFloat("10"); //devuelve 10
parseFloat("10.5 años"); //devuelve 10.5
parseFloat("10 54"); //devuelve 10
parseFloat("10.50"); //devuelve 10.50
parseFloat("casi 10.4"); //devuelve NaN
parseFloat("1.000,33"); //devuelve 1
parseFloat("10,50"); //devuelve 10

Entonces ¿qué hago si tengo una cadena donde los decimales vienen separados por comas y los miles marcados con puntos? Pues usando la función replace(). Vamos con un ejemplo:

var strEx = "1.000,33";
//primer paso: fuera puntos
strEx = strEx.replace(".","");
//cambiamos la coma por un punto
strEx = strEx.replace(",",".");
//listo
var numFinal = parseFloat(strEx);

Podría ser útil tener una función creada ya para realizar esta operación de conversión.

Y hasta aquí con esta entrada de Javascript básico.

Las funciones setInterval() y setTimeout() en javascript.

Feliz 2017 a todos, esta es la primera entrada del año. Una cuestión sencilla de javascript ¿para qué valen las funciones setInterval() y setTimeout() y en qué se diferencian?

Pues ambas funciones tienen el mismo objetivo: ejecutar otra función pasado un intervalo de tiempo. ¿En qué se diferencian? En que setTimeout() se ejecutará solamente una vez, mientras que setInterval() lo hará en repetidas ocasiones.

Por ejemplo, podríamos usar setInterval() para que se mostrara en pantalla cuántos segundos llevamos desde que se cargó la página:

/*definimos una función que cada ponga en un
cuadro de texto un valor numérico, sumando uno cada
vez que la invocamos*/
function showSeconds(){
 var val = document.getElementById("tiempo").value;
 document.getElementById("tiempo").value = parseInt(val)+1;
}
/*usamos setTimeout() para que se
ejecute cada segundo (1000 milisegundos como parámetro)*/
setInterval(showSeconds,1000);

O podríamos usar setTimeout() para dar un aviso al usuario a los diez segundos de entrar

/*función que sólo hace un alert*/
function funcAvisa(){
 window.alert("Pareces interesado en esta sección");
}
/*se la llama a los 10 segundos*/
setTimeout(funcAvisa,10000);

Así funcionan los dos temporizadores de Javascript.

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);
}