
// Lifted from: http://www.brockman.se/writing/method-references.html.utf8
Function.prototype.bind = function (object) {
    var method = this;
    return function () {
        method.apply(object, arguments);
    };
};

var HomePage = {
	// Lifted from: http://www.quirksmode.org/js/events_properties.html
	getEventTarget: function(e)
	{
		var target;
		
		if (!e) 
		{
		    /*jsl:ignore*/
			var e = window.event;
			/*jsl:end*/
		}
		
		if (e.target) 
		{
			target = e.target;
		}
		else if (e.srcElement) 
		{
			target = e.srcElement;
		}
		
		// defeat Safari bug
		if (target.nodeType == 3) 
		{
			target = target.parentNode;
		}
		
		return target;
	},

    videoLaunch: function(siteId, url)
    {
        switch (siteId) {
            case "aolpf": case "netscape": case "aol": case "compuserve": case "yhoo": case "myyahoo": case "intuit":
                url = url.replace(/player.asp/g, "playerFull.asp");

                if(url.search(/siteid=/g) == -1) 
                {
                    url = url + "&siteid=" + siteId;
                }
                
                document.location = url;
                break;
            default:
                pop = window.open(url,'vviewer','width=988,height=550,scrollbars=no,resize=no,location=no,status=no');
                pop.focus();
                break;
        }           
    },

	 getRequest: function()
	 {
		 var xmlHttp = false;
        
		 try 
		 {
		    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
		 } 
		 catch (msxml2Exception) 
		 {
		    try 
			{
			   xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
			} 
			catch (microsoftException) 
			{
			   xmlHttp = false;
			}
		 }
        	
		 if (!xmlHttp && typeof XMLHttpRequest != 'undefined')
		 {
		    xmlHttp = new XMLHttpRequest();
		 }
        	
		 return xmlHttp; 
	 },
	 
	 
	 reportError : function(msg)
	 {
	    // TODO - Doug - 7/5/2006 - it would be nice if this could alert in dev/acceptance, but be silent in production...
	    // alert(msg);
	 },
	 
	 // Lifted from: http://www.quirksmode.org/js/findpos.html
	 findPosX: function(obj)
	 {
		var curleft = 0;
		if (obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curleft += obj.offsetLeft;
				obj = obj.offsetParent;
			}
		}
		else if (obj.x)
		{
			curleft += obj.x;
		}
		return curleft;
	},

	findPosY: function(obj)
	{
		var curtop = 0;
		if (obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curtop += obj.offsetTop;
				obj = obj.offsetParent;
			}
		}
		else if (obj.y)
		{
			curtop += obj.y;
		}
		return curtop;
	},
	
	addCssClass: function(element, className)
	{
		var present = false;
		if (element != null && element.className != null && element.className != "")
		{
			var currentClasses = element.className.split(" ");
			for (i = 0; i < currentClasses.length; i++)
			{
				if (currentClasses[i] == className)
				{
					present = true;
				}
			}
			if (!present)
			{
				element.className += " " + className;
			}
		}
		else if (element != null)
		{
			element.className = className;
		}
	},
	
	removeCssClass: function(element, className)
	{
		var present = false;
		var newClasses = "";
		if (element != null && element.className != null && element.className != "")
		{
			var currentClasses = element.className.split(" ");
			for (i = 0; i < currentClasses.length; i++)
			{
				if (currentClasses[i] != className)
				{
					if (newClasses != "")
					{
						newClasses += " ";
					}
					newClasses += currentClasses[i];
				}
			}
			element.className = newClasses;
		}
	},
	
	isOfCssClass: function(element, className)
	{
	    if (element.className != null)
	    {
	        var classes = element.className.split(" ");
	        for (var i = 0; i < classes.length; i++)
	        {
	            if (classes[i] == className)
	            {
	                return true;
	            }
	        }
	    }
	    return false;
	},
	 
	 getUserIdFromCookie: function()
	 {
		  var cookieName = "marketwatchportfolio";
		  var documentCookie = document.cookie;
		  var begin = documentCookie.indexOf(cookieName);
		   
		  if (begin == -1)
		  {
			 return null;
		  }
		  var end = documentCookie.indexOf(";", begin);
		  if (end == -1)
		  {
			 end = documentCookie.length;
		  }
		  var portfolioCookie = documentCookie.substring(begin, end);
		  var uidString = "UID=";
		  begin = portfolioCookie.indexOf(uidString);
		  if (begin == -1)
		  {
			 return null;
		  }
		  end = portfolioCookie.indexOf("&", begin);
		  if (end == -1)
		  {
			 end = portfolioCookie.length;
		  }
		  var userId = portfolioCookie.substring(begin + uidString.length, end);
		  return userId;
	 }
};

function PollingCoordinator()
{
	this.callbacks = new Array();
	this.minimumRefreshRate = PollingCoordinator.MaximumRefreshRate;
	this.startTimeout = null;
	this.debug = false;
}

PollingCoordinator.MaximumRefreshRate = 2147483647;

PollingCoordinator.prototype.add = function(coordinationId, coordinatedRequest, getRequestCallback, processResponseCallback)
{
	this.callbacks[this.callbacks.length] = 
		{"coordinationId":coordinationId, "coordinatedRequest":coordinatedRequest, "getRequest":getRequestCallback, "processResponse":processResponseCallback};
		
	if(this.minimumRefreshRate > coordinatedRequest.RefreshRate)
	{
		this.minimumRefreshRate = coordinatedRequest.RefreshRate;
	}
};

PollingCoordinator.prototype.remove = function(coordinationId)
{
    var updatedCallbacks = new Array();
    
    for(var i = 0; i < this.callbacks.length; i++)
    {
        if(this.callbacks[i].coordinationId != coordinationId)
        {
            updatedCallbacks[updatedCallbacks.length] = this.callbacks[i];
        }
    }
    
    this.callbacks = updatedCallbacks;
};

PollingCoordinator.prototype.start = function()
{
	var thunk = this;
	
	// Safari has an issue with deserializing some stuff that crashes the browser...although
	// Kevin may have cleaned up the issue (as of 7/18/06)...
	//
	// FireFox 1.0 seems to have an issue with setTimeout...we were seeing way, way too many
	// ad refreshes from users running FF 1.0, so we're disabling the ad refresh for them.  It
	// seemed prudent to do the same for polling...
	if(!BrowserDetect().isSafari && !BrowserDetect().isFF10)
	{
		this.startTimeout = setTimeout(function()
		{
			thunk.sendMessages();	
		}, this.minimumRefreshRate);
	}
};

