/**
 * This file must be included to support resize, drag & drop functionality.
 * 
 * @version 12-08-2010
 * @author <a href="mailto:r.tennapel@griponservice.nl?SUBJECT=dragdrop.js">R. ten Napel, ing.</a>
 **/

/**
 * The drag object which wrappes an element which may be dragged.
 * 
 * @param element			The element to make draggable.
 * @param dropObjects		The drop object where this element may be dropped in.
 * @param graspHandler		The handler that is called when this element is clicked on for dragging.
 * @param dragHandler		The handler that is called when this element is being dragged.
 * @param releaseHandler	The handler that is called when a dragged element is being released.
 **/
function DragObject(element, dropObjects, graspHandler, dragHandler, releaseHandler) {
	this.element = element;
	this.dropObjects = (dropObjects == null) ? [] : dropObjects;
	this.graspHandler = (graspHandler == null) ? DragObject.defaultGraspHandler : graspHandler;
	this.dragHandler = (dragHandler == null) ? DragObject.defaultDragHandler : dragHandler;
	this.releaseHandler = (releaseHandler == null) ? DragObject.defaultReleaseHandler : releaseHandler;
	
	// The basic settings:
	this.original = { position: null, x: 0, y: 0 };
	this.offset = { x: 0, y: 0 };
	
	// Disable selection:
	$(element).noSelect().addClass("dragObject");
};

/**
 * The default grasp handler is used when none is given. The following steps are done:<br />
 * <ol>
 * 		<li>All original settings of the element are stored.</li>
 * 		<li>The offset (mouse to XY of the element) is stored.</li>
 * 		<li>The dragging style is added to the element and it's position style is set to fixed.</li>
 * 		<li>The element is positioned directly.</li>
 * 		<li>A drop object is detected and handled if necessary.</li>
 * </ol> 
 * 
 * @param dragObject		This drag object.
 * @param pos				The position where the drag object is being grasped.
 **/
DragObject.defaultGraspHandler = function(dragObject, pos) {
	// Store the original settings:
	dragObject.original = {
			position: $(dragObject.element).getStyle("position"),
			left: $(dragObject.element).getStyle("left"),
			top: $(dragObject.element).getStyle("top")
		};
	
	// Store the drag offset:
	var box = $(dragObject.element).setStyle("position", "absolute").getBox();
	dragObject.offset.x = pos.x - box.x;
	dragObject.offset.y = pos.y - box.y;
	
	// Change the drag offset to static values when out of the box (necessary for IE):
	if (dragObject.offset.x < 0 || dragObject.offset.x > box.w) { dragObject.offset.x = 4; }
	if (dragObject.offset.y < 0 || dragObject.offset.y > box.h) { dragObject.offset.y = 4; }
	
	// Prepare the element for dragging:
	$(dragObject.element).addClass("dragging").setStyle("position", "fixed");
	
	// Calculate the position of the element:
	var scroll = GlobalKit.scrollPos();
	var x = (pos.x - dragObject.offset.x - scroll.x);
	var y = (pos.y - dragObject.offset.y - scroll.y);
	
	// Update the position of the element:
	$(dragObject.element).css({
		left: x + "px",
		top: y + "px"
	});
	
	// Retrieve the drop object under this drag object:
	var dropObject = dragObject.detectDropObject(pos.x, pos.y);
	
	// When the dragdropper tracked drop object is not the same as the current found drop object:
	if (Dragdropper.dropObject != dropObject) {
		// When the old drop object is not NULL, remove the class:
		if (Dragdropper.dropObject != null) {
			$(Dragdropper.dropObject.element).removeClass("dropObject");
		}
		
		// When the new drop object is not NULL, add the class:
		if (dropObject != null) {
			$(dropObject.element).addClass("dropObject");
		}
		
		// Store the new drop object:
		Dragdropper.dropObject = dropObject;
	}
};

