/*
 * Drag & Drop
 * event list:
 * 		- onDragEnd
 * 		- onDragStart
 * 		- onOverDropTarget
 * 		- onBorder
 * 		- onDrag
 *
 * style:
 * 		- .cursor-move *			{ cursor: move !important; }
 * 		- .cursor-not-allowed *		{ cursor: not-allowed !important; }
 */

var DDA_INNER		= 0x0000001;	// drag target align inner
var DDA_LEFT		= 0x0000010;	// drag target align left
var DDA_TOP			= 0x0000100;	// drag target align top
var DDA_RIGHT		= 0x0001000;	// drag target align right
var DDA_BOTTOM		= 0x0010000;	// drag target align bottom

var CURRENT_DRAG_DROP_OBJECT = null;

function dragAndDrop()
{
	this.dropTargetList		= new Array();		// ahova lehet mozgatni az aktuális elemet
	this.assignTargetList	= new Array();		// ezekhez az elemekhez lett hozzárendelve a drag funkció
	this.dropTarget			= null;				// ami megvan adva a dropTargetList-ben azok közül az az objektum ami fölöt éppen a cursor van
	this.dragObject			= null;				// aktuális elem
	this.cloneObject		= null;				// ezt az objektumot mozgatja
	this.cloneObjectBounds	= {_x:0, _y:0, width:0, height: 0};
	this.validTarget		= false;			// le lehet-e itt dobni az aktuális elemet
	this.addEvent			= addEvent;			// eventhandler
	this.drag				= false;			// megkezdődhet-e a mozgatás
	this.sensitive			= 2;				// mekkora egértevékenységtől kezdje a mozgatást
	this.startMouse			= new Object();		// egér kezdeti kordinátái
	this.startObject		= new Object();		// objektum kezdeti kordinátái
	this.onDragEnd			= function(){};		// event - ha vége a dragnak akkor hívódik meg (param: this)
	this.onDragStart		= function(){};		// event - ha megkezdődik a drag akkor hívódik meg (param: this)
	this.onOverDropTarget	= function(){};		// event - ha valamelyik dropTarget fölött van az aktuális objektum ez a fügvény folyamatosan hívodik ha mozgatják az objektumot
	this.onBorder			= function(){};		// event - ha eléri valamelyik határt akkor folyamatosan meghívódik amikor mozgatják az objektumot
	this.onDrag				= function(){};		// event - objektum mozgatása közben/alatt hívódik meg
	this.axis				= {_x:true,_y:true};// melyik tengelyeken müködjön a drag
	this.noClone			= false;			// ha true akkor az eredetit mozgatja és nem egy másolatot
	this.noFullClone		= false;			// ha true akkor visszamenőleg nem klónozza az elemeket
	this.uproot				= false;			// ha a noClone true ennek akkor van szerepe, Ha true akkor az objektumot kiszakítja az eredeti környezetéből és azt mozgatja tovább
	this.alpha				= 90;				// a mozgatott objektum alfája
	this.assignNumber		= 0;				// hány darab objecthez lett hozzárendelve ez az objektum
	this.cursor				= {drag:'cursor-hand', noDrop:'cursor-not-allowed'};// egér cursor ikonok class nevei
	this.border				= {_x:null,_y:null,width:null,height:null};				// határok amin kívülre nem lehet húzni az adott objektumot
	this.borderTest			= {border:'', hit:false};	// ha ütközött valamilyek oldalhoz akkkor a hit true és a border értéke hogy melyikhez ütközik: L,T,R,B,LT,LB,RT,RB
	this.enableDrag			= true;						// ha false nem lehet mozgatni az elementet
	this.distance			= {_x:0,_y:0};				// a kiindulási pont és a jelenlegi pont közti eltérés
	this._clusterList		= new HTMLNodeList(new Array());		// ha egy html nodeokból álló csoportot adunk meg mozgatás céljából akkor ez tartalmazza az elemek listáját
	this.delClone			= true;									// ha true akkor törli a másolatot egyébként nem
	this.cloneClassName		= null;									// a leklónozott node class nevéhez hozzáfűzi még ezt, ha meg van adva
	this.mouseAlign			= null;									// a jelenleg mozgatott element sarkait lehet az egérkurzorhoz pozicionálni
	this.cloneToBox			= false;								// ha true akkor egy kis dobozba másolja a tartalmat és azt mozgatja (látványelem)
	this.dropAligns			= DDA_LEFT | DDA_TOP | DDA_RIGHT | DDA_BOTTOM | DDA_INNER;		// melyik területeket vizsgálja a droptargeten belül
	this.scrollContainer	= null;
	this.scrollStep			= 10;
	this.scrollInterval		= 50;
	
	this.onBorderEvents		= {
		'T'	 : [],
		'R'	 : [],
		'B'	 : [],
		'L'	 : [],
		'LT' : [],
		'RT' : [],
		'LB' : [],
		'RB' : [],
		'ALL': []
	}
	
	this.dropAlignsPercent				= new Object();				// területek felosztása
	this.dropAlignsPercent[DDA_LEFT]	= 30;
	this.dropAlignsPercent[DDA_TOP]		= 30;
	this.dropAlignsPercent[DDA_RIGHT]	= 30;
	this.dropAlignsPercent[DDA_BOTTOM]	= 30;
	this.dropAlignsPercent[DDA_INNER]	= 40;
	
	this.dropAlignClassName				= new Object();				// területek class nevei
	this.dropAlignClassName[DDA_LEFT]	= 'dda-left';
	this.dropAlignClassName[DDA_TOP]	= 'dda-top';
	this.dropAlignClassName[DDA_RIGHT]	= 'dda-right';
	this.dropAlignClassName[DDA_BOTTOM]	= 'dda-bottom';
	this.dropAlignClassName[DDA_INNER]	= 'dda-inner';
	
	this.temp	= new Object();		// átmeneti információk tárolása
	
	this.addEvent(document, 'mousemove', null, this.handlerMouseMove);
	this.addEvent(document, 'mouseup', null, this.handlerMouseUp);
}

