//*****************************************************************************
// Common script code, should be included on all pages.
//*****************************************************************************

//=============================================================================
// Create the easternTimeDisplay object.
//
// This singleton object maintains the current Eastern time zone date and time
// display shown on the page header.
//=============================================================================
var easternTimeDisplay = function() {

	var easternTimeEl  = null;
	var easternTime    = null;
	var localTime      = new Date();
	var timeDifference = 0;
	
	var dayNames   = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
	var monthNames = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

	//-------------------------------------------------------------------------
	// Initializes the display.
	//-------------------------------------------------------------------------
	function init()
	{
		// Get the Eastern time display element, exit if not found.
		easternTimeEl = document.getElementById("easternTime");
		if (easternTimeEl == null)
			return;

		// Get the current Eastern time from the server. Once retrieved, start
		// updating the display.
		var xhr = new XHR();
		xhr.url = "getEasternTime.asp?random=" + Math.floor(Math.random() * 10000000);
		xhr.successCallback = function(reqObj) {

			// Create a Date object from that string and calculate the
			// difference between it and the client's current time.
			easternTime = new Date(reqObj.responseText);
			timeDifference = easternTime.valueOf() - localTime.valueOf();

			// Update the display now and set an interval timer to keep it
			// updated.
			update();
			setInterval(update, 500);
		}
		xhr.get();
	}

	//-------------------------------------------------------------------------
	// Updates the display.
	//-------------------------------------------------------------------------
	function update()
	{
		// Determine Eastern time based on the client's current time.
		var currentTime = new Date();
		easternTime = new Date(currentTime.valueOf() + timeDifference);

		// Format it and update the display.
		var meridiem = "am";
		var hrs = easternTime.getHours();
		if (hrs >= 12 && hrs <= 23)
			meridiem = "pm";
		if (hrs == 0)
			hrs = 12;
		if (hrs > 12)
			hrs -= 12;
		var mins = easternTime.getMinutes();
		if (mins < 10)
			mins = "0" + mins;
		var secs = easternTime.getSeconds();
		if (secs < 10)
			secs = "0" + secs;
		easternTimeEl.firstChild.nodeValue = dayNames[easternTime.getDay()] + ", "
			+ monthNames[easternTime.getMonth()] + " " + easternTime.getDate() + ", "
			+ easternTime.getFullYear()
			+ " " + hrs + ":" + mins + ":" + secs + " " + meridiem;
	}

	//=========================================================================
	// Initialization code.
	//=========================================================================

	// Initialize on page load.
	domUtils.onready(init);
}();

