/**
 * Site is the main wrapper for all of the small javascript features on this site.
 */
var Site = {
	/**
	 * This will init all of the features.
	 */
	Init: function() {
		Site.BodyCssClassHack();
		Site.Forms.Init();		 
		Site.TertiaryNav();
		Site.Weather.Init();
		Site.Horoscope.Init();
		Site.HoroscopeHero.Init();
		Site.Modules.ScoreBoard();
		Site.FontSize.Init();	
		Site.PhotoGallery.InitPopup();		 	
		Site.PhotoGallery.Init();
	},
	BodyCssClassHack: function() {
		var bodyEle = $(document.body);
		if( BrowserDetect.OS == 'Mac' ) { 
			if( BrowserDetect.browser == 'Safari' ) {
				bodyEle.addClassName('safariMac');
			} else {
				bodyEle.addClassName('mac');
			}
		}
	},
	/**
	 * The font size tool allows the article to be shown in various different font sizes. It is represented with
	 * three "A"s (__FONT_SIZE_LINKS). This will add a class to two elements on the site, the article body and
	 * the article header. These values are shown in a cookie and will reflect the user's choice on pageload. If
	 * no selection is made, the default normal (size 2) will be used.
	 */
	FontSize: {
		/**
		 * Init will go through and detect the article body and header, and assign the appropriate events to the
		 * font size links.
		 */
		Init: function() {
			Site.__ARTICLE_BODY = $(document.body).selectFirst('.articleBody');
			
			if (Site.__ARTICLE_BODY ) {
				Site.__FONT_SIZE_LINKS = $$('.article .headerTools .fontSize a');
				
				Site.__FONT_SIZE = 2; // default font size is 2
				
				// Read the cookie and set the current font size accordlingly
				if (Cookie.get('fontsize')) {
					Site.__FONT_SIZE = Cookie.get('fontsize');
				}

				// iterate through all of the links and assign the active class and the click event
				Site.__FONT_SIZE_LINKS.each(function(linkEle, index){
					// highlight this nav item if its the one that is showing.
					if (Site.__FONT_SIZE == index + 1) {
						linkEle.addClassName('active');
					}
					
					// the click event
					linkEle.observe('click', function(){
						// reset the links so active isn't showing
						Site.__FONT_SIZE_LINKS.invoke('removeClassName', 'active');
						
						// TODO: change this to a custom attribute, get the font size, currently it parses the class name
						Site.FontSize.ChangeSize( linkEle.className.substring( linkEle.className.length - 1 ) );
						
						// mark this link as it is the one that is currently showing.
						linkEle.addClassName('active');
					});
				});
				
				// show the font size that's set.
				Site.FontSize.ChangeSize( Site.__FONT_SIZE );
			}
		},
		/**
		 * This will physically alter the dom and add a css class to the header and body divs causing
		 * these elements to show the new font size of choice. This is called from the click event set 
		 * in Init.
		 * 
		 * @param {Number} newSize a number from 1 to 3 that represents the new font size to show
		 */
		ChangeSize: function( newSize ) {	
			// remove the old size
			Site.__ARTICLE_BODY.removeClassName('articleSize' + Site.__FONT_SIZE);
			
			// add the new size
			Site.__ARTICLE_BODY.addClassName('articleSize' + newSize );
			
			// set the cookie to remember this new font size
			Cookie.set('fontsize', newSize, 365);
			Site.__FONT_SIZE = newSize;
		}
	},
	
	/**
	 * TertiaryNav are the drop downs located in the header. A simple mouseover and mouse will add an 
	 * active class causing the elements to show the dropdown.
	 */
	TertiaryNav: function() {
		// these are where the dropdowns are located
		$$('.header .tertiaryNav .dropdown').each(function( dropdownEle ) {   
			// the LI element should be where the mouse events take place, simple mouseover/mouseout show/hide's the menu
			var liEle = dropdownEle.up();
			
			// show the dropdown
			liEle.observe('mouseover', function() { 
				liEle.addClassName('active');
				// TODO: hide all form elements on mouseover
			});
			
			// hide the dropdown
			liEle.observe('mouseout', function() {  
				liEle.removeClassName('active'); 
				//TODO: restore input elements
			});			
		});   
	},
	/**
	 * Certain modules have specific workings to them. As of the time of this writing, there is only one.
	 */
	Modules: { 
		/**
		 * The scoreboard module is a module where each of the tab links will link to the full scoreboard.
		 * When each of the tabs are clicked on, it should change the button's location so that when it
		 * is clicked, it will redirect to the full scoreboard.
		 */
		ScoreBoard: function() {
			// find the instance of the scoreboard module
			var scoreBoardEle = $$('.scoreboardModule')[0];
			if( scoreBoardEle ) {
				// get the location of the button we need to assign
				var fullScoreBoardLink = scoreBoardEle.selectFirst('.footerBar .btn');
				
				// go through each tab, and set it so that when it is clicked, to set the href of the current tab
				scoreBoardEle.select('.tabNav li a').each( function( tabLinkEle ) {
					tabLinkEle.observe('click', function(e){
						
						// stops propagation so we don't visit the link when we click the tab (more accessible)
						e.stop();
						fullScoreBoardLink.writeAttribute('href', tabLinkEle.readAttribute('href') );
						return false;
					});
				});
			}
		}
	},
	/**
	 * this sets all of the links that have a "submit" class to submit the form when it's clicked.
	 */
	Forms: {
		Init: function() {
			$$('form').each(function( formEle ) {
				formEle.evaluate = function() { return true; };
				   
				// get all the buttons that should submit the form
				var linkButtons = formEle.select('a.submit');
								
				linkButtons.each(function( linkEle ) {
					// divisionselect has it's own handler
					if ($(formEle).getAttribute('id') == 'divisionselect') return;
					// tell the button what form should submit when it clicks
					linkEle.observe('click', function(event) {
						// Stop me from hitting the # in the HREF.
						event.stop();
						if (formEle.evaluate()) {
							formEle.submit();
						}
						return false;
					});
				});    
			});
		}
	},
	PhotoGallery: {
		InitPopup: function() {
			$$('a.launchGallery').each(function( ele ) { 
				ele.observe('click', function(e) { 
					e.stop(); 	
					Site.Popup({ 'Url': ele.href, 'Name': 'photoGallery', 'Height': 528, 'Width': 631 }); 
					return false;
				});  
			});    
		},
		Init: function() {
			$$('.galleryModule').each( Site.PhotoGallery.Create );
		},
		Create: function( galleryEle ) {
			// we need to hookup the main carousel with the thumbnail viewer (and vice versa)
			
			// this is the main carousel that has the slides in it
			var galleryCarousel = galleryEle.selectFirst('.galleryCarousel');
			
			// this is a reference to the thumbnails carousel, we use this to
			// show the current slide of thumbnails when browsing using back/next
			// on the main carousel
			var thumbCarousel = galleryEle.selectFirst( '.thumbnailCarousel' );
			var thumbViewport = thumbCarousel.__VIEWPORTS[0];
			
			// create a custom call back so that when we show a new slide, we can show
			// the proper thumbnail slide and highlight
			Carousel.Common.CallBack.Add( galleryCarousel, 'new_slide', function( slideEle, slideIndex ) {

				if( ! slideEle.__SKIP_THUMB_SHOW ) { 
				// get the current thumbnail 
					var currentThumb = thumbCarousel.select('li')[ slideIndex ];
									
					// get the slide that this thumbnail is in.
					var currentThumbSlide = currentThumb.up().up();
					
					// this will give us the current index of the slide set that has this thumbnail
					var newSlideIndex = thumbViewport.__SLIDES.indexOf( currentThumbSlide );

					// we have to show the correct set that the thumbnail is in.
					Carousel.Common.Show.Slide( thumbCarousel, newSlideIndex );
					
					// highlight the thumbnail
					Carousel.Thumbnails.Highlight( thumbCarousel, slideIndex );
				}
				
				slideEle.__SKIP_THUMB_SHOW = false;
			});
			
			Carousel.Common.CallBack.Add( thumbCarousel, 'thumb_click', function( slideEle, thumbIndex ) {
				Carousel.Common.Show.Fade( galleryCarousel, thumbIndex );
				// TODO: fix comment
				// returning true will stop execution from anything going forward, default is false
				return true;
			});
		}
	},
	HoroscopeHero: { 
		Init: function() {
			var horoscopeSign = Cookie.get('HoroscopeSign');
			if( ! horoscopeSign ) { 
				horoscopeSign = 0;
				Cookie.set('HoroscopeSign', horoscopeSign, 365);
			}
			
			var horoscopeEles = $$(".horoscopeModule");
			horoscopeEles.each( function( ele ) {				
				ele.resetTabEles = function( horoscope ) {
					ele.select('.tabNav li') .invoke('removeClassName','active');
					ele.select('.tabNav li.' + horoscope).invoke('addClassName','active');	
				};
				
				ele.select('.horoscope').each( function( horoscope, horoscopeIndex ) {
					if( horoscopeIndex != horoscopeSign ) { 
						horoscope.hide();
					} else {
						horoscope.show();
					}
				});
				
				var changeEle = ele.selectFirst('.change');
				var cancelButton = changeEle.selectFirst('.formBtns a.cancel');
				
				cancelButton.voidLink();
				cancelButton.observe('click', function() {
					ele.removeClassName('showHoroscopeSettings');
				});
				
				var setDefaultHoroscope = ele.selectFirst('p.option input');
				
				changeEle.select('.selectBox li a').each( function( horoscopeLink, horoscopeLinkIndex ) { 
					horoscopeLink.voidLink();
					horoscopeLink.observe('click', function() {
						if( setDefaultHoroscope.checked ) {
							Cookie.set('HoroscopeSign', horoscopeLinkIndex, 365);
						}
						
						ele.select('.horoscope').each( function( horoscope, horoscopeIndex ) {
							if( horoscopeIndex != horoscopeLinkIndex ) { 
								horoscope.hide();
							} else {
								horoscope.show();
							}
						});		
						
						ele.removeClassName('showHoroscopeSettings');			
					});
				});			
				ele.select('.titleBar .changeSign a').each( function( changeLinkEle ) { 
					changeLinkEle.voidLink();
					changeLinkEle.observe('click', function() {
						ele.addClassName('showHoroscopeSettings');
					});
				});
				
				ele.addClassName('showExtendedHoroscopeHero');
				ele.removeClassName('showRomanticHoroscopeHero');
				ele.removeClassName('showOverviewHoroscopeHero');
								
				ele.select('.tabNav').each( function( tabNavEle ) {					
					tabNavEle.select('li').each( function( tabEle ) {
						tabEle.selectFirst('a').voidLink();
						tabEle.observe('click', function() {							
							ele.removeClassName('showExtendedHoroscopeHero');
							ele.removeClassName('showRomanticHoroscopeHero');
							ele.removeClassName('showOverviewHoroscopeHero');
													
							if( tabEle.hasClassName('extended') ) {
								ele.addClassName('showExtendedHoroscopeHero');
								ele.resetTabEles('extended');
							} else if( tabEle.hasClassName('romantic') ) {
								ele.addClassName('showRomanticHoroscopeHero');
								ele.resetTabEles('romantic');
							} else if( tabEle.hasClassName('overview') ) {
								ele.addClassName('showOverviewHoroscopeHero');
								ele.resetTabEles('overview');
							}
						
						
						});
						
					})
				})
			});
		},
		ShowChangeSettings: function( ele ) {
			ele.addClassName('showHoroscopeSettings');		
		}
	},
    Horoscope: {
    	Init: function() {
    		if (!$('horoscopeTab')) return;
    		
			Site.Horoscope.__ELE = $('horoscopeTab');
    		// If no sign is set via cookie, display sign selector.
    		Site.Horoscope.__ELE.up().select('ul.tabNav li').each(function(tab) {
    			if ($(tab).selectFirst('span a').childNodes[0].nodeValue != 'Horoscope') return;
    			 $(tab).observe('click',function() {
    			 	if (Cookie.get( 'HoroscopeSign' ) == null) {
    			 		Site.Horoscope.__ELE.select('div.change')[0].showSettings();
    			 	}
    			 });
    		});
    		
    		if( Site.Horoscope.__ELE ) {
	    		Site.Horoscope.__ELE.select( 'ul.selectBox li a').each( function( linkEle, signIndex ) { 
					linkEle.voidLink();
					linkEle.observe( 'click', function() { 
						 Site.Horoscope.Show( signIndex );
					});
				});
				
				var currentSign = Cookie.get( 'HoroscopeSign' );
				Site.Horoscope.Show( currentSign );
				
				var horoscopeEles = Site.Horoscope.__ELE.select( '.horoscopeSign' );
				horoscopeEles.each( function( ele ) {
					var resetActive = function() {
						ele.removeClassName('showOverview');
						ele.removeClassName('showRomantic');
						ele.removeClassName('showExtended');
					};
									
					var overviewEles = ele.select('a.overview');
					overviewEles.each( function( linkEle ) {
						linkEle.voidLink();
						linkEle.observe('click', function() {
							resetActive();
							ele.addClassName('showOverview');
						});
					});
					
					var romanticEles = ele.select('a.romantic');
					romanticEles.each( function( linkEle ) {
						linkEle.voidLink();
						linkEle.observe('click', function() {
							resetActive();
							ele.addClassName('showRomantic');
						});
					});
					
					var extendedEles = ele.select('a.extended');
					extendedEles.each( function( linkEle ) {
						linkEle.voidLink();
						linkEle.observe('click', function() {
							resetActive();
							ele.addClassName('showExtended');
						});
					});
					
					resetActive();
					ele.addClassName('showOverview');
				});				
    		} 
		},
		Show: function( signIndex ) {
			if (signIndex != null) {
				
				if($('checkbox3').checked) Cookie.set( 'HoroscopeSign', signIndex, 365 );
				
				var allSigns = Site.Horoscope.__ELE.select('.allHoroscopes .horoscopeSign');
					allSigns.invoke( 'removeClassName', 'active' );
					allSigns[ signIndex ].addClassName( 'active' );
				
				var signList = Site.Horoscope.__ELE.select('ul li');
					signList.invoke('removeClassName', 'active' );
					signList[ signIndex ].addClassName( 'active' );
				
				
				if( typeof Site.Horoscope.__ELE.selectFirst('.change').cancelChanges == 'function' ) {
					Site.Horoscope.__ELE.selectFirst('.change').cancelChanges();
				}
			}
		}
    },
	Popup: function( options ) {  
		var width = document.viewport.getWidth();
		var height =  document.viewport.getHeight(); 	
		var leftPos = (width > options.Width) ? (width - options.Width) / 2 : 0;
		var topPos = (height > options.Height) ? (height - options.Height) / 2 : 0; 
		window.open(options.Url,options.Name,'width='+options.Width +',height='+options.Height+',top='+topPos+',left='+leftPos+',toolbar=no,menubar=no,location=no');
	},
	// returns true or false depending on if the email provided matches the regex (matches *@*.----)
	ValidateEmail: function( email ) {
		var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
		return (filter.test(email));
	},
	Weather: { 
		Init: function() {
			if (!Cookie) return;
			var currentSetting = Cookie.get('TempUnit');

			if( currentSetting == null || ! currentSetting ) { 
				currentSetting = 'f';
			}
												
			Site.Weather.ShowUnit( currentSetting );
			
			Site.Weather.SetToggler( $$('.weatherHero ul.units') );
			
		},
		ShowUnit: function( unit ) {
			var bodyEle = $(document.body);
			bodyEle.removeClassName('unitsFht');
			bodyEle.removeClassName('unitsCel');
						
 			switch( unit ) { 				 
			
				case 'f': 
					bodyEle.addClassName('unitsFht');
					break;
				case 'c': 
					bodyEle.addClassName('unitsCel');				
					break;
			}

			Cookie.set( 'TempUnit', unit, 365 );			
		},
		SetToggler: function( togglerEles ) {
			togglerEles.each( function( ele ) { 
				ele.select('li').each( function( liEle )  {
					var linkEle = liEle.selectFirst('a');
					linkEle.voidLink();
					linkEle.observe('click', function() {
						var currentSetting = null; 
						if( liEle.hasClassName('unitsFht') ) {
							currentSetting = 'f';
						} else if( liEle.hasClassName('unitsCel') ) {
							currentSetting = 'c';
						}
							
						Site.Weather.ShowUnit( currentSetting );
					});
				});
			});
		}
	}
};

