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"> </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"> </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"> </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"> </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"> </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
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"> </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"> </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"> </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"> </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"> </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