Hi,
I have a problem with my implementation of Drag and Drop lists. Particulary I have 3 scrollable divs, which represent lists. The divs contain "LI s" which represent particular units.
Code (ddHeader.php5) Header:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs" lang="cs">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="content-language" content="cz" />
<meta name="author" content="Mojmir Chabron"/>
<link rel="stylesheet" type="text/css" href="ddCss.css"/>
<script language="JavaScript" type="text/javascript" src="js/coordinates.js"></script>
<script language="JavaScript" type="text/javascript" src="js/drag.js"></script>
<script language="JavaScript" type="text/javascript" src="js/dragdrop.js"></script>
<script language="JavaScript" type="text/javascript">
<!--
function onDrop(){
var data = DragDrop.serData('list');
}
window.onload = function() {
var list = document.getElementById("left_col"); ;
DragDrop.makeListContainer( list, 'list' );
list.onDragOver = function() { this.style["background"] = "#F90"; this.style["position"] = "relative"; };
list.onDragOut = function() {this.style["background"] = "none"; };
list.onDragDrop = function() {onDrop(); };
list = document.getElementById("center");
DragDrop.makeListContainer( list, 'list' );
list.onDragOver = function() { this.style["background"] = "#F90"; this.style["position"] = "relative"; };
list.onDragOut = function() {this.style["background"] = "none"; };
list.onDragDrop = function() {onDrop(); };
list = document.getElementById("right_col");
DragDrop.makeListContainer( list, 'list' );
list.onDragOver = function() { this.style["background"] = "#F90"; this.style["position"] = "relative"; };
list.onDragOut = function() {this.style["background"] = "none"; };
list.onDragDrop = function() {onDrop(); };
};
//-->
</script>
<title>3 scrollable div with li's - scroll problem</title>
</head>
Code (index.php5) Main page:
<?php
require ("ddHeader.php5");
?>
<!-- Body -->
<body>
<table id="main_table" border="0" align="center">
<tr bgcolor="#6699DD">
<td valign="top" colspan="3" align="left" height="50">
<h1> 3 scrollable div's with li's nodes - scroll problem</h1>
<td>
</tr>
<tr>
<td valign="top" id="dad">
<h3>List1</h3></br>
<div class='scroll' id='scroll1'>
<ul id='left_col' class='sortable boxy'>
<li id="0">One</li>
<li id="1">One</li>
<li id="2">One</li>
<li id="3">One</li>
<li id="4">One</li>
<li id="5">One</li>
<li id="6">One</li>
<li id="7">One</li>
<li id="8">One</li>
<li id="9">One</li>
<li id="10">One</li>
<li id="11">One</li>
<li id="12">One</li>
<li id="13">One</li>
<li id="14">One</li>
<li id="15">One</li>
<li id="16">One</li>
<li id="17">One</li>
<li id="18">One</li>
<li id="19">One</li>
<li id="20">One</li>
<li id="60">One</li>
<li id="61">One</li>
<li id="62">One</li>
<li id="63">One</li>
<li id="64">One</li>
<li id="65">One</li>
<li id="66">One</li>
<li id="67">One</li>
<li id="68">One</li>
<li id="69">One</li>
<li id="70">One</li>
<li id="71">One</li>
<li id="72">One</li>
<li id="73">One</li>
<li id="74">One</li>
<li id="75">One</li>
<li id="76">One</li>
<li id="77">One</li>
<li id="78">One</li>
<li id="79">One</li>
<li id="80">One</li>
</ul>
</div>
</td>
<td valign="top" id="dad">
<h3>List2</h3></br>
<div class='scroll' id='scroll2'>
<ul id='center' class='sortable boxy'>
<li id="21">One</li>
<li id="22">One</li>
<li id="23">One</li>
<li id="24">One</li>
<li id="25">One</li>
<li id="26">One</li>
<li id="27">One</li>
<li id="28">One</li>
<li id="29">One</li>
<li id="30">One</li>
</ul>
</div>
</td>
<td valign="top" id="dad">
<h3>List3</h3></br>
<div class='scroll' id='scroll3'>
<ul id='right_col' class='sortable boxy'>
<li id="42">One</li>
<li id="43">One</li>
<li id="44">One</li>
<li id="45">One</li>
<li id="46">One</li>
<li id="47">One</li>
<li id="48">One</li>
<li id="49">One</li>
<li id="50">One</li>
<li id="51">One</li>
<li id="52">One</li>
<li id="53">One</li>
<li id="54">One</li>
<li id="55">One</li>
<li id="56">One</li>
<li id="57">One</li>
<li id="58">One</li>
<li id="59">One</li>
<li id="50">One</li>
<li id="51">One</li>
</ul>
</div><br />
</td>
</tr>
<tr>
<td valign="top" bgcolor="#3366EE"></td>
<td valign="top" bgcolor="#3366EE"></td>
<td valign="center" bgcolor="#3366EE" align="right" height="30">
</tr>
</table>
</body>
<!-- End_Body -->
PROBLEM with scrolls:
>>>>>>>>>>>>>>>>>>>>>>>>>>
when I have scroll of the div in lower position and I try to drag the item (li tag) in order to drop it into another div, that item is not at position of the mouse pointer but there is a space which is caused by high of the scroll. You can try it online http://ufosite.ic.cz/
>>>>>>>>>>>>>>>>>>>>>>>>>>
Code (dragdrop.js):
var DragDrop = {
firstContainer : null,
lastContainer : null,
parent_id : null,
parent_group : null,
/////// we need made containers with 'li' nodes /////////
makeListContainer : function(list, group) {
if (this.firstContainer == null) {
this.firstContainer = this.lastContainer = list;
list.previousContainer = null;
list.nextContainer = null;
} else {
list.previousContainer = this.lastContainer;
list.nextContainer = null;
this.lastContainer.nextContainer = list;
this.lastContainer = list;
}
list.onDragOver = new Function();
list.onDragOut = new Function();
list.onDragDrop = new Function();
list.group = group;
//// we get list 'ul' with 'li' nodes
var items = list.getElementsByTagName("li");
//// lets make every 'li' item dgabale
for (var i = 0; i < items.length; i++) {
DragDrop.makeItemDragable(items[i]);
}
},
serData : function ( group, theid ) {
var container = DragDrop.firstContainer;
var j = 0;
var string = "";
while (container != null) {
if(theid != null && container.id != theid){
container = container.nextContainer;
continue;
}
if(group != null && container.group != group){
container = container.nextContainer;
continue;
}
j ++;
if(j > 1){
string += ":";
}
//string += container.id;
var items = container.getElementsByTagName("li");
string += "(";
for (var i = 0; i < items.length; i++) {
if(i > 0)
{
string += ",";
}
string += items[i].id;
}
string += ")";
container = container.nextContainer;
}
return string;
},
makeItemDragable : function(item) {
Drag.makeDraggable(item);
item.setDragThreshold(2);
item.isOutside = false;
item.onDragStart = DragDrop.onDragStart;
item.onDrag = DragDrop.onDrag;
item.onDragEnd = DragDrop.onDragEnd;
},
onDragStart : function(nwPosition, sePosition, nwOffset, seOffset) {
var container = DragDrop.firstContainer;
while (container != null) {
container.northwest = Coordinates.northwestOffset( container, true );
container.southeast = Coordinates.southeastOffset( container, true );
container = container.nextContainer;
}
this.parentNode.onDragOver();
parent_id = this.parentNode.id;
parent_group = this.parentNode.group;
},
onDrag : function(nwPosition, sePosition, nwOffset, seOffset) {
if (this.isOutside) {
var container = DragDrop.firstContainer;
while (container != null) {
if ((nwOffset.inside( container.northwest, container.southeast ) ||
seOffset.inside( container.northwest, container.southeast )) && container.group == parent_group) {
container.onDragOver();
this.isOutside = false;
var tempParent = this.parentNode;
tempParent.removeChild( this );
container.appendChild( this );
tempParent.parentNode.removeChild( tempParent );
break;
}
container = container.nextContainer;
}
if (this.isOutside)
return;
} else if (!(nwOffset.inside( this.parentNode.northwest, this.parentNode.southeast ) ||
seOffset.inside( this.parentNode.northwest, this.parentNode.southeast ))) {
this.parentNode.onDragOut();
this.isOutside = true;
var container = DragDrop.firstContainer;
while (container != null) {
if ((nwOffset.inside( container.northwest, container.southeast ) ||
seOffset.inside( container.northwest, container.southeast )) && container.group == parent_group) {
container.onDragOver();
this.isOutside = false;
this.parentNode.removeChild( this );
container.appendChild( this );
break;
}
container = container.nextContainer;
}
if (this.isOutside) {
var tempParent = this.parentNode.cloneNode( false );
this.parentNode.removeChild( this );
tempParent.appendChild( this );
tempParent.style.border = 0;
document.getElementsByTagName( "body" ).item(0).appendChild( tempParent );
return;
}
}
var parent = this.parentNode;
var item = this;
var next = DragUtils.nextItem(item);
while (next != null && this.offsetTop >= next.offsetTop - 2) {
var item = next;
var next = DragUtils.nextItem(item);
}
if (this != item) {
DragUtils.swap(this, next);
return;
}
var item = this;
var previous = DragUtils.previousItem(item);
while (previous != null && this.offsetTop <= previous.offsetTop + 2) {
var item = previous;
var previous = DragUtils.previousItem(item);
}
if (this != item) {
DragUtils.swap(this, item);
return;
}
},
onDragEnd : function(nwPosition, sePosition, nwOffset, seOffset) {
if (this.isOutside) {
var container = DragDrop.firstContainer;
while (container != null) {
if(container.id == parent_id){
break;
}
container = container.nextContainer;
}
this.isOutside = false;
this.parentNode.removeChild( this );
container.appendChild( this );
this.style["top"] = "0px";
this.style["left"] = "0px";
return;
}
this.parentNode.onDragOut();
this.parentNode.onDragDrop();
this.style["top"] = "0px";
this.style["left"] = "0px";
}
};
var DragUtils = {
swap : function(item1, item2) {
var parent = item1.parentNode;
parent.removeChild(item1);
parent.insertBefore(item1, item2);
item1.style["top"] = "0px";
item1.style["left"] = "0px";
},
nextItem : function(item) {
var sibling = item.nextSibling;
while (sibling != null) {
if (sibling.nodeName == item.nodeName) return sibling;
sibling = sibling.nextSibling;
}
return null;
},
previousItem : function(item) {
var sibling = item.previousSibling;
while (sibling != null) {
if (sibling.nodeName == item.nodeName) return sibling;
sibling = sibling.previousSibling;
}
return null;
}
};
Code (drag.js):
var Drag = {
BIG_Z_INDEX : 10000,
group : null,
isDragging : false,
makeDraggable : function(group) {
group.handle = group;
group.handle.group = group;
group.minX = null;
group.minY = null;
group.maxX = null;
group.maxY = null;
group.threshold = 0;
group.thresholdY = 0;
group.thresholdX = 0;
group.onDragStart = new Function();
group.onDragEnd = new Function();
group.onDrag = new Function();
group.setDragHandle = Drag.setDragHandle;
group.setDragThreshold = Drag.setDragThreshold;
group.setDragThresholdX = Drag.setDragThresholdX;
group.setDragThresholdY = Drag.setDragThresholdY;
group.constrain = Drag.constrain;
group.constrainVertical = Drag.constrainVertical;
group.constrainHorizontal = Drag.constrainHorizontal;
group.onmousedown = Drag.onMouseDown;
},
constrainVertical : function() {
var nwOffset = Coordinates.northwestOffset(this, true);
this.minX = nwOffset.x;
this.maxX = nwOffset.x;
},
constrainHorizontal : function() {
var nwOffset = Coordinates.northwestOffset(this, true);
this.minY = nwOffset.y;
this.maxY = nwOffset.y;
},
constrain : function(nwPosition, sePosition) {
this.minX = nwPosition.x;
this.minY = nwPosition.y;
this.maxX = sePosition.x;
this.maxY = sePosition.y;
},
setDragHandle : function(handle){
if(handle && handle != null){
this.handle = handle;
} else {
this.handle = this;
}
this.handle.group = this;
this.onmousedown = null;
this.handle.onmousedown = Drag.onMouseDown;
},
setDragThreshold : function(threshold) {
if (isNaN(parseInt(threshold))) return;
this.threshold = threshold;
},
setDragThresholdX : function(threshold) {
if (isNaN(parseInt(threshold))) return;
this.thresholdX = threshold;
},
setDragThresholdY : function(threshold) {
if (isNaN(parseInt(threshold))) return;
this.thresholdY = threshold;
},
onMouseDown : function(event){
var targ;
if (!event){
var event = window.event;
}
if (event.target){
targ = event.target;
}
else if (event.srcElement){
targ = event.srcElement;
}
if (targ.nodeType == 3){ // defeat Safari bug
targ = targ.parentNode;
}
var tname;
tname = targ.tagName;
if(tname == "LI"){
event = Drag.fixEvent(event);
Drag.group = this.group;
var group = this.group;
var mouse = event.windowCoordinate;
var nwOffset = Coordinates.northwestOffset(group, true);
var seOffset = Coordinates.southeastOffset(group, true);
var nwPosition = Coordinates.northwestPosition(group);
var sePosition = Coordinates.southeastPosition(group);
group.originalOpacity = group.style.opacity;
group.originalZIndex = group.style.zIndex;
group.initialWindowCoordinate = mouse;
group.dragCoordinate = mouse;
Drag.showStatus(mouse, nwPosition, sePosition, nwOffset, seOffset);
group.onDragStart(nwPosition, sePosition, nwOffset, seOffset);
if (group.minX != null)
group.minMouseX = mouse.x - nwPosition.x + group.minX - nwOffset.x;
if (group.maxX != null)
group.maxMouseX = group.minMouseX + group.maxX - group.minX;
if (group.minY != null)
group.minMouseY = mouse.y - nwPosition.y + group.minY - nwOffset.y;
if (group.maxY != null)
group.maxMouseY = group.minMouseY + group.maxY - group.minY;
group.mouseMin = new Coordinate(group.minMouseX, group.minMouseY);
group.mouseMax = new Coordinate(group.maxMouseX, group.maxMouseY);
document.onmousemove = Drag.onMouseMove;
document.onmouseup = Drag.onMouseUp;
return false;
} else {
return true;
}
},
// Useing it for debugging mouse movement
showStatus : function(mouse, nwPosition, sePosition, nwOffset, seOffset) {
window.status =
"mouse: " + mouse.toString() + " " +
"NW pos: " + nwPosition.toString() + " " +
"SE pos: " + sePosition.toString() + " " +
"NW offset: " + nwOffset.toString() + " " +
"SE offset: " + seOffset.toString();
},
onMouseMove : function(event) {
event = Drag.fixEvent(event);
var group = Drag.group;
var mouse = event.windowCoordinate;
var nwOffset = Coordinates.northwestOffset(group, true);
var nwPosition = Coordinates.northwestPosition(group);
var sePosition = Coordinates.southeastPosition(group);
var seOffset = Coordinates.southeastOffset(group, true);
Drag.showStatus(mouse, nwPosition, sePosition, nwOffset, seOffset);
if (!Drag.isDragging) {
if (group.threshold > 0) {
var distance = group.initialWindowCoordinate.distance(mouse);
if (distance < group.threshold) return true;
} else if (group.thresholdY > 0) {
var deltaY = Math.abs(group.initialWindowCoordinate.y - mouse.y);
if (deltaY < group.thresholdY) return true;
} else if (group.thresholdX > 0) {
var deltaX = Math.abs(group.initialWindowCoordinate.x - mouse.x);
if (deltaX < group.thresholdX) return true;
}
Drag.isDragging = true;
group.style["zIndex"] = Drag.BIG_Z_INDEX;
group.style["opacity"] = 0.85;
}
var adjusted = mouse.constrain(group.mouseMin, group.mouseMax);
nwPosition = nwPosition.plus(adjusted.minus(group.dragCoordinate));
nwPosition.reposition(group);
group.dragCoordinate = adjusted;
var offsetBefore = Coordinates.northwestOffset(group, true);
group.onDrag(nwPosition, sePosition, nwOffset, seOffset);
var offsetAfter = Coordinates.northwestOffset(group, true);
if (!offsetBefore.equals(offsetAfter)) {
var errorDelta = offsetBefore.minus(offsetAfter);
nwPosition = Coordinates.northwestPosition(group).plus(errorDelta);
nwPosition.reposition(group);
}
return false;
},
onMouseUp : function(event) {
event = Drag.fixEvent(event);
var group = Drag.group;
var mouse = event.windowCoordinate;
var nwOffset = Coordinates.northwestOffset(group, true);
var nwPosition = Coordinates.northwestPosition(group);
var sePosition = Coordinates.southeastPosition(group);
var seOffset = Coordinates.southeastOffset(group, true);
document.onmousemove = null;
document.onmouseup = null;
group.onDragEnd(nwPosition, sePosition, nwOffset, seOffset);
if (Drag.isDragging) {
group.style["zIndex"] = group.originalZIndex;
group.style["opacity"] = group.originalOpacity;
}
Drag.group = null;
Drag.isDragging = false;
return false;
},
fixEvent : function(event) {
if (typeof event == 'undefined') event = window.event;
Coordinates.fixEvent(event);
return event;
}
};
Code (coordinates.js):
var Coordinates = {
ORIGIN : new Coordinate(0, 0),
northwestPosition : function(element) {
var x = parseInt(element.style.left);
var y = parseInt(element.style.top);
return new Coordinate(isNaN(x) ? 0 : x, isNaN(y) ? 0 : y);
},
southeastPosition : function(element) {
return Coordinates.northwestPosition(element).plus(
new Coordinate(element.offsetWidth, element.offsetHeight));
},
northwestOffset : function(element, isRecursive) {
var div = document.getElementById("scroll1");
var offset = new Coordinate(element.offsetLeft, element.offsetTop);
if (!isRecursive) return offset;
var parent = element.offsetParent;
while(parent){
offset = offset.plus(new Coordinate(parent.offsetLeft, parent.offsetTop));
parent = parent.offsetParent;
}
return offset;
},
southeastOffset : function(element, isRecursive) {
return Coordinates.northwestOffset(element, isRecursive).plus(
new Coordinate(element.offsetWidth, element.offsetHeight));
},
fixEvent : function(event) {
event.windowCoordinate = new Coordinate(event.clientX, event.clientY);
}
};
function Coordinate(x, y) {
this.x = x;
this.y = y;
}
Coordinate.prototype.toString = function() {
return "(" + this.x + "," + this.y + ")";
}
Coordinate.prototype.plus = function(that) {
return new Coordinate(this.x + that.x, this.y + that.y);
}
Coordinate.prototype.minus = function(that) {
return new Coordinate(this.x - that.x, this.y - that.y);
}
Coordinate.prototype.distance = function(that) {
var deltaX = this.x - that.x;
var deltaY = this.y - that.y;
return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
}
Coordinate.prototype.max = function(that) {
var x = Math.max(this.x, that.x);
var y = Math.max(this.y, that.y);
return new Coordinate(x, y);
}
Coordinate.prototype.constrain = function(min, max) {
if (min.x > max.x || min.y > max.y) return this;
var x = this.x;
var y = this.y;
if (min.x != null) x = Math.max(x, min.x);
if (max.x != null) x = Math.min(x, max.x);
if (min.y != null) y = Math.max(y, min.y);
if (max.y != null) y = Math.min(y, max.y);
return new Coordinate(x, y);
}
Coordinate.prototype.reposition = function(element) {
element.style["top"] = this.y + "px";
element.style["left"] = this.x + "px";
}
Coordinate.prototype.equals = function(that) {
if (this == that) return true;
if (!that || that == null) return false;
return this.x == that.x && this.y == that.y;
}
Coordinate.prototype.inside = function(northwest, southeast) {
if ((this.x >= northwest.x) && (this.x <= southeast.x) &&
(this.y >= northwest.y) && (this.y <= southeast.y)) {
return true;
}
return false;
}
NEED HELP:
>>>>>>>>>>>>>>>>>>>
I read some forums about that problem but I haven't solved it yet. Please try to help me...
>>>>>>>>>>>>>>>>>>>