dragAndDrop.prototype.getClusterList = function()
{
	if(isNodeList(this._clusterList))
	{
		if(this._clusterList.length)
			return this._clusterList;
		else
			return new HTMLNodeList([this.dragObject]);
	}
	return new HTMLNodeList(new Array());
}

dragAndDrop.prototype.getDragElementDistance = function()
{
	var bounds = getBounds(this.cloneObject);
	
	return {
		_x		: bounds._x - this.startObject._x,
		_y		: bounds._y - this.startObject._y 
	}
};

dragAndDrop.prototype.startDrag = function(mouseEvent)
{
	if(isFunction(this.onDragStart)) this.onDragStart(mouseEvent);
	
	this.refreshDropTarget();
	this.refreshBorder();
	
	if(this.cloneObject)
	{
		if(this.alpha < 100 && this.alpha > 0)
		this.cloneObject.setStyle({filter:'alpha(opacity='+this.alpha+')', opacity:this.alpha/100});
	}	
}

dragAndDrop.prototype.endDrag = function(mouseEvent, noExecuteCallBack)
{
	this.enableSelection();
	this.changeMouseStyle(true);
	this._changeDropTargetClass(true);
	
	if(isFunction(this.onDragEnd) && this.drag && !noExecuteCallBack) this.onDragEnd(mouseEvent);
	if(this.cloneObject && !this.noClone && this.delClone) this.cloneObject.del();
	
	this.startMouse 		= new Object();
	this.startObject		= new Object();
	if(!this.noClone)this.cloneObject = null;
	this.drag				= false;
	this.validTarget		= false;
	this.dropTarget			= null;
	clearInterval(this.scrollInterval);
	this.scrollInterval = null;
	
	if(this.cloneObject)
	{
		this.cloneObject.setStyle({filter:'alpha(opacity=100)', opacity:1});
	}
}

/**
 * @param obj {HTMLElement} Ez az objektum indítja a drag&drop funkciót
 * @param className {String} Az objektumon belül azok kerülnek be ebbe a listába aminek ez a class neve
 * @param tagName {String} Az objektumon belül azok kerülnek bele ebbe a listába aminek ez a tag neve ( ha class és tag név is megvan adva akkor mindkét szűkítés érvényes lesz)
 * @param drag {HTMLElement} Ez nem fontos,de ha megvan adva akkor ezt fogja mozgatni, ha nincs megadva akkor azt ami az első paraméterben megvolt adva
 */
dragAndDrop.prototype.assign = function(obj, filter, drag)
{
	if(!isElement(obj)) return false;
	
	var list = getElementsByFilter(obj, filter);	
	
	if(!list.length)
	{
		var list = new Array();
		list.push(obj);
	}
	
	this.assignNumber 		= list.length;
	this.assignTargetList	= new Array();
	for(var i=0; i<list.length ; i++)
	{
		obj = list[i];
		this.assignTargetList.push(obj);
		
		if(!isElement(drag))
			this.dragObject = obj;
		else
			this.dragObject = drag;
		
		
		obj.dragAndDrop = this;
		if(getBrowser().ie)obj.setAttribute('_dragObject', 'true');
		this.addEvent(obj, 'mousedown', null, this.handlerMouseDown);
		
	}
	return true;
}