//=============================================================================
// Create the siteMenu object.
//
// This singleton object handles the site menu.
//=============================================================================
var siteMenu = function() {

	// The site menu element.
	var siteMenuEl = null;

	// The currently active sub menu.
	var activeSubMenu = null;

	//-------------------------------------------------------------------------
	// Initialize the site menu.
	//-------------------------------------------------------------------------
	function init() {

		// Get the site menu element, exit if not found.
		siteMenuEl = document.getElementById("siteMenu");
		if (siteMenuEl == null)
			return;

		// Process each item within the site menu.
		var rowEl = siteMenuEl.rows[0];
		var linkEl, subMenuEl;
		for (var i = 0; i < rowEl.cells.length; i++)
		{
			// Scan the table cell for a link and a sub menu. Note that not all
			// links will have a sub menu.
			var cellEl = rowEl.cells[i];
			linkEl = null;
			subMenuEl = null;
			for (var j = 0; j < cellEl.childNodes.length; j++)
			{
				var node = cellEl.childNodes[j];
				if (linkEl == null && node.tagName == "A")
					linkEl = node;
				if (subMenuEl == null && node.tagName == "DIV")
					subMenuEl = node;
			}

			// If a link was found, set it up.
			if (linkEl != null)
			{
				// Set the link up according to whether it has a sub menu or
				// not.
				if (subMenuEl == null)
				{
					// Set up event handling for the link.
					linkEl.onfocus = closeSubMenu;
				}
				else
				{
					// Add a style class to the link.
					domUtils.addClass(linkEl, "hasSubMenu");

					// Initialize the sub menu.
					initSubMenu(linkEl, subMenuEl);

					// Set up event handling for the link.
					linkEl.onfocus     = openSubMenu;
					linkEl.onmouseover = openSubMenu;
				}
			}
		}
	}

	//-------------------------------------------------------------------------
	// Event handler for the page.
	//-------------------------------------------------------------------------
	function pageMousedown(e)
	{
		// If there is no currently active sub menu, exit.
		if (activeSubMenu == null)
			return;

		// Find the node that triggered the event.
		var node = (domUtils.isIE ? window.event.srcElement : e.target);

		// If the triggering node is part of the site menu, exit.
		if (domUtils.contains(siteMenuEl, node))
			return;

		// Close the currently active menu.
		closeSubMenu();
	}

	//-------------------------------------------------------------------------
	// Event handler for top-level menu links.
	//-------------------------------------------------------------------------
	function menuLinkMouseout(e)
	{
		var current, related;

		try
		{
			if (window.event)
			{
				current = this;
				related = window.event.toElement;
			}
			else
			{
				current = e.currentTarget;
				related = e.relatedTarget;
			}

			// If the mouse has moved off the link but not onto the sub menu,
			// close it.
			if (!domUtils.contains(current, related) && !domUtils.contains(activeSubMenu, related))
				closeSubMenu();
		}
		catch (ex)
		{}
	}

	//-------------------------------------------------------------------------
	// Event handlers for sub menus.
	//-------------------------------------------------------------------------
	function subMenuMouseout(e)
	{
		var current, related;

		try
		{
			if (window.event)
			{
				current = this;
				related = window.event.toElement;
			}
			else
			{
				current = e.currentTarget;
				related = e.relatedTarget;
			}

			// If the mouse has moved off the sub menu, close it.
			if (current != related && !domUtils.contains(current, related))
				closeSubMenu();
		}
		catch (ex)
		{}
	}

	function subMenuClick(e)
	{
		// Find the element that triggered the event.
		var el = (domUtils.isIE ? window.event.srcElement : (e.target.tagName ? e.target : e.target.parentNode));
	
		// If it is not a link, exit.
		if (el.tagName != "A")
			return;

		// Close the sub menu.
		closeSubMenu();
	}

	//-------------------------------------------------------------------------
	// Initializes a sub menu.
	//-------------------------------------------------------------------------
	function initSubMenu(linkEl, subMenuEl) {

		// Set object references.
		linkEl.subMenuEl = subMenuEl;
		subMenuEl.linkEl = linkEl;

		// Make sure the sub menu is at least as wide as its parent link
		// (plus 10%).
		var lw = linkEl.offsetWidth;
		var mw = subMenuEl.offsetWidth;
		if (mw < lw)
			subMenuEl.style.width = Math.round(1.1 * lw) + "px";

		// Set event handlers for the sub menu and it's opener link.
		subMenuEl.onmouseout = subMenuMouseout;
		subMenuEl.onclick    = subMenuClick;
		linkEl.onmouseout    = menuLinkMouseout;
	}

	//-------------------------------------------------------------------------
	// Opens a sub menu.
	//-------------------------------------------------------------------------
	function openSubMenu(e)
	{
		// Get the sub menu associated with this link.
		var subMenuEl = this.subMenuEl;

		// If that sub menu is the currently active one, exit.
		if (activeSubMenu != null && activeSubMenu == subMenuEl)
			return false;

		// Highlight the link.		
		domUtils.addClass(this, "isActive");

		// Close any currently active sub menu.
		closeSubMenu();

		// Position the sub menu just below the link and make it visible.
		var pt = domUtils.offset(this);
		subMenuEl.style.left = pt.x + "px";
		subMenuEl.style.top  = (pt.y + this.parentNode.offsetHeight) + "px";
		subMenuEl.style.visibility = "visible";

		// Mark this sub menu as the currently active one.
		activeSubMenu = subMenuEl;

		return false;
	}

	//-------------------------------------------------------------------------
	// Closes the currently active sub menu.
	//-------------------------------------------------------------------------
	function closeSubMenu()
	{
		// Exit if there is no active sub menu.
		if (activeSubMenu == null)
			return;

		// Unhighlight the owner link.		
		domUtils.removeClass(activeSubMenu.linkEl, "isActive");

		// Make the active sub menu invisible.
		activeSubMenu.style.visibility = "";

		// Clear the active sub menu.
		activeSubMenu = null;
	}

	//=========================================================================
	// Initialization code.
	//=========================================================================

	// Set event capturing on the page.
	if (document.documentElement.addEventListener)
		document.documentElement.addEventListener("mousedown", pageMousedown, true);
	else if (document.documentElement.attachEvent)
		document.documentElement.attachEvent("onmousedown", pageMousedown);

	// Initialize on page load.
	domUtils.onready(init);
}();

