PDA

View Full Version : Sortable Lists?



keithpitt
30 Apr 2007, 11:10 PM
Gday guys,

Before I begin, congrats on the very awesome library.

Im implementing a sortable list into an application I'm creating. Just a bunch of DIV's that can be dragged & dropped into order. I'm using Ext with the prototype adapter. Should I be using script.aculo.us to do this? Or is there a Ext equivalent I should be using?

Thanks is advance.

Keith

dfenwick
1 May 2007, 12:16 AM
You could use the MixedCollection class for this. You could also extend the MixedCollection class to provide your own rendering for your divs. You could also implement a new class that uses a MixedCollection class for your data and then provides its own rendering engine. You could also use a tree with a hidden root node and then apply a TreeSorter to the tree.

If you're referring to sortable as in being able to be reordered, then the tree is your friend. Remove the TreeSorter from it and all of the drag/drop is builtin. You don't have to deal with anything at all. Just add a bunch of TreeNode objects to it and you're done.

brian.moeskau
1 May 2007, 12:34 AM
FYI, if you're after simple list sorting, then dfenwick's advice may work (I haven't tried it , but it sounds good :) ). If you're after multi-column panel sorting (like for example a portal layout) that is something that we're currently working on for an upcoming release... ;)

keithpitt
1 May 2007, 1:22 AM
The stuff Im sorting will only every have 5-10 records. Its only very simple sorting. I did consider using a tree for the sorting, but I thought it would be a little over-kill for what im trying to achieve. Will Ext ever support simple sorting? Is it something I can make a submit to Ext? Or should I just use the script.aculo.us stuff?

brian.moeskau
1 May 2007, 2:11 AM
Ext will likely support simple sorting similar to script.aculo.us and jQuery "sortables," although I can't guarantee when that might happen. But based on some of the other things we're working on, simple sorting should not be very difficult to add. But as of today, you'd need to either implement it yourself (you could look at extending DragSource and DropTarget for example, or using a tree as suggested), or you could use another library (assuming you're not concerned with download size).

oshcha
21 Jul 2007, 12:39 AM
Ext will likely support simple sorting similar to script.aculo.us and jQuery "sortables," although I can't guarantee when that might happen. But based on some of the other things we're working on, simple sorting should not be very difficult to add. But as of today, you'd need to either implement it yourself (you could look at extending DragSource and DropTarget for example, or using a tree as suggested), or you could use another library (assuming you're not concerned with download size).

Any progress with this one? ;)

brian.moeskau
21 Jul 2007, 1:48 AM
Nope. It's not currently planned at the moment.

willydee
27 Jul 2007, 7:12 AM
That's a pity. A sortable list with sophisticated DD implementation similar to TreePanel would be just great. At the moment I'm kinda "degrading" TreePanels and TreeNodes for that purpose, but a store bound solution would be way better than crippling a full-blown tree.
Count my vote for linear sortable lists.

brian.moeskau
27 Jul 2007, 8:36 AM
Could this help?

http://extjs.com/forum/showthread.php?t=9629

willydee
28 Jul 2007, 4:24 PM
Possibly yes. I discovered Animal's post just yesterday. Will have a look into it.

tm8747a
4 Nov 2007, 6:33 PM
I found some code by Rowan in this thread: http://extjs.com/forum/showthread.php?t=7992

It pretty much does what I need for sortables, but I'm having problems implementing something to take action on drop (essentially, serialize and do an Ajax request). I just want the same action to fire any time there's a drop. Problem is, the only event that seems to fullfil my requirement is afterInvalidDrop set on a DragZone object. While this seems to work fine for my purposes, it seems a little weird. I would have thought that if I dropped on the container that afterInvalidDrop would not fire, since a DropZone gets defined. Or could it be that a DropZone only makes the child nodes droppable areas and not the container? If that's the case it would explain it, that would mean that there's never a valid drop because as soon as you drag an item over another, the item moves, so you're never dropping on top of another item. Any insight into that?

