Egy érdekes DataView rendezési megoldást láttam nemrégiben az ExtJS fórumán. Általában a DragAndDrop rendezéseknél megfogjuk az elemeket, egérrel ide-oda mozgathatjuk, majd az egér gomb felengedésénél a megfelelő helyre illesztjük a kiválasztott elemet. Jobb esetben az egér mozgatása közben az eredeti elemet egy átmeneti töltelék elemmel helyettesítjük.
Itt az alapötlet annyi, hogy nincs tetszőleges mozgatás, nincs mozgatandó elem és nincs átmeneti állapot. Az megoldás kihasználja, hogy amikor megváltozik a DataView-hoz tartozó Store, akkor a HTML felépítés is változik, illetve, hogy a DataView-on belüli egérmozgásnál egyszerűen lekérhetjük azt az elemet, amelyik felett mozgatjuk az egeret. Nem kell mást csinálnunk, mint az eredeti elemet az új elem helyére tesszük, így a Store-ban az rekordok rendezése pont ugyanazt az eredményt adja, mintha az egérrel áthelyeznénk az adott elemeket.
Első lépésben létrehozunk egy plugin-t, amivel a DataView-hoz hozzáadjuk az rendezhetőséget:
Ext.namespace("Ext.ux.plugins");
Ext.ux.plugins.SortableDataView = {
init: function(view) {
view.on('render', function() {
view.addEvents('serialise');
Ext.apply(new Ext.dd.DragDrop(view.el), {
// itt indul a folyamat, megkeressük, hogy melyik rekordon nyomtuk le az egeret:
onMouseDown: function(e) {
try {
this.dragData = null;
var id = view.indexOf(e.getTarget(view.itemSelector));
if (id !== -1) {
this.dragData = {orig: id, last: id, record: view.store.getAt(id)};
}
} catch (error) {}
},
// mozgatás kezdete, a kiválasztott elemhez (ha van) hozzáadjuk a megfelelő osztályt
startDrag: function() {
if (!this.dragData) {return;}
Ext.fly(view.getNode(this.dragData.orig)).addClass(view.dragCls);
},
// a lényegi rész, lekérjük, hogy melyik elem felett vagyunk, és a kiválasztott elemet annak a helyére szúrjuk
onDrag: function(e) {
if (!this.dragData) {return;}
try {
var id = view.indexOf(e.getTarget(view.itemSelector));
if (id !== -1 && id !== this.dragData.last) {
this.dragData.last = id;
view.store.remove(this.dragData.record);
view.store.insert(id, [this.dragData.record]);
Ext.fly(view.getNode(id)).addClass(view.dragCls);
}
} catch (error) {}
},
// folyamat vége, a dragCls-t leszedjük a kiválasztott elemről, továbbá az esemény elküldése
endDrag: function() {
if (!this.dragData) {return;}
Ext.fly(view.getNode(this.dragData.last)).removeClass(view.dragCls);
if (this.dragData.orig !== this.dragData.last) {
view.fireEvent('serialise', view, this.dragData.orig, this.dragData.last);
}
}
});
});
}
};
Második lépés, ennek a használata:
store: new Ext.data.SimpleStore({
fields: ['item'],
data: ...
}),
tpl: '<tpl for="."><div class="item">{item}<\/div><\/tpl>',
overClass: 'x-view-over',
dragCls: 'x-view-drag',
itemSelector: 'div.item',
plugins: Ext.ux.plugins.SortableDataView,
listeners: {
serialise: ...
}
});