﻿// A library for reordering images, based on the wz_dragdrop.js library
// Mark Heimonen, 5/12/2009
//*********************************************************************
//wz_dragdrop.js and mootools-1.2.2-core-nc.js need to be included on the calling page
//See Common/Controls/CSGallery/GalleryManageAlbumOrder.ascx for a working example

//The following variables should be set on the calling page

//var AlbumContainer = document.getElementById('<% = AlbumContainer.ClientID %>');		
//var NumberOfColumns = parseInt(document.getElementById('<% = hiddenNumberOfColumns.ClientID %>').value);		
//var ThumbnailWidth = parseInt(document.getElementById('<% = hiddenThumbnailWidth.ClientID %>').value);		
//var ThumbnailHeight = parseInt(document.getElementById('<% = hiddenThumbnailHeight.ClientID %>').value);	
//var hiddenImageOrder = document.getElementById('<% = hiddenThumbnailOrder.ClientID %>');
//var DragDropEnabled = new Boolean(document.getElementById('<% = hiddenDragDropEnabled.ClientID %>').value);	
		
//var topMargin = 225;
//var verticalSpacing = 30;
//var distanceThreshold = 75;
//var tableScale = 0.85;
//var elements = document.getElementsByTagName("a");
var horizontalThreshold = 4;

//Create an array of all draggable images on the form
var a = [];
var aElts = [];
var posOldx, posNewx, posOldy, posNewy, currentIndex; 
a.push(CURSOR_MOVE);
for(var i=0,j=elements.length; i<j; i++)
{
	if(elements[i].className == "draggable")
	{		
		a.push(elements[i].id);
	}
}

if (DragDropEnabled == true)
{
	//Set images as draggable
	SET_DHTML.apply(this,a);
	aElts = dd.elements;
	if (aElts.length < NumberOfColumns) { NumberOfColumns = aElts.length; }
}

var maxThumbnailHeight = 0;
		

//This function, readjustLayout(), is called initially to layout the draggable items with the appropriate number of columns & rows
//readjustLayout() is also called whenever the window is resized, since the layout is based on absolute position, 
//and the layout is determined with respect to the total viewable window size.
function readjustLayout()
{
	if (DragDropEnabled == true)
	{	
		var imageNodeLevel = -1;
		//determine Max Thumbnail Height
		for(var i = 0; i < aElts.length; i++)
		{
			var element = document.getElementById(aElts[i].id);
			if (imageNodeLevel = -1) //determine Node Level --firefox and IE behave differently
			{ 
				if (element.childNodes[0].nodeName == "IMG") { imageNodeLevel = 0; } else {imageNodeLevel = 1; }
			}
			if ($(element.childNodes[imageNodeLevel].id).getSize().y > maxThumbnailHeight)
			{
				maxThumbnailHeight = $(element.childNodes[imageNodeLevel].id).getSize().y;
			}
		}	
		
		//Determine current total browser window width
		var newInnerWidth = window.innerWidth;
		if (typeof(newInnerWidth) == "undefined")
		{
			newInnerWidth = document.documentElement.offsetWidth;
		}
		var absoluteMargin = $(marker.id).getCoordinates().left; 
		
		//Set Table width to 85% of total width of the browser
		AlbumContainer.style.width = ((newInnerWidth - absoluteMargin) * tableScale) + "px";
		if (aElts.length > 0)
		{
			AlbumContainer.style.height = ((maxThumbnailHeight + (verticalSpacing)) * Math.ceil(aElts.length/NumberOfColumns) + verticalSpacing) +  "px";
		}
		else
		{
			AlbumContainer.style.visibility = "hidden";
		}
		
		//Calculate Difference between left and right margins	
		var rightMargin = $(AlbumContainer.id).getCoordinates().right;
		if (rightMargin < 0) { rightMargin = 0; }
		if (absoluteMargin < 0) { absoluteMargin = 0; }
			
		//Determine spacing between each image
		var horizontalSpacing = (((newInnerWidth - absoluteMargin) * tableScale) - (NumberOfColumns * ThumbnailWidth)) / (NumberOfColumns + 1);
		var shrinkImage = false;
		var leftMargin = 0;
		if (horizontalSpacing < horizontalThreshold) { shrinkImage = true; horizontalSpacing = 0;} //leftMargin =  ((newInnerWidth - absoluteMargin) * (1 - tableScale) / 2); horizontalSpacing = 0; }
			
		for(var i = 0; i < aElts.length; i++)
		{
			var element = document.getElementById(aElts[i].id);
			var currentColumn = element.getAttribute("currentColumn");
			var currentRow = element.getAttribute("currentRow");
			element.childNodes[imageNodeLevel].style.marginBottom= maxThumbnailHeight - element.childNodes[imageNodeLevel].height;
		
			aElts[i].moveTo(leftMargin + absoluteMargin + ((currentColumn - 1) *  ThumbnailWidth) + (currentColumn * horizontalSpacing) + 2,topMargin + ((maxThumbnailHeight + verticalSpacing) * (currentRow - 1)) );
			if (shrinkImage)
			{
			
				element.childNodes[imageNodeLevel].width =  ThumbnailWidth  - (horizontalThreshold - horizontalSpacing);		
				aElts[i].resizeTo(ThumbnailWidth  - (horizontalThreshold - horizontalSpacing) + 6,maxThumbnailHeight + 6);
			}
			else
			{
				element.childNodes[imageNodeLevel].width =  ThumbnailWidth;
				aElts[i].resizeTo(ThumbnailWidth + 6,maxThumbnailHeight + 6);
			}	
		}
	}
}

