/****************************************************************** 
 System:	Dynamic Dialogue (DD) System File
 File:		dd_drag_drop.js
 Title:		DD drag and drop scripts 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !! REMARK: Please do not change orders of Proto-definitions     !!
 !!         Check dependencies if you do                         !!
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
******************************************************************* 
 Description:  
 History		Version		Person	Remark
 15-03-2007		0.1		SAPR	Creation
*******************************************************************/

//******************************************************************
// A bit of config:
// Setting showStatusEnabled to true shows user the coordinates in
// the browsers' statusbar:  window.status
var showStatusEnabled = false;
//******************************************************************

var cloneNodeOnDrop = false;

//for correction when drag list is in scrollpane
var yScrollCorrection = 0;
var yScrollCorrectSwitch = false;

/*
 * Name		: Coordinates
 * Author	: SaPr
 * Description	: 
 */
var Coordinates = {
	ORIGIN : new Coordinate(0, 0),

	northwestPosition : function(element) {
		var x = parseInt(element.style.left);
		var y = parseInt(element.style.top);
	
		if(!isNaN(y) && yScrollCorrectSwitch){
			y = y - yScrollCorrection;
			yScrollCorrectSwitch = false;
			yScrollCorrection = 0;
		}
		
		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 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;
	},

	//element.offsetWidth and element.offsetHeight : actual widht and height of this element
	//For Southeast : add these values
	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;
}

// returns true of this point is inside specified box
Coordinate.prototype.inside = function(northwest, southeast) {
	//HAHO, if undefined return false;
	if(typeof(northwest) == 'undefined' || typeof(southeast) == 'undefined'){
		return false;
	}
	if ((this.x >= northwest.x) && (this.x <= southeast.x) &&
		(this.y >= northwest.y) && (this.y <= southeast.y)) {	
		return true;
	}
	return false;
}

/*
 * Name		: Drag
 * Author	: SaPr
 * Description	: 
 */
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();
		
		// TODO: use element.prototype.myFunc
		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;

//TODO : keep origins of dragged item, have to put it back if dropped where not allowed

		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) {
		event = Drag.fixEvent(event);
		//ignore drag if clickt on form element
		var targ;
		if(event.target){
			targ = event.target;
		} else if(event.srcElement){
			targ = event.srcElement;	
		}
		if(targ.tagName.toLowerCase() == "input" ||
		targ.tagName.toLowerCase() == "select" ){
			return;	
		}
		
		Drag.group = this.group;

		var group = this.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);

		group.originalOpacity = group.style.opacity;
		group.originalZIndex = window.getComputedStyle ? window.getComputedStyle(group,'').zIndex : group.currentStyle.zIndex;
		group.initialWindowCoordinate = mouse;

		// TODO: need a better name 
		group.dragCoordinate = mouse;

		Drag.showStatus(mouse, nwPosition, sePosition, nwOffset, seOffset);

		group.onDragStart(nwPosition, sePosition, nwOffset, seOffset);

		// TODO: need better constraint API
		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;
	},

	showStatus : function(mouse, nwPosition, sePosition, nwOffset, seOffset) {
		if(showStatusEnabled)
		{
			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.75;
		}

		// TODO: need better constraint API
		var adjusted = mouse.constrain(group.mouseMin, group.mouseMax);
		nwPosition = nwPosition.plus(adjusted.minus(group.dragCoordinate));
		nwPosition.reposition(group);
		group.dragCoordinate = adjusted;

		// once dragging has started, the position of the group
		// relative to the mouse should stay fixed.  They can get out
		// of sync if the DOM is manipulated while dragging, so we
		// correct the error here
		//
		// TODO: what we really want to do is find the offset from
		// our corner to the mouse coordinate and adjust to keep it
		// the same
		
		// changed to be recursive/use absolute offset for corrections
		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) {

//ToDo : Think of a fix if mouse-up outside browserwindow, while browsing.
//This now loses the dragged item. If this is the case: move item to original position
//		alert("mouseup");

		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) {
			// restoring zIndex before opacity avoids visual flicker in Firefox
			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;
	}
};

/*
 * Name		: DragDrop
 * Author	: SaPr
 * Description	: 
 */