PollingCoordinator.prototype.sendMessages = function()
{
	try
	{
	    if (this.debug)
	    {
	        window.status = "Polling: " + new Date().toLocaleTimeString() + "...";
	    }
	
		var messages = new Array();
		var messagesIndex = 0;
		
		for(var i = 0; i < this.callbacks.length; i++)
		{
		    var callback = this.callbacks[i];
			var coordinatedRequest = callback.coordinatedRequest;
			var callbackMessage = callback.getRequest();
			
			if(callbackMessage != null)
			{
				coordinatedRequest.Message = callbackMessage;
				coordinatedRequest.RequestId = i.toString();
				messages[messagesIndex] = coordinatedRequest;
				messagesIndex++;
			}		
		}
		
		if(messages.length > 0)
		{
			var message = {"Requests": messages};
			var request = HomePage.getRequest();
			var thunk = this;
			request.open("GET", "CoordinatedBridgePage.aspx?Messages=" + JSON.serialize(message), true);
			request.onreadystatechange = function()
			{
				if(request.readyState == 4)
				{
					thunk.onMessagesProcessed(request.responseText);
				}
			};
			request.send(null);
		}
		else
		{
			this.start();
		}
	}
	catch(sendException) 
	{
		HomePage.reportError("PollingCoordinator.prototype.sendMessages() - " + sendException);	
		this.start();
	}		
};

PollingCoordinator.prototype.onMessagesProcessed = function(responseText)
{
	try
	{
		var response = JSON.deserializeNoValidate(responseText);
		
		if(response != null && response.Succeeded == true && response.Responses != null)
		{
			for(var i = 0; i < response.Responses.length; i++)
			{
				var coordinatedResponse = response.Responses[i];
				var requestId = parseInt(coordinatedResponse.RequestId);

				var coordinatedRequest = this.callbacks[requestId].coordinatedRequest;
				
				if(coordinatedRequest.LastUpdated != coordinatedResponse.LastUpdated &&
				    coordinatedResponse.Response != null)
				{
					coordinatedRequest.LastUpdated = coordinatedResponse.LastUpdated;
					// NOTE - Jason - 4/19/2006 - It's possible that the callback could handle
					// the response asynchronously. We should pass in a 
					// callback to processRequest() as a 2nd argument such that the called function 
					// could call us back and we'd decrement a count (or something like that).
					// That way, we'd know when we could set the timer again to fire start(), but
					// we'll leave it this way for now.
					
	                // NOTE: for some reason a callback may still occur even if the target object is null.
	                // So...in case the target is gone, we'll catch-all.
					try
					{
    					this.callbacks[requestId].processResponse(coordinatedResponse.Response);					
					}
					catch(callbackException) { }
				}
			}			
		}
	}
	catch(processException) 
	{ 
		HomePage.reportError("PollingCoordinator.prototype.onMessagesProcessed() - " + processException);	
	}
	
	this.start();
};

function AdRefresher(containerId, refreshRate, orderValue)
{
	//Deprecated
}

function MyMarketWatchManager(uiMessage, dataMessage, userId, tabId, tickerContent, headlineContent)
{
	this.recentTabControl = document.getElementById(uiMessage.RecentTabId);
	this.portfolioTabControl = document.getElementById(uiMessage.PortfolioTabId);
	this.recentHeadlineControl = document.getElementById(uiMessage.RecentHeadlineId);
	this.recentHeadlineContentControl = document.getElementById(uiMessage.RecentHeadlineContentId);
	this.recentTickerControl = document.getElementById(uiMessage.RecentTickerId);
	this.recentTickerContentControl = document.getElementById(uiMessage.RecentTickerContentId);
	this.tickerHRef = uiMessage.TickerHRef;
	this.portfolioTickerControl = document.getElementById(uiMessage.PortfolioTickerId);
	this.portfolioTickerContentControl = document.getElementById(uiMessage.PortfolioTickerContentId);
	this.portfolioHeadlineControl = document.getElementById(uiMessage.PortfolioHeadlineId);
	this.portfolioHeadlineContentControl = document.getElementById(uiMessage.PortfolioHeadlineContentId);
	this.portfolioHeaderControl = document.getElementById(uiMessage.PortfolioHeaderId)
	this.recentHeaderControl = document.getElementById(uiMessage.RecentHeaderId);
	this.userId = userId;

    this.tickerContentHTML = tickerContent;
    this.headlineContentHTML = headlineContent;
	
	this.myData = new Array();
	this.myData[tabId] = dataMessage;
	this.showData(tabId);
}

MyMarketWatchManager.MyQuotes = 0;
MyMarketWatchManager.Portfolio = 1;

MyMarketWatchManager.prototype.clearAll = function(tabId)
{
    if (tabId == MyMarketWatchManager.MyQuotes)
    {
        mymwCookie.clearAllViewedQuotes();
        if (this.myData[tabId] != null)
        {
            this.myData[tabId].Tickers = null;
            this.myData[tabId].Headlines = null;
            this.showData(tabId);
        }

	    //If user is logged in, update the User2 Database
	    if(mymwCookie.UID)
	    {
		    var message = {"UserId": mymwCookie.UID};
    		
		    var request = HomePage.getRequest();
		    try
		    {
		        request.open("GET", "BridgePage.aspx?Method=UpdateUserWithMyMW&Message=" + JSON.serialize(message), true);
		        request.send(null);
		    }
            catch(sendException)
            {
	            //alert(sendException);
            }
		}
    }
}

