function DragAndDrop_v2(){
	this.isIE=document.all&&!window.opera;
	this.isNN=!document.all&&document.getElementById;
	this.isN4=document.layers;
	this.dragables  = new Array();
	this.dropZones  = new Array();
	this.CurrentDropZone = null;
	this.CurrentMouseFocus = null;
	this.ActivelyDragging = false;
	this.DragEnabled = true;
}
function dragableElement(oDragableElement,oDragHotSpotElement, nDragableIndex,cDragableGroupName){
	this.Element = oDragableElement;
	this.Element.dragableIndex = nDragableIndex;
	this.ElementHotSpot = oDragHotSpotElement;
	this.DragableGroupName = cDragableGroupName;
	this.ClonedElement = null;
	this.CloneEnabled = true;
	this.ResizeEnabled = false;
	this.clonedElementOffsetY = 0;
	this.clonedElementOffsetX = 0;
	this.zIndex = 10;
	this.offsetScrollDiv = null;
	this.offsetScrollDivInterval = null;
	this.onDragComplete = null;
	this.onDragStart = null;
	this.Enabled = true;
	this.arrParameters = [];
}
dragableElement.prototype.setParameter = function(cName,cValue){
	this.arrParameters[cName] = cValue;
}
dragableElement.prototype.getParameter = function(cName){
	return this.arrParameters[cName];
}
dragableElement.prototype.disable = function(){
	this.ElementHotSpot.style.cursor = 'default';
	this.ElementHotSpot.style.pointer = 'default';
	this.Enabled = false;
}
dragableElement.prototype.enable = function(){
	this.ElementHotSpot.style.cursor = 'move';
	this.ElementHotSpot.style.pointer = 'move';
	this.Enabled = true;
}
function preventDefault(e){
	if (e && e.preventDefault) {
		e.preventDefault();
	}else if (window.event){
		window.event.returnValue = false;
	}
}
function getParentNodeByAttribute(oElement, cAttributeName){
	var oElementParent = oElement.parentNode
	while(typeof(oElementParent[cAttributeName]) == 'undefined'){
		oElementParent = oElementParent.parentNode;
	}
	return oElementParent
}
DragAndDrop_v2.prototype.RegisterDragable = function(oDragableElement ,oDragHotSpotElement,cDragableGroupName){
	var nDragableIndex = this.dragables.length;
	var oDragable = new dragableElement(oDragableElement,oDragHotSpotElement,nDragableIndex,cDragableGroupName)
	oDragHotSpotElement.style.cursor = 'move'
	oDragHotSpotElement.style.pointer = 'move'
	oDragable.currentWidth=parseInt(oDragableElement.offsetWidth,10);
	oDragable.currentHeight=parseInt(oDragableElement.offsetHeight,10);	
	oDragHotSpotElement.DragableIndex = nDragableIndex;
	this.dragables.push(oDragable);
	var obj = getObject(this);	
	this.hotSpotEvent = function registerHotSpot(e) { 
				if(obj.DragEnabled){
					var oSourceElement = obj.isIE ? event.srcElement : e.target;
					preventDefault(e);
					if(typeof(oSourceElement.DragableIndex) == 'undefined'){
						obj.RegisterElement(e, getParentNodeByAttribute(oSourceElement , 'DragableIndex').DragableIndex); 
					}else{
						obj.RegisterElement(e, oSourceElement.DragableIndex); 
					}
					e.cancelBubble = true;
				}
			      }
	EventManager.Add(this.dragables[this.dragables.length-1].ElementHotSpot ,'mousedown', obj.hotSpotEvent);
	return this.dragables[nDragableIndex]
}

