﻿
///////////////////////////////////////////////////////////////////
// Drag object attributes
//		dragclass
//		onclick (simulation)
//		ondblclick (simulation) not done
//		ondrop
//
// Drop target attributes
//		accepgdragclass
//		ondrop (disabled due to ambigous)
//		ondropout
//		ondropover
//		droppable
//
// Global
//
//		dragObject
//		dropTarget
//		dragObjectClass
//
///////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mouse coordination
////////////////////////////////////////////////////////////////////////////////////////////////////////


document.attachEvent('onmousemove', drag_mouseMove);
document.attachEvent('onmouseup', drag_mouseUp);

var mouseOffset 		= null;

var dropTargets 		= new Array();
var allDropTargets		= new Array();
var dragObjectClick		= null;

var dragObject  		= null;
var dropTarget			= null;
var dragObjectClass		= null;

var dropTargetStyle		= null;
var dropTargetMouseover	= null;
var dropTargetMouseout	= null;

var useDummy			= true;
var dummyOpacity		= 70;


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, ev) {
	ev = ev || window.event;

	var docPos    = getPosition(target);
	var mousePos  = mouseCoords(ev);
	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 - e.scrollLeft;
		top  += e.offsetTop - e.scrollTop;
		e     = e.offsetParent;
	}

	left += e.offsetLeft;
	top  += e.offsetTop;

	return {x:left, y:top};
}

function object_intersect(pos, target) {
	var targPos    = getPosition(target);
	var targWidth  = parseInt(target.offsetWidth);
	var targHeight = parseInt(target.offsetHeight);

	return (
		(pos.x > targPos.x)                &&
		(pos.x < (targPos.x + targWidth))  &&
		(pos.y > targPos.y)                &&
		(pos.y < (targPos.y + targHeight)));
}

function drag_mouseMove(ev) {
	ev           = ev || window.event;
	var mousePos = mouseCoords(ev);

	if (dragObject != null) {
		if (useDummy)	obj		= dragDummy;
		else			obj		= dragObject;

		obj.style.top      = mousePos.y - mouseOffset.y;
		obj.style.left     = mousePos.x - mouseOffset.x;
		
		if (dragObjectClick != false) {
			
			if (Math.abs(dragObjectClick.x - mousePos.x) > 1 || Math.abs(dragObjectClick.y - mousePos.y) > 1)

				dragObjectClick	= false;
				
		}
		
		if (dropTarget != null) {
			if (!object_intersect(mousePos, dropTarget)) {
				
				// Leave drop target
				dropTarget.style.cssText		= dropTargetStyle;
//				dropTarget.onmouseover		= dropTargetMouseover;
				//dropTarget.onmouseout		= dropTargetMouseout;
				with (dropTarget) {
					eval(getAttribute('ondropout'));
				}
				dropTarget	= null;
				return false;
			}
			return false;
		}
		
		for(var i=0; i<dropTargets.length; i++){
			var curTarget  = dropTargets[i];
			
			if (object_intersect(mousePos, curTarget)) {
				
				// Enter drop target
				if (useDummy)	obj		= dragDummy;
				else			obj		= dragObject;
				
				dropTarget			= curTarget;
				dropTargetStyle		= dropTarget.style.cssText;
//				alert(dropTargetMouseout);
				with (dropTarget) {
					eval(getAttribute('ondropover'));
				}
				break;
	
			}
		}


		return false;
	}
}

//function disable_mouseover() {};


