/*Following js files are clubbed in this file:
1. setfilter.js
2. Calendar.js
3. launch_calendar.js
4. TagCloud.js
*/

/*----------------------------------------------------- setfilter.js starts ---------------------------------------------------*/
if(detectBrowser.modernBrowser()){
	
var SetFilterFactory = Class.create();
SetFilterFactory.prototype = {
	initialize:function(){
		this.filters = $$('.setfilter').map(function(el){
			return new SetFilter(el);
		});
	}
};

/*
format for a filter checkbox:
<input type="checkbox" class="setfilter_check 40" />
*/
var SetFilter = Class.create();
SetFilter.prototype = {
	initialize:function(filterContainer,updateFilterClosure,listenEventAtContainer){
		if(filterContainer){
			var parseWeight = function(elem){ // parse classnames to find the weight of a given checkbox
				return $A(elem.classNames()).find(function(token){
					return parseInt(token) > -1;
				});
			};
			var getTotalWeight = function(){ // return the total weight of the checked checkboxes
				var checkedTotal = this.filterCheckboxes.inject(0,function(acc,filterCheck){
					return acc + parseInt(filterCheck.checked?parseWeight(filterCheck):0);
				});
				return (checkedTotal==0)?this.totalTotal:checkedTotal;
			}.bind(this);
			this.filterCheckboxes = filterContainer.getElementsBySelector("input.setfilter_check").map(function(fc){
				if(listenEventAtContainer){
					Event.observe(fc.parentNode,'click',function(ev){
						if(ev.target!=fc){
							fc.checked = !fc.checked;
						}
						updateFilterClosure(getTotalWeight()); // when a checkbox is checked, we recalculate the filter
					}.bind(this));								
				} else {
					Event.observe(fc,'click',function(ev){
						updateFilterClosure(getTotalWeight()); // when a checkbox is checked, we recalculate the filter
					}.bind(this));				
				}
				return fc;
			}.bind(this));
			this.totalTotal = this.filterCheckboxes.inject(0,function(acc,filterCheck){
				return acc + parseInt(parseWeight(filterCheck));
			});
			updateFilterClosure(getTotalWeight());
		}
	}
};

}
/*----------------------------------------------------- setfilter.js ends -----------------------------------------------------*/

/*----------------------------------------------------- Calendar.js starts ----------------------------------------------------------*/
/*
 * @Class: Calendar
 * 
 * @Description: An interactive calendar widget
 * 
 * @Usage: new Calendar(containerElement)
 *	
 * @Methods: no public methods
 * 
 */