/**
 * The default drag handler is used when none is given. The following steps are done:<br />
 * <ol>
 * 		<li>The new position of the element is calculated.</li>
 * 		<li>A check is done if the element bounds are inside the browser window, and if necessary the position is updated.</li>
 * 		<li>The position is set.</li>
 * 		<li>A drop object is detected and handled if necessary.</li>
 * </ol>
 * Note that in IE, when dropping inside a droppable, the box position may be little ofcourse when the node before the dropper is p.h. a textnode.
 * 
 * @param dragObject		This drag object.
 * @param pos				The position where the drag object is being dragged.
 **/
DragObject.defaultDragHandler = function(dragObject, pos) {
	// Calculate the position of the element:
	
	var scroll = GlobalKit.scrollPos();
	var x = (pos.x - dragObject.offset.x - scroll.x);
	var y = (pos.y - dragObject.offset.y - scroll.y);
	
	// Update the position if the drag object is outside the screen:
	var box = $(dragObject.element).getBox();
	if (x < 0) {
		x = 0;
	} else if ((x + box.w) > GlobalKit.screenWidth()) {
		x = GlobalKit.screenWidth() - box.w;
	}
	if (y < 0) {
		y = 0;
	} else if ((y + box.h) > GlobalKit.screenHeight()) {
		y = GlobalKit.screenHeight() - box.h;
	}
	
	// Set the position:
	$(dragObject.element).css({
		left: x + "px",
		top: y + "px"
	});
	
	// Retrieve the drop object under this drag object:
	var dropObject = dragObject.detectDropObject(pos.x, pos.y);
	
	// When the dragdropper tracked drop object is not the same as the current found drop object:
	if (Dragdropper.dropObject != dropObject) {
		// When the old drop object is not NULL, remove the class:
		if (Dragdropper.dropObject != null) {
			$(Dragdropper.dropObject.element).removeClass("dropObject");
		}
		
		// When the new drop object is not NULL, add the class:
		if (dropObject != null) {
			$(dropObject.element).addClass("dropObject");
		}
		
		// Store the new drop object:
		Dragdropper.dropObject = dropObject;
	}
};

/**
 * The default release handler is used when none is given. The following steps are done:<br />
 * <ol>
 * 		<li>The old settings of the element are restored.</li>
 * 		<li>The basic settings are cleared.</li>
 * 		<li>If a drop object is being tracked by the dragdropper, the element is dropped inside that drop object.</li>
 * </ol> 
 * 
 * @param dragObject		This drag object.
 **/
DragObject.defaultReleaseHandler = function(dragObject) {
	// Restore the original settings:
	$(dragObject.element).removeClass("dragging").css({
			position: dragObject.original.position,
			left: dragObject.original.left,
			top: dragObject.original.top
		});
	
	// Clear the basics:
	dragObject.original = { position: null, x: 0, y: 0 };
	dragObject.offset = { x: 0, y: 0 };
	
	// If a drop object is tracked, drop this drag object into it:
	if (Dragdropper.dropObject != null) {
		Dragdropper.dropObject.drop(dragObject);
	}
};

/**
 * Register a drop object to this drag object.
 * 
 * @param dropObject		The drop object to register.
 **/
DragObject.prototype.registerDropObject = function(dropObject) {
	// If not set, show debug error and return:
	if (dropObject == null) {
		Debugger.write("Drop object is NULL!");
		
		return;
	}
	
	// Don't register yourself:
	if (this.element == dropObject.element) {
		return;
	}
	
	// Add the drop object:
	if (!this.dropObjects.contains(dropObject)) {
		this.dropObjects.add(dropObject);
	}
	
	// Register this drag object:
	if (!dropObject.dragObjects.contains(this)) {
		dropObject.registerDragObject(this);
	}
};

/**
 * This function must be called when a drag object is being grasped.
 * 
 * @param pos				The position where this drag object is being grasped.
 **/
