function newImage(arg) {
    if (document.images) {
	rslt = new Image();
	rslt.src = arg;
	return rslt;
    }
}

function changeImages() {
    if (document.images && (preloadFlag == true)) {
	for (var i=0; i<changeImages.arguments.length; i+=2) {
	    document[changeImages.arguments[i]].src = changeImages.arguments[i+1];
	}
    }
}

var preloadFlag = false;
function preloadImages() {
    if (document.images) {
	menu_03_over = newImage("/wyatts/images/menu_03-over.gif");
	menu_05_over = newImage("/wyatts/images/menu_05-over.gif");
	menu_07_over = newImage("/wyatts/images/menu_07-over.gif");
	menu_09_over = newImage("/wyatts/images/menu_09-over.gif");
	menu_11_over = newImage("/wyatts/images/menu_11-over.gif");
	menu_13_over = newImage("/wyatts/images/menu_13-over.gif");
	menu_15_over = newImage("/wyatts/images/menu_15-over.gif");
	preloadFlag = true;
    }
}

/*
 * Utility Functions
 */

function getWindowDimensions() {
    if (parseInt(navigator.appVersion) > 3) {
	if (navigator.appName == "Netscape") {
	    w = window.innerWidth;
	    h = window.innerHeight;
	}
	if (navigator.appName.indexOf("Microsoft") != -1) {
	    w = document.body.offsetWidth;
	    h = document.body.offsetHeight;
	}
    }

    return { 'width': w, 'height': h };
}

function getElementPosition(elem) {
    var curLeft = curTop = 0;
    if (elem.offsetParent) {
	curLeft = elem.offsetLeft
	curTop = elem.offsetTop
	while (elem = elem.offsetParent) {
	    curLeft += elem.offsetLeft
	    curTop += elem.offsetTop
	}
    }

    return { 'x': curLeft, 'y': curTop };
}

function getPageScrollOffset() {
    if (window.pageYOffset)
	return window.pageYOffset;
    else if (document.body.scrollTop)
	return document.body.scrollTop;
    else
	return 0;
}

/*
 * Converts from e.g. 123px to 123.
 */
function cssToPixels(str) {
    var index = str.indexOf('px');
    if (index != -1)
	return Number(str.substring(0, index));
    else
	return Number(str);
}

function pointInRect(point, rect) {
    if (point.x >= rect[0] && point.x < rect[2] && point.y > rect[1]
	&& point.y < rect[3])
	return true;
    else
	return false;
}

/*
 * Tests whether the given point is inside any of the given rectangles.
 */
function pointInRegion(point, rects) {
    for (var i = 0; i < rects.length; i++)
	if (pointInRect(point, rects[i]))
	    return true;

    return false;
}

/*
 * Mouse Functions
 */

function getMouseCoords(evt) {
    var x = null;
    var y = null;

    if (window.event) {
	x = event.clientX + document.body.scrollLeft;
	y = event.clientY + document.body.scrollTop;
    } else if (evt) {
	x = evt.pageX;
	y = evt.pageY;
    }

    return { 'x': x, 'y': y };
}

var cursor = {};
var enterCallbacks = [];
var exitCallbacks = [];

document.onmousemove = function(evt) {
    cursor = getMouseCoords(evt);

    for (var i = 0; i < enterCallbacks.length; i++)
	if (pointInRegion(cursor, enterCallbacks[i].region)) {
	    var result = enterCallbacks[i].callback();
	    if (result)
		enterCallbacks.splice(i, 1);
	}

    for (var i = 0; i < exitCallbacks.length; i++) {
	if (!pointInRegion(cursor, exitCallbacks[i].region)) {
	    var result = exitCallbacks[i].callback();
	    if (result)
		exitCallbacks.splice(i, 1);
	}
    }
};

/*
 * Specifies that the given callback be called when the mouse cursor is moved
 * to within the region specified by the given array of rectangles.  If the 
 * allback returns true, callback is removed from the list; if false, it will
 * continue to called when within the region.
 */
function registerEnterCallback(region, callback) {
    enterCallbacks.push({ 'region': region, 'callback': callback })
}

/*
 * Specifies that the given callback be called when the mouse cursor is
 * outside the region specified by the given array of rectangles.  If the
 * callback returns true, it is removed from the list of callbacks; if false,
 * it will continue to be called when outside the region.
 */
function registerExitCallback(region, callback) {
    exitCallbacks.push({ 'region': region, 'callback': callback })
}

/*
 * Menu Functions
 *
 * A menu item must have its width and height defined in its inline style
 * definition in order for the following code to function properly.
 */

var MENU_TOP = 232;  // The y-offset of the drop-downs
var MENU_TOP_PADDING = 1;  // Pixels between the menu and the activator
var ACTIVATOR_PADDING = 2;  // Number of pixels around the activator to still
			    // be considered as within the menu
var PANEL_WIDTH = 705;  // The width of the centered panel of the site

// This specifies the X-offsets of each drop-down element relative to the
// left edge of the panel as 0.
var MENU_OFFSETS = {
    'familyHistoryMenu': 213,
    'mediaMenu': 454,
    'picsMenu': 501,
    'contactMenu': 614
};

// Whether a menu is displayed.  The key is the id of the menu element.
var popupMenus = {};

function clearMenus() {
    popupMenus = {};
}

function showMenu(id, activator) {
    if (popupMenus[id])
	return;

    var menu = $(id);
    var activator = $(activator);

    var activatorDims = activator.getDimensions();
    var activatorPos = getElementPosition(activator);
    var windowDims = getWindowDimensions();
    var menuDims = { 'width': cssToPixels(menu.style.width),
		     'height': cssToPixels(menu.style.height) };

    var menuLeftPadding = (windowDims.width - PANEL_WIDTH) / 2;
    var menuLeft = Math.floor((menuLeftPadding + MENU_OFFSETS[id])
	- (menuDims.width / 2));

    if (navigator.userAgent.indexOf("KHTML") != -1)
	var scrollOffset = getPageScrollOffset();
    else
	var scrollOffset = 0;

    var activatorTop = activatorPos.y + scrollOffset;
    var menuTop = MENU_TOP + scrollOffset;

    var activatorRect = [activatorPos.x - ACTIVATOR_PADDING,
			 activatorTop - ACTIVATOR_PADDING,
			 activatorPos.x + activatorDims.width + ACTIVATOR_PADDING,
			 activatorTop + activatorDims.height + ACTIVATOR_PADDING];
    var menuRect = [menuLeft, menuTop - MENU_TOP_PADDING,
		    menuLeft + menuDims.width,
		    menuTop + menuDims.height];

    var hider = function() {
	popupMenus[id] = false;
	Effect.Fade(menu, { 'duration': 0.3 });
	return true;
    };

    registerExitCallback([activatorRect, menuRect], hider);

    menu.style.left = menuLeft + "px";
    menu.style.top = MENU_TOP + "px";
    Effect.Appear(menu, { 'duration': 0.3 });
    popupMenus[id] = true;
}
