Hoy vamos a ejercitar de nuevo el manejo de listas con jQuery. Para ello vamos a ver cómo podemos copiar elementos entre listas con jQuery.
El objetivo es conseguir mover elementos de una lista Origen a otra lista Destino. Esta vez moveremos el elemento sobre el que hagamos click en la lista origen y añadiremos ese elemento a la lista destino.
Seguramente todos vamos intuyendo que haremos lo siguiente:
- Definir una lista origen y sobre cada uno de sus elementos de forma individual les vincularemos el evento click para que reaccionen ante él.
- Pasarle una función que tome el elemento seleccionado y lo mueva a otra lista con Jquery appendTo
Nuestro código HTML que represente a las listas será así:
Lista origen
- Elemento 1
- Elemento 2
- Elemento 3
- Elemento 4
Lista destino
Vemos que utilizamos el elemento ol para representar las listas desordenadas, el cual contiene elementos li para representar cada uno de los items de la lista.
Además hemos utilizados dos identificadores «listaOrigen» y «listaDestino» los cuales vamos a emplear desde el código jQuery.
En el código jQuery asignaremos el evento click a cada elemento li de #listaOrigen.
$('#listaOrigen li')
Con el selector ‘#listaOrigen li’ seleccionamos todos los li de #listaOrigen y les vinculamos el evento.
$('#listaOrigen li').on('click', function (){
...
});
Fijémonos en que cuando se produce el evento queremos actuar sobre el elemento li seleccionado y no sobre todos. Para eso usamos this. This es la palabra clave reservada de Javascript que hace referencia al objeto que provoca la ejecución; es el objeto en donde el método está siendo invocado.
$('#listaOrigen li').on('click', function (){
$(this).appendTo('#listaDestino');
});
El método .appendTo() será el que nos permita copiar elementos entre listas con jQuery ya que realiza el movimiento de la listaOrigen a la listaDestino.
Con ese código sería suficiente pero para estar seguros de qué elemento estamos seleccionando con el ratón y que recibirá el evento click resaltaremos en naranja el elemento. Así mismo con jQuery onmouseout haremos que recupere su estilo original en fondo blanco y así deje de estar resaltado.
$('#listaOrigen li').on('mouseover', function (){
$(this).css('background', 'orange');
});
$('#listaOrigen li').on('mouseout', function (){
$(this).css('background', 'white');
});
El resultado no parece el esperado. Veamos por qué
Si ejecutamos el código tal cual está observaremos varias cosas. Cuando hacemos click el elemento está resaltado y su estilo está en color de fondo naranja. El elemento se mueve en el DOM pero su CSS permanece. Es decir, no nos ha dado tiempo a ejecutar el mouseout pues en cuanto hagamos click el elemento se mueve a lista Destino y cuando quitemos el ratón de su posición -que es cuando se lanza el evento mouseout -ya tendremos debajo de nosotros a otro elemento de la lista Origen o ninguno si la lista ya se ha quedado sin elementos. Tendremos que pasar de nuevo encima de él en la lista Destino para volver a ejecutar mouseover y mouseout y recuperar su color blanco.
Este comportamiento puede resultar más o menos obvio a algunos. ¿Te lo parece? Aquí es donde debemos darnos cuenta de una cosa. Nosotros habíamos asignado un comportamiento a todos los elementos li de listaOrigen que consistía en ponerse naranja al posicionar el ratón sobre él y recuperar el blanco al irnos. Pero ahora el elemento está en listaDestino. ¿Por qué se ejecuta? Muy sencillo. Los eventos se vinculan sobre los elementos últimos del DOM no sobre la jerarquía completa. Es decir, para vincular inicialmente seleccionamos todos los li de ListaOrigen pero son solo esos li los que tienen el evento. Si se mueven en el DOM y ocupan otras posiciones siguen poseyendo sus comportamientos, textos y estilos y todas sus propiedades.
Además, si hacemos click sobre los elementos en listaDestino se vuelve a ejecutar su función asignada a click y la lista se comporta algo así como la lista circular que definimos en el ejercicio anterior. En realidad, el elemento seleccionado (this) se mueve al final de la lista.
¿Cómo lo solucionamos?
- Antes de ejecutar el movimiento del elemento a la lista destino volveremos a ponerle fondo blanco
- Queremos que el appendTo que mueve el elemento al final de la listaDestino se ejecute una única vez. Para ello tenemos dos opciones. Una vez usado desvincular el evento llamando a jQuery off. O vincularemos el evento con jQuery.one en lugar de jQuery.on que vincula el evento pero permite que se ejecute una sola vez y sólo una. Una vez en la lista destino li ya no tendrá ese comportamiento.
El código llamando a jQuery.off sería el siguiente:
$(document).on('ready', function(){
$('#listaOrigen li').on('click', function (){
$(this).css('background', 'white');
$(this).appendTo('#listaDestino');
$(this).off('click');
});
$('#listaOrigen li').on('mouseover', function (){
$(this).css('background', 'red');
});
$('#listaOrigen li').on('mouseout', function (){
$(this).css('background', 'white');
});
});
Y su queremos ejecutar el jQuery.one sería:
$(document).on('ready', function(){
$('#listaOrigen li').one('click', function (){
$(this).css('background', 'white');
$(this).appendTo('#listaDestino');
});
$('#listaOrigen li').on('mouseover', function (){
$(this).css('background', 'red');
});
$('#listaOrigen li').on('mouseout', function (){
$(this).css('background', 'white');
});
});
Conclusiones de copiar elementos entre listas con jQuery
En este ejercicio hemos repasado y explicado la vinculación de eventos, a usar el método one, cambiar el estilo de los elementos con la función JQuery css y el uso de eventos click, mouseover y mouseout para explicar cómo copiar elementos entre listas con jQuery.