PDA

View Full Version : Simple Drag&Drop Example


schmidetzki
02-23-2007, 06:44 PM
I experimented with the new Ext 1.0 drag&drop classes and analized how they work.
Perhaps this will help others to get started using Ext.dd.

There are two base classes Ext.dd.DragSource and Ext.dd.DropTarget.
Here is a simple example of how to use it:

<style>
.box{
width: 200;
border: solid black 1px;
padding:20px;
}
</style>

<div id="dragsource" class="box">Drag me</div>




<div id="droptarget" class="box">drop me</div>
<div class="box">but not here</div>

<script>
new Ext.dd.DragSource("dragsource", {dragData:{name: "Wolfgang"}});

var droptarget=new Ext.dd.DropTarget("droptarget");
droptarget.notifyDrop=function(dd, e, data){
console.log("dropped " + dd.id + " on dragtarget", data);
return true;
}
</script>
The advantage over basic YAHOO.dd is that you can implement a function notifyDrop() on the target what is more practical then to implement onDragDrop() on the dragsource.

The next step ist to user Ext.dd.DragZone and Ext.dd.DropZone.
These two classes makes it possible to use only one YAHOO.util.DDProxy but enabling D&D for a set of elements in one container element. This saves resources because a YAHOO.util.DDProxy object takes much memory in your client.
Here again is a simple example:

<div id="dragzone">
DragZone
<div id="dd1" class="box">Drag me</div>
<div id="dd2" class="box">Drag me too</div>
<div id="dd3" class="box">Drop only</div>
</div>


<div id="dropzone">
DropZone
<div id="drop" class="box">drop me</div>
<div id="nodrop" class="box">but not here</div>
</div>

<script>
new Ext.dd.DragZone("dragzone")
var dragdropzone=new Ext.dd.DropZone("dragzone");
Ext.dd.Registry.register("dd1", {name:"Wolfgang"});
Ext.dd.Registry.register("dd2", {name:"Schmidetzki"});
dragdropzone.onNodeDrop=function(target, dd, e, data){
console.log("dropped " + data.ddel.id + " on " + target.ddel.id, data);
return true;
}
var droponly=new Ext.dd.DropTarget("dd3");
droponly.notifyDrop=function(dd, e, data){
console.log("dd3: dropped " + data.ddel.id + " on dd3", data);
return true;
}

var dropzone=new Ext.dd.DropZone("dropzone", {});
dropzone.onNodeDrop=function(n, dd, e, data){
console.log(n, dd, e, data);
return false;
}
Ext.dd.Registry.register("drop");
</script>

Instead of defining mehtods for all DDSource- and DDTarget-Objects you define only one onNodeDrop() method for each target container.
The example uses two target container. The first is a DragZone and a DropZone, the second is a DropZone only.

To use DragZone and DropZone you have to "register" each drag- (and drop-) element using Ext.dd.Registry.register(). You may assign as data object during registration. This data is automaticaly passed to your onNodeDrop()-method.

What I don't understand however is, why the onNodeDrop() methode is called twice on a drop-target-only.
FireBug logges:

dd3: dropped dd1 on dd3 Object name=Wolfgang ddel=div#dd1.box
dd3: dropped dd1 on dd3 Object name=Wolfgang ddel=div#dd1.box

Bobafart
02-23-2007, 07:20 PM
I don't get it.. how do you figure this stuff out on your own?

what kind of programming experience do you have?

trbs
02-23-2007, 11:47 PM
thanks schmidetzki !

great example for people (like me) who want to start experimenting with DnD classes.

schmidetzki
02-24-2007, 05:29 AM
how do you figure this stuff out on your own?
You probably have to know how the basic YUI library handles d&d and already worked with this lib.

YUI knows two basic classes ddSource and ddTarget.
You can just instanciate those classes with "new" and the source element is draggable. To do something meaningfull with it however you either have to implement your own dd-source class derived form ddSource or just overwrite one or some of its methods.
The most important method to overwrite is onDragDrop() which is called when the source element has been dropped on a valid target.

The Ext-classes Ext.dd.DragSource does exactly this. It extends ddSource from the YUI-lib and overwrite the onDragDrop() method (and some more ...).
In onDragDrop() dd.DragSource does some internal things and than calls a method notifyDrop() on the Ext.dd.dropTarget object which again is thought to be overwritten by the user (same concept as YUI has).
The diffenrence to the YUI-concept is, that you have to overwrite a methode on the TARGET instead of the SOURCE (I impelemented this by myself several times in this way because normaly the target knows what to do when something is dropped on it. The source just carries some data the target needs to decide what to do ...).
dd.DragSource and dd.dropTarget can be used instead of the YUI classes. They just replaces them giving you more comfort.

