
//==============================================================================
// Javascript Library (c) Virtooz 2006-2008
//
// LIBRARY: uDragDrop.js
//
// DESCRIPTION
// Add drag-drop functionality to DIV's
//==============================================================================

var cardDistance = 22;      //Distance between cards
var cardDistanceHorizontal = 10; //Distance between cards when using horizontal orientation
var cardBorder   = 1;       //Border width of cards
var dragContainers = [];    //Array of DIV's with drag-drop capabilities
var isDragging = false;     //Are we dragging anything?
var dragItem = null;        //The item currently being dragged
var originalItem = null;    //The original item that was hidden while a copy is being dragged 
var originalCont = null;    //The container of the original item
var dragOffsetX = 0;        //X-coord of mouse in the item currently being dragged
var dragOffsetY = 0;        //Y-coord of mouse in the item currently being dragged
var dragHelper = null;      //Drag helper DIV, used to store the item being dragged
var onAfterDrop = '';       //Function to call after item is dropped
var lastItem = null;
//------------------------------------------------------------------------------
// NaN0
//
// Extend prototype of the javascript object number with a function which 
// returns the number itself, or 0 when the number evaluates to 'Not a Number'.
//------------------------------------------------------------------------------

Number.prototype.NaN0=function(){return isNaN(this)?0:this;}

//------------------------------------------------------------------------------
// getMouseCoords
//
// Get the mouse coordinates in the current document
//------------------------------------------------------------------------------

function getMouseCoords(event) {
	if(event.pageX || event.pageY) {
		return {x:event.pageX, y:event.pageY};
  }
	return {
		x:event.clientX + document.body.scrollLeft - document.body.clientLeft,
		y:event.clientY + document.body.scrollTop  - document.body.clientTop
	};
}

//------------------------------------------------------------------------------
// getMouseOffset
//
// Get relative mouse coordinates in a DIV
//------------------------------------------------------------------------------

function getMouseOffset(Div, event){
	event = event || window.event;
	var docPos    = getDivCoords(Div);
	var mousePos  = getMouseCoords(event);
	return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}

//------------------------------------------------------------------------------
// mouseOverDiv
//
// Is the mouse over a DIV when an mouse event was fired?
//------------------------------------------------------------------------------

function mouseOverDiv(Div, event) {
  var coords = getMouseOffset(Div, event);
  if ((coords.x >= 0) && (coords.x < Div.offsetWidth) && 
      (coords.y >= 0) && (coords.y < Div.offsetHeight)) {
     return true;
  }
  return false;
}

//------------------------------------------------------------------------------
// getDivCoords
//
// Get the coordinates of a DIV in the current document.
//------------------------------------------------------------------------------

function getDivCoords(Div) {
	var left = 0;
	var top  = 0;
	while (Div.offsetParent) {
		left += Div.offsetLeft + (Div.currentStyle?(parseInt(Div.currentStyle.borderLeftWidth)).NaN0():0);
		top  += Div.offsetTop  + (Div.currentStyle?(parseInt(Div.currentStyle.borderTopWidth)).NaN0():0);
		Div     = Div.offsetParent;
	}
	left += Div.offsetLeft + (Div.currentStyle?(parseInt(Div.currentStyle.borderLeftWidth)).NaN0():0);
	top  += Div.offsetTop  + (Div.currentStyle?(parseInt(Div.currentStyle.borderTopWidth)).NaN0():0);
	return {
    x:left, 
    y:top
  };
}

//------------------------------------------------------------------------------
// showDiv
//
// Show or hide a div
//------------------------------------------------------------------------------

function showDiv(Div, flag) {
  if (flag) {
    Div.style.visibility = 'visible';
  }
  else {
    Div.style.visibility = 'hidden';
  }
}

//------------------------------------------------------------------------------
// hideDiv
//
// pposite of showDiv: Hide or show  a div
//------------------------------------------------------------------------------

function hideDiv(Div, flag) {
  if (flag) {
    Div.style.visibility = 'hidden';
  }
  else {
    Div.style.visibility = 'visible';
  }
}

//------------------------------------------------------------------------------
// displayDiv(Div, flag)
//
// Display or do not display a div
//------------------------------------------------------------------------------

function displayDiv(Div, flag) {
  if (flag) {
    Div.style.display = '';
  }
  else {
    Div.style.display = 'none';
  }
}

//------------------------------------------------------------------------------
// countDivs
//
// Count the number of child DIV's in a DIV
//------------------------------------------------------------------------------

function countDivs(Div) {
  var numDivs = 0
  for (var i=0; i<Div.childNodes.length; i++) {
    if(Div.childNodes[i].nodeName=='DIV') numDivs++;
  }
  return numDivs;
}

//------------------------------------------------------------------------------
// sumDivHeights
//
// Calculate the sum of the heights of all child DIV's in a DIV
//------------------------------------------------------------------------------

function sumDivHeights(Div) {
  var height = 0;
  for (var i=0; i<Div.childNodes.length; i++) {
    if(Div.childNodes[i].nodeName=='DIV') {
      height += Div.childNodes[i].offsetHeight;
    }
  }
  return height;
}

