/** * Drag Module * © 2002-2006 Garrett Smith * @version 2.0 *//** DragObj * *  @param el         type: HTMLElement the element to drag *  @param constraint type: int  *  @see DragObj.constraints */DragObj = function(el, constraint){	this.id = el.id;	this.el = this.origEl = el;	this.isRel = getStyle(el, "position").toLowerCase() == "relative";	this.container = (this.isRel ? el.parentNode : getContainingBlock(el));	this.dropTargets = [];	this.handle = this.el;	this.constraint = constraint||0;		this.el.style.zIndex = getStyle(el, "z-index") || DragObj.highestZIndex++;	if(ua.ie||ua.safari)		setIeTopLeft(el);	Listener.add(el, "onfocus", DragObj.focused, this)	Listener.add(el, "onblur", DragObj.blurred, this)};DragObj.instances = [];DragObj.getInstance = function(el, constraint) {	if(!el.id)		el.id = "DragObj" + DragObj.instances.length;	var instance = DragObj.instances[el.id];	if(instance == null)		instance = DragObj.instances[el.id] 			= DragObj.instances[DragObj.instances.length] = new DragObj(el, constraint);	return instance;};DragObj.focused = function(e) {	DragObj.getInstance(this).focusEventReceived(e); };DragObj.blurred = function(e) {	DragObj.getInstance(this).blurEventReceived(e); };DragObj.constraints = {	NONE : 0,	HORZ : 1,	LEFT : 3,	RIGHT: 5,		VERT : 2,	UP   : 4,	DOWN : 6	};DragObj.prototype = {	x : 0,	y : 0,	_origX : 0,	_origY : 0,		grabX : 0,	grabY : 0,		/** Where it will move to next. onbeforedrag */	newX : 0, 	newY : 0,	/**	 * returns position of where element is initially dragged from.	 */	origX : function() { return this._origX; },	origY : function() { return this._origY; },			isDragEnabled : true,		hasFocus : false,		dragCopy : false,		dragMultiple : false,		onfocus : function(){},	onblur : function() {},		setFocus : function(isFocus) {		this.hasFocus = isFocus;		if(isFocus) {			this.onfocus();			if(!this.dragMultiple)				DragHandlers.focusedElement = this;		}		else			this.onblur();	},		focusEventReceived : function(e) {		DragHandlers.removeGroupFocus();		this.setFocus(true);	},		blurEventReceived : function(e) {		this.setFocus(false);	},		dropTargets : [],		isOnDropTarget : false,		onbeforedragstart : function(e){ return true; },	ondragstart : function(e){},		/** Being dragged */	ondrag : function(e){},	/** Will be dragged */	onbeforedrag : function(e){ return true; },	/** Dragging stopped before it escaped its container. */	ondragstop : function(e){},	/** Dragging completed (as a result of mouseup). */	ondragend : function(e){},	/** Hit a droptarget. */	ondragdrop : function(e){ },	keepInContainer : false,	onbeforeexitcontainer : function() { return !this.keepInContainer; },		setOrigX : function(origX) {		this._origX = origX;	},	setOrigY : function(origY) {		this._origY = origY;	},		getPosLeft : function() {		return this.el.style.pixelLeft || parseInt(getStyle(this.el, "left"))||0;	},		getPosTop : function() {		return this.el.style.pixelTop || parseInt(getStyle(this.el, "top"))||0;	},		constraint : DragObj.constraints.NONE,		enableDrag : function() {		this.isDragEnabled = true;	},			disableDrag : function() {		this.isDragEnabled = false;			},		isBeingDragged : false,		handle : null,		hasHandleSet : false,	isDragStopped : false,		useHandleTree : true,		setHandle : function(el, setHandleTree){		this.handle = el;		this.hasHandleSet = true;		// Make sure user didn't forget the secondParam and expect true.		this.useHandleTree = setHandleTree != false;	},		isInHandle : function(target) { 		return !this.hasHandleSet || target == this.handle || (this.useHandleTree && contains( this.handle, target )); 	},	getContainerWidth : function() {		return this.container.clientWidth || parseInt(getStyle(this.container, "width"));	},		getContainerHeight : function() {		return this.container.clientHeight || parseInt(getStyle(this.container, "height"));	},		/** @param dropTarget (DropTarget or HTMLElement) HTMLElement only for bkwd compat.	 * use of HTMLElement as param type is deprecated.	 */	addDropTarget : function(dropTarget) {		var el = document.getElementById(dropTarget.id);		if(this.el == el) return;		return this.dropTargets[this.dropTargets.length] = DropTarget.getInstance(el);	},		grab : function(e, xOffset, yOffset) {			if(!e) e = window.event;				var target = getTarget(e);		if(e.preventDefault) e.preventDefault();		e.returnValue = false;				if(contains(this.el, target)) return; 		 		this.grabX = this.getPosLeft(); 		this.grabY = this.getPosTop(); 				var offsetY = eventPageY(e) - getOffsetTop(getContainingBlock(this.el));		var newY = offsetY - (this.el.offsetHeight)/2;		var moved = false;		if(this.constraint != DragObj.constraints.VERT) {			// Center the dragObject around the coords, but keep it inside.			var offsetX = eventPageX(e) - getOffsetLeft(getContainingBlock(this.el));			var newX = offsetX - (this.el.offsetWidth)/2;			newX = Math.max(newX, 0);			newX = Math.min(newX, this.getContainerWidth() - this.el.offsetWidth);			this.moveToX(newX- getOffsetLeft(this.handle, this.el) + (xOffset||0));			moved = true;		}		if(this.constraint != DragObj.constraints.HORZ) {			newY = Math.max(newY, 0);			newY = Math.min(newY, this.getContainerHeight() - this.el.offsetHeight);			this.moveToY(newY - getOffsetTop(this.handle, this.el) + (yOffset||0));			moved = true;		}		if(moved)			this.ondrag(e);		DragHandlers.dragObjGrabbed(e, this);			DragHandlers.dO = this;	},		release : function(e) {		DragHandlers.dragObjReleased(e, this);	},		checkDragClones : function() {		if(this.dragCopy) {			if(!this.origEl)				this.origEl = this.el;			if(!this.copyEl) {				this.copyEl = this.el.cloneNode(true);			}			else {				this.copyEl.style.display = "";			}			this.el.parentNode.insertBefore(this.copyEl, this.el);			this.copyEl.style.zIndex = this.origEl.style.zIndex + 1;			this.el = this.copyEl;		}		for(var id in DragObj.draggableList) {			var item = DragObj.draggableList[id];			if(item.dragCopy) {				if(!item.origEl)					item.origEl = item.el;				if(!item.copyEl) {					item.copyEl = item.el.cloneNode(true);				}				else					item.copyEl.style.display = "";				item.el.parentNode.insertBefore(item.copyEl, item.el);					item.copyEl.style.zIndex = item.origEl.style.zIndex + 1;				item.el = item.copyEl;			}		}		},		moveToX : function(x) {		this.el.style.left = (this.x = x) + "px";	},		moveToY : function(y) {		this.el.style.top = (this.y = y) + "px";	},	carryGroup : function(distX, distY) {		for(var id in DragObj.draggableList) {			var o = DragObj.draggableList[id];			if(distX != null)				o.moveToX( o.origX() + distX );			if(distY != null)				o.moveToY( o.origY() + distY );		}	},		glideStart : function(x, y) {		if(this.animTimer) return;				this.startX = x;		this.startY = y;		this.GlideDist = Math.ceil(Math.sqrt(Math.pow(this.startX - this.grabX, 2) 			+ Math.pow(this.startY - this.grabY, 2)));				this.rx = Math.abs(this.startX-this.grabX)/this.GlideDist;		this.ry = Math.abs(this.startY-this.grabY)/this.GlideDist;		if(this.x > this.grabX)			this.rx = -this.rx;		if(this.y > this.grabY)			this.ry = -this.ry;				this.startTime = new Date().getTime();				this.animTimer = window.setInterval("DragObj.instances['"+this.id+"'].glide()", 10);	},	glide : function() {		var t = new Date().getTime() - this.startTime;		// 2px per 10ms slight acceleration 10px/s		var d = Math.ceil(2 * t + .5 * .01 * t*t);		if(d >= this.GlideDist) {			this.animTimer = clearInterval(this.animTimer);			this.moveToX( this.grabX );			this.moveToY( this.grabY );			if(this.copyEl) {				this.el = this.origEl;				this.copyEl.style.display = "none";			}		}		else { 			this.moveToX(this.startX + d * this.rx); 			this.moveToY(this.startY + d * this.ry);		}	},		animateBack : function(x, y) { 		this.glideStart(x||this.x, y||this.y);	},			setContainer : function(el) {		this.container = el;	},		removeDropTarget : function(el){				var newTargets = new Array(this.dropTargets.length-1);		var removed = null;				for(var i = 0, len = this.dropTargets.length; i < len; i++)			if(this.dropTargets[i].el == el)				removed = el;			else newTargets[i] = this.dropTargets[i];		return removed;	},				toString : function() {		return this.id;	}};DragObj.highestZIndex = 1000;DragObj.draggableList = { };/** DropTarget * * properties: *  el  -  the HtmlElement *  * methods:  * getX() * getY() * getWidth() * getHeight() */DropTarget = function(el){	this.el = el;	this.id = el.id;};DropTarget.instances = { };DropTarget.getInstance = function(el) {	return DropTarget.instances[el.id] || (DropTarget.instances[el.id] = new DropTarget(el));};DropTarget.prototype = {		hasDropTargetOver : false,		getX : function(){ return getOffsetLeft(this.el) - 		(ua.isNotUsingPaddingEdge ? parseInt(getStyle(this.el, "padding-left"))||0 : 0);	},	getY : function(){ return getOffsetTop(this.el) - 		(ua.isNotUsingPaddingEdge ? parseInt(getStyle(this.el, "padding-top"))||0 : 0);	},	getWidth : function(){ return this.el.offsetWidth; },	getHeight : function(){ return this.el.offsetHeight; },	/** Dragged over a droptarget **/	ondragover : function(e){ }, 	ondragout : function(e){ },	ondrop : function(e){ }};DropTarget.prototype.ondragover.isSet = true;DropTarget.instances = {};DropTarget.getInstance = function(el) {	var instance = DropTarget.instances[el.id];	if(instance == null)		instance = DropTarget.instances[el.id] = new DropTarget(el);	return instance;};/** DragHandlers * * properties: *    *  * methods:  * mouseDown - initializes dragging * * mouseMove - tracks the mouse position and updates dO * * mouseUp   - releases any dO and calls ondragend, *             passing the event. The event has a dropTarget  *             property, which may be null. *  */DragHandlers = {		dO : null,	instances : [],		inited : false,		init : function(){				if(this.inited)			return;				Listener.add(document, "onmousedown", this.mouseDown);		Listener.add(document, "onkeypress", this.keyPressed);		Listener.add(document, "onmousemove", this.mouseMove);		Listener.add(document, "onmouseup", this.mouseUp);		 // prevent text selection while dragging.		document.onselectstart = document.ondragstart = function() { return DragHandlers.dO == null; };				this.inited = true;	},	dragObjGrabbed : function(e, dO) {			DragHandlers.locked = true;				dO.setFocus(true);		dO.el.style.zIndex = ++DragObj.highestZIndex;		DragHandlers.mousedownX = (e.pageX ? e.pageX : e.clientX + getScrollLeft());		DragHandlers.mousedownY = (e.pageY ? e.pageY : e.clientY + getScrollTop());				dO.setOrigX(dO.grabX = dO.getPosLeft());  		dO.setOrigY(dO.grabY = dO.getPosTop());						// subtract in-flow offsets.		var inFlowOffsetX = dO.el.offsetLeft - dO.getPosLeft() 			+ getOffsetLeft(getContainingBlock(dO.el), dO.container); 		var inFlowOffsetY = dO.el.offsetTop - dO.getPosTop()			+ getOffsetTop(getContainingBlock(dO.el), dO.container); 				// Impl Note: Don't use margins for absolutely positioned elements for Safari.		// Safari calculates offsetTop from parentNode border edge (not padding edge).  		// Safari can't read style values from styleSheets.  		// Safari also adds parentNode border-width to offsetLeft.   		// This poor approach can only work if the parentNode has no border.		if(ua.safari && !dO.isRel) {			if(!getStyle(dO.el, "left")) {				dO.setOrigX(dO.grabX = dO.el.offsetLeft);				inFlowOffsetX = 0;			}			if(!getStyle(dO.el, "top")) {				dO.setOrigY(dO.grabY = dO.el.offsetTop);				inFlowOffsetY = 0;			}		}				if(ua.macIE || ua.safari) {			// Safari should need this patch, but this patch fails because safari can't read styles.			inFlowOffsetX -= parseInt(getStyle(dO.el, "border-left-width"))||0;			inFlowOffsetY -= parseInt(getStyle(dO.el, "border-top-width"))||0;		}				if(ua.isNotUsingPaddingEdge)  { // Mac IE and Opera.			inFlowOffsetX -= parseInt(getStyle(dO.el, "padding-left")) || 0;			inFlowOffsetY -= parseInt(getStyle(dO.el, "padding-top")) || 0;		}				dO.minX = 0 - inFlowOffsetX;		dO.maxX = dO.getContainerWidth() - dO.el.offsetWidth - inFlowOffsetX;		dO.minY = 0 - inFlowOffsetY;		dO.maxY = dO.getContainerHeight() - dO.el.offsetHeight - inFlowOffsetY;		 		dO.isBeingDragged = false;	},		mouseDown : function(e) {	 		 			if(!e) 			e = window.event;					var target = getTarget(e);					var dO = null;				for(var testNode = target;dO == null && testNode != null;									testNode = findAncestorWithAttribute(testNode, "id", "*")) {			if(testNode != null) {				dO = DragObj.instances[testNode.id];			}		}	 	if(dO) {			var handle = dO.handle; 					if( dO.hasHandleSet && !dO.isInHandle( target ) ) {				if(!DragHandlers.locked) {					DragHandlers.removeGroupFocus();					DragHandlers.dO = null;					DragHandlers.locked = false;		 		}				return false;			}	 			 		else if("preventDefault" in e) 				e.preventDefault(); 			else e.returnValue = false; 		} 		else {			DragHandlers.removeGroupFocus();			if(!DragHandlers.locked) {				DragHandlers.dO = null;		 		DragHandlers.locked = false;		 	}			return;		}		var metaKey = e.metaKey || (ua.win && e.ctrlKey); 		if(metaKey && dO.hasFocus) {			dO.setFocus(false);			delete DragObj.draggableList[dO.id];			if(DragHandlers.focusedElement == dO) {				DragHandlers.focusedElement = null;			}			return;		}		// Determine focusedElement or otherwise setFocus( false ) to group.		if(DragHandlers.focusedElement) { 			// make sure we're not in the tree (above or below).			var isInTree = contains(dO.el, DragHandlers.focusedElement.el) || contains(DragHandlers.focusedElement.el, dO.el); 						if(metaKey && !isInTree) {				if(dO.dragMultiple 					&& DragHandlers.focusedElement == null 					|| DragHandlers.focusedElement.dragMultiple					&& DragHandlers.focusedElement.container == dO.container) {					DragObj.draggableList[DragHandlers.focusedElement.id] = DragHandlers.focusedElement;				}				else 					DragHandlers.removeGroupFocus();			}			else if(dO.id in DragObj.draggableList) {				delete DragObj.draggableList[dO.id];				if(DragHandlers.focusedElement && DragHandlers.focusedElement != dO					&& DragHandlers.focusedElement.container == dO.container) {					DragObj.draggableList[DragHandlers.focusedElement.id] = DragHandlers.focusedElement;					DragHandlers.focusedElement = dO;				}			}			else if(DragHandlers.focusedElement != dO)				DragHandlers.removeGroupFocus();		}		 		DragHandlers.focusedElement = dO; 		if(false == dO.onbeforedragstart(e)) return true;		DragHandlers.dragObjGrabbed(e, dO);		for(var id in DragObj.draggableList) {			DragHandlers.dragObjGrabbed(e, DragObj.draggableList[id]);		}		DragHandlers.dO = dO;	},	dragObjReleased : function(e, dO) {		var group = DragObj.draggableList;		dO.animateBack();		for(var id in DragObj.draggableList) {			var item = DragObj.draggableList[id];			item.animateBack();		}		DragHandlers.dO = null;	},		removeGroupFocus : function() {		if(DragHandlers.focusedElement) {			DragHandlers.focusedElement.setFocus(false);		}		for(var id in DragObj.draggableList) {			DragObj.draggableList[id].setFocus(false);		}		DragObj.draggableList = { };	},	mouseMove : function(e) {		var dO = DragHandlers.dO;				if(e == null)			e = event;				if(dO == null || dO.el.style == null || !dO.isDragEnabled)			return; 		var distX = eventPageX(e) - DragHandlers.mousedownX;		var distY = eventPageY(e) - DragHandlers.mousedownY;				 		dO.newX = dO.origX() + distX;		dO.newY = dO.origY() + distY;				// drag the bitch.				if(dO.isBeingDragged == false) {			dO.checkDragClones();			dO.ondragstart(e);			for(var id in DragObj.draggableList) 				DragObj.draggableList[id].ondragstart(e);		}		dO.isBeingDragged = true;		dO.hasBeenDragged = (dO.hasBeenDragged || Boolean(distX || distY));						// Drag constraints. 		//if(dO.container != null)		//	dO.keepInContainer();				var constraints = DragObj.constraints;						var isLeft = dO.newX < dO.minX;		var isRight = dO.newX > dO.maxX;		var isAbove = dO.newY < dO.minY;		var isBelow = dO.newY > dO.maxY; 				if(dO.onbeforedrag(e) == false) return;				var isOutsideContainer = dO.container != null;				if(dO.constraint == DragObj.constraints.NONE) { // no constraint. Life is hard.						isOutsideContainer &= ( isLeft || isRight || isAbove || isBelow );						var planesStopped = 0;			if(isOutsideContainer && dO.onbeforeexitcontainer() == false) {				if(isLeft) {					if(!dO.isAtLeft) {						dO.moveToX( dO.minX );						// dO.minX - dO.origX() = max possible negative distance to travel.						dO.carryGroup(dO.minX - dO.origX(), null);						dO.ondrag(e);						dO.isAtRight = false;						dO.isAtLeft = true;						planesStopped += 1;					}				}				else if(isRight) {					if(!dO.isAtRight) {						dO.moveToX( dO.maxX );						// dO.maxX - dO.origX() = max possible positive distance to travel.						dO.carryGroup(dO.maxX - dO.origX(), null);						dO.ondrag(e);						dO.isAtRight = true;						dO.isAtLeft = false;						planesStopped += 1;					}				}				else {					dO.isAtLeft = dO.isAtRight = false;					dO.moveToX( dO.newX );					dO.carryGroup(distX, null);				}				if(isAbove) {					if(!dO.isAtTop) {						var sy = dO.y;						dO.moveToY( dO.minY );						// dO.minY - dO.origY() = max possible positive distance to travel.						dO.carryGroup(null, dO.minY - dO.origY());						dO.ondrag(e);						dO.isAtTop = true;						dO.isAtBottom = false;						planesStopped += 1;					}				}				else if(isBelow) {					if(!dO.isAtBottom) {						var sy = dO.y;						dO.moveToY( dO.maxY );						// dO.maxY - dO.origY() = max possible positive distance to travel.						dO.carryGroup(null, dO.maxY - dO.origY());						dO.ondrag(e);						dO.isAtTop = false;						dO.isAtBottom = true;						planesStopped += 1;					}				}				else {					dO.isAtTop = dO.isAtBottom = false;					dO.moveToY( dO.newY );					dO.carryGroup(null, distY);				}								dO.isDragStopped = planesStopped == 2;								if(dO.isDragStopped)					dO.ondragstop(e);				else					dO.ondrag(e);			}			else {			// In container.				dO.isDragStopped = dO.isAtLeft = dO.isAtRight =					dO.isAtTop = dO.isAtBottom = false;				dO.moveToX( dO.newX );				dO.moveToY( dO.newY );				dO.carryGroup(distX, distY);				dO.ondrag(e);			}		}				else {  // A constraint. 					// A VERT type constraint? 			if(dO.constraint % 2 == 0) {			  			  					isOutsideContainer &= (isAbove || isBelow);				if(isOutsideContainer && dO.onbeforeexitcontainer() == false) {					if(isAbove) {						if(!dO.isAtTop) {							dO.moveToY( dO.minY );							// dO.minY - dO.origY() = max possible positive distance to travel.							dO.carryGroup(null, dO.minY - dO.origY());							dO.ondrag(e);							dO.isAtTop = !(dO.isAtBottom = false);						}					}					else if(isBelow) {						if(!dO.isAtBottom) {							dO.moveToY( dO.maxY );							// dO.maxY - dO.origY() = max possible positive distance to travel.							dO.carryGroup(null, dO.maxY - dO.origY());							dO.ondrag(e);							dO.isAtBottom = !(dO.isAtTop = false);						}					}					if(!dO.isDragStopped) {						dO.ondragstop(e);						dO.isDragStopped = true;					}				}				else { // in container.					dO.isAtTop = dO.isAtBottom = false;					dO.isDragStopped = false;					dO.moveToY( dO.newY );					dO.carryGroup(null, distY);					dO.ondrag(e);				}			}						// A HORZ type constraint? 			else {			  				isOutsideContainer &= (isLeft || isRight);								if(isOutsideContainer && dO.onbeforeexitcontainer() == false) {						if(isLeft) {  						if(!dO.isAtLeft) {							dO.moveToX( dO.minX );							// dO.minX - dO.origX() = max possible negative distance to travel.							dO.carryGroup(dO.minX - dO.origX(), null);							dO.isAtLeft = !(dO.isAtRight = false);						}					}					else if(isRight) {						if(!dO.isAtRight) {							// dO.maxX - dO.origX() = max possible negative distance to travel.							dO.carryGroup(dO.maxX - dO.origX(), null);							dO.moveToX( dO.maxX );							dO.isAtRight = !(dO.isAtLeft = false);						}					}															if(!dO.isDragStopped) {						dO.ondragstop(e);						dO.isDragStopped = true;					} 				}				else {			// In container.					dO.isAtLeft = dO.isAtRight = false;					dO.isDragStopped = false;					dO.moveToX( dO.newX );					dO.carryGroup(distX, null);					dO.ondrag(e);				}							}		}				// Handle dropTarget dragOver		var dropTargets = dO.dropTargets;		if(dropTargets.length > 0 && dO.isOnDragOverSet != false)  {			var coords = { x:eventPageX(e), y:eventPageY(e) };						for(var i = 0, j = dropTargets.length; i < j; i++) {				var dt = dropTargets[i];				if(!dt.ondragover.isSet) continue;				var isInTarget = isInside(coords, dt);				// Did we just move over this dropTarget?				if(!dt.hasDropTargetOver && isInTarget) {					dt.hasDropTargetOver = true;					dt.ondragover(e, dO);				}				else { // Were we previously over this dropTarget?					if(dO.isOnDropTarget && !isInTarget) { 						dt.ondragout(e, dO);						dt.hasDropTargetOver = false;					}				}			}		}		return false;	},		mouseUp : function(e) {				if(DragHandlers.dO == null)			return true;		if(e == null)			e = window.event;				var dO = DragHandlers.dO;		var group = DragObj.draggableList;		if(dO.dragCopy && dO.copyEl) {			dO.el = dO.origEl;			dO.moveToX(dO.x);			dO.moveToY(dO.y);			dO.copyEl.style.display = "none";		}		for(var id in DragObj.draggableList) {			var item = DragObj.draggableList[id];			if(item.copyEl) {				item.el = item.origEl;				item.moveToX(item.x);				item.moveToY(item.y);				item.copyEl.style.display = "none";			}		}		if(dO.hasBeenDragged) {			var el = dO.el;			var targets = dO.dropTargets;			if(targets.length > 0) {			var coords = { x:eventPageX(e), y:eventPageY(e) };				var dropTarget;				for(var i = 0, len = targets.length; i < len; i++) {					var dropTarget = targets[i];					if(isInside(coords, dropTarget)) {						dropTarget.ondrop(e, dO);						for(var id in group) 							dropTarget.ondrop(e, group[id]);						break;					}				}			}			for(var id in group) {				var o = group[id];				if(o.x < o.minX)					o.moveToX(o.minX);				else if(o.x > o.maxX)					o.moveToX(o.maxX);				if(o.y < o.minY)					o.moveToY(o.minY);				else if(o.y > o.maxY)					o.moveToY(o.maxY);				o.ondragend(e);			}		}		dO.ondragend(e);		dO.hasBeenDragged = false;		DragHandlers.dO = null;	},		keyPressed : function(e) {		e=e||event;if(e.keyCode == 27) { // esc key.			if(DragHandlers.dO) {				DragHandlers.dragObjReleased(e, DragHandlers.dO);			}		}	}	};function forIn(o, win) {	var s = "" + o + " : ";	for(var x in o) {		s += "\n"+ x + " = " + o[x];	}	if(win) {		var w = window.open();		w.document.write("<plaintext>"+s+"</plaintext>");		w.document.close();	}	else		alert(s);}/** isInside checks to see if the coordinates  *   x and y are both inside dropTarget */function isInside(curs, dropTarget){	 // check for x, then y.	var dt_x = dropTarget.getX(), dt_y = dropTarget.getY();		return (curs.x >= dt_x && curs.x < dt_x + dropTarget.getWidth())		&& // now check for y.		(curs.y >= dt_y && curs.y < dt_y + dropTarget.getHeight());}function findAncestorWithAttribute(el, attrName, value) {	for(var parent = el.parentNode;parent != null;){			if(parent[attrName])			if(parent[attrName] == value || value == "*")				return parent;					parent = parent.parentNode;	}	return null;}function getContainingBlock(el) {	var root = document.documentElement;	for(var parent = el.parentNode; parent != null && parent != root;) {			if(getStyle(parent, "position") != "static")			return parent;		parent = parent.parentNode;	}	return root;}function getStyle(el, style) {	if(!el.style) return;    var value = el.style[toCamelCase(style)];	    // IE provides "medium" as default inline-style border value for all border props.	    // This bogus value should be ignored.    if(!value || ua.ie && style.indexOf("border") == 0) 		if(typeof document.defaultView == "object")        	value = document.defaultView.                 getComputedStyle(el, "").getPropertyValue(style);               else if(el.currentStyle)            value = el.currentStyle[toCamelCase(style)];     return value || "";}// faster toCamelCase.function toCamelCase(s) {	for(var exp = toCamelCase.exp; exp.test(s); s = s.replace(exp, RegExp.$1.toUpperCase()));	return s;}toCamelCase.exp = /-([a-z])/;//--------------------------- Element location functions ------------------------/** Returns true if a contains b. */function contains(a, b) {	while(a != b && (b = b.parentNode) != null);	return a == b;}var ua = new function() {	var s = navigator.userAgent, d = document, dt = d.doctype ? d.doctype.name : "";	this.ie = /MSIE/.test(s);	this.safari = /Safari/.test(s);	this.win = /Win/.test(s);	this.winIE = this.win && this.ie;	this.macIE = /Mac/.test(s) && this.ie;	this.moz = /Gecko/.test(s) && !this.safari;	this.toString=function(){return s;};	this.isNotUsingPaddingEdge = /Opera/.test(s) || (this.ie && !this.winIE);};function getOffsetTop(el, container) {		if(!container) container = document;		for(var offsetTop = 0; el && el != container; el = el.offsetParent)			offsetTop += el.offsetTop;		return offsetTop;}function getOffsetLeft(el, container) {		if(!container) container = document;		for(var offsetLeft = 0; el && el != container; el = el.offsetParent) 			offsetLeft += el.offsetLeft;		return offsetLeft;}//--------------------------- Viewport functions ------------------------function getScrollTop() {	return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;}function getScrollLeft() {	return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;}//--------------------------- IE Functions ---------------------------function setIeTopLeft(el) { 	// For IE, set top/left values when declared values are auto	// and right/bottom values are given.	var cs = el.currentStyle || 		(document.defaultView.getComputedStyle && document.defaultView.getComputedStyle(el,"")) || el.style;	var cb = getContainingBlock(el);	var curL = cs.left||cs.getPropertyValue("left"), 	curR = cs.right||cs.getPropertyValue("right"), 	curT = cs.top||cs.getPropertyValue("top"),	curB = cs.bottom||cs.getPropertyValue("bottom");		// Calculate left when right is given pixel value and left is "auto".	if((curL == "" || curL == "auto") && curR && curR != "auto")		el.style.left = cb.clientWidth - el.offsetWidth - parseInt(curR) + "px";	// Calculate top when bottom is given pixel value and top is "auto".	if((curT == "" || curT == "auto") && curB && curB != "auto")		el.style.top = cb.clientHeight - el.offsetHeight - parseInt(curB) + "px";}//--------------------------- Event functions ------------------------function getTarget(e){	return window.event ? 		window.event.srcElement : e.target.tagName 			? e.target : e.target.parentNode;}function eventPageX(e) { return e.pageX || e.clientX + getScrollLeft(); }function eventPageY(e) { return e.pageY || e.clientY + getScrollTop(); }// Listener//---------------------------------------------------------------------------------------Listener = function(src) {	this.src = src;	this.callStack = [];};Listener.instances = {};Listener.getInstance = function(src, sEvent, oScope) {	var bucket = Listener.instances[sEvent] || (Listener.instances[sEvent] = []);		for(var i = bucket.length-1; i >= 0; i--)		if(bucket[i].src == src)			return bucket[i];		// not found.	var listener = new Listener(src, sEvent, oScope);	if(src[sEvent])		listener.callStack[listener.callStack.length] = src[sEvent];	src[sEvent] = Listener.fire(listener, oScope||src);	return bucket[bucket.length] = listener;};Listener.fire = function(listener, src) {	return function(e) {		for(var i = listener.callStack.length - 1; i >= 0; i--) {			src.__scopeFix = listener.callStack[i];			src.__scopeFix(e);		}		src.__scopeFix = null;	};};Listener.add = function(src, sEvent, fp, oScope) {	var callStack = Listener.getInstance(src, sEvent, oScope).callStack;	callStack[callStack.length] = fp;};Listener.cleanUp = function () {	for(var type in Listener.instances) {		var bucket = Listener.instances[type];		var i = bucket.length-1;		while(i >= 0)			bucket[i--][type] = null;	}        	if(window.CollectGarbage && i > 15)		window.CollectGarbage();};Listener.add(window, "unload", Listener.cleanUp);DragHandlers.init();