function drag_mouseUp(ev) {

	if (dragObject == null)		return;

	ev           = ev || window.event;
	var mousePos = mouseCoords(ev);

	for(var i=0; i<dropTargets.length; i++){
		var curTarget  = dropTargets[i];

		if (object_intersect(mousePos, curTarget)) {

			if (useDummy)	obj		= dragDummy;
			else			obj		= dragObject;

			if (curTarget.getAttribute('droppable')) {
				curTarget.appendChild(obj.children(0));
			}
			
			dragObjectClass		= dragObject.getAttribute('dragclass');
			//eval(curTarget.getAttribute('ondrop'));  // Disabled due to ambigous
			eval(dragObject.getAttribute('ondrop'));
			dragObject.fireEvent('ondrop');
			
			dropTarget.style.cssText		= dropTargetStyle;

		}
	}

	if (useDummy) {
		// Clear dummy object
		for (i=0; i<dragDummy.children.length; i++) {
			dragDummy.removeChild(dragDummy.children(i));
		}
	}
	
	if (dragObjectClick)
		dragObject.fireEvent('onclick');

	changeOpacity(dragObject, 100);
	
	dragObject   = null;
}


function dragstart(ev) {
	ev				= ev || window.event;
	if (ev.button == 2)	return;
	
	if (this.dragDisable == true)	return;
	
	this.fireEvent('onmouseout');
	dragObject		= this;
	dragObjectClick	= true;

	mouseOffset		= getMouseOffset(this, ev);
	dragObjectClick	= mouseCoords(ev);

	if (useDummy) {
		
		// Initialize the dummy object
		dummyNode	= this.cloneNode(true);
//		drag_disable_child_event(dummyNode);
		dragDummy.appendChild(dummyNode);

		// Initialize the dummy object position
		var mousePos = mouseCoords(ev);
		dragDummy.style.top			= mousePos.y - mouseOffset.y;
		dragDummy.style.left		= mousePos.x - mouseOffset.x;
		dragDummy.style.display		= 'block';

		
		changeOpacity(this, 50);

	} else {
		dragObject.style.position	= 'absolute';
	}
	
	
	// Find all dropable targets
	dropTargets.length	= 0;
	dragclasses			= dragObject.getAttribute('dragclass').split(/,| |, /);
	for (i in allDropTargets) {
		accept			= allDropTargets[i].getAttribute('acceptdragclass').split(/,| |, /);
		if (array_intersect(accept, dragclasses).length != 0) {
			dropTargets.push(allDropTargets[i]);
		}
	}
}

function array_intersect(array1, array2) {
	var result = new Array();
	for (j in array1) {
		for (k in array2) {
			if (array1[j] == array2[k]) {
				result.push(array2[k]);
				break;
			}
		}
		
	}
	return result;
}


function changeOpacity(object, opacity) {
	if (!object)
    	object = document.getElementById(object).style;
    object.opacity = (opacity / 100); 
    object.MozOpacity = (opacity / 100); 
    object.style.filter = "alpha(opacity=" + opacity + ")"; 
}


function drag_disable_child_event(node) {
	if (node.tagName == undefined)	return;
	if (node.nodeType == 1 || node.nodeType == 3 || node.nodeType == 9) {
		//node.clearAttributes();		Not applicatable , this will remove image !
		if (node.hasChildNodes()) {
			var children = node.childNodes;
			for (var i = 0; i < children.length; i++) {
				drag_disable_child_event(children[i]);
			}
		}
	}
}


function drag_initialize() {

	mouseOffset 			= null;
	dragObject  			= null;
	dropTarget				= null;
	dropTargetStyle			= null;
	dropTargetMouseover		= null;
	dropTargetMouseout		= null;
	dragObjectClick			= null;
	dropTargets 			= new Array();
	allDropTargets			= new Array();
	
	if (useDummy) {
		// Create Dummy object
		dragDummy					= document.createElement('DIV');
		dragDummy.id				= 'dragDummy';
		dragDummy.style.cssText 	= 'position:absolute;display:none;filter: alpha(opacity=' + dummyOpacity + ');';
		document.body.appendChild(dragDummy);
	}


    var alltags = document.getElementsByTagName("*");
	
	// Check for all draggable classes
    for (i=0; i < alltags.length; i++) {
        tag   = alltags[i];    
        if (tag.getAttribute('dragclass') != null) {
            tag.onmousedown		= dragstart;
        }
        if (tag.getAttribute('acceptdragclass') != null) {
        	allDropTargets.push(tag);
        }
    }
}


window.attachEvent('onload', drag_initialize);



