/*
	NACC: The N.A. Cleatime Calculator

	Version: 1.6.9

	See changelog.txt for details of changes

	This is a cooperative venture of the MAGNAWS Community Commons - http://wiki.magnaws.com/

	This is a real purty cleantime calculator that displays a whole
	bunch of nicely-rendered keytags to commemorate your cleantime.

	This uses JavaScript. It is 100% JavaScript, so it's easy to steal
	and re-use. There's no server-side technology (like PHP or ASP) involved.

	You can choose among various themes including Basic Text Blue, It Works- How and Why and Just For Today.

	More themes may be added later and, if you are comfortable with CSS (Cascading Style Sheets),
	you can make your own theme.

	HOW TO USE THIS:

	You first need to include this file in your <head> section. You also should include the base
	stylesheet file and one of the theme style sheets.

	This example assumes that the calling file is one directory level above the NACC directory:

		<head>
			.
			.
			.
			<link rel="stylesheet" href="../../nacc.1.6/nacc/nacc/nacc.css" type="text/css" />
			<link rel="stylesheet" href="../../nacc.1.6/nacc/nacc/nacc_theme_bt.css" type="text/css" />
			<script type="text/javascript" src="../../nacc.1.6/nacc/nacc/nacc.js"></script>
			.
			.
			.
		</head>

	NOTE:   If you are on a PHP server, you can include a different file that will trim all this
			text out of the JavaScript file, and give you a much smaller file. In that case, the
			script would look like this:

				<script type="text/javascript" src="../../nacc.1.6/nacc/nacc/nacc.js.php"></script>

	The best way to invoke it is to put a call to this function in an onload() event:

		<body onLoad="NACC_CleanTime(pContainerId, pPathToNACC, pUseCookie, pChained, pHideTags)">

	Where:
		pContainerId:   string - ID of the containing div on the html page.

						This needs to be a valid DOM ID of an empty <div> or other block level
						HTML element. The contents of this element will be completely
						replaced by the NACC.

						For example:

							<div id="my_blank_div"></div>

						Would need:

							NACC_CleanTime('my_blank_div', pPathToNACC, pUseCookie, pChained, pHideTags)

		pPathToNACC:	string - path to location of 'nacc' directory (e.g. "/third/party/apps").

						The NACC needs to have all its files kept together in one directory. This
						parameter is a relative HTTP (URL address-style) path from the page that
						is using the NACC to the directory that contains the NACC.

						For example:

							public_html
								|
								cleantime_calc.html <- Contains the code that calls the NACC
									The <head> code would look like this:
										<link rel="stylesheet" href="../../nacc.1.6/nacc/special_code/nacc/nacc.css" type="text/css" />
										<script type="text/javascript" src="../../nacc.1.6/nacc/special_code/nacc/nacc.js"></script>
								|
								special_code					<- An in-between directory
									|
									nacc						<- The NACC directory
										|
										nacc.js					<---
										|						   |
										nacc.css					<------- These are the only files/directories
										|						   |		 necessary for normal use.
										nacc_theme_?.css	<-------
										|						   |
										images					<---

						Would need:

							NACC_CleanTime(pContainerId, 'special_code/nacc', pUseCookie, pChained, pHideTags)

		pUseCookie	  boolean - store cleandate in a cookie

						Some people might not like this if they have privacy concerns. By default, cookies
						are not stored. What a stored cookie does is store the visitor's cleandate and
						tag display preference. That's all. There's actually no danger to privacy, and no
						really insidious information is stored (unless the visitor likes to use their
						cleandate as a password).

						In order to store cookies, you can set this to true:

							NACC_CleanTime(pContainerId, pPathToNACC, true, pChained, pHideTags)

		pChained:	   boolean - whether to display key tags vertically (chained together) or horizontally

						This is the initial (default) method of arranging the tags. Chained means that they
						are displayed as one long vertical chain. Not chained is what we call a "tabletop"
						arrangement, where they are laid out in horizontal rows.

						If the visitor has a cookie, this parameter will be ignored, and the visitor's
						preference will be honored instead. If the visitor does not have a cookie, then this
						will always be the initial setting.

						In order to have the results specified as a chain by default:

							NACC_CleanTime(pContainerId, pPathToNACC, pUseCookie, true, pHideTags)

		pHideTags:	   boolean - whether to hide key tag display

						You might not want to disply the key tags in cases where bandwidth or
						other issues come into play.

						In order to hide the key tags:

							NACC_CleanTime(pContainerId, pPathToNACC, pUseCookie, pChained, true)

		You can ignore all but the first parameter, but default values will be used. The first parameter
		must always be specified.

			NACC_CleanTime('my_blank_div')
				Will result in no cookies, tabletop, and the file must be in the NACC directory.

			NACC_CleanTime('my_blank_div', 'nacc')
				Will result in no cookies, tabletop, and the file must be one above the NACC directory.

			NACC_CleanTime('my_blank_div', 'nacc', true)
				Will result in cookies, tabletop, and the file must be one above the NACC directory.

			NACC_CleanTime('my_blank_div', 'nacc', true)
				Will result in cookies, tabletop, and the file must be one above the NACC directory.

			NACC_CleanTime('my_blank_div', 'nacc', true, true)
				Will result in cookies, chained, and the file must be one above the NACC directory.

			NACC_CleanTime('my_blank_div', 'nacc', true, true, true)
				Will result in cookies, chained, hide key tags and the file must be one above the NACC directory.

		The default ("NACC_CleanTime('my_blank_div')") is the equivalent of this:
			NACC_CleanTime('my_blank_div', '', false, false, false, false)

	THE 90-DAY ODDITY:
		When the visitor passes 90 days, the calculator stops counting days for keytags, and, instead, counts dates.
		For example, a visitor may have 90 days, but not 3 months, or they may have 91 days, and 3 months and 2 days.
		This is actually expected behavior.

	NOTE:   We use an interesting system to keep all the cleantime stuff in its own context. This prevents it
			from interfering with other JavaScript you may have.

			Basically, the entire cleantime calculator lives inside the NACC_CleanTime() function, so the only
			exposed interface is that function name, and the DOM elements generated by the code.
*/
function NACC_CleanTime ( pContainerId, pPathToNACC, pUseCookie, pChained, pHideTags ) {

	// Set the globals that reflect the input parameters.
	var gContainerEl = document.getElementById(pContainerId);

	if (gContainerEl == null) {
		alert('ERROR: There is no element on the page whose ID is "' + pContainerId + '"!');
		return;
	}

	 // Fix pPathToNACC directory param before setting global var
	 // Fixes missing or multiple forward slashes at end
	 // Gives end user leeway if they forget to add one
	 if (typeof(pPathToNACC) == 'string') {
		  // Trim white space from beginning and end
		  pPathToNACC = pPathToNACC.replace(/^\s+|\s*$/g, '');

		  if (pPathToNACC.length > 0) {
				// Trim forward slash(es) from end
				pPathToNACC = pPathToNACC.replace(/\/*$/, '');

				// Add forward slash back
				pPathToNACC += '/';
		  }
	 }
	 else {
		  pPathToNACC = '';
	 }

	var gPathToNACC = pPathToNACC;

	// Set global variable based on param passed to function
	var gChained = (pChained == true);

	// Set global variable based on param passed to function
	var gCookieName = (pUseCookie == true) ? 'nacc_cleantime' : '';

	// Set global variable based on param passed to function
	var gHideTags = (pHideTags == true);

	// This is one day, in milliseconds. It is needed to break down the getTime() results.
	var gDay = (24 * 60 * 60 * 1000);

	// These reflect the current cleandate, parsed into a simple format.
	var gSelMonth;
	var gSelDay;
	var gSelYear;

	// This is today.
	var gTodayDate = new Date();
	// set the date to midnight so hours, minutes and seconds don't influence calculations
	gTodayDate.setHours(0);
	gTodayDate.setMinutes(0);
	gTodayDate.setSeconds(0);

	// Determine whether the browser is IE6 or older
	var gOldIE = (NACC_browser() == 'msie');

	/*****************************************************
		BEGIN LOCALIZATION SECTION

		These globals are the displayed strings. This means they need to be changed in order to make this work in
		languages other than English.

		NOTE- the function BuildCleantimeMessage() has NOT been localized!!! If you need a non-Englisg message,
		you'll have to change it accordingly until we get to it.
	*/

	var gTitle_lang = 'NA Cleantime Calculator';
	var gPrompt_lang = 'Please enter your Clean Date';
	var gCalcBtn_lang = 'Calculate';
	var gResetLinkText_lang = new Array('Click to reset your cleantime', 'Reset Cleantime');
	var gMonthsFull_lang = new Array ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	var gFutureWarning_lang = 'Error! Clean Date is in the future!';
	var gChangeLinkText_lang = new Array('Click to change how key tags are laid out', 'Change Key Tag Layout');

	/*****************************************************
		END LOCALIZATION SECTION
	*/


	/********************
		This function actually constructs the cleantime form. It does this by pure DOM construction, and places
		everything into the container whose ID is passed in by the pContainerId element.

		Parameters:
			initDate	string - This is the initial date and keytag setting.
						It is a string in the following format:
							[M]M/[D]D/YYYY-[1|0]
						The first part is the month (1-12)
						The second part is the day of the month (1-31)
						The third part is the year, as a 4-digit number.
						There is a dash. After that, is either a 1 (Chained) or a 0 (Tabletop).
						If this parameter is omitted, the default values (today, pChained) will be used.
	*/
	function Initialize (initDate) {
		// Start DOM creation section

		// This is an overall wrapper <div>
		var wrapperDiv = document.createElement('div');
		wrapperDiv.id = 'nacc_wrapper';
		wrapperDiv.className = 'nacc_wrapper';

		// Create main <div>- contains title, prompt and form
		var mainDiv = document.createElement('div');
		mainDiv.id = 'nacc_main';

		// adjust class for IE peekaboo bug fix css selector
		if (NACC_browser()&&NACC_browser().indexOf('msie') != -1) {
			mainDiv.className = 'nacc_main nacc_pb_fix';
		}
		else {
			mainDiv.className = 'nacc_main';
		}

		// Create title <span>
		var titleSpan = document.createElement('span');
		titleSpan.id = 'nacc_title';
		titleSpan.className = 'nacc_title';
		titleSpan.innerHTML = gTitle_lang;

		// Add title <span> to main <div>
		mainDiv.appendChild(titleSpan);

		// Create prompt <span> and add it to main <div>
		var promptSpan = document.createElement('span');
		promptSpan.id = 'nacc_prompt';
		promptSpan.className = 'nacc_prompt';
		promptSpan.innerHTML = gPrompt_lang;

		mainDiv.appendChild(promptSpan);

		// Create <form> The controls live within this <form>

		var theForm = document.createElement('form');
		theForm.action = "#";   // Required for valid XHTML.
		theForm.id = 'nacc_form';
		theForm.className = 'nacc_form';

		// Submitting the form calculates cleantime, but does not cause a page to be submitted to server.
		theForm.onsubmit = SubmitForm;

		// Create empty month <select> and add it to <form>. It will be filled later.
		var selectMonth = document.createElement('select');
		selectMonth.id = 'nacc_month_sel';
		selectMonth.className = 'nacc_month_sel';

		theForm.appendChild(selectMonth);

		// Create empty day <select> and add it to <form>. It will be filled later.
		var selectDay = document.createElement('select');
		selectDay.id = 'nacc_day_sel';
		selectDay.className = 'nacc_day_sel';

		theForm.appendChild(selectDay);

		// Create empty year <select> and add it to <form>. It will be filled later.
		var selectYear = document.createElement('select');
		selectYear.id = 'nacc_year_sel';
		selectYear.className = 'nacc_year_sel';

		theForm.appendChild(selectYear);

		// Create the calculate button and add it to <form>
		var calcBtn = document.createElement('input');
		calcBtn.id = 'nacc_calc_btn';
		calcBtn.className = 'nacc_calc_btn';
		calcBtn.type = 'submit';
		calcBtn.value = gCalcBtn_lang;

		theForm.appendChild(calcBtn);


		// Create reset <a> and add it to the <form>
		var resetLink = document.createElement('a');

		resetLink.id = 'nacc_reset_link';
		resetLink.className = 'nacc_reset_link';
		resetLink.href = '#';
		resetLink.title = gResetLinkText_lang[0];
		resetLink.innerHTML = gResetLinkText_lang[1];

		// Clicking link resets everything
		resetLink.onclick = ResetForm;

		theForm.appendChild(resetLink);

		// Create a clearing <div> and add it to the form to clear floated elements
		var clearingDiv = document.createElement('div');
		clearingDiv.className = 'nacc_clearing_div';

		theForm.appendChild(clearingDiv);

		// Add <form> to main <div>
		mainDiv.appendChild(theForm);

		// Add main <div> to wrapper <div>
		wrapperDiv.appendChild(mainDiv);

		// Create results <div>- contains cleantime message and key tag display
		var resultsDiv = document.createElement('div');
		resultsDiv.id = 'nacc_results';
		resultsDiv.className = 'nacc_results';

		// adjust class for IE peekaboo bug fix css selector
		if (NACC_browser()&&NACC_browser().indexOf('msie') != -1) {
			resultsDiv.className = 'nacc_results  nacc_pb_fix';
		}
		else {
			resultsDiv.className = 'nacc_results';
		}

		// Add results <div> to wrapper <div>
		wrapperDiv.appendChild(resultsDiv);

		// Put the whole schmeel into the user-supplied container
		gContainerEl.appendChild(wrapperDiv);

		// End DOM creation section


		// If we have an initial date, it will be in the cookie format, so we parse it out.
		if (initDate) {
			var mycookie = initDate.split('-');
			var parts = mycookie[0].split('/');
			gSelMonth = parts[0];
			gSelDay = parts[1];
			gSelYear = parts[2];

			gChained = parseInt(mycookie[1], 10) == 1;
		}
		else {
			gSelMonth = gTodayDate.getMonth() + 1;
			gSelDay = gTodayDate.getDate();
			gSelYear = gTodayDate.getFullYear();
		}

		// Set up the contents of the three date <select> elements.
		FillYearSelect();
		FillMonthSelect();
		FillDaySelect();
	}

	/********************
		This function constructs a plain-English phrase that summarizes the results. It would need to be
		completely rewritten for non-English implementations.

		Parameters:
			totalDays   integer - The total number of days between the cleandate and today.
			years	   integer - The total number of years between the cleandate and today.
			months	  integer - The total number of months between the cleandate's last year anniversary and today
			days		integer - The total number of days between the cleandate's last year/month anniversary and today
	*/
	function BuildCleantimeMessage (totalDays, years, months, days) {
		var msg = 'You have been clean for '+ totalDays;

		if (totalDays > 90) msg += ' total';

		if (totalDays > 1) {
			msg += ' days';
		}
		else {
			if ( totalDays ) {
				msg = 'Congratulations! You have been clean for one day!';
			}
			else {
				msg = 'Welcome to NA! Pick up a white tag, and keep coming back!';
			}
		}

		if (years || months || days) {
			msg += ', which is ';
			if (years > 0) {
				msg += years + ' year';
				if (years > 1)  msg += 's';
			}

			if (months > 0) {
				if (years) {
					if (!days) {
						msg += ' and ';
					}
					else {
						msg += ', ';
					}
				}
				msg += months + ' month';
				if (months > 1) msg += 's';
			}

			if (days > 0) {
				if (years || months) msg += ' and ';
				msg += days + ' day';
				if (days > 1) msg += 's';
			}
		}

		msg += '!';

		return msg;
	}

	/*****************************************************
		COOKIE FUNCTIONS

		These are simple JavaScript cookie functions. They use the
		cookie name in gCookieName.
	*/

	/********************
		Get the cookie value.

		Parameters:
			inCookieName	string - The name of the cookie

		Function Return:
			string - The value of the cookie
	*/
	function GetCookie (inCookieName) {
		if ( inCookieName ) {
			var nameEq = inCookieName + '=';
			var ca = document.cookie.split(';');
			for (var i = 0; i < ca.length; i++) {
				var c = ca[i];
				while (c.charAt(0) == ' ') {
					c = c.substring(1, c.length);
				}
				if (c.indexOf(nameEq) == 0) {
					return unescape(c.substring(nameEq.length, c.length));
				}
			}
		}
		return null;
	}

	/********************
		Set a new cookie.

		Parameters:
			inCookieName	string - The name of the cookie
			value		   string - The value of the cookie.
	*/
	function SetCookie (inCookieName, value) {
		if ( inCookieName ) {
			var nameEq = inCookieName + '=';
			var date = new Date();
			date.setTime(date.getTime() + (gDay * 366));
			var expires = "; expires=" + date.toGMTString();
			document.cookie = nameEq + escape(value) + expires;
		}
	}

	/********************
		Clear the cookie.

		Parameters:
			inCookieName	string - The name of the cookie
	*/
	function RemoveCookie (inCookieName) {
		if ( inCookieName ) {
			var nameEq = inCookieName + '=';
			var date = new Date();
			date.setTime(date.getTime() - gDay);
			var expires = "; expires=" + date.toGMTString();
			document.cookie = nameEq + expires;
		}
	}

	/*****************************************************
		CALCULATION FUNCTIONS

		These are the functions where the calculation is actually done.
	*/

	/********************
		Given a month and a year, returns the number of days in that month.

		Parameters:
			inYear  integer - The year in question
			inMonth integer - The month of that year (0-based, so it is 0-11).

		Function Return:
			integer - The number of days in the given month.
	*/
	function DaysInMonth ( inYear, inMonth ) {
		return 32 - new Date(inYear, inMonth, 32).getDate();
	}

	/********************
		The Big Kahuna. This calculates the total number of cleandays, the yaers, months and days, etc.
		It returns an associative array of Cleandate numbers ('total_days', 'years', 'months', and 'days')
		Or false if clean date is in the future
	*/
	function CalcCleantime () {
		// Set the date to midnight so hours, minutes and seconds don't influence calculations
		var cleanDate = new Date();
		cleanDate.setFullYear(gSelYear);
		cleanDate.setMonth(gSelMonth - 1);
		cleanDate.setDate(gSelDay);
		cleanDate.setHours(0);
		cleanDate.setMinutes(0);
		cleanDate.setSeconds(0);

		if (parseInt(cleanDate.getTime()/gDay, 10) <= parseInt(gTodayDate.getTime()/gDay, 10)) {
			var years = null;
			var months = null;
			var days = null;
			var totalDays = null;

			// We gotta use round here rather than parseInt or floor because of floating point issues
			var totalDays = Math.round((gTodayDate.getTime() - cleanDate.getTime()) / gDay);

			if (totalDays > 90) {
				var endYear = gTodayDate.getFullYear();
				var endMonth = gTodayDate.getMonth();
				var startMonth = cleanDate.getMonth()-1;
				var startYear = cleanDate.getFullYear();
				var endDay = gTodayDate.getDate();
				var startDay = cleanDate.getDate();

				// We first see how many years have passed.
				years = endYear - startYear;
				// We then check months.
				months = (endMonth - startMonth) - 1;
				// We do a similar thing with days.
				days = endDay - startDay;
				// If this month is earlier than the cleandate month, we reduce the
				// year by one, and figure out how many months it's been since the
				// last annual anniversary of the clean date.
				if (months < 0) {
				    if( (months < 0) || (startDay > endDay) ) {
						months = 10 - startMonth;
						months += (endMonth + 1);
						if (years > 0) {
							 years--;
							 }
						}
				    }
				// We need to figure out how many days it was between the last monthly
				// anniversary and today.
				if (days < 0) {
					months--;
					// If we went too far with the months, we go back to the previous year
					if (months < 0) {
						endMonth--;
						if (endMonth < 0) {
							endMonth = 11;
							endYear--;
						}
						months = 10 - startMonth;
						months += (endMonth + 1);
						if (years > 0) {
							years--;
						}
					}

					days = DaysInMonth(endYear, endMonth) - startDay;
					days += endDay;
				}
			}

			if (totalDays >= 0) {
				// Return associative array of Cleandate numbers
				var retArray = new Array();
				retArray['total_days'] = totalDays;
				retArray['years'] = years;
				retArray['months'] = months;
				retArray['days'] = days;

				return retArray;
			}
		}
		else {
			// Cleandate is in the future
			return false;
		}
	}

	/********************
		This fills the year <select> element.
		1953 is when NA was formed.
	*/
	function FillYearSelect () {
		var obj = document.getElementById('nacc_year_sel');

		obj.onchange = null;
		obj.options.length = 0;
		obj.selectedIndex = -1;

		var final_year = gTodayDate.getFullYear();
		var sel = -1;
		var i = 0;

		for (var c = 1953; c <= final_year; c++) {
			var opt = document.createElement('option');
			opt.value = c;
			opt.text = c;

			if (gSelYear == c) {
				sel = c - 1953;
			}

			obj.options[i++] = opt;
		}

		if (sel == -1) {
			obj.selectedIndex = obj.options.length - 1;
		}
		else {
			obj.selectedIndex = sel;
		}

	   // Make sure that the day <select> element is corrected for leap years.
	   obj.onchange = function () { gSelYear = document.getElementById('nacc_year_sel').value;FillDaySelect()};
	}


	/********************
		This fills the month <select> element.
	*/
	function FillMonthSelect () {
		var obj = document.getElementById('nacc_month_sel');

		obj.onchange = null;
		obj.options.length = 0;
		obj.selectedIndex = -1;

		var max_month = 12;
		var sel = -1;
		var i = 0;

		for (var c = 1; c <= max_month; c++) {
			var opt = document.createElement('option');

			opt.value = c;
			opt.text = gMonthsFull_lang[c - 1];

			if (gSelMonth == c) {
				sel = c - 1;
			}

			obj.options[i++] = opt;
		}

		if (sel == -1) {
			obj.selectedIndex = obj.options.length - 1;
		}
		else {
			obj.selectedIndex = sel;
		}

		// Make sure that the day <select> element reflects the correct number of days for this month.
	   obj.onchange = function () { gSelMonth = document.getElementById('nacc_month_sel').value;FillDaySelect()};
	}

	/********************
		This fills the day <select> element.
	*/
	function FillDaySelect () {
		var iSelYear = gSelYear;
		var iSelMonth = gSelMonth;

		if ( document.getElementById('nacc_year_sel').value ) {
			iSelYear = parseInt(document.getElementById('nacc_year_sel').value, 10);
		}
		if ( document.getElementById('nacc_month_sel').value ) {
			iSelMonth = parseInt(document.getElementById('nacc_month_sel').value, 10);
		}
		var obj = document.getElementById('nacc_day_sel');

		obj.onchange = null;
		obj.options.length = 0;
		obj.selectedIndex = -1;

		var max_days = DaysInMonth(iSelYear, iSelMonth - 1);
		var sel = -1;
		var i = 0;

		for (var c = 1; c <= max_days; c++) {
			var opt = document.createElement('option');
			opt.value = c;
			opt.text = c;

			if (gSelDay == c) {
				sel = c - 1;
			}

			obj.options[i++] = opt;
		}

		if (sel == -1) {
			obj.selectedIndex = obj.options.length - 1;
		}
		else {
			obj.selectedIndex = sel;
		}
	   // FIX ADDED 8/31/07: The gSelDay was not being set when we changed the last day.
	   gSelDay = document.getElementById('nacc_day_sel').value;
	   obj.onchange = function () { gSelDay = document.getElementById('nacc_day_sel').value };
	}

	/********************
		When the reset control is activated, we remove the cookie and set the date to today.
		We clear the key tag and message displays.
		We do not change the layout preference.
	*/
	function ResetForm () {
		RemoveCookie(gCookieName);

		EmptyObject('nacc_results');

		ResetCleantime();

		FillYearSelect();
		FillMonthSelect();
		FillDaySelect();
		
		return false;
	}

	/********************
		When the form is submitted (either with return key or button click), we clear the message and keytag displays.
		Then we do the calculations, render displays and set cookie.
	*/
	function SubmitForm () {
		EmptyObject('nacc_results');

		var result = CalcCleantime();

		// Check if result is not false to determine if it's an array (can't safely check if its an array due to limitations of language)
		if (result !== false) {
			var rTotalDays = result['total_days'];
			var rYears = result['years'];
			var rMonths = result['months'];
			var rDays = result['days'];

			RenderMessage(BuildCleantimeMessage(rTotalDays, rYears, rMonths, rDays));
			RenderKeyTags(BuildKeyTagList(rTotalDays, rYears, rMonths, rDays));

			var mycookie = gSelMonth + '/' + gSelDay + '/' + gSelYear + '-' + (gChained ? '1' : '0');
			SetCookie(gCookieName, mycookie);
		}
		else {
			alert(gFutureWarning_lang);
		}

		return false;
	}

	/********************
		Toggle key tag layout between chained and tabletop and reruns everything
	*/
	function ChangeLayout () {
		gChained = (!gChained);

		return SubmitForm();
	}

	/********************
		Simple. Empties DOM object whose id is passed in param.

		Parameters:
			objId string - the id of the DOM object to empty.
	*/
	function EmptyObject (objId) {
		if (objId) {
			if (obj = document.getElementById(objId)) {
				// Add event removal here?!?
				
				obj.innerHTML = '';
			}
		}
	}

	/********************
		Simple. We just set the cleantime to today.
	*/
	function ResetCleantime () {
		gSelMonth = gTodayDate.getMonth() + 1;
		gSelDay = gTodayDate.getDate();
		gSelYear = gTodayDate.getFullYear();
	}

	/********************
		This simply writes out the message to the message <div>

		Parameters:
			msg string - The message to be displayed.
	*/
	function RenderMessage (msg) {
		var resultsDiv = document.getElementById('nacc_results');

		var msgDiv = document.getElementById('nacc_msg');

		if (!msgDiv) {
			msgDiv = document.createElement('div');
			msgDiv.id = 'nacc_msg';
			msgDiv.className = 'nacc_msg';
			resultsDiv.appendChild(msgDiv);
		}

		msgDiv.innerHTML = msg;
	}

	/********************
		This builds a list of keytags that should be displayed for given cleandate.

		Parameters:
			totalDays   integer - The total number of days between the cleandate and today.
			years	   integer - The total number of years between the cleandate and today.
			months	  integer - The total number of months between the cleandate's last year anniversary and today
			days		integer - The total number of days between the cleandate's last year/month anniversary and today

		Function Return:
			array of string - The list of tag images, given as src URIs.
	*/
	function BuildKeyTagList (totalDays, years, months, days) {
		if (gChained) {
			var fileEnd = '.png';
		}
		else {
			var fileEnd = '_H.png';
		}

		var imageList = new Array();

		imageList[0] = gPathToNACC + 'images/Day_1' + fileEnd;

		if (totalDays >= 30) {
			imageList[1] = gPathToNACC + 'images/Day_30' + fileEnd;
		}

		if (totalDays >= 60) {
			imageList[2] = gPathToNACC + 'images/Day_60' + fileEnd;
		}

		if (totalDays >= 90) {
			imageList[3] = gPathToNACC + 'images/Day_90' + fileEnd;
		}

		if (!years) {
			if (months >= 6) {
				imageList[4] = gPathToNACC + 'images/Month_6' + fileEnd;
			}
			if (months >= 9) {
				imageList[5] = gPathToNACC + 'images/Month_9' + fileEnd;
			}
		}
		else {
			imageList[4] = gPathToNACC + 'images/Month_6' + fileEnd;
			imageList[5] = gPathToNACC + 'images/Month_9' + fileEnd;
			imageList[6] = gPathToNACC + 'images/Month_12' + fileEnd;

			if ((years == 1 && months >= 6) || (years > 1)) {
				imageList[7] = gPathToNACC + 'images/Month_18' + fileEnd;
			}

			for (var c = 8; --years > 0; c++) {
				imageList[c] = gPathToNACC + 'images/Month_24' + fileEnd;
			}
		}

		return imageList;
	}

	/********************
		This takes the calculated list of tags, and creates a bunch of floated <img> elements that correspond to the list.
		This will take the keytag layout preference into account, and will select the correct images accordingly.

		Parameters:
			imageList   array of string - The list of image src names.
	*/
	function RenderKeyTags (imageList) {
		if (gHideTags) {
			return;
		}

		if (imageList.length == 0) {
			return;
		}

		var resultsDiv = document.getElementById('nacc_results');


		var keyTagsDiv = document.getElementById('nacc_keytags');

		if (!keyTagsDiv) {
			keyTagsDiv = document.createElement('div');
			keyTagsDiv.id = 'nacc_keytags';
			keyTagsDiv.className = 'nacc_keytags';
			resultsDiv.appendChild(keyTagsDiv);
		}

		var changeLink = document.createElement('a');

		changeLink.id = 'nacc_change_link';
		changeLink.className = 'nacc_change_link';
		changeLink.href = '#';
		changeLink.title = gChangeLinkText_lang[0];
		changeLink.innerHTML = gChangeLinkText_lang[1];
		changeLink.onclick = ChangeLayout;

		keyTagsDiv.appendChild(changeLink);

		var innerDiv = document.createElement('div');

		if (gChained) {
			innerDiv.id = 'nacc_keytags_chained';
			innerDiv.className = 'nacc_keytags_layout_chained';
		}
		else {
			innerDiv.id = 'nacc_keytags_tabletop';
			innerDiv.className = 'nacc_keytags_layout_tabletop';
		}

		keyTagsDiv.appendChild(innerDiv);

		var max = imageList.length;

		if (gOldIE) {
			for (var c = 0; c < max; c++) {
				var imgSpan = document.createElement('span');

				if (gChained) {
					imgSpan.className = 'nacc_keytag_img_chained';
				}
				else {
					imgSpan.className = 'nacc_keytag_img_tabletop';
				}

				imgSpan.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + imageList[c] + "');";

				innerDiv.appendChild(imgSpan);
			}
		}
		else {
			for (var c = 0; c < max; c++) {
				var img = document.createElement('img');
				img.alt = 'Key Tag';

				if (gChained) {
					img.className = 'nacc_keytag_img_chained';
				}
				else {
					img.className = 'nacc_keytag_img_tabletop';
				}

				img.src = imageList[c];

				innerDiv.appendChild(img);
			}
		}
	}

	// The first thing we do when the function is called is to create the <form>. Everything after that is up to the user.
	Initialize(GetCookie(gCookieName));
}

/*
	Function to determine browser

	Does not determine version except in the case of MSIE

	Return values by browser are:
		Opera				opera
		MSIE 7				msie7
		MSIE 6 (and below) 	msie
		Safari				safari
		Gecko-based			gecko
		Other				false
*/
function NACC_browser () {
	var ua = navigator.userAgent.toLowerCase();

	if (ua.indexOf('opera') != -1) { // Opera (check first in case of spoof)
		return 'opera';
	}
	else if (ua.indexOf('msie 7') != -1) { // IE7
		return 'msie7';
	}
	else if (ua.indexOf('msie') != -1) { // IE
		return 'msie';
	}
	else if (ua.indexOf('safari') != -1) { // Safari (check before Gecko because it includes "like Gecko")
		return 'safari';
	}
	else if (ua.indexOf('gecko') != -1) { // Gecko
		return 'gecko';
	}
	else {
		return false;
	}
}

/*
	We need to add the following code so that IE6 will cache background images.
	By design it will not!!!
	IE5.x and IE7 will, but not IE6.

	Though not well documented, apparently it won't work when called in onload().
	So we have to call it inline when this JS file is included.

	Documented at http://www.mister-pixel.com/ and other
*/
if (NACC_browser() == 'msie') {
	try {
		document.execCommand("BackgroundImageCache", false, true);
	}
	catch (err) {
	}
}