var HomePage = {
	Init: function() {
		if (!Prototype.Browser.IE) return;
		if (!$('defaultHP')) return;
		$('defaultHP').select('a')[0].setAttribute('href','#');
		$('defaultHP').select('a')[0].observe('click',HomePage.Set);
	},
	Set: function(event) {
		var callr = Event.element(event);
		callr.style.behavior='url(#default#homepage)';
		callr.setHomePage('http://www.rr.com/');
		// Omniture tracking
		var s=s_gi(s_account);
		s.tl(callr,'o','set road runner as my homepage');
	}
};

/* Carousel */

/**
 * This is the main Carousel. Carousel.Init is the main function of this class.
 * This "class" doesn't actually create instances using the "new" operator, it 
 * instead passes around "slideEle" to each functions to avoid using "new". All
 * properties of slideEle are instead store in the DOM. The basic hierarchy a
 * carousel is: .slideCarousel > .slideViewport > .slides > .slide
 * 
 * @author Adam S. Kirschner adams.kirschner@ogilvy.com
 */
var Carousel = {
	/**
	 * This is used to init all of the actual slide elements used on the page. Calls Carousel.Create
	 */
	Init: function() {
		// all carousels have the slideCarousel class
		$$(".slideCarousel").each( Carousel.Create )
	},
	
	/**
	 * This will init all of the features of a Carousel, setting events.
	 * 
	 * @param {HtmlElement} slideEle This is the main div of a carousel.
	 */
	Create: function( slideEle ) {
		// viewports need to be init'ed first, after this it doesn't matter
		Carousel.Viewports.Init( slideEle );
		
		// these are all of the features that carousels can have
		// if a specific carousel does not have the HTML for that feature, it will be ignored
		Carousel.Advertise.Init(slideEle);
		Carousel.Pager.Init( slideEle );
		Carousel.SlideStatus.Init( slideEle );
		Carousel.Thumbnails.Init( slideEle );
		Carousel.Overlay.Init( slideEle );
		Carousel.Title.Init( slideEle );
		Carousel.AutoScroll.Init( slideEle );
	},
	AutoScroll: { 
		/**
		 * 
		 * @param {Object} slideEle
		 */
		Init: function( slideEle ) {
			if( slideEle.hasClassName( 'heroCarousel') ) {
				setTimeout( function() { Carousel.AutoScroll.Handler( slideEle ); }, 8000 );
			}
		}, 
		/**
		 * 
		 * @param {Object} slideEle
		 */
		Handler: function( slideEle ) {
			if (!slideEle.__DISABLE_AUTO_SCROLL) {
				Carousel.Pager.Next(slideEle);
				if (!slideEle.__DISABLE_AUTO_SCROLL) {
					setTimeout(function(){
						Carousel.AutoScroll.Handler(slideEle);
					}, 8000);
				}
			}
		}
	},
	
	/**
	 * Thumbnails are the images (usually on the bottom of a carousel) that represent 
	 * which of all of the slides is currently being shown by an 'active' css class
	 */
	Thumbnails: {
		/**
		 * This will go through each slideEle and assign the necessary private variables needed
		 * and will also update them with the correct 'active' status (depending on which slide is shown)
		 * 
		 * @param {HTMLElemenet} slideEle @see Carousel.Create	
		 */
		Init: function( slideEle ) {
			// the thumbnail ele's are really the LI element, this is what active gets set on it
			slideEle.__SLIDE_THUMBS = slideEle.select('.slideThumbnails li');
		
			// if thumbnails don't exist then die gracefully
			if (slideEle.__SLIDE_THUMBS.length > 0) {
				
				// go through each thumbnail and set the 'click' event
				slideEle.__SLIDE_THUMBS.each(function(thumbEle, thumbIndex){
					
					// we want to set the event on the link of each thumbnail, not the LI
					var linkEle = thumbEle.selectFirst('a');
					
					linkEle.voidLink();
					
					linkEle.observe('click', function(){
						linkEle.blur();
						
						slideEle.__DISABLE_AUTO_SCROLL = true;
						
						// when each thumb is clicked, we need to reset the highlighting
						Carousel.Thumbnails.Highlight(slideEle, thumbIndex);	
						
						// this allows us to have a custom call back function that when the 
						// thumbnails are clicked to do something else, this is primarily used
						// on the photogallery
						// TODO: update comment
						// the not fire means that if we return true, then don't execute any further
						if( ! Carousel.Common.CallBack.Fire( slideEle, thumbIndex, 0, 'thumb_click' ) ) {
							// if the class 'slideOnThumbClick' is applied to 'slideEle', then 
							// it will not fade on click but will slide
							if (slideEle.hasClassName('slideOnThumbClick')) {
								Carousel.Common.Show.Slide(slideEle, thumbIndex);
							} else {
								Carousel.Common.Show.Fade(slideEle, thumbIndex);
							}
						}
					});
				});
				
				// get the active thumb
				var activeThumb = slideEle.__SLIDE_THUMBS[0].selectFirst('.active');
				
				// if there isn't one, set it to the first one
				if (!activeThumb) {
					slideEle.__SLIDE_THUMBS[0].addClassName('active');
				}
			}
		},
		
		/**
		 * This will highlight the appropriate thumbnail image
		 * 
		 * @param {HtmlElement} slideEle
		 * @param {int} slideIndex the index of the thumbnail that needs to highlighted
		 */
		Highlight: function(slideEle, slideIndex){
			if (slideEle.__SLIDE_THUMBS.length > 0) {
				slideEle.__SLIDE_THUMBS.invoke('removeClassName', 'active');
				slideEle.__SLIDE_THUMBS[slideIndex].addClassName('active');
			}
		}
	},
	
	/**
	 * Pagers are the left and right arrows on the top of the Carousel.
	 * 
	 * @param {HtmlElement} slideEle
	 */
	Pager: { 
		/**
		 * Init sets the events on the arrow elements, will also retrive them and set a reference to them
		 * in slideEle
		 * 
		 * @param {HtmlElement} slideEle 
		 */
		Init: function(slideEle){

			// the pager element is wrapped in a 'slideNav' class
			var slideNav = slideEle.selectFirst(".slideNav");
			
			if (slideNav) {
				
				// get the left pager
				var leftPager = slideNav.selectFirst('.left');
				leftPager.voidLink();
				
				// call the pager's previous event when clicked
				leftPager.observe( 'click', function(){
					slideEle.__DISABLE_AUTO_SCROLL = true;
					leftPager.blur();
					Carousel.Pager.Previous(slideEle);
				});
				
				// get the right pager
				var rightPager = slideNav.selectFirst('.right');
				rightPager.voidLink();
				
				// call the pager's next event when clicked
				rightPager.observe( 'click', function(){
					slideEle.__DISABLE_AUTO_SCROLL = true;
					rightPager.blur();
					Carousel.Pager.Next(slideEle);
				});
			}
		},
		
		/**
		 * Previous will take slideEle and show the slide to its left. If it is showing the first slide, 
		 * it will wrap and show the last one.
		 * 
		 * @param {HtmlElement} slideEle
		 */
		Previous: function( slideEle ) {
			// grab any viewport since they should all be showing the same location anyway
			var viewportEle = slideEle.__VIEWPORTS[0];
			
			// index starts at -1, if it is break.
			var currentIndex = -1;
			
			// get the index of which element is currently being shown.
			viewportEle.__SLIDES.each( function( singleSlideEle, slideIndex ) {
				if( singleSlideEle.hasClassName('active') ) {
					currentIndex = slideIndex;
				}
			});

			// if it's at the beginning
			if( currentIndex == -1 ) {
				alert( 'something really bad happened' );
				return false;
			} else if( currentIndex == 0 ) {
				
				// if a css class 'slideAtEnds' is on slideEle, then the Carousel will 
				// slide to the other end instead of fading
				if( slideEle.hasClassName('slideAtEnds') ) {
					Carousel.Common.Show.Slide( slideEle, viewportEle.__SLIDES.length - 1 );
				} else {
					Carousel.Common.Show.Fade( slideEle, viewportEle.__SLIDES.length - 1 );
				}
			} else {
				// otherwise just go back one
				if( slideEle.hasClassName('fadeOnSlideChange' ) ) {
					Carousel.Common.Show.Fade( slideEle, currentIndex - 1 );	
				} else {
					Carousel.Common.Show.Slide( slideEle, currentIndex - 1 );
				}
			}
		},
		
		/**
		 * Next will take slideEle and show the slide to its right. If it is showing the last slide
		 * it will wrap and show the first one.
		 * 
		 * @param {HtmlElement} slideEle
		 */
		Next: function( slideEle ) {
			// grab any viewport since they should all be showing the same location anyway
			var viewportEle = slideEle.__VIEWPORTS[0];
			
			// get the index of which element is currently being shown.
			
			// get the index of which element is currently being shown.
			viewportEle.__SLIDES.each( function( singleSlideEle, slideIndex ) {
				if( singleSlideEle.hasClassName('active') ) {
					currentIndex = slideIndex;
				}
			});
			
			// if it's at the end
			if( currentIndex == viewportEle.__SLIDES.length - 1 ) {
				
				// if a css class 'slideAtEnds' is on slideEle, then the Carousel will 
				// slide to the other end instead of fading
				if( slideEle.hasClassName('slideAtEnds') ) {
					Carousel.Common.Show.Slide( slideEle, 0 );
				} else {
					Carousel.Common.Show.Fade( slideEle, 0 );
				}				
			} else {
				// otherwise just go forward one
				if( slideEle.hasClassName('fadeOnSlideChange' ) ) {
					Carousel.Common.Show.Fade( slideEle, currentIndex + 1 );	
				} else {
					Carousel.Common.Show.Slide( slideEle, currentIndex + 1 );
				}
			}
		}
	},
	/**
	 * SlideStatus is the X of Y paging status usually located on the bottom of a Carousel. The SlideStatus.Update will
	 * usually get called from the Common.NewSlideIsShown method
	 */
	SlideStatus: {
		Init: function ( slideEle ) {
			
			// the slide status element is wrapped in a 'slideStatus' class
			var slideStatus = slideEle.selectFirst(".slideStatus");
			
			if( slideStatus ) {
				
				// 'current' and 'total' are the css classes that are used to store each value (respectively)
				slideEle.__SLIDE_STATUS = {
					'Current': slideStatus.selectFirst('.current'),
					'Total': slideStatus.selectFirst('.total') 
				};
				
				// update the slide element to show the initial values
				Carousel.SlideStatus.Update( slideEle );
			}
		},
		
		/**
		 * Update will set the appropriate numbers in slide status. The HTML is physically updated. The status 
		 * is updated based on the first viewport that is found. @see Carousel.Viewports
		 */
		Update: function(slideEle){
			if (slideEle.__SLIDE_STATUS) {
				// grab the first viewport since they should all be showing the same location anyway
				var viewportEle = slideEle.__VIEWPORTS[0];
				
				// get the index of which element is currently being shown.
				var currentIndex = viewportEle.__SLIDES.indexOf( slideEle.selectFirst('.active') );
				
				slideEle.__SLIDE_STATUS.Current.innerHTML = currentIndex + 1;
				slideEle.__SLIDE_STATUS.Total.innerHTML = viewportEle.__SLIDES.length;
			}
		}
	},
	
	/**
	 * A Viewport is the closest wrapper div to all of the slides that show. This DIV will have the full width set and 
	 * becomes the 'filmstrip' to slide and show the appropriate slide. These two DIVs are required:
	 * 	- the parent div ('.slideViewport') will have { overflow: hidden; width: WIDTHpx; } where WIDTH equals the width of a slide
	 *  - the inner div ('.slides') will have a width that is equal to all of the widths of the slides so it can slide left/right
	 */
	Viewports: {
		/**
		 * Init sets the sizes of the viewports and retains reference of them in slideEle. 
		 * The slide count and slides width are used to determine the width of the viewport.
		 * These calculations take place here.
		 * 
		 * @param {HtmlElement} slideEle
 		 */
		Init: function( slideEle ) {
			
			// the topic hero carousel has its own "image viewport", so create this first
			// before we init all of the viewports for each slide
			if( slideEle.hasClassName( 'topicHeroCarousel' ) ) {
				Carousel.Viewports.ImageInit( slideEle );	
			}
			
			// most modules only have one viewport, however you can have more than one (like the topic hero)
			slideEle.__VIEWPORTS = slideEle.select('.viewport .slides');

			// each viewport has the same functionalilty, thats why everything is pretty much in a loop
			slideEle.__VIEWPORTS.each( function( viewportEle ) {

				// viewports are made up of a set slides
				viewportEle.__SLIDES = viewportEle.select('.slide');
				
				// get the width of one of those slides
				viewportEle.__SLIDE_WIDTH = viewportEle.__SLIDES[0].getStyle('width').toInt();

				// set the viewport's width so it becomes a strip
				viewportEle.setStyle({ 'width':( viewportEle.__SLIDES.length * viewportEle.__SLIDE_WIDTH ) + 'px' });
				
				// if there's no active slide, highlight the first one
				var activeSlide = viewportEle.selectFirst('.active');

				if( ! activeSlide ) {
					viewportEle.__SLIDES[0].addClassName('active');
				}
				
			});
		},
		
		/**
		 * The topic hero carousel is setup in a specific way to have the image
		 * of the slide to scroll separately from the rest of the slides, this function
		 * is used to move all the 'photo' elements into a new 'div.imageViewport' 
		 * @param {HtmlElement} slideEle
		 */
		ImageInit: function( slideEle ){			
			// go grab all the photo elements in this slide
			var photoEles = slideEle.select('div.photo')
			
			// create the div's, a viewport has two parts to it, @see Carousel.Viewports
			var imageViewport = new Element('div', { 'class': 'imageViewport viewport' });
			var slides = new Element( 'div', { 'class': 'slides' });
					
			// create each slide
			photoEles.each(function(ele){
				var newSlide = new Element('div',{ 'class': 'slide' });
				newSlide.appendChild( ele );
				slides.appendChild( newSlide );
			});
			
			// append it
			imageViewport.appendChild( slides );
			slideEle.appendChild( imageViewport );
		}
	},
	
	/**
	 * The Title of each slide shows in the carousels title. This will simply copy the title.
	 */
	Title: {
		/**
		 * Init will get the carousel's title element and retains reference.
		 * 
		 * @param {HtmlElement} slideEle
		 */
		Init: function( slideEle ) {
			
			// find the title element
			var title = slideEle.selectFirst('.titleBar .titleText');
			
			// if we found it, keep it and update it
			if( title ) {
				slideEle.__TITLE = title;
				Carousel.Title.Update( slideEle );
			}
		},
		
		/**
		 * This will update the carousel's title.
		 * 
		 * @param {HtmlElement} slideEle
		 */
		Update: function( slideEle ) {
			if( slideEle.__TITLE ) {
				var currentTitle = slideEle.selectFirst('.slides .active .titleText');
				slideEle.__TITLE.innerHTML = currentTitle.innerHTML;
			}
		}
	},
	
	/**
	 * Carousels can have this small overaly that appears on the bottom of the main photo.
	 * This will initialize the click events so that it either shows in a 'minimized' view or not.
	 */
	Overlay: { 
		/**
		 * Overlays are captions that appear on the bottom of the pictures. You can
		 * click on these overlays and show them in a "minimized" state. The overlay state
		 * is shared across that set of slides.
		 * 
		 * @param {HtmlElement} slideEle
		 */
		Init: function( slideEle ) {
			// go find a '.slides' element that has this 'overlayToggleSet' class.
			slideEle.select('.overlayToggleSet').each(function( ele ){

				// within each of those, an '.overlayToggle' element will exist
				ele.select('.overlayToggle').each( function( toggleEle ) {
					
					// set this click action to just toggle the 'minimized' class on the '.slides' element
					toggleEle.observe('click', function(){
						ele.toggleClassName('minimized');
					});
				});
				
			});
		}
	},
	
	/**
	 * This Carousel.Common namespace is used for general carousel purposes.
	 */
	Common: {
		/**
		 * There are two ways to show a new slide, either to fade it in, or to slide it in.
		 * These two functions, Show/Fade do the samething at the end but with different animation
		 * techniques. Both take a slideEle and a slideIndex. The end result being slideIndex showing.
		 */
		Show: {
			/**
			 * Slide will transition the filmstrip and move it left/right), therefore causing a shift.
			 * 
			 * @param {Object} slideEle
			 * @param {Object} slideIndex
			 */
			Slide: function( slideEle, slideIndex ) {
				var direction = 1;
				// there can be more than one viewport, we have to maintain all of them
				slideEle.__VIEWPORTS.each( function( viewportEle ) {
				
					// clear and reset the active states
					viewportEle.__SLIDES.invoke( 'removeClassName', 'active' );
					viewportEle.__SLIDES[ slideIndex ].addClassName('active');
					
					// figure out how far left we need to go
					var leftOffset = viewportEle.__SLIDE_WIDTH * slideIndex;

					// check to see if we are going left, if we are set -1
					if( -leftOffset > viewportEle.getStyle('left').toInt() ) {
						direction = -1;
					}
					// animate it
					new Effect.Morph( viewportEle, {
						'style': {
							'left': -leftOffset + "px"
						},
						'duration': 0.5
					});
				});
				
				// call back to handle any new 'plugins' that need to be updated
				// pass direction so any callback can know if we went to the next or previous slide
				Carousel.Common.NewSlideIsShown( slideEle, slideIndex, direction );
			},
			
			/**
			 * Fade will transition the element by setting 'opacity' on the slide from 1 to 0 and then from 0 to 1.
			 * 
			 * @param {HtmlElement} slideEle
			 * @param {HtmlElement} slideIndex
			 */
			Fade: function( slideEle, slideIndex ) {
				// assume we are going to the next slide
				var direction = 1;
				
				// there can be more than one viewport, we have to maintain all of them
				slideEle.__VIEWPORTS.each( function( viewportEle ) {
					
					// clear and reset the active states
					viewportEle.__SLIDES.invoke( 'removeClassName', 'active' );
					viewportEle.__SLIDES[ slideIndex ].addClassName('active');
					
					// figure out how far left we need to go					
					var leftOffset = viewportEle.__SLIDE_WIDTH * slideIndex;

					// check to see if we are going left, if we are set -1
					if( -leftOffset > viewportEle.getStyle('left').toInt() ) {
						direction = -1;
					}

					// animate it (2 steps, fade out, fade in)
					viewportEle.fade({ 'from': 1, 'to': 0, 'duration': 0.25,
						'afterFinish': function(){
							
							// after faded out, move it left and then fade it back in 
							// TODO: why does prototype set { display: none; opacity: 1; } on fade out?
							viewportEle.setStyle({ 'left': -leftOffset + "px", 'opacity': 0, 'display': 'block' });
							viewportEle.fade({ 'from': 0, 'to': 1, 'duration': 0.25 });
						}
					});
				});

				// call back to handle any new 'plugins' that need to be updated
				// pass direction so any callback can know if we went to the next or previous slide
				Carousel.Common.NewSlideIsShown( slideEle, slideIndex, direction );
			}
		},
		
		/**
		 * This is a call back used whenever a Carousel is showing a different slide. Use this to add different
		 * features into a Carousel.
		 * 
		 * @param {HtmlElement} slideEle
		 * @param {HtmlElement} slideIndex
		 */
		NewSlideIsShown: function( slideEle, slideIndex, direction ) {
			// TODO: fix comments
			// if we did not return true, then execute normally
			Carousel.Common.CallBack.Fire(slideEle, slideIndex, direction, 'new_slide')
			
			// this is really a list of "update" methods for some of the carousel's components
			Carousel.SlideStatus.Update(slideEle);
			Carousel.Thumbnails.Highlight(slideEle, slideIndex);
			Carousel.Title.Update(slideEle);

			// this allows for each carousel to have a custom callback to run
			// this is primarily used for the photogallery			
			
		},
		CallBack: {
			Init: function(slideEle) {
				slideEle.__CALLBACKS = {
					'new_slide': [],
					'thumb_click': []
				};
				
				slideEle.__CALLBACKS_INIT = true;
			},
			Add: function( slideEle, callbackType, callback ) {
				if( ! slideEle.__CALLBACKS_INIT ) { Carousel.Common.CallBack.Init(slideEle); }
				
				slideEle.__CALLBACKS[ callbackType ].push( callback );
			},
			Fire: function( slideEle, slideIndex, direction, callbackType ) {				
				if (slideEle.__CALLBACKS) {
					if( slideEle.__CALLBACKS[ callbackType ] ) { 
						var stopOthers = false;
						slideEle.__CALLBACKS[callbackType].each(function(callbackFunction){
							var retVal = false;
							if (!stopOthers) {
								retVal = callbackFunction(slideEle, slideIndex, direction);
							}
	
							// if anything comes back as true, it will not allow any other callbacks to be made
							if( ! stopOthers && retVal ) { 
								stopOthers = true; 
							}
						});
					}
					return stopOthers;
				}
			}
		} 
	},
	Advertise: {
		Init: function( slideEle ) {
			var adOverlayEle = slideEle.selectFirst('.adOverlay');
			if( adOverlayEle ) {
				slideEle.__AD_ELE = adOverlayEle;
				slideEle.__AD_ELE.hideElement();
				
				var counter = 0;
				
				Carousel.Common.CallBack.Add( slideEle, 'new_slide', function( slideEle, slideIndex, direction ) {
					counter++;

					if( counter % 3 == 0 && counter != 0 ) { 
						counter = -1;

						if( direction > 0 ) {
							Carousel.Pager.Previous( slideEle );
						} else {
							Carousel.Pager.Next( slideEle );
						}
						
						Carousel.Advertise.Show( slideEle );
					}
					
					if( slideEle.__AD_SHOWING ) {
						Carousel.Advertise.Hide( slideEle );
					}
				});
			}
		},
		Show: function( slideEle ) {
			slideEle.__VIEWPORTS.each( function( viewportEle ) {
				viewportEle.fade({ 'from': 1, 'to': 0, 'duration': 0.25,
					'beforeStart': function() {
						slideEle.__AD_ELE.setStyle({'opacity': '0', 'display':'block'});
						slideEle.__AD_ELE.showElement();
					},
					'afterFinish': function(){
						viewportEle.hideElement();
						viewportEle.setStyle({ 'display': 'none', 'visibility': 'hidden' });
						slideEle.__AD_ELE.fade({ 'from': 0, 'to': 1, 'duration': 0.25 });
						slideEle.__AD_SHOWING = true;
					}
				});
			});
			
			slideEle.__SKIP_THUMB_SHOW = true;
		},
		Hide: function( slideEle ) {
			slideEle.__AD_ELE.fade({ 'from': 1, 'to': 0, 'duration': 0.25,
				'afterFinish': function() { 
					slideEle.__AD_ELE.hideElement();
					slideEle.__VIEWPORTS.each( function( viewportEle ) {
						viewportEle.showElement();
						viewportEle.setStyle({'display': 'block', 'visibility': 'visible'});
						viewportEle.fade({ 'from': 0, 'to': 1, 'duration': 0.25 });
					});
				}
			});
			
			slideEle.__AD_SHOWING = false;
		}
	}
	
};



