Empezar a utilizar Grunt

Como programador front-end hay ciertas tareas que pueden repetirse a diario como:

  • Modularizar el CSS pero posteriormente concatenarlos en unos pocos archivos css en su versión de producción. Lo mismo para el JavaScript.
  • Comprimir el CSS y el JavaScript para conseguir un tamaño menor de los ficheros cuando se ponen en producción.
  • Realizar una optimización de todas las imágenes utilizadas.
  • Compilar el código de Less, Sass, SCSS, etc a código real CSS.

logo de gruntjs

La lista anterior, que desde luego no es una lista completa de las tareas de un front-end, pero son cosas que tenemos que hacer, podemos decir que es una lista de tareas.

Pues bien, Grunt, del que seguro que ya has oído hablar,  resulta que es un gestor de tareas. Grunt puede realizar tareas automáticas, como las indicadas anteriormente,  que apenas requieran de nuestro maravilloso talento. Simplemente tendremos que abrir la línea de comandos, ir hasta el directorio raíz de nuestro proyecto, escribir grunt y darle al return. Así de sencillo. Obviamente es necesario configurarlo antes, y ahí es donde nos podemos quedar atascados ya que en contra de la forma en que lo venden, no es algo tan trivial.

Y como creo que Grunt es más conocido de lo que luego en realidad se usa, he decidido escribir este post en donde todos podamos ver cómo configurarlo para un proyecto web.

Lo primero que debemos saber es que Grunt se ejecuta sobre Node, por lo que deberemos tener Node instalado. La instalación de Node a día de hoy es trivial (siguiente, siguiente, siguiente y  finalizar).

Instalar Grunt

Primero abrimos una ventana de comandos con permisos de administrador y vamos hasta el directorio raíz de nuestro proyecto. Escribimos el siguiente comando:

npm install -g grunt-cli

Con esto instalamos la interfaz de línea de comandos de Grunt de forma global.

grunt-packagejson

 

Después necesitaremos un fichero en la raíz de tu proyecto llamado package.json. Este fichero define cómo Node y NPM trata las dependencias. Una vez tenemos el package.json en su sitio e indicando que grunt es una dependencia, podemos teclear el siguiente comando:

npm install

Y veremos que se crea una nueva carpeta llamada node_modules, que es donde se nos han descargado todas las dependencias necesarias.

grunt-node_modules

Concatenar ficheros con Grunt

Ya tenemos Grunt instalado y vemos que en nuestro proyecto tenemos tres ficheros de javascript responsables de realizar 3 peticiones al servidor que podríamos reducirlos a un sólo fichero y por lo tanto a una sola llamada al servidor.

  • plugins.js
  • main.js
  • carrusel.js

En producción, concatenaremos estos tres ficheros en uno, produccion.js. Tenemos que indicarle a Grunt que lo haga. El plugin oficial de Grunt para concatener ficheros se llama grunt-contrib-concat. En su página podemos leer que para incluirlo como dependencia es necesario ejecutar el siguiente comando:

npm install grunt-contrib-concat --save-dev

Si ahora volvemos a nuestro package.json veremos que se ha añadido la línea:

“grunt-contrib-concat”: “^0.5.1”

Para usar este plugin necesitamos empezar a configurar Grunt para que realmente lo utilice tal y como nosotros queremos. Para ello vamos a crear al mismo nivel que package.json un fichero llamado Gruntfile.js (ojo con la G mayúscula)

module.exports = function ( grunt ) {
  // La configuración de Grunt va aquí
  
  grunt.initConfig({
    pkg: grunt.file.readJSON( 'package.json' ), //lectura del package.json
    
    concat: {
      //La configuración para concatenar los fichero va aquí
    }

  });

  // Le decimos a Grunt que queremos usar grunt-contrib-concat
  grunt.loadNpmTasks( 'grunt-contrib-concat' );

  // Donde le decimos a Grunt qué hacer cuando teclearmos "grunt" en la consola.
  grunt.registerTask('default', [ 'concat' ] );

};

Hay que seguir la sintaxis anterior en donde se puede ver por los comentarios, de qué va el asunto.

concat: {
      dist: {
        src : [ 'js/plugins.js', 'js/carrusel.js', 'js/main.js' ],
        dest: 'build/js/produccion.js'
      }
}

Aquí, en el fichero Gruntfile.js hemos incluido dentro de la tarea concat, la sintaxis necesaria para concatenar los tres ficheros js en uno solo llamado produccion.js que está en la subcarpeta js de la carpeta build. src es de source y dest de destination.

