function fetchParentContainer(t) {
	if (t.nodeName == 'DIV') return t;
	return fetchParentContainer(t.parentNode);
//	if (!t)t = t.parentNode;
//	return (t.nodeName == 'DIV') ? t : fetchParentContainer(t);
// nodeType 
//	
//	return (t!=null && t.className == 'outerParentBlock') ? t : fetchParentContainer(t);
}
function mouseMove(ev){
	ev         = ev || window.event;
	var target   = ev.target || ev.srcElement;
	var mousePos = mouseCoords(ev);
	// mouseOut event - fires if the item the mouse is on has changed

	if(lastTarget && (target!==lastTarget)){
		// reset the classname for the target element
		var origClass = lastTarget.getAttribute('origClass');
		if(origClass) lastTarget.className = origClass;
	}

	/*
	dragObj is the grouping our item is in (set from the createDragContainer function).
	if the item is not in a grouping we ignore it since it can't be dragged with this
	script.
	*/
	if (targetListener!=null) target = fetchParentContainer(targetListener.parentNode);

	var dragObj = target.getAttribute('DragObj');
	 // if the mouse was moved over an element that is draggable
	if(dragObj!=null && targetListener!=null){
		// mouseOver event - Change the item's class if necessary
		if(target!=lastTarget){
			var oClass = target.getAttribute('overClass');
			if(oClass){
				target.setAttribute('origClass', target.className);
				target.className = oClass;
			}
		}

		// if the user is just starting to drag the element
		if(iMouseDown && !lMouseState){
			// mouseDown target
			curTarget     = target;

			// Record the mouse x and y offset for the element
			rootParent    = curTarget.parentNode;
			rootSibling   = curTarget.nextSibling;

			mouseOffset   = getMouseOffset(target, ev);

			// We remove anything that is in our dragHelper DIV so we can put a new item in it.
			for(var i=0; i<tmpDrag.childNodes.length; i++) tmpDrag.removeChild(tmpDrag.childNodes[i]);

			// Make a copy of the current item and put it in our drag helper.
			tmpDrag.appendChild(curTarget.cloneNode(true));
			tmpDrag.style.display = 'block';
			tmpDrag.style.width = parseInt(curTarget.offsetWidth);
			// tmpDrag.style.width = curTarget.getAttribute('startWidth');

			// Make the phantom-tween thingy
			curTarget.style.height = parseInt(curTarget.offsetHeight)-15;
			curTarget.className = curTarget.className+"Tween";

			// set the class on our helper DIV if necessary
			var dragClass = curTarget.getAttribute('dragClass');
			if(dragClass){
				tmpDrag.firstChild.className = dragClass;
			}

			// disable dragging from our helper DIV (it's already being dragged)
			tmpDrag.firstChild.removeAttribute('DragObj');

			/*
			Record the current position of all drag/drop targets related
			to the element.  We do this here so that we do not have to do
			it on the general mouse move event which fires when the mouse
			moves even 1 pixel.  If we don't do this here the script
			would run much slower.
			*/
			var dragConts = DragDrops[dragObj];

			/*
			first record the width/height of our drag item.  Then hide it since
			it is going to (potentially) be moved out of its parent.
			*/
			curTarget.setAttribute('startWidth',  parseInt(curTarget.offsetWidth));
			curTarget.setAttribute('startHeight', parseInt(curTarget.offsetHeight));
			curTarget.style.display  = 'none';

			// loop through each possible drop container
			for(var i=0; i<dragConts.length; i++){
				with (dragConts[i]){
					var pos = getPosition(dragConts[i]);
					setAttribute('startWidth',  parseInt(offsetWidth));
					setAttribute('startHeight', parseInt(offsetHeight));
					setAttribute('startLeft',   pos.x);
					setAttribute('startTop',    pos.y);
				}

				// loop through each child element of each container
				for(var j=0; j<dragConts[i].childNodes.length; j++){
					with (dragConts[i].childNodes[j]){
						if((nodeName=='#text') || (dragConts[i].childNodes[j]==curTarget)) continue;

						var pos = getPosition(dragConts[i].childNodes[j]);

						// save the width, height and position of each element
						setAttribute('startWidth',  parseInt(offsetWidth));
						setAttribute('startHeight', parseInt(offsetHeight));
						setAttribute('startLeft',   pos.x);
						setAttribute('startTop',    pos.y);
					}
				}
			}
		}
	}

	// If we get in here we are dragging something
	if(curTarget){
		// move our helper div to wherever the mouse is (adjusted by mouseOffset)
		tmpDrag.style.top  = mousePos.y - mouseOffset.y;
		tmpDrag.style.left = mousePos.x - mouseOffset.x;

		var dragConts  = DragDrops[curTarget.getAttribute('DragObj')];
		var activeCont = null;

		var xPos = mousePos.x - mouseOffset.x + (parseInt(curTarget.getAttribute('startWidth')) /2);
		var yPos = mousePos.y - mouseOffset.y + (parseInt(curTarget.getAttribute('startHeight'))/2);


		// check each drop container to see if our target object is "inside" the container
		for(var i=0; i<dragConts.length; i++){
			with (dragConts[i]){
				if((parseInt(getAttribute('startLeft'))+parseInt(getAttribute('startWidth'))) > xPos) {
					activeCont = dragConts[i];
					break;
				}
			}
		}
		// detect beyond the right margin righ column case
		if (activeCont==null) activeCont = dragConts[dragConts.length-1];

		// Our target object is in one of our containers.  Check to see where our div belongs
		if(activeCont){
			// beforeNode will hold the first node AFTER where our div belongs
			var beforeNode = null;
			// loop through each child node (skipping text nodes).
			for(var i=activeCont.childNodes.length-1; i>=0; i--){
				with (activeCont.childNodes[i]){
					if(nodeName=='#text') continue;

					// if the current item is "After" the item being dragged
/*
					if(
						curTarget != activeCont.childNodes[i]                              &&
						((getAttribute('startLeft') + getAttribute('startWidth'))  > xPos) &&
						((getAttribute('startTop')) > yPos)){
							beforeNode = activeCont.childNodes[i];
					}
					if(curTarget != activeCont.childNodes[i] && (getAttribute('startTop') > yPos)) {
						 beforeNode = activeCont.childNodes[i];
					}
*/
					if((parseInt(getAttribute('startTop'))+parseInt(getAttribute('startHeight'))/2) > yPos) {
							beforeNode = activeCont.childNodes[i];
					}
				}
			}
			if (curTarget != beforeNode) {
				// the item being dragged belongs before another item
				if(beforeNode){
					if(beforeNode!=curTarget.nextSibling) activeCont.insertBefore(curTarget, beforeNode);
				// the item being dragged belongs at the end of the current container
				} else {
					if((curTarget.nextSibling) || (curTarget.parentNode!=activeCont)) activeCont.appendChild(curTarget);
				}
				// make our drag item visible
				if(curTarget.style.display!='') curTarget.style.display  = '';
			}
		} else {
			// our drag item is not in a container, so hide it.
			if(curTarget.style.display!='none') curTarget.style.display  = 'none';
		}
	}

	// mouseMove target
	lastTarget  = target;

	// track the current mouse state so we can compare against it next time
	lMouseState = iMouseDown;

	// this helps prevent items on the page from being highlighted while dragging, for non-IE UAs only!!!
	if (!isIEtest()) return false;
}
function CreateDragContainer(){
	/*
	Create a new "Container Instance" so that items from one "Set" can not
	be dragged into items from another "Set"
	*/
	var cDrag        = DragDrops.length;
	DragDrops[cDrag] = [];

	/*
	Each item passed to this function should be a "container". 
	Store each of these items in our current container
	*/
	var tmpflag;
	for(var i=0; i<arguments.length; i++){
	var cObj = arguments[i];
	if (cObj&&cObj!=null) {
		DragDrops[cDrag].push(cObj);
		cObj.setAttribute('DropObj', cDrag);

		/*
		Every top level item in these containers should be draggable.  Do this
		by setting the DragObj attribute on each item and then later checking
		this attribute in the mouseMove function
		*/
		
		for(var j=0; j<cObj.childNodes.length; j++){
//		tmpflag = true;
			if (cObj.childNodes[j].nodeName=='#text') continue; // ff cleanup
			if ((!cObj.childNodes[j].className) || (cObj.childNodes[j].className!='outerParentBlock')) continue;
			cObj.childNodes[j].setAttribute('DragObj', cDrag);
			for(var z=0; z<cObj.childNodes[j].childNodes.length; z++){
				if ((cObj.childNodes[j].childNodes[z].nodeName=='#text')) continue; // ff cleanup
				if (cObj.childNodes[j].childNodes[z].id && (cObj.childNodes[j].childNodes[z].id.indexOf('ttid')==0)) {
					cObj.childNodes[j].childNodes[z].style.cursor='move';
					if (isIEtest()) {
						cObj.childNodes[j].childNodes[z].onmouseover = function() {enableTgtListener(this);}
						cObj.childNodes[j].childNodes[z].onmouseout = function() {disableTgtListener(this,event);}
					} else {
						cObj.childNodes[j].childNodes[z].setAttribute("onmouseover", "enableTgtListener(this)");
						cObj.childNodes[j].childNodes[z].setAttribute("onmouseout", "disableTgtListener(this,event)");
					}
				}
//				tmpflag = false;
			}
		}
	}
	}
}
function enableTgtListener(o) {
	targetListener = o;
}