//=============================================================================
// Create the scoreboard object.
//
// This singleton object handles the live scoreboard. Game data is pulled from
// the NFL.com web site at regular intervals and used to generate a live
// display of the current games.
//=============================================================================
var scoreboard = function() {

	// Preload the background image.
	var img = new Image();
	img.src = "graphics/smokedGlassBg.png";

	// Create an XMLHttpRequest object for loading the scoreboard data.
	var xhr = new XHR();
	xhr.url = "getRequest.asp";
	xhr.queryString = "url=" + escape("http://www.nfl.com/liveupdate/scorestrip/ss.xml?random=" + Math.floor(Math.random() * 10000000));
	xhr.successCallback = getScoresSuccess;

	// Define an interval timer for updating the scoreboard.
	var updateInterval = null;

	// Used to throttle update requests. If no active games are found during a
	// scoreboard update, this will hold the time that update was made. When
	// active games are found, this set to null.
	var lastInactiveUpdate = null;

	// Used to hold scoreboard game data.
	var gamesList = new Array();

	//-------------------------------------------------------------------------
	// Initializes the scoreboard.
	//-------------------------------------------------------------------------
	function init()
	{
		// Get the scoreboard container element, exit if not found.
		var containerEl = document.getElementById("scoreboardContainer");
		if (containerEl == null)
			return;
		var tabEl = document.getElementById("scoreboardTab");
		if (tabEl == null)
			return;

		// If we have saved scoreboard data, us it to build the display. This
		// will prevent it from being empty while we wait for the first update
		// request to complete.
		var lastData = domUtils.getCookie("scoreboardData");
		try
		{
			if (lastData != "")
			{
				var parser = new DOMParser();
				var xmlDoc = parser.parseFromString(lastData, "text/xml");
				processScores(xmlDoc);
			}
		}
		catch (ex)
		{}

		// Make the scoreboard tab visible.
		tabEl.style.visibility = "visible";

		// Check the cookie to see if the user had the scoreboard visible on
		// the previous page.
		if (domUtils.getCookie("scoreboardOn") == "1")
		{
			// Yes, make it visible now.
			toggleDisplay();
		}
		else if (lastData == "")
		{
			// No, and we have no saved data so go ahead and do an update
			// request.
			getScores();
		}
	}

	//-------------------------------------------------------------------------
	// Shows or hides the scoreboard.
	//-------------------------------------------------------------------------
	function toggleDisplay()
	{
		// Get the scoreboard and arrow elements.
		var scoreboardEl = document.getElementById("scoreboard");
		var arrowEl      = document.getElementById("scoreboardArrow");

		if (scoreboardEl.style.display == "none")
		{
			// Begin an update request.
			lastInactiveUpdate = null;
			getScores();

			// Show the scoreboard.
			scoreboardEl.style.display = "";
			arrowEl.firstChild.nodeValue = "\u25bc";

			// Set the scoreboard display cookie.
			domUtils.setCookie("scoreboardOn", "1");

			// Set the interval timer for 30 second updates.
			if (updateInterval == null)
				updateInterval = setInterval(getScores, 30000);
		}
		else
		{
			// Hide the scoreboard.
			scoreboardEl.style.display = "none";
			arrowEl.firstChild.nodeValue = "\u25b2";

			// Stop the interval timer.
			if (updateInterval != null)
			{
				clearInterval(updateInterval);
				updateInterval = null;
			}

			// Set the scoreboard display cookie.
			domUtils.setCookie("scoreboardOn", "0");
		}
	}

	//-------------------------------------------------------------------------
	// Called by the interval timer to update the scoreboard.
	//-------------------------------------------------------------------------
	function getScores()
	{
		// If no active games were found on the last update, we will wait at
		// least five minutes before making a new request.
		if (lastInactiveUpdate != null)
		{
			var currentTime = new Date();
			if (currentTime.valueOf() - lastInactiveUpdate.valueOf() < 300000)
				return;
		}

		// Initiate the request.
		try
		{
			xhr.get();
		}
		catch (ex)
		{}
	}

	//-------------------------------------------------------------------------
	// Callback for the get scores request.
	//-------------------------------------------------------------------------
	function getScoresSuccess(reqObj)
	{
		try
		{
			// Save the current time.
			lastInactiveUpdate = new Date();

			// Process the data.
			processScores(reqObj.responseXML);
		}
		catch (ex)
		{}
	}

	//-------------------------------------------------------------------------
	// Processes the scoreboard data.
	//-------------------------------------------------------------------------
	function processScores(xmlDoc)
	{
		// Save the scoreboard data in a cookie.
		try
		{
			var serializer = new XMLSerializer();
			var xml = serializer.serializeToString(xmlDoc);
			domUtils.setCookie("scoreboardData", xml);
		}
		catch (ex)
		{}

		// Build the array of game objects.
		gamesList = new Array();
		var gameEls = xmlDoc.getElementsByTagName("g");
		for (var i = 0; i < gameEls.length; i++)
		{
			var gameEl = gameEls[i];
			var list = new Array();
			list.push(gameEl.getAttribute("d"));    // Game day.
			list.push(gameEl.getAttribute("t"));    // Kickoff time.
			list.push(gameEl.getAttribute("q"));    // Status = "P", "H", "F", "FO", "1" - "8".
			list.push(gameEl.getAttribute("k"));    // Time left in quarter/overtime.
			list.push(gameEl.getAttribute("v"));    // Visitor team ID.
			list.push(gameEl.getAttribute("vs"));   // Visitor score.
			list.push(gameEl.getAttribute("h"));    // Home team ID.
			list.push(gameEl.getAttribute("hs"));   // Home score.
			list.push(gameEl.getAttribute("p"));    // ID of team with possession.
			list.push(gameEl.getAttribute("rz"));   // Redzone flag = "0" or "1".
			list.push(gameEl.getAttribute("gsis")); // Game center ID.

			// Fix any missing values.
			for (var j = 0; j < list.length; j++)
				if (list[j] == null)
					list[j] = "";

			// Add it to the array.
			gamesList.push(gameObj(list));
		}

		// Build the display.
		buildDisplay();
	}

	//-------------------------------------------------------------------------
	// Creates the scoreboard display.
	//-------------------------------------------------------------------------
	function buildDisplay()
	{
		// Build the scoreboard HTML.
		var html = "<table cellpadding=\"0\" cellspacing=\"0\"><tr valign=\"top\">";
		for (var i = 0; i < gamesList.length; i++)
		{
			// Add the HTML for the individual game.
			html += "<td" + (i > 0 ? " class=\"leftEdge\"" : "") + ">" + gamesList[i].toHtml() + "<\/td>";

			// If a game is active, clear the last update time.
			if (gamesList[i].isActive)
				lastInactiveUpdate = null;
		}

		// Handle the case where no scores are posted.
		if (gamesList.length == 0)
			html += "<td>&nbsp;<br />No scores available.<br />&nbsp;</td>";

		html += "<\/tr><\/table>";

		// Clear any current content.
		var scoreboardEl = document.getElementById("scoreboard");
		while (scoreboardEl.firstChild != null)
			scoreboardEl.removeChild(scoreboardEl.firstChild);

		// Insert the new HTML.
		var divEl = document.createElement("DIV");
		divEl.innerHTML = html;
		scoreboardEl.appendChild(divEl);
	}

	//-------------------------------------------------------------------------
	// Returns an object representing a single game.
	//-------------------------------------------------------------------------
	function gameObj(list)
	{
		// Get the game status and teams.
		var status   = list[2];
		var vid      = list[4];
		var hid      = list[6];

		// For Jacksonville, use "JAX" instead of "JAC".
		vid = vid.replace("JAC", "JAX");
		hid = hid.replace("JAC", "JAX");

		// Handle unknown IDs (as in the postseason).
		if (vid == "TBD")
			vid = "[<em>TBD<\em>]";
		if (hid == "TBD")
			hid = "[<em>TBD<\em>]";

		// Used for custom properties.
		var isActive = false;
		var isOver   = false;
		var isOT     = false;

		// Determine the game status.
		switch(status.toUpperCase())
		{
			case "P":
				status = "Pregame"
				break;
			case "H":
				status = "Halftime";
				isActive = true;
				break;
			case "F":
				status = "Final"
				isOver = true;
				break;
			case "FO":
				status = "Final"
				isOver = true;
				isOT   = true;
				break;
			default:
				isActive = true;
				break;
		}

		// Create the object, setting all properties and methods.
		return {
			day	     : list[0],
			time     : list[1],
			status   : status,
			timeLeft : list[3],
			vid      : vid,
			vscore   : list[5],
			hid      : hid,
			hscore   : list[7],
			pid      : list[8],
			redzone  : list[9],
			gameId   : list[10],
			event    : list[11],
			week     : list[12],
			season   : list[13],
			isActive : isActive,
			isOver   : isOver,
			isOT     : isOT,
			toHtml   : gameHtml // See function below.
		}
	}

	//-------------------------------------------------------------------------
	// Creates HTML from a game data object.
	//-------------------------------------------------------------------------
	function gameHtml()
	{
		var vid    = this.vid;
		var hid    = this.hid;
		var vpos   = "";
		var hpos   = "";
		var vscore = "&nbsp;";
		var hscore = "&nbsp;";
		var status = "";
		var vclass = "";
		var hclass = "";

		// Get the scores, if available.
		if (this.isActive || this.isOver)
		{
			vscore = parseInt(this.vscore);
			hscore = parseInt(this.hscore);
		}

		// Handle a completed game.
		if (this.isOver)
		{
			// Highlight the winner.
			if (vscore > hscore)
			{
				vid    = highlightText(vid);
				vscore = highlightText(vscore);
			}
			if (hscore > vscore)
			{
				hid    = highlightText(hid);
				hscore = highlightText(hscore);
			}
			status = "Final" + (this.isOT ? "-OT" : "");
		}

		// Handle an active game.
		if (this.isActive)
		{
			// Game is underway, show current situation.
			if (this.status == "Halftime")
			{
				// Game is at halftime.
				status = "Half";
			}
			else
			{

				// Mark the team with possession and add a class attribute if
				// they are in the red zone.
				if (this.vid == this.pid)
				{
					vid += highlightText("&#9642;");
					if (this.redzone == "1")
						vclass = " class=\"redzone\"";
				}
				if (this.hid == this.pid)
				{
					hid += highlightText("&#9642;");
					if (this.redzone == "1")
						hclass = " class=\"redzone\"";
				}

				// Use the quarter and time remaining as the status.
				var quarter = "";
				switch (this.status)
				{
					case "1":
						quarter = "1st";
						break;
					case "2":
						quarter = "2nd";
						break;
					case "3":
						quarter = "3rd";
						break;
					case "4":
						quarter = "4th";
						break;
					default:
						quarter = "OT";
						break;
				}
				status = this.timeLeft + " " + quarter;
			}
		}

		// Handle a game that has not started.
		if (!this.isActive && !this.isOver)
		{
			// Show game day and start time.
			status = this.day + " " + this.time;
		}

		// Build and return the HTML.
		var html = "<table cellpadding=\"0\" cellspacing=\"0\">";
		html += "<tr" + vclass + " valign=\"top\"><td>" + vid + "<\/td><td align=\"right\">" + vscore + "<\/td><\/tr>";
		html += "<tr" + hclass + " valign=\"top\"><td>" + hid + "<\/td><td align=\"right\">" + hscore + "<\/td><\/tr>";
		html += "<tr valign=\"top\"><td align=\"center\" colspan=\"2\">" + status + "<\/td><\/tr>";
		html += "<\/table>";

		return html;
	}

	//-------------------------------------------------------------------------
	// Wraps the given text in a span with the highlight class.
	//-------------------------------------------------------------------------
	function highlightText(s)
	{
		// Wrap the given string in a SPAN to highlight it.
		return "<span class=\"highlight\">" + s + "<\/span>";
	}

	//=========================================================================
	// Initialization code.
	//=========================================================================

	// Initialize on page load.
	domUtils.onready(init);

	//=========================================================================
	// Public properties and methods.
	//=========================================================================
	return {

		//---------------------------------------------------------------------
		// Toggles the scoreboard display.
		//---------------------------------------------------------------------
		toggle : function() {

			toggleDisplay();
		}
	}
}();