DragObject.prototype.grasp = function(pos) {
	this.graspHandler(this, pos);
};

/**
 * This function must be called when a drag object is being dragged.
 * 
 * @param pos				The position where this drag object is being dragged.
 **/
DragObject.prototype.drag = function(pos) {
	this.dragHandler(this, pos);
};

/**
 * This function must be valled when a drag object is being released.
 **/
DragObject.prototype.release = function() {
	this.releaseHandler(this);
};

/**
 * Retrieve the drop object on the given coördinates.
 * 
 * @param x					The X-coördinate to check for a droppable.
 * @param y					The Y-coördinate to check for a droppable.
 * 
 * @return					The drop object if available on the given coördinates.
 **/
DragObject.prototype.detectDropObject = function(x, y) {
	// Sort all the drop objects by DOM depth, the first hit is hereby also on top:
	this.dropObjects.sort(function(a, b) {
		var aDepth = GlobalKit.getDOMDepth(a.element);
		var bDepth = GlobalKit.getDOMDepth(b.element);
		
		// Check which value to return:
		if (aDepth < bDepth) {
			return 1;
		} else if (aDepth > bDepth) {
			return -1;
		} else {
			return 0;
		}
	});
	
	/*var txt = "";
	for (var i = 0; i < this.dropObjects.length; i++) {
		txt += "DROP OBJECTS[" + i + "]: " + this.dropObjects[i].element.id + "<br />";
	}
	Debugger.write(txt);*/
	
	// Iterate through all registered drop objects of this drag object:
	for (var i = 0; i < this.dropObjects.length; i++) {
		// Retrieve the drop object boundaries (need to set absolute for getBox):
		var old = $(this.dropObjects[i].element).getStyle("position");
		var box = $(this.dropObjects[i].element).setStyle("position", "absolute").getBox();
		$(this.dropObjects[i].element).setStyle("position", old);
		
		// Check if in bounds:
		if ((x >= box.x) && (x <= box.x2) && (y >= box.y) && (y <= box.y2)) {
			//Debugger.write("HIT");
			return this.dropObjects[i];
		}
	}
	
	return null;
};

/**
 * The drop object which wrappes an element in which drag objects may be dropped.
 * 
 * @param element			The element to wrap as a drop object.
 * @param dragObjects		The drag objects which may be dropped into this drop object.
 * @param dropHandler		The handler that is called when a drag object is dropped into this drop object.
 **/
function DropObject(element, dragObjects, dropHandler) {
	this.element = element;
	this.dragObjects = (dragObjects == null) ? [] : dragObjects;
	this.dropHandler = (dropHandler == null) ? DropObject.defaultDropHandler : dropHandler;
	
	// Disable selection:
	$(element).noSelect();
};

/**
 * This function handles dropping of a drag object into a drop object.
 * 
 * @param dropObject		The drop object.
 * @param dragObject		The drag object.
 **/
DropObject.defaultDropHandler = function(dropObject, dragObject) {

	// Remove the class from the drop object and set to NULL in the dragdropper:
	$(Dragdropper.dropObject.element).removeClass("dropObject");
	Dragdropper.dropObject = null;
	
	// Do nothing when a drag object is dropped in itself:
	if (dropObject.element == dragObject.element) {
		Debugger.write("Cannot drop '" + dragObject.element.id + "' into itself!");
		
		return;
	}
	
	// Remove the dragged element from it's original parent:
	dragObject.element.parentNode.removeChild(dragObject.element);
	
	// Add the drag object to the drop object:
	//dropObject.element.style.width = dragObject.element.style.width;
	dropObject.element.appendChild(dragObject.element);
	
};

/**
 * Register a drag object to this drop object.
 * 
 * @param dragObject		The drag object to register.
 **/