var activeItem = null;
var DragDrop = {
	parentNodeID	: null,
	firstContainer	: null,
	lastContainer	: null,
	droppedItemID	: null,
	newParentID	: null,
	//HAHO
	droppedItem	: null,
	oldParent	: null,
	oldChildBefore	: null,

	makeListContainer : function(list) {
		// each container becomes a linked list node
		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;
		}
		
		// these functions are called when an item is draged over
		// a container or out of a container bounds.  onDragOut
		// is also called when the drag ends with an item having
		// been added to the container
		list.onDragOver = new Function();
		list.onDragOut = new Function();
		
	    	var items = list.getElementsByTagName( "li" );
		for (var i = 0; i < items.length; i++) {
			DragDrop.makeItemDragable(items[i]);
		}
	},

	makeItemDragable : function(item) {
		Drag.makeDraggable(item);
		item.setDragThreshold(5);
		
		// tracks if the item is currently outside all containers
		item.isOutside = false;
		
		item.onDragStart = DragDrop.onDragStart;
		item.onDrag = DragDrop.onDrag;
		item.onDragEnd = DragDrop.onDragEnd;
		//alert(item);
		/*noDragElements = item.getElementsByTagName("input");
		for(i = 0; i<noDragElements.length; i++){
			//alert(noDragElements[i]);	
			noDragElements[i].onMouseDown = function(){};
		}*/			
	},

	onDragStart : function(nwPosition, sePosition, nwOffset, seOffset) {
		yScrollCorrection = DyCoGetContentDivTop(this);

		this.departureNode = this.parentNode;
		DragDrop.oldParent = this.parentNode;
		DragDrop.oldChildBefore = this.nextSibling;

		// update all container bounds, since they may have changed
		// on a previous drag
		//
		// could be more smart about when to do this
		var container = DragDrop.firstContainer;
		while (container != null) {
			container.northwest = Coordinates.northwestOffset( container, true );
			container.southeast = Coordinates.southeastOffset( container, true );
			container = container.nextContainer;
		}

		// item starts out over current parent
		//findParent(this).onDragOver();
		this.parentNode.onDragOver();
	},

	onDrag : function(nwPosition, sePosition, nwOffset, seOffset) {
		/*if (this.isOutside){
			if(!this.getAttribute('class').contains("dragging"))
				this.setAttribute('class', this.getAttribute('class')+" dragging");
		} else {
			this.setAttribute('class', this.getAttribute('class').replace(" dragging",""));	
		}*/
		// check if we were nowhere
		if (this.isOutside) {
			// check each container to see if in its bounds
			var container = DragDrop.firstContainer;
			while (container != null) {
				if (nwOffset.inside( container.northwest, container.southeast ) ||
					seOffset.inside( container.northwest, container.southeast )) {
					this.style.width = "";
					// we're inside this one
					container.onDragOver();
					this.isOutside = false;
					
					// since isOutside was true, the current parent is a
					// temporary clone of some previous container node and
					// it needs to be removed from the document
					var tempParent = this.parentNode;
					tempParent.removeChild( this );
					container.appendChild( this );
					tempParent.parentNode.removeChild( tempParent );
					break;
				} else {
					this.style.width = "40%";
				}
				container = container.nextContainer;
			}
			// we're still not inside the bounds of any container
			if (this.isOutside){
				return;
			}
		
		// check if we're outside our parent's bounds
		} else if (!(nwOffset.inside( this.parentNode.northwest, this.parentNode.southeast ) ||
			seOffset.inside( this.parentNode.northwest, this.parentNode.southeast ))) {
			
			yScrollCorrectSwitch = true;
			
			this.parentNode.onDragOut();
			this.isOutside = true;
			
			// check if we're inside a new container's bounds
			var container = DragDrop.firstContainer;
			while (container != null) {
				if (nwOffset.inside( container.northwest, container.southeast ) ||
					seOffset.inside( container.northwest, container.southeast )) {
					// we're inside this one
					container.onDragOver();
					this.isOutside = false;
					this.parentNode.removeChild( this );
					container.appendChild( this );
					yScrollCorrection -= DyCoGetContentDivTop(this);;
					yScrollCorrectSwitch = true;
					break;
				}
				container = container.nextContainer;
			}

			// if we're not in any container now, make a temporary clone of
			// the previous container node and add it to the document
			if (this.isOutside) {
				var tempParent = this.parentNode.cloneNode( false );
				this.parentNode.removeChild( this );

				//Since this clone is not within a container, remove any
				//Style elements not belonging to the dragged item,
				//like borders around the container (because these would show
				//up elsewhere on screen)
				tempParent.style.border = "none";
				tempParent.appendChild( this );
				document.getElementsByTagName( "body" ).item(0).appendChild( tempParent );
				return;
			}
		}
		
		// if we get here, we're inside some container bounds, so swap us into the
		// correct position
		
		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) {
		this.style.width = "";
		//Check if drop is allowed, set flag to true if it is.
		var dropAllowed = false;
		if( this.parentNode.attributes )
		{
			var myNewNodeID = '';
			var myDepartureNodeID = '';
			var myAllowDropFrom = '';
			if( this.parentNode.parentNode.attributes )
			{
				if(this.parentNode.attributes.getNamedItem('id'))
				{
					myNewNodeID = this.parentNode.attributes.getNamedItem('id').value.replace("_ul","");
				}//End If
			}//End If
			if( this.departureNode.attributes )
			{
				if(this.departureNode.attributes.getNamedItem('id'))
				{
					myDepartureNodeID = this.departureNode.attributes.getNamedItem('id').value.replace("_ul","");
				}//End If
			}//End If
			if( this.parentNode.parentNode.attributes )
			{
				if(this.parentNode.parentNode.attributes.getNamedItem('allowdropfrom'))
				{
					myAllowDropFrom = this.parentNode.parentNode.attributes.getNamedItem('allowdropfrom').value;
				}
				else
				{
					//There doesn't seem to be a property called allowdropfrom,
					//or we dropped outside a container, so allow dropping of the dragged item
					dropAllowed = true;
				}//End If
			}//End If

//			alert("myNewNodeID id : " + myNewNodeID + " , myDepartureNodeID id : " + myDepartureNodeID + " , myAllowDropFrom id : " + myAllowDropFrom  );

		}//End If

		if( myAllowDropFrom.indexOf(myDepartureNodeID) > -1 )
		{
			dropAllowed = true;
		}//End If

		if (dropAllowed)
		{
			// if the drag ends and we're still outside all containers:
			if (this.isOutside) {
	
				//Remove original from the document
				var tempParent = this.parentNode;
				this.parentNode.removeChild( this );
	
				//Move (replace) the dragged item to the bottom of the node we departured from
				this.departureNode.appendChild( this );
				if (tempParent)
				{
					tempParent.parentNode.removeChild( tempParent );
				}

				//Recreate
				createDragDrops();
			}

			this.parentNode.onDragOut();

			//Correct the ID of the dragged item to reflect the new Container:
			var newParentIdBase = this.parentNode.attributes.getNamedItem('id').value.replace("_ul","");
			var myLength1 = newParentIdBase.length;
			var myLength2 = this.attributes.getNamedItem('itemid').value.length;
			var parts = this.attributes.getNamedItem('itemid').value.split("_");
			this.attributes.getNamedItem('itemid').value = newParentIdBase + "_" + parts[parts.length-1];
			//HAHO 
			DragDrop.droppedItem = this;

			//Reorder the orders in the container to reflect the new situation:
			setOrder(newParentIdBase);	//Parameter is the ID of the container to be ordered

			//top and lef denote top and left at itempoint in a container,
			//or topleft point in screen if dropped outside container.
			//Set to 0:
			this.style["top"] = "0px";
			this.style["left"] = "0px";
	
			//Handle onDroppedOn attribute of the target where the item was dropped on if present
			//N.b. all items are dropped on the <UL> element, __NOT__ the <DIV>'s enclosing them.
			//See xslt or view source for more details on this.
			//In other words: "this.parentNode" points to the <UL>, not the <DIV>.
			var myOnDroppedOn = '';
			if( this.parentNode.attributes )
			{
				if( this.parentNode.attributes.getNamedItem('ondroppedon') )
				{
					myOnDroppedOn = this.parentNode.attributes.getNamedItem('ondroppedon').value;
					if(   (myOnDroppedOn!='') && (myOnDroppedOn!='null') && (myOnDroppedOn!='undefined') )
					{
						//Get the ID for this new Parent and
						//save it in DragDrop's newParentID
						if( this.parentNode.attributes.getNamedItem('id') )
						{
							var parentID = this.parentNode.attributes.getNamedItem('id').value;
							if( parentID!='null' )
							{
								DragDrop.newParentID = parentID;
							}
							else
							{
								DragDrop.newParentID = '';
							}//End If
						}//End If
					}//End If
				}//End If			
			}//End If

			//Handle onDrop attribute of a draggable item
			var myOnDrop = '';
			if( this.attributes )
			{
				if( this.attributes.getNamedItem('ondrop') )
				{
					myOnDrop = this.attributes.getNamedItem('ondrop').value;
					if( myOnDrop!='null' )
					{
						//Get the ID for this item and
						//save it in DragDrop's droppedItemID
						if( this.attributes.getNamedItem('itemid') )
						{
							var itemID = this.attributes.getNamedItem('itemid').value;
							if( itemID!='null' )
							{
								DragDrop.droppedItemID = itemID;
							}
							else
							{
								DragDrop.droppedItemID = '';
							}
						}//End If
					}//End If
				}//End If
			}//End If
			
			if( (myOnDroppedOn!='') && (myOnDroppedOn.toLowerCase()!='null') )
			{
				//Handle dropping on to a container
				//console.log( "DragDropEventHandlers." + myOnDroppedOn + "()" );
				eval( "if(DragDropEventHandlers." + myOnDroppedOn + "){DragDropEventHandlers." + myOnDroppedOn + "();}" );
				//eval( "DragDropEventHandlers." + myOnDroppedOn );
			}
	
			if( (myOnDrop!='') && (myOnDrop.toLowerCase()!='null') )
			{
				//Handle dropping of an item
				//eval( "DragDropEventHandlers." + myOnDrop + "()" );
				eval( "DragDropEventHandlers." + myOnDrop + "()" );
			}

		}
		else
		{
			//Drop was not allowed, so reset dragged item	
			//Set top left to 0 first:
			this.style["top"] = "0px";
			this.style["left"] = "0px";
			//Move (replace) the dragged item to the bottom of the node we departured from
			this.departureNode.appendChild( this );
			if (tempParent)
			{
				tempParent.parentNode.removeChild( tempParent );
			}
		}//End If Drop Allowed

	},
	
	getCurrentItemId : function(){
		return this.attributes.getNamedItem('itemid').value;
	},
	
	deleteItem : function(srcEl){
		while(srcEl.tagName.toLowerCase() != "li"){
			srcEl = srcEl.parentNode;	
		}
		srcEl.parentNode.removeChild(srcEl);
		addItemOrderToForm();
	}//End Functions
};