dragAndDrop.prototype.clone = function()
{
	var bounds	= this.startObject;
	
	if(!this.noClone)
	{
		if(!this.cloneToBox)
			var e = create.div(null, null, null, {position:'absolute', width:bounds.width+'px', height:bounds.height+'px', left:bounds._x+'px', top:bounds._y+'px'}, document.getElementsByTagName('body').item(0));
		else
		{
			var e 					= create.div(null, null, 'drag-drop-box', 	{ position:'absolute', left:bounds._x+'px', top:bounds._y+'px', display:'block'}, document.getElementsByTagName('body').item(0));
			e.content				= create.div(null, null, 'ddb-content', null, e);
			e.shadow				= new Object();
			e.shadow.right			= create.div(null, null, 'shadow-right', null, e);
			e.shadow.right.round	= create.div(null, null, 'round', null, e.shadow.right);
			e.shadow.bottom			= create.div(null, null, 'shadow-bottom', null, e);
			e.shadow.bottom.round	= create.div(null, null, 'round', null, e.shadow.bottom);
			e.shadow.corner			= create.div(null, null, 'shadow-corner', null, e);
			e.appendChild = function(elm){ this.content.appendChild(elm); };
		}
		
		if(!this.noFullClone)
			var copy = fullCloneElement(this.dragObject);
		else
			var copy = copyElement(this.dragObject, e);
			
		if(this.cloneClassName)
			copy.addClassName(this.cloneClassName);
		
		e.appendChild(copy);
		
		this.cloneObject 			= e;
		this.cloneObject.original 	= copy.original;
		this.cloneObject.addClassName('drag-object');
	}
	else
	{
		var dragOb = this.dragObject;
		if(this.uproot)
		{
			var b = getBounds(this.dragObject);
			dragOb = document.getElementsByTagName('body').item(0).appendChild(this.dragObject);
			dragOb.style.left		= b._x+'px';
			dragOb.style.top		= b._y+'px';
			dragOb.style.position	= 'absolute';
			
			this.cloneObject = dragOb;
			this.cloneObject.original = dragOb;
			this.startObject = getBounds(dragOb);
		}
		else
		{
			this.cloneObject = dragOb;
			this.cloneObject.original = dragOb;
			
			this.cloneObject.style.left 	= this.cloneObject.offsetLeft+'px';
			this.cloneObject.style.top 		= this.cloneObject.offsetTop+'px';
			this.cloneObject.style.position = 'absolute';
		}			
	}
}

dragAndDrop.prototype.createCluster = function(obj, filter)
{
	if(!this.noClone)
	{
		if(!isElement(obj)) return false;
		var list = getElementsByFilter(obj, filter);
		if(!list.length) return false;
		
		this._clusterList = list;
		
		var cloneObject		= create.div(null, null, null, {position:'absolute'}, document.getElementsByTagName('body').item(0));
		var cloneWidth		= 0;
		var cloneHeight		= 0;
		var cloneLeft		= 0;
		var cloneTop		= 0;
		
		var startTop 	= list.item(0).offsetTop;
		var startLeft	= list.item(0).offsetLeft;
		
		for(var i=0 ; i<list.length ; i++)
		{
			var elm 			= list.item(i);
			var fullCloneElm 	= fullCloneElement(elm);
			if(i > 0)
			{
				
				var top 					= elm.offsetTop - startTop;
				var left					= elm.offsetLeft - startLeft;
				fullCloneElm.style.left 	= left+'px';
				fullCloneElm.style.top		= top+'px';
				fullCloneElm.style.position = 'absolute';
			}
			else
			{
				var top 	= 0;
				var left	= 0;
			}
			cloneWidth = Math.max(cloneWidth, left);
			cloneHeight = Math.max(cloneHeight, top);
			cloneObject.appendChild(fullCloneElm);
		}
		var bounds = getBounds(this.dragObject);
        cloneHeight += bounds.height;
        cloneWidth 	+= bounds.width;
		cloneLeft	= bounds._x-this.dragObject.offsetLeft+startLeft;
		cloneTop	= bounds._y-this.dragObject.offsetTop+startTop;		
		
		cloneObject.setStyle({width:cloneWidth+'px', height:cloneHeight+'px', left:cloneLeft+'px', top:cloneTop+'px'});
		this.setDragObject(cloneObject);
		return true;
	}
	return false;
}