//------------------------------------------------------------------------------
// rearrangeCards
//
// Rearrange the cards in the container div
//
// Div:             container div
// maxHeight:       max. distance between top of cards
// cardBorderWidth: width of the border of the cards
//------------------------------------------------------------------------------

function rearrangeCards(Div, maxHeight, cardBorderWidth) {
  var numDivs = countDivs(Div);
  var cardSize = 0
  if (Div.getAttribute("orientation")=="horizontal") {
    for (var i=0; i<Div.childNodes.length; i++) {
      if (Div.childNodes[i].nodeName=='DIV') {
        cardSize = Div.childNodes[i].offsetWidth;
        break;
      }
    }
    var widthPerDiv = (Div.offsetWidth - cardSize) / (numDivs-1);
    if (widthPerDiv > maxHeight) widthPerDiv = maxHeight;
    var currentX = 0;
    for (var i=0; i<Div.childNodes.length; i++) {
      if (Div.childNodes[i].nodeName=='DIV') {
        Div.childNodes[i].style.left = currentX + 'px';
        Div.childNodes[i].style.top = '0px';
        currentX += widthPerDiv;
      }
    }
  }
  else {
    for (var i=0; i<Div.childNodes.length; i++) {
      if (Div.childNodes[i].nodeName=='DIV') {
        cardSize = Div.childNodes[i].offsetHeight;
        break;
      }
    }
    var heightPerDiv = (Div.offsetHeight - cardSize) / (numDivs-1);
    if (heightPerDiv > maxHeight) heightPerDiv = maxHeight;
    var currentY = 0;
    for (var i=0; i<Div.childNodes.length; i++) {
      if (Div.childNodes[i].nodeName=='DIV') {
        Div.childNodes[i].style.top = currentY + 'px';
        Div.childNodes[i].style.left = '0px';
        currentY += heightPerDiv;
      }
    }
  }
}

//------------------------------------------------------------------------------
// getContainerByEvent
//
// When a mouse event is fired, this function returns the dragContainer which
// is at the mouse position, or null when the mouse is not over a dragContainer.
//------------------------------------------------------------------------------

function getContainerByEvent(event) {
  for (i=0; i<dragContainers.length; i++) {
    if (mouseOverDiv(dragContainers[i], event)) return dragContainers[i];
  }
  return null;
}

//------------------------------------------------------------------------------
// getCardByEvent
//
// When a mouse event is fired, this functions returns the card which is at the 
// mouse position, or null when the mouse is not over a card, 
//------------------------------------------------------------------------------

function getCardByEvent(event) {
  var Container = getContainerByEvent(event);
  if (Container != null) {
    for (var i=Container.childNodes.length-1; i>=0; i--) {
      if ((Container.childNodes[i].nodeName == 'DIV') && 
          (mouseOverDiv(Container.childNodes[i], event))) {
        return Container.childNodes[i];
      }
    }
  }
  return null;
}

//------------------------------------------------------------------------------
// emptyDragHelper
//
// Empty the dragHelper, by removing all childnodes in it.
//------------------------------------------------------------------------------

function emptyDragHelper() {
    for(var i=0; i<dragHelper.childNodes.length; i++) {
      dragHelper.removeChild(dragHelper.childNodes[i]);
    }
}

//------------------------------------------------------------------------------
// addDragContainer
//
// Add a DIV as a container with drag-drop capabilities
//------------------------------------------------------------------------------

function addDragContainer(Div) {
  dragContainers.push(Div);
}

//------------------------------------------------------------------------------
// isCardInContainer
//
// Can a certain card be found in a container. 
//------------------------------------------------------------------------------

function isCardInContainer(cardDiv, containerDiv) {
  var cardId = cardDiv.getAttribute('cardId');
  for (i=0; i<containerDiv.childNodes.length; i++) {
    if ((containerDiv.childNodes[i].nodeName == 'DIV') &&
        (containerDiv.childNodes[i].getAttribute('cardId')==cardId)) {
      return true;
    } 
  }
  return false;
}

//------------------------------------------------------------------------------
// doMouseDown
//
// Handle mouse down event
//------------------------------------------------------------------------------

function doMouseDown(event) {
  var container = getContainerByEvent(event);
  var item = getCardByEvent(event);
  
  //************************************************************
  //RV 20080124: Dirty hack to prevent that the dialog can not be 
  //             be closed when it is over the cards
  //************************************************************
  if (document.getElementById('dialog')) {
    if (document.getElementById('dialog').style.visibility=='visible') return true;
  }
  
  if (item != null) {
  
    originalCont = container;
    originalItem = item;
    
    dragItem = document.body.appendChild(originalItem.cloneNode(true));
    dragItem.style.left = getDivCoords(originalItem).x + 'px';
    dragItem.style.top = getDivCoords(originalItem).y + 'px';
    
    if (originalCont.getAttribute('spawnCards')=='false') {
      hideDiv(originalItem, true);
    }
    
    var mouseOffset = getMouseOffset(dragItem, event);
    dragOffsetX = mouseOffset.x;
    dragOffsetY = mouseOffset.y;

    isDragging = true;
    return false;
  }
}

