PDA

View Full Version : Drag and drop - Any help appreciated!



Rowan
6 Jun 2007, 7:36 AM
I'm having some major issues with drag and drop - Basically im trying to recreate the scriptaculous / YUI method of DnD where a node is inserted before or after the node its dragged on to based on mouse movement up or down.

This bit I will say is all working how I would expect it to but... I cannot for the life of me work out how to add a node to a container that hasn't got any existing nodes. Ive looked through the API as much as is humanly possible and tried a few tricks to try to get it working, however I'm stuck.

Firstly I tried to initialise the former parent of a node as a drop target if it had no children (this code can be run by un-commenting the lines starting with - dragdropzone.notifyDrop=function(dd, e, data) ) - This didnt really work correctly so I tried another way.

This was to add in an oncontainerover method to the original Dropzone so that It would check e.target to see if it was a container or a node. This really hasn't worked as I'd have hoped but just cant work out the right way to make the empty containers use the appendTo method on them.

Any ideas welcome and greatly appreciated - If I can get a simple working example of this I can completely eradicate YUI from my app.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Untitled</title>

<script type="text/javascript" src="../../yui/build/yahoo/yahoo-min.js" ></script>
<script type="text/javascript" src="../../yui/build/event/event-min.js" ></script>
<script type="text/javascript" src="../../yui/build/dom/dom-min.js"></script>
<script type="text/javascript" src="../../yui/build/logger/logger-min.js"></script>
<script type="text/javascript" src="../../yui/build/container/container.js"></script>
<script type="text/javascript" src="../../yui/build/dragdrop/dragdrop-debug.js" ></script>
<script type="text/javascript" src="../../yui/build/animation/animation-min.js"></script>

<script type="text/javascript" src="EXT/adapter/yui/ext-yui-adapter.js"></script> <!-- ENDLIBS -->
<script type="text/javascript" src="EXT/ext-all.js"></script>

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

.container {
width:400px;
padding:0;
margin:0;
background:yellow;
min-height:40px;
}
.article {
width:400px;
padding-top:20px;
}

</style>

</head>
<body>
<div id="dragzone" class="container">
<div class="article" id="article_76947200">
<h1>Im number one</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
<div class="article" id="article_78787787">
<h1>Im number two</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
<div class="article" id="article_7474747474">
<h1>and im three</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
</div>
<hr>
<div id="dragzone2" class="container">
<div class="article" id="article_7474787874">
<h1>and second column</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
</div>


<hr>
<div id="dragzone3" class="container">
<div class="article" id="article_7477575741">
<h1>and new column</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
</div>

<script>

//$$ is shorthand for YAHOO.dom.getElementsByClassName
//$ is short for YAHOO.dom.get

var dragDrop = function(){

createDropZone = function(zone){
var dragzone = new Ext.dd.DragZone(zone)
var dragdropzone=new Ext.dd.DropZone(zone);

var drags = $$('article', 'div', zone);

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

dragzone.onBeforeDrag = function(data, e){
//console.log("dropped " + data.ddel.id, data);
var srcEl = Ext.get(data.ddel);
previousParent = srcEl.dom.parentNode;
}

dragzone.onDrag = function(data,e){
var srcEl = Ext.get(data.ddel);

}

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;
//console.log(n.ddel);
var destEl = Ext.get(n.ddel);
var srcEl = Ext.get(data.ddel);
srcEl.setStyle('visibility', 'hidden');

//see if this exists

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

//this code is a bit ropey but cant find a better way to do this just yet

dragdropzone.onContainerOver = function(source,e,data){
var destEl = Ext.get(e.target);
var srcEl = Ext.get(data.ddel);
if(!destEl.findParent('div.article') && !destEl.is('div.article')) {
srcEl.appendTo(destEl);
}
return true;
}

//first code that i tried, sets the empty area as a new drag zone with different properties but doesn't work correctly. When executing this you can then insert the node into the middle of other nodes - I think because it uses e.target / appendTo - I think this is the wrong method to use though hence the removal

dragdropzone.notifyDrop=function(dd, e, data){
//if(previousParent.getElementsByTagName('div').length===0){
//Ext.dd.Registry.unregister(previousParent);
//createDropTarget(previousParent);
//}
}
}

createDropTarget = function(el){
alert('making');
var hitZone;
var dropzone = new Ext.dd.DropZone(el);
//Ext.dd.Registry.register(el);

dropzone.notifyEnter = function(dd, e, data){
//alert('banana');
console.log(dd);
console.log(e);
hitZone = e.target;
var destEl = Ext.get(hitZone);
var srcEl = Ext.get(data.ddel);
srcEl.appendTo(destEl);
}

dropzone.notifyDrop = function(dd, e, data){
alert('destroying');
Ext.dd.Registry.unregister(hitZone);
dropzone.unreg();
createDropZone(hitZone);
}
//alert(el.id);
}

return {

init : function() {
var previousParent;
var zones = $$('container');

for(var i=0; i<zones.length; i++){
createDropZone(zones[i]);
}
}
}
}();