dragAndDrop.prototype.checkValidTarget = function(event)
{
	if(this.dropTargetList.length == 0)
	{
		this.dropTarget	 = null;
		this.validTarget = true;	
		return true;
	}
	
	//var drag		= this.cloneObjectBounds;
	var drag		= null;
	var mouse		= null;
		
	for(var i=0 ; i<this.dropTargetList.length ; i++)
	{
		var curr = this.dropTargetList[i];
		 
		if(curr.type == 'object')
		{
			if(drag == null) drag = getBounds(this.cloneObject);
			if(boxIntercept(curr.bounds, drag))
			{
				this.dropTarget		= curr.obj;
				this.dropTarget.cb	= curr.cb;
				this.validTarget 	= true;
				if(isObject(curr.cb))
				{
					var _OBJ = isObject(curr.cb.obj) ? curr.cb.obj : window;
					if(isFunction(_OBJ[curr.cb.method])) this.validTarget = _OBJ[curr.cb.method](this, curr.cb.param);
					else if(curr.cb.event) this.validTarget = _OBJ.fireEvent(curr.cb.event,{dragAndDrop:this,sourceComponent:_OBJ},false);
				}
				return this.validTarget;
			}
		}
		else if(curr.type == 'mouse')
		{
			if(mouse == null) mouse = getMouseCoords(event);
			var bound = {};
			
			if( isElement(this.scrollContainer) )
			{
				bound._x = curr.bounds._x - this.scrollContainer.scrollLeft;
				bound._y = curr.bounds._y - this.scrollContainer.scrollTop;
				bound.width = curr.bounds.width;
				bound.height = curr.bounds.height;				
			}
			else
				bound = curr.bounds;
			
			if(pointInBox(bound, mouse))
			{
				this.dropTarget			= curr.obj;
				this.dropTarget.cb		= curr.cb;
				this.validTarget 		= true;
				this.dropTargetAlign	= 0;
				
				for(var align in this.dropAlignsPercent)
				{
					if( (this.dropAligns & align) != align ) continue;
					if(this._getPointInBoxSegment(bound, mouse, align, this.dropAligns))
					{
						this.dropTargetAlign = align;
						break;
					}
				}
				
				if(isObject(curr.cb))
				{
					var _OBJ = isObject(curr.cb.obj) ? curr.cb.obj : window;
					if(curr.cb.event) this.dropTargetAlign = _OBJ.fireEvent(curr.cb.event,{dragAndDrop:this,sourceComponent:_OBJ},false);
					if(curr.cb.method) this.dropTargetAlign = _OBJ[curr.cb.method](this);
				}
				
				if(this.dropTargetAlign === false)
					this.validTarget = false;
				else
					this.validTarget = ((this.dropAligns & this.dropTargetAlign) == this.dropTargetAlign) ? true : false;
				
				return this.validTarget;
			}		
		}		
		
	}
	
	this.dropTarget		= null;
	this.validTarget 	= false;
	return false;
}

dragAndDrop.prototype.changeMouseStyle = function(remove)
{
	var body = document.getElementsByTagName('body').item(0);
	if(!remove)
	{
		if(this.validTarget)
		{
			body.delClassName(this.cursor.noDrop);
			body.addClassName(this.cursor.drag);	
		}
		else
		{
			body.delClassName(this.cursor.drag);
			body.addClassName(this.cursor.noDrop);	
		}
	}
	else
	{	
		body.delClassName(this.cursor.drag);
		body.delClassName(this.cursor.noDrop);
	}
}

/**
 * @param obj {HTMLElement} Lehetséges hely hozzáadása, hogy lehessen leejteni az objektumot
 * @param className {String} Az objektumon belül azok kerülnek be ebbe a listába aminek ez a class neve
 * @param tagName {String} Az objektumon belül azok kerülnek bele ebbe a listába aminek ez a tag neve ( ha class és tag név is megvan adva akkor mindkét szűkítés érvényes lesz)
 * @param type {String} Az ellenőrzés típúsa : mouse( egérkordinátát vizsgálja ), object ( az objektum határait vizsgálja )
 */
dragAndDrop.prototype.addDropTarget = function(obj, filter, type, cb, offset)
{
	if(isElement(obj) || isNodeList(obj))
	{
		type = (isUndefined(type) ? 'object' : type);
		
		if(isNodeList(obj))
			list = obj;
		else
			list = getElementsByFilter(obj, filter);
		
		if(!list.length)
		{
			var list = new Array();
			list.push(obj);
		}
		
		this.temp['addDropTargetParams'] = {obj:obj, filter:filter, type:type, cb:cb, offset:offset};
		
		for(var i=0; i<list.length ; i++)
		{
			var bound = getBounds(list[i]);
			if(isObject(offset))
			{
				if(offset._x)		bound._x 		+= offset._x;
				if(offset._y)		bound._y 		+= offset._y;
				if(offset.width)	bound.width 	+= offset.width;
				if(offset.height)	bound.height 	+= offset.height;
			}
			list[i].dtIndex = this.dropTargetList.length;
			this.dropTargetList.push({obj:list[i], bounds:bound, type:type, cb:cb, index:this.dropTargetList.length});
		}
	}
}