/*
 * Name		: DragUtils
 * Description	: 
 */
var DragUtils = {
	swap : function(item1, item2) {
		var parent = item1.parentNode;
		parent.removeChild(item1);
		parent.insertBefore(item1, item2);

		//top and lef denote top and left at itempoint in a container,
		//or topleft point in screen if dropped outside container.
		//Set to 0:
		item1.style["top"] = "0px";
		item1.style["left"] = "0px";
	},

	nextItem : function(item) {
		var sibling = item.nextSibling;
		/*while (sibling != null && sibling.nodeType==3) { 
		//HAHO Fix for Mozilla/FireFox Empty Space becomes a TextNode, 
		//so next sibling could be a white space, not the next element.
			sibling = sibling.nextSibling;
		};*/
		while (sibling != null) {
			//HAHO added toLowerCae li != LI
			if (sibling.nodeName.toLowerCase() == item.nodeName.toLowerCase()){
				return sibling;
			}
			sibling = sibling.nextSibling;
		}
		return null;
	},

	previousItem : function(item) {
		var sibling = item.previousSibling;
		/*while (sibling != null && sibling.nodeType==3) { 
		//HAHO Fix for Mozilla/FireFox Empty Space becomes a TextNode, 
		//so next sibling could be a white space, not the next element.
			sibling = sibling.previousSibling;
		};*/
		while (sibling != null) {
			//HAHO added toLowerCae li != LI
			if (sibling.nodeName.toLowerCase() == item.nodeName.toLowerCase()){
				 return sibling;
			}
			sibling = sibling.previousSibling;
		}
		return null;
	}		
};