DropObject.prototype.registerDragObject = function(dragObject) {
	// If not set, show debug error and return:
	if (dragObject == null) {
		Debugger.write("Drag object is NULL!");
		
		return;
	}
	
	// Don't register yourself:
	if (this.element == dragObject.element) {
		return;
	}
	
	// Add the drag object:
	if (!this.dragObjects.contains(dragObject)) {
		this.dragObjects.add(dragObject);
	}
	
	// Register this drop object:
	if (!dragObject.dropObjects.contains(this)) {
		dragObject.registerDropObject(this);
	}
};

/**
 * Drops the given drag object in a way specified by the drop handler.
 * 
 * @param dragObject		The drag object to drop.
 **/
DropObject.prototype.drop = function(dragObject) {
	this.dropHandler(this, dragObject);
};

/**
 * The dragdropper class handles drag & drop operations.
 **/
function Dragdropper() {};

// The dragdropper variables:
Dragdropper.dragObject = null;
Dragdropper.dropObject = null;
Dragdropper.dragObjects = [];
Dragdropper.dropObjects = [];

/**
 * Initialize the dragdrop handler.
 **/
Dragdropper.init = function() {
	// Register the mouse handlers:
	$(document).on("mousemove",
		Dragdropper.mousemoveHandler
	).on("mousedown",
		Dragdropper.mousedownHandler
	).on("mouseup",
		Dragdropper.mouseupHandler
	).on("mousedrag",
		Dragdropper.mousedragHandler
	);
	
	// Register the scroll handler:
	$(window).on("scroll", function(e) {
		Dragdropper.scrollHandler(e);
	});
};

/**
 * Retrieve a drag object that corresponds to the given element.
 * 
 * @param element			The element to check in all the drag objects.
 * 
 * @return					The corresponding drag object or NULL if not found.
 **/
Dragdropper.getDragObject = function(element) {
	// Check each drag object and return if a match is found:
	for (var i = 0; i < Dragdropper.dragObjects.length; i++) {
		if (Dragdropper.dragObjects[i].element == element) {
			return Dragdropper.dragObjects[i];
		}
	}
	
	return null;
};

/**
 * Retrieve a drop object that corresponds to the given element.
 * 
 * @param element			The element to check in all the drop objects.
 * 
 * @return					The corresponding drop object or NULL if not found.
 **/
Dragdropper.getDropObject = function(element) {
	// Check each drop object and return if a match is found:
	for (var i = 0; i < Dragdropper.dropObjects.length; i++) {
		if (Dragdropper.dropObjects[i].element == element) {
			return Dragdropper.dropObjects[i];
		}
	}
	
	return null;
};

/**
 * Check whether an element is already created as a drag object.
 * 
 * @param element			The element to check.
 * 
 * @return					If the given element is draggable (in a drag object).
 **/
Dragdropper.isDraggable = function(element) {
	return (Dragdropper.getDragObject(element) != null);
};

/**
 * Check whether an element is already created as a drop object.
 * 
 * @param element			The element to check.
 * 
 * @return					If the given element is droppable (in a drop object).
 **/
Dragdropper.isDroppable = function(element) {
	return (Dragdropper.getDropObject(element) != null);
};

/**
 * Make an element draggable by encapsulating it in a drag object. Note that the given element would idially be a DIV.
 * 
 * @param element			The element to make draggable.
 * @param dropObjects		The drop object where this element may be dropped in.
 * @param graspHandler		The handler that is called when this element is clicked on for dragging.
 * @param dragHandler		The handler that is called when this element is being dragged.
 * @param releaseHandler	The handler that is called when a dragged element is being released.
 * 
 * @return					The created drag object.
 **/
Dragdropper.makeDraggable = function(element, dropObjects, graspHandler, dragHandler, releaseHandler) {
	// Check if the element is a DIV:
	if (element.tagName != "DIV") {
		Debugger.write("WARNING: The element ('" + element.id + "' | '" + element.tagName + "') that is made draggable is NOT a DIV!");
	}
	
	// Create the drag object:
	var dragObject = new DragObject(element, dropObjects, graspHandler, dragHandler, releaseHandler);
	
	// Register the drag object:
	Dragdropper.dragObjects.add(dragObject);
	
	return dragObject;
};