/* END Carousel */
/* Search */
var Search = {
	Init: function() {
		if (!$('headersearchformweb')) return;
		$('headersearchformweb').selectFirst('input').focus();
		
		//When text is changed in search box, keep them all sync'd
		$$('.searchinput').each(function( searchinput ) {
			searchinput.observe('keyup', function(event) {
				var theElement = Event.element(event);
				$$('.searchinput').each(function( updateEle ) {
					if (updateEle != theElement) {
						updateEle.value = theElement.value;	
					}
				}, theElement);			
			});
		});
	}
};
/* End Search */
/* Tabs */
var Tabs = { 
	Init: function() {		 
		$$('.tabs').each( Tabs.Create );
	},
	/**
	 * 
	 * @param ele the tabber element itself, has components such as "ul.tabNav", and ".tabBody"
	 */
	Create: function( ele ) { 
		// by default, the active tab is the first one.
		ele.active = 0;
		
		// get all the tab elements
		ele.tabEles = ele.select('.tabNav li');
		
		// get all the tab "content" elements
		ele.tabContentEles = ele.select('.tabBody');

		// before assigning events to the tabs, check to see if a change settings link exists
		// if it does, then we need to hide that div if someone clicks on the tab.
		var changeSettingBody = ele.select('.change');

		/**
		 * go through each change settings element
		 * 
		 * @param {HtmlElement} changeEle
		 */ 
		changeSettingBody.each( function( changeEle ) { 
			// since change elements can either be for all tabs or tab specific, 
			// this is the general call to show the change settings element
			changeEle.showSettings = function() {
				// show the settings element
				ele.addClassName('showChangeSettingsTab');
				
				// we actually wanna hide the second active item we find, which is the content element
				// and also check that the change tab is already shown
				if( ele.__TAB_WIDE_CHANGE && ! ele.__CURRENT_ACTIVE_TAB ) {
					// usually all the tab contents should be in its own div, but its not
					
					// the local module located on the channel page is not a tabbed module, yet it is treated like a tab
					// since there's not tabs, there's only 1 active class on the main content, so pick the first one, not the 2nd
					if (ele.select('.active').length == 1) {
						ele.__CURRENT_ACTIVE_TAB = ele.selectFirst('.active').removeClassName('active');
					} else {
						ele.__CURRENT_ACTIVE_TAB = ele.select('.active')[1].removeClassName('active');
					}
					ele.__CURRENT_ACTIVE_TAB.removeClassName('active');
				}
			};
			
			// this cancel function can get called 1 of 2 ways: A) by clicking cancel
			// B) by choosing another tab when the settings element is being shown.
			changeEle.cancelChanges = function() {
				ele.removeClassName('showChangeSettingsTab');
				
				// show the element since we are done
				if( ele.__CURRENT_ACTIVE_TAB ) { 
					// usually all the tab contents should be in its own div, but its not
					ele.__CURRENT_ACTIVE_TAB.addClassName('active');
					ele.__CURRENT_ACTIVE_TAB = null;
				}
			}
			
			// set the onclick for the cancel function (if the button exists)
			var cancelButtons = changeEle.select('.cancel');
			if (cancelButtons.length > 0) {
				
				cancelButtons.each(function( cancelEle ) {
					cancelEle.voidLink();
					cancelEle.observe('click', changeEle.cancelChanges);
				});
			}
		});
					
		// go through each tab
		ele.tabEles.each( function( tabEle, index ) {
			
			// store the change settings element for this tab if it exists on this tabEle
			var changeEle =  null;
			if (ele.tabContentEles.length > 0) {
				changeEle = ele.tabContentEles[index].selectFirst('.change');
			}
			
			// check to see that this tab is actually shown
			if( tabEle.hasClassName('active') ) {
				// if it is shown, set the current index and show the appropriate tabBody
				ele.active = index;			
			}
			
			// if the change element exists in this tab, then we need to show the settings tab when we click this link
			if( changeEle ) {
				var linkEle = ele.tabContentEles[index].selectFirst('.changeSetting');
				linkEle.voidLink();
				linkEle.observe('click', changeEle.showSettings );
			}
			
			var linkEle = tabEle.selectFirst('a');
			linkEle.voidLink();
			
			// assign the click event to the tabs, show/hide the tab content based on the tab clicked on
			linkEle.observe('click', function() {
				// the last tab we clicked on if one, has to reset it, not this tab.
				if( ele.active ) { 
					var lastTabChangeEle = ele.tabContentEles[ele.active].selectFirst('.change');
					// if this tab has its own change element, then call its cancel function 
					// and reset it before we do anything else
					if( lastTabChangeEle && typeof(lastTabChangeEle.cancelChanges) == 'function' ) {
						lastTabChangeEle.cancelChanges();
					}
				}
							
				// if this tab has has a global tab-wide change then call that one
				if( ele.changeEle ) {
					ele.changeEle.cancelChanges();
				}
				
				// hide everything by reseting active
				ele.tabEles.invoke('removeClassName', 'active');				
				ele.tabContentEles.invoke('removeClassName', 'active');
				
				// highlight the correct tab
				tabEle.addClassName('active');

				// show the correct tab body
				ele.tabContentEles[index].addClassName('active');
				
				// set the active index of the current tab				
				ele.active = index;
						
			});
		});
		
		// check to see if there's a tab-wide change settings link
		var changeSettingTabWideEle = ele.selectFirst('.titleBar .changeSetting');
		if( changeSettingTabWideEle ) {
			
			// set a flag so the ShowSettings method shows/hides the active tab.
			ele.__TAB_WIDE_CHANGE = true;
			// get the tab-wide 
			var changeEle = ele.selectFirst('.change');
			
			// set the onclick but also hide the active div in this case
			changeSettingTabWideEle.voidLink();
			changeSettingTabWideEle.observe('click', changeEle.showSettings );
			
			// since there's only one change link, we need to be able to reference it from within a tab
			// so assign it to the tabber element
			ele.changeEle = changeEle;
		}
	}
};
/* END Tabs */
/* Watermark */
var WatermarkText = {
	Set: function( options ) {
		if( ! WatermarkText.__INIT ) { 
			document.observe('dom:loaded', WatermarkText.Init );			
			WatermarkText.__ELEMENTS = [];
			WatermarkText.__INIT = true;
		}
		
		WatermarkText.__ELEMENTS.push( options );
	},
	Init: function() {
		if( WatermarkText.__ELEMENTS ) {
			WatermarkText.__ELEMENTS.each( function( options ) { 
				var ele = $(options.Id);
				if( ele ) {
					ele.__WATERMARK_TEXT = options.Text;
					ele.observe('focus', function() { 
						if( ele.value == ele.__WATERMARK_TEXT ) {
							ele.value = "";
							ele.removeClassName('watermarkText');
						}
					});
					
					ele.observe('blur', function() { 
						if( ele.value.length == 0 ) {
							ele.value = ele.__WATERMARK_TEXT;
							ele.addClassName('watermarkText');
						}
					});
					
					if( ele.value.length == 0 || ele.value == ele.__WATERMARK_TEXT ) {
						ele.value = ele.__WATERMARK_TEXT;
						ele.addClassName('watermarkText');
					}
				}
			});	
		}
	}	
};
/* END Watermark */
/* Division Select */
var DivisionSelect = {
		url: 'http://'+ document.domain + '/division/',
		emailCounter: null,
		// initialzize function, watch for an onchange event on the state, evaluate the form submission, this is hack for olgivy assigning a submit class
		init: function(){
			if(!$('divisionselect')) return;
			Event.observe('divisionStates','change',DivisionSelect.updateDivisionSelect);
			Event.observe('divisionemailaddress','focus',DivisionSelect.clearDivisionSelect);
			Event.observe('divisionselectbtn','click',DivisionSelect.eventsubmit);
		},
		eventsubmit: function(event) {
			event.stop();
			DivisionSelect.validateSubmission();
		},
		// get the associated division systems
		updateDivisionSelect: function(){
			$('divisionselect').divisionemailaddress.value = '';
			$('errorMessageDisplay').innerHTML = '';
			new Ajax.Request('/assets/javascript/ajax/data.cfm?method=divisionSystemAJAXRequest&stateid=' + $F('divisionStates') , {
				method: 'get', 
				onSuccess: function(transport){
					var json = transport.responseText.evalJSON();
					DivisionSelect.buildSelectOptions(json);
				}
			});
		},	 
		clearDivisionSelect: function(){		
			$('errorMessageDisplay').innerHTML = '';
 			while ($('divisionSystem').childNodes.length > 0) {
 				$('divisionSystem').removeChild($('divisionSystem').childNodes[0]);
  			}
 			var option = new Element('option',{'value':''}).update('Please Select A State From Above');
			$('divisionSystem').appendChild(option);
			$('divisionselect').divisionStates.value = '';
		},
		//check to see if we have a one to one match on email domain
		checkEmailDomain: function(emailaddress){
			new Ajax.Request('/assets/javascript/ajax/data.cfm?method=checkEmailDomainAJAXRequest&emailaddress=' + DivisionSelect.getEmailDomain(emailaddress) , {
				method: 'get', 
				onComplete: function(transport){					 
					 json = transport.responseText.evalJSON();			
					 DivisionSelect.setDomainCounter(json);
 				}
			});
		},
		setDomainCounter: function(count){
			DivisionSelect.emailCounter = count;
				$('errorMessageDisplay').innerHTML = '';
				if(DivisionSelect.emailCounter == 1){
					$('divisionemailaddress').value = '';
					$('errorMessageDisplay').innerHTML = 'Your email address is associated to multiple divisions. Please select your state and division below.';
					return false;
				}
				else if(DivisionSelect.emailCounter == 0){
					$('divisionemailaddress').value = '';
					$('errorMessageDisplay').innerHTML = 'Your email address was not recogonized by our system. Please try again or select your state and division below.';
					return false;
				}		
				else{
					window.location.href = '/division/' + count;
				}
		},
		// push options to the division system select
		buildSelectOptions: function(jsonObject){ 			
			while ($('divisionSystem').childNodes.length > 0 ){
				$('divisionSystem').removeChild($('divisionSystem').childNodes[0]);			
			}					
			//loop over json object to build options
			jsonObject.data.division_system_code.each(
				function(ele,i){							 
					var option = new Element('option',{'value':ele}).update(jsonObject.data.division_system_name[i]);
					$('divisionSystem').appendChild(option);
			});
		},
		//start validating the users input
		validateSubmission: function(event){
			$('errorMessageDisplay').innerHTML = 'Please Wait...';		
			if($('divisionselect').divisionStates.value != '' && $('divisionselect').divisionSystem.value != '') {
				var divisionURL = DivisionSelect.url + $('divisionSystem').value;
				window.location.href = divisionURL;
				return false;
			}
			if($('divisionselect').divisionemailaddress.value == '' && $('divisionselect').divisionStates.value == ''){
				$('errorMessageDisplay').innerHTML = 'Please enter your email address or select your state and division.';
				return false;
			}
			if($('divisionselect').divisionemailaddress.value != ''){
				if(!DivisionSelect.validateEmail($('divisionselect').divisionemailaddress.value)) {
 					$('errorMessageDisplay').innerHTML = 'Please enter a valid email address.';
 					$('divisionselect').divisionemailaddress.value = '';
 					$('divisionselect').divisionemailaddress.focus();
 					return false;
 				}
				else{
					$('errorMessageDisplay').innerHTML = '';
				}
			}				
			if($('divisionselect').divisionemailaddress.value != ''){
				DivisionSelect.checkEmailDomain($('divisionselect').divisionemailaddress.value);
			}	
			return false;
		},
		validateEmail: function(email) {
			var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
			return (filter.test(email));
		},
		getEmailDomain: function(email){
			return email.split('@')[1];
		}
	}