dragAndDrop.prototype.setBorder = function(param, offset)
{
	if(isElement(param)) 	this.border = getBounds(param);
	else
	if(isObject(param))		this.border = param;	
	if(isObject(offset))
	{
		if(offset._x)		this.border._x 		+= offset._x;
		if(offset._y)		this.border._y 		+= offset._y;
		if(offset.width)	this.border.width 	+= offset.width;
		if(offset.height)	this.border.height 	+= offset.height;
		if(offset._x === null) this.border._x  = null;
		if(offset._y === null) this.border._y  = null;
		if(offset.width === null) this.border.width  = null;
		if(offset.height === null) this.border.height  = null;
	}
	this.border.obj		= param;
	this.border.offset 	= offset;
}

dragAndDrop.prototype.setScrollContainer = function(node, param)
{
	if( (list = getElementsByFilter(node, param)) )
	{
		if( !list.item(0) ) return false;
		
		this.scrollContainer = list.item(0);		
		var step = this.scrollStep;
		var interval = this.scrollInterval;
		var self = this;
		
		var checkValidTarget = function(event)
		{
			if(self.checkValidTarget(event))
				self.onOverDropTarget(event);			
		}
		
		var funcScrollBottom = function(event)
		{
			if( !this.scrollInterval )
			{
				this.scrollInterval = setInterval(function()
				{
					var scrollTop = self.scrollContainer.scrollTop + step;
					if( scrollTop >= self.scrollContainer.scrollHeight )
					{
						scrollTop = self.scrollContainer.scrollHeight;						
					}
					self.scrollContainer.scrollTop = scrollTop;
					checkValidTarget.call(self, event);
				}, interval);
			}
			
		}
		
		var funcScrollTop = function(event)
		{
			if( !this.scrollInterval )
			{
				this.scrollInterval = setInterval(function()
				{
					var scrollTop = self.scrollContainer.scrollTop - step;
					if( scrollTop <= 0 )
					{
						scrollTop = 0;						
					}
					self.scrollContainer.scrollTop = scrollTop;
					checkValidTarget.call(self, event);
				}, interval);
			}			
		}
		
		this.onBorderEvents.T.push(funcScrollTop);
		this.onBorderEvents.LT.push(funcScrollTop);
		this.onBorderEvents.RT.push(funcScrollTop);
		this.onBorderEvents.B.push(funcScrollBottom);
		this.onBorderEvents.RB.push(funcScrollBottom);
		this.onBorderEvents.RB.push(funcScrollBottom);
		this.onBorderEvents.ALL.push(function(event)
		{
			if(this.scrollInterval)
			{
				clearInterval(this.scrollInterval);
				this.scrollInterval = null;
			}
		});
	}
}

dragAndDrop.prototype.setDragObject = function(obj)
{
	if(isElement(this.cloneObject) && !this.noClone) this.cloneObject.del();
	this.cloneObject = obj;
	this.startObject = getBounds(obj);
}

dragAndDrop.prototype.refreshDropTarget = function(deep)
{
	if(deep === true)
	{
		var tmp = this.temp['addDropTargetParams'];
		if(isObject(tmp))
		{
			this.dropTargetList = new Array();
			this.addDropTarget(tmp.obj, tmp.filter, tmp.type, tmp.cb, tmp.offset);
		}
	}
	else
	{
		for(var k=0; k<this.dropTargetList.length ; k++)
		{
			this.dropTargetList[k].bounds = getBounds(this.dropTargetList[k].obj);		
		}
	}	
}

dragAndDrop.prototype.prevDropTarget = function(elm)
{
	if(isUndefined(elm.dtIndex)) return null;
	if(isUndefined(this.dropTargetList[elm.dtIndex-1])) return null;
	
	return this.dropTargetList[elm.dtIndex-1].obj;
}

dragAndDrop.prototype.nextDropTarget = function(elm)
{
	if(isUndefined(elm.dtIndex)) return null;
	if(isUndefined(this.dropTargetList[elm.dtIndex+1])) return null;
	
	return this.dropTargetList[elm.dtIndex+1].obj;
}

dragAndDrop.prototype.refreshBorder = function()
{
	if(isElement(this.border.obj))
		this.setBorder(this.border.obj, this.border.offset);
	else if( isElement(this.scrollContainer) )
		this.setBorder(this.scrollContainer, {_x:null, width:null});	
}

dragAndDrop.prototype.removeAllEvent = function()
{
	removeEvent(document, 'mousemove', null, this.handlerMouseMove);
	removeEvent(document, 'mouseup', null, this.handlerMouseUp);
	
	for(var i=0 ; i<this.assignTargetList.length ; i++)
	{
		removeEvent(this.assignTargetList[i], 'mousedown', null, this.handlerMouseDown);
	}	
}