/*
 * Function	: createDragDrops
 * Description	: Creates all necessary ListContainers for dragging and dropping
 */
function createDragDrops()
{
	//Iterate all divs
	var allDIV = document.getElementsByTagName('div');
	for (var i=0; i<allDIV.length; i++)
	{
		//Get The current Div under investigation
		var currentDiv = allDIV[i];

		//Do we want to make this DIV Dragable?
		if (currentDiv.attributes.getNamedItem('dragdrop'))
		{

//			if (currentDiv.attributes.getNamedItem('allowdropfrom'))
//			{
//				alert( currentDiv.attributes.getNamedItem('allowdropfrom').value );
//			}

			//Get it's ID
			var myNewDivID = currentDiv.attributes.getNamedItem('id').value;
			//Get it's dragdrop-flag: draggable or not (true/false)?
			var myNewDivDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
			//Create the ID for the UL-Element within by adding "_ul"
			var myUlElement = document.getElementById(myNewDivID + "_ul");
			//Is the container dragable?
			if(myNewDivDragDrop=="true")
			{
				//alert( "makeListContainer( " + myUlElement + ")" );
				//then make ListContainer
				DragDrop.makeListContainer( myUlElement );
			}//End If
		}//End If
	}//End For
	return true;
}//End Function

/*
 * Function	: refreshDragDrops
 * Description	: refreshes all necessary ListContainers for dragging and dropping
 *		  by removing them first using function removeDragDrops() before
 *		  calling function createDragDrops()
 */