/* END Division Select */
/* Radio */
var Radio = {
	timeout: 300000, // milliseconds
	interval: null,
	headerStream: 5, // Hit List
	initStreams: [2,1,53,6,5,12,3,29,13,7],
	viewEle: null,
	showAll: false,
	data: {},
	jsonURL: '/radiodata.json?',
	popup: null,
	streamPath: 'http://www.rr.com/radio/index.cfm?startstream=',
	loadChannel: function(event) {
		var channelID;
		if (Object.isNumber(event)) {
			channelID = event;
		} else {
			var ele = Event.element(event);
			channelID = $(ele).findParent('audio').getAttribute('id');	
		}
		var url = Radio.streamPath + channelID;
		var name = 'RRRADIO';
		var args = 'width=320,height=425,resizable=no,scrollbars=no,toolbar=no,location=no,directories=no,status=no,menubar=no';
		Radio.popup = window.open(url,name,args);
	},
	init: function() {
		Radio.navSetup();
		if (!$('radioModule')) return;
		Radio.viewEle = $$('div#radioModule div.titleBar a.btn')[0];
		Radio.setupEvents();
		Radio.loadData();
		Radio.interval = setInterval(Radio.loadData,Radio.timeout);
	},
	navSetup: function() {
		$$('div.header div.content ul.menu li a[href="#"]').each(function(el) {
			if (el.childNodes[0].nodeValue !== 'Radio') return;
			$(el).observe('click',Radio.preventDefault);
			$(el).observe('click',function() {
				Radio.loadChannel(Radio.headerStream);
			});
		});
	},
	loadData: function() {
		var time = new Date().getTime();
		new Ajax.Request(Radio.jsonURL+time, {
			method: 'get',
			onSuccess: function(tr) {
				Radio.data = tr.responseText.evalJSON();
				Radio.callback();
			}
		});
	},
	setupEvents: function() {
		$(Radio.viewEle).observe('click',Radio.viewAll);
		$($('radioModule').select('a.btn')[0]).observe('click',Radio.preventDefault);
	},
	preventDefault: function(ev) {
		ev.stop();
	},
	viewAll: function() {
		$(Radio.viewEle).stopObserving('click',Radio.viewAll);
		$(Radio.viewEle).observe('click',Radio.viewSome);
		$(Radio.viewEle).select('span')[0].update('Top '+ Radio.initStreams.length);
		
		Radio.showAll = true;
		Radio.loadData();
	},
	viewSome: function() {
		$(Radio.viewEle).stopObserving('click',Radio.viewSome);
		$(Radio.viewEle).observe('click',Radio.viewAll);
		$(Radio.viewEle).select('span')[0].update('View All');
		
		Radio.showAll = false;
		Radio.loadData();
	},
	callback: function() {
		Radio.clear();
		Radio.sorter();
		Radio.genresDisplay();
		Radio.streamsDisplay();
		Radio.hideGenres();
	},
	clear: function() {
		while($('radioChannels').childNodes.length>0) {
			$('radioChannels').removeChild($('radioChannels').childNodes[0]);
		}
	},
	genresDisplay: function() {
		var last = $H(Radio.data.genres).values().length;
		var genreDiv = new Element('div', { 'class': 'item' });
		var heading  = new Element('h6');
		var anchor   = new Element('a', { 'class': 'genre' } ).setStyle({ 'cursor': 'default' });
		
		$H(Radio.data.genres).each(function(genre,i) {
			var div = $('radioChannels').appendChild(genreDiv.cloneNode(true));
			$(div).setAttribute('id',genre[1].id);
			if (i==0) $(div).addClassName('first');
			var h6 = $(div).appendChild(heading.cloneNode(true));
			var a = $(h6).appendChild(anchor.cloneNode(true));
			$(a).update(genre[1].title);
		});
	},
	streamsDisplay: function() {
		var p     = new Element('p',{'class': 'audio'});
		var str   = new Element('strong');
		var a     = new Element('a');
		var mdash = document.createTextNode('\u00a0\u2013\u00a0');
		
		$H(Radio.data.streams).each(function(stream,i) {
			var streamID = parseInt(stream.key,10);
			var stream = stream.value;
			
			var genreID = Radio.data.genres[stream.genreID].id;
			var node = $(genreID).appendChild(p.cloneNode(true));
				node.setAttribute('id',stream.startID);
			var chan = node.appendChild(str.cloneNode(true));
			if (stream.explicit.toBool()) chan.addClassName('explicit');
			var chanlink = $(chan).appendChild(a.cloneNode(true));
			$(chanlink).observe('click',Radio.loadChannel);
			$(chanlink).update(stream.title);
			$(chan).appendChild(mdash.cloneNode(true));
			var song = $(node).appendChild(a.cloneNode(true));
			$(song).update(stream.song.artist +' | '+ stream.song.title);
			$(song).observe('click',Radio.loadChannel);
			
			if (Radio.showAll == true) return;
			if (Radio.initStreams.indexOf(streamID) == -1) $(node).hide();
		});
	},
	hideGenres: function() {
		$A($('radioChannels').select('div.item')).each(function(genre) {
			var paragraphs = $(genre).select('p');
			var count = 0;
			paragraphs.each(function(p) {
				if (! $(p).visible()) count++;
			});
			if (count == paragraphs.length) {
				$(genre).hide();
			}
		});
	},
	sorter: function() {
		// Genre Sort
		var temp = {};
		var gOrder = $H(Radio.data.genres).keys().sort(Radio.genreTitleSort);
		gOrder.each(function(key) {
			temp[key] = Radio.data.genres[key];
		});
		Radio.data.genres = temp;
		
		// Channel Sort
		var temp = {};
		var sOrder = $H(Radio.data.streams).keys().sort(Radio.streamTitleSort);
		sOrder.each(function(key) {
			temp[key] = Radio.data.streams[key];
		});
		Radio.data.streams = temp;
	},
	genreTitleSort: function(a,b) {
		var Atitle = Radio.data.genres[a].title;
		var Btitle = Radio.data.genres[b].title;
		return (Atitle<Btitle) ? -1 : (Btitle<Atitle) ? 1 : 0;
	},
	streamTitleSort: function(a,b) {
		var Atitle = Radio.data.streams[a].title;
		var Btitle = Radio.data.streams[b].title;
		return (Atitle<Btitle) ? -1 : (Btitle<Atitle) ? 1 : 0;
	}
};