MyMarketWatchManager.prototype.showData = function(tabId)
{
	var data = this.myData[tabId];
	var quoteTable = null;
	
	if (tabId == MyMarketWatchManager.MyQuotes)
	{
		HomePage.addCssClass(this.recentTabControl, "selected");
		HomePage.removeCssClass(this.portfolioTabControl, "selected");
		HomePage.addCssClass(this.portfolioTickerContentControl, "invisible");
		HomePage.removeCssClass(this.recentTickerContentControl, "invisible");
		HomePage.addCssClass(this.portfolioHeadlineContentControl, "invisible");
		HomePage.removeCssClass(this.recentHeadlineContentControl, "invisible");
		HomePage.addCssClass(this.portfolioHeaderControl, "invisible");
		if (data != null && data.Tickers != null && data.Tickers.length > 0)
		{
		    HomePage.removeCssClass(this.recentHeaderControl, "invisible");
		}
		else
		{
		    HomePage.addCssClass(this.recentHeaderControl, "invisible");
		}
		
		quoteTable = this.recentTickerContentControl.getElementsByTagName("table")[0];
	}
	else if (tabId == MyMarketWatchManager.Portfolio)
	{
		HomePage.addCssClass(this.portfolioTabControl, "selected");
		HomePage.removeCssClass(this.recentTabControl, "selected");
		HomePage.addCssClass(this.recentTickerContentControl, "invisible");
		HomePage.removeCssClass(this.portfolioTickerContentControl, "invisible");
		HomePage.addCssClass(this.recentHeadlineContentControl, "invisible");
		HomePage.removeCssClass(this.portfolioHeadlineContentControl, "invisible");
		HomePage.addCssClass(this.recentHeaderControl, "invisible");
		if (data != null && data.Tickers != null && data.Tickers.length > 0)
		{
		    HomePage.removeCssClass(this.portfolioHeaderControl, "invisible");
		}
		
		quoteTable = this.portfolioTickerContentControl.getElementsByTagName("table")[0];
	}
	
	if(data != null)
	{	
		if (data.Tickers != null && data.Tickers.length > 0)
		{
			if (quoteTable == null)
			{
				quoteTable = this.generateQuoteTable(data.Tickers);
				headlineTable = this.generateHeadlineLinks(data.Headlines);
				if (tabId == MyMarketWatchManager.MyQuotes)
				{
					this.recentTickerContentControl.appendChild(quoteTable);
					this.recentHeadlineContentControl.appendChild(headlineTable);
				}
				else if (tabId == MyMarketWatchManager.Portfolio)
				{
					this.portfolioTickerContentControl.appendChild(quoteTable);
					this.portfolioHeadlineContentControl.appendChild(headlineTable);
				}
			}
		}
		else
		{
			if (tabId == MyMarketWatchManager.MyQuotes)
			{
			    this.recentTickerContentControl.innerHTML = this.tickerContentHTML[tabId];
			    this.recentHeadlineContentControl.innerHTML = this.headlineContentHTML[tabId];
			}
			else if (tabId == MyMarketWatchManager.Portfolio)
			{
				this.portfolioTickerContentControl.innerHTML = this.tickerContentHTML[tabId];
				this.portfolioHeadlineContentControl.innerHTML = this.headlineContentHTML[tabId];
			}
		}
	}	
	else
	{
		var message = {"Type": tabId, "UserId": this.userId};

		var request = HomePage.getRequest();

		var thunk = this;
		request.open("GET", "BridgePage.aspx?Method=GetMyMarketWatchData&Message=" + JSON.serialize(message), true);
		request.onreadystatechange = function()
		{
			if(request.readyState == 4)
			{
				thunk.onMessagesProcessed(tabId, request.responseText);
			}
		};
		request.send(null);		
		
	}
};

MyMarketWatchManager.prototype.onMessagesProcessed = function(tabId, responseText)
{
	var response = JSON.deserializeNoValidate(responseText);		
	
	if(response != null && response.Succeeded == true)
	{
		this.myData[tabId] = response;
		this.showData(tabId);
		
		if (window.MWLiveQuotes != null)
		{
			MWLiveQuotes.setup();
		}
		else if (window.LiveQuotesGateway != null)
		{
		    LiveQuotesGateway.setup();
		}
	}
};

MyMarketWatchManager.prototype.generateHeadlineLinks = function(headlines)
{
    var now = new Date();
    
    var headlineTable = document.createElement("table");
    headlineTable.cellPadding = 0;
    headlineTable.cellSpacing = 0;
    headlineTable.border = 0;
    
    var headlineTableBody = document.createElement("tbody");
    
	for(var i = 0; i < headlines.length; i++)
	{
		var headlineRow = document.createElement("tr");
		
		if((i + 1) % 2 == 0)
		{
    			headlineRow.className = "myMarketWatchRow even";		
		}
		else
		{
    			headlineRow.className = "myMarketWatchRow odd";				
		}
		
		var currentHeadline = headlines[i];
		var timestamp = document.createElement("td");
		
		headlineRow.appendChild(timestamp);
		var createdTimestamp = new Date(Date.parse(currentHeadline.CreatedTimestamp));

        if((now.getDate() == createdTimestamp.getDate()) && (now.getMonth() == createdTimestamp.getMonth()) && (now.getFullYear() == createdTimestamp.getFullYear()))
        {
            var minutes = createdTimestamp.getMinutes() < 10 ? "0" + createdTimestamp.getMinutes() : createdTimestamp.getMinutes();
            var hours = createdTimestamp.getHours() % 12 == 0 ? "12" : createdTimestamp.getHours() % 12;
            timestamp.innerHTML = hours + ":" + minutes;
        }
        else
        {
            var month = createdTimestamp.getMonth() + 1;
            var day = createdTimestamp.getDate();
            timestamp.innerHTML = month + "/" + day;
        }
        
		timestamp.className = "timestamp";

		var headline = document.createElement("td");
		headline.className = "headline";
		
		if(currentHeadline.DocType == 90)
		{
		    if(currentHeadline.Symbol != null)
		    {
		        var symbolSpan = document.createElement("span");
		        symbolSpan.innerHTML = currentHeadline.Symbol;
                var symbolLink = document.createElement("a");
                symbolLink.href = currentHeadline.Link;          
                symbolLink.appendChild(symbolSpan); 
                headline.appendChild(document.createTextNode("["));
                headline.appendChild(symbolLink);		
                headline.appendChild(document.createTextNode("] "));		    
                headline.appendChild(document.createTextNode(currentHeadline.Headline));		    
		    }
            headlineRow.appendChild(headline);		
		}
		else
		{
	        var link = document.createElement("a");
	        link.href = currentHeadline.Link;
	        link.innerHTML = currentHeadline.Headline;
	        headline.appendChild(link);		
    		headlineRow.appendChild(headline);
		}
		
		headlineTableBody.appendChild(headlineRow);
	}
	
	headlineTable.appendChild(headlineTableBody);
	
	return headlineTable;
};