function refreshDragDrops()
{
	//remove containers first
	var removeResult = removeDragDrops();
	if(removeResult)
	{
		//now recreate them
		createDragDrops();
	}//End If
	
	addItemOrderToForm();
}//End Function

/*
 * Function	: refreshDragDrops
 * Description	: refreshes all necessary ListContainers for dragging and dropping
 *		  by removing them first using function removeDragDrops() before
 *		  calling function createDragDrops()
 */
function addItemOrderToForm()
{
	var myDivID = DragDrop.firstContainer.id.split("_")[0];
	var myULElement = document.getElementById(myDivID+"_ul");
	if(myULElement)
	{
		//add node order to form
		var myILElements = myULElement.getElementsByTagName("li");
		myText = "";
		for (var j=0; j<myILElements.length; j++)
		{
			myText = myText + myILElements[j].attributes.getNamedItem('itemid').value.split("_")[1];
			if(j<myILElements.length-1){
			 	myText = myText + ", ";
			}
		}
		document.getElementById(myDivID+"_order_input").value = myText;
	}
}

/*
 * Function	: removeDragDrops
 * Description	: removes all ListContainers from page
 */
function removeDragDrops()
{
	//Remove all objects, do not remove from HTML (need the new situation later on to build
	//the new objects with, so delete linked List with conatainers
	if(DragDrop)
	{
		if(DragDrop.firstContainer)
		{
			//Iterate linked list with containers
			var currentContainer = DragDrop.firstContainer;
			while (currentContainer != null) {
				if(currentContainer.previousContainer)
				{
					//alert("Deleting : " + currentContainer.previousContainer.innerHTML);
					currentContainer.previousContainer = null;
				}//End If
				if(currentContainer.nextContainer==null)
				{
					//alert("Deleting : " + currentContainer.innerHTML);
					currentContainer.nextContainer = null;
				}
				currentContainer = currentContainer.nextContainer;
			}//End While
		}//End If
		DragDrop.firstContainer = null;
	}//End If
	return true; //return true triggers recreate (init) of dragdrops
}//End Function


/*
 * Function	: setOrder
 * Description	: 
 */
function setOrder(newParentIdBase)
{
	//alert("Re-Ordering items in Container : " + newParentIdBase);
	if(newParentIdBase)
	{
		currentDiv = document.getElementById(newParentIdBase);		

		if(currentDiv)
		{
			//Does it have drag and drop?
			if(currentDiv.attributes.getNamedItem('dragdrop'))
			{
				var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
				var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
				if(myDragDrop=="true")
				{
					//Get container
					var myULElement = document.getElementById(newParentIdBase+"_ul");
					if(myULElement)
					{
						var myILElements = myULElement.getElementsByTagName("li");
						var newOrder = 0;
						for (var j=0; j<myILElements.length; j++)
						{
							newOrder = newOrder + 1;
							if(myILElements[j].attributes.getNamedItem('order'))
							{
								myILElements[j].attributes.getNamedItem('order').value = newOrder;
							}
						}
					}//End If
				}//End If
			}//End If
		}//End If
	}//End If

}//End Function