//IE is unable to determine the offset of the Container div until the DOM has finished loading
//This functionality is dependent on mootools
window.addEvent('domready', function() {
	topMargin = topMargin + $(AlbumContainer.id).getCoordinates().top;
	//Set Initial Absolute Image Layout
	readjustLayout();
});

if (DragDropEnabled == true)
{
	//Readjust layout when window is resized
	window.onresize = readjustLayout;
}
	
//Function called to open a new window when a draggable item is clicked, rather than dragged.	
function Navigate(link) {	
	window.open(link, '_blank');    		   
}	

//Function called at the beginning of a drag motion
function my_PickFunc()
{
	if (DragDropEnabled == true)
	{
		// Store position of the item about to be dragged
		// so we can interchange positions of items when the drag operation ends
		posOldx = dd.obj.x;
		posOldy = dd.obj.y;
		for(i = 0; i < aElts.length; i++)
		{
			if (aElts[i] == dd.obj)
			{
				currentIndex = i;
			}
		}
	}
}

var previousDropElement;
var locked = false;
//Function called while dragging
function my_DragFunc()
{
	if (!locked)
	{
		locked =true;		
		if (DragDropEnabled == true)
		{
			var posCurx;
			var posCury;
		
			posCurx = dd.obj.x;
			posCury = dd.obj.y;
			
			var minDistance, otherIndex;
			minDistance = 9999;
			for(i = 0; i < aElts.length; i++)
			{
				var distanceX = Math.abs(posCurx - aElts[i].x);
				var distanceY = Math.abs(posCury - aElts[i].y);
				var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
				if (distance < minDistance && i != currentIndex)
				{
					minDistance = distance;
					otherIndex = i;
				}
			}		
			var dropElement;
			//If image is dropped within minimum threshold of distance
			dropElement = document.getElementById(aElts[otherIndex].id);			
			if (minDistance < distanceThreshold)
			{	
				dropElement.style.border = "3px solid red";		
			}	
			else
			{
				dropElement.style.border = "3px solid #333333";		
			}		
			if (previousDropElement != dropElement && previousDropElement != null)
			{
				dropElement.style.border = "3px solid #333333";				
			}
			previousDropElement = dropElement;		
		}
		locked = false;
	}
}



