/* * * * * * * * * * * * * * * * * * * * * * * * *
 *		 Seir Anphin Drag'n Drop Library	   *
 *			 Copyright Darrel Grant			*
 *			 http://www.anphin.com			 *
 * * * * * * * * * * * * * * * * * * * * * * * * */

	/**
	 * dragObject
	 * 
	 * Dependencies: 
	 * dom.js for cross-browser event handling
	 */
function dragObject(element, attachElement, lowerBound, upperBound,
                    startCallback, moveCallback, endCallback, attachLater, 
                    passObject) {
// function dragObject(element, attachElement, boundary, startCallback, moveCallback, endCallback, attachlater, passObject)
	element = dom.getElm(element);
	if(element == null) return;
 
	if(lowerBound != null && upperBound != null) {
		var temp = lowerBound.Min(upperBound);
		upperBound = lowerBound.Max(upperBound);
		lowerBound = temp;
	}
	/*
	if (boundary != null) {

	}
	*/	
	var cursorStartPos = null;
	var elementStartPos = null;
	var dragging = false;
	var listening = false;
	var disposed = false;
 
 	// These functions are not declared as methods, so that
 	// they can be called outside of this function (as callbacks)
	function dragStart(eventObj) {
		if (dragging || !listening || disposed)
			return;

		dragging = true;
   
		if (startCallback != null) {
			startCallback(eventObj, element);
		}
   
		cursorStartPos = dom.absoluteCursorPostion(eventObj);
   
		elementStartPos = new Position(parseInt(element.style.left), parseInt(element.style.top));
   
		elementStartPos = elementStartPos.Check();

		dom.addEvent(document, "mousemove", dragGo);
		dom.addEvent(document, "mouseup", dragStopHook);
   
		return dom.cancelEvent(eventObj);
	}
 
	function dragGo(eventObj) {
		if (!dragging || disposed)
			return;
   
		var newPos = dom.absoluteCursorPostion(eventObj);
		newPos = newPos.Add(elementStartPos).Subtract(cursorStartPos);
		newPos = newPos.Bound(lowerBound, upperBound)
		newPos.Apply(element);

		if (moveCallback != null) {
			moveCallback(newPos, element, passObject);
		}

		return dom.cancelEvent(eventObj);
	}
 
	function dragStopHook(eventObj) {
		dragStop();
		return dom.cancelEvent(eventObj);
	}
 
	function dragStop() {
		if (!dragging || disposed)
			return;

		dom.removeEvent(document, "mousemove", dragGo);
		dom.removeEvent(document, "mouseup", dragStopHook);
		cursorStartPos = null;
		elementStartPos = null;
		if (endCallback != null)
			endCallback(element);
		dragging = false;
	}
 
	this.Dispose = function() {
		if (disposed)
			return;

		this.StopListening(true);
		element = null;
		attachElement = null
		lowerBound = null;
		upperBound = null;
		startCallback = null;
		moveCallback = null;
		endCallback = null;
		passObject = null;
		disposed = true;
	}
 
	this.StartListening = function() {
		if (listening || disposed)
			return;

		listening = true;
		dom.addEvent(attachElement, "mousedown", dragStart);
	}
 
	this.StopListening = function(stopCurrentDragging) {
		if (!listening || disposed)
			return;

		dom.removeEvent(attachElement, "mousedown", dragStart);
		listening = false;
   
		if (stopCurrentDragging && dragging)
			dragStop();
	}

	// Accessor methods / "Getters"
	this.IsDragging = function(){ return dragging; }
	this.IsListening = function() { return listening; }
	this.IsDisposed = function() { return disposed; }
 
	attachElement = dom.getElm(attachElement);
	if (attachElement == null) attachElement = element;
   
	if (!attachLater) {
		this.StartListening();
	}
}


function Boundary(top, right, down, left) {
	this.top = top;
	this.right = right;
	this.down = down;
	this.left = left;
}

function Position(x, y) {
	this.X = x;
	this.Y = y;

	this.Add = function (val) {
		var newPos = new Position(this.X, this.Y);
		if (val != null) {
			if (!isNaN(val.X)) {
				newPos.X += val.X;
			}
			if (!isNaN(val.Y)) {
				newPos.Y += val.Y;
			}
		}
		return newPos;
	};

	this.Subtract = function (val) {
		var newPos = new Position(this.X, this.Y);
		if (val != null) {
			if (!isNaN(val.X)) {
				newPos.X -= val.X;
			}
			if (!isNaN(val.Y)) {
				newPos.Y -= val.Y;
			}
		}
		return newPos;
	};

	this.Min = function (val) {
		var newPos = new Position(this.X, this.Y);
		if (val == null) {
			return newPos;
		}
		if (!isNaN(val.X) && this.X > val.X) {
			newPos.X = val.X;
		}
		if (!isNaN(val.Y) && this.Y > val.Y) {
			newPos.Y = val.Y;
		}
		return newPos;
	};

	this.Max = function (val) {
		var newPos = new Position(this.X, this.Y);
		if (val == null) {
			return newPos;
		}
		if (!isNaN(val.X) && this.X < val.X) {
			newPos.X = val.X;
		}
		if (!isNaN(val.Y) && this.Y < val.Y) {
			newPos.Y = val.Y;
		}
		return newPos;
	};

	this.Bound = function (lower, upper) {
		var newPos = this.Max(lower);
		return newPos.Min(upper);
	};

	this.Check = function () {
		var newPos = new Position(this.X, this.Y);
		if (isNaN(newPos.X)) {
			newPos.X = 0;
		}
		if (isNaN(newPos.Y)) {
			newPos.Y = 0;
		}
		return newPos;
	};

	this.Apply = function (element) {
		if (typeof element == "string") {
			element = document.getElementById(element);
		}
		if (element == null) {
			return;
		}
		if (!isNaN(this.X)) {
			element.style.left = this.X + "px";
		}
		if (!isNaN(this.Y)) {
			element.style.top = this.Y + "px";
		}
	};
}