/**
 * Make an element droppable by encapsulating it in a drop object.
 * 
 * @param element			The element to make droppable.
 * @param dragObjects		The drag object which may be dropped into this element.
 * @param dropHandler		The handler that is called when a drag object is dropped into this element.
 * 
 * @return					The created drop object.
 **/
Dragdropper.makeDroppable = function(element, dragObjects, dropHandler) {
	// Create the drop object:
	var dropObject = new DropObject(element, dragObjects, dropHandler);
	
	// Register the drop object:
	Dragdropper.dropObjects.add(dropObject);
	
	return dropObject;
};

/**
 * Make an element resizable. Note that element's with padding will not be rendered as should be when resizing top or left!
 * 
 * @param element			The element to make resizable.
 **/
Dragdropper.makeResizable = function(element) {
	// The resize vars:
	var fix = navigator.userAgent.contains("Firefox") ? 1 : 0;
	var bar = 8;
	
	// Create a specific grasp handler for resize blocks only:
	var graspHandler = function(dragObject, pos) {
		// Store the original settings:
		dragObject.original = {
				position: $(dragObject.element).getStyle("position"),
				left: $(dragObject.element).getStyle("left"),
				top: $(dragObject.element).getStyle("top")
			};
		
		// Store the drag offset:
		var box = $(dragObject.element).setStyle("position", "absolute").getBox();
		dragObject.offset.x = pos.x - box.x;
		dragObject.offset.y = pos.y - box.y;
		
		// Change the drag offset to static values when out of the box (necessary for IE):
		if (dragObject.offset.x < 0 || dragObject.offset.x > box.w) { dragObject.offset.x = 4; }
		if (dragObject.offset.y < 0 || dragObject.offset.y > box.h) { dragObject.offset.y = 4; }
		
		// Prepare the element for dragging:
		$(dragObject.element).addClass("dragging");
	};
	
	//////////////////////////////////////////////////
	// TOP BOX: //////////////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the top resize box:
	var topDragHandler = function(dragObject, pos) {
		// Retrieve the position of the element:
		var x = (pos.x - dragObject.offset.x);
		var y = (pos.y - dragObject.offset.y);
		
		// Fix the Y-coördinate:
		y = (y < 0) ? 0 : y;
		
		// Retrieve the dimensions of the parent node and calculate the new height:
		var box = $(dragObject.element.parentNode).setStyle("position", "absolute").getBox();
		var h = box.h + (box.y - y) + fix;
		
		// Reset the position of the resize box:
		$(dragObject.element).css({
			left: "0px",
			top: "0px"
		});
		
		// Set the position of the parent node:
		$(dragObject.element.parentNode).css({
			top: y + "px",
			height: h + "px"
		});
	};
	
	// Create the top resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		left: "0px",
		top: "0px",
		right: "0px",
		height: bar + "px",
		cursor: "n-resize"
	}).addClass("resizer");
	
	// Make the top resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, topDragHandler);
	
	// Add the top resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// RIGHT BOX: ////////////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the right resize box:
	var rightDragHandler = function(dragObject, pos) {
		// Retrieve the position of the element:
		var x = (pos.x - dragObject.offset.x);
		var y = (pos.y - dragObject.offset.y);
		
		// Fix the X-coördinate:
		x = (x > GlobalKit.screenWidth()) ? GlobalKit.screenWidth() - fix : x;
		
		// Retrieve the dimensions of the parent node and calculate the new width:
		var box = $(dragObject.element.parentNode).setStyle("position", "absolute").getBox();
		var w = box.w + dragObject.offset.x + (x - box.x2);
		
		// Set the position of the parent node:
		$(dragObject.element.parentNode).css({
			width: w + "px"
		});
	};
	
	// Create the right resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		top: "0px",
		right: "0px",
		width: bar + "px",
		bottom: "0px",
		cursor: "e-resize"
	}).addClass("resizer");
	
	// Make the right resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, rightDragHandler);
	
	// Add the right resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// BOTTOM BOX: ///////////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the bottom resize box:
	var bottomDragHandler = function(dragObject, pos) {
		// Retrieve the position of the element:
		var x = (pos.x - dragObject.offset.x);
		var y = (pos.y - dragObject.offset.y);
		
		// Fix the Y-coördinate:
		y = (y > GlobalKit.screenHeight()) ? GlobalKit.screenHeight() - fix : y;
		y -= fix;
		
		// Retrieve the dimensions of the parent node and calculate the new width:
		var box = $(dragObject.element.parentNode).setStyle("position", "absolute").getBox();
		var h = box.h + (y - box.y2) + fix;
		
		// Set the position of the parent node:
		$(dragObject.element.parentNode).css({
			height: h + "px"
		});
	};
	
	// Create the bottom resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		left: "0px",
		bottom: "0px",
		height: bar + "px",
		right: "0px",
		cursor: "n-resize"
	}).addClass("resizer");
	
	// Make the bottom resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, bottomDragHandler);
	
	// Add the bottom resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// LEFT BOX: /////////////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the left resize box:
	var leftDragHandler = function(dragObject, pos) {
		// Retrieve the position of the element:
		var x = (pos.x - dragObject.offset.x);
		var y = (pos.y - dragObject.offset.y);
		
		// Fix the X-coördinate:
		x = (x < 0) ? 0 : x;
		
		// Retrieve the dimensions of the parent node and calculate the new width:
		var box = $(dragObject.element.parentNode).setStyle("position", "absolute").getBox();
		var w = box.w + (box.x - x) + fix;
		
		// Set the position of the parent node:
		$(dragObject.element.parentNode).css({
			left: x + "px",
			width: w + "px"
		});
	};
	
	// Create the left resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		left: "0px",
		top: "0px",
		width: bar + "px",
		bottom: "0px",
		cursor: "e-resize"
	}).addClass("resizer");
	
	// Make the left resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, leftDragHandler);
	
	// Add the left resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// TOP-LEFT BOX: /////////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the top-left resize box:
	var topLeftDragHandler = function(dragObject, pos) {
		leftDragHandler(dragObject, pos);
		topDragHandler(dragObject, pos);
	};
	
	// Create the top-left resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		left: "0px",
		top: "0px",
		width: (bar * 2) + "px",
		height: (bar * 2) + "px",
		cursor: "nw-resize"
	}).addClass("resizer");
	
	// Make the top-left resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, topLeftDragHandler);
	
	// Add the top-left resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// TOP-RIGHT BOX: ////////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the top-right resize box:
	var topRightDragHandler = function(dragObject, pos) {
		topDragHandler(dragObject, pos);
		rightDragHandler(dragObject, pos);
	};
	
	// Create the top-left resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		right: "0px",
		top: "0px",
		width: (bar * 2) + "px",
		height: (bar * 2) + "px",
		cursor: "ne-resize"
	}).addClass("resizer");
	
	// Make the top-right resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, topRightDragHandler);
	
	// Add the top-right resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// BOTTOM-RIGHT BOX: /////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the bottom-right resize box:
	var bottomRightDragHandler = function(dragObject, pos) {
		rightDragHandler(dragObject, pos);
		bottomDragHandler(dragObject, pos);
	};
	
	// Create the bottom-right resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		right: "0px",
		bottom: "0px",
		width: (bar * 2) + "px",
		height: (bar * 2) + "px",
		cursor: "nw-resize"
	}).addClass("resizer");
	
	// Make the bottom-right resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, bottomRightDragHandler);
	
	// Add the bottom-right resize box to the original element:
	element.appendChild(cell);
	
	//////////////////////////////////////////////////
	// BOTTOM-LEFT BOX: //////////////////////////////
	//////////////////////////////////////////////////
	
	// Prepare the drag handler for the bottom-left resize box:
	var bottomLeftDragHandler = function(dragObject, pos) {
		bottomDragHandler(dragObject, pos);
		leftDragHandler(dragObject, pos);
	};
	
	// Create the bottom-left resize box:
	var cell = document.createElement("DIV");
	$(cell).css({
		position: "absolute",
		left: "0px",
		bottom: "0px",
		width: (bar * 2) + "px",
		height: (bar * 2) + "px",
		cursor: "ne-resize"
	}).addClass("resizer");
	
	// Make the bottom-left resize box draggable:
	Dragdropper.makeDraggable(cell, null, graspHandler, bottomLeftDragHandler);
	
	// Add the bottom-left resize box to the original element:
	element.appendChild(cell);
};

