/**
 * @author Ryan Johnson <ryan@livepipe.net>
 * @copyright 2007 LivePipe LLC
 * @package Object.Event
 * @license MIT
 * @url http://livepipe.net/projects/object_event/
 * @version 1.0.0
 */
if(typeof Object.Event=="undefined"){
   /**
    * Object.Event is an class that allows any object to support
    * custom events.
    @extends Object
    */
	Object.Event = {
	   /**
	    * Object.Event.extend is a method that extends the object
	    * passed in as an arguement with all it's own methods.
	    * @param {Object} object Object to be extended
	    */
		extend: function(object){
			object._objectEventSetup = function(event_name){
				this._observers = this._observers || {};
				this._observers[event_name] = this._observers[event_name] || [];
			};
			object.observe = function(event_name,observer){
				if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){
					this._objectEventSetup(event_name);
					if(!this._observers[event_name].include(observer))
						this._observers[event_name].push(observer);
				}else
					for(var e in event_name)
						this.observe(e,event_name[e]);
			};
			object.stopObserving = function(event_name,observer){
				this._objectEventSetup(event_name);
				this._observers[event_name] = this._observers[event_name].without(observer);
			};
			object.notify = function(event_name){
				this._objectEventSetup(event_name);
				var collected_return_values = [];
				var args = $A(arguments).slice(1);
				try{
					for(var i = 0; i < this._observers[event_name].length; ++i)
						collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null);
				}catch(e){
					if(e == $break)
						return false;
					else
						throw e;
				}
				return collected_return_values;
			};
			if(object.prototype){
				object.prototype._objectEventSetup	= object._objectEventSetup;
				object.prototype.observe			= object.observe;
				object.prototype.stopObserving		= object.stopObserving;
				object.prototype.notify				= function(event_name){
					if(object.notify){
					   
						var args = $A(arguments).slice(1);
						args.unshift(this);
						args.unshift(event_name);
						object.notify.apply(object,args);
					}
					this._objectEventSetup(event_name);
					var args = $A(arguments).slice(1);
					var collected_return_values = [];
					try{
						if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function')
							collected_return_values.push(this.options[event_name].apply(this,args) || null);
						for(var i = 0; i < this._observers[event_name].length; ++i)
							collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null);
					}catch(e){
						if(e == $break){
							return false;
						}else{ throw e; }
					}
					return collected_return_values;
				};
			}
		}
	}
}
Function.prototype.defaults = function(origArgs/*, defaults*/) {
	for (var i = 0, j = 1; j < arguments.length; i++, j++) {
		if (typeof origArgs[i] == 'undefined')
			origArgs[i] = arguments[j];
	}
}
document.insertAfter=function(new_node, existing_node){
	/**
	 * if the existing node has a following sibling, insert the current
	 * node before it. otherwise appending it to the parent node
	 * will correctly place it just after the existing node.
	 */
	try{
		if(existing_node.next()){
			existing_node.parentNode.insertBefore(new_node,existing_node.next());
		}else{
			existing_node.parentNode.appendChild(new_node);
		}
	}catch(err){
		nfl.log("insertAfter Error: "+ err.message);
	//	alert("insertAfter Error: "+ err.message);
	}
}
Object.extend(Prototype.Browser,{
	Version: (navigator.userAgent.toLowerCase().match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1]
});
/*
 * Creates a cross browser "window:hashchange" event
 * using the document object. 
 * patches in the native support for IE8's 'window.hashchange' event.
 * simulates native 'window.hashchange' event for dom compliant browsers.
 *
 * usage:
 * document.observe('window:hashchange',func);
 * window.observe('hashchange',func);
 */
Event.observe(window,'hashchange',function(event){ document.fire('window:hashchange'); });
document.observe('dom:loaded',function(){
	if(!((!!(window.attachEvent && !window.opera)) && parseInt((navigator.userAgent.toLowerCase().match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1]) >= 8)){
		window.__hash = location.hash;	
		setInterval((function(){ if(window.__hash != location.hash){
			window.__hash = location.hash;
			var event;
			if (document.createEvent) {
				event = document.createEvent("UIEvents");
				event.initUIEvent('hashchange', true, true,window,window.__hash);
				event.eventName = 'hashchange';
				event.memo = {};
				window.dispatchEvent(event);
			}else{
				document.fire('window:hashchange');
			}
		}}), 200);
	}
});
window.location.hashparams = function(){
	return {
		getStringFromHash: function(hashObj){
			var retStr = '';
			hashObj.each(function(pair){
				if(hashObj.keys().sort().indexOf(pair.key) > -1){
					if(pair.key != pair.value){
						retStr += (pair.key+':'+pair.value +'/');
					}else{
						retStr += (pair.value +'/');
					}
				}
			});
			return (retStr.substring(0,retStr.length - 1));
		},
		getHashFromString: function(stringObj){
			nfl.log("getHashFromString: type of stringObj = "+(typeof stringObj));
			if(stringObj.strip() == ''){ return null; }
			var hashParams	= stringObj.split('/');
			var actParams	= new Hash();
			for(ap=0; ap < hashParams.length; ap++){
				if(hashParams[ap].indexOf(':') > -1){
					paramSet	= hashParams[ap].split(':');
					actParams.set(paramSet[0],paramSet[1]);
				}else{
					actParams.set(hashParams[ap],hashParams[ap]);
				}
			}
			return actParams
		},
		get: function(){
			return window.location.hashparams.getHashFromString(location.hash.replace('#',''));
		},
		set: function(hashParams){
			location.hash	= ("#"+ (window.location.hashparams.getStringFromHash(hashParams)));
			location	= location;
		}
	}
}()