MyMarketWatchManager.prototype.generateQuoteTable = function(tickers)
{
	var quoteTable = document.createElement("table");
	quoteTable.className = "quotes";		

	var quoteBody = document.createElement("tbody");
	quoteTable.appendChild(quoteBody);
	
	this.generateTableHeader(quoteBody);
	
	var index = 0;
	for(var i = 0; i < tickers.length; i++)
	{
		if (tickers[i] != null)
		{
			this.generateTableRow(quoteBody, tickers[i], index);
			index++;
		}
	}
	
	return quoteTable;
};

MyMarketWatchManager.prototype.generateTableRow = function(quoteTable, ticker, index)
{
	var quoteRow = document.createElement("tr");
	quoteTable.appendChild(quoteRow);	
	if((index + 1) % 2 == 0)
	{
		quoteRow.className = "myMarketWatchRow even";		
	}
	else
	{
		quoteRow.className = "myMarketWatchRow odd";				
	}
	
	var symbolCell = document.createElement("td");
	quoteRow.appendChild(symbolCell);
	symbolCell.className = "symbol";
	var symbolAnchor = document.createElement("a");
	symbolCell.appendChild(symbolAnchor);
	
	var tickerValue = null;
	if(ticker.Exchange != null && ticker.Exchange.toUpperCase() !=  "US") 
	{
	    tickerValue = ticker.Exchange + ":" + ticker.Symbol;
	}
	else
	{
    		tickerValue = ticker.Symbol;
	}
	
    symbolAnchor.innerHTML = tickerValue;
	
    symbolAnchor.href = this.tickerHRef + tickerValue;
	var priceCell = document.createElement("td");
	quoteRow.appendChild(priceCell);
	priceCell.className = "price";
	var neutralPrice = document.createElement("span");
	priceCell.appendChild(neutralPrice);
	neutralPrice.className = "neutral";
	var formattedPrice = document.createElement("span");
	priceCell.appendChild(formattedPrice);
	formattedPrice.className = "mwlivequotes";
	formattedPrice.setAttribute("mwfield", "Price");
	formattedPrice.setAttribute("mwformat", ",2");
	formattedPrice.setAttribute("mwsymbol", tickerValue);
	formattedPrice.innerHTML = ticker.Price;

	var changeCell = document.createElement("td");
	quoteRow.appendChild(changeCell);
	changeCell.className = "change";
	var formattedChange = document.createElement("span");
	changeCell.appendChild(formattedChange);
	formattedChange.className = "mwlivequotes";
	formattedChange.setAttribute("mwfield", "Change");
	formattedChange.setAttribute("mwformat", ",2");
	formattedChange.setAttribute("mwsymbol", tickerValue);
	var colorChange = document.createElement("span");
	if (ticker.Change > 0)
	{
		colorChange.className = "up";
	}
	else if (ticker.Change < 0)
	{
		colorChange.className = "down";
	}
	colorChange.innerHTML = ticker.Change;
	formattedChange.appendChild(colorChange);
		
	var percentChangeCell = document.createElement("td");
	quoteRow.appendChild(percentChangeCell);
	percentChangeCell.className = "percentChange";
	var formattedPercentChange = document.createElement("span");
	percentChangeCell.appendChild(formattedPercentChange);
	formattedPercentChange.className = "mwlivequotes";
	formattedPercentChange.setAttribute("mwfield", "PercentChange");
	formattedPercentChange.setAttribute("mwformat", ",2");
	formattedPercentChange.setAttribute("mwsymbol", tickerValue);
	var colorPercentChange = document.createElement("span");
	if (ticker.PercentChange > 0)
	{
		colorPercentChange.className = "up";
	}
	else if (ticker.PercentChange < 0)
	{
		colorPercentChange.className = "down";
	}
	colorPercentChange.innerHTML = ticker.PercentChange;
	formattedPercentChange.appendChild(colorPercentChange);
};

MyMarketWatchManager.prototype.generateTableHeader = function(quoteTable)
{
	var quoteHeaderRow = document.createElement("tr");
	quoteTable.appendChild(quoteHeaderRow);

	var symbolHeader = document.createElement("th");
	quoteHeaderRow.appendChild(symbolHeader);
	symbolHeader.className = "symbol";
	symbolHeader.innerHTML = "Symbol";
	
	var priceHeader = document.createElement("th");
	quoteHeaderRow.appendChild(priceHeader);
	priceHeader.className = "price";
	priceHeader.innerHTML = "Price";
	
	var changeHeader = document.createElement("th");
	quoteHeaderRow.appendChild(changeHeader);
	changeHeader.className = "change";
	changeHeader.innerHTML = "Change";

	var percentChangeHeader = document.createElement("th");
	quoteHeaderRow.appendChild(percentChangeHeader);
	percentChangeHeader.className = "percentChange";
	percentChangeHeader.innerHTML = "% Change";
};

function BulletinMonitor(containerId, headlineId, message)
{
    this.container = document.getElementById(containerId);
    this.headline = document.getElementById(headlineId);
    this.message = message;
}

BulletinMonitor.prototype.getRequest = function()
{
    return JSON.serialize(this.message);
};

BulletinMonitor.prototype.processResponse = function(response)
{
	try
	{
		if((response.Succeeded == true) && (response.Bulletin != null))
		{
		    var bulletin = response.Bulletin;
		    
		    var displayStyle = (bulletin.HasExpired == false) ? "block" : "none";
		    
            if(this.message.LastUpdated != bulletin.LastUpdated || displayStyle != this.container.style.display)		
            {
		        this.message.LastUpdated = bulletin.LastUpdated;		

		        if(bulletin.HasExpired == false)
		        {
		            this.headline.innerHTML = "<a href=\"" + bulletin.Link + "\">" + bulletin.Headline + "</a>";
		            this.container.style.display = "block";
		        }
		        else
		        {
                    this.container.style.display = "none";
		        }
		    }
		}
	}
	catch(sendException) 
	{
		HomePage.reportError("BulletinMonitor.prototype.processResponse() - " + sendException);
	}	
};



function TimeBrandingMonitor(message)
{
    try
    {
        TimeBrandingMonitor.currentInterval = null;
        TimeBrandingMonitor.nextInterval = null;
        TimeBrandingMonitor.lastUpdate = null;
        this.message = message;
    }
    catch(e)
    {
        HomePage.reportError("TimeBrandingMonitor() - " + e);
    }
}

