/***********************************************************

	Drag-and-Drop Library

	Author: Fred Snyder
	Company: Castwide Technologies
	URL: http://castwide.com
	Date Created: May 14, 2007
	Date Modified: May 14, 2007

	Required files:
	* prototype.js (http://prototypejs.org)
	* cfx.js (http://castwide.com)

	This library provides two static objects.  DND enables
	drag-and-drop functionality for HTML elements.
	Sortable utilizes the DND object to allow users to
	change the order of items in lists or rows in tables.

***********************************************************/

var DND = new function() {

	var currentDragElement = null;
	var currentX = -1;
	var currentY = -1;

	var startDrag = function(e) {
		if ( (!currentDragElement) && (Event.element(e).draggee) ) {
			currentDragElement = Event.element(e);
			oldPosition = currentDragElement.draggee.style.position;
			currentX = Event.pointerX(e);
			currentY = Event.pointerY(e);
			Event.stop(e);
		}
	}

	var updateDrag = function(e) {
		if (currentDragElement) {
			var d = currentDragElement.draggee;
			d.position.set(d.position.getX() + (Event.pointerX(e) - currentX), d.position.getY() + (Event.pointerY(e) - currentY));
			currentX = Event.pointerX(e);
			currentY = Event.pointerY(e);
			Event.stop(e);
		}
	}

	var stopDrag = function(e) {
		if (currentDragElement) {
			currentX = -1;
			currentY = -1;
			var thisDragElement = currentDragElement;
			currentDragElement = null;
			if (thisDragElement.onDrop) {
				thisDragElement.onDrop(e);
			}
			Event.stop(e);
		}
	}

	Event.observe(document, 'mousemove', updateDrag.bindAsEventListener(DND));
	Event.observe(document, 'mouseup', stopDrag.bindAsEventListener(DND));

	return {
		enable: function(button, element, params) {
			button = $CFX(button);
			element = $CFX(element);
			button.draggee = element;
			Event.observe(button, 'mousedown', startDrag);
			if (params) {
				if (params.onDrop) {
					button.onDrop = params.onDrop.bind(button);
				}
			}
		},
		disable: function(button) {
			button.draggee = null;
			Event.stopObserving(button, 'mousedown', startDrag);
		}
	};

}

var Sortable = new function() {
	var onDropListItem = function(e) {
		var moved = this.draggee;
		var list = null;
		switch (moved.tagName) {
			case 'TR':
				list = moved.parentNode;
				while (list) {
					if (list.tagName == 'TABLE') {
						break;
					}
					list = list.parentNode;
				}
				break;
			case 'LI':
				list = moved.parentNode;
				while (list) {
					if ( (list.tagName == 'UL') || (list.tagName == 'OL') ) {
						break;
					}
					list = list.parentNode;
				}
				break;
			default:
				alert('Unsortable item');
		}
		if (!list) {
			alert('Could not find item\'s parent element');
			return;
		}
		var items = list.getElementsByTagName(moved.tagName);
		var before = null;
		for (var i = items.length - 1; i >= 0; i--) {
			if (items[i] != moved) {
				var ie = $CFX(items[i]);
				if (moved.position.getY() <= ie.position.getY()) {
					before = ie;
				}
			}
		}
		var parentNode = moved.parentNode;
		parentNode.removeChild(moved);
		if (before) {
			parentNode.insertBefore(moved, before);
		} else {
			parentNode.appendChild(moved);
		}
		moved.style.position = 'static';
		if (list.submitForm) {
			list.submitForm.submit();
		}
	}
	return {
		enable: function(list, moverClass, submitForm) {
			/*
			Arguments:
				list - The UL, LI, or TABLE element to be made sortable.
				moverClass - The class name of the element that users push to
					move the item.  If moverClass is omitted, users can move
					the item by clicking anywhere inside it.
				submitForm - An optional form to be submitted after an item
					is moved.
			*/
			list = $(list);
			if (submitForm) {
				list.submitForm = $(submitForm);
			}
			var tagName = '';
			switch (list.tagName) {
				case 'TABLE':
					tagName = 'TR';
					break;
				case 'UL':
				case 'OL':
					tagName = 'LI';
					break;
				default:
					alert('Unsortable element');
			}
			var items = list.getElementsByTagName(tagName);
			for (var i = 0; i < items.length; i++) {
				var mover = items[i];
				if ( (moverClass != null) && (moverClass != '') ) {
					var movers = $(items[i]).getElementsByClassName(moverClass);
					if (movers[0]) {
						mover = movers[0];
						if (mover.tagName == 'A') {
							mover.onclick = function() {
								return false;
							}
						}
					}
				}
				DND.enable(mover, items[i], {onDrop: onDropListItem});
				Event.observe(mover, 'mousedown', function(e) {
					// If we're dragging a table row, explicitly declare each
					// column's width so it doesn't change size after being
					// absolutely positioned
					if (Event.element(e).draggee.tagName == 'TR') {
						var cols = Event.element(e).draggee.getElementsByTagName('TD');
						for (var i = 0; i < cols.length; i++) {
							cols[i].style.width = cols[i].clientWidth + 'px';
						}
					}
				});
			}
		}
	};
}

