var ST = {
	Callback:{},
	AddLoadEvent:function(func){
		var oldOnLoad = window.onload;
		if (typeof window.onload != 'function'){
	    	window.onload = func;
		} else {
			window.onload = function(){
				oldOnLoad();
				func();
			}
		}
	},
	PopUp:{
		types:{
			'popup':"width=860,height=560,left="+ ((screen.availWidth - 860) /2) + ",top=" + (((screen.availHeight - 560) /2) - 16) + ",scrollbars=no,menubar=no,resizable=yes,location=no",
			'popupscroll':"width=877,height=577,left="+ ((screen.availWidth - 877) /2) + ",top=" + (((screen.availHeight - 577) /2) - 16) + ",scrollbars=yes,menubar=no,resizable=yes,location=no",
			'slideshowpopup':"width=750,height=675,left="+ ((screen.availWidth - 750) /2) + ",top=" + (((screen.availHeight - 675) /2) - 16) + ",scrollbars=no,menubar=no,resizable=yes,location=no",
			'footerpopup':"width=620,height=500,left="+ ((screen.availWidth - 620) /2) + ",top=" + (((screen.availHeight - 500) /2) - 16) + ",scrollbars=yes,menubar=no,resizable=yes,location=no"
		},
		Add:function(element){
			if( !element ) return false;
			
			//get the type we need
			if( !ST.PopUp.types[ element.className ] ) return false;

			//assign the link everything it needs
			if( !element.target ) element.target = element.className;
			element.onclick = ST.PopUp.Open;
		},
		Open:function(){
			if( !ST.PopUp.types[this.target] ) return false;
			
			newWin = window.open(this.href, this.target, ST.PopUp.types[this.target]);
			newWin.focus();
			return false;
		}
	},
	AddScript:function(params){
		//Add script to the head.  Typically used for adding cross [sub]domain JS where AJAX
		//like functions will not work.
	
		if( !params.URI ) return false;
		
		if( params.overwriteId ){
			var scriptObj = document.getElementById(params.overwriteId);
			if( scriptObj != null ){
				scriptObj.parentNode.removeChild(scriptObj);
				delete scriptObj;
			}
		}
	
		var scriptObj = document.createElement('script');
		scriptObj.setAttribute('type', 'text/javascript');
		scriptObj.setAttribute('src', params.URI);
		if( params.overwriteId ) scriptObj.id = params.overwriteId;
		document.getElementsByTagName('head')[0].appendChild(scriptObj);
		return;
	},
	ImageCarousel:function(container){
		if( !container ) return false;
		
		var thisImageCarousel = this;
		
		thisImageCarousel.imageIds =new Array();
		thisImageCarousel.currentImage = 0;
		thisImageCarousel.totalImages = 0;
		var imageHeight = 0;
		try {
			var allDivs = container.getElementsByTagName('div');
			for (var elementNumber = 0; elementNumber < allDivs.length; elementNumber++) {
				switch( allDivs[elementNumber].className ){
					case "ImageDiv":
						thisImageCarousel.imageIds[thisImageCarousel.totalImages] = allDivs[elementNumber].id;
						thisImageCarousel.totalImages++;
						//get the max height across all images
						if (allDivs[elementNumber].offsetHeight > imageHeight) {
							imageHeight = allDivs[elementNumber].offsetHeight;
						}
						//hide it
						allDivs[elementNumber].style.display = 'none';
						break;
					case 'ImageBox':
						thisImageCarousel.ImageBox = allDivs[elementNumber];
				}
			}
			thisImageCarousel.totalImages--;
			
			var allAnchors = container.getElementsByTagName('a');
			for (var elementNumber = 0; elementNumber < allAnchors.length; elementNumber++) {
				switch( allAnchors[elementNumber].className ){
					case 'next_button':
						allAnchors[elementNumber].onclick = function(){ thisImageCarousel.Rotate('+'); };
						break;
					case 'previous_button':
						allAnchors[elementNumber].onclick = function(){ thisImageCarousel.Rotate('-'); };
						break;
				}
			}

			if (thisImageCarousel.imageIds[0]) {
				document.getElementById(thisImageCarousel.imageIds[0]).style.display = 'block';
				thisImageCarousel.ImageBox.style.height = imageHeight + "px";
				if (thisImageCarousel.totalImages >= 1) {
					document.getElementById("ImageControl").style.display = 'block';
					ST.ReplaceContent("ImageNumber","1");
					ST.ReplaceContent("TotalImages",thisImageCarousel.totalImages + 1);
				}
				thisImageCarousel.ImageBox.style.visibility = 'visible';
			}
		} catch(error) {
			return false;
		}
		
		thisImageCarousel.Rotate = function(direction) {
			if ((direction == "+") || (direction == "1")) {
				thisImageCarousel.currentImage++;
				if (thisImageCarousel.currentImage > thisImageCarousel.totalImages) {
					thisImageCarousel.currentImage = 0;
				}
			} else if (direction == "-") {
				thisImageCarousel.currentImage--;
				if (thisImageCarousel.currentImage < 0) {
					thisImageCarousel.currentImage = thisImageCarousel.totalImages;
				}
			}
			for (var imageNumber = 0; imageNumber <= thisImageCarousel.totalImages; imageNumber++) {
				document.getElementById(thisImageCarousel.imageIds[imageNumber]).style.display = 'none';
			}
			document.getElementById(thisImageCarousel.imageIds[thisImageCarousel.currentImage]).style.display = 'block';
			ST.ReplaceContent("ImageNumber",thisImageCarousel.currentImage + 1);
		}
	},
	Map:function(elementId,latitude,longitude,description,icon,mapCallback) {
		try {
			var element = document.getElementById(elementId);
		} catch(error) {
			return false;
		}

		if (! latitude) { return false; }
		if (! longitude) { return false; }
		
		thisMap = this;

		thisMap.AddMarker = function(latitude,longitude,description,icon,zIndex) {
			var point = new GLatLng(latitude,longitude);
			var marker = new Marker(point,description,icon,zIndex);
			map.addOverlay(marker);
		}

		function Icon(image) {
			var icon = new GIcon();
			icon.image = "/art/maps/icons/" + image; 
			icon.iconAnchor = new GPoint(16,16);
			icon.infoWindowAnchor = new GPoint(16,0);
			icon.iconSize = new GSize(22,32);
			return icon;
		}

		function Marker(point,description,image,zIndex) {
			var markerOptions = { zIndexProcess:GetZIndex };
			if (image) {
				var icon = new Icon(image);
				markerOptions = { icon:icon,zIndexProcess:GetZIndex };
			}

			var marker = new GMarker(point,markerOptions);
			marker.zIndex = zIndex;
			if (description) {
				var html = "<div>" + decodeURIComponent(description) + "</div>";
				GEvent.addListener(marker,"click",function() {
					marker.openInfoWindowHtml(decodeURIComponent(description));
				});
			}

			return marker;
		}

		function GetDistance(sourceLatitude,sourceLongitude,destinationLatitude,destinationLongitude) {
			var radiusEarth = 6371; // kilometers

			function DegreesToRadians(degrees) {
				return degrees * Math.PI / 180;
			}

			sourceLatitude = DegreesToRadians(sourceLatitude);
			sourceLongitude = DegreesToRadians(sourceLongitude);
			destinationLatitude = DegreesToRadians(destinationLatitude);
			destinationLongitude = DegreesToRadians(destinationLongitude);

			var distance = Math.acos(Math.sin(sourceLatitude) * Math.sin(destinationLatitude) + Math.cos(sourceLatitude) * Math.cos(destinationLatitude) * Math.cos((destinationLongitude - sourceLongitude))) * radiusEarth;
			return distance; // kilometers
		}

		function GetZoomForDistance(distance) {
			var distanceMaximum = 18000; // kilometers
			var zoomMinimum = 1;
			var zoomMaximum = 14;

			var zoom = zoomMaximum - ((zoomMaximum - zoomMinimum) * (distance / distanceMaximum));
			zoom = (zoom > 0 ? Math.floor(zoom) : Math.ceil (zoom));
			return zoom;
		}

		function GetZIndex(marker,unused) {
			return GOverlay.getZIndex(marker.getPoint().lat()) + marker.zIndex * 1000000;
		}

		if( !ST.Callback.Map ) ST.Callback.Map = new Array;
		ST.Callback.Map[elementId] = function() {
			// delay map load for slow browsers
			setTimeout(function() {
				var homeLatitude = 47.620716; // degrees
				var homeLongitude = -122.347533; // degrees
				var zoom = GetZoomForDistance(GetDistance(homeLatitude,homeLongitude,latitude,longitude));

				this.map = new GMap2(element);

				var center = new GLatLng(latitude,longitude);
				map.addControl(new GSmallMapControl());
				map.setCenter(center,zoom);

				var marker = new Marker(center,description,icon,100);
				map.addOverlay(marker);

				if (mapCallback) {
					mapCallback();
				}
			},300);
		}

		//Safari can't handle multiple callbacks at once, so we need to space them out.
		if( !ST.MapCallBackCounter ) ST.MapCallBackCounter = 0;
		ST.MapCallBackCounter++;
		setTimeout(function(){
			ST.AddScript({'URI':"http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAiwQtnpn7b2hCLsfhsf9inxT4-dzEtyrooIDu8E6uHITdmt7QKxT95xaBl3RAWIx3hTPW_cYH2nmGlg&async=2&callback=ST.Callback.Map."+elementId});
		}, 600*ST.MapCallBackCounter);
	},
	ReplaceContent:function(elementId,content) {
		try {
			var element = document.getElementById(elementId);
		} catch(error) {
			return false;
		}
		if( !element ){
			return false;
		}

		if (document.all) {
			element.innerHTML = content;
		} else {
			while (element.hasChildNodes()) { element.removeChild(element.lastChild); }
			var range = document.createRange();
			range.setStartAfter(element);
			var fragment = range.createContextualFragment(content);
			element.appendChild(fragment);
		}
	},
	Slider:function(container){
		if( !container ) return false;

		//variable to maintain scope
		var thisSlider = this;
	
		thisSlider.loop = function(params){
			thisSlider.timeoutId = setTimeout( function(){ thisSlider.slide(params); }, thisSlider.delay);
		}

		//find our key pieces
		var containerDivs = container.getElementsByTagName('div');
		for( var currDiv = 0; currDiv < containerDivs.length; currDiv++ ){
			if( containerDivs[currDiv].className.match(/\bleft_button\b/) ){
				thisSlider.leftButton = containerDivs[currDiv];
			}
			else if( containerDivs[currDiv].className.match(/\bright_button\b/) ){
				thisSlider.rightButton = containerDivs[currDiv];
			}
			else if( containerDivs[currDiv].className.match(/\bslider\b/) ){
				thisSlider.sliderBox = containerDivs[currDiv];
			}
			else if( containerDivs[currDiv].className.match(/\bslider_container\b/) ){
				thisSlider.sliderContainer = containerDivs[currDiv];
			}
		}
	
		//the slider width is initially set to a rediculous width because CSS is 
		//dumb, and IE is dumber.  Calculate and set the correct width.
		var numTiles = 0;
		var tileWidth = 0;
		var currChild = thisSlider.sliderBox.firstChild;
		while( currChild ){
			if( currChild.className == 'tile' ) {
				numTiles++;
				//while where are here, let's get the width of the tiles
				if( !tileWidth ) {
				
					//ghetto cross browser margin detection
					if( currChild.currentStyle ){
						var marginLeft = currChild.currentStyle['marginLeft'];
					}else if( window.getComputedStyle ){
						var marginLeft = document.defaultView.getComputedStyle(currChild,null).getPropertyValue('margin-left');
					}
					if( currChild.currentStyle ){
						var marginRight = currChild.currentStyle['marginRight'];
					}else if( window.getComputedStyle ){
						var marginRight = document.defaultView.getComputedStyle(currChild,null).getPropertyValue('margin-right');
					}
					marginLeft = parseInt(marginLeft.replace(/px/, ''));
					marginRight = parseInt(marginRight.replace('px', ''));
					tileWidth = currChild.offsetWidth + marginLeft + marginRight;
				}
			}
			currChild = currChild.nextSibling;
		}
		thisSlider.sliderBox.style.width = (numTiles*tileWidth +10) + 'px';/*I hate IE++*/
	
		//calculate the max left-ward scroll (don't want to scroll all the way.  abcde[fghi] vs abcdefghi[    ])
		thisSlider.leftScrollLimit = numTiles*tileWidth +20 -thisSlider.sliderContainer.offsetWidth;
	
		//assign controls
		thisSlider.rightButton.onmouseover = function(){
			this.className = this.className.replace(/\bright_button_off\b/, 'right_button_on');
			thisSlider.slide({'direction':'right', 'speed':'fast'});
		}
		thisSlider.rightButton.onmouseout = function(){
			this.className = this.className.replace(/\bright_button_on\b/, 'right_button_off');
			thisSlider.slide({'direction':'left', 'speed':'slow'});
		}
		thisSlider.leftButton.onmouseover = function(){
			this.className = this.className.replace(/\bleft_button_off\b/, 'left_button_on');
			thisSlider.slide({'direction':'left', 'speed':'fast'});
		}
		thisSlider.leftButton.onmouseout = function(){
			this.className = this.className.replace(/\bleft_button_on\b/, 'left_button_off');
			thisSlider.slide({'direction':'left', 'speed':'slow'});
		}
		thisSlider.sliderContainer.onmouseover = function(){
			thisSlider.slide({ 'direction':'stop' });
		}
		thisSlider.sliderContainer.onmouseout = function(){
			thisSlider.timeoutId = setTimeout(function(){
				thisSlider.slide({'direction':'left', 'speed':'slow'}),
				1000
			});
		}
	
		//this is the function that does the actual moving, and is the only thing that that should recur
		thisSlider.slide = function(params){
			if( params.direction != 'left' && params.direction != 'right' && params.direction != 'stop' && params.direction != 'restart' ){
				return false;
			}
		
			//blast out any previous timer
			if( thisSlider.timeoutId ) clearTimeout(thisSlider.timeoutId);
		
			//if we are stopping (pausing) the scroll, stop now
			if( params.direction == 'stop' ) return true;
		
			//get the current position of the sliding box
			var oldPos = this.sliderBox.style.left;
			if( !oldPos ) oldPos = '0px';
			oldPos = parseInt(oldPos.replace('px', ''));

			//calculate the new position
			if( params.direction == 'left' ){
				var newPos = oldPos - 1;
				//This next part is kludgey.  This creates a slight pause before resetting the 
				//slider.  The timeout controls the next occurence; we can't just sleep.  Instead
				//we have to load the timer to restart on the next run, and then abort.
				if( newPos*-1 >= thisSlider.leftScrollLimit ) {
					thisSlider.timeoutId = setTimeout( function(){ 
						thisSlider.slide({'direction':'restart', 'speed':params.speed }); 
					}, 3000);
					return true;
				}
			}else if( params.direction == 'right'){
				var newPos = oldPos+1;
				//if we have scrolled all the way to the beginning, stop
				if( newPos >= 0 ) return true;
			}else if( params.direction == 'restart' ){
				newPos = 0;
				params.direction = 'left';
			}
		
			//determine the timeout delay
			switch( params.speed ){
				case 'fast':
					thisSlider.delay = 1;
					break;
				case 'slow':
				default:
					thisSlider.delay = 70;
					break;
			}
		
			//move, and set it to recur
			thisSlider.sliderBox.style.left = newPos + 'px';
			thisSlider.loop(params);
		}
	
		//start it off
		thisSlider.slide({'direction':'left', 'speed':'slow'});
	},
	Tabs:function(){},//deprecated
	TabSet:function(container) {
		if( !container ) return false;
		
		//variable to maintain scope
		var thisTabSet = this;
		
		thisTabSet.contentElements = new Array();
		thisTabSet.labelElements = new Array();
		
		// collect content and label elements.
		var labelCounter = 0;
		var contentCounter = 0;
		var tabElements = container.getElementsByTagName("DIV");
		for (var tabKey in tabElements) {
			switch( tabElements[tabKey].className ){
				case 'st_tabs_label_on':
				case 'st_tabs_label_off':
					tabElements[tabKey].labelCounter = labelCounter;
					tabElements[tabKey].onclick = function(){ thisTabSet.SelectTab(this.labelCounter) };
					thisTabSet.labelElements.push(tabElements[tabKey]);
					labelCounter++;
					break;
				case 'st_tabs_content':
					thisTabSet.contentElements[ contentCounter ] = tabElements[tabKey];
					contentCounter++;
					break;
			}
		}
		
		//the function assigned to the labels
		thisTabSet.SelectTab = function(tab) {
			try {
				for (var tabNumber in thisTabSet.labelElements) {
					thisTabSet.labelElements[tabNumber].className = 'st_tabs_label_off';
					thisTabSet.contentElements[tabNumber].style.display = 'none';
					if (tabNumber == tab) {
						thisTabSet.labelElements[tabNumber].className = 'st_tabs_label_on';
						thisTabSet.contentElements[tabNumber].style.display = 'block';
					}
				}
			} catch(error) {
				return false;
			}
		}

		//activate the first tab
		thisTabSet.SelectTab(0);
	},
	TriggerPageLoadFunctions:function(){
		//divs
		var allItems = document.getElementsByTagName('div');
		for (var currItem = 0; currItem < allItems.length; currItem++) {
			switch(allItems[currItem].className) {
				case 'st_slider':
					new ST.Slider(allItems[currItem]);
					break;
				case 'st_tabs':
					new ST.TabSet(allItems[currItem]);
					break;
				case 'st_image_carousel':
					new ST.ImageCarousel(allItems[currItem]);
					break;
				case 'map_container':
					new ST.Map(allItems[currItem]);
					break;
			}
		}
		//anchors
		var allItems = document.getElementsByTagName('a');
		for (var currItem = 0; currItem < allItems.length; currItem++) {
			switch(allItems[currItem].className) {
				case 'popup':
				case 'popupscroll':
				case 'slideshowpopup':
				case 'footerpopup':
					ST.PopUp.Add(allItems[currItem]);
					break;
			}
		}
		//uls
		var allItems = document.getElementsByTagName('ul');
		for (var currItem = 0; currItem < allItems.length; currItem++) {
			switch(allItems[currItem].className) {
				case 'navigation_container':
					ST.InitNavigation(allItems[currItem]);
					break;
			}
		}
		//one offs
		ST.DisplayAccountCenterLinks();
	},
	SetCookie:function(params){
		if( !params.name || !params.value ) return false;
		
		var cookie = params.name + "=" + escape(params.value);
		if( params.days ){
			var date = new Date();
			date.setTime(date.getTime()+(params.days*24*60*60*1000));
			cookie += "; expires="+date.toGMTString();
		}
		if( params.path ) cookie += "; path=" + params.path;
		if( params.domain ) cookie += "; domain=" + params.domain;
		if( params.secure ) cookie += "; secure";
		document.cookie = cookie;
	},
	GetCookie:function(params){
		if( !params.name ) return false;

		var cookie = document.cookie;
		var prefix = params.name + "=";
		var begin = cookie.indexOf("; " + prefix);
		if (begin == -1) {
			begin = cookie.indexOf(prefix);
			if (begin != 0) return null;
		} else {
			begin += 2;
		}
		var end = document.cookie.indexOf(";",begin);
		if (end == -1) {
			end = cookie.length;
		}
		return unescape(cookie.substring(begin + prefix.length, end));
	},
	DisplayAccountCenterLinks:function(){
		//this could be more abstracted, but its purpose is so specialized there's not much point
		var firstName = ST.GetCookie({ 'name':'NMNAME' });
		var html = "";
		if (firstName) {	
			firstName = firstName.replace(/\+/g," ");
			firstName = firstName.substr(0,20);
			html = '<a href="https://secure.nwsource.com/reg/seattletimes/">Hi ' + firstName + '</a> <span class="hspacing">|</span> <a href="https://secure.nwsource.com/reg/seattletimes/logout.php">Log out</a><span class="hspacing">|</span>';
		} else {
			html = '<a href="https://secure.nwsource.com/reg/seattletimes/">Your account</a> <span class="hspacing">|</span> <a href="https://secure.nwsource.com/reg/seattletimes/">Log in</a><span class="hspacing">|</span>';
		}
		ST.ReplaceContent('account_center_links', html);
	},
	InitNavigation:function(container){
		if( !container ) return false;
		
		//loop through all the li's (top menu items)
		for( var i=0; i < container.childNodes.length; i++ ){
			currMenu = container.childNodes[i];
			if( currMenu.nodeName.toUpperCase() != 'LI' ) continue;

			//I am just blasticating any exiting class name with out attempt to preserve it.
			//We can change this easily later if we need to.
			//I am deliberately keeping the display style out of the CSS class
			currMenu.onmouseover = function(){
				this.className = 'selected';
				var dropDown = this.getElementsByTagName('ul')[0];
				if( dropDown ){
					dropDown.className = 'selected';
					dropDown.style.display = 'block';
				}
			}
			
			currMenu.onmouseout = function(){
				this.className = '';
				var dropDown = this.getElementsByTagName('ul')[0];
				if( dropDown ){
					dropDown.className = '';
					dropDown.style.display = 'none';
				}
			}
		}
	},
	ToggleDisplay:function(params){
		//allow them to pass an ID, set of IDs, element or set of elements
		if( params.id ) params.ids = new Array(params.id);
		if( params.ids ){
			params.elements = new Array();
			for( var key in params.ids ){
				params.elements.push(document.getElementById(params.ids[key]));
			}
		}
		if( params.element ) params.elements = new Array(params.element);
		if( !params.elements ) return false;
		
		//allow for any kind of toggling, but default to block
		if( !params.displayType ) params.displayType = 'block';
		
		for( var i = 0; i < params.elements.length; i++  ){
			if( !params.elements[i] ) continue;
			if( params.elements[i].style.display != 'none' ){
				params.elements[i].style.display = 'none';
			}else{
				params.elements[i].style.display = params.displayType;
			}
		}
	}
};

//set up our page load functions
ST.AddLoadEvent(ST.TriggerPageLoadFunctions);

//third party page variables

//addthis
var addthis_pub = "seattletimes";
var addthis_header_color = "#ffffff";
var addthis_header_background = "#506a8f";
var addthis_options = "facebook, digg, google, twitter, linkedin, delicious, myspace, friendfeed, newsvine, live, more";

//DEPRECATED
function PopoffWindow(windowName,windowWidth,windowHeight,URL,shouldResize,shouldScroll) {
	var availableWidth = screen.availWidth;
   	var availableHeight = screen.availHeight;

   	var windowLeft = (availableWidth - windowWidth) / 2;
   	var windowTop = ((availableHeight - windowHeight) / 2) - 16;
   		
	newWindow = window.open(URL,windowName,"width=" + windowWidth + ",height=" + windowHeight + ",left=" + windowLeft + ",top=" + windowTop + ",location=no,resizable=" + shouldResize + ",scrollbars=" + shouldScroll + ",toolbar=no");
	newWindow.focus();
}