/**
 * The handler that is called when the mouse is moved.
 * 
 * @param e					The mouse event.
 **/
Dragdropper.mousemoveHandler = function(e) {
	// If no event given retrieve the window event:
	e = e || window.event;
	
	// Check if a target is being dragged:
	if (Dragdropper.dragObject != null) {
		return Dragdropper.mousedragHandler(e);
	}
};

/**
 * The handler that is called when a mouse button is being pressed.
 * 
 * @param e					The mouse event.
 **/
Dragdropper.mousedownHandler = function(e) {
	// If no event given retrieve the window event:
	e = e || window.event;
	
	// Firefox uses event.target here, MSIE uses event.srcElement
	var target = e.target || e.srcElement;
	var isImg = (target.tagName == "IMG");
	
	// When the found target is not a DIV, assume that it's parent is a DIV (this is handy when dragging p.h. images):
	if (target.tagName != "DIV") {
		target = target.parentNode;
	}
	
	// If there is no target registered, register the current target:
	if (Dragdropper.dragObject == null && Dragdropper.isDraggable(target)) {
		// Store the element and wrapper being dragged:
		Dragdropper.dragObject = Dragdropper.getDragObject(target);
		
		// Calculate the target position with the scroll position when IE:
		var pos = GlobalKit.mousePos(e);
		var scroll = GlobalKit.scrollPos();
		if (GlobalKit.browser().contains("MSIE")) {
			pos.x += scroll.x;
			pos.y += scroll.y;
		}
		
		// Call the grasp handler of the dragging object:
		Dragdropper.dragObject.grasp(pos);
	}
	
	// Prevent default event handling for images:
	if (isImg) {
		return GlobalKit.stopEvent(e);
	}
};