//=============================================================================
// Code to fix browser-specific issues.
//=============================================================================

if (domUtils.isIE && document.documentMode == null)
{
	domUtils.onready(function() {

		//---------------------------------------------------------------------
		// For IE versions prior to IE 8, fix the problem with tables that have
		// an explicit style width of "100%" being cut off (but only for tables
		// with class "main").
		//---------------------------------------------------------------------
		var elList = document.getElementsByTagName("TABLE");
		for (var i = 0; i < elList.length; i++)
		{
			if (domUtils.hasClass(elList[i], "main") && elList[i].style.width == "100%")
				elList[i].style.width = "99%";
		}
	});
}

//=============================================================================
// Code to adjust the width of specified DIVs to fit the current display.
//=============================================================================
domUtils.onready(function() {

	// Find the width of the widest element in the main wrapper.
	var el = document.getElementById("mainWrapper");
	el = el.rows[0].cells[0];
	var maxWidth = 0;
	for (var i = 0; i < el.childNodes.length; i++)
	{
		var width = el.childNodes[i].offsetWidth;
		if (width != null && width > maxWidth)
			maxWidth = width;
	}

	// Search for error, success and warning messages.
	var elList = document.getElementsByTagName("DIV");
	for (i = 0; i < elList.length; i++)
		if (domUtils.hasClass(elList[i], "adjustWidth"))
		{
			// Make the message the same width as the widest element.
			elList[i].style.width = maxWidth + "px";
			var dw = elList[i].offsetWidth - maxWidth;
			elList[i].style.width = (maxWidth - dw) + "px";
		}
	}
);