I'll include the code I have in case somebody finds it useful. The idea is to create a Sortable class so you can pass a container element's ID and a function to run onDrop that would receive as an argument an array of draggable items in the order they are after the drop. All credit goes to Rowan on this, I merely adapted the code he came up with that's in the thread I mentioned above.



Ext.namespace('Ext.ux');

Ext.ux.Sortable = function(container, onDrop) {
this.init(container, onDrop);
}

Ext.ux.Sortable.prototype = function() {

function init(zone, onUserDefinedDrop) {
this.zone = Ext.get(zone);
this.onUserDefinedDrop = onUserDefinedDrop;

zone = Ext.get(zone).dom;

var groupName = (zone.tagName === 'DIV') ? 'divs' : 'lists';
var drags;
var mode;

if(zone.tagName === 'UL' || zone.tagName === 'OL'){
mode = 'list';
drags = Ext.query('li', zone);
} else {
mode = 'div';
drags = Ext.query('.draggable', zone);
}

if (drags.length > 1) {
var dragzone = new Ext.dd.DragZone(zone, {ddGroup: groupName});
var dragdropzone = new Ext.dd.DropZone(zone, {ddGroup: groupName});

for(var i =0; i< drags.length; i++){
Ext.dd.Registry.register(drags[i]);
}

dragzone.afterInvalidDrop = onDrop.createDelegate(this);

dragdropzone.notifyEnter = function(source, e, data){
if(!zone.getElementsByTagName('div').length > 0){
var srcEl = Ext.get(data.ddel);
srcEl.appendTo(zone);
}
}

dragdropzone.onNodeOver=function(n, dd, e, data){
var y = e.getPageY();

if (y < this.lastY) {
this.goingUp = true;
} else if (y > this.lastY) {
this.goingUp = false;
}

this.lastY = y;
var destEl = Ext.get(n.ddel);
var srcEl = Ext.get(data.ddel);
srcEl.setStyle('visibility', 'hidden');

//see if this exists
if(mode === 'div'){
// We are only concerned with items, we ignore the dragover
// notifications for the list.
if (destEl.is('.draggable')) {
if (this.goingUp) {
// insert above
srcEl.insertBefore(destEl);
} else {
// insert below
srcEl.insertAfter(destEl);
}
}
} else if(mode === 'list') {
if (destEl.is('li')) {
if (this.goingUp) {
// insert above
srcEl.insertBefore(destEl);
} else {
// insert below
srcEl.insertAfter(destEl);
}
}
}
}

}
}

function onDrop(e, id) {
this.onUserDefinedDrop( this.zone.query('.draggable') );
}

return {
init: init
};
}();

Ext.onReady(function(){
new Ext.ux.Sortable('tbrk_sortable', function(items) {
console.log(items);
});
});

fangzhouxing
5 Nov 2007, 2:36 AM
hi,tm8747a,thanks for sharing code.

Can you convert it to Ext 2.0?

tm8747a
5 Nov 2007, 5:16 AM
@fangzhouxing,

I may eventually do that, but right now my app is running on Ext 1.1 so I need to concentrate on that. I'm not even sure this implementation is any good since I don't have a strong understanding of the Ext drag and drop classes, so I think it'll be a while for that. But it may not be that different in Ext 2.0, maybe it'll work, or if it doesn't it may require very little changes.

Rowan
29 Nov 2007, 3:44 AM
I think because my code uses the insertBefore and insertAfter method it isn't necessarily classed as a valid drop - you may need to move whatever function you are trying to fire.

It would probably be best to define a custom event for when the insert happens then make another listener to do something like

this.addEvent(
{
'insertLi' : true
}
)


in the function
insertBefore(XX)
this.fireEvent('insertLi');

then make a listener
this.on('insertLi',fireMyEvent);

I have only worked with Ext 1 so not sure if this will help for Ext 2.0 or not, im sure it should be similar to this though

dawesi
7 Jan 2008, 10:08 PM
bump

Rowan
15 Jun 2008, 1:20 PM
http://extjs.com/forum/showthread.php?t=29033

I made it as simple as possible to do this now, you can listen on events and create really simple lists.