dragAndDrop.prototype.handlerMouseMove = function(event)
{
	if(CURRENT_DRAG_DROP_OBJECT !== null && isObject(CURRENT_DRAG_DROP_OBJECT) && CURRENT_DRAG_DROP_OBJECT.enableDrag)
	{
		var mouse = getMouseCoords(event);
		var dragAndDrop = CURRENT_DRAG_DROP_OBJECT;
		if(!dragAndDrop.drag)
		{
			var sm 		= dragAndDrop.startMouse;
			var sens	= dragAndDrop.sensitive;
			if( (sm._x - sens >= mouse._x || sm._x + sens <= mouse._x) || (sm._y - sens >= mouse._y || sm._y + sens <= mouse._y) )
			{
				dragAndDrop.drag = true;
				if(dragAndDrop.cloneObject) dragAndDrop.startDrag(event);
			}	
		}
		else if(isElement(dragAndDrop.cloneObject))
		{
			var sm 		= dragAndDrop.startMouse;
			var so		= dragAndDrop.startObject;
			var dist 	= new Object();
				dist._x	= sm._x - mouse._x;
				dist._y	= sm._y - mouse._y;
			dragAndDrop.distance = dist;
			
			var newLeft	= so._x - dist._x;
			var newTop	= so._y - dist._y;
			
			if(dragAndDrop.scrollContainerOffset)
			{
				newLeft -= dragAndDrop.scrollContainerOffset._x;
				newTop -= dragAndDrop.scrollContainerOffset._y;
			}
			
			var border	= dragAndDrop.border;
			dragAndDrop.borderTest = {border:'', hit:false}
			
			if(border._x !== null && newLeft <= border._x){ newLeft = border._x; dragAndDrop.borderTest.border+= 'L'; dragAndDrop.borderTest.hit = true };
			if(border._x !== null && border.width !== null && newLeft >= border.width + border._x - so.width){ newLeft = border.width + border._x - so.width; dragAndDrop.borderTest.border+= 'R'; dragAndDrop.borderTest.hit = true}
			
			if(border._y !== null && newTop <= border._y){ newTop = border._y; dragAndDrop.borderTest.border+= 'T'; dragAndDrop.borderTest.hit = true }
			if(border._y !== null && border.height !== null && newTop >= border.height + border._y - so.height){ newTop = border.height + border._y - so.height; dragAndDrop.borderTest.border+= 'B'; dragAndDrop.borderTest.hit = true }
			
			if(dragAndDrop.axis._x)dragAndDrop.cloneObject.style.left = newLeft + 'px';
			if(dragAndDrop.axis._y)dragAndDrop.cloneObject.style.top = newTop + 'px';
			
			if(dragAndDrop.checkValidTarget(event))
				dragAndDrop.onOverDropTarget(event);
				
			dragAndDrop.executeOnBorderEvent(event);
				
			dragAndDrop.onDrag(dragAndDrop);
			
			dragAndDrop.changeMouseStyle();
			dragAndDrop._changeDropTargetClass();
		}
		else
		{
			if( isElement(dragAndDrop.scrollContainer) )
				dragAndDrop.scrollContainerOffset = {_x:dragAndDrop.scrollContainer.scrollLeft,_y:dragAndDrop.scrollContainer.scrollTop};				
			dragAndDrop.clone();
			dragAndDrop.startDrag(event);			
		}		
	}
	else
	{
		if(this.cloneObject)
			this.cloneObject.del();
	}
}
/*UGLY BY IE!!! :S*/
dragAndDrop.prototype.handlerMouseDown = function(event)
{
	if(getBrowser().ie)
	{
		var target = event.srcElement;
		while(target && target.getAttribute('_dragObject') != 'true')
		{
			target = target.parentNode;
		}
		CURRENT_DRAG_DROP_OBJECT = target.dragAndDrop;
		
		if(!CURRENT_DRAG_DROP_OBJECT.noClone)CURRENT_DRAG_DROP_OBJECT.dragObject = target;
		/*
		if(CURRENT_DRAG_DROP_OBJECT.assignNumber > 1)
		{
			
		}
		else
		{
			if(!CURRENT_DRAG_DROP_OBJECT.noClone)CURRENT_DRAG_DROP_OBJECT.dragObject = target.dragObject;
		}*/
	}
	else
	{
		CURRENT_DRAG_DROP_OBJECT = this.dragAndDrop;
		if(!CURRENT_DRAG_DROP_OBJECT.noClone)CURRENT_DRAG_DROP_OBJECT.dragObject = this;
		/*
		if(CURRENT_DRAG_DROP_OBJECT.assignNumber > 1)
		{
			
		}
		else
		{
			if(!CURRENT_DRAG_DROP_OBJECT.noClone)CURRENT_DRAG_DROP_OBJECT.dragObject = this.dragObject;
		}*/
	}
	
	if( !(CURRENT_DRAG_DROP_OBJECT instanceof dragAndDrop) ) return false;
	
	CURRENT_DRAG_DROP_OBJECT.disableSelection();
	CURRENT_DRAG_DROP_OBJECT.startMouse 	= getMouseCoords(event);
	
	if(!CURRENT_DRAG_DROP_OBJECT.noClone)
		var bounds = getBounds(CURRENT_DRAG_DROP_OBJECT.dragObject);
	else
		var bounds = {_x:CURRENT_DRAG_DROP_OBJECT.dragObject.offsetLeft, _y:CURRENT_DRAG_DROP_OBJECT.dragObject.offsetTop, width:CURRENT_DRAG_DROP_OBJECT.dragObject.offsetWidth, height:CURRENT_DRAG_DROP_OBJECT.dragObject.offsetHeight}
	
	CURRENT_DRAG_DROP_OBJECT.startObject = bounds;
	
	if(isString(CURRENT_DRAG_DROP_OBJECT.mouseAlign))
	switch(CURRENT_DRAG_DROP_OBJECT.mouseAlign.toUpperCase())
	{
		case 'LEFT-TOP':
			CURRENT_DRAG_DROP_OBJECT.startObject._x += CURRENT_DRAG_DROP_OBJECT.startMouse._x - CURRENT_DRAG_DROP_OBJECT.startObject._x;
			CURRENT_DRAG_DROP_OBJECT.startObject._x += 10;
			CURRENT_DRAG_DROP_OBJECT.startObject._y += CURRENT_DRAG_DROP_OBJECT.startMouse._y - CURRENT_DRAG_DROP_OBJECT.startObject._y;
			CURRENT_DRAG_DROP_OBJECT.startObject._y += 10;
		break;
	
		case 'RIGHT-TOP':			
		break;
	
		case 'LEFT-BOTTOM':
		break;
	
		case 'RIGHT-BOTTOM':
		break;
	}
}