TimeBrandingMonitor.prototype.getRequest = function()
{
    return JSON.serialize(this.message);
};

TimeBrandingMonitor.prototype.processResponse = function(response)
{
	try
	{
		if(response.Succeeded == true)
		{
		    TimeBrandingMonitor.lastUpdate = response.LastUpdate;
		    TimeBrandingMonitor.currentInterval = response.CurrentInterval;
		    TimeBrandingMonitor.nextInterval = response.NextInterval;
		}
	}
	catch(sendException) 
	{
		HomePage.reportError("TimeBrandingMonitor.prototype.processResponse() - " + sendException);
	}	
};


function PhatMonitor(containerId, lastCheckedDateId, lastCheckedTimeId, lastCheckedZoneId, message, imageUrl, phatItems)
{
	this.imageUrl = imageUrl;
	this.message = message;
	this.container = document.getElementById(containerId);
	this.lastCheckedDate = document.getElementById(lastCheckedDateId);
	this.lastCheckedTime = document.getElementById(lastCheckedTimeId);
	this.lastCheckedZone = document.getElementById(lastCheckedZoneId);
	this.phatItems = phatItems;
	
	for(var i = 0; i < this.phatItems.length; i++)
	{
	    var phatItem = this.phatItems[i];
	    
	    if(phatItem.AddJavaScript != null)
	    {
	        eval(phatItem.AddJavaScript);
	    }
	}
}

PhatMonitor.prototype.getRequest = function()
{
	return JSON.serialize(this.message);
};

PhatMonitor.prototype.processResponse = function(response)
{
	try
	{
	    if(response != null)
	    {
	        if(response.LastChecked != null)
	        {
	            if ((response.LastChecked.Date != null) && (this.lastCheckedDate != null))
	            {
	                this.lastCheckedDate.innerHTML = response.LastChecked.Date;
	            }
	            
	            if ((response.LastChecked.Time != null) && (this.lastCheckedTime != null))
	            {
	                this.lastCheckedTime.innerHTML = response.LastChecked.Time;
	            }
	            
	            if ((response.LastChecked.Zone != null) && (this.lastCheckedZone != null))
	            {
                    this.lastCheckedZone.innerHTML = response.LastChecked.Zone;
	            }	            
	        }
    	    
		    if(response.Succeeded == true && response.Responses != null &&
		        response.Responses.length == 1 && response.Responses[0] != null)
	        {
                var phatContentResponse = response.Responses[0];
                if(phatContentResponse.LastUpdated != this.message.Requests[0].LastUpdated && 
		            phatContentResponse.PhatContent != null)
		        {
		            this.getCurrentPhatWidgets();		    
		            this.message.Requests[0].LastUpdated = phatContentResponse.LastUpdated;
		           
		//			var newcontainer = document.createElement(
		           
		            this.container.innerHTML = phatContentResponse.PhatContent;
                   
                    this.updatePhatWidgets(phatContentResponse);
		        }	    
	        }
	    }
	}
	catch(sendException) 
	{
		HomePage.reportError("PhatMonitor.prototype.processResponse() - " + sendException);
	}
};

PhatMonitor.prototype.updatePhatWidgets = function(response)
{
    var updatedPhatItemsList = new Array();

    // NOTE: This is slightly dangerous in that I'm assuming the ordering in 
    // currentPhatElements is the same as what you find in this.phatItems.
        
    for(var k = 0; k < this.phatItems.length; k++)
    {
        var phatItem = this.phatItems[k];
        
        var newPhatElement = document.getElementById(phatItem.WidgetId);
        
        if(newPhatElement != null)
        {
            newPhatElement.parentNode.replaceChild(phatItem.CurrentPhatElement, newPhatElement);
            updatedPhatItemsList[updatedPhatItemsList.length] = phatItem;
            phatItem.CurrentPhatElement = null;
        }
        else
        {
            eval(phatItem.RemoveJavaScript);
        }
    }
    
    // Now see if an element was added that wasn't there before
    if(response.Widgets != null && response.Widgets.length > 0)
    {
        for(var i = 0; i < response.Widgets.length; i++)
        {
            var addedPhatItem = response.Widgets[i];
            var itemFound = false;
            
            for(var j = 0; j < updatedPhatItemsList.length; j++)
            {
                if(addedPhatItem.WidgetId == updatedPhatItemsList[j].WidgetId)
                {
                    itemFound = true;
                    break;
                }
            }
            
            if(itemFound == false)
            {
                updatedPhatItemsList[updatedPhatItemsList.length] = addedPhatItem;
                eval(addedPhatItem.AddJavaScript);
            }
        }
    }
    
    this.phatItems = updatedPhatItemsList;
};

PhatMonitor.prototype.getCurrentPhatWidgets = function()
{
    for(var i = 0; i < this.phatItems.length; i++)
    {
        var currentPhatElement = document.getElementById(this.phatItems[i].WidgetId);
        currentPhatElement.parentNode.removeChild(currentPhatElement);
        this.phatItems[i].CurrentPhatElement = currentPhatElement;
    }
};

function MarketOverview()
{
    this.selectedTickers = new Array();
    this.chartTimeout;
    this.popupTimeout;
    this.currentTicker;
    this.currentTickerRow;
    this.displayedTicker;
}

MarketOverview.prototype.addSelectedTicker = function(ticker)
{
    this.selectedTickers[this.selectedTickers.length] = ticker;
};

MarketOverview.prototype.showPopupMenu = function(menuId, ticker, tickerRowElement)
{
   var menuElement = document.getElementById(menuId);
   if (menuElement != null)
   {
	  menuElement.style.visibility = "visible";
	  this.currentTicker = ticker;
	  if (tickerRowElement != null)
	  {
		if (tickerRowElement.tagName == "TR")
		{
			this.currentTickerRow = tickerRowElement;
		}
	  }
	  var spans = menuElement.getElementsByTagName("span");
	  for (var i = 0; i < spans.length; i++)
	  {
		if (spans[i].className == "symbolToExchange")
		{
			var index = ticker.indexOf(":");
			if (index != -1 || ticker.length - 1)
			{
				spans[i].innerHTML = ticker.substring(index + 1, ticker.length);
			}
		}
	  }
   }
};

MarketOverview.prototype.delayHidePopupMenu = function(menuId)
{
    var thunk = this;
    clearTimeout(this.popupTimeout);
    this.popupTimeout = setTimeout(function() { thunk.hidePopupMenu(menuId); }, 1000);
};

