function ordering_enableDrag(el) {
	SortableListItem.getInstance(el);
}

function ordering_hover(el) {

	if(DragPane.hoveredElement != null) {
		removeClass(DragPane.hoveredElement, "hoveredItem");
	}
	if(!hasToken(el.className, "hoveredItem"))
		el.className += " hoveredItem";
	DragPane.hoveredElement = el;

	//SortableListItem.getInstance(el);
}

function ordering_hoverOff() {
	if(DragPane.hoveredElement != null){
		removeClass(DragPane.hoveredElement, "hoveredItem");
	}
	DragPane.hoveredElement = null;
}


//--------------------------------------------------------------------------------

SortableListItem = function(el) {

	this.el = el;
	this.el.oncontextmenu = function() {
		return false;
	};
	
	this.listItem = DragObj.getInstance(el, DragObj.constraints.VERT);
	this.listItem.isRel = true;
	this.listItem.keepInContainer = true;
	
	this.dragPane = DragPane.getInstance(findAncestorWithClass(el, "dragPane"));
	
	var dragPane = this.dragPane;
	this.listItem.onbeforedragstart = function() {
		
		if(DragPane.focusedElement != this.el) {
			if(DragPane.focusedElement != null)
				removeClass(DragPane.focusedElement, "focusedItem");
			this.el.className += " focusedItem";
			DragPane.focusedElement = this.el;
		}
		
		return true;
	};
	
	this.listItem.onfocus = function() {
		
	};
	
	this.listItem.ondragstart = function() {
		this.el.className += " activeDrag";
		this.el.style.cursor = "move";
		this.el.style.zIndex = 1000;
	};	
	

	var items = this.dragPane.items();
	
	for(var i = 0; i < items.length; i++)
		if(el != items[i]) 
			this.listItem.addDropTarget(items[i]);
	
	
	// define accessible variable;
	var dragPane = this.dragPane;
	
	// all done dragging
	this.listItem.ondragend = function() {
		removeClass(this.el, "activeDrag");
		this.el.style.cursor = "default";
		this.el.style.top=0;
		this.el.style.zIndex = "";
	};


	// we hit a drop target.
	this.listItem.ondragdrop = function(e) {
		dragPane.resort(this, e.dropTarget);
		dragPane.updateForm();
	};
	
	Listener.add(this.listItem, "ondrag", listItemDragged);
	
};

listItemDragged = function() {
	var listItem = SortableListItem.instances[this.id];
	while(listItem.yPosOverlap() > -5) 
		window.scrollBy(0, 1);
		
	while(listItem.yNegOverlap() < 3) 
		window.scrollBy(0, -1);
}

SortableListItem.instances =  {};

SortableListItem.prototype = {

	onfocus : function(){},
	
	focus : function() {
		this.listItem.onbeforedragstart();
		this.onfocus();
	},
	
	yPosOverlap : function() {
		return getOffsetTop(this.el) - (getViewportHeight() + getScrollTop() - 15);
	},
	
	yNegOverlap : function() { return getOffsetTop(this.el) - getScrollTop(); }

};


SortableListItem.getInstance = function(el) { 
	var x = SortableListItem.instances[el.id];
	if(!x)
		x= SortableListItem.instances[el.id] = new SortableListItem(el);
	return x; 
};


DragPane = function(el) {
	this.el = el;
	
	if(typeof this.el.style.MozUserSelect == "string")
	this.el.style.MozUserSelect = "none";
	this.form = document.getElementById(this.el.id+"form");
	//this.elements= document.getElementById(this.el.id+"Fields").getElementsByTagName("input");
		
	this.id = el.id;
	//this.el.onselectstart = function() { return false; };
		
	
	this.position = {
		top : el.offsetTop,
		left : el.offsetLeft,
		bottom : el.offsetTop + el.offsetHeight,
		right : el.offsetWidth + el.offsetLeft
	};
	
	
	DragPane.instances[this.id] = this;
};
DragPane.instances = {};
DragPane.getInstance = function(el) {
	var instance = DragPane.instances[el.id];
	if(instance == null)
		instance = DragPane.instances[el.id] = new DragPane(el);
	return instance;
}