dragAndDrop.prototype.handlerMouseUp = function(event)
{
	if(CURRENT_DRAG_DROP_OBJECT instanceof dragAndDrop)
	{
		if(isFunction(CURRENT_DRAG_DROP_OBJECT.endDrag))
			CURRENT_DRAG_DROP_OBJECT.endDrag(event);
		CURRENT_DRAG_DROP_OBJECT = null;
	}
}

dragAndDrop.prototype.disableSelection = function()
{
	disableSelection(document.getElementsByTagName('body').item(0));
}

dragAndDrop.prototype.enableSelection = function()
{
	enableSelection(document.getElementsByTagName('body').item(0));
}

dragAndDrop.prototype.drawDropTargetBounds = function()
{
	var list = this.dropTargetList;
	if(list.length)
	{
		for(var k=0 ; k<list.length ; k++)
		{
			create.div(null, 'x:'+list[k].bounds._x+'<br />y:'+list[k].bounds._y+'<br />w:'+list[k].bounds.width+'<br />h:'+list[k].bounds.height+'<br />', null, {position:'absolute', left:list[k].bounds._x+'px', top:list[k].bounds._y+'px', width:list[k].bounds.width+'px', height:list[k].bounds.height+'px', backgroundColor:'#80FFFF', opacity:0.5, filter:'alpha(opacity=50)', fontSize:'12px', fontWeight:'bold', color:'#000000'}, document.getElementsByTagName('body').item(0));
		}
	}
}

dragAndDrop.prototype.disableDrag = function()
{
	this.enableDrag = false;
	this.endDrag(null, true);
}

dragAndDrop.prototype.drawBorder = function()
{
	if(this.border)
	{
		var styleLeft	= { left:this.border._x+'px', top:this.border._y+'px', width:'0px', height:this.border.height+'px', position:'absolute', borderRight:'2px dashed #ffd200', backgroundColor:'#333333' };
		var styleTop	= { left:this.border._x+'px', top:this.border._y+'px', width:this.border.width+'px', height:'0px', position:'absolute', borderBottom:'2px dashed #ffd200', backgroundColor:'#333333' };
		var styleRight	= { left:this.border._x+this.border.width+'px', top:this.border._y+'px', width:'0px', height:this.border.height+'px', position:'absolute', borderLeft:'2px dashed #ffd200', backgroundColor:'#333333' };
		var styleBottom	= { left:this.border._x+'px', top:this.border._y+this.border.height+'px', width:this.border.width+'px', height:'0px', position:'absolute', borderTop:'2px dashed #ffd200', backgroundColor:'#333333' };
		
		create.div(null, null, null, styleLeft, document.getElementsByTagName('body').item(0));
		create.div(null, null, null, styleTop, document.getElementsByTagName('body').item(0));
		create.div(null, null, null, styleRight, document.getElementsByTagName('body').item(0));
		create.div(null, null, null, styleBottom, document.getElementsByTagName('body').item(0));
	}
}