var Calendar = (!detectBrowser.modernBrowser())?function(){}:Class.create();
Calendar.prototype = (!detectBrowser.modernBrowser())?{}:{
	initialize: function(div) {
		// don't draw calendar if div doesn't exist
		if(!div){ return false; }

		// This is the element into which all of the calendar's DOM elements are inserted
		this.container = div;

		this.today = new Date();
		this.month = this.today.getMonth();
		this.year = this.today.getFullYear();

		// Back and forward buttons to navigate months
		this.backward = new Element("a", {"class": "backward",'href':'#'});
		Event.observe(this.backward, "click", function(e) {
			this.changeMonth(this.month - 1);
			Event.stop(e);
			return false;
		}.bind(this));
		this.forward = new Element("a", {"class": "forward",'href':'#'});
		Event.observe(this.forward, "click", function(e) {
			this.changeMonth(this.month + 1);
			Event.stop(e);
			return false;
		}.bind(this));

		this.display_month = new Element("span").insert(Calendar.prototype.monthNames[this.month]);
		this.display_year = new Element("span").insert(this.year);
	
		// navigational elements
//		var tableNav_wrapper = new Element("div",{'id':'tableNav_wrapper'});
		var tableNav_wrapper = $('tableNav_wrapper');
		tableNav_wrapper.innerHTML = "";
		var tableNav = new Element("div", {'id': "tableNav"});
		tableNav.insert(this.backward);
		tableNav.insert(this.forward);
		tableNav.insert(this.display_month);
		tableNav.insert(this.display_year);
		tableNav_wrapper.insert(tableNav);
		this.container.insertBefore(tableNav_wrapper, this.container.firstChild);

		var tableAlreadyExists = false;
		this.table = this.container.getElementsBySelector("table")[0];

		// collect of all the days in the entire month
		this.cells = this.table.getElementsBySelector("td");
		// collection of all the week rows (empty or not)
		this.rows = this.table.getElementsBySelector("tr");

		// lazy-loaded list of events
		this.monthEventLists = {};

		this.populateTable();
	},

	// draw calendar
	populateTable: function() {
		var date = new Date(this.year, this.month, "1");
		var firstDay = date.getDay();
		date.setFullYear(this.year, this.month, "32");
		var numDays = 32 - date.getDate();

		// use much faster direct node manipulation instead of prototype's innerHTML-based method
		var newDrawMethod = false;

		var cellTexts = [];

		// give calendar cells numbers and styles, style the cell for today.
		for(var i = 0; i < this.cells.length; i++) {
			if(newDrawMethod && this.cells[i].firstChild && this.cells[i].firstChild.nodeType==1 && $(this.cells[i].firstChild).hasClassName('this_day_wrap')){
				this.cells[i].innerHTML = "";
			}
			var cellDigits = ((i - firstDay + 1)>9)?(i - firstDay + 1):"0"+(i - firstDay + 1).toString();
			var cellText = (i >= firstDay && i < (numDays + firstDay))?(cellDigits):String.fromCharCode(160);
			cellTexts[i] = cellText;
			if(newDrawMethod){
				if(this.cells[i].firstChild){
					this.cells[i].firstChild.nodeValue = cellText;
				} else {
					this.cells[i].appendChild(document.createTextNode(cellText));
				}
			} else {
				this.cells[i].update(cellText);
			}

			if(this.cells[i].hasClassName("event")){
				this.cells[i].removeClassName("event");
			}
			if(this.cells[i].hasClassName("today")){
				this.cells[i].removeClassName("today");
			}
			this.cells[i].stopObserving();

/*
			// handle keyboard focus for the link inside of the cell
			Event.observe(
				this.cells[i].firstChild,
				'focus',
				(function(cellIndex){
					return function(ev){
						if(
							typeof(this.cellOverlayHandlers)=='object' 
							&& this.cellOverlayHandlers!=null 
							&& this.cellOverlayHandlers.length > 0 
							&& typeof(this.cellOverlayHandlers[cellIndex])=='function'
						){
							this.cellOverlayHandlers[cellIndex](ev);
						}
					}.bind(this)
				}.bind(this))(i)
			);

			// warning: Calling a Prototypical function here out of laziness -- Dependence on FloatingInfo class internals
			Event.observe(
				this.cells[i].firstChild,
				'blur',
				(function(cellIndex){
					return function(ev){
						FloatingInfo.prototype.hideOverlay();
						ev.stop();
					}.bind(this);
				}.bind(this))(i)
			);
*/

		}
	
		// Style "today's" cell properly, (if we're displaying the current month)
		if(this.month == this.today.getMonth() && this.year == this.today.getFullYear()){
			var thisDay = this.cells[this.today.getDate() + (firstDay - 1)];
			thisDay.addClassName("today");
			var thisDayWrap = new Element("div", {"class":"this_day_wrap"}).insert(thisDay.innerHTML);
			thisDay.innerHTML = "";
			thisDay.insert(thisDayWrap);
			var thisDayHeight = Math.round(this.table.getHeight() / 6);
			thisDayWrap.setStyle({
				'height':(thisDayHeight - 2) + 'px',
				'lineHeight':(thisDayHeight - 2) + 'px'
			});
		}

		// fetch events for this month and convert into a handy array of hashes
		//if(typeof(this.monthEventLists[this.month])=='undefined'){
			this.monthEventLists[this.month] = this.getEventListItems().select(function(listItem){
				var startDateElement = listItem.getElementsBySelector("abbr.dtstart")[0];
				var endDateElem = listItem.getElementsBySelector("abbr.dtstart")[0];
				var endDateAttrs = endDateElem?endDateElem.getAttribute("title").split("-"):null;
				var yearofevent=(endDateAttrs && endDateAttrs.length>=3)?parseInt(endDateAttrs[0]):undefined;
				return(startDateElement && startDateElement.getAttribute("title").indexOf("-"+(this.month+1)+"-") > -1
				&& yearofevent==this.year);
			}.bind(this)).collect(function(listItem){
				//
				// Parse hCalendar microformat
				//
				var linkElem = listItem.getElementsBySelector("a.url")[0];
				var startDateElem = listItem.getElementsBySelector("abbr.dtstart")[0];
				var endDateElem = listItem.getElementsBySelector("abbr.dtstart")[0];
				var summaryElem = listItem.getElementsBySelector("h3.summary")[0];
				var descriptionElem = listItem.getElementsBySelector("p.description")[0];
				var startDateAttrs = startDateElem?startDateElem.getAttribute("title").split("-"):null;
				var endDateAttrs = endDateElem?endDateElem.getAttribute("title").split("-"):null;
				return {
					'start_day':(startDateAttrs && startDateAttrs.length>=3)?parseInt(startDateAttrs[2]):undefined,
					'start_month':(startDateAttrs && startDateAttrs.length>=3)?parseInt(startDateAttrs[1]):undefined,
					'start_year':(startDateAttrs && startDateAttrs.length>=3)?parseInt(startDateAttrs[0]):undefined,
					'end_day':(endDateAttrs && endDateAttrs.length>=3)?parseInt(endDateAttrs[2]):undefined,
					'end_month':(endDateAttrs && endDateAttrs.length>=3)?parseInt(endDateAttrs[1]):undefined,
					'end_year':(endDateAttrs && endDateAttrs.length>=3)?parseInt(endDateAttrs[0]):undefined,
					'summary':summaryElem?summaryElem.innerHTML.strip():"",
					'description':descriptionElem?descriptionElem.innerHTML.strip():"",
					'url':linkElem?linkElem.getAttribute("href").strip():"#",
					'linktext':linkElem?linkElem.innerHTML.strip():""
				};
			}.bind(this));
		//}

		if(this.monthEventLists[this.month].length > 0) {
			// assign overlay events for any day cells that contain events

			// cellOverlayHandlers is an array that holds all the current closures that pop up overlays to show events
			this.cellOverlayHandlers = [];
			for(var i = 0; i < this.cells.length;i++) {
				if(i >= (firstDay)){
					var cell = this.cells[i];
					var dayIndex = i - firstDay;
					var calendarDay = dayIndex + 1;
					// grab all the events for this given day
					var todaysEvents = this.monthEventLists[this.month].select(function(item){return item.start_day==calendarDay;});

					if(todaysEvents.length > 0){

						// overlay closure to float information about this event
						var todaysEventOverlay = function(cellElement, private_month, eventCollection) {
							return function (event) {
								var currentEventIndex = 0;
								new FloatingInfo(cellElement, {
									'float':'auto',
									'padding':0,
									'floatDirection':'auto',
									'arrowClass':'float_arrow',
									'overlayClasses':{
										'top':'floatType_calendar_top',
										'inner':'floatType_calendar_inner',
										'bottom':'floatType_calendar_bottom'
									},
									// this function is called *once* by FloatingInfo in order to allow for custom rendering in the calendar overlay
									'contentRender':function(contentElement_){
										// this render function is called by the buttons in the calendar overlay
										this.renderOverlayContents(contentElement_,eventCollection,currentEventIndex);
									}.bind(this)
								});
								Event.stop(event);
							}.bind(this);
						}.bind(this)($(cell), this.month, todaysEvents);

						// for keyboard handling: the text of the cell has to be a link so that IE can focus on it (accessibility/508)
						cell.update("<a href='#'>" + cellTexts[i] + "</a>");

						// handle keyboard focus for the link inside of the cell
						Event.observe(
							this.cells[i].firstChild,
							'focus',
							(function(cellIndex){
								return function(ev){
									if(
										typeof(this.cellOverlayHandlers)=='object' 
										&& this.cellOverlayHandlers!=null 
										&& this.cellOverlayHandlers.length > 0 
										&& typeof(this.cellOverlayHandlers[cellIndex])=='function'
									){
										this.cellOverlayHandlers[cellIndex](ev);
									}
								}.bind(this)
							}.bind(this))(i)
						);

						// warning: Calling a Prototypical function here out of laziness -- Dependence on FloatingInfo class internals
						Event.observe(
							this.cells[i].firstChild,
							'blur',
							(function(cellIndex){
								return function(ev){
									FloatingInfo.prototype.hideOverlay();
									ev.stop();
								}.bind(this);
							}.bind(this))(i)
						);

						cell.addClassName("event");
						var hoverObj = new mouseOverClassify();
						hoverObj.classify(cell, 'eventHover');

						// hover a floating info overlay for day cells which have events associated with them
						Event.observe(cell, "mouseover", todaysEventOverlay);
						this.cellOverlayHandlers[i] = todaysEventOverlay;

					} else {
						this.cellOverlayHandlers[i] = null;
					}
				}
			} // end overlay assignment loop

		}

		// style calendar as 6 rows, always
		this.rows[4].className = "";
		this.rows[5].className = "";
		this.rows[6].className = "row_last";
		this.table.className = "rows_6";
	},
	
	renderOverlayContents:function(contentElement,eventCollection,currentEventIndex){
		contentElement.innerHTML = "";
		var eventObject = eventCollection[currentEventIndex];
		var title = new Element("h3",{});
		title.update(eventObject.summary);
		var body = new Element("p",{});
		body.update(eventObject.description);
		var link = new Element("a",{'className':'event_url','href':eventObject.url});
		if (eventObject.url == '#' ){}
		else {link.update("&rsaquo; "+eventObject.linktext);}
		//
		// Back/forward buttons on calendar overlay
		// these are only drawn if we have more than one event on this day
		//
		if(eventCollection.length > 1){
			var eventNavContainer = new Element("div",{'className':'event_nav_container'});
			var locationLabel = new Element("div",{'className':'event_label'});
			var prevBtn = new Element("a",{'href':'#','className':'event_prev'});
			var nextBtn = new Element("a",{'href':'#','className':'event_next'});
			// locationLabel is the label that says, for example: "Event 1 of 5"
			locationLabel.update("Event "+(currentEventIndex+1)+" of "+eventCollection.length);
			prevBtn.update(" ");
			nextBtn.update(" ");
			var callRender = function(incrementor){
				currentEventIndex = currentEventIndex + incrementor;
				Event.stopObserving(prevBtn,'click',prevFunc);
				Event.stopObserving(nextBtn,'click',nextFunc);
				//
				// re-render the inner content region of the calendar overlay
				//
				this.renderOverlayContents(contentElement,eventCollection,currentEventIndex); 
			}.bind(this);
			//
			// forward / back click event handlers
			//
			var prevFunc = function(ev){
				if(currentEventIndex>0){
					callRender(-1);
				} else {
					currentEventIndex = eventCollection.length - 1;
					callRender(0);
				}
				ev.stop();
				return false;
			};
			var nextFunc = function(ev){
				if(currentEventIndex < eventCollection.length - 1){
					callRender(1);
				} else {
					currentEventIndex = 0;
					callRender(0);
				}
				ev.stop();
				return false;
			};
			Event.observe(nextBtn,'click',nextFunc);
			Event.observe(prevBtn,'click',prevFunc);

			eventNavContainer.appendChild(prevBtn);
			eventNavContainer.appendChild(locationLabel);
			eventNavContainer.appendChild(nextBtn);
			contentElement.appendChild(eventNavContainer);
		}
		contentElement.appendChild(title);
		contentElement.appendChild(body);
		contentElement.appendChild(link);
	},

	// fetch the list item elements representing events
	getEventListItems:function(){
		if(typeof(this.eventListCache)=='undefined'){
			this.eventListCache = this.container.getElementsBySelector("ul.eventlist li");
		}
		return this.eventListCache;
	},

	// navigate to newMonth and redraw the calendar situated in newMonth
	changeMonth: function(newMonth) {
		this.month = newMonth;
	
		if(this.month == -1) {
			this.month = 11;
			this.year--;
		} else if(this.month == 12) {
			this.month = 0;
			this.year++;
		}
	
		this.display_month.update(Calendar.prototype.monthNames[this.month]);
		this.display_year.update(this.year);
	
		this.populateTable();
	},

	monthNames: [
		"January", 
		"February", 
		"March", 
		"April", 
		"May", 
		"June", 
		"July", 
		"August", 
		"September", 
		"October", 
		"November", 
		"December"
	]
};

