Before Splats. Spoiler: it is all about tagless components

There is a recurring question about components that appear in Slack: how can I pass different attributes to a component depending on a given object?

As an example, people want to be able to do something like the object spread operator in ECMAScript.

Object Spread Properties

The TC39 proposal Object Rest/Spread Properties for ECMAScript gives us programmers the ability to use the rest and spread operators with objects.

let defaults = { name: "No one", location: "Braavos" };
let arya = { ...defaults, name: "A girl" };
console.log(; // A girl
console.log(arya.location); // Braavos

let jaqen = { name: "A girl", ...defaults };
console.log(; // No one
console.log(jaqen.location); // Braavos

In these two cases, the spread operator works pretty much like Object.assign:

let arya = Object.assign({}, defaults, { name: "A girl" });
let jaqen = Object.assign({ name: "A girl” }, defaults);

Wouldn’t it be great if we could just {{component varComponentName …someObject}}?

Spread in Handlebars

There is a proposal for adding the splat operator to Handlebars. You can follow the discussion on the original issue opened by mixonic or the PoC implementation by machty. The last I heard is that this feature is on hold because of performance concerns.

But I need a solution!

Let’s try to fix this problem. For that, we will create an interface for a mili-blogging (more than microblogging but not as huge as blogging) network with several (read as “at least three”) post types. Let’s call this network stumblr.

You can blog text, images and quotes in stumblr. These three types are defined as follow in the JSON payload (the Ember Data models can be found in the twiddle linked later):

// Text
  id: "some-text",
  type: "text",
  attributes: {
    text: "Verde que te quiero verde. Verde viento. Verdes ramas."

// Quote type
  id: "some-quote",
  type: "quote",
  attributes: {
    quote: "There's one thing I always wanted to ask Jack. Back in the old days. I wanted to know about that Doctor of his. The man who appears out of nowhere and saves the world; except sometimes he doesn't. All those times in history where there was no sign of him … I wanted to know why not. But I don't need to ask anymore. I know the answer now: Sometimes the Doctor must look at this planet and turn away in shame. I'm recording this in case anyone ever finds it, so you can see. You can see how the world ended.",
    author: "Gwen Cooper"

// Image Type
  id: "some-image",
  type: "image",
  attributes: {
    src: "",
    caption: "Some caption"

(I know this is not valid JSON but each part is a valid JSO, close enough for me.)

We define three components, one for each type:

// Assuming the template is {{text}}
import Ember from 'ember';
export default Ember.Component.extend({
  tagName: 'article',
  classNames: ['stumblr-text']
// Assuming the template is
// <p class="quote-body”>{{quote}}</p>
// <p class="quote-author”>{{author}}</p>
import Ember from 'ember';
export default Ember.Component.extend({
  tagName: 'article',
  classNames: ['stumblr-quote']
// Assuming the template is
// <figure> 
//   <img src={{src}} />
//    {{#if caption}}<figcaption>{{caption}}</figcaption>{{/if}}
// </figure>
import Ember from 'ember';
export default Ember.Component.extend({
  tagName: 'article',
  classNames: ['stumblr-image']

We now have one component for each post type and we can render them statically just by invoking them, as usual. You can play with the result in this twiddle.

In this example we are very restrictive: we are assuming we will always receive an image, a quote and a text. What if our user used stumblr strictly as a photoblog?

Since we will need to choose the component based on a model we can used a property to choose between several options. As an example, we add the property componentName to the Image model:

export default DS.Model.extend({
  componentName: 'dynamic-stumblr-image'

We can now render the right component just using the {{component}} helper:

{{component postModel.componentName post=postModel}}

If you want to know more about the {{component}} helper, read my post about it: The Path to Contextual Components: Understanding dynamic components. Notice that we are not restricted to a property in the object to return the name for the component: we can use a helper too.

We will use dynamic-stumblr-image to set the right attributes in stumblr-image.

{{! template for dynamic-stumblr-image }}

Repeat this for the rest of components and change the previous template to:

{{#each model as |item|}}
  {{component item.componentName post=item}}

and you will get a pretty similar result. Examine this twiddle to see the rest of the changes (new dynamic-stumblr-foo components and new model hook in the route).

Still not there

Though it seems so, we are not producing the exact same output: our dynamic-stumblr-foo components produce an extra tag around the stumblr-foo version. Let’s get rid of that.

In a component, the property tagName let us select which tag Ember will use to surround our template. If we set tagName to ul we will make our component a list, article would make it an article, null will make Ember use div. But if we want Ember not to use any tag at all, what should we do then?

River Song always have a way out

Set tagName to ’’ (empty string). This is our way of asking Ember to get a tagless component. This has some limitations: an id is not guaranteed to get generated and you cannot expect it to call event methods like click, focus and such.

You can see the final result in this twiddle.

Final notes

There are more options here too. Creating a blueprint for component wrappers should not be too difficult. Or maybe your application does not need the duplicated components at all!

Hope you enjoyed it!

The Path to Contextual Components: Contextual Components

Contextual components are introduced in Ember.js 2.3 to improve component composition and the usage of components for DSL.

Contextual components bring three new features to Ember:

  1. The hash helper: this simple helper just returns a hash with the attributes passed to it.
  2. Closure components: similar to closure actions, a closure component encapsulates a component with a set of attributes for later reuse.
  3. Dot syntax: any identifier with a dot (.) whose context is a closure component will be rendered as the component itself.

Using the hash helper

The hash helper, though simple, is a fundamental element of this new feature as we will see in the third part. Invoking the hash helper with a collection of key-value pairs returns a hash with the given collection as content.

{{! app/templates/components/my-hash.hbs }}
{{yield (hash text="my-text-component"

This component will yield a hash with the passed key-value pairs. The following template:

{{#my-hash as |f|}}

would produce three lines with the names of the components: my-text-component, my-checkbox-component, and my-textarea.


Creating a closure component

The first part of using contextual component is the ability to create a closure around a component and a set of parameters and attributes. The {{component}} helper has been modified to be able to render these closures too.

Creating a new contextual component is very easy: you just need to use the component helper!

Let us create our first contextual component:

{{! app/templates/components/my-greeter.hbs }}

{{yield (component (if formal "formal-greeting" "informal-greeting") name=name)}}
{{! app/templates/components/formal-greeting.hbs }}

Good morning, Mr/Mrs {{name}}!
{{! app/templates/components/informal-greeting.hbs }}
Hey, {{name}}, how's it going?

Then, we can render our closure using the component helper as in the following snippet:

{{#my-greeter formal=true name="Sergio" as |greet|}}
{{component greet}}
{{component greet name="Matthew"}}

In my-greeter, (component ...) creates a closure over the inline if and name="Sergio". This closure is passed as first argument to the block. Then, when rendered with {{component greet}} would be like invoking it as {{component "formal-greeting" name="Sergio"}}. In the second example, the passed name is Matthew, the most recent value to the name attribute.

As with the usual {{component}} helper, the rendered component can change just by changing the first parameter to the helper. You can play with this twiddle to see basic contextual components in action.

Rendering a closure component without the component helper

Remember when I said that the hash helper, though simple, is a fundamental element of contextual components? Well, this is the part everything comes together. The best part of contextual components is that, if Ember finds and invocation with a point in the name containing a closure component, it will render the component. As an example:

{{! app/templates/components/form-for.hbs }}

{{yield (hash text-field=(component "my-text-field" object=object)
text-area =(component "my-text-area" object=object)
checkbox =(component "checkbox" object=object))}}
import Ember from 'ember';

const FormForComponent = Ember.Component.extend({});

positionalParams: ['object']

export default FormForComponent;

The FormForComponent is quite simple. It has a positional parameter mapped to object (just not to call it model) and exposes a hash with three different components. Then, we can invoke those components by using the dot syntax for contextual components:

{{! app/templates/your-route.hbs }}

{{#form-for model as |f|}}

{{f.text-field "name"}}
{{f.text-area "lastName"}}
{{f.checkbox "lovesEmber"}}


When Ember finds a dot in the first part of a moustache, it checks if the value is a contextual component. If it is, Ember is intelligent enough to unbox it and render it.

Full example

Previous example needs some more code to be fully functional. The rest of the code can be found in this twiddle. There is an interesting trick being done there: you can use the mut helper with a get helper inside to make a mutable binding to a variable property of an object.

You can see the code in this gist as well.


  1. While passing null or undefined as component name to the component helper will render nothing, passing it to a closure component will raise an error.
  2. Conflicting positional parameters and attributes usually raise an assertion. When working with contextual components, a collision between current parameters and attributes with those from the closure won’t raise an error.

The Path to Contextual Components: Understanding dynamic components

The component helper allows the user to render a component based on a given name.

Given these two components:

{{! app/templates/components/first-component }}

This is first-component

{{! app/templates/components/second-component }}

This is second-component


We can render dynamically any of them with the following invocation:

{{component componentToRender name='Sergio'}}

The first parameter contains the name of the component you want to render. In this case, either 'first-component' or 'second-component'. The {{component}} helper passes everything but the first parameter to the component. In the example above, the rendered component receives name='Sergio'.

This twiddle demonstrates how to change the rendered component by changing a variable.

Rendering inputs and textareas

As of 2.3, inputs and textareas components cannot be rendered using dynamic components. The reason is simple: neither {{input}} nor {{texturea}} are components but helpers. There is a simple workaround for that. input is a helper around two components: Ember.TextField and Ember.Checkbox. Thus, we can extend those components just by creating new ones with no template and the following content:

// app/components/my-text-field
import Ember from 'ember';

// If you want to re-export it
export default Ember.TextField;

// If you want to extend it
export Ember.TextField.extend();
// app/components/my-checkbox
import Ember from 'ember';

// If you want to re-export it
export default Ember.Checkbox;

// If you want to extend it
export Ember.Checkbox.extend();

For textarea the code is pretty similar but with Ember.TextArea as the underlying component.

This twiddle demonstrates how it is done. There is a difference between using this technique and using a bound attribute to type. The former rises an assertion when using checkbox and a value attribute, like demonstrated in this twiddle.


  1. If null or undefined are passed as a component name, nothing is rendered.
  2. If a invalid or nonexistent component name is passed, an error is raised.

Go to the last post: Contextual Components!

The Path to Contextual Components: Understanding positional parameters.

Ember.js 2.3 introduces a brand new feature: contextual components. This feature aims to better component composition and the usage of components for DSL.

Before diving into this new feature, we will go through some of the details of current components invocation. In this post, we will see how positional params are used.

Positional params Vs. Attributes

Positional params are the secret behind liquid-fire or the new link-to component. It allows the programmer to automatically assign to an attribute the value of a positional parameter.

Positional params are declared as class properties in the component. The value of positionalParams will determine how and to which attributes the parameters will be mapped to.

There are two types of positional parameters: named and rest positional parameters.

Named positional parameters map one value to one attribute. Let’s see and example:

// app/components/my-if.js
import Ember from 'ember';

const { computed } = Ember;

const MyIfComponent = Ember.Component.extend({});

positionalParams: ['predicateValue']

export default MyIfComponent;
{{! app/templates/components/my-if.hbs }}

{{#if predicateValue}}
{{ else }}
{{yield to="inverse"}}

We are setting positionalParams to an array containing only one value: the string 'predicateValue'. When the component is rendered, Ember.js extracts and process the positional params, setting the property in the component’s instance.

Calling the component using this syntax {{my-if booleanValue}} is virtually the same as calling it with an explicit attribute {{my-if predicateValue=booleanValue}}.

Then, we can use this new component like the following example:

{{! app/templates/application.hbs }}

{{#my-if currentBooleanValue}}
This is true
{{ else }}
This is false

You can see a complete working example in this twiddle (files in this gist).

When you don’t know the number of parameters

Some components behave in different ways depending on the number of parameters. LinkToComponent treat a parameter in different ways depending on the number it received.

Rest positional parameters sets the property in positionalParams to an array containing all the properties.

Let’s take a look at the list-properties:

// app/components/list-properties.js
import Ember from 'ember';

const { computed } = Ember;

const ListPropertiesComponent = Ember.Component.extend({
object: computed.readOnly('params.firstObject'),
properties: computed(
get() {
let [,...props] = this.get('params');
return props;

positionalParams: 'params'

export default ListPropertiesComponent;
{{! app/templates/components/list-properties.hbs }}

{{#each properties as |prop|}}
{{yield prop (get object prop)}}

And then use it in a template in the following way:

{{#list-properties obj 'a' 'c' 'b'
tagName='dl' as |key value|}}



In this example, positionalParams property is just a string. Ember.js will take the array of all positional parameters ([obj, 'a', 'b', 'c']) and set it in the params property in our component’s instance. Then we create two computed properties, object and properties, based on the head and tail of said property.


  1. If a component invocation finds both a positional parameter and an attribute for the same property, then an assertion is raised.

Follow up in Understanding dynamic components and Contextual Components!

Eventos en jQuery, cómo usar on.

En la última entrega vimos que el siguiente código no funcionaba: El anuncio desencadenó un charla con Sergi manteniendo que debería escribir directamente sobre delegación de eventos, que es precisamente lo que vamos a tratar ahora.

Delegando eventos.

jQuery cuenta con muchos métodos para delegar a eventos (bind, delegate o live). Sin embargo, estos métodos están obsoletos desde jQuery 1.7 en favor de on. A pesar de eso, empezaré explicando live, pasaré a delegate y finalmente llegaré a on.


El problema del código original se hubiese solucionado fácilmente llamando a live en vez de a on, como se comprueba en el fiddler correspondiente. El código es idéntico, simplemente cambia on por live.

Lo que hace este método es disparar el evento en cualquier elemento que satisfaga el selector, valiéndose de la propagación.

Dado que live está obsoleto y que actualmente live usa on internamente, lo dejaremos aquí.


delegate es bastante similar a live, sólo cambia cómo llamarlo. La equivalencia de llamadas sería:

El fiddler para delegate simplemente busca el elemento #container y le añade los handlers a él con los selectores correspondientes.

Por cierto, a la hora de escribir este artículo, delegate, ya obsoleto, también delega en on.


Finalmente, on es el camino a seguir con jQuery, al fin y al cabo, como habéis podido comprobar, tanto live como delegate usan on internamente.

Usar on para delegar eventos es muy similar a usar delegate, salvando que los eventos y los selectores están en orden inverso. El fiddle lo muestra en funcionamiento y el código completo es el siguiente:

¿Qué es lo que está pasando realmente?

Delegar un evento no hace que jQuery lo añada a los elementos correspondientes en cuanto se creen, sino que se añaden al elemento seleccionado ya existente y, por lo tanto, la propagación se puede parar en cualquier elemento que esté por debajo de él. De ahí que tengamos que pensar dónde delegar el evento ya que podemos cancelarlo sin darnos cuenta.

Por otro lado, tal y como podemos leer en la documentación de on en la sección Event performance, no debemos complicar mucho los selectores dentro de la delegación. Si nos vemos usando selectores jerárquicos, seguramente podamos delegar el evento en un elemento más cercano.

Delegación a mano

Para simular la delegación anterior cuyo selector era una simple clase, podemos hacerla usando el siguiente código:

En él simplemente comprobamos que el elemento que ha lanzado el evento ( en el código) contiene la clase box. Puede parecer poco código extra, pero sin duda son dos líneas que nos ahorramos a cambio de un selector (el cual puede ser más complicado).

Eventos en jQuery, uso básico de on.

En la primera entrega, vimos lo básico de los eventos de nuestro DOM. Ahora veremos cómo usar de forma básica jQuery para manejarlos.

Notas previas

Todo el código javascript mostrado en este artículo se supone dentro de la función jQuery tal que así:

El cuerpo del html es:

El método on

Antiguamente, jQuery usaba varios métodos para manejar los eventos (click, bind, live, delegate), pero actualmente se favorece el uso de un único método: on.

Lo básico

En el primer ejemplo, dibujamos tres cajas que, al hacer click sobre ellas, muestran un mensaje.

Seleccionamos los div correspondientes con $('.box') y llamamos al método on con dos parámetros. El primero, es el evento en el que estamos interesados; el segundo, la función a la que se llamará. jQuery pasará un objeto Event que no es más que una normalización de los objetos de cada navegador. Además, dentro del handler this se refiere al objeto en el se ha llamado al evento, en este caso, el div en el que se ha hecho click.

Ahora, supongamos que queremos darles un borde negro a las distintas cajas cuando pasamos el ratón por encima y quitárselo cuando el ratón sale de ellas. La forma obvia de hacerlo sería crear una clase CSS black-border con la regla correspondiente y añadírselo en el evento mouseenter y quitársela en el evento mouseout. El código en funcionamiento se puede ver en este fiddler.  Podemos acortar un poco el código pasando un objeto cuyas claves sean los eventos y los valores los handlers, como se observa en este otro fiddler.

Sin embargo, en vez de usar los métodos autodescriptivos addClass y removeClass, podemos usar el método toggleClass. Este método, pasado un nombre de clase, la añade si el elemento la tenía y la quita en caso contrario. Si además sabemos que como nombre de evento podemos pasar varios nombres separados por espacios el código (totalmente funcional) queda similar a esto:

Disparando eventos

Podemos hacer uso del método trigger para lanzar eventos. Aunque a primera vista pueda parecer poco útil, unido al hecho de podemos añadir handlers a eventos propios trigger se convierte en una importante herramienta a tener en cuenta.

Este método no tiene mucho más secreto, salvo un par de formas más de llamarlo, perfectamente documentadas en la documentación oficial. Probadlo en este fiddler.

Evitando la propagación

Ya comentamos qué era la propagación y que se podía evitar pero, dado que difería un poco jQuery respecto al comportamiento habitual en ciertos casos, no entramos en detalles. Ahora veremos qué cuatro métodos nos proporciona jQuery para lidiar con la propagación.


Al igual que en el caso general, si llamamos a este método, la acción por defecto del evento no se llevará a cabo. Además, podemos usar el método isDefaultPrevented para saber si se ha llamado o no preventDefault en el evento.


Este método evita que el evento continúe propagándose y los handlers de los elementos padres sean llamados. Sin embargo, el resto de handlers para dicho evento en el elemento actual sí serán llamados. El método que nos permitirá saber si se ha llamado a stopPropagation es isPropagationStopped.


En el caso de stopPropagtion, vimos que no evitaba que el resto de handlers del propio elemento sean llamados. Si queremos evitarlo, deberemos llamar a stopImmediatePropagation. Éste llama por sí solo a stopPropagation, así que también evita que el evento se propague a los nodos padre.

Por si os lo preguntáis, isImmediatePropagationStopped (menudo nombrecito) nos dirá si ya se ha llamado o no a este método. La utilidad de este método se me escapa.

return false

Y es aquí cuando vienen las diferencias. En jQuery, devolver false desde un handler equivale a llamar event.preventDefault() y event.stopPropagation(). Esto es diferente de lo que ocurre normalmente si no usamos jQuery, ya que sólo equivaldría a event.preventDefault().

Personalmente, prefiero llamar a cada uno de los métodos porque dejo claras mis intenciones (y no me veo obligado a parar la ejecución del handler).

¡Pero esto qué es!

Supongamos que en nuestro documento html sólo tenemos un div#container. Supongamos que ejecutamos el siguiente código:

Podremos comprobar que no funciona. Esto se debe a que los elementos no existen cuando llamamos al método on. Veremos cómo solucionar esto en la segunda parte.

Un alto en el camino, eventos.

Hacemos un alto en el camino para aprender un poco más sobre los eventos. Serán tres entregas:

  1. Eventos, cómo funcionan. Características básicas.
  2. Eventos en jQuery. Veremos cómo usar on.
  3. Eventos en jQuery. ¿Qué es eso de trigger?

¿Qué es un evento?

Un evento puede representar varias cosas, pero normalmente es una respuesta a una acción del usuario en nuestra página. Por ejemplo, al pinchar en un elemento lanzamos el evento click. Si seleccionamos un campo, se lanza el evento focus. La lista completa la podéis encontrar la página de w3schools.

 El proceso

El proceso que sigue un evento es algo más elaborado de lo que nos podríamos imaginar en un primer momento. Cuando damos una función para que maneje (handle) un evento, hacemos que maneje el evento en un elemento determinado. Por ejemplo, en este fiddle tenemos tres cajas y, cada vez que pinchamos en una de ellas, nos muestra una alerta con el número de caja, distintas cajas, responden de distinta forma. El código no es importante, pues usaremos jQuery para manejar los eventos y no las apis del DOM, como en este caso. Además, para ahorrarnos código podríamos haber escrito una función que devolviese funciones, como en este fiddle.

Manejando un evento

Para manejar un evento contamos con dos importantes conceptos: el handler y el objeto event.

El handler no es más que la función que será invocada cuando se reciba el evento. Dicha función se ha de relacionar con un nodo del documento, y sólo será invocada si ese nodo en particular recibe el evento correspondiente. Esto es importante cuando veamos qué pasa cuando se dispara un evento.

El handler recibe un argumento con un objeto Event. Aunque dicho objeto es bastante importante, esperaremos a verlo al momento en el que veamos cómo manejar eventos con jQuery.

Sin embargo, el proceso no es tan simple como disparar y recibir un evento.

Every event is bubbling

Un evento es una respuesta a una acción. La acción crea y pone en movimiento un objeto Event. ¿Pero qué camino sigue este evento?  Veamos el siguiente fiddler. El código sigue sin ser importante, sólo que estoy añadiendo un handler (así llamaremos a las funciones que se ejecutan cuando sucede el evento) a todos los elementos li, estando estos anidados y con fondo de distinto color para saber en cuál de ellos estamos haciendo click. El handler lo único que hace es cambiar el texto dentro del li.

Una vez el evento se pone en marcha, sigue subiendo en el árbol del documento, yendo nodo padre a nodo padre. A este proceso lo llamaremos propagación o bubbling. Dicho proceso se puede comprobar haciendo click en los distintos colores de fondo en el anterior fiddler.

Podemos refinar un poco más esta idea con el siguiente fidller. En él, añadimos un nodo hermano al nivel 3. Si pulsamos en el nivel 3 o 4, vemos que el hermano no pulsado no recibe el evento.

Parando un evento

Podemos evitar que un evento siga propagándose o cancelar la acción predefinida de un evento.

Un evento se dice cancelable si su acción predefinida puede ser evitada. Por ejemplo, hacer click en un enlace tiene como acción predefinida el seguir dicho enlace. Al hacer click en un botón para enviar la información de un formulario, la acción predefinida consiste en evitar dicho envío. Estos eventos son cancelables y podemos evitar la acción por defecto llamando al método preventDefault en el objeto Event que se pasa al handler. Hay una forma alternativa de evitar la acción por defecto: devolviendo false desde el handler. Sin embargo, prefiero llamar explícitamente a los diferentes métodos puesto que el comportamiento difiere en jQuery.

Por otra parte, también podemos usar el método stopPropagation para evitar que el evento se propague, aunque esto no evitaría la acción por defecto.

Notas finales

Sé que esta entrega se ha retrasado, y seguramente reduzca el número de publicaciones a dos por semana: una al principio y otra al final.

Lo importante de esta entrega no es saber cómo añadir handlers o cómo parar la propagación de un evento. Todos eso lo veremos cuando hablemos de eventos en jQuery.

Aprendiendo jQuery con la web del Senado, IV

Hoy aprenderemos:

  • Qué es jQuery UI y a buscar su API.
  • A usar un objeto Date.
  • A crear elementos con jQuery.

Código inicial

Me llama la atención que, a pesar de que las variables year, txt_month y month son independientes del elemento de la colección, los está recalculando en cada iteración. Saquémoslos fuera, y hagamos unas pequeñas modificaciones.

¡Hop! ¡Hecho!

jQuery UI

jQuery User Interface es una colección de elementos orientados hacia la interfaz de usuario basados en jQuery. Entre otras cosas, la web del Senado usa jQuery UI para el selector de fechas.

Captura de la sección Actividad parlamentaria,

También recalcar que estamos en la sección Actividad parlamentaria. Este plugin también se usa en la página principal, pero el código se refiere a éste en concreto, por lo que trabajaremos aquí.

La página del datepicker en jQuery UI contiene varios ejemplos. Sin embargo, ahora mismo es más interesante mirar su API (al fin y al cabo, está en un enlace bien grande y tentador).

Veréis, no había usado nunca el selector de fecha de jQuery UI hasta leer el código. Sin embargo, me parecía raro que no tuviese un método que devolviese la fecha seleccionada (llamadme loco). Y, en efecto, allí estaba. El método llamado getDate.

Por lo tanto, simplemente llamamos a ese método para obtener la fecha, como vemos a continuación.

Puede parecer un poco rara la forma de llamar a los métodos, pero pensad que así es más difícil pisar los nombres de otros plugins.

Para obtener el mes y el año, primero debemos indagar un poco más en el objeto Date de js.


Una pequeña anécdota, trabajando en una gran cárnica consultora, me encontré con un código de cerca de 30 líneas de js para comparar fechas. El tipo que lo escribió me pidió ayuda para solucionar un problema, puesto que no le funcionaba la comparación para un par de fechas. El fallo ocurrió en producción.

Bien, el problema se soluciona fácilmente comparando las fechas directamente (date1 < date2, por ejemplo). Lo podéis comprobar en el siguiente fiddle.

En nuestro caso queremos conseguir el año y el mes.


Los objetos Date tienen dos métodos para obtener el año, getYear y getFullYear. El primero, obsoleto, devolvía el número de años desde 1900 (WTF?); el segundo, devuelve el año completo. Por lo tanto, es lo que usaremos para obtener el año.


El siguiente paso es obtener el mes. El método getMonth devuelve el índice del mes. Así enero es 0, febrero es 1 y así hasta diciembre que es el 11.

El código original coge el texto del mes y recorre los options correspondientes para conseguir el valor del option seleccionado. Lo curioso es que se podrían haber ahorrado el bucle si en vez de llamar a text hubiesen llamado a val. jQuery hace que la llamada a val en el select sea el valor de la opción elegida (en el caso de que la selección sea múltiple, devuelve un array con los valores). Sin embargo, val devuelve una cadena de texto, por lo que no nos ahorraríamos el parseo.

Si nos fijamos en el select, los valores de los options se corresponden con los índices que devuelve método (salvo, por supuesto, que uno son textos y otros son números).

Options de los meses en el calendario.

Finalmente, el código queda así:

Creando elementos con jQuery.

Por último, el script crea un elemento y lo pone dentro del elemento correspondiente a la iteración.

Si a la función jQuery le pasamos una cadena con html, ésta crea los elementos por nosotros. Además, podemos encadenar funciones en jQuery. La diferencia se puede ver en el siguiente gist:

Para terminar, usaremos appendTo para añadir un elemento como hijo a otro. Además, usaremos empty para eliminar cualquier texto anterior (y nodo hijo) del elemento correspondiente.

El código queda así:

Notas finales

El resto de la semana hablaré un poco de los eventos, que ya va siendo hora. Además, veremos cómo es aconsejable declararlos ahora (en el script anterior usaba la función click).

Aprendiendo jQuery con la web del Senado, III

Hoy veremos el espinoso mundo de las variables globales. Además, veremos cómo

  1. Usar el atributo data.
  2. Usar la función map.
  3. Inicializar un array.

El código inicial.

El código a modificar es el siguiente:

Me encanta cuando la gente usa variables globales. Me hace preguntarme “¿por qué?”. Seré sincero, no suelo usar javascript. En su lugar uso coffeescript. Cuando estoy probando el código en desarrollo, coffeescript rodea cada uno de mis archivos con una IIFE, lo que hace que tenga que pensar qué he de exportar al ámbito global, no qué tengo que poner en el local. Lo primero que hago, es crear algo del estilo a window.Senado = {}, ahí meto toda mi mierda todo mi código.

He de reconocer que al menos meten todas las variables globales dentro de una variable nombrada, ejem, globales. Pero esto es un nombre fácilmente pisable.

Attributos data.

Por otra parte, la mayor porción del código accede a elementos para coger el texto. Todos los que he comprobado son elementos que no se muestran (tienen display: none, algunos de ellos escritos a fuego). Para ello, personalmente, prefiero meter la configuración en el elemento en sí. Para ello, me valgo de los atributos data. Si en un elemento ponéis un attributo data-x, después podéis acceder a él usando jQuery fácilmente. En este fiddle, lo uso para poner el texto del alert y el color de fondo nuevo. Más información en la documentación de la función data.


Veamos la siguiente variable.

Podríamos hacer lo mismo usando la función ya vista each. Veamos cómo en el siguiente código:

Tenemos un array con los valores del 1 al 5. Creamos un array result vacío. Después usamos la función each, y en cada iteración metemos el doble del elemento actual en el array result. Finalmente, ponemos en la consola el resultado.

El resultado de nuestro código es [2,4,6,8,10]

Esta forma de usar each parece muy útil; podríamos repetirla muchas veces en varios sitios. Podríamos hacer una función que hiciese algo parecido, pero para eso ya tenemos map. En ella pasamos una función que recibe como parámetros el índice del elemento en la colección y el elemento en cuestión. Esto mismo es para lo que sirve la función map de jQuery. Map creará un nuevo array con el mismo número de elementos, pero cada elemento será el resultado de aplicar la función al elemento original de la misma posición.

Por ejemplo, el código anterior reescrito usando quedaría como:

Y comprobamos que efectivamente devuelve el mismo resultado.

El código reescrito con

¿Os habéis dado cuenta de que podemos usar las funciones each y map en cualquier array o similar simplemente usándolos de forma diferente? En efecto, usando las formas jQuery.each y podemos usarlo en objetos lo suficientemente parecidos a un array. Daos cuenta, sin embargo, que la función que pasamos a recibirá los argumentos al revés: primero el elemento en sí y luego el índice.

Finalmente, el código corrrespondiente a la variable monthNames queda así:

Inicializando un array.

En general, si queremos crear un array, tenemos dos opciones recogidas en el siguiente gist:

En este caso, es preferible usar la segunda opción, puesto que es más rápida (se puede comprobar con este jsperf). Sin embargo, la variable está siendo inicializada con 31 elementos, todos ellos undefined.

En ese caso tenemos tres opciones. La primera es llamar a new Array con el número de elementos. El segundo, consiste simplemente en asignar 31 a la longitud del array (sí, sí, ¡funciona!). Finalmente, podemos añadir al array un método undefined 31 veces valiéndonos de un bucle para hacerlo.

Sorprendentemente, esta vez la más rápida es la que utiliza el constructor (new Array(31)). La más lenta se corresponde con la tercera opción. Los resultados del jsperf correspondiente en mi máquina son estos:

  • new Array(31): 18,590,339 operaciones por segundo.
  • [] + for: 2,497,498 operaciones por segundo.
  • [] + length: 6,512,241 operaciones por segundo.

Por lo tanto, amigos, en este caso lo han hecho bien. ¡Un aplauso para Rocío!

Notas finales.

En general, esta parte no está tan mal. Se sigue notando que son incapaces de consultar una api o de leerse un tutorial, pero no está del todo mal. El código modificado quedaría así:

Hay que tener en cuenta que estamos modificando función a función. Esto no estaría así, si de mí dependiese.

¡Ánimo, Rocío!


Aprendiendo jQuery con la web del Senado, II

Hoy, refactorizando la web del senado, aprenderemos:

  1. A obtener el valor seleccionado de un select.
  2. A ocultar y a mostrar de nuevo un elemento del DOM.
  3. A separar un poco más la funcionalidad javascript del estilo de nuestra web.
  4. A añadir una función a jQuery.
  5. A retrasar la ejecución de nuestro código a que el document html esté listo.
  6. De paso, recordaremos cómo seleccionar un elemento del DOM.

El código original.

El código original es muy simple. Es el siguiente:

En primer lugar, no soy muy fan de poner nombres en español pero, si lo vas a hacer, al menos hazlo bien, mendrugo de pan. Se dice “selecciona”.

Como novedad, iré creando un jsfiddle para que podáis probar el código que vamos creando. La primera versión es ésta. Podréis ver que hay un poco de código extra, ya veremos para qué. Si jugáis un poco con él, veréis que el “Selecioname” cambia de posición. Además está mal escrito.



Como ya he dicho, no soy muy fan de poner nombres en castellano en lo que a programación se refiere. Sin embargo, de hacerlo, debemos intentar poner los cinco sentidos en los nombres.

Dicho esto, solucionemos este tema de una vez por todas. El nuevo fiddle recoge los cambios.

Primeros cambios.

Por primera vez, vamos a extender jQuery, vamos a añadir una función al objeto jQuery para saber si devuelve un resultado o no. Llamaremos a la función exist(), y vi esta implementación por primera vez en esta respuesta de StackOverflow.

Vemos que para añadir la función exists sólo tenemos que declararla como un miembro de $.fn.En dicha función, vemos si existe algún elemento comprobando que la longitud de la selección sea distinta a cero. Ésta es la forma más sencilla de extender las capacidades de jQuery.

Dentro de selectCharge, usamos la función $ como aprendimos en la primera parte para seleccionar el elemento div#fs_selecciona_orden. El código ahora mismo no es funcional, pero lo resolveremos en las siguientes secciones.

To display or not to display.

En el condicional, lo que se hace realmente es mostrar o esconder un elemento del dom dependiendo del valor seleccionado en el select.

En vez de modificar la propiedad CSS display del elemento deberíamos usar las funciones show y hide de jQuery. La razón más poderosa es que show y hide recuerdan la propiedad display anterior del elemento. Así, si el elemento tenía display: block; antes de usar hide, al llamar a show volverá a tener display: block;. Esto permite separar mejor el estilo de la programación. Si el diseñador cambiase el estilo del elemento y nosotros no tocásemos el código, la podíamos liar “parda”.

Además, podemos pasar parámetros extra si queremos que se convierta en una animación.

El código en esta fase se parece a lo siguiente:

Retoques finales.

El código requiere de dos toques finales:

  1. La función exists no es realmente necesaria.
  2. Usar jQuery con el parámetro select.

Como ahora estamos usando las funciones show y hide, no necesitamos comprobar que haya un elemento en la colección. Por lo tanto, podemos eliminar ese código.

Por último, vamos a user jQuery para obtener el valor seleccionado del select. En jQuery podemos hacerlo directamente con $(select).val(), suponiendo que select contiene el elemento DOM correspondiente. Personalmente, prefiero encontrar primero el option que está seleccionado. Para ello, usaremos una pseudoclase CSS :selected. Además, ya que estamos, compararemos con un más correcto ===.

Finalmente el código termina así:

Y el fiddle correspondiente nos permite jugar con el código y observar cómo el elemento conserva el display: block.

No tan deprisa.

Al principio os prometí ver qué pasaba con ese código extra que le había metido al fiddle.

La primera parte son dos simples líneas de código que se parecen a esto.

Otra forma de escribirlo, que nos da más pistas de qué sucede, es:

En nuestro código referenciamos elementos de html que pueden no existir cuando el código se ejecuta. Si esto pasa, nuestro código puede, en el mejor de los casos, no funcionar. Para evitar esto, usamos la función $ (otra vez nos encontramos, vieja amiga) pasándole una función que jQuery ejecutará cuando el documento este listo (document y ready, fácil).

¿Qué pasa con la otra parte? Es un poco más complicada de explicar y no voy a explicar exactamente qué sucede con los eventos en jQuery, eso será para otro momento. Veamos el código:

Básicamente, le estamos diciendo a jQuery que, cada vez que un elemento de $('select') cambie (change en inglés), debe llamar a la siguiente función. Para terminar de entenderlo, debemos saber que jQuery hará que la variable this se refiera al select correspondiente. ¿Por qué decir ‘el correspondiente’ cuando sólo hay uno? Pues porque $('select') podría devolver una colección de más de un elemento, en cuyo caso añadiría el callback (así es como llamamos a la función que le pasamos) al evento change de cada uno de los elementos.

Notas finales.

No hemos reducido mucho el código (LoC nunca ha sido un buen indicador de la calidad del código), pero a cambio hemos separado nuestro código del diseño. Si tuviera que hacer ese código, probablemente lo haría de forma diferente (¡Qué coño porras! ¡Lo he escrito hace menos de un mes! ¡Diferente!), pero no está del todo mal.