if(typeof nfl=="undefined"){ var nfl={}; } 
/**
 * Creates new namespaces under the nfl namespace
 * @param {String} The name of the new namespace
 */
nfl.namespace=function(){ var a=arguments,o=null,i,j,d;for(i=0;i<a.length;++i){d=a[i].split(".");o=nfl;for(j=(d[0]=="nfl")?1:0;j<d.length;++j){o[d[j]]=o[d[j]]||{};o=o[d[j]];}} return o;};
nfl.namespace("ui","util","global");
nfl.global.debugenabled	= true;
/**
 * Writes a message to the console(if available)
 * @param {String} message The message to write
 */
nfl.log=function(message,type){ 
	if(!Prototype.Browser.Opera && !Prototype.Browser.IE && nfl.global.debugenabled){ 
		try{ console.log(message); }catch(err){nfl.global.debugenabled	= false;}
	}else{ 
		if(Prototype.Browser.IE && nfl.global.debugenabled){ 
			try{
				$('nfl-debug-console-logger').options[$('nfl-debug-console-logger').options.length] = new Option(message,'');
				$('nfl-debug-console-logger').options[($('nfl-debug-console-logger').options.length - 1)].className = type;
				$('nfl-debug-console-logger').options[($('nfl-debug-console-logger').options.length - 1)].focus();
			}catch(err){nfl.global.debugenabled	= false;}}
	}}; nfl.log("loading nfl.js..");
/**
 * Defines the type of event model to use
 * This automatically sets itself to the style used
 * by the prototype library if it's available, otherwise
 * it uses livepipes custom object.extend methodology.
 */
//nfl.global.eventModel			= document.observe ? "prototype":"livepipe";  
nfl.global.eventModel			= "livepipe";
// ---------------------------- WARNING ----------------------------
// the property above is to allow us to do early compat testing. eventually 
// moving to the prototype 1.6 release once proper time for testing 
// has taken place. if you enable prototype 1.6 also enable the 1.8 release 
// of scriptaculous.

/** 
 * create simple 'nfl.events' object for global events 
 * or if eventModel == 'prototype' use prototype custom events
 * attached to the document object.
 */
nfl.events = Class.create(); nfl.events = {}; Object.Event.extend(nfl.events) ;

/**
 * Loads in the enviromental variables defined in the commons_js
 */
nfl.global.imagepath			= n_imagepath;
nfl.global.scriptpath			= n_scriptpath;
nfl.global.flashpath			= n_flashpath;
/**
 * Initialize nfl.util.cookies namespace 
 * Functions in this namespace are for cookie manipulation.
 */
nfl.namespace("util.cookies");
nfl.util.cookies.getExpDate		= function(days, hours, minutes) {var expDate = new Date( ); if(typeof days == "number" && typeof hours == "number" && typeof hours == "number") {expDate.setDate(expDate.getDate( ) + parseInt(days));expDate.setHours(expDate.getHours( ) + parseInt(hours));expDate.setMinutes(expDate.getMinutes( ) + parseInt(minutes));return expDate.toGMTString( );}}
nfl.util.cookies.getCookieVal	= function(offset){ var endstr = document.cookie.indexOf (";", offset); if (endstr == -1){endstr = document.cookie.length;}; return unescape(document.cookie.substring(offset, endstr));}
nfl.util.cookies.getCookie		= function(name) { var arg = name + "="; var alen = arg.length; var clen = document.cookie.length; var i = 0; while (i < clen) { var j = i + alen; if (document.cookie.substring(i, j) == arg) { return nfl.util.cookies.getCookieVal(j); }; i = document.cookie.indexOf(" ", i) + 1; if (i == 0) break; } return "";}
nfl.util.cookies.setCookie		= function(name, value, expires, path, domain, secure) { document.cookie = name + "=" + escape (value) + ((expires) ? "; expires=" + expires : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : "");}
nfl.util.cookies.deleteCookie	= function(name,path,domain) { if (nfl.util.cookies.getCookie(name)) { document.cookie = name + "=" + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + "; expires=Thu, 01-Jan-70 00:00:01 GMT";}}
var getExpDate					= nfl.util.cookies.getExpDate;
var getCookieVal				= nfl.util.cookies.getCookieVal;
var getCookie					= nfl.util.cookies.getCookie;
var setCookie					= nfl.util.cookies.setCookie;
var deleteCookie				= nfl.util.cookies.deleteCookie;