if(detectBrowser.modernBrowser()){
	Event.observe(window, 'load', function() { 
	 	$$('.NASACalendar').each(function(calendarElement){
			var c = new Calendar(calendarElement);
		});
	});
}
/*----------------------------------------------------- Calendar.js ends ------------------------------------------------------------*/

/*----------------------------------------------------- launch_calendar.js starts ---------------------------------------------------*/
if(detectBrowser.modernBrowser()){


//                        year  mo day  hr  min sec
//
//
//											NOTE: 0 = january
//											11 = december
//
document.observe('contentloaded', function() {
	var clock_day = $("day");
	var clock_hour = $("hour");
	var clock_minute = $("minute");
	var clock_second = $("second");
	if(clock_day && clock_hour && clock_minute && clock_second){
		var launchDate = new Date(2007, 9, 31, 18, 30, 15, 0);

		function getDHMS(targetDate){
			var nowDate = new Date();
			var secondsTillLaunch = Math.floor(targetDate.getTime() / 1000) - Math.floor(nowDate.getTime() / 1000);
			var daysLeft = Math.floor(secondsTillLaunch / (60 * 60 * 24));
			var leftoverHours = Math.floor((secondsTillLaunch - (daysLeft * 60 * 60 * 24)) / (60 * 60));
			var leftoverMinutes = Math.floor( (secondsTillLaunch - (daysLeft * 60 * 60 * 24) - (leftoverHours * 60 * 60)) / 60);
			var leftoverSeconds = Math.floor( (secondsTillLaunch - (daysLeft * 60 * 60 * 24) - (leftoverHours * 60 * 60) - (leftoverMinutes * 60)));
			var pastFlag = false;
			if(secondsTillLaunch < 0){
				pastFlag = true;
			}
			return {
				'daysleft':daysLeft,
				'hoursleft':leftoverHours,
				'minutesleft':leftoverMinutes,
				'secondsleft':leftoverSeconds,
				'pastFlag':pastFlag
			};
		}
	
		new PeriodicalExecuter(function(){
			var d = getDHMS(launchDate);
			if(d.pastFlag){
				clock_day.update("00");
				clock_hour.update("00");
				clock_minute.update("00");
				clock_second.update("00");
			} else {
				if(d.daysleft < 10) clock_day.update("0" + d.daysleft);
				else clock_day.update(d.daysleft);

				if(d.hoursleft < 10) clock_hour.update("0" + d.hoursleft);
				else clock_hour.update(d.hoursleft);

				if(d.minutesleft < 10) clock_minute.update("0" + d.minutesleft);
				else clock_minute.update(d.minutesleft);

				if(d.secondsleft < 10) clock_second.update("0" + d.secondsleft);
				else clock_second.update(d.secondsleft);
			}
		}, 1);
	}
});

}
/*----------------------------------------------------- launch_calendar.js ends -----------------------------------------------------*/