dragAndDrop.prototype.getDropAligText = function(dda)
{
	dda = dda ? dda : this.dropTargetAlign;
	
	if(dda == DDA_BOTTOM)	return 'bottom';
	if(dda == DDA_RIGHT)	return 'right';
	if(dda == DDA_TOP)		return 'top';
	if(dda == DDA_LEFT)		return 'left';
	if(dda == DDA_INNER)	return 'inner';
}

dragAndDrop.prototype.executeOnBorderEvent = function(event)
{
	if( this.borderTest.hit )
	{
		this.onBorder(event);
		if( this.onBorderEvents[this.borderTest.border] )
		{
			var el = this.onBorderEvents[this.borderTest.border];
			for(var i=0, func ; func = el[i] ; i++ )
				if(isFunction(func)) func.call(this, event);			
		}
	}
	else
	{
		var el = this.onBorderEvents['ALL'];
		for(var i=0, func ; func = el[i] ; i++ )
			if(isFunction(func)) func.call(this, event);		
	}
}

dragAndDrop.prototype._getPointInBoxSegment = function(box, point, segment, validSegment)
{
    var segmentPercent 	= this.dropAlignsPercent[segment];
	var bound			= {_x:0,_y:0,width:0,height:0};
	//var body			= document.getElementsByTagName('body').item(0);
	
	if(segment == DDA_BOTTOM)
	{
		bound._y = box._y + box.height * ( (100 - segmentPercent) / 100);
		bound._x = box._x;
		bound.height = box.height * segmentPercent / 100;
		bound.width	= box.width;
		
		//create.box(null, {backgroundColor:'#CC3300'}, bound, body);
	}
	else if(segment == DDA_INNER)
	{
		bound._y 		= box._y;
		bound._x 		= box._x;
		bound.width 	= box.width;
		bound.height 	= box.height;
		
		if( (validSegment & DDA_TOP) == DDA_TOP )
		{
			bound._y += box.height - box.height * ( ( 100 - this.dropAlignsPercent[DDA_TOP] ) / 100 );
			bound.height -= box.height * ( this.dropAlignsPercent[DDA_TOP] / 100 );
		}
		
		if( (validSegment & DDA_BOTTOM) == DDA_BOTTOM )
		{
			bound.height -= box.height * ( this.dropAlignsPercent[DDA_BOTTOM] / 100 );
		}
		
		if( (validSegment & DDA_LEFT) == DDA_LEFT )
		{
			bound._x += box.width - box.width * ( ( 100 - this.dropAlignsPercent[DDA_LEFT] ) / 100 )
			bound.width -= box.width * ( this.dropAlignsPercent[DDA_LEFT] / 100 );
		}
		
		if( (validSegment & DDA_RIGHT) == DDA_RIGHT )
		{
			bound.width -= box.width * ( this.dropAlignsPercent[DDA_RIGHT] / 100 );
		}
		//create.box(null, {backgroundColor:'#CCCCCC'}, bound, body);
	}
	else if(segment == DDA_LEFT)
	{
		bound._y = box._y;
		bound.height = box.height;
		bound.width = box.width - box.width * ( ( 100 - segmentPercent ) / 100 );
		bound._x = box._x;
		
		//create.box(null, {backgroundColor:'#0033CC'}, bound, body);
	}
	else if(segment == DDA_RIGHT)
	{
		bound._y = box._y;
		bound.height = box.height;
		bound.width = box.width - box.width * ( ( 100 - segmentPercent ) / 100 );
		bound._x = box._x + box.width * ( ( 100 - segmentPercent ) / 100 );
		
		//create.box(null, {backgroundColor:'#CC33CC'}, bound, body);
	}
	else if(segment == DDA_TOP)
	{
		bound._y = box._y;
		bound._x = box._x;
		bound.height = box.height * segmentPercent / 100;
		bound.width	= box.width;
		
		//create.box(null, {backgroundColor:'#123450'}, bound, body);
	}
	return pointInBox(bound, point);
}

dragAndDrop.prototype._changeDropTargetClass = function(remove)
{
    for(var i=0 ; i<this.dropTargetList.length ; i++)
	{
		var curr = this.dropTargetList[i];
		
		curr.obj.delClassName(this.dropAlignClassName[DDA_BOTTOM]);
		curr.obj.delClassName(this.dropAlignClassName[DDA_INNER]);
		curr.obj.delClassName(this.dropAlignClassName[DDA_LEFT]);
		curr.obj.delClassName(this.dropAlignClassName[DDA_RIGHT]);
		curr.obj.delClassName(this.dropAlignClassName[DDA_TOP]);
		
		if( (curr.obj == this.dropTarget && this.validTarget) && !remove)
		{
			curr.obj.addClassName(this.dropAlignClassName[this.dropTargetAlign]);
		}		
	}
}

dragAndDrop.prototype.destroy = function()
{
	this.removeAllEvent();	
}