nfl.namespace('nfl.events');
/**
 * Simple onDOMReady function
 * @author ryan.cannon@nfl.com
 * @class DomReady
 */
nfl.events.DomReady = function() {
	var funcs = [];
	function _fire(func, args) { func.apply(window, args); }
	return {
		/**
		 * Add a DomReady callback
		 * @method add
		 * @param {Function} f the function to be called onDomReady
		 * @returns {number} the index of the added function
		 */
		add: function(f) {
			var l = funcs.length;
			funcs[l] = f;
			return l;
		},
		/**
		 * Add a DomReady callback before another callback
		 * @method addBefore
		 * @param {Function} f the function to be called onDomReady
		 * @param {Function} oldF the function before which to call f
		 * @returns {number} the index of the added function, -1 if not added.
		 */
		addBefore: function(f, oldF) {
			try {
				var i = nfl.events.DomReady.indexOf(oldF);
				if (i == -1) { return nfl.events.DomReady.add(f) }
				funcs.splice(i, 0, f);
				return i;
			}
			catch(e){ return -1 }
		},
		/**
		 * Find the index of a DomReady callback
		 * @method indexOf
		 * @param {Function} f the function to found
		 * @returns {number} the index of the function, -1 if not found.
		 */
		indexOf: function(f) { return funcs.indexOf(f) },
		/**
		 * Fire the DomReady method. Passes and arguments to all callbacks.
		 * @method fire
		 * @returns {boolean} true
		 */
		fire: function() {
			try{
				var a = $A(arguments);
				var f = function(func) { return _fire.call(window,func,a); }
				funcs.each(f);
				a = f = funcs = null;
				return true;
			}catch(e){}
		},
		/**
		 * Get the callback at an index
		 * @method item
		 * @param {number} the index of the function
		 * @returns {Function} f the function found
		 */
		item: function(i) { return funcs[i]; },
		/**
		 * Remove a callback
		 * @method remove
		 * @param {Function} f the function to remove
		 * @returns {Function} f the function removed
		 */
		remove: function(f) {
			funcs = funcs.without(f);
			return f;
		}
	}
}();
/*
 * This is a prototype library bridge(hack *cough*)
 * that plugs in prototype's "dom:loaded" event to 
 * our nfl.events.DomReady hook. this provides a 
 * reliable way to fire a contentReady event event in 
 * IE since prototype's built-in hack doesn't work 
 * reliably on our site.
 */
document.observe("dom:loaded",function(){
	nfl.events.DomReady.fire();
});
document.observe("dom:ready",function(){
	if(!document.ready){
		document.ready = true;
		document.fire("dom:beforeloaded");
	}
	if(!document.loaded){
		document.loaded = true;
		document.fire("dom:loaded");
	}
});

/**
 * Initialize nfl.ads namespace 
 */	
nfl.namespace("nfl.ads");
/**
 * Rotataing Ads Functionality
 * @author ryan.cannon
 * @module RotatingAds
 * @namespace nfl.ads
 */