Para ejecutarlo tecleamos

grunt

Y si todo ha ido bien, ¡Mágia!. Grunt pasa a ejecutar nuestra tarea default que lanzará a su vez la tarea ‘concat‘. Vemos que aunque no existía la carpeta build, Grunt la ha generado.

grunt-concat

Dejaré para futuros post cómo hacer que Grunt haga otras tareas muy comunes por nosotros como minificar javascript, optimizar imágenes.

 

 

Empezar a utilizar Grunt

Palabras clave y palabras reservadas en JavaScript

Este post es simplemente para consulta. A veces se comete el despite de dar el nombre a una variable con una palabra reservada, como por ejemplo “default”, de ahi que muchas veces la veamos como “defaults”. Y aqui dejo esta entrada para consulta.

Palabras clave

  • break
  • case
  • catch
  • continue
  • default
  • delete
  • do
  • else
  • finally
  • for
  • function
  • if
  • in
  • instanceof
  • new
  • return
  • switch
  • this
  • throw
  • try
  • typeof
  • var
  • void
  • while
  • with

palabras reservadas

  • abstract
  • boolean
  • byte
  • char
  • class
  • const
  • debugger
  • double
  • enum
  • export
  • extends
  • final
  • float
  • goto
  • implements
  • import
  • int
  • interface
  • long
  • native
  • package
  • private
  • protected
  • public
  • short
  • static
  • super
  • synchronized
  • throws
  • transient
  • volatile

 

Palabras clave y palabras reservadas en JavaScript

La igualdad de JavaScript

la_igualdad_de_javascript

Cualquiera que haya visto un poco de programación le sonará enseguida el siguiente operador

==

Sí, el operador de igualdad.

En JavaScript además de tener este operador de igualdad tenemos otro más de igual, que es

===

Viéndolo con ejemplos:

var a = "1";
a == 1;  //true

Es decir, que el String “1” es igual que es Number 1.

En cambio

var b= "1";
b === 1; //false
var c = 2;
c === 2; //true

En principio deberemos usar el operador de los tres iguales ( === ) ya que además de comparar el valor, compara el tipo de objeto. También es más eficiente ya que no tiene que andar internamente realizando cálculos convirtiendo valores de un tipo a otro a ver si coinciden.

Cierto es que, a veces, nos puede venir bien el tipo de comparación que nos ofrece el comparador de los dos iguales ( == )

La igualdad de JavaScript

Ya, pero… ¿qué es el this en javascript? episodio 2

what the fuck is this?

Vimos en el episodio 1 que invocando a this en javascript en el contexto global nos devuelve el objeto window.

Ahora nos vamos a servir de la función

function imprimirThis(){
  console.log(this);
}

y la vamos a incluir en un objeto nuestro:

¿Qué es el this en javascript?
(descarga el código)