/* END Radio */
/* Video */
var Video = {
	url: null,
	popup: null,
	load: function() {
		var name = 'RRVIDEO';
		var args = 'width=1005,height=720';
		Video.popup = window.open(Video.url,name,args);
	},
	init: function() {
		Video.navSetup();
	},
	navSetup: function() {
		$$('div.header div.content ul.menu li a').each(function(el) {
			var url = $(el).readAttribute('href');	
			var label = el.childNodes[0].nodeValue;	
			if (Video.isVideoNavElement(url, label)) {	
				Video.url = url;
				$(el).observe('click',function(ev) {
					Video.preventDefault(ev);
				});
				$(el).observe('click',function() {
					Video.load()
				});
				$(el).writeAttribute('href','#');
				$(el).writeAttribute('target', null);
			}
		});
	},
	isVideoNavElement: function(url,label) {
		var result = true;
		if (url == '' || url == '#') {
			result = false;
		} 
		if (label !== 'Video') {
			result = false;
		} 
		return result;
	},
	preventDefault: function(ev) {
		ev.stop();
	}
};

/* END Video */
/* Header Tools */
var Email = {
	message: '',
	ajaxURL: 'http://'+ document.domain +'/cfc/rp/emailer.cfc?method=article',
	init: function() {
		if (!$('emailForm')) return;
		// Form submission
		$$('form#emailForm a.nosubmit')[0].observe('click',Email.stopSubmit);
		
		var x = 'abc@abc.com';
			// Email link
		$('emailForm').getFirstAncestor('li').select('a')[0].observe('click',Email.activate);
		// Cancel Button
		$('emailForm').getFirstAncestor('li').select('a')[2].observe('click',Email.deactivate);
		// Submit Button
		$('emailForm').getFirstAncestor('li').select('a')[1].observe('click',Email.validate);
		
		$('formThankYou').hide();
		Email.fixErrorMessage();
	},
	fixErrorMessage: function() {
		$('emailErrorMsg').removeClassName('errorMessage');
		$('emailErrorMsg').setStyle({ 'color': '#CA0000', 'margin-top': '5px' });
		$('emailErrorMsg').hide();
	},
	stopSubmit: function(event) {
		// Stop the form from being submitted
		event.stop();
	},
	validate: function() {
		var errors = 0;

		$$('form#emailForm input.emailInput').each(function(inp) {
			if (!$(inp).value.isEmail()) {
				errors++;
				$$('LABEL[for="'+ $(inp).getAttribute('id') +'"]')[0].addClassName("error");
				$(inp).addClassName("error");
			} else {
				$$('LABEL[for="'+ $(inp).getAttribute('id') +'"]')[0].removeClassName("error");
				$(inp).removeClassName("error");
			}
		});
		
		Email.message = 'Email address(es) invalid or missing.';
		if (errors>0) Email.showError();
		else Email.submitForm();
	},
	showError: function() {
		$('emailErrorMsg').removeAllChildren();
		$('emailErrorMsg').appendChild(document.createTextNode(Email.message));
		$('emailErrorMsg').show();
	},
	submitForm: function() {
		var data = $('emailForm').serialize(true);
			data.title = $('emailForm').findParent('article').selectFirst('h1').childNodes[0].nodeValue;
		new Ajax.Request(Email.ajaxURL,{
			method: 'get',
			parameters: data,
			onSuccess: function(transport) {
				var res = transport.responseText.strip().evalJSON();
				if (res.sent == true) {
					Email.successful();
				} else {
					Email.message = 'Errors: '+ res.reason;
					showError();
				}
			}
		});
	},
	successful: function() {
		$('formThankYou').show();
		$('emailForm').hide();
		setTimeout(Email.deactivate,6000);
	},
	deactivate: function(event) {
		try { event.preventDefault(); } catch(er) {};
		$('emailForm').getFirstAncestor('div').hide();
		$('emailForm').getFirstAncestor('li').removeClassName('active');
		
		$('formThankYou').hide();
		$('emailForm').show();
		$('emailErrorMsg').hide();
	},
	activate: function() {
		$('emailForm').getFirstAncestor('li').addClassName('active');
		$('emailForm').getFirstAncestor('div').show();
	}       
};