/*
 * Function	: showDragDropId's
 * Description	: 
 */
function showDragDropIDs()
{
	//Iterate all divs
	var allDIV = document.getElementsByTagName('div');
	for (var i=0; i<allDIV.length; i++)
	{
		//Get The current Div under investigation
		var currentDiv = allDIV[i];

		//Get it's id
		if( currentDiv.attributes.getNamedItem('id') )
		{
			var myDivID = currentDiv.attributes.getNamedItem('id').value;
			if(myDivID)
			{
				//Does it have drag and drop?
				if(currentDiv.attributes.getNamedItem('dragdrop'))
				{
					var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
					var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
					if(myDragDrop=="true")
					{
						//Get container
						var myULElement = document.getElementById(myDivID+"_ul");
						if(myULElement)
						{
							var myILElements = myULElement.getElementsByTagName("li");
							var myText = "The container element ID's in container " + myDivID + " are:\n\n";
							for (var j=0; j<myILElements.length; j++)
							{
								myText = myText + myILElements[j].attributes.getNamedItem('itemid').value + "\n";
							}
							alert(myText);
						}//End If
					}//End If
				}//End If
			}//End If
		}//End If
	}//End For
	return true;
}//End Function

/*
 * Function	: showDragDropItemId's
 * Description	: 
 */
function showDragDropItemIDs()
{
	//Iterate all divs
	var allDIV = document.getElementsByTagName('div');
	for (var i=0; i<allDIV.length; i++)
	{
		//Get The current Div under investigation
		var currentDiv = allDIV[i];

		//Get it's id
		if( currentDiv.attributes.getNamedItem('id') )
		{
			var myDivID = currentDiv.attributes.getNamedItem('id').value;
			//alert(myDivID);
			if(myDivID)
			{
				//Does it have drag and drop?
				if(currentDiv.attributes.getNamedItem('dragdrop'))
				{
					var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
					var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
					if(myDragDrop=="true")
					{
						//Get container
						var myULElement = document.getElementById(myDivID+"_ul");
						if(myULElement)
						{
							var myILElements = myULElement.getElementsByTagName("li");
							var myText = "The item ID's in container " + myDivID + " are:\n\n";
							for (var j=0; j<myILElements.length; j++)
							{
								myText = myText + myILElements[j].attributes.getNamedItem('itemid').value.replace(myDivID+"_","") + "\n";
							}
							alert(myText);
						}//End If
					}//End If
				}//End If
			}//End If
		}//End If
	}//End For
	return true;
}//End Function

/*
 * Function	: showDragDropOrders
 * Description	: 
 */
function showDragDropOrders()
{
	//Iterate all divs
	//(n.b: Not very effective yet, should actually use some sort of anchor inside the page to start iterating from, but hey, this is in DEV mode ;-) )	
	var allDIV = document.getElementsByTagName('div');
	for (var i=0; i<allDIV.length; i++)
	{
		//Get The current Div under investigation
		var currentDiv = allDIV[i];

		//Get it's id
		if( currentDiv.attributes.getNamedItem('id') )
		{
			var myDivID = currentDiv.attributes.getNamedItem('id').value;
			//alert(myDivID);
			if(myDivID)
			{
				//Does it have drag and drop?
				if(currentDiv.attributes.getNamedItem('dragdrop'))
				{
					var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
					var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
					if(myDragDrop=="true")
					{
						//Get container
						var myULElement = document.getElementById(myDivID+"_ul");
						if(myULElement)
						{
							var myILElements = myULElement.getElementsByTagName("li");
							var myText = "The Orders in container " + myDivID + " are:\n\n";
							for (var j=0; j<myILElements.length; j++)
							{
								var tempOrder = myILElements[j].attributes.getNamedItem('order').value;
								myText = myText + myILElements[j].attributes.getNamedItem('itemid').value.replace(myDivID+"_","") + " , order=" + tempOrder + "\n";
							}
							alert(myText);
						}//End If
					}//End If
				}//End If
			}//End If
		}//End If
	}//End For
	return true;
}//End Function