//------------------------------------------------------------------------------
// doMouseUp
//
// Handle mouse up event
//------------------------------------------------------------------------------

function doMouseUp(event) {
  if (isDragging) {
    
    document.body.removeChild(dragItem);
    dragItem = null;
    var isRemoved = false;
    
    var container = getContainerByEvent(event);
    
    if ((container==null) || (container==originalCont)) {
      if (originalCont.getAttribute('dropOutside')=='true') {
        originalCont.removeChild(originalItem);
        isRemoved = true;
        if (originalCont.getAttribute('orientation')=='horizontal') {
          rearrangeCards(originalCont, cardDistanceHorizontal, cardBorder);
        }
        else {
          rearrangeCards(originalCont, cardDistance, cardBorder);
        }
        isDragging = false;
        return false;
      }
      else {
        hideDiv(originalItem, false);
        isDragging = false;
        return false;
      }
    }
    
    //Check for destroyCards
    if (container.getAttribute('destroyCards')=='true') {
      originalCont.removeChild(originalItem);
      isRemoved = true;
      if (originalCont.getAttribute('orientation')=='horizontal') {
        rearrangeCards(originalCont, cardDistanceHorizontal, cardBorder);
      }
      else {
        rearrangeCards(originalCont, cardDistance, cardBorder);
      }
      if (onAfterDrop!='') eval(onAfterDrop);
    }
        
    if (isCardInContainer(originalItem, container) && container.getAttribute('allowDuplicates')=='false') {
      /*
      //******************************************
      //RV 20080125: Another dirty hack:
      //hideDiv(originalItem, false);
      //isDragging = false;
      //return false;
      //******************************************
      if (container==originalCont) {
        var newItem = container.appendChild(originalItem.cloneNode(true));
        originalCont.removeChild(originalItem);
        hideDiv(newItem, false);
        if (originalCont.getAttribute('orientation')=='horizontal') {
          rearrangeCards(originalCont, cardDistanceHorizontal, cardBorder);
        }
        else {
          rearrangeCards(originalCont, cardDistance, cardBorder);
        }
        isDragging = false;
        return false;
      }
      else {
      */
        hideDiv(originalItem, false);
        isDragging = false;
        return false;
      
    }
    
    if (countDivs(container) >= parseInt(container.getAttribute('maxCards'))) {
      hideDiv(originalItem, false);
      isDragging = false;
      return false;
    }
     
    var newItem = container.appendChild(originalItem.cloneNode(true));
    lastItem = newItem;
    hideDiv(newItem, false);
    if (container.getAttribute('orientation')=='horizontal') {
      rearrangeCards(container, cardDistanceHorizontal, cardBorder);
    }
    else {
      rearrangeCards(container, cardDistance, cardBorder);
    }
    
    if (originalCont.getAttribute('spawnCards')=='false') {
      if (!isRemoved) {
        originalCont.removeChild(originalItem);
        isRemoved = true;
      }
      //rearrangeCards(originalCont, cardDistance, cardBorder);
      if (originalCont.getAttribute('orientation')=='horizontal') {
        rearrangeCards(originalCont, cardDistanceHorizontal, cardBorder);
      }
      else {
        rearrangeCards(originalCont, cardDistance, cardBorder);
      }
    }
    if (onAfterDrop!='') eval(onAfterDrop);
  
    isDragging = false;
    return false;
  }
}

//------------------------------------------------------------------------------
// undoLastDrop()
//
// Undo last drop action (destroys the card, but does not restore the container
// where the card was taken from.)
//------------------------------------------------------------------------------

function undoLastDrop() {
  if (lastItem) {
    var c = lastItem.parentNode;
    c.removeChild(lastItem);
    if (c.getAttribute('orientation')=='horizontal') {
      rearrangeCards(c, cardDistanceHorizontal, cardBorder);
    }
    else {
      rearrangeCards(c, cardDistance, cardBorder);
    }
  }
}

//------------------------------------------------------------------------------
// doMouseMove
//
// Handle mouse move event
//------------------------------------------------------------------------------

function doMouseMove(event) {
  if (isDragging) {
    var mouseOffset = getMouseOffset(dragItem, event);
    dragItem.style.left = dragItem.offsetLeft + mouseOffset.x - dragOffsetX;
    dragItem.style.top = dragItem.offsetTop + mouseOffset.y - dragOffsetY;
    return false;
  }
}

//------------------------------------------------------------------------------
// dragDropInit
//
// Init drag drop 
//------------------------------------------------------------------------------

function dragDropInit() {
  dragHelper = document.createElement('DIV');
  dragHelper.style.cssText = 'position:absolute;display:none;';
  document.body.appendChild(dragHelper);

  for (i=0; i<dragContainers.length; i++) {
    rearrangeCards(dragContainers[i], cardDistance, cardBorder);
  }
}

//------------------------------------------------------------------------------
// Hook events
//------------------------------------------------------------------------------

function hookDragDropEvents() {
  document.onmousedown = doMouseDown;
  document.onmouseup = doMouseUp;
  document.onmousemove = doMouseMove;
}

setTimeout('hookDragDropEvents()', 1000);