var Share = {
	st: null,
	url: null,
	headline: null,
	Init: function() {
		if ($$('ul.shareTools').length == 0) return;
		Share.setVars();
		Share.setupLinks();
	},
	setVars: function() {
		Share.st		= $$('ul.shareTools')[0];
		Share.url		= encodeURI(window.location.href.replace(/\?.*/,''));
		Share.headline	= encodeURI($$('div.article h1')[0].childNodes[0].nodeValue);

	},
	setupLinks: function() {
		$A($(Share.st).select('a')).each(function(a) {
			$(a).observe('click',Share.handleLink);
		});
	},
	handleLink: function(event) {
		// Keep from hitting the #
		event.stop();
		var callr = Event.element(event);
		var txt = callr.childNodes[0].nodeValue;

		var url = '';
		switch(txt) {
			case 'delicious':
				url = 'http://del.icio.us/login/?url='+ Share.url +'&title='+ Share.headline;
				break;
			case 'digg':
				url = 'http://digg.com/submit?phase=2&url='+ Share.url +'&title='+ Share.headline +'&bodytext=';
				break;
			case 'Facebook':
				url = 'http://www.facebook.com/sharer.php?u='+ Share.url;
				break;
			case 'MySpace':
				url = 'http://www.myspace.com/Modules/PostTo/Pages/?t='+ Share.headline +'&c=%20&u='+ Share.url +'&l=2';
				break;
			case 'reddit':
				url = 'http://reddit.com/submit?url='+ Share.url +'&title='+ Share.headline;
				break;
			case 'StumbleUpon':
				url = 'http://www.stumbleupon.com/submit?url='+ Share.url +'&title='+ Share.headline;
				break;
			case 'twitter':
				url = 'http://twitter.com/home?tab=home&source=web&status='+ Share.url;
				break;
			default: break;
		}
		if (url=='') return;
		window.location.href = url;
	},
	deactivate: function(event) {
		try { event.stop(); } catch(er) {};
		$('shareLinks').removeClassName('active');
	}
};