MarketOverview.prototype.stopHidePopupMenu = function()
{
    clearTimeout(this.popupTimeout);
};

MarketOverview.prototype.hidePopupMenu = function(menuId)
{
   var menuElement = document.getElementById(menuId);
   if (menuElement != null)
   {
	  menuElement.style.visibility = "hidden";
   }
};

MarketOverview.prototype.showTickerData = function(tableRow, ticker, displayTicker, chartId, chartSrc)
{
	var overviewTable = tableRow.parentNode;
	if (overviewTable.tagName.toLowerCase() == "table" || overviewTable.tagName.toLowerCase() == "tbody")
	{
		var trs = overviewTable.getElementsByTagName("tr");
		for (i = 0; i < trs.length; i++)
		{
			if (HomePage.isOfCssClass(trs[i], "highlighted"))
			{
				HomePage.removeCssClass(trs[i], "highlighted");
			}
		}
	}
	HomePage.addCssClass(tableRow, "highlighted");
  

   var chartElement = document.getElementById(chartId);
   if (chartElement != null && chartElement.childNodes != null)
   {
	for (i = 0; i < chartElement.childNodes.length; i++)
	{
		if (chartElement.childNodes[i].tagName.toLowerCase() == "img")
		{
		    chartElement.childNodes[i].src = chartSrc;
		}
	}
   }
};

MarketOverview.prototype.delayShowTickerData = function(tableRow, ticker, displayTicker, chartId, chartSrc)
{
    var thunk = this;
    clearTimeout(this.chartTimeout);
    this.chartTimeout = setTimeout(function() { thunk.showTickerData(tableRow, ticker, displayTicker, chartId, chartSrc); }, 500);
};

MarketOverview.prototype.stopShowTickerData = function()
{
    clearTimeout(this.chartTimeout);
};

MarketOverview.prototype.switchTicker = function(newTicker, newTickerRowElement)
{
    for (i = 0; i < this.selectedTickers.length; i++)
    {
	   if (this.selectedTickers[i] == this.currentTicker)
	   {
		  this.selectedTickers[i] = newTicker;
		  break;
	   }
    }
    
    this.switchTickerRowElements(this.currentTicker, this.currentTickerRow, newTicker, newTickerRowElement);
    
    var userId = HomePage.getUserIdFromCookie();
    var tickers = this.selectedTickers.join("|");
    var message = {"UserId": userId, "Tickers": tickers};
    if (userId != null)
    {  
	   this.updateUserWithMarketOverviewTickers(message);
    }
    else
    {
	   this.saveSelectedTickersToCookie(message.Tickers);
    }
    
    return false;
};

MarketOverview.prototype.switchTickerRowElements = function(oldTicker, oldTickerRow, newTicker, newTickerRow)
{
	var oldCells = oldTickerRow.getElementsByTagName("td");
	var newCells = newTickerRow.getElementsByTagName("td");
	if (oldCells.length == 3 && newCells.length == 3)
	{
		var icon = oldCells[0].getElementsByTagName("a")[0];
		icon.childNodes[0].innerHTML = newTicker;
		var oldSymbol = oldCells[0].getElementsByTagName("a")[1];
		var newSymbol = newCells[0].getElementsByTagName("a")[0];
		newSymbol.onmouseover = oldSymbol.onmouseover;
		oldSymbol.onmouseover = "";
		oldSymbol.onclick = newSymbol.onclick;
		newSymbol.onclick = "";
		var tempSymbol = oldCells[0].replaceChild(newSymbol, oldSymbol);
		newCells[0].appendChild(tempSymbol);
		var tempPrice = oldTickerRow.replaceChild(newCells[1], oldCells[1]);
		newTickerRow.appendChild(tempPrice);
		var tempChange = oldTickerRow.replaceChild(newCells[1], oldCells[2]);
		newTickerRow.appendChild(tempChange);
	}
};

MarketOverview.prototype.updateUserWithMarketOverviewTickers = function(message)
{
	var request = HomePage.getRequest();

	try
	{
		request.open("GET", "BridgePage.aspx?method=UpdateUserWithMarketOverviewTickers" + 
			"&message=" + JSON.serialize(message), false);
		request.send(null);
		this.saveSelectedTickersToCookie(message.Tickers);
	}
	catch(sendException) 
	{
		HomePage.reportError(sendException);
	}
};

MarketOverview.prototype.saveSelectedTickersToCookie = function(tickers)
{
	var cookieName = "mw_tickers";
	var expires = new Date();
	expires.setFullYear(expires.getFullYear() + 1);
	var domain = ".marketwatch.com";
	document.cookie = cookieName + "=values=" + tickers + "; expires=" + expires.toGMTString() + "; path=/; domain=" + domain;
};

var marketOverview = new MarketOverview();

function LiveHeadlines(elementId, message, latestHeadlines)
{
	this.MAX_HEADLINES = 30;
	this.elementId = elementId;
	this.element = document.getElementById(elementId);
	this.headlines = new Array();
	this.message = message;
	
	if(latestHeadlines != null && latestHeadlines.length > 0)
	{
	    this.sliceHeadlines(latestHeadlines);
	    this.message.LastUpdated = latestHeadlines[0].CreatedTimestamp;	
	}

	this.scrollTimeout;
}

LiveHeadlines.prototype.getRequest = function()
{
	var request = null;
	
	request = JSON.serialize(this.message);	
	
	return request;
};

LiveHeadlines.prototype.processResponse = function(response)
{
	try
	{
		if (response.Succeeded == true && response.LastUpdated != this.message.LastUpdated && response.Headlines != null)
		{
			this.addHeadlines(response.Headlines);
			this.message.LastUpdated = response.LastUpdated;
		}
	}
	catch(sendException) 
	{
		HomePage.reportError("LiveHeadlines.prototype.processResponse() - " + sendException);
	}
};

LiveHeadlines.prototype.sliceHeadlines = function(headlines)
{
	var numHeadlines = headlines.length;
	var numHeadlinesAdded = 0;
	
	if (numHeadlines < this.MAX_HEADLINES)
	{
		if (numHeadlines + this.headlines.length > this.MAX_HEADLINES)
		{
			this.headlines = this.headlines.slice(0, this.MAX_HEADLINES - numHeadlines);
		}
		this.headlines = headlines.concat(this.headlines);
		numHeadlinesAdded = numHeadlines;
	}
	else
	{
		this.headlines = headlines.slice(0, this.MAX_HEADLINES);
		numHeadlinesAdded = this.MAX_HEADLINES;
	}
};