function isIEtest() {
	return (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent));
}

function disableTgtListener(o,e) {
	var tmp = null;
		 if(e.toElement) tmp = e.toElement;
	else if(e.relatedTarget) tmp = e.relatedTarget;
	if (!checkIfNested(o,tmp) && o!=tmp) targetListener = null;
}
function checkIfNested(o,t) {
	if(t!=null) {while(t.parentNode) {if((t=t.parentNode)==o) return true;}}
	return false;
}
function mouseCoords(ev) {
	if(ev.pageX || ev.pageY){
		return {x:ev.pageX, y:ev.pageY};
	}
	return {
		x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
		y:ev.clientY + document.body.scrollTop  - document.body.clientTop
	};
}
function getMouseOffset(target, e) {
	var docPos    = getPosition(target);
	var mousePos  = mouseCoords(e || window.event);
	return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}
function getPosition(e) {
	var left = 0;
	var top  = 0;
	while (e.offsetParent) {
		left += e.offsetLeft;
		top  += e.offsetTop;
		e     = e.offsetParent;
	}
	left += e.offsetLeft;
	top  += e.offsetTop;
	return {x:left, y:top};
}
function mouseUp(e) {
	if(curTarget){
		tmpDrag.style.display = 'none';
		if(curTarget.style.display == 'none'){
			if(rootSibling){
				rootParent.insertBefore(curTarget, rootSibling);
			} else {
				rootParent.appendChild(curTarget);
			}
		}
		curTarget.style.display = '';
		// Remove the phantom-tween thingy
		curTarget.style.height = "auto";
		curTarget.className = curTarget.className.substring(0,curTarget.className.indexOf("Tween"));
	}
	curTarget  = null;
	iMouseDown = false;
	targetListener = null;
}
function mouseDown() {
	iMouseDown = true;
//	if(lastTarget) {
	if(targetListener!=null) {
		return false;
	}
}
function createTmpDragTweenUnit() {
	tmp = document.createElement('DIV');
	tmp.id = "kfjnrekjnfjnfkjf";
	tmp.style.cssText = "position:absolute;display:none;opacity:.6;filter:alpha(opacity=60);";
	document.body.appendChild(tmp);
	return tmp;
}
function createInitDragEnvs() {
	tmpDrag = createTmpDragTweenUnit();
	CreateDragContainer(
//		document.getElementById('thisDragableUnitA'),
		document.getElementById('thisDragableUnitB'),
		document.getElementById('thisDragableUnitC')
	);
}
var DragDrops	= [];
var iMouseDown	= false;
var lMouseState	= false;
var targetListener = null;
var dragTween	= null;
var dragObj	= null;
var tmpDrag	= null;
var mouseOffset	= null;
var curTarget	= null;
var lastTarget	= null;
var rootParent	= null;
var rootSibling	= null;
document.onmouseup	= mouseUp;
document.onmousemove	= mouseMove;
document.onmousedown	= mouseDown;