var HeaderTools = {
	Init: function(){
		// Return if no headerTools found.
		if (!$(document.body).selectFirst('.article .headerTools')) return;
		
		// Inits for specific tools
		Email.init();
		Share.Init();
		
		// if the header tools exists (on the article page) then we'll need to init some functionality
		var headerTools = $(document.body).selectFirst('.article .headerTools');
		
		// use a generic reset so that we if we decide to change how we reset "active", it's in one spot
		$(headerTools).resetActive = function() {
			$(headerTools).select('li').invoke('removeClassName', 'active');
		}
		
		//go through each drop down element
		headerTools.select('.dropdown').each(function(ele){
		
			// go get the links for the tools
			ele.up().selectFirst('a.tool').observe('click', function(){
			
				// reset active
				headerTools.resetActive();
				
				// show the item that we clicked on
				ele.up().addClassName('active');
			});
			
			// if the cancel button is clicked, then we need to reset the form
			// and hide the element
			ele.selectFirst('.cancel').observe('click', function(){
				ele.up().removeClassName('active');
				
				// if there's a form in this element, then it needs to be reset
				var formEle = ele.up().selectFirst('form');
				if (formEle) {
					// reset the form
					formEle.reset();
					
					// hide the error messages
					if (formEle.selectFirst('.errorMessage')) formEle.selectFirst('.errorMessage').hideElement();
					
					// reset the labels so they aren't red anymore
					if (formEle.select('.error')) formEle.select('.error').invoke('removeClassName', 'error');
				}
			});
		});
		var printEle = headerTools.selectFirst('.print')
		if (printEle) {
			printEle.observe('click', function(){
				// reset active
				headerTools.resetActive();
				window.print();
				return false;
			});
		}
	}
};
/* END Header Tools */

var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

//--------load
document.observe( 'dom:loaded', function() { 
	Carousel.Init();
	Tabs.Init();
	Site.Init();
	HomePage.Init();
	Search.Init();
	Video.init();
	Radio.init();
	HeaderTools.Init();
	DivisionSelect.init();
});