/**
 * The handler that is called when a mouse button is being released.
 * 
 * @param e					The mouse event.
 **/
Dragdropper.mouseupHandler = function(e) {
	// If there is a target registered, release it:
	if (Dragdropper.dragObject != null) {
		// Release the dragged object:
		Dragdropper.dragObject.release();
		
		Dragdropper.dragObject = null;
	}
};

/**
 * The handler that is called when the mouse is being dragged (mouse down + move).
 * 
 * @param e					The mouse event.
 **/
Dragdropper.mousedragHandler = function(e) {
	// If no event given retrieve the window event:
	e = e || window.event;
	
	// Check if a target is being dragged:
	if (Dragdropper.dragObject != null) {
		// Calculate the target position with the scroll position when IE:
		var pos = GlobalKit.mousePos(e);
		var scroll = GlobalKit.scrollPos();
		if (GlobalKit.browser().contains("MSIE")) {
			pos.x += scroll.x;
			pos.y += scroll.y;
		}
		
		// Drag the drag object:
		Dragdropper.dragObject.drag(pos);
	}
};

/**
 * The handler that is called when the page is scrolled.
 * 
 * @param e					The scroll event.
 **/
Dragdropper.scrollHandler = function(e) {
	
};

//Initalize the dragdropper:
Dragdropper.init();