//Function called at the end of drag movement.
function my_DropFunc()
{
	if (DragDropEnabled == true)
	{
		for(i = 0; i < aElts.length; i++)
		{
			var currentElement = document.getElementById(aElts[i].id);
			currentElement.style.border = "3px solid #333333";				
		}
		locked = false;	
	
		posNewx = dd.obj.x;
		posNewy = dd.obj.y;
		
		if (Math.abs(posOldx - posNewx) < 1 && Math.abs(posOldy - posNewy) < 1)
		{
				//User has clicked, rather than dragged image.  Navigate to selected image
				if (document.getElementById(dd.obj.id).getAttribute("navigateUrl"))
				{ 		
					Navigate(document.getElementById(dd.obj.id).getAttribute("navigateUrl"));
					return false;
				}
		}
		
		var minDistance, otherIndex;
		minDistance = 9999;
		for(i = 0; i < aElts.length; i++)
		{
			var distanceX = Math.abs(posNewx - aElts[i].x);
			var distanceY = Math.abs(posNewy - aElts[i].y);
			var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
			if (distance < minDistance && i != currentIndex)
			{
				minDistance = distance;
				otherIndex = i;
			}
		}		
		//If image is dropped within minimum threshold of distance
		if (minDistance < distanceThreshold)
		{	
			aElts[currentIndex].moveTo(posOldx,posOldy);
						
			var imageOrder = hiddenImageOrder.value.split(',');
		
			//Determine first Image
			var rowOne, columnOne, rowTwo, columnTwo;
			rowOne = parseInt(document.getElementById(aElts[currentIndex].id).getAttribute("currentRow"));
			rowTwo = parseInt(document.getElementById(aElts[otherIndex].id).getAttribute("currentRow"));
			columnOne = parseInt(document.getElementById(aElts[currentIndex].id).getAttribute("currentColumn"));
			columnTwo = parseInt(document.getElementById(aElts[otherIndex].id).getAttribute("currentColumn"));
			
			var minImageId, maxImageId;
			var minIndex, maxIndex;
			var currentImage, nextImage;
			if (rowOne < rowTwo  || (rowOne == rowTwo && columnOne < columnTwo))
			{
				//We are dragging an image further down.  Move all enveloped images one slot to the left
				//& then put the first image into the last slot
				minImageId = document.getElementById(aElts[currentIndex].id).getAttribute("ImageID");				
				maxImageId = document.getElementById(aElts[otherIndex].id).getAttribute("ImageID");
				for (i = 0; i < imageOrder.length; i++)
				{					
					if (imageOrder[i] == minImageId) { minIndex = i; }
					if (imageOrder[i] == maxImageId) { maxIndex = i; }
				}
				
							
				//Store location of last image
				var lastImageX, lastImageY, lastImageRow, lastImageColumn;
				for (j = 0; j<aElts.length; j++)
				{
					if (document.getElementById(aElts[j].id).getAttribute("ImageID") == imageOrder[maxIndex])
					{ 
						lastImageX = aElts[j].x;
						lastImageY = aElts[j].y;
						lastImageRow = document.getElementById(aElts[j].id).getAttribute("currentRow");
						lastImageColumn = document.getElementById(aElts[j].id).getAttribute("currentColumn");
					}				
				}
				//Store Next Image Variables
				for(i = maxIndex - 1; i >= minIndex; i--)
				{
					//Find Current and next Element
					for (j = 0; j<aElts.length; j++)
					{
						if (document.getElementById(aElts[j].id).getAttribute("ImageID") == imageOrder[i])
						{ 
							currentImage = aElts[j];
						}
						if (document.getElementById(aElts[j].id).getAttribute("ImageID") == imageOrder[i + 1])
						{ 
							nextImage = aElts[j];
						}
					}
					//nextImage.moveTo(currentImage.x,currentImage.y);
					moveTablePosition(nextImage.id,false);					
				}
				//Move first image to last location
				if (typeof(currentImage) != "undefined")
				{
					//currentImage.moveTo(lastImageX,lastImageY);
					document.getElementById(currentImage.id).setAttribute("currentRow",lastImageRow); 
					document.getElementById(currentImage.id).setAttribute("currentColumn",lastImageColumn); 
				}
				
				//correct the image order
				var firstIndex = imageOrder[minIndex];
				for(i = minIndex; i < maxIndex; i++)
				{
					imageOrder[i] = imageOrder[i + 1];
				}
				imageOrder[maxIndex] = firstIndex;
			}
			else
			{
				//We are dragging an image higher up.  Move all contained images one slot to the right
				//& then put the last image into the first slot
		 		minImageId = document.getElementById(aElts[otherIndex].id).getAttribute("ImageID");
				maxImageId = document.getElementById(aElts[currentIndex].id).getAttribute("ImageID");
			
				for (i = 0; i < imageOrder.length; i++)
				{					
					if (imageOrder[i] == minImageId) { minIndex = i; }
					if (imageOrder[i] == maxImageId) { maxIndex = i; }
				}
				
				var firstImageX, firstImageY, firstImageRow, firstImageColumn;
				//Store location of first image
				for (j = 0; j<aElts.length; j++)
				{
					if (document.getElementById(aElts[j].id).getAttribute("ImageID") == imageOrder[minIndex])
					{ 
						firstImageX = aElts[j].x;
						firstImageY = aElts[j].y;
						firstImageRow = document.getElementById(aElts[j].id).getAttribute("currentRow");
						firstImageColumn = document.getElementById(aElts[j].id).getAttribute("currentColumn");
					}				
				}
				//Store Next Image Variables
				for(i = minIndex; i < maxIndex; i++)
				{
					//Find Current and next Element
					for (j = 0; j<aElts.length; j++)
					{
						if (document.getElementById(aElts[j].id).getAttribute("ImageID") == imageOrder[i])
						{ 
							currentImage = aElts[j];
						}
						if (document.getElementById(aElts[j].id).getAttribute("ImageID") == imageOrder[i + 1])
						{ 
							nextImage = aElts[j];
						}
					}
					//currentImage.moveTo(nextImage.x,nextImage.y);
					moveTablePosition(currentImage.id,true);					
				}
				//Move last image to first location
				if (typeof(nextImage) != "undefined")
				{
					//nextImage.moveTo(firstImageX,firstImageY);
					document.getElementById(nextImage.id).setAttribute("currentRow",firstImageRow); 
					document.getElementById(nextImage.id).setAttribute("currentColumn",firstImageColumn); 
				}
				
				//correct the image order
				var lastIndex = imageOrder[maxIndex];
				for(i = maxIndex - 1; i >= minIndex; i--)
				{
					imageOrder[i + 1] = imageOrder[i];
				}
				imageOrder[minIndex] = lastIndex;
			}
			hiddenImageOrder.value = imageOrder.toString(); 
		}
		else
		{
			//Cancel Move
			aElts[currentIndex].moveTo(posOldx,posOldy);
		}
		//Assume user attempted to drag, rather than click	 on the link.  Cancel Navigation
		posOldx = -99;
		posOldy = -99;
		currentIndex = -99;
		readjustLayout();
		return false;	
	}	
}

//Each draggable element has an internal currentRow and currentColumn custom attribute
//If increment is true, we are incrementing the element by one position.  If increment
//is false, we are decrementing the element by one position
function moveTablePosition(elementId,increment)
{
	var element = document.getElementById(elementId);
	
	var imageRow = parseInt(element.getAttribute("currentRow"));
	var imageColumn = parseInt(element.getAttribute("currentColumn"));
	if (increment)
	{
		if (imageColumn + 1 <= NumberOfColumns)
		{
			element.setAttribute("currentColumn",imageColumn+1);
		}
		else					
		{
			element.setAttribute("currentColumn",1);		
			element.setAttribute("currentRow",imageRow + 1);	
	}
	}
	else //decrement
	{
		if (imageColumn - 1 > 0)
		{
			element.setAttribute("currentColumn",imageColumn-1);
		}
		else					
		{
			element.setAttribute("currentColumn",NumberOfColumns);		
			element.setAttribute("currentRow",imageRow - 1);		
		}
	}
}