function dropzoneElement(oDropZoneElement, nDropZoneIndex, arrAcceptedDragableGroupNames){
	this.Element = oDropZoneElement;
	this.Element.dropZoneIndex = nDropZoneIndex;
	this.AcceptedDragableGroupNames = arrAcceptedDragableGroupNames;
	this.AbsoluteRectangle = null;
	this.onDragOver = null;
	this.onDrop = null;
	this.onDragOut= null;
	this.offsetScrollDiv = null;
	this.onMouseFocus = null;
	this.mouseFocusTimeout = null;
	this.mouseFocusDelayInSeconds = 1.2;
	this.arrParameters = []
}
dropzoneElement.prototype.setParameter = function(cName,cValue){
	this.arrParameters[cName] = cValue;
}
dropzoneElement.prototype.getParameter = function(cName){
	return this.arrParameters[cName];
}
DragAndDrop_v2.prototype.RegisterDropZone = function(oDropZoneElement,arrAcceptedDragableGroupNames){
	var nDropZoneIndex = this.dropZones.length;
	this.dropZones.push(new dropzoneElement( oDropZoneElement,nDropZoneIndex ,arrAcceptedDragableGroupNames));
	return this.dropZones[nDropZoneIndex];
}
DragAndDrop_v2.prototype.RegisterElement = function(e, nDragableIndex){
	var oSourceElement = this.isIE ? event.srcElement : e.target;
	oDragable = this.dragables[nDragableIndex];
	if(oDragable.onDragStart != null){
		oDragable.onDragStart();
	}
	this.setDropzoneAbsoluteRectangles(oDragable);
	var obj = getObject(this);
	this.dragDelaytimeout = setTimeout(function(){obj.ActivelyDragging = true;},"500");	
	this.moveDragAndDropFN = function moveDragAndDrop(e) { if(obj.DragEnabled){preventDefault(e); obj.MoveBy(e,nDragableIndex); obj.getCurrentDropZone(e,nDragableIndex); }}
	this.stopDragAndDropFN = function stopDragAndDrop(e) { if(obj.DragEnabled){preventDefault(e); obj.dragComplete(e,nDragableIndex); obj.stopDrag();}}
	EventManager.Add(document,'mousemove',  obj.moveDragAndDropFN);
	EventManager.Add(document,'mouseup',  obj.stopDragAndDropFN);
}
DragAndDrop_v2.prototype.stopDrag = function(oDragable){
	clearTimeout(this.dragDelaytimeout); 
	this.ActivelyDragging = false; 
 	var oLocDnd = getObject(this);
        for (var i = 0; i < EventManager._registry.length; i++) {
            with (EventManager._registry[i]) {
		    if(obj == document){
			    if(fn == oLocDnd.moveDragAndDropFN || fn == oLocDnd.stopDragAndDropFN){
				if (obj.removeEventListener) {
				    obj.removeEventListener(type, fn, useCapture);
				}else if (obj.detachEvent) {
				    obj.detachEvent("on" + type, fn);
				}
			    }
		    }
            }
        }
        var obj = getObject(this);
}
DragAndDrop_v2.prototype.setDropzoneAbsoluteRectangles = function(oDragable){
	for(var i=0;i<this.dropZones.length;i++){
		if(this.dropZones[i].AcceptedDragableGroupNames.inArray(oDragable.DragableGroupName)){
			this.dropZones[i].AbsoluteRectangle = new AbsoluteRectangle(this.dropZones[i].Element , this.dropZones[i].offsetScrollDiv);
		}
	}
}
function AbsoluteRectangle(oElement, oOffsetObject){
	var nPositionY = 0 ;
	var nPositionX = 0 ;
	try{nPositionY = findPosY(oElement);}catch(e){}
	try{nPositionX = findPosX(oElement);}catch(e){}	
	if(oOffsetObject != null){
		var nScrollTop = oOffsetObject.scrollTop;
		var nScrollLeft = oOffsetObject.scrollLeft;	
		nPositionY = nPositionY - nScrollTop;
		nPositionX = nPositionX - nScrollLeft;
	}
	var nOffsetWidth =  oElement.offsetWidth
	var nOffsetHeight =  oElement.offsetHeight;
	this.topLeft = [nPositionX , nPositionY];
	this.topRight= [nPositionX + nOffsetWidth ,   nPositionY];
	this.bottomLeft= [nPositionX,   nPositionY + nOffsetHeight];
	this.bottomRight= [nPositionX + nOffsetWidth  ,   nPositionY + nOffsetHeight];
	return this;
}