dragDrop.init();

</script>


</body>
</html>


Thanks guys, Rowan

Rowan
8 Jun 2007, 12:19 AM
Anyone?

Rowan
8 Jun 2007, 3:24 AM
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Drag and drop lists and divs</title>
<script type="text/javascript" src="EXT/adapter/yui/yui-utilities.js" ></script>
<script type="text/javascript" src="EXT/adapter/yui/ext-yui-adapter.js"></script> <!-- ENDLIBS -->
<script type="text/javascript" src="EXT/ext-all.js"></script>


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

<style>

body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,img,input,textarea,p,blockquote,th,td{
margin:0;
padding:0;
border:0;
font-family:arial,helvetica,clean,sans-serif;
}

h1,h2,h3,h4,h5,h6 {
font-weight:normal;
}

div.container {
width:408px;
padding:0;
margin:0;
background:yellow;
min-height:40px;
float:left;
border:1px solid #ccc;
background:#dfdfdf;
margin:20px;
}
div.article {
width:400px;
padding-top:20px;
background:white;
padding:4px;
}

.imgRight {
float:right;
margin:0 0 4px 4px;
background:#ccc;
border:1px solid black;
}

.article h1 {
font-size:1.6em;
margin-bottom:0.25em;
}

.article p {
min-height: 50px;
white-space:normal !important;
}

ul.container {
width:400px;
border:1px solid #ccc;
background:#dfdfdf;
float:left;
margin:20px;
}

ul.container li {
background:white;
}

div.clear {
clear:both;
}

</style>

</head>
<body>

<ul class="container">
<li>Can you drag me 1</li>
<li>Can you drag me 2</li>
<li>Can you drag me 3</li>
<li>Can you drag me 4</li>
<li>Can you drag me 5</li>
</ul>

<ul class="container">
<li>Can you drag me 6</li>
<li>Can you drag me 7</li>
<li>Can you drag me 8</li>
<li>Can you drag me 9</li>
<li>Can you drag me 10</li>
</ul>

<div class="clear">&nbsp;</div>

<div id="dragzone" class="container">
<div class="article draggable" id="article_76947200">
<h1>Im number one</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
<div class="article draggable" id="article_78787787">
<h1>Im number two</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
<div class="article draggable" id="article_7474747474">
<h1>and im three</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
</div>

<div id="dragzone2" class="container">
<div class="article draggable" id="article_7474787874">
<h1>and second column</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
</div>

<div class="clear">&nbsp;</div>

<hr>
<div id="dragzone3" class="container">
<div class="article draggable" id="article_7477575741">
<h1>and new column</h1>
<p><img src="spacer.gif" width="60" height="60" alt="Drag your story here" class="imgRight" />Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sit amet metus. Nunc quam elit, posuere nec, auctor in, rhoncus quis, dui.</p>
<div class="clear">&nbsp;</div>
</div>
</div>

<script>

var Dragdrop = function(){

createDropZone = function(zone){
var dragzone = new Ext.dd.DragZone(zone);
var dragdropzone = new Ext.dd.DropZone(zone);
var DDM = Ext.dd.DragDropMgr;

var drags;
var mode;

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

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

dragdropzone.notifyEnter = function(source, e, data){
if(!zone.getElementsByTagName('div').length > 0){
//alert('hello');
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;
//console.log(n.ddel);
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 list 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);
}
}
}
}

}

return {

init : function() {
var previousParent;
var zones = Ext.query('.container', 'body');
for(var i=0; i<zones.length; i++){
createDropZone(zones[i]);
}
}
}

}();

Ext.onReady(function(){
Dragdrop.init();
})

</script>


</body>
</html>

medusadelft
30 Jun 2007, 1:14 PM
Great piece of code Rowan!
I was just looking for something like this. Thanks for sharing.

Unfortunately, in FF1.5 & IE6, the columns are not draggable.
The lines 'you can drag me' are, but shows the 'drag not allowed' (red icon) on drag in stead of the green icon (drag allowed), but I can still drop the line and it is sorted. Any fixes for this?

Maurice.

jsakalos
2 Jul 2007, 4:25 PM
Have you seen this (http://aariadne.com/accordion-preview)?

I've chosen to override Ext.dd.DragProxy class and handle the insertions/movements of nodes (divs) within a container or out and back into it.

The source code is available on that page - it's at the (almost) bottom of Ext.ux.Accordion.js