If you have a lot of identically drag elements in your application (like the tree control has) you may create one dd.dragSource for each element. And it works. You waste resources however. That's where the dd.dragZone and dd.dropZone comes into play.

Instead of creating one dd.dragSource for each element you create one dd.dragZone and one dd.dropZone for the container of all those dragable elements:

Ext.dd.DropZone extends Ext.dd.DropTarget and - you may guess it - overwrites the notifyDrop() method for you. On notifyDrop() it does some internal things and calls a method onNodeDrop() (with the registered(!) dom-node of the dropped source as parameter)
Again: onNodeDrop() is thought to be overwritten by the user (have done this im my example code).

Wolfgang
03-09-2007, 04:46 PM
Hello Wolfgang,

Great example :D

I tried it and it has still the effect you described in alpha3

What I don't understand however is, why the onNodeDrop() methode is called twice on a drop-target-only.
FireBug logges:

dd3: dropped dd1 on dd3 Object name=Wolfgang ddel=div#dd1.box
dd3: dropped dd1 on dd3 Object name=Wolfgang ddel=div#dd1.box



Mabye this is a bug?

Regards

Wolfgang

jack.slocum
03-10-2007, 02:44 AM
Can anyone provide a test case that can be dropped in an example directory? I'd be happy to look into it.

Wolfgang
03-12-2007, 04:13 PM
Can anyone provide a test case that can be dropped in an example directory? I'd be happy to look into it.

I just took the example that "schmidetzki" provided in this thread and was able to get the result described.

Wolfgang
03-12-2007, 04:32 PM
Here a simple testbed (thanks to schmidetzki ) that can be dropped in the example folder that creates the problem in a3-rev2:
I put comments to the divs in question:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">


<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css">


<script type="text/javascript" src="../yui-utilities.js"></script>
<script type="text/javascript" src="../ext-yui-adapter.js"></script>
<script type="text/javascript" src="../ext-all-debug.js"></script>


<style>
.box{
width: 200;
border: solid black 1px;
padding:20px;
}
</style>
<body>
<h1>Example 1 - Simple</h1>
<div id="dragsource" class="box">Drag me</div>




<div id="droptarget" class="box">drop me</div>
<div class="box">but not here</div>

<script>
new Ext.dd.DragSource("dragsource", {dragData:{name: "Wolfgang"}});

var droptarget=new Ext.dd.DropTarget("droptarget");
droptarget.notifyDrop=function(dd, e, data){
console.log("dropped " + dd.id + " on dragtarget", data);
return true;
}
</script>

<h1>Example 2 Using container</h1>

<div id="dragzone">
DragZone
<div id="dd1" class="box">Drag me1 (cause 2 Events when dropped on (Drop only)</div>
<div id="dd2" class="box">Drag me too</div>
<div id="dd3" class="box">Drop only (get 2 events when dragged from (Drag me1)</div>
</div>


<div id="dropzone">
DropZone
<div id="drop" class="box">drop me</div>
<div id="nodrop" class="box">but not here</div>
</div>

<script>
new Ext.dd.DragZone("dragzone")
var dragdropzone=new Ext.dd.DropZone("dragzone");
Ext.dd.Registry.register("dd1", {name:"Wolfgang"});
Ext.dd.Registry.register("dd2", {name:"Schmidetzki"});
dragdropzone.onNodeDrop=function(target, dd, e, data){
console.log("dropped " + data.ddel.id + " on " + target.ddel.id, data);
return true;
}
var droponly=new Ext.dd.DropTarget("dd3");
droponly.notifyDrop=function(dd, e, data){
console.log("dd3: dropped " + data.ddel.id + " on dd3", data);
return true;
}

var dropzone=new Ext.dd.DropZone("dropzone", {});
dropzone.onNodeDrop=function(n, dd, e, data){
console.log(n, dd, e, data);
return false;
}
Ext.dd.Registry.register("drop");
</script>

</body>
</html>

alexandern
06-21-2008, 08:05 PM
I experimented with the new Ext 1.0 drag&drop classes and analized how they work.
Perhaps this will help others to get started using Ext.dd.
FireBug logges:


Would be nice to see this example using 2.1