LiveHeadlines.prototype.addHeadlines = function(headlines)
{
    this.sliceHeadlines(headlines);
	
	this.element.innerHTML = "";
	for (var i = 0; i < this.headlines.length; i++)
	{
	    var currentHeadline = this.headlines[i];
	    
		var timestamp = document.createElement("span");
		var firstSpace = currentHeadline.CreatedTimestamp.indexOf(" ");
		var secondSpace = currentHeadline.CreatedTimestamp.indexOf(" ", firstSpace + 1);
		var time = currentHeadline.CreatedTimestamp.substr(firstSpace, secondSpace - firstSpace);
		var lastColon = time.lastIndexOf(":");
		timestamp.innerHTML = time.substr(0, lastColon);
		timestamp.className = "timestamp";
		
		var headlineRow = document.createElement("div");
		headlineRow.className = "headlineEntry";
		headlineRow.appendChild(timestamp);

		var headline = document.createElement("span");
		headline.innerHTML = currentHeadline.Headline;
		headline.headline = "headline";
		
		if(currentHeadline.DocType == 90)
		{
		    if(currentHeadline.Symbol != null)
		    {
		        var symbolSpan = document.createElement("span");
		        symbolSpan.innerHTML = currentHeadline.Symbol;
                var symbolLink = document.createElement("a");
                symbolLink.href = currentHeadline.Link;          
                symbolLink.appendChild(symbolSpan); 
                headlineRow.appendChild(document.createTextNode("["));
                headlineRow.appendChild(symbolLink);		
                headlineRow.appendChild(document.createTextNode("] "));		    
		    }
            headlineRow.appendChild(headline);		
		}
		else if(currentHeadline.DocType == 103 || currentHeadline.DocType == 91)
		{
			var link = document.createElement("a");
	        link.href = currentHeadline.Link;
	        link.appendChild(headline);		
    		headlineRow.appendChild(link);
    //		headlineRow.appendChild(document.createTextNode(" "));
    //		headlineRow.appendChild(createClipIcon(currentHeadline.Id));
		}
		else
		{
	        var link = document.createElement("a");
	        link.href = currentHeadline.Link;
	        link.appendChild(headline);		
    		headlineRow.appendChild(link);
		}
		
		this.element.appendChild(headlineRow);
	}
};

LiveHeadlines.prototype.scrollUp = function()
{
	if (this.element != null)
	{
		var topLoc = this.element.style.top.replace(/px/, "");
		if (topLoc == "")
		{
			topLoc = 0;
		}
		
		topLoc = parseInt(topLoc);
		if (topLoc < 0)
		{
			topLoc += 6;
			this.element.style.top = topLoc + "px";
			
			var thunk = this;
			clearTimeout(this.scrollTimeout);
			this.scrollTimeout = setTimeout(function() { thunk.scrollUp(); }, 50);
		}
	}
};

LiveHeadlines.prototype.scrollDown = function()
{
	if (this.element != null && this.element.parentNode != null)
	{
		var topLoc = this.element.style.top.replace(/px/, "");

		if (topLoc == "")
		{
			topLoc = 0;
		}
		else
		{
		    topLoc = parseInt(topLoc);
		}
			
	    var elementHeight = this.element.offsetHeight;
	    var parentNodeHeight = this.element.parentNode.offsetHeight;

	    if(elementHeight > parentNodeHeight)
	    {
	        var bottomPosition = parentNodeHeight - topLoc;
	        
	        if(bottomPosition < elementHeight)
	        {
	            topLoc -= 6;
	            this.element.style.top = topLoc + "px";
        		
	            var thunk = this;
	            clearTimeout(this.scrollTimeout);
	            this.scrollTimeout = setTimeout(function() { thunk.scrollDown(); }, 50);		        
	        }
	    }
	}
};

LiveHeadlines.prototype.scrollStop = function()
{
	clearTimeout(this.scrollTimeout);
};





function TimeBrandingSeedData(seedData)
{
    this.Data = seedData;
}


function TimeBrandingRibbon()
{
    this.startTimeout = null;
    this.outerDiv = null;
    this.innerDiv = null;
    this.textDiv = null;
    this.minuteSpan = null;
    this.secondSpan = null;
    this.innerPageElement = null;
    this.outerPageElement = null;
    this.debugDiv = null;
    this.delay = 1000;
}



TimeBrandingRibbon.prototype.setup = function(seedData)
{
    try
    {
        if ((seedData != null) && (seedData.Data != null) && (seedData.Data.InitialResponse != null))
        {
            TimeBrandingMonitor.lastUpdate = seedData.Data.InitialResponse.LastUpdate;
            TimeBrandingMonitor.currentInterval = seedData.Data.InitialResponse.CurrentInterval;
            TimeBrandingMonitor.nextInterval = seedData.Data.InitialResponse.NextInterval;
            
            if (seedData.Data.DebugDivId != null)
            {
                this.debugDiv = browser.getElement(seedData.Data.DebugDivId);
            }
            
            this.innerDiv = BrowserDetect().getElement(seedData.Data.InnerDivId);
            this.outerDiv = BrowserDetect().getElement(seedData.Data.OuterDivId);
            this.textDiv = BrowserDetect().getElement(seedData.Data.TextDivId);
            this.minuteSpan = BrowserDetect().getElement(seedData.Data.MinuteSpanId);
            this.secondSpan = BrowserDetect().getElement(seedData.Data.SecondSpanId);
            
            this.outerPageElement = new PageElement(this.outerDiv);
            this.innerPageElement = new PageElement(this.innerDiv);
            
            this.innerPageElement.setClippingFrame (this.outerPageElement);
            this.innerPageElement.makeWindowShade (20, 3, "bottom");
            
            this.outerPageElement.setOpenDimensions (660, 30);

            this.innerPageElement.snapShadeClosed();
            if (TimeBrandingMonitor.currentInterval.Image != null)
            {
                this.innerPageElement.toggleShade(true);
            }
            
            if (this.innerDiv != null)
            {
	            var thunk = this;
            	this.startTimeout = setTimeout(function() { thunk.timerTick(); }, this.delay);
	        }
	    }
	}
	catch (e)
	{
	    HomePage.reportError ("TimeBrandingRibbon.prototype.setup: " + e);
	}
};


