/**
* @fileoverview Funcoes para controle de janela Drag And Drop
* @author Ricardo M. Poffo - 03/2006.
* @version 0.1
*/
var dragging = null;				// Object being dragged
var startX = 0; var startY = 0;		// Position where drag started
var maxZIndex = 0;					// Bigger Z-Index
var blinkingObject = null;			// Object being blinked

/**
* Testa se o objeto pode ser arrastado (draggable)
* @param {string} obj Nome da janela
*/
function isDraggable(obj) {
	return (obj.isDraggable != undefined && obj.isDraggable);
}

/**
 * Efeito de piscar a janela definida x vezes
 * @param {integer} times N?mero de vezes para piscar
 * @param {string} color1 Cor 1 para efeito
 * @param {string} color1 Cor 2 para efeito
 * @param {string} actualBorder estilo da borda
 */
function blinkBorder(times, color1, color2, actualBorder) {

	if (blinkingObject == null)	return;
	
	if (!times) { 
		blinkingObject.style.border = actualBorder;
		blinkingObject = null; 
		return;
	}
	
	if (times%2)
		blinkingObject.style.border = "1px solid "+ color1;
	else
		blinkingObject.style.border = "1px solid "+ color2;
		
	setTimeout('blinkBorder('+ (times-1) + ', "'+ color1 +'", "'+ color2+'", "'+ actualBorder +'")', 30);
	
}

/**
 * Seta o objeto como arrast?vel (draggable) ou n?o arrast?vel
 * Set the object as draggable (mode = true) or not (mode = false), or switch the current mode (mode = 'switch')
 * @param {DNDWindow} obj Objeto DNDWindow
 * @param {string} mode Modo.
 * @param {boolean} blink Propriedade piscar.
 * @param {float} opacity Opacidade da janela.
 * @param {string} Handle Objeto de controle do movimento da janela.
 */
function setDraggable(obj, mode, blink, opacity, Handle) {

	if (mode == undefined)			// No mode defined?
		mode = true;				// Set as "true"
	if (blink == undefined)			// No blinking defined?
		blink = true;				// Set as true
	if (opacity == undefined)		// No opacity defined?
		opacity = "1";			// Set as 85%

	if (String(mode).toLowerCase() == 'switch')
		obj.isDraggable = (obj.isDraggable == undefined || !obj.isDraggable)? true : false;
	else 
		obj.isDraggable = mode;
		
	if ( isDraggable(obj) ) {
	
		if (obj.style.position != "absolute") {			// Is not as absolute position?
		
			posX = findPosX(obj) - 20;
			posY = findPosY(obj) - 20;
			
			obj.style.top = posY + 'px';
			obj.style.left = posX + 'px';
			
			// Set transparency
			obj.style.filter = "alpha(opacity="+ (opacity * 100) +")";
			obj.style.MozOpacity = opacity;
			obj.style.opacity = opacity;

			obj.style.position = "absolute";
			
		}
		
		obj.style.zIndex = ++maxZIndex;				// "Focus" the dragging object
		setDragAndDropFunctions(Handle);		// Associates drag 'n' drop functions to object events
		obj.title = "Clique e arraste para mover";	// Put a title
		
	} else {										// Setting as not draggable...

		unsetDragAndDropFunctions(obj);	
		obj.style.zIndex = "0";
		obj.style.position = "relative";
		obj.style.top = "";
		obj.style.left = "";
		obj.title = "";
		
		obj.style.MozOpacity = "";
		obj.style.opacity = "";
		obj.style.filter = "";

		window.scrollTo(findPosX(obj) - 60, findPosY(obj) - 60);			// Go to object position
		
	}

	// Blink object borders
	if (blink) {
		blinkingObject = obj;
		blinkBorder(10, 'gold', 'black', obj.style.border);
	}

}



/**
 * Testa se janela pode ser arrastada. Sen?o, tenta arrastar objeto pai.
 * Checks if object can be dragged. If can't, try to drag parent objects
 * @param {DNDWindow} obj Objeto DNDWindow.
 */
function startDragToObject(obj) {
	if ( isDraggable(obj) ) 				// Object is draggable
		dragging = obj;
	else if (obj.parentNode != undefined)	// parent object is draggable
		startDragToObject(obj.parentNode);
}


/**
 * Inicia evento de arrastar
 * Start a drag event
 * @param {event} ev Evento.
 */
function startDrag(ev) {
	e = ev? ev : event;
	src = e.srcElement? e.srcElement : e.target;
	
	startDragToObject(src);
	if (dragging != null) {
		startX = (e.clientX - dragging.style.left.replace('px', '') );
		startY = (e.clientY - dragging.style.top.replace('px', '') );
		dragging.style.zIndex = ++maxZIndex;
	}

}


/**
 * Encerra evendo de arrastar
 * Stops a drag event
 * @param {event} ev Evento.
 */
function stopDrag(ev) {
	dragging = null;
	startX = 0;
	startY = 0;
}


/**
 * Move objeto atrav?s do
 * Move dragging objects though the document.
 * @param {event} ev Evento.
 */
function doMove(ev) {

	e = ev? ev : event;
	src = e.srcElement? e.srcElement : e.target;

	if (dragging != null) {
		dragging.style.top = e.clientY - startY;
		dragging.style.left = e.clientX - startX;
	} 
	
}


/**
 * Se for pressionada a tecla ESC, para de arrastar.
 * If ev.keyCode == ESC key code, stop dragging
 * @param {event} ev Evento.
 **/
function stopDragOnEsc(ev) {
	e = ev? ev : event;
	key = (e.which == undefined)? e.keyCode : e.which;
	if (key == 27)		// "esc" key
		stopDrag(e);	// stop drag
}



/**
 * Associa os eventos do objeto com fun??es de arrastar e soltar.
 * Associates the events on object to drag and drop functions.
 * @param {DNDWindow} obj Objeto DNDWindow
 **/
function setDragAndDropFunctions(obj) {
	if (document.all != undefined) {						// ** IE model
		obj.attachEvent('onmouseup', stopDrag);
		obj.attachEvent('onmousedown', startDrag);
	}
	else {													// ** W3C model
		obj.addEventListener('mouseup', stopDrag, false);
		obj.addEventListener('mousedown', startDrag, false);
	}
}


/**
 * Remove associa??es entre eventos do objeto e fun??es de arrastar e soltar.
 * Remove associations between objct events and drag 'n' drop functions.
 * @param {DNDWindow} obj Objeto DNDWindow.
 **/
function unsetDragAndDropFunctions(obj) {
	if (document.all != undefined) {						// ** IE model
		obj.detachEvent('onmouseup', stopDrag);
		obj.detachEvent('onmousedown', startDrag);
	}
	else {													// ** W3C model
		obj.removeEventListener('mouseup', stopDrag, false);
		obj.removeEventListener('mousedown', startDrag, false);
	}
}

/**
* Encontra a posi??o do elemento no eixo X
* @param {DNDWindow} obj Objeto DNDWindow.
*/
function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}
/**
* Encontra a posi??o do elemento no eixo Y
* @param {DNDWindow} obj Objeto DNDWindow.
*/

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

/**
* Associa eventos arrastar e soltar ao documento
*/
// *** ATTACH DRAG 'N' DROP EVENTS TO DOCUMENT *** //
if (document.all != undefined) {								// IE model
	document.attachEvent('onmousemove', doMove);
	document.attachEvent('onkeypress', stopDragOnEsc);
}
else {															// W3C model
	document.addEventListener('mousemove', doMove, false);
	document.addEventListener('keypress', stopDragOnEsc, false);
}