nfl.ads.RotatingAds = function() {
	var executer, interval = 30, collection = [];
	function updateAd(Ad){ Ad.update() };
	function updateAds() { collection.each(updateAd); }
	function startRotation (e) {
		if (collection.length > 0) {
			executer = new PeriodicalExecuter(updateAds, interval);
			updateAds();
		}
	}
	return {
		/**
		 * Adds an add to the rotating collection. If no rotating ads exist
		 * it also starts the ad rotation.
		 * @method add
		 * @param {nfl.ads.RotatingAds.Ad Ad} The ad object to be rotated.
		 * @returns {number} the offset in the ad collection
		 */
		add: function(Ad) {
			count = collection.length;
			collection[count] = Ad;
			if (count == 0) { Event.observe(window, 'load', startRotation); }
			return count + 1;
		},
		/**
		 * Sets the rotation interval for all rotating ads on the page.
		 * @method setSpeed
		 * @param {number int} The speed in seconds at which the ads should rotate.
		 */
		setSpeed: function(spInt) { interval = spInt },
		/**
		 * Rotating Ad class 
		 * @class Ad
		 * @namespace nfl.ads.RotatingAds
		 */
		Ad: Class.create()
	}
}();
nfl.ads.RotatingAds.Ad.prototype = {
	/**
	 * Creates a dynamic iframe into which the ad should load
	 * and adds the ad into the rotating collection
	 * @method initialize
	 * @param {String | HTMLElement div} the container div for the ad.
	 * @param {String params} the ad params.
	 * @param {String | number width} the width of the ad.
	 * @param {String | number height} the height of the ad.
	 */
	initialize: function(div, params, options) {
		var el, count, url;
		el			= $(div);
		this.params	= params;
		this.rotate	= (typeof options.rotate == 'undefined')? false:options.rotate;
		count = nfl.ads.RotatingAds.add(this);
		this.id		= (el.id + '-iframe') || ("nfl-rotating-ad-" + count);
		//url = encodeURIComponent(this.params + ';ord=' + (Math.random() * 1000)) + '?';
		this.url	= 'http://ad.doubleclick.net/adi/'+ this.params +';ord=' + adRandom + '?';
		el.innerHTML = (options.transparent != true)?'<iframe src="'+ this.url +'" id="' + this.id + '" width="' + options.width + '" height="' + options.height + '" frameborder="0" scrolling="no"></iframe>':'<iframe src="'+ this.url +'" id="' + this.id + '" width="' + options.width + '" height="' + options.height + '" allowTransparency="true" frameborder="0" scrolling="no"></iframe>';
		el = null;
	},
	/**
	 * Reloads the ad.
	 * @method update
	 */
	update: function() { $(this.id).up().update($(this.id).up().innerHTML); nfl.log(this.id +' updated.'); }
}
nfl.ads.collection	= [];
nfl.ads.add	= function(Ad){
	if(Ad.rotate == true){
		count = nfl.ads.RotatingAds.collection.length;
		nfl.ads.RotatingAds.collection[count] = Ad;
		if (count == 0) { Event.observe(window, 'load', nfl.ads.RotatingAds.startRotation); }
	}else{
		count = nfl.ads.collection.length;
		nfl.ads.collection[count] = Ad;
	}
	return count + 1;
}
nfl.ads.Ad	= Class.create();
nfl.ads.Ad.prototype	= {
	initialize: function(div, params, options) {
		var el, count, url;
		el			= $(div);
		this.params	= params;
		this.rotate	= (typeof options.rotate == 'undefined')? false:options.rotate;
		count = nfl.ads.add(this);
		this.id		= (el.id + '-iframe') || ("nfl-rotating-ad-" + count);
		//url = encodeURIComponent(this.params + ';ord=' + (Math.random() * 1000)) + '?';
		this.url	= 'http://ad.doubleclick.net/adi/'+ this.params +';ord=' + adRandom + '?';
		el.innerHTML = (options.transparent != true)?'<iframe src="'+ this.url +'" id="' + this.id + '" width="' + options.width + '" height="' + options.height + '" frameborder="0" scrolling="no"></iframe>':'<iframe src="'+ this.url +'" id="' + this.id + '" width="' + options.width + '" height="' + options.height + '" allowTransparency="true" frameborder="0" scrolling="no"></iframe>';
		el = null;
	}
}
/**
 * Generates new random number 
 * for use in creating sets of ads.
 * @return {Integer}
 */
nfl.ads.random					= function(){ adRandom	= (Math.random() * 1000); return adRandom; };
nfl.ads.random();

/**
 * Image Preloading functions.
 */
nfl.namespace("nfl.util.images.preloader");
nfl.util.images.preloader.notFoundImg	= null;
nfl.util.images.preloader.checks		= {generic: function(image){ image.src = notFoundImg.src; }};
nfl.util.images.preloader.loadImages	= function(){ 
	var imagesToPreload = arguments; var preloadedImages = [];
	for(var i = 0; i < imagesToPreload.length; i++) { preloadedImages[i] = document.createElement('img'); preloadedImages[i].src = imagesToPreload[i];} return preloadedImages;
};
nfl.util.images.preloader.loadImages2	= function(){
	var imagesToPreload = arguments[0]; var preloadedImages = [];
	for(var i = 0; i < imagesToPreload.length; i++) { preloadedImages[i] = new Image(); preloadedImages[i].src = imagesToPreload[i]; } return preloadedImages;
};
nfl.util.images.preloader.loadImages3	= function() {
	var imagesToPreload = arguments[0]; var preloadedImages = [];
	for(var i = 0; i < imagesToPreload.length; i++) { var c = i + 1; $('sr_image' + c).src = imagesToPreload[i]; } return preloadedImages;
};
var preloadImages		= nfl.util.images.preloader.loadImages; var preloadImages2	= nfl.util.images.preloader.loadImages2; var preloadImages3	= nfl.util.images.preloader.loadImages3;
/**
 * Open a new pop up window.
 * @param {string} url the url of the window.
 * @param {string} panelName the name of the window.
 * @param [{object}] an object containing key-value pairs of window attributes to overide the defaults
 */
nfl.util.openPopWindow	= function(url, name){
	var win_args		= '';
	var win_options		= {width:800,height:600,toolbar:0,scrollbar:'auto'}
	if(typeof arguments[2] == 'object'){
		for(var argName in arguments[2]) { win_options[argName] = arguments[2][argName]; }
		for(var argName in win_options) { win_args += (argName+"="+win_options[argName]+","); }
		win_args		= win_args.substring(0,(win_args.length - 1));
	}
	if(typeof arguments[2] == 'number' && typeof arguments[3] == 'number'){
		win_args		= 'width='+ arguments[2] +',height='+ arguments[3] +',toolbar=0,scrollbar=auto';
	}
	if(typeof arguments[2] == 'string'){
		win_args		= arguments[2];
	}
	var win				= window.open(url,name,win_args);
	win.focus();
};
var $openWindow			= nfl.util.openPopWindow; //shorthand pointer
/**
 * Methods for creating and updating the scorestrip
 * @author ryan.cannon
 * @namespace nfl.global
 * @class Scorestrip
 * @requires swfobject, nfl
 */
