/*******************************************************************************************
 * drag
 * Written by Craig Francis
 * Allow the
 *******************************************************************************************/

	var drag = new function() {

		//--------------------------------------------------
		// Old browsers

			if (!document.getElementById || !document.getElementsByTagName) {
				return;
			}

		//--------------------------------------------------
		// Initialisation

			this.init = function() {

				//--------------------------------------------------
				// Debug

					console.log('drag.js: Initialisation');

				//--------------------------------------------------
				// Currently not dragging

					drag.currentlyDragging = null;

			}

		//--------------------------------------------------
		// Setup

			this.setup = function(el, c) {

				//--------------------------------------------------
				// Debug

					console.log('drag.js: Setup (' + (el.id ? el.id : 'unknown') + ')');

				//--------------------------------------------------
				// Current position

					el.dragPosCurrentLeft = 0;
					el.dragPosCurrentTop = 0;

				//--------------------------------------------------
				// Styles

					if (c && c.relative) {
						el.style.position = 'relative';
					} else {
						el.style.position = 'absolute';
					}

				//--------------------------------------------------
				// Setup this element as a handle

					el.onmousedown = function(event) {
						return drag.moveStart(event, this);
					};

				//--------------------------------------------------
				// If elements have been found to be ignored

					// if (c && c.ignoreElements) {
					// 	for (var k in c.ignoreElements) {
					//
					// 		c.ignoreElements[k].onmousedown = function(event) {
					// 			if (!event) var event = window.event;
					// 			event.cancelBubble = true;
					// 			if (event.stopPropagation) event.stopPropagation();
					// 		}
					//
					// 	}
					// }

				//--------------------------------------------------
				// If the click propegation is allowed - for example
				// dragging item which contain input fields. This is
				// not the default as text selection can occur

					el.dragAllowClickPropagation = ((c && c.allowClickPropagation) ? true : false); // Must be set explicitly

				//--------------------------------------------------
				// If a bound update function has been provided

					if (c && c.boundUpdate) {
						el.dragBoundUpdate = c.boundUpdate;
					}

				//--------------------------------------------------
				// If a function has been provided that needs to be
				// called on update.

					if (c && c.onUpdate) {
						el.dragOnUpdate = c.onUpdate;
					}

				//--------------------------------------------------
				// If a function has been provided that needs to be
				// called on click (not drag).

					if (c && c.onMouseClick) {
						el.dragOnMouseClick = c.onMouseClick;
					}

			}

		//--------------------------------------------------
		// Set handle

			this.setHandle = function(handle, el) {

				handle.onmousedown = function(event) {
					return drag.moveStart(event, el);
				}

			}

		//--------------------------------------------------
		// Set position

			this.setPosition = function(left, top, el) {

				//--------------------------------------------------
				// Bounds

					if (el.dragBoundValues) {

						if (el.dragBoundValues.left > left) left = el.dragBoundValues.left;
						if (el.dragBoundValues.right  < left) left = el.dragBoundValues.right;

						if (el.dragBoundValues.top  > top) top = el.dragBoundValues.top;
						if (el.dragBoundValues.bottom < top) top = el.dragBoundValues.bottom;

					}

				//--------------------------------------------------
				// Move

					el.style.left = left + 'px';
					el.style.top = top + 'px';

					//console.log('L: ' + left + ' T: ' + top);

				//--------------------------------------------------
				// Remember

					el.dragPosCurrentLeft = left;
					el.dragPosCurrentTop = top;

			}

		//--------------------------------------------------
		// Canvas dragging

			this.moveStart = function(event, el) {

				//--------------------------------------------------
				// Give up if something is already selected... this
				// triggers when something is selected and the mouse
				// is released off the browser

					if (drag.currentlyDragging) {
						return false;
					}

					drag.currentlyDragging = el;

				//--------------------------------------------------
				// Remember starting positions

					drag.moveStartPosMouse = drag.mousePos(event);

					drag.moveStartPosCanvas = {
						x: el.dragPosCurrentLeft,
						y: el.dragPosCurrentTop
					};

					drag.hasMoved = false;

				//--------------------------------------------------
				// Update the moving bounds

					if (el.dragBoundUpdate) {
						el.dragBoundUpdate();
					}

				//--------------------------------------------------
				// Show the moving cursor

					$('html').css('cursor', 'move');

				//--------------------------------------------------
				// Apply the mousemove and mouseup handles

					document.onmousemove = drag.moveChange;
					document.onmouseup = drag.moveEnd;

				//--------------------------------------------------
				// Try to stop event passing onto native browser
				// handler - can be disabled for dragging items 
				// which contain form elements.

					return el.dragAllowClickPropagation;

			}

			this.moveChange = function(event) {

				//--------------------------------------------------
				// Give up if something is not moving - should
				// not happen

					if (!drag.currentlyDragging) {
						return false;
					}

				//--------------------------------------------------
				// Position

					var mousePos = drag.mousePos(event);

					var left = ((mousePos.x - drag.moveStartPosMouse.x) + drag.moveStartPosCanvas.x);
					var top = ((mousePos.y - drag.moveStartPosMouse.y) + drag.moveStartPosCanvas.y);

					drag.setPosition(left, top, drag.currentlyDragging);

				//--------------------------------------------------
				// If moved

					if (drag.hasMoved == false && (mousePos.x != drag.moveStartPosMouse.x || mousePos.y != drag.moveStartPosMouse.y)) {
						drag.hasMoved = true;
					}

				//--------------------------------------------------
				// Update

					if (drag.currentlyDragging.dragOnUpdate) {
						drag.currentlyDragging.dragOnUpdate();
					}

				//--------------------------------------------------
				// Do not pass event onto native browser handler

					return false;

			}

			this.moveEnd = function(event) {

				//--------------------------------------------------
				// Give up if something is not moving - should
				// not happen

					if (!drag.currentlyDragging) {
						return false;
					}

				//--------------------------------------------------
				// Show the moving cursor

					$('html').css('cursor', 'auto');

				//--------------------------------------------------
				// Has not moved

					if (drag.hasMoved == false && drag.currentlyDragging.dragOnMouseClick) {

						var mousePos = drag.mousePos(event);
						mousePos.x -= drag.currentlyDragging.dragPosCurrentLeft;
						mousePos.y -= drag.currentlyDragging.dragPosCurrentTop;

						drag.currentlyDragging.dragOnMouseClick(mousePos);

					}

				//--------------------------------------------------
				// Cleanup

					drag.currentlyDragging = null;

					document.onmousemove = null;
					document.onmouseup = null;

				//--------------------------------------------------
				// Do not pass event onto native browser handler

					return false;

			}

		//--------------------------------------------------
		// Mouse position

			this.mousePos = function(event) {

				if (!event) {
					event = window.event;
				}

				if (event.pageX) {
					return {
						x: event.pageX,
						y: event.pageY
					};
				} else if (event.clientX) {
					return {
						x: event.clientX + document.body.scrollLeft,
						y: event.clientY + document.body.scrollTop
					};
				} else {
					return {
						x: 0,
						y: 0
					};
				}

			}

		//--------------------------------------------------
		// On page load

			addLoadEvent(function() {
				drag.init();
			});

	}