TimeBrandingRibbon.prototype.toggleCountdown = function(show)
{
   this.textDiv.style.visibility = show ? "visible" : "hidden";
};


TimeBrandingRibbon.prototype.timerTick = function()
{
    try
    {
        if (TimeBrandingMonitor.currentInterval != null)
        {
            if (TimeBrandingMonitor.currentInterval.SecondsRemaining > -5)
            {
                TimeBrandingMonitor.currentInterval.SecondsRemaining--;
            }

            var minutes = 0;
            var seconds = 0;

            if (TimeBrandingMonitor.currentInterval.ShowCountdown)
            {
                minutes = Math.floor(TimeBrandingMonitor.currentInterval.SecondsRemaining / 60);
                seconds = TimeBrandingMonitor.currentInterval.SecondsRemaining - (minutes * 60);
            }

            if (this.debugDiv != null)
            {
                this.debugDiv.innerHTML = "<font size=1>Minutes: " + minutes + "  Seconds: " + seconds + "<br/>";
                
                if (TimeBrandingMonitor.lastUpdate != null)
                {
                    this.debugDiv.innerHTML += "LastUpdate: " + TimeBrandingMonitor.lastUpdate + "<br/>";
                }
                
                if (TimeBrandingMonitor.currentInterval != null)
                {
                    this.debugDiv.innerHTML += "CurrentInterval:<br/>" +
                                            "&nbsp;&nbsp;Image: " + TimeBrandingMonitor.currentInterval.Image + "<br/>" +
                                            "&nbsp;&nbsp;Seconds Remaining: " + TimeBrandingMonitor.currentInterval.SecondsRemaining + "<br/>" +
                                            "&nbsp;&nbsp;ShowCountdown: " + TimeBrandingMonitor.currentInterval.ShowCountdown + "<br/>";
                }

                if (TimeBrandingMonitor.nextInterval != null)
                {
                    this.debugDiv.innerHTML += "NextInterval:<br/>" +
                                        "&nbsp;&nbsp;Image: " + TimeBrandingMonitor.nextInterval.Image + "<br/>" +
                                        "&nbsp;&nbsp;Seconds Remaining: " + TimeBrandingMonitor.nextInterval.SecondsRemaining + "<br/>" +
                                        "&nbsp;&nbsp;ShowCountdown: " + TimeBrandingMonitor.nextInterval.ShowCountdown + "<br/>";
                }


                this.debugDiv.innerHTML += "&nbsp;<br/></font>";
            }

            if (TimeBrandingMonitor.currentInterval.ShowCountdown && (TimeBrandingMonitor.currentInterval.SecondsRemaining >= 0))
            {
                this.minuteSpan.innerHTML = minutes.toString();
                this.secondSpan.innerHTML = seconds.toString();
            }
            
            switch (TimeBrandingMonitor.currentInterval.SecondsRemaining)
            {
                case 0:
                    if ((TimeBrandingMonitor.currentInterval != null) && (TimeBrandingMonitor.currentInterval.Image != null))
                    {
                        this.innerPageElement.snapShadeClosed();
                    }
                    break;
                    
                    
                case -1:
                    break;
                    
                case -2:
                    if ((TimeBrandingMonitor.nextInterval != null) && (TimeBrandingMonitor.nextInterval.Image != null))
                    {
                        this.toggleCountdown(false);

                        TimeBrandingMonitor.currentInterval = TimeBrandingMonitor.nextInterval;
                        TimeBrandingMonitor.nextInterval = null;
                        
                        if (TimeBrandingMonitor.currentInterval != null)
                        {
                            TimeBrandingMonitor.currentInterval.SecondsRemaining -= 2;     // Correct for the delay in switching images
                        }
                        
                        this.innerDiv.style.background = "url('" + TimeBrandingMonitor.currentInterval.Image + "')"; 
                        
                        this.innerPageElement.toggleShade(true);
                        
						if(TimeBrandingMonitor.currentInterval.Image.indexOf("countdownToClose") > -1)
						{
							this.toggleCountdown(true);
						}
						else
						{
							this.toggleCountdown(false);
						}                        
                    }
                    break;
                    
                default:
                    break;
            }

        }
        
        var thunk = this;
        this.startTimeout = setTimeout(function() { thunk.timerTick(); }, this.delay);
    }
    catch (e)
    {
        HomePage.reportError("TimeBrandingRibbon.prototype.timerTick" + e);
    }
};

function openwindow(url, width, height) 
{
    params = 'width=' + width + ',height=' + height + ',resizeable,scrollbars';
    myvar = window.open(url, 'calculators', params);
    myvar.focus();
}

function newToggleSection(disabledSectionNames, disabledTabNames, enabledSection, enabledTab)
{
	for(de = 0; de < disabledSectionNames.length; de++)
	{
		var disabledSection = document.getElementById(disabledSectionNames[de]);
		if (disabledSection && disabledSection.style)
		{
		    disabledSection.style.display = 'none';
		}
	}

	for(dl = 0; dl < disabledTabNames.length; dl++)
	{
		var disabledTab = document.getElementById(disabledTabNames[dl]);
		var disabledTabLeftImg = document.getElementById(disabledTabNames[dl]+'Left');
		
		var disabledTabRightImg = document.getElementById(disabledTabNames[dl]+'Right');
		if (disabledTab && disabledTab.style)
		{
		    disabledTab.className = "RRTab Off";
		    disabledTabRightImg.className = "ImgTab OffRight";
		    disabledTabLeftImg.className = "ImgTab OffLeft";
		}
	}
	
	var enabledSection = document.getElementById(enabledSection);
	if (enabledSection && enabledSection.style)
	{
	    enabledSection.style.display = 'block';
	}
	
	var enabledTabLeftImg = document.getElementById(enabledTab+'Left');
	var enabledTabRightImg = document.getElementById(enabledTab+'Right');
	var enabledTab = document.getElementById(enabledTab);	
	if (enabledTab && enabledTab.style)
	{
	    enabledTab.className = "RRTab On";
	    enabledTabRightImg.className = "ImgTab OnRight";
	    enabledTabLeftImg.className = "ImgTab OnLeft";
	}
	
	return false;
}