nfl.global.Scorestrip = Class.create();
nfl.global.Scorestrip.prototype = {
	/**
	 * Adds the scorestrip to the page
	 * @param {String} weekColor Hex numer for the text color of the current week defaults to "FFFFFF
	 * @param {String} scheduleColor Hex numer for the text color of the schedules link
	 * @param {String} ssID ID of the element to write the scoretrip to, defaults to 'fo_scorestrip'
	 * @param {Hash} options Overwrites any default options.
	 * @returns {String} The ID of the element to which the scorestrip was written.
	 */
	initialize: function(divID, options) {
		this.ssID 	= 'fo_scorestrip';
		this.opts	= options;
	 	this.write();
	},
	write: function(){
		/* this is a hack */
		var pageDomain = 'http://' + window.document.domain;
		if (pageDomain.indexOf("localhost") != -1) pageDomain += ":8080";
		/* end this hack */
	 	var o = $H({
	 		id: this.ssID,
			flashVars: {
				baseURL: pageDomain
			},
			params: { wmode: "transparent" },
			width: '870',
			height: '115',
			version: "8",
			background: "#FFFFFF"
		});
		this.flash = new nfl.media.Flash('http://static.nfl.com/static/site/flash/scorestrip.swf', "header-scorestrip", o.merge($H(this.opts))); 
		/* checked against prototype 1.6.0.2 */
	},
	getID: function() { return this.ssID },
	getFlash: function() { return this.flash },
	reload: function() {
		$("header-scorestrip").update();
		this.write();
	}
};
/**
 * Provides constants for observing and firing authentication events
 * Authentication events should be fired with a "component"
 * 
 * @namespace nfl.events
 * @class AuthenticationEvent
*/
nfl.events.AuthenticationEvent = function () {
	var AE, prefix;
	prefix = 'nfl:authentication:';
	AE = { SIGN_IN: prefix + 'signin', SIGN_OUT: prefix + 'signout', AUTH_FAILURE: 'authfailure' };
	// monitor events
	if (window.console) {
		function logger(event) { console.log('AuthenticationEvent: ' + event.eventName); console.log(event.memo); }
		for (var i in AE) { document.observe(AE[i], logger);}
	}
	return AE;
}();
/**
 * The Authentication class provides static methods to get/set/clear cookies 
 * associated with a user. Fires an AuthenticationEvent when either 
 * set or clear is called. e.g.:
 * 
 * document.observe(nfl.events.AuthenticationEvent.SIGN_IN, doSomething);
 *
 * @namespace nfl.global
 * @class Authentication
 */
nfl.global.Authentication = function () {
	var AuthenticationEvent = nfl.events.AuthenticationEvent;
	var Cookies			= { USER: 'userId', SITELIFE: 'at', FAVORITE_TEAM: 'favoriteTeam' };
	var $C				= nfl.util.cookies;
	var COMPONENT		= 'AuthenticationEvent';
	var DOMAIN			= document.domain;
	var PATH			= '/';
	var COOKIE_SIGN_IN	= 'CookieSignIn';

	var cookie, team, username;

	cookie			= $C.getCookie(Cookies.USER).toQueryParams();
	if (cookie.u) {
		team			= decodeURIComponent(cookie.t);
		username		= decodeURIComponent(cookie.u);
	}
	document.observe('dom:loaded', initialize);
	document.observe(AuthenticationEvent.SIGN_OUT, onSignOut);

	// Listens for dom:loaded event
	function initialize (e) {
		if (is_authenticated()) {
			document.fire(AuthenticationEvent.SIGN_IN, { component: COOKIE_SIGN_IN, username: username, team: team });
		}
		else if ($C.getCookie(Cookies.USER) && ! $C.getCookie(Cookies.SITELIFE)) {
			$C.deleteCookie(Cookies.FAVORITE_TEAM, PATH);
			$C.deleteCookie(Cookies.USER, PATH);
		}
	}

	// Returns bool if user is authenticated or not
	function is_authenticated() { return !! username; }

	// Listener for a SIGN_OUT event
	function onSignOut(e) {
		username = team = null;
		/* delete cookies for site */
		$C.deleteCookie(Cookies.USER, PATH, DOMAIN);
		$C.deleteCookie(Cookies.SITELIFE, PATH, DOMAIN);
	}

	return {
		signOut: function() { document.fire(AuthenticationEvent.SIGN_OUT, { component: COMPONENT });},
		isAuthenticated: function() { return is_authenticated();},
		getUser: function() { return is_authenticated() ? { username: username, team: team } : null; }
	};
}();
/**
 * The Header class observes AuthenticationEvents and updates the
 * login/logout buttons that appear in most site headers.
 *
 * @namespace nfl.global
 * @class Header
 * @requires nfl.global.Authentication
 */