DragPane.prototype = {
	
	id : "",
	form : null,
	elements : null,
	
	position : { top: 0, left : 0, bottom : 0, right : 0 },
	
	items : function() { return getElementsWithClass(this.el, "div", "orderingItem"); },

	resort : function(listItem, dropTarget) {
		
		// If the element is on the top half of the drop target, insert it before.
		// otherwise, append it.
		
		
		var listItemBottom = listItem.y + listItem.el.offsetTop + listItem.el.offsetHeight;
		var dropTargetBottom = dropTarget.el.offsetTop + dropTarget.el.offsetHeight;
		
		if(listItemBottom >= dropTargetBottom) {
			this.el.insertBefore(listItem.el, dropTarget.el.nextSibling);
		}
		
		else {
 			this.el.insertBefore(listItem.el, dropTarget.el);
 		}
				
		listItem.el.style.top = dropTarget.el.style.top = 0;

		document.documentElement.style.cursor = "auto";
		
	},
	
	updateForm : function() {
		
		var items = this.items();
		var stringitems = "";
		for(var i = 0, len = items.length; i < len; i++) {
			stringitems +=items[i].id + "|";
			//if(!this.elements[items[i].id])
				//alert("Form Element \""+items[i].id+"\" does not exist.");
			//this.elements[items[i].id].value = i;
		}
		stringitems = stringitems.substring(0, stringitems.length-1);
		document.getElementById("t_"+t_prefix+"listOrder").value = stringitems;
	}
	
};
keyPressed = function(e) {
	
	if(DragPane.focusedElement == null)
		return;

	if(!e)
		e = window.event;
	
	var sibling;
	
	var isUpArrow = e.keyCode == 38;
	var isDownArrow = e.keyCode == 40;
	
	if(isUpArrow) { // up arrow key.
	
		sibling = findPreviousSiblingWithClass(DragPane.focusedElement, "orderingItem");
	}
	else if(isDownArrow) { // down arrow key.
	
		sibling = findNextSiblingWithClass(DragPane.focusedElement, "orderingItem");
		
	}
	
	if(sibling != null) {
		var sli = SortableListItem.getInstance(sibling);
		
		if(e.ctrlKey) {
			if(isUpArrow)
				sli.dragPane.el.insertBefore(DragPane.focusedElement, sibling);
			else if(isDownArrow)
				sli.dragPane.el.insertBefore(sibling, DragPane.focusedElement);
		}
		else 
			sli.focus();
	}
	
};

Listener.add(document, "keydown", keyPressed);


DragPane.hoveredElement = null;
DragPane.focusedElement = null;

/**
 * DragPane.documentMouseMove handles mousemove for the dragPane's parent element
 * so we can track when the cursor leaves the dragPane element.
 */
DragPane.documentMouseMove = function(e) {

 	var target = getTarget(e);
	
	var dragPaneTarget = null;
	if(target.className && hasToken(target.className, "dragPane"))
		dragPaneTarget = target;
	else 
		dragPaneTarget = findAncestorWithClass(target, "dragPane");
	if(dragPaneTarget == null)
		return;


	var dragPane = DragPane.getInstance(dragPaneTarget);
	if(!contains(dragPane.el, target) && DragPane.hoveredElement != null){
		removeClass(DragPane.hoveredElement, "hoveredItem"); 
		DragPane.hoveredElement = null;
	}
	
};
Listener.add(document, "mousemove", DragPane.documentMouseMove);



//---------------------------------------------------------------------------


function findPreviousSiblingWithClass(el, className) {

	for(var ps = el.previousSibling; ps != null; ps = ps.previousSibling)
		if(hasToken(ps.className, className)) 
			return ps;
		return null;
}

function findNextSiblingWithClass(el, className) {

	for(var ns = el.nextSibling; ns != null; ns = ns.nextSibling)
		if(hasToken(ns.className, className)) 
			return ns;
		return null;
}

/**
 * Returns an Array of elements with the specified tagName and className.
 */
function getElementsWithClass(parent, tagName, klass){
	var returnedCollection = [];

	var exp = getTokenizedExp(klass,"");
	var collection = (tagName == "*" && parent.all) ?
		parent.all : parent.getElementsByTagName(tagName);
	
	for(var i = 0, counter = 0, len = collection.length; i < len; i++){
		
		if(exp.test(collection[i].className))
			returnedCollection[counter++] = collection[i];
	}
	return returnedCollection;
}


function findAncestorWithClass(el, klass) {
	
	if(el == null)
		return null;
	var exp = getTokenizedExp(klass,"");
	for(var parent = el.parentNode; parent != null;){
	
		if( exp.test(parent.className) )
			return parent;
			
		parent = parent.parentNode;
	}
	return null;
}


var TRIM_EXP = /^\s+|\s+$/g;
String.prototype.trim = function(){
		return this.replace(TRIM_EXP, "");
};
var WS_MULT_EXP = /\s\s+/g;
String.prototype.normalize = function(){
		return this.trim().replace(WS_MULT_EXP, " ");
};

TokenizedExps = {};
function getTokenizedExp(token, flag){
	var x = TokenizedExps[token];
	if(!x)
		x = TokenizedExps[token] = new RegExp("(^|\\s)"+token+"($|\\s)", flag);
	return x;
}

function hasToken(s, token){
	return getTokenizedExp(token,"").test(s);
};
function removeClass(el, klass){
	el.className = el.className.replace(getTokenizedExp(klass, "g")," ").normalize();
}

function getViewportHeight() {
	if(window.innerHeight)
		return window.innerHeight;
	if(typeof window.document.documentElement.clientHeight=="number")
		return window.document.documentElement.clientHeight;
	return window.document.body.clientHeight;
}
function getScrollTop(){
	if(typeof window.pageYOffset=="number")
		return window.pageYOffset;
	if(document.documentElement.scrollTop)
		return Math.max(document.documentElement.scrollTop,document.body.scrollTop);
	if(document.body.scrollTop!=null)
		return document.body.scrollTop;
	return 0;
}