/*----------------------------------------------------- TagCloud.js starts ----------------------------------------------------------*/
if(detectBrowser.modernBrowser()){



document.observe("contentloaded",function(){

	/* seedable random number functionality */

	var RandSeed = 0;
	var initRandSeed=null;

	// used by seedble random number functionality
	function PrfxTo(S, L, C) {
		S += ""
		if (C.length>0){
			while (S.length<L) {
				S = C + S ;
			}
		}
		return S;
	}

	// used by seedble random number functionality
	function StrU(X, M, N) { // X > -0.5e-N ; to M digits point N digits
		var S = String(Math.round(X*Math.pow(10, N)));

		if (/\D/.test(S)){
			return SpcsTo(X, M+N+1); // cannot cope
		}
		S = PrfxTo(S, M+N, '0');
		var T = S.length - N;
		return S.substring(0, T) + '.' + S.substring(T);
	}

	// used by seedble random number functionality
	function SpcsTo(S, L) {
		S += "" // SpcsTo is a reduction of PrfxTo
		while (S.length<L) {
			S = " " + S;
		}
		return S;
	}

	// used by seedble random number functionality
	function StrT(X, M, N) {
		return SpcsTo(StrU(X, 1, N), M+N+2);
	}

	// used by seedble random number functionality
	function RRN2(_initseed) {
		if(initRandSeed==null){
			initRandSeed = _initseed;
		}
		var Q
		var XX = [];
		var rnge = Math.pow(2, 32);
		function SeedRand() {
			return (RandSeed = ((134775813*initRandSeed)*RandSeed+1)%rnge)/rnge;
		}
		for (var Q = 0; Q < 9; Q++){
			XX[Q] = StrT(SeedRand(), 1, 3);
		}
		return XX[XX.length - 1];
	}


	function drawCloud(container){
		var words = container.getElementsBySelector("li a").map(function(item){
			var h = $H({ name: item.innerHTML.strip(), href: item.readAttribute('href') });
			return h;
		});

		// start up the random generator using our word list as the seed
		var randInit = (Math.round(RRN2(words.join("").split("").inject(0,function(acc,n){
			return (acc = acc + n.charCodeAt(0));
		})) * 12));

		var basketHeight = 45;

		var tagCloudWrapperContainer = new Element("div");

		for(var i=0;i<words.length;i++){

			var d = new Element("div");
			d.appendChild(new Element("div"));
			d.firstChild.appendChild(new Element("a",{'href':words[i]['href']}));
			d.firstChild.firstChild.appendChild(document.createTextNode(words[i]['name']));
			d.setStyle({
				'height':'45px',
				'float':'left'
			});

			var link = $(d.firstChild.firstChild);
			(function(elem){
				Event.observe(elem,"mouseover",function(){
					elem.setStyle({'color':'#99ccff'});
				});
				Event.observe(elem,"mouseout",function(){
					elem.setStyle({'color':'#ffffff'});
				});
			})(link);
			link.setStyle({'color':'#ffffff'});

			// TODO : this text size will not be randomized but rather depend on a priority attribute on the tags from eTouch.
			var textsize = 12 + Math.round(RRN2() * 13);
			$(d.firstChild).setStyle({
				'fontSize':textsize+'px',
				'lineHeight':textsize+'px',
				'whiteSpace':'nowrap',
				'paddingLeft':'8px',
				'paddingRight':'8px',
				'paddingTop':Math.round(RRN2() * (basketHeight - textsize)) + "px"
			});
			tagCloudWrapperContainer.appendChild(d);
		}
		
		container.appendChild(tagCloudWrapperContainer);
	}

	//
	// tag cloud boot strap
	//
	$$('.tag_cloud').each(function(container){
		drawCloud(container);
	});

});

}
/*----------------------------------------------------- TagCloud.js ends -----------------------------------------------------*/