nfl.global.Header = function(){
	var AuthenticationEvent = nfl.events.AuthenticationEvent;
	var ID = {
		LIST:		'hd-micro-nav-list',
		SIGN_IN:	'link-user-sign-in',
		SIGN_OUT:	'link-user-sign-out',
		REGISTER:	'link-user-register',
		PROFILE:	'link-user-profile'
	};
	// Retrieves the last section of the url before a query string
	var USER_REGEXP = /\/([^\/\?#]*)(([#\?][^#\?]*){0,2})$/;
	var initialized = false;

	document.observe(AuthenticationEvent.SIGN_IN, onSignIn);
	document.observe(AuthenticationEvent.SIGN_OUT, onSignOut);
	document.observe('dom:loaded', initialize);

	function initialize() {
		if (! $(ID.LIST)) { return killHeaderLinks();}

		// Hide the sign out info if it hasn't yet been addressed
		if (! initialized) { onSignOut(); }
		initialized = true;
	}
	function onSignIn(e) {
		try {
			var profile, profileLink;
			profile				= $(ID.PROFILE);
			profileLink			= profile.select('a').first();
			profileLink.href	= profileLink.href.replace(USER_REGEXP, "/" + e.memo.username + "$1");

			initialized = true;

			$(ID.SIGN_IN, ID.REGISTER).invoke('hide');
			$(ID.SIGN_OUT, profile).invoke('show');
		}
		catch(e) { killHeaderLinks(e);}
	}
	
	function onSignOut() {
		try {
			var profile, profileLink;
			profile				= $(ID.PROFILE);
			profileLink			= profile.select('a').first();
			profileLink.href	= profileLink.href.replace(USER_REGEXP, "/$1");

			$(ID.SIGN_IN, ID.REGISTER).invoke('show');
			$(ID.SIGN_OUT, profile).invoke('hide');
		}
		catch(e) { killHeaderLinks(e); }
	}
	function killHeaderLinks(e) {
		nfl.log("nfl.global.Header could not locate loginButtons");
		nfl.log(e);
		document.stopObserving(AuthenticationEvent.SIGN_IN, onSignIn);
		document.stopObserving(AuthenticationEvent.SIGN_OUT, onSignOut);
	}
	function replace_return(path) {
		return function (el) {
			el.href = el.href.replace(/returnTo=([^#&]*)/, 'returnTo=' + encodeURIComponent(path));
		}
	}
	return {
		setReturnToURLs: function(path) {
			$$('#' + ID.LIST + ' li a').each(replace_return(path));
		}
	}
}();
/**
 * Adds decorating <div> elements
 * @namespace nfl.global
 * @class Decorators
 */
nfl.global.Decorators = function() {
	// initialize at page load
	// Event.observe(window,'load', function() { initialize() });
	//document.observe("dom:loaded",initialize);
	//nfl.events.DomReady.add(initialize);
	document.observe('dom:loaded',initialize);
	
	function initialize() {
		var el = $('copyright');
		if (! el) { return;}
		nfl.global.Decorators.add(el, ['bl', 'br'], false);
		var els = $$('div.shadowed').each(nfl.global.Decorators.add);
	}
	return {
		/**
		 * Adds empty divs to an element in order to add decoration
		 * @method add
		 * @param {String | HTMLElement} el the element to add decoration
		 * @param {Array} classNamesArray array of classNames for the decorating divs. default: ['b', 'r', 'tr', 'br', 'bl']
		 * @param {boolean} wrap whether the element should be wrapped in a container
		 */
		add: function(el, classNamesArray, wrap) {
			var c, d, e, h, w;
			w = (typeof wrap == 'undefined') ? true : wrap;
			c = classNamesArray || ['b', 'r', 'tr', 'br', 'bl'];
			h = '<div class="' + c.join('"></div><div class="') + '"></div>';
			e = $(el);
			if (w) {
				d = document.createElement('div');
				d.className = "has-shadow";
				d.innerHTML = h;
				if (e.id) { d.id = e.id + "-wrap" }
				e.parentNode.insertBefore(d, e);
				d.insertBefore(e, d.firstChild);
			}
			else {
				e.innerHTML += h;
				e.addClassName('has-shadow');
			}
			return true;
		}
	}
}();
/**
 * The Footer class inserts a Flash footer with dynamic text and text color into
 * the document.
 *
 * @namespace nfl.global
 * @class Footer
 */
nfl.global.Footer = Class.create();
nfl.global.Footer.prototype = {
	initialize: function(id) {
		this.textColor = "#FFFFFF";
		this.id = id;
	},
	setTextColor: function(c) {
		this.textColor = c;
		return this;
	},
	write: function() {
		var so, el, text;
		el = $(this.id);
		text = (el.innerText || el.textContent).strip().toUpperCase();
		new nfl.media.Flash(nfl.global.imagepath + "/flash/footer.swf", el, $H({
			width: "705",
			height: "25",
			version: "8",
			background: "#000000",
			params: $H({ wmode: "transparent"}),
			flashVars: $H({
				debug: true,
				allowFullScreen: false,
				footerText: text,
				textColor: this.textColor
			})
		}));
		el = null;
	}
};
/**
 * The CenterPiece module inserts a Flash centerpiece of various sizes into
 * the document.
 *
 * @namespace nfl.global
 * @class CenterPiece
 */
nfl.global.CenterPiece = Class.create();
nfl.global.CenterPiece.prototype = {
	/**
	 * Constructor for the CenterPiece class.
	 * @constructor
	 * @param {String}  type The type of CenterPiece. Accepted vaults are
	 *                  "normal", "wide" and "extra-wide".
	 *                  the window object.  The listener can override this.
	 * @param {String}  flashURL path to the Flash file for the centerpiece.
	 * @param {String}  subjectType The subjecType of the page calling the
	 *                  Centerpiece (normal only).
	 * @param {String}  modifiedDate The date the centerpiece content was
	 *                  modified (normal only).
	 * @param {Object}	options An associated array used to override any
	 * 					defaults in the CenterPiece.
	 */
	initialize: function(divID, type, flashURL, subjectType, modifiedDate, options) {
		var width, so, div, anchor;
		div = $(divID);
		div.addClassName("cp-" + this.type);
		var o = $H({
			width: ((type == "extra_wide") ? "965" : (type == "wide") ? "660" : "408"),
			height: "325",
			version: "8.0",
			background: "#FFFFFF",
			params: { wmode: (this.type == "normal") ? 'opaque' : 'transparent' },
			flashVars: $H({ IMAGEPATH: nfl.global.imagepath }),
			playerVolume: 50,
			pauseSeconds: 10
		});
		if (type == "normal") {
			var tmpO	= o.get('flashVars');
			tmpO.set("playerXmlUrl","/widget/centerpiece?subjectType=" + encodeURIComponent(subjectType));
			tmpO.set('modifiedDate',modifiedDate);
			tmpO.set("playerVolume",o.get('playerVolume'));
			tmpO.set("pauseSeconds",o.get('pauseSeconds'));
			o.set('flashVars',tmpO);
		}
		this.flash = new nfl.media.Flash(flashURL, div, o.merge($H(options || {})));
	},
	getFlash: function() { return this.flash }
}
nfl.namespace("nfl.media");
nfl.media.Flash = Class.create();
nfl.media.Flash.prototype = {
	initialize: function(url, el, options) {
		var so, id, o, fID;
		id = (typeof el == 'string') ? el : el.id;
		fID = id.replace(/-/g, "") + "Flash";
		o = $H({ id: fID, width: "550", height: "400", version: "8", background: "#FFFFFF" }).merge($H(options)); /* checked against prototype 1.6.0.2 */
		this.fid = o.get('id');
		if ($(this.fid)) { throw("Cannot embed Flash movie: Element with the id \"" + this.fid + "\" already exists."); }
		var optParams	= new Hash();
		var optVars		= new Hash();
		nfl.log("typeof options = "+ (typeof options));
		if((typeof options == 'object') && options.get){
			if(typeof options.get('params') == 'object'){
				optParams	= $H(options.get('params'));
				optVars		= $H(options.get('flashVars'));
			}else{
				try{
					optParams = $H(options['params'])
				}catch(e){}
			}
		}
		o.set('params',$H({ allowScriptAccess: "always", wmode: "opaque" }).merge(optParams)); /* checked against prototype 1.6.0.2 */
		o.set('flashVars', optVars);
		so = new SWFObject(url, this.fid, o.get('width') + "", o.get('height') + "", o.get('version') + "", o.get('background'));
		o.get('params').each(function(pair) { so.addParam(pair.key, pair.value) });
		o.get('flashVars').each(function(pair) { so.addVariable(pair.key, encodeURIComponent(pair.value)) });
		so.write(id);
		so = null;
	},
	getMovie : function(){
		return (navigator.appName.indexOf("Microsoft") != -1)?
			function() { return window[this.fid] } :
			function() { return document[this.fid] }
	}(),
	exec: function(s) { this.getMovie()[s]();}
}
/* event logging */
document.observe('dom:loaded',function(){ nfl.log("{dom:loaded}"); });
document.observe('dom:beforeloaded',function(){ nfl.log("{dom:beforeloaded}"); });
document.observe('dom:ready',function(){ nfl.log("{dom:ready}"); });
document.observe('window:hashchange',function(){ nfl.log("{window:hashchange}"); });

nfl.namespace("nfl.bandages");
nfl.bandages.IE6BackgroundImageFix = (function(){
	if (Prototype.Browser.IE && navigator.appVersion.indexOf('MSIE 6.0')!=-1) {
		try { document.execCommand("BackgroundImageCache", false, true); }
		catch(err) { return false; }
		return true;
	}
	else return false;
})();
nfl.bandages.IE6HeaderFixes = Class.create();
nfl.bandages.IE6HeaderFixes.prototype = {
	initialize: function (options) {
		if (navigator.appVersion.indexOf('MSIE 6.0')==-1) { return }
		try{
			/*	<iframe id="DivShim" scrolling="no" frameborder="0"></iframe> */
			var iframe = document.createElement('iframe');
			iframe.id = "DivShim";
			iframe.setAttribute("scrolling","no");
			iframe.setAttribute("frameborder","0");
			nfl.bandages.IE6NavigationId = (typeof options['navId'] == 'undefined')?'nav':options['navId']; 	
			var nav = document.getElementById(nfl.bandages.IE6NavigationId);
			nav.parentNode.insertBefore(iframe, nav);
			var sfEls = nav.getElementsByTagName("LI");
			for (var i=0; i<sfEls.length; i++) {
				sfEls[i].onmouseover=onRollOver;
				sfEls[i].onmouseout=onRollOut;
			}
		} catch(err){}
		Event.observe(window, 'unload', cleanup);
		iframe = nav = sfEls = null;
		function cleanup(e) {
			var sfEls = document.getElementById(nfl.bandages.IE6NavigationId).getElementsByTagName("LI");
			for (var i=0; i<sfEls.length; i++) {
				sfEls[i].onmouseover = null;
				sfEls[i].onmouseout = null;
			}
			sfELs = null;
		}
		function ie6CoverDropDowns(menuButton, newState) {
			if(newState == 'mouseover') {
			   var DivRef = menuButton.getElementsByTagName("UL")[0];
			   var IfrRef = document.getElementById('DivShim');
			    DivRef.style.display = "block";
			    IfrRef.style.top = DivRef.offsetTop;
			    IfrRef.style.left = DivRef.offsetLeft;
			    IfrRef.style.width = DivRef.offsetWidth;
			    IfrRef.style.height = DivRef.offsetHeight;
			    IfrRef.style.zIndex = DivRef.style.zIndex + 1;
			    IfrRef.style.display = "block";
				if ( menuButton.getElementsByTagName("UL").length > 1 ) //for the teams drop down which is two ULs
				{
				   var DivRef2 = menuButton.getElementsByTagName("UL")[1];
				    DivRef2.style.display = "block";
				    IfrRef.style.width = (DivRef.offsetWidth + DivRef2.offsetWidth) - 1;  // the second UL for teams overflaps the first one, so the -1 removes a not so pretty white line next to the that dropdown in ie6
				}
		
			} else {
			   var DivRef = menuButton.getElementsByTagName("UL")[0];
			   var IfrRef = document.getElementById('DivShim');
			    DivRef.style.display = "none";
			    IfrRef.style.display = "none";
				if ( menuButton.getElementsByTagName("UL").length > 1 ) //for the teams drop down which is two ULs
				{
				   var DivRef2 = menuButton.getElementsByTagName("UL")[1];
				    DivRef2.style.display = "none";
				}
			}
		}
		function onRollOver(e) {
			if(!($(this).hasClassName("sfhover"))){ $(this).addClassName("sfhover"); }
			if((this.parentNode.id==nfl.bandages.IE6NavigationId) && (this.getElementsByTagName("UL").length != 0) ){ ie6CoverDropDowns(this, 'mouseover'); }
		}
		function onRollOut(e){
			if($(this).hasClassName("sfhover")){ $(this).removeClassName("sfhover"); }
			if((this.parentNode.id==nfl.bandages.IE6NavigationId) && (this.getElementsByTagName("UL").length != 0) ){ ie6CoverDropDowns(this, 'mouseout'); }
		}
	}
};
nfl.bandages.IE6FooterFixes = function(){
	if (Prototype.Browser.IE && navigator.appVersion.indexOf('MSIE 6.0')!==-1) {
		function getAlphaImageLoader(path) {
			return "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + nfl.global.imagepath + path + "')";
		}
		try {
			$('ft-teams-afc-mark').style.filter = getAlphaImageLoader('/img/global/ft-teams-marks-ie6-afc.png');
			$('ft-teams-nfc-mark').style.filter = getAlphaImageLoader('/img/global/ft-teams-marks-ie6-nfc.png');
			$('ft-teams-afc-mark-container').select('div.ft-teams-parenthesis').first().style.filter = getAlphaImageLoader('/img/global/ft-teams-marks-ie6-brace.png');
			$('ft-teams-nfc-mark-container').select('div.ft-teams-parenthesis').first().style.filter = getAlphaImageLoader('/img/global/ft-teams-marks-ie6-brace.png');
		}
		catch(err) {}
	}
};