DragAndDrop_v2.prototype.dragComplete = function(e,nDragableIndex){
	var oDragable = this.dragables[nDragableIndex];
	if(oDragable.DragableGroupName != ''){	
		if(oDragable.ElementClone != null){
			var oElementParent = oDragable.ElementClone.parentNode
			oElementParent.removeChild(oDragable.ElementClone);
			oDragable.ElementClone = null;		
			var nMouseX = (this.isIE ? event.clientX : e.clientX) ;
			var nMouseY = (this.isIE ? event.clientY : e.clientY);		
			var oDropZone = this.getCurrentDropZone(e,nDragableIndex);
			if(oDropZone != null){
				oDropZone.onDrop != null
				oDropZone.onDrop(e, oDragable);			
			}
			this.AssignCursor(oDragable , 'hand')
			this.clearCurrentDropZone(e ,nDragableIndex);
		}
	}	
	if(oDragable.onDragComplete != null){		
		oDragable.onDragComplete();
	}	
}
DragAndDrop_v2.prototype.getCurrentDropZone = function(e ,nDragableIndex){
	if (!this.ActivelyDragging){return}
	var oDragable = this.dragables[nDragableIndex]
	if(typeof(oDragable.DragableGroupName) != 'undefined'){
		var nMouseX = (this.isIE ? event.clientX : e.clientX) ;
		var nMouseY = (this.isIE ? event.clientY : e.clientY) ;			
		var oTargetDropZone = null;
		for(var i=0;i<this.dropZones.length;i++){			
			if(this.inDropZone([nMouseX,nMouseY] , this.dropZones[i])){
				if(this.dropZones[i].onMouseFocus != null){	
					var oLocDropZone = this.dropZones[i];
					if(this.CurrentMouseFocus != oLocDropZone){
						var oLocDnD = this
						oLocDropZone.mouseFocusTimeout = setTimeout(function(){oLocDropZone.onMouseFocus(e,oDragable);oLocDnD.setDropzoneAbsoluteRectangles(oDragable);} , oLocDropZone.mouseFocusDelayInSeconds * 1000);
						this.CurrentMouseFocus = oLocDropZone
					}
				}
				if(this.dropZones[i].AcceptedDragableGroupNames.inArray(oDragable.DragableGroupName)){	
					oTargetDropZone = this.dropZones[i];					
					this.AssignCursor(oDragable , 'default')
					break;
				}
			}
		}
		if(oTargetDropZone != null){	
			this.clearCurrentDropZone(e ,nDragableIndex);
			this.CurrentDropZone = oTargetDropZone;
			if(oTargetDropZone.onDragOver != null){
				oTargetDropZone.onDragOver(oDragable);
				e.cancelBubble = true;
			}
			return oTargetDropZone;
		}
	}
	this.AssignCursor(oDragable , 'not-allowed')
	this.clearCurrentDropZone(e ,nDragableIndex);
	return oTargetDropZone;
}
DragAndDrop_v2.prototype.inDropZone = function(arrMouseCoords ,oDropZone){
	var nScrollTop = window.pageYOffset || document.documentElement.scrollTop || 0; 
	var nScrollLeft = window.pageXOffset || document.documentElement.scrollLeft || 0;
	var nMouseX = arrMouseCoords[0]  + nScrollLeft;
	var nMouseY = arrMouseCoords[1]  + nScrollTop;
	var oRectangle = oDropZone.AbsoluteRectangle;		
	try{
		if((nMouseX > oRectangle.topLeft[0] && nMouseX < oRectangle.topRight[0]) && (nMouseY > oRectangle.topLeft[1] && nMouseY < oRectangle.bottomLeft[1])){
			return true;
		}
	}catch(e){}
	if(this.CurrentDropZone != null){
		if(this.CurrentDropZone.mouseFocusTimeout != null){
			clearTimeout(this.CurrentDropZone.mouseFocusTimeout)
			this.CurrentMouseFocus = null
		}	
	}
	return false;
}
DragAndDrop_v2.prototype.clearCurrentDropZone = function(e, nDragableIndex){
	var oDragable = this.dragables[nDragableIndex]
	if(this.CurrentDropZone != null){
		if(this.CurrentDropZone.onDragOut != null){
			this.CurrentDropZone.onDragOut(oDragable);
		}
		if(this.CurrentMouseFocus != this.CurrentDropZone){
			clearTimeout(this.CurrentDropZone.mouseFocusTimeout)
		}
	}
	this.CurrentDropZone = null;
}
DragAndDrop_v2.prototype.AssignCursor = function(oDragable, cCursorName){
	//alert(oDragable.Element.tagName)
	//how to get cursor 'not-allowed' whenever not over dropzone??????!!!! this doesn't work always. no time.
	oDragable.Element.style.cursor = cCursorName;
	if(oDragable.Element.getElementsByTagName('A')[0]){
		oDragable.Element.getElementsByTagName('A')[0].style.cursor = cCursorName
	}
	if(oDragable.Element.getElementsByTagName('SPAN')[0]){
		oDragable.Element.getElementsByTagName('SPAN')[0].style.cursor = cCursorName
	}
	if(oDragable.Element.getElementsByTagName('P')[0]){
		oDragable.Element.getElementsByTagName('P')[0].style.cursor = cCursorName
	}
	if(oDragable.Element.getElementsByTagName('IMG')[0]){
		oDragable.Element.getElementsByTagName('IMG')[0].style.cursor = cCursorName
	}	
	
}
DragAndDrop_v2.prototype.AdjustScrollDivPosition = function(oDragable , cDirection){
	if (!this.ActivelyDragging){return}
	var oScrollDiv = oDragable.offsetScrollDiv;
	var nAutoScrollPercentage = Math.floor(oScrollDiv.offsetHeight * .03);
	this.setDropzoneAbsoluteRectangles(oDragable);
	if(cDirection.match(/up/i)){
		oScrollDiv.scrollTop = oScrollDiv.scrollTop - nAutoScrollPercentage;
	}else{
		oScrollDiv.scrollTop = oScrollDiv.scrollTop + nAutoScrollPercentage;
	}
}
DragAndDrop_v2.prototype.MoveBy = function(e , nDragableIndex){	
	oDragable = this.dragables[nDragableIndex]
	if (!oDragable.Enabled){this.stopDrag();return}
	if (!this.ActivelyDragging){return}
	var nScrollTop = window.pageYOffset || document.documentElement.scrollTop || 0; 
	var nScrollLeft = window.pageXOffset || document.documentElement.scrollLeft || 0;
	var nPositionY = 0;
	var nPositionX = 0;
	if(oDragable.ElementClone == null){
		if(typeof(oDragable.ErrorMessageElement) != 'undefined'){
			oDragable.ElementClone = oDragable.ErrorMessageElement.cloneNode(true);			
		}else{
			oDragable.ElementClone = oDragable.Element.cloneNode(true);
		}
		this.AssignCursor(oDragable , 'not-allowed');
		oDragable.ElementClone.style.position = 'absolute';
		oDragable.ElementClone.style.zIndex = oDragable.zIndex;    
		try{ nPositionY = findPosY(oDragable.Element) + nScrollTop;}catch(e){}
		try{ nPositionX = findPosX(oDragable.Element) + nScrollLeft;}catch(e){}
		oDragable.ElementClone.style.top = nPositionY + oDragable.clonedElementOffsetY + 'px';
		oDragable.ElementClone.style.left =  nPositionX +  oDragable.clonedElementOffsetX + 'px';
		
		var oBody = document.body;		
		oBody.appendChild(oDragable.ElementClone);
		if(!oDragable.CloneEnabled){
			var oParent = oDragable.Element.parentNode;
			oParent.removeChild(oDragable.Element);
			if(!this.isIE){
				oDragable.ElementHotSpot = document.getElementById(oDragable.ElementHotSpot.id);
				oDragable.ElementHotSpot.DragableIndex = nDragableIndex;
				obj = this;
				EventManager.Add(oDragable.ElementHotSpot ,'mousedown', obj.hotSpotEvent);
			}			
		}else{
			oDragable.ElementClone.style.filter="alpha(opacity=70)"
		}
	}else{
		oDragable.ElementClone.style.position = 'absolute';
		oDragable.ElementClone.style.zIndex = oDragable.zIndex; 
	}
	var nMouseX = ( this.isIE ?  event.clientX : e.clientX) + nScrollLeft;
	var nMouseY = ( this.isIE ?  event.clientY : e.clientY) + nScrollTop;
	if(oDragable.offsetScrollDiv != null){
		var nTopBounds = findPosY(oDragable.offsetScrollDiv);
		var nBottomBounds = nTopBounds + oDragable.offsetScrollDiv.offsetHeight;
		if(this.offsetScrollDivInterval != null){
			clearInterval(this.offsetScrollDivInterval);
			this.offsetScrollDivInterval = null
			this.setDropzoneAbsoluteRectangles(oDragable);
		}
		if(nMouseY < nTopBounds){
			var oLocDnD = this;
			this.offsetScrollDivInterval =  setInterval(function(){oLocDnD.AdjustScrollDivPosition(oDragable , 'up');} , "100")
		}else if(nMouseY > nBottomBounds){
			var oLocDnD = this;
			this.offsetScrollDivInterval =  setInterval(function(){oLocDnD.AdjustScrollDivPosition(oDragable , 'down');} , "100")			
		}
	}	
	oDragable.ElementClone.style.left = nMouseX +  oDragable.clonedElementOffsetX + 'px';
	oDragable.ElementClone.style.top = nMouseY + oDragable.clonedElementOffsetY + 'px';
}