function imprimirThis () {
    console.log(this)
}
//creamos un objeto javascript
var objeto = {
    propiedadUno : “Valor propiedad uno”,
    propiedadDos : “Valor propiedad dos”,
    mostrarPropiedades : function (){
        console.log(“Propiedad uno = ” + this.propiedadUno + ” :::: Propiedad dos = ” + this.propiedadDos)
     },
    //asignamos la misma función que está en el contexto global
    imprimirThis: imprimirThis
}
objeto.mostrarPropiedades();
objeto.imprimirThis();
Resultado
Propiedad uno = Valor propiedad uno :::: Propiedad dos = Valor propiedad dos
Object {propiedadUno“Valor propiedad uno”propiedadDos“Valor propiedad dos”mostrarPropiedadesfunctionimprimirThisfunction}
  1. imprimirThisfunction imprimirThis() {
  2. mostrarPropiedadesfunction (){
  3. propiedadDos“Valor propiedad dos”
  4. propiedadUno“Valor propiedad uno”
  5. __proto__Object

Vemos que desde dentro de objeto this es el mismo objeto. Lo demuestran las sentencias:

this.propiedadUno
this.propiedadDos

Esta vez la función que imprime el this no imprime el objeto window, si no nuestro objeto.

Por lo tanto, el this dentro de un objeto es el mismo objeto.

Seguiremos complicándolo en el episodio 3…

Ya, pero… ¿qué es el this en javascript? episodio 2

Ya, pero… ¿qué es el this en javascript? episodio 1

what the fuck is this?

La mala noticia es que el this en javascript es dinámico y va cambiando según el contexto en el que hagamos referencia a él.

En este episodio 1 voy a por lo fácil. Para verlo hay que seguir los siguientes pasos:

  1. Abrir un navegador (Chrome por ejemplo). La página a la que vayas da igual.
  2. Pulsar F12 para abrir las “herramientas del desarrollador”
  3. Ir a la pestaña Consola desde donde podremos ejecutar comandos javascript

Una vez allí escribimos

this

La salida de consola es…..

salida de consola: this devuelve window

 

Eso es, el objeto window, el objeto más global de javascript (cuando se ejecuta en un navegador).

Tiene su lógica ya que en el momento de invocarlo nuestro contexto es el global.

Ahora voy a crear una función que cuelga directamente del contexto global que nos va a imprimir el objeto this.

function imprimirThis(){
console.log(this);
}

Al llamar a esta función con

imprimirThis();

tendremos

Salida de consola. this

Como la función se ejecuta en un contexto global, de nuevo nos devuelve el objeto window. Podrías pensar que  this iba a ser la función, pero no.

Video en youtube.

Hasta ahora muy fácil ¿no? Desgraciadamente, en los siguientes episodios se irá complicando…  😦

Ya, pero… ¿qué es el this en javascript? episodio 1

Los pilares de la funcion en JavaScript

En la JavaScript la función es el ciudadano de primera clase.

Su formato es:

function transformar (x) { return x*2 }

Pero además… una función puede ser asignada a una variable:

var func = transformar;

Se utilizaria como func(x)

 

Y una función puede tener propiedades o ser una propiedad:

func.inverso = function (x) { return x / 2 }

Se utilizaría como func.inverso(x)

 

Y una función puede ser usada como parámetro.

[1, 2, 3].map( func.inverso );

Nota: map no es muy conocido. Lo que hace es aplicar la misma función a cada elemento del array y devuelve otro array. El resultado para lo anterior es [0.5, 1, 1.5]

 

Y una función puede ser devuelta en un return

function damePi () {
  return 3.1416;
}

function damePiNegativo () {
  return -3.1416;
}

function configurar(opciones){
//si opciones viene informado con una propiedad flag
  if (opciones.flag) { return damePi } else { return damePiNegativo }
}

var opc = "hola";

configurar(opc);

//Devuelve la función de damePiNegativo (opc no tiene propiedad flag),
//y digo que devuelve la función en sí, no el resultado de la función.

 

Los pilares de la funcion en JavaScript

Filtra las propiedades de un objeto con hasOwnProperty

A la hora de saber qué propiedades tiene un objeto y que esas propiedades sean solo las que nosotros le hemos dado podemos filtrarlo utilizando hasOwnProperty.

//crea un objeto
var obj = {};

//crea una propiedad y establece un valor para ella
obj.propiedad = "valor de propiedad";

//Si hicieramos un recorrido por sus propiedades nos encontrariamos
//con las propiedades creadas y las heredadas del objeto global Object.
//Para filtrarlas podemos utilizar hasOwnProperty()
for (var prop in obj) {
   if( obj.hasOwnProperty(prop) ) {
      console.log( obj[prop] );
   }
}

El resultado para el código anterior es:

“valor de propiedad”

Comentar que para acceder a las propiedades de un objeto de JavaScript lo podemos hacer de alguna de las dos siguientes formas:

  • objeto.propiedad
  • objeto[‘propiedad’]

La segunda propiedad deja una puerta abierta al acceso dinámico muy interesante. Así que conviene tener esta forma (menos común) siempre presente.

Filtra las propiedades de un objeto con hasOwnProperty

Evitando lo global en JavaScript

Las variables globales y funciones en el ambito global no son una muy buena idea. La razón es que cada script se ejecuta en el mismo ambito y si hay varios programadores no es difícil coincidir en variables o funciones con el mismo nombre y que quedaran sobrescritas.

Existen varias soluciones. Voy a ir una a una comentandolas.  Digamos que tienes tres funciones y una variable tal que asi:

var actual = null;
function iniciar(){...}
function cambiar(){...}
function verificar(){...}

Se pueden proteger utilizando un objeto javascript:

var nombreUnico = {
  actual: null,
  iniciar: function(){...},
  cambiar: function(){...},
  verificar: function(){...}
}

 Para llamar a las funciones o cambiar el valor de la variable tendremos que hacerlo con el prefijo nombreUnico., así para ejecutar la función iniciar seria nombreUnico.iniciar().

El siguiente paso es envolver todo en una función anónima. A esto se le conoce como el module pattern.

var nombreUnico = function(){
  var actual = null;
  function iniciar(){...}
  function cambiar(){...}
  function verificar(){...}
}();

Pero de esta manera hay un problema. Nada es accesible desde fuera. Si quieres hacerlo público necesitas envolver lo que quieras hacer publico en una sentencia de return.

var nombre = function(){
  var actual = null;
  function verificar(){...}
  return { 
    iniciar: function(){...}
    cambiar: function(){...}
  }
}();

De esta manera desde fuera solo tenemos accesibles las funciones de iniciar() y cambiar().

Así que el siguiente paso es:

nombre = function(){
  var actual = null;
  function iniciar(){...}
  function cambiar(){...}
  function verificar(){...}
  return {
    iniciar: iniciar,
    cambiar: cambiar
  }
}();

En vez de devolver directamente las funciones, lo que se devuelve son punteros a esas funciones. El nombre de la función no hace falta que coincida con el del puntero.

Si no necesitas que ninguna variable o función sea accesible desde fuera, puedes envolver toda la construcción en otro set de parentesis para ejecutarla sin necesidad de ningún nombre.

(function(){
  var actual = null;
  function iniciar(){...}
  function cambiar(){...}
  function verificar(){...}
})();

Esto mantiene todo en una especie de paquete que es inaccesible desde el fuera.

Evitando lo global en JavaScript

Consigue un bucle while más rápido en JavaScript

Una forma de iterar más rápido es utilizar un while en vez de un for de la siguiente manera:

var valores = [1,2,3,4,5];
var length = valores.length;
while (length--){
   console.log(valores[length]);
}

// 5 4 3 2 1

Cuando length sea 0 se evalua como false.

Bucle while Eficiente

Podemos usarlo cuando  iterar en orden inverso no sea un contratiempo.

 

Consigue un bucle while más rápido en JavaScript

jQuery: on, live, bind, click, …

En jQuery a la hora de asociar eventos a elementos del DOM surge la duda de cual utilizar. Por ejemplo si al boton

<button class="botonActivo">haz click</button>

queremos asociarle el evento click podriamos hacerlo de las siguientes maneras:

$('.botonActivo').click(function(){
  console.log( $(this).text() );
});

o bien

$('.botonActivo').on('click', function(){
  console.log( $(this).text() );
});

Va a dar exactamente igual cual uses. Ahora bien, jQuery desde su version 1.8 recomienda el uso de on() para asociar eventos  aunque sigue dando soporte para el “atajo” click.

Ahora vamos a clonar el boton e incluirlo en el DOM.

$('.botonActivo').on('click', function(){
  console.log( $(this).text() );
  $(this).clone().appendTo('body');
});

Si pulsamos sobre ese nuevo boton que ha aparecido no ocurrirá nada. No tiene ninguna acción asociada. En este caso, el de clonar, si queremos hacerlo para que contenga sus acciones asociadas a eventos tendremos que hacerlo pasándole true como parametro a clone().

$('.botonActivo').on('click', function(){
console.log( $(this).text() );
$(this).clone(true).appendTo('body');
});

El nuevo boton ahora clonaria otro mas.

 

Otra forma de hacer que los elementos que se incorporan al DOM una vez cargada la pagina tengan event handlers seria utilizando el metodo live().

$('.botonActivo').live('click', function(){
  console.log( $(this).text() );
  $(this).clone().appendTo('body');
});

Ahora no seria necesario incluir el parametro true a clone(). Ten en cuenta que el uso de live(), si no lo tenemos bien controlado, puede ser contraproducente.

Lo siguiente es ver el caso para deletegate(). Supongamos que tenemos el siguiente codigo HTML:

<div class="container">
  <button>boton</button>
  <button>boton</button>
</ul>

y el siguiente javascript:

$('.container').delegate('button','click',function(){
  $(this).clone().appentTo('body');
});

El nuevo boton no tendra asociado ningún event handler. Es así porque el appendTo() se realiza al body, si se realiza dentro del contexto del .container, si quedaría asociado a su tratamiento de eventos. Es decir, así:

$('.container').delegate('button','click',function(){
  $(this).clone().appentTo('.container');
});

Conviene saber que delegate en realidad utiliza live(), aunque dentro de un contexto determinado.

Si utilizamos bind(), que va cayendo en desuso, actualmente jQuery llama a on().

Ahora es cosa tuya decidir cual te conviene usar. Eso si, no conviene utilizar de forma indiscriminada live() para todo ya que consume  mas recursos que on(). Habría que estudiar bien la casuística.

Recuerda que a veces no hay que volverse loco y que seguimos pudiendo usar el tradicional onclick que llama a una function definida en javascript.

jQuery: on, live, bind, click, …