// IE has a bug (surprise) that renders select boxes above all other elements, regardless of z-index.
// This poses a problem for DHTML menus that must obscure select boxes.
//
// This JavaScript solves the problem by detecting overlap between a div tag (used as a DHTML menu) and each select box 
// on the page, and clipping each select box accordingly.
//
//   Call "ClipAll()" with the menu ID to clip all overlapping select boxes on the page.
//   Call "UnClipAll()" to unclip all select boxes
//
// IMPORTANT NOTE: clipping only works if the elements are absolutely positioned with css.
//

// return a rectangle-like object
function Rect(top,right,bottom,left)
{
	// weird syntax, but it works; returns an object with properties top, right, bottom, left
	return {top:top,right:right,bottom:bottom,left:left};
}

// return a fresh copy of a rect
function CopyRect(rect)
{
	// copy the passed rect
	return {top:rect.top,right:rect.right,bottom:rect.bottom,left:rect.left};
}

// get the rectangle of an element
function GetRect(obj)
{
	var objPosition = GetPosition(obj);
	return Rect(objPosition.y,objPosition.x+obj.offsetWidth,objPosition.y+obj.offsetHeight,objPosition.x);
}

// get the width of a rect object
function GetRectWidth(rect) {
	return rect.right - rect.left;
}

// get the height of a rect object
function GetRectHeight(rect) {
	return rect.bottom - rect.top;
}

// return true if the rect's area is 0
function IsNullRect(rect)
{
	// check for null width or height
	if(GetRectWidth(rect) <= 0 || GetRectHeight(rect) <= 0)
		return true;
	else
		return false;
}

// return the overlapping rectangle of two rects
function GetOverlapRect(rect1,rect2)
{
	// create overlap rectangle as rect1
	var overlapRect = CopyRect(rect1);
	
	// create the overlap rectangle by shrinking rect1 to fit inside rect2
	if(rect2.top > rect1.top)
		overlapRect.top = rect2.top;
	if(rect2.right < rect1.right)
		overlapRect.right = rect2.right;
	if(rect2.left > rect1.left)
		overlapRect.left = rect2.left;
	if(rect2.bottom < rect1.bottom)
		overlapRect.bottom = rect2.bottom;
		
	return overlapRect;
}

// intelligently clip all select boxes to the menu - this is the big function that starts 'em all.
function ClipAll(menuID)
{
	// only perform clipping for IE
	if(document.all)
	{
		// get the menu rectangle
		var menuObj = document.getElementById(menuID);
		var menuRect = GetRect(menuObj);
		
		// get the collection of select tag objects
		var selectTags = document.getElementsByTagName("SELECT");
		
		// iterate through all select elements
		for(i=0; i<selectTags.length; i++)
		{
			// get the select element
			var selectObj = selectTags[i];
			
			// check if the select box is absolutely positioned
			if(selectObj.currentStyle.position != 'absolute')
				continue;
			
			// get the selectbox's rect and its overlapping rect with the menu
			var selectRect = GetRect(selectObj);
			var overlapRect = GetOverlapRect(menuRect,selectRect);
		
			// yay it's time to clip!
			ClipFromOverlap(selectObj,selectRect,overlapRect);
		}
	}
}

// intelligently clips the element based on how it is being overlapped
function ClipFromOverlap(obj,objRect,overlapRect)
{
	// check for no overlap
	if(IsNullRect(overlapRect))
		return;
		
	// top (either it overlaps the entire width, or partially overlaps the top half of the obj)
	if(GetRectWidth(overlapRect) == GetRectWidth(objRect) || overlapRect.bottom < objRect.top + GetRectHeight(objRect)/2)
		obj.style.clip = 'rect(' + (overlapRect.bottom - objRect.top) + 'px auto auto auto)';
	// left
	else if(overlapRect.right < objRect.right)
		obj.style.clip = 'rect(auto auto auto ' + (overlapRect.right - objRect.left) + 'px)';
	// right
	else if(overlapRect.left > objRect.left)
		obj.style.clip = 'rect(auto ' + (overlapRect.left - objRect.left) + 'px auto auto)';
}

// unclip all select boxes
function UnClipAll()
{
	// only perform clipping for IE
	if(document.all)
	{
		// get the collection of select tag objects
		var selectTags = document.getElementsByTagName("SELECT");
		
		// iterate through all select objects
		for (i=0; i<selectTags.length; ++i)
		{
			// get the select object
			var selectObj = selectTags[i];
			
			// unclip the select box
			UnClip(selectObj);
		}
	}
}

// unclip an object
function UnClip(obj)
{
	obj.style.clip = 'rect(auto auto auto auto)';
	
	// BUG - object doesn't refresh after unclip
	// so flip the display style
	var oldDisplay = obj.style.display;
	obj.style.display = 'block';
	obj.style.display = oldDisplay;
}

// get the absolute coordinates of an element
function GetPosition(obj) {
    var offsetTrail = obj;
    var offsetLeft = 0;
    var offsetTop = 0;
    while(offsetTrail) {
        offsetLeft += offsetTrail.offsetLeft;
        offsetTop += offsetTrail.offsetTop;
        offsetTrail = offsetTrail.offsetParent;
    }
    // accomodate margins on Mac IE
    if (navigator.userAgent.indexOf("Mac") != -1 && 
        typeof document.body.leftMargin != "undefined") {
        offsetLeft += document.body.leftMargin;
        offsetTop += document.body.topMargin;
    }
return {x:offsetLeft, y:offsetTop};
}

// debugging helper functions
function Output(str)
{
	document.getElementById('Output').innerHTML += str + " ";
}

function OutputRect(rect)
{
	document.getElementById('Output').innerHTML += "top: " + rect.top + ", right: " + rect.right + ", bottom: " + rect.bottom + ", left: " + rect.left + "<br />";
}