/*
 * Function	: showDragDropValues
 * Description	: 
 */
function showDragDropValues()
{
	//Iterate all divs
	var allDIV = document.getElementsByTagName('div');
	for (var i=0; i<allDIV.length; i++)
	{
		//Get The current Div under investigation
		var currentDiv = allDIV[i];

		//Get it's id
		if( currentDiv.attributes.getNamedItem('id') )
		{
			var myDivID = currentDiv.attributes.getNamedItem('id').value;
			if(myDivID)
			{
				//Does it have drag and drop?
				if(currentDiv.attributes.getNamedItem('dragdrop'))
				{
					var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
					var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
					if(myDragDrop=="true")
					{
						//Get container
						var myULElement = document.getElementById(myDivID+"_ul");
						if(myULElement)
						{
							var myILElements = myULElement.getElementsByTagName("li");
							var myText = "Dragged elements contents in container " + myDivID + " are:\n\n";
							for (var j=0; j<myILElements.length; j++)
							{
								myText = myText + myILElements[j].innerHTML + "\n";
							}
							alert(myText);
						}//End If
					}//End If
				}//End If
			}//End If
		}//End If
	}//End For
	return true;
}//End Function



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Use this global to enable alerts (popups) showing the event that's beeing handled below, in the DragDropEventHandlers - functions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var DragDropEventHandlersDebug = false;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var DragDropEventHandlers = {

	//Container DropOn Handlers
	handleOnDroppedOn : function(url) {
		//console.log("handleOnDroppedOn");
		if(DragDropEventHandlersDebug)
		{
			alert("handleOnDroppedOn1 : Handling dropping " + DragDrop.droppedItemID + " onto container " + DragDrop.newParentID );
		}
		//if droped from self, do not handle event
		if(DragDrop.droppedItem.departureNode.id == DragDrop.newParentID)
			return;
		//HAHO put back copy in orginal list
		if(cloneNodeOnDrop)
			DragDrop.oldParent.insertBefore(DragDrop.droppedItem.cloneNode(true), DragDrop.oldChildBefore);	
		
		/*this.oldParent = this.parentNode;
		this.oldChildBefore = this.nextSibling;*/
		
		var xmlhttp = new XMLHttpRequest();   
		//alert(url+"&contenttype=text/xml&PARENTID="+DragDrop.newParentID+"&ITEMID="+DragDrop.droppedItemID);
		xmlhttp.open("GET", url+"&contenttype=text/xml&PARENTID="+DragDrop.newParentID+"&ITEMID="+DragDrop.droppedItemID, false);    
		xmlhttp.send('');   
		newElement = document.importNode(xmlhttp.responseXML.documentElement, true);
		oldElement = DragDrop.droppedItem;
		oldElement.parentNode.replaceChild(newElement, oldElement);
		refreshDragDrops();
	},
	handleOnDroppedOn2 : function() {
		if(DragDropEventHandlersDebug)
		{
			alert("handleOnDroppedOn2 : Handling dropping " + DragDrop.droppedItemID + " onto container " + DragDrop.newParentID + ", parent is " + DragDrop.parentNodeID + " - " + DragDrop.droppedItem.departureNode.id );
		}
		//if droped from self, do not handle event
		if(DragDrop.droppedItem.departureNode.id == DragDrop.newParentID){
			addItemOrderToForm();
			return;
		}
		//HAHO put back copy in orginal list
		if(cloneNodeOnDrop)
			DragDrop.oldParent.insertBefore(DragDrop.droppedItem.cloneNode(true), DragDrop.oldChildBefore);
		//alert(DragDrop.newParentID);
		var myDivID = DragDrop.newParentID.split("_")[0];
		var currentDiv = document.getElementById(myDivID);
		if(myDivID)
		{
			//Does it have drag and drop?
			if(currentDiv.attributes.getNamedItem('dragdrop'))
			{
				var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
				var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
				if(myDragDrop=="true")
				{
					//Get container
					var myULElement = document.getElementById(myDivID+"_ul");
					if(myULElement)
					{
						//add id from dropped node to form
						var myText = "";
						parts = DragDrop.droppedItemID.split("_");
						myText = myText + parts[parts.length-1];
						document.getElementById(myDivID+"_input").value = myText;
						//add node order to form
						addItemOrderToForm();
						/*var myILElements = myULElement.getElementsByTagName("li");
						myText = "";
						for (var j=0; j<myILElements.length; j++)
						{
							myText = myText + myILElements[j].attributes.getNamedItem('itemid').value.split("_")[1];
							if(j<myILElements.length-1){
							 	myText = myText + ", ";
							}
						}
						document.getElementById(myDivID+"_order_input").value = myText;*/
					}//End If
				}//End If
			}//End If
		}//End If
		KPWindowDoPost( KPWindowFindParent(DragDrop.droppedItem).getAttribute('id'),'AddNode');
		
		
	},
	handleOnDroppedOn3 : function() {
		if(DragDropEventHandlersDebug)
		{
			alert("handleOnDroppedOn3 : Handling dropping " + DragDrop.droppedItemID + " onto container " + DragDrop.newParentID );
		}
		//if droped from self, do not handle event
		if(DragDrop.droppedItem.departureNode.id == DragDrop.newParentID)
			return;
		//alert(DragDrop.newParentID);
		var myDivID = DragDrop.newParentID.split("_")[0];
		var currentDiv = document.getElementById(myDivID);
		if(myDivID)
		{
			//Does it have drag and drop?
			if(currentDiv.attributes.getNamedItem('dragdrop'))
			{
				var myDragDrop = currentDiv.attributes.getNamedItem('dragdrop').value;
				var myDragDropID = currentDiv.attributes.getNamedItem('id').value;
				if(myDragDrop=="true")
				{
					//Get container
					var myULElement = document.getElementById(myDivID+"_ul");
					if(myULElement)
					{
						var myILElements = myULElement.getElementsByTagName("li");
						var myText = "";
						parts = DragDrop.droppedItemID.split("_");
						myText = myText + parts[parts.length-1];
						/*for (var j=0; j<myILElements.length; j++)
						{
							//myText = myText + myILElements[j].attributes.getNamedItem('itemid').value.replace(myDivID+"_","") + ",";
							parts = myILElements[j].attributes.getNamedItem('itemid').value.split("_");
							myText = myText + parts[parts.length-1] + ",";
						}*/
						//alert(myText);
						//myText = myText.substr(0,myText.length-1);
						document.getElementById(myDivID+"_input").value = myText;
					}//End If
				}//End If
			}//End If
		}//End If
		KPWindowDoPost( KPWindowFindParent(DragDrop.droppedItem).getAttribute('id'),'AddNode');
		//clntSub("AddNode",KPWindowFindParent(DragDrop.droppedItem).getAttribute('id'));
	},
	/*handleOnDroppedOn4 : function() {
		if(DragDropEventHandlersDebug)
		{
			alert("handleOnDroppedOn4 : Handling dropping " + DragDrop.droppedItemID + " onto container " + DragDrop.newParentID );
		}
	},
	handleOnDroppedOn5 : function() {
		if(DragDropEventHandlersDebug)
		{
			alert("handleOnDroppedOn5 : Handling dropping " + DragDrop.droppedItemID + " onto container " + DragDrop.newParentID );
		}
	},*/

	//Item Drop Handlers
	handleDropEvent1 : function() {
		//Use getElementByID(DragDrop.droppedItemID) in order to acces the dropped Item
		//Iterate all divs
		if(DragDropEventHandlersDebug)
		{
			alert("handleDropEvent1 : Handling Drop Event for item " + DragDrop.droppedItemID );
		}
	},

	handleDropEvent2 : function() {
		//Use getElementByID(DragDrop.droppedItemID) in order to acces the dropped Item
		if(DragDropEventHandlersDebug)
		{
			alert("handleDropEvent2 : Handling Drop Event for item " + DragDrop.droppedItemID );
		}
	}		
};

function findParent(node){
	while(typeof(node.onDragOver) == "undefined"){
		node = node.parentNode;	
	}
	return node;
}

function DyCoGetContentDivTop(targetel){
	return targetel.parentNode.parentNode.scrollTop;
}