Laboratorio: reordenar lista mediante mootools

Estoy empezando a curiosear Mootools, y aunque me está gustando bastante, si que echo en falta una documentación más detallada, no solo explicar como va el API, ya que a veces son necesarios ejemplos más básicos para no tener que estar buscando en el API.

En este caso voy a reorganizar mediante drag&drop una lista de elementos, la cual puede tener subelementos también, un típico ejemplo de categorías y subcategorías. Para ello me crearé una lista cuyos elementos tendrán el estilo categoria y cuyos subelementos tendrán el estilo subcategorias, necesario para diferenciar estilos y comportamiento.

ordenarlistas.png

<ul id="lista_categorias">
<li class="categoria">Elemento 1</li>
<li class="categoria">Elemento 2
<ul>
<li class="subcategoria">Elemento 2.1</li>
<li class="subcategoria">Elemento 2.2</li>
<li class="subcategoria">Elemento 2.3</li>
<li class="subcategoria">Elemento 2.4</li>
<li class="subcategoria">Elemento 2.5</li>
<li class="subcategoria">Elemento 2.6</li>
</ul>
</li>
<li class="categoria">Elemento 3</li>
<li class="categoria">Elemento 4
<ul>
<li class="subcategoria">Elemento 4.1</li>
<li class="subcategoria">Elemento 4.2</li>
<li class="subcategoria">Elemento 4.3</li>
<li class="subcategoria">Elemento 4.4</li>
</ul>
</li>
<li class="categoria">Elemento 5</li>
<li class="categoria">Elemento 6</li>
<li class="categoria">Elemento 7</li>
<li class="categoria">Elemento 8</li>
<li class="categoria">Elemento 9</li>
</ul>

Para ser lo menos intrusivo que se pueda, anadiré al evento load del objeto window la carga de las funciones necesarias para ello, siempre que exista el objeto lista_categorias (el primer ul de todos).

window.addEventListener('load', function() {
_lista();
}
, false);
function _lista() {
if ($('lista_categorias')) {
...
}

Habrá tres operaciones distintas: crear efecto drag, añadir evento drop a las categorías y añadir evento drop a las subcategorías. Digo crear efecto drag porque realmente lo que se hace es que cuando se ejecuta el evento mousedown, se crea una copia del elemento, y es este el que se mueve por la pantalla, guardando una referencia al elemento original. Hay distinción entre el evento drop de las categorías y las subcategorías porque si se trata de una categoría se añade sin más, y si es una subcategoría se añade en la categoría. A parte, si se intenta mover una categoría que contiene subcategorías, solo se añadirán las subcategorías, no la categoría.

// Drag & Drop de listado
function _lista() {
if ($('lista_categorias')) {
// Drag de cada categoria/subcategoria
// Para cada elemento li añado el evento mousedown, para que cuando se ejecute se cree una copia de ese elemento, se le de estilo semi transparente y se permita hacer drag
$$('#lista_categorias li').each(function(elemento){
elemento.addEvent('mousedown', function(e) {
e = new Event(e).stop();
window.item = elemento;
window.categoria_clone = this.clone()
.setStyles(this.getCoordinates())
.setStyles({'opacity': 0.7, 'position': 'absolute'})
.addEvent('drop', function() {console.log('DROP')})
.addEvent('emptydrop', function() {
this.remove();
}).inject(document.body);
categoria_clone.makeDraggable({
droppables: $$('#lista_categorias li')
}).start(e);
});
});
// Drop en las categorias
// Para cada categoria, le añadimos el evento drop, que permite recibir elementos "drag". Si el elemento que se recibe tiene subcategorias, entonces se cogen estas y se añaden al elemento ul que contiene, si no lo contiene, lo creamos. Si no contiene subcategorías, se añade sin más.
$$('#lista_categorias li.categoria').each(function(drop){
drop.addEvents({
'drop': function() {
window.categoria_clone.remove();
var ul = window.item.getElement('ul');
if (!drop.getElement('ul')) {
(new Element('ul')).inject(drop);
}
dropul = drop.getElement('ul');
if (ul) {
ul.getElements('li').each(function(li) {
li.inject(dropul);
});
ul.remove();
} else {
window.item.inject(dropul);
}
drop.setStyle('background', '#FFFFFF');
//dropFx.start('7389AE').chain(dropFx.start.pass('ffffff', dropFx));
},
'over': function() {
drop.setStyle('background', '#DDDDFF');
//dropFx.start('98B5C1');
},
'leave': function() {
drop.setStyle('background', '#FFFFFF');
//  				window.categoria_clone.remove();
//dropFx.start('ffffff');
}
})
});
// Si cae el drop en una subcategoria lo inserto en el padre
$$('#lista_categorias li.subcategoria').each(function(drop){
drop.addEvents({
'drop': function() {
window.categoria_clone.remove();
var ul = window.item.getElement('ul');
dropul = drop.parentNode;
if (ul) {
ul.getElements('li').each(function(li) {
li.inject(dropul);
});
ul.remove();
} else {
window.item.inject(dropul);
}
}
})
});
}
}

Ejemplo

Descargar ódigo