Bienvenidos sean a este post, hoy continuaremos con los eventos.
Para entender como propagar un evento debemos entender como es el viaje de uno, para ello consideremos el siguiente codigo:
<div>
<span>
<a href="index.html">
Un link de ejemplo.
</a>
</span>
<p>
Este es un parrafo.
</p>
</div>
Este es un contenedor de tipo div con dos elementos, uno de tipo span y otro de tipo p, en el primero tenemos un link y en el segundo un simple texto, en este caso vamos a suponer que trabajamos con el evento click y sobre el link dentro de span, cuando lo presionemos solamente tres elementos podran responder a este evento:
- div
- span
- a
En cambio el parrafo (p) ignorara este evento, otro punto de vista que podemos considerar, es que estos tres elementos estan bajo el mouse, cuando permitimos que varios elementos tengan la posibilidad de poder responder a la interaccion del usuario se lo denomina Captura de evento, en este caso se le asigna el evento al elemento mas completo y luego a los mas especificos, por ejemplo en el codigo anterior el primero seria el div, luego el span y finalmente el a, el link en cuestion, el opuesto a esto se lo denomina burbujeo de eventos, en este caso sera al reves porque comenzaremos desde el elemento mas especifico hasta el mas global, lo opuesto a lo citado anteriormente, el estandar de DOM utiliza a ambos porque al momento de usarlo iremos desde el evento general hasta el especifico y al momento de volver lo haremos al reves, con la salvedad de que los manejadores de eventos pueden ser usados en cualquier parte del proceso, para facilitar las cosas jQuery siempre registra los manejadores de eventos en la fase de burbujeo del modelo, donde el elemento mas especifico siempre tendra la primera oportunidad de responder.
Un problema que podemos tener con esta forma de trabajar es cuando el elemento equivocado responde al evento, tomemos como ejemplo a mouseout y mouseover, si lo aplicamos sobre el div el evento mouseout solo se disparara desde este lo cual no creara ningun inconveniente pero en uno mas especifico con el burbujeo de evento, por ejemplo si fuera en el link y si salimos de este con mouseout tambien se disparara cuando pasaemos sobre el span o el div, lo cual no queremos.
Ya mencionamos un inconveniente que nos puede surgir al trabajar de esta forma pero como podemos solucionarlo? bueno, una forma seria trabajar con los eventos pero para ello deberemos primero descargar los archivos que trabajamos en el post anterior, les dejo un link a ellos:
Extraigan los archivos en un directorio y listo, repasemos como trabaja este codigo mediante el siguiente video
Si ven el video, cuando presionamos el titulo donde estan los botones lo ocultamos o mostramos, en el archivo codigo.js tenemos este segmento:
$('#cambiador h3')
.on('click', function() {
$('#cambiador button')
.toggleClass('oculto');
});
Ahora vamos a modificarlo de la siguiente manera:
$('#cambiador')
.on('click', function() {
$('#cambiador button')
.toggleClass('oculto');
});
Esto hara que ocultemos o mostremos los botones no solamente presionando el titulo o el elemento con h3 sino en cualquier parte del cuadro, veamos como funciona ahora
Si bien cumple la conducta que deseamos tambien agrego una nueva que no esperabamos, o si? bueno, en realidad si por todo lo mencionado anteriormente pero como podemos solucionarlo? aqui debemos modificar el segmento anterior de la siguiente manera:
$('#cambiador')
.on('click', function(evento) {
if (evento.target==this){
$('#cambiador button')
.toggleClass('oculto');
}
});
Para solucionarlo simplemente agregamos un argumento a la funcion anonima, en este caso la llamamos evento pero le pueden poner el nombre que deseen o lo identifique mejor, lo que despues usamos es un condicional donde por medio de la variable anterior y target verificaremos si es igual a this, es decir que especificamos el destino a trabajar que no sera otro que el div cambiador en lugar de todos los elementos, si esto se cumple ocultaremos o mostraremos los botones en esta, veamos como trabaja ahora
Aqui volvimos a trabajar un poco mas parecido a como lo hacia antes, pero en lugar de apretar el titulo para ocultarlo o no utilizamos al contenedor y como especificamos que sea solamente este el destino cuando presioamos cualquier de los otros elementos no se disparara este evento sino los correspondientes a cada uno de ellos, ahora vamos a hacer una serie de modificaciones para continuar con el siguiente tema, el primero de ellos sera ir al archivo estilo.css y cambiar los nombres de las clases achicar y agrandar por chico y grande, veamos como estan actualmente en el archivo:
body.agrandar .capitulo {
font-size: 1.5em;
}
body.achicar .capitulo {
width: 250px;
}
Lo cambiaremos de la siguiente manera:
body.grande .capitulo {
font-size: 1.5em;
}
body.chico .capitulo {
width: 250px;
}
En realidad solo cambiamos la forma de identificarlo, el resto se mantiente de la misma forma, con esto modificado nuestro siguiente paso sera cambiar el codigo de codigo.js por el siguiente:
$(document).ready(function() {
$('#cambiador').click(function(evento) {
$('#cambiador button')
.toggleClass('oculto');
});
});
$(document).ready(function() {
$('#el-default').addClass('seleccionado');
$('#cambiador button')
.click(function(evento) {
var e = this.id.split('-')[1];
$('body').removeClass()
.addClass(e);
$('#cambiador button')
.removeClass('seleccionado');
$(this).addClass('seleccionado');
evento.stopPropagation();
});
});
A comparacion del codigo anterior tenemos dos eventos ready, en el primero tenemos la rutina para ocultar o mostrar los botones cada vez que pulsemos el contenedor pero le quitamos el condicional por lo cual volvimos al inconveniente de antes pero esto no es tan asi ahora veremos porque.
El siguiente se encargara de hacer mucho de lo que haciamos antes pero de una forma mas resumida, primero agregaremos la clase seleccionado al boton default, nuestro siguiente paso sera aplicar la captura de evento a los botones de cambiador pero ahora tendremos un par de particularidades, la primera sera definir una variable llamada e, en esta almacenaremos el resultado de aplicar la funcion split, esta funcion divide una cadena en base al elemento que le indiquemos, transformandola en un array, y en este caso le pedimos que seleccione el segundo elemento de este array y lo almacenaremos en la variable, esta es la razon porque debimos renombrar las clases dado que ahora coincidaran con el resultado de aplicar split, nuestro siguiente paso sera remover todas las clases del documento y aplicamos la clase que almacenamos en e, lo siguiente sera remover la clase seleccionado de todos los botones y aplicarla al que pulsamos y aqui agregamos una nueva opcion llamada stopPropagation, esta funcion detendra la propagacion del burbujeo del evento, por lo tanto no continuara cuando lo pulsemos evitando que entre en accion el evento anterior, vamos a verlo mediante el siguiente video
Si lo comparamos con el caso anterior ahora funciona mejor porque el evento de ocultar/mostrar los botones ahora tambien se aplica al titulo como era originalmente, esto es gracias a la ultima funcion que agregamos, pero tiene una particularidad la cual no nos permite evitar su accion predeterminada, para ello debemos usar a preventDefault pero eso debe usarse solo para cuando no queremos que un evento haga su accion predeterminada, por ultimo tambien podemos delegar eventos.
Cuando hablamos de delegar eventos nos referimos a la capacidad de poder asignar un manejador de eventos en un solo elemento para que haga el trabajo por muchos, por ejemplo si trabajaramos con el evento click y tuvieramos muchos botones al momento de asignar los eventos seria facil pero tendriamos un inconveniente con la performance por el bucle de la iteracion de jQuery y el rastro que debe usar la memoria para el mantenimiento de los manejadores, para entenderlo vamos a trabajar con el codigo pero antes modifiquemos a estilo.css donde agregaremos la siguiente clase:
.flotar {
cursor: pointer;
background-color: #afa;
}
Esta clase la aplicaremos a continuacion, para ello hara debemos ir al archivo codigo.js y agregaremos el siguiente segmento:
$(document).ready(function() {
$('#cambiador').hover(function() {
$(this).addClass('flotar');
}, function() {
$(this).removeClass('flotar');
});
});
Esto simplemente aplicamos el metodo hover al div llamado cambiador, cuando estemos por encima agregaremos la clase flotar y cuando nos salgamos lo removeremos, modifiquemos el siguiente segmento:
$(document).ready(function() {
$('#cambiador').click(function(evento) {
$('#cambiador button')
.toggleClass('oculto');
});
});
De la siguiente manera:
$(document).ready(function() {
$('#cambiador').click(function(evento) {
if (!$(evento.target).is('button')){
$('#cambiador button')
.toggleClass('oculto');
}
});
});
Aqui haremos nuestra primera delegacion por medio de la funcion is, aqui tenemos un condicional donde verifica que todo elemento del destino sea distinto de un boton, esto es asi por el operador de negacion (!), y en caso de ser verdadero aplicamos y quitamos la clase oculto en los botones, ahora tomemos este segmento:
$(document).ready(function() {
$('#el-default').addClass('seleccionado');
$('#cambiador button')
.click(function(evento) {
var e = this.id.split('-')[1];
$('body').removeClass()
.addClass(e);
$('#cambiador button')
.removeClass('seleccionado');
$(this).addClass('seleccionado');
evento.stopPropagation();
});
});
Y vamos a modificarlo de la siguiente manera:
$(document).ready(function() {
$('#el-default').addClass('seleccionado');
$('#cambiador')
.click(function(ev) {
if ($(ev.target).is('button')) {
var e = ev.target.id.split('-')[1];
$('body').removeClass()
.addClass(e);
$('#cambiador button')
.removeClass('seleccionado');
$(ev.target).addClass('seleccionado');
}
});
});
No es muy distinto al anterior pero si tiene algunas diferencias, la primera sera que cambiamos el nombre del argumento del evento, despues agregamos un condcional donde verificamos si el destino del evento es un boton, en caso de ser verdadero procede a hacer todo lo que haciamos antes pero sin la necesidad de detener la propagacion porque ahora solamente trabaja sobre el boton e ignorara al resto, con esto tenemos la pagina funcionando de la siguiente manera
Seguimos con todo lo anterior y a su vez el cambio de color y cursor cuando pasamos sobre el contenedor, pero ese codigo puede mejorarse mas porque al igual que en otro caso es funcional pero poco practico, para ello podriamos modificarlo de la siguiente manera:
$(document).ready(function() {
$('#cambiador').hover(function() {
$(this).addClass('flotar');
}, function() {
$(this).removeClass('flotar');
});
});
$(document).ready(function() {
$('#el-default').addClass('seleccionado');
$('#cambiador').click(function(ev) {
if ($(ev.target).is('button')) {
var e = ev.target.id.split('-')[1];
$('body').removeClass()
.addClass(e);
$('#cambiador button')
.removeClass('seleccionado');
$(ev.target).addClass('seleccionado');
} else {
$('#cambiador button')
.toggleClass('oculto');
}
});
});
Si lo comparan con el anterior, eliminamos el segmento encargado de ocultar los botones y lo pasamos al siguiente donde en el condicional agregamos un else para ocultar o mostrar los botones, el resto sigue exactamente igual a como lo trabajamos antes, es mas si prueban la pagina deberia seguir funcionando de la misma forma, pero como pudimos delegar al destino si es un boton o no podemos manejarlo de esta forma, antes de finalizar tenemos dos formas de delegar eventos:
- is(), este nos permite evaluar cual elemento activo el evento que informamos de destino, es el mas utilizado porque es un poco mas flexible
- hasClass(), es similar al anterior pero verificamos si tiene la clase que le pasemos
Por ultimo tambien podemos usar la funcion on para delegar eventos, por ejemplo:
$('#cambiador').on('click','button',function(){ ... el resto
Si repasan casos anteriores siempre pasabamos el evento seguido del metodo pero si antes indicamos cual es el elemento hara una delegacion interna, es una opcion mas pero de esto trataremos de verlo un poco mas adelante, a continuacion les dejo los codigos finales en este post:
En resumen, hoy hemos visto como es la propagacion de eventos, los distintos tipos que disponemos, asi como tambien en cual trabaja jQuery, asi como algunos inconvenientes que pueden surgir, como solucionarlos, la propagacion de un evento y como manejar esta, y por ultimo la delegacion de un evento como consecuencia de todo lo hablado previamente, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
