//	String functions

String.prototype.left = function(n)
	{
	return this.substr(0, Math.min(this.length, n));
	}

String.prototype.right = function(n)
	{
	return this.substr(Math.max(0, this.length - n));
	}

String.prototype.repeat = function(n)
	{
	var s = new String();
	var t = this.toString();

	while (--n >= 0)
		s += t
	return s;
	}

String.prototype.padLeft = function(width, c)
	{
	if (typeof c == "undefined")
		c = " ";
	if (this.length < width)
		return c.repeat(width - this.length) + this;
	else if (this.length == width)
		return this;
	else
		return "#".repeat(width);
	}

String.prototype.padRight = function(width, c)
	{
	if (typeof c == "undefined")
		c = " ";

	if (this.length < width)
		return this + c.repeat(width - this.length);
	else if (this.length == width)
		return this;
	else
		return "#".repeat(width);
	}

String.prototype.trimLeft = function()
	{
	return this.replace(/^\s+/, "");
	}

String.prototype.trimRight = function()
	{
	return this.replace(/\s+$/, "");
	}

String.prototype.trim = function()
	{
	return this.replace(/^\s+|\s+$/g, "");
	}

// Date functions

Date.prototype.format = function(f)
//*****************************************************************************
//	Description:
//	Parameters:
//	Return Values:
//
//*****************************************************************************
	{
    if (!this.valueOf())
        return ' ';

    var d = this;

	return f.replace(/(yyyy|mmmm|mmm|mm|dddd|ddd|dd|d|hh|nn|ss|a\/p)/gi,
		function($1)
			{
			switch ($1.toLowerCase())
				{
				case 'yyyy':
					return d.getFullYear();
				case 'mmmm':
					return gsMonthNames[d.getMonth()];
				case 'mmm':
					return gsMonthNames[d.getMonth()].left(3);
				case 'mm':
					return (d.getMonth() + 1).toString().padLeft(2, "0");
				case 'dddd':
					return gsDayNames[d.getDay()];
				case 'ddd':
					return gsDayNames[d.getDay()].left(3);
				case 'dd':
					return d.getDate().toString().padLeft(2, "0");
				case 'd':
					return d.getDate().toString();
				case 'hh':
					return ((h = d.getHours() % 12) ? h : 12).toString().padLeft(2, "0");
				case 'nn':
					return d.getMinutes().toString().padLeft(2, "0");
				case 'ss':
					return d.getSeconds().toString().padLeft(2, "0");
				case 'a/p':
					return d.getHours() < 12 ? 'a' : 'p';
				}
			}
		);
	}

var gsDayNames = new Array
	(
	"Sunday",
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
	"Friday",
	"Saturday"
	);

var gsMonthNames = new Array
	(
	"January",
	"February",
	"March",
	"April",
	"May",
	"June",
	"July",
	"August",
	"September",
	"October",
	"November",
	"December"
	);

function Updated()
	{
	lastModified = new Date(document.lastModified);
	document.write("Updated: " + lastModified.format("yyyy-mm-dd"));
	}

function HighlightTable(table)
//******************************************************************************
// Written by Jeffrey P. Smith, September 28, 2005
//
// Highlights rows of a table based on a color sequence specified in the
// HIGHLIGHT tag as follows:
//    <TABLE class="highlight:ColorSequence">
// Where ColorSequence is a semicolon delimited string of colors such as:
//    #FFFFC0;White
// Which will alternately set the background color of the rows to "Pale Yellow"
// and "White".
//
// If no color sequence is specified, then #FFFFC0;Transparent is assumed.
//
// If one color is specified, then the alternate color is "White".
//
// Rows with a predefined background color (e.g., <TR BGCOLOR=Color>) are
// skipped.
//
// If a row contains cells that span multiple rows, then the background color of
// all rows spanned by the cell are set to the same color.
//
// Cells with a predefined background color (e.g., <TD BGCOLOR=Color>) are not
// altered.
//******************************************************************************
	{
	if (table.className)
		{
		var className = table.className.split(":");
		if (className.length && className[0] == "highlight")
			{
			if (className.length == 1)
				var colors = new Array ("#FFFFC0","Transparent");
			else
				{
				colors = className[1].split(";");
				if (colors.length == 1)
					colors[1] = "White";
				}
		   	var color = 0;
			for	(var row = 0; row < table.rows.length;)
				{
				var rowSpan = 1;
				var highlighted = false;
				var visible = false;

				for (var cell = 0; cell < table.rows[row].cells.length; cell++)
					rowSpan = Math.max(rowSpan, table.rows[row].cells[cell].rowSpan);

				while (rowSpan)
					{
					if (highlighted = !table.rows[row].bgColor)
						table.rows[row].bgColor = colors[color];
					visible = visible || table.rows[row].style.display != 'none';
					--rowSpan;
					++row;
					}
	  			if (highlighted && visible)
				    color = ++color % colors.length;
				}
			}
		}
	}

function HighlightTables()
	{
	var object = document.getElementsByTagName("TABLE");

	if (object != null)
		if (object.length)
			for (var i = 0; i < object.length; i++)
				HighlightTable(object[i]);
		else
			HighlightTable(object);
	}

function Redirect(url)
//******************************************************************************
// 2007-11-04 Jeffrey P. Smith
//    a. Original.
// 2007-03-08 Jeffrey P. Smith
//    a. Passes along document hash, if any.
//******************************************************************************
	{
	if (self.name == "Search")
		top.location.replace(url);
	else if (window.parent.location.href == window.self.location.href)
		{
		if (url.indexOf("#") == -1)
			window.location.replace(url + document.location.hash);
		else
			window.location.replace(url);
		}
	}

function SetTitle()
	{
	top.document.title = document.title;
	}

function GetCookie(NameOfCookie)
	{
	if (document.cookie.length > 0)
		{              
		begin = document.cookie.indexOf(NameOfCookie + "=");       
		if (begin != -1)
			{           
			begin += NameOfCookie.length+1;       
			end = document.cookie.indexOf(";", begin);
			if (end == -1)
				end = document.cookie.length;
			return unescape(document.cookie.substring(begin, end));
			} 
		}
	return null;
	}

function SetCookie(NameOfCookie, value, expiredays)
	{
	var ExpireDate = new Date();

	ExpireDate.setTime(ExpireDate.getTime() + (expiredays * 24 * 3600 * 1000));
	document.cookie = NameOfCookie + "=" + escape(value) + ((expiredays == null) ? "" : "; expires=" + ExpireDate.toGMTString());
	}

function DeleteCookie(NameOfCookie)
	{
	if (GetCookie(NameOfCookie))
		{
		document.cookie = NameOfCookie + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
		}
	}

function Check(name)
	{
	SetCookie(name,'ON', 7);
	}

function Checked(name)
	{
	return GetCookie(name) == 'ON';
	}

function Uncheck(name)
	{
	SetCookie(name,'OFF', 7);
	}

function Toggle(name)
	{
	if (GetCookie(name) == 'ON')
		SetCookie(name, 'OFF', 7);
	else
		SetCookie(name, 'ON', 7);
	}

function CheckCitation(object, display)
	{
	if (object != null)
		{
		if (object.length != null)
			for (var i = 0; i < object.length; i++)
				object[i].style.display = display;
		else
			object.style.display = display;
		}
	}

function CheckCitations()
//******************************************************************************
// Written by Jeffrey P. Smith
//
// If the "Citations" cookie is ON then the "inner text" is displayed per the
// style definition. Otherwise, it is hidden.
//******************************************************************************
	{
	var display = Checked("Citations") ? "inline" : "none";

	var object = document.getElementsByTagName("CITE");
	CheckCitation(object, display);
	}

function CheckInserts()
//******************************************************************************
// Written by Jeffrey P. Smith
//
// If the Inserts cookie is OFF then the font style and color of the "inner text"
// are changed to "italics" and "red", respectively. Other there are set to
// "normal" and "black".
//******************************************************************************
	{
	var fontStyle	= Checked("Inserts") ? "normal" : "italic";
	var color	= Checked("Inserts") ? "black" : "red";
	var object = document.getElementsByTagName("INS");

	if (object != null)
		{
		if (object.length != null)
			for (var i = 0; i < object.length; i++)
				{
				object[i].style.fontStyle = fontStyle;
				object[i].style.color = color;
				}
		else
			{
			object.style.fontStyle = fontStyle;
			object.style.color = color;
			}
		}
	}

function CheckStrikeout(object, display)
	{
	if (object != null)
		{
		if (object.length != null)
			for (var i = 0; i < object.length; i++)
				object[i].style.display = display;
		else
			object.style.display = display;
		}
	}

function CheckStrikeouts()
//******************************************************************************
// Written by Jeffrey P. Smith
//
// If the "Strikeouts" cookie is OFF then the "inner text" is displayed per the
// style definition. Otherwise, it is hidden.
//******************************************************************************
	{
	var display = Checked("Strikeouts") ? "none" : "inline";

	var object = document.getElementsByTagName("S");
	CheckStrikeout(object, display);
	var object = document.getElementsByTagName("STRIKE");
	CheckStrikeout(object, display);
	var object = document.getElementsByTagName("DEL");
	CheckStrikeout(object, display);
	}

function CheckOptions()
	{
//	CheckCitations();
	CheckInserts();
	CheckStrikeouts();
	}

var tabberOptions =
	{
	'cookie': "tabber", /* Name to use for the cookie */
	'onLoad': function(argsObj)
		{
		var t = argsObj.tabber;
		var i;

		/* Optional: Add the id of the tabber to the cookie name to allow
		   for multiple tabber interfaces on the site.  If you have
		   multiple tabber interfaces (even on different pages) I suggest
		   setting a unique id on each one, to avoid having the cookie set
		   the wrong tab.
		*/
		if (t.id)
			t.cookie = t.id + t.cookie;

		/* If a cookie was previously set, restore the active tab */
		i = parseInt(GetCookie(t.cookie));
		if (isNaN(i))
			return;
		t.tabShow(i);
		},
	'onClick': function(argsObj)
		{
		var c = argsObj.tabber.cookie;
		var i = argsObj.index;

		//alert('SetCookie(' + c + ',' + i + ')');
		SetCookie(c, i);
		}
	};

function OnLoad(text)
	{
	CheckOptions();
	HighlightTables();
	FormatDates();
	if (typeof tabberAutomatic == "function")
		if (typeof tabberOptions == "undefined")
			tabberAutomatic();
		else
			tabberAutomatic(tabberOptions);
	if (typeof text != "undefined")
		alert(text);
//	SetTitle();
	}

function MailTo(name, domain)
	{
	document.write("<a href=\"mailto:" + name + "@" + domain + "\">" + name + "@" + domain + "</a>");
	}

function OnFirstEndNote(noteholder)
	{
	var newEle = document.createElement("h2");

	newEle.appendChild(document.createTextNode("End Notes"));
	noteholder.appendChild(newEle);
//	return noteholder;
	}

function GenerateEndNotes()
	{
	var noteHolderId = "EndNotesHolder";

	if (!FormatNotes("", "EndNotesHolder", "footnote", OnFirstEndNote))
		{
//		var noteholder	= document.getElementById(noteHolderId);
//		if (noteholder != null)
//			{
//			var newEle = document.createElement("div");

//			newEle.className = "footnote";
//			newEle.appendChild(document.createTextNode("None."));
//			noteholder.appendChild(newEle);
//			}
		}
	}

var articles = 0;

function FormatNotes(contentId, noteHolderId, noteClassName, OnFirstNote)
//******************************************************************************
//  Description:
//
//  Parameters:
//		contentId
//			Identification of the div containing the note spans.
//		noteHolderId
//			Identification of the div where the notes are to be displayed.
//		noteClassName
//			Class name of the span containing the note.
//		OnFirstNote
//			Function called on first note.
//		OnLastNote
//			Function called on last note.
//  Return Values:
//	
//  Global References:
//		article
//		document
//  Function References:
//		appendChilrd
//		cloneNode
//		createElement
//		createTextNode
//		getElementbyId (document method)
//		getElementsByTagName
//		remoteChild
//	Revision History:
//		1.00 yyyy-mm-dd by Timothy Groves http://www.brandspankingnew.net/
//			a. Original.
//		1.01 2010-09-05 by Jeffrey P. Smith
//			a. Added noteClassName parameter.
//******************************************************************************
	{
	if (typeof noteClassName == "undefined")
		noteClassName = "footnote";

	//  check for DOM capabilities

	if (!document.getElementById)
		return false;

	var contents;

	if (contentId == "")
		contents = document;
	else
		contents = document.getElementById(contentId);

	var noteholder	= document.getElementById(noteHolderId);
	if (typeof noteholder == "undefined")
		return false;

	var spans	= contents.getElementsByTagName("span");
	var notes	= 0;
	articles++;

	for (var i = 0; i < spans.length; i++)
		{
		if (spans[i].className == noteClassName)
			{
			notes++;
			if (notes == 1 && typeof OnFirstNote != "undefined")
				OnFirstNote(noteholder);

			var noteIdSuffix = articles + "." + notes;

			//  get content of span

			var noteNode = spans[i].cloneNode(true);

			//  remove css styling

			noteNode.className = "";

			//  create a new div to hold the note

			var newEle = document.createElement("div");
			newEle.className = "footnote";
			newEle.id = "note:" + noteIdSuffix;
			newEle.appendChild(document.createTextNode(notes + ". ") );
			newEle.appendChild(noteNode);

			//  create back link

			var backLink = document.createElement("a");
			backLink.href = "#ref:" + noteIdSuffix;
			backLink.className = noteClassName + "LinkBack";
			backLink.appendChild(document.createTextNode(" [back]"));
			newEle.appendChild(backLink);

			noteholder.appendChild(newEle);

			//  insert link into span

			var newEle = document.createElement("a");
			newEle.href = "#" + "note:" + noteIdSuffix;
			newEle.title = "Show";
			newEle.id = "ref:" + noteIdSuffix;
			newEle.className = noteClassName + "LinkTo";

      		newEle.appendChild(document.createTextNode("(" + notes + ")"));

			//  empty span

			while (spans[i].childNodes.length)
				spans[i].removeChild(spans[i].firstChild);
		spans[i].appendChild(newEle);
			}
		}
	return notes > 0;
	}

function FormatDates()
	{
	function FormatDate(date, format)
		{
		var s = "";

		if (date.circa)
			s = "ca. ";
		s += date.format(format);
		return s;
		}

	function FormatDateRange(dates, format)
		{
		if (dates.length == 1)
			return FormatDate(dates[0], format);

		var sameYear			= dates[0].getFullYear() == dates[1].getFullYear();
		var sameYearMonth		= sameYear && (dates[0].getMonth() == dates[1].getMonth());
		var sameYearMonthDay	= sameYearMonth && (dates[0].getDate() == dates[1].getDate());

		if (sameYearMonthDay)
			return FormatDate(dates[0], format);

		if (sameYearMonth)
			{
			if (dates[0].precision == 3 && dates[1].precision == 3)
				return gsMonthNames[dates[0].getMonth()] + " " + dates[0].getDate() + " to " + dates[1].getDate() + ", " + dates[0].getFullYear();
			else
				return gsMonthNames[dates[0].getMonth()]  + dates[0].getFullYear();
			}
		else if (sameYear)
			{
			if (dates[0].precision == 3 && dates[1].precision == 3)
				return gsMonthNames[dates[0].getMonth()] + " " + dates[0].getDate() + " to " + gsMonthNames[dates[1].getMonth()] + " " + dates[1].getDate() + ", " + dates[0].getFullYear();
			else if (dates[0].precision == 1 && dates[1].precision == 1)
				return gsMonthNames[dates[0].getMonth()] + " to " + gsMonthNames[dates[1].getMonth()] + ", " + dates[0].getFullYear() ;
			else
				return dates[0].getFullYear();
			}
		else
			return FormatDate(dates[0], format) + " to " + FormatDate(dates[1], format);
		}

	function ParseDate(s)
	//	yyyy[-mm[-dd]][c]
		{
		var circa = false;
		var	date;
		
		switch (s.charAt(s.length - 1))
			{
			case "c":
			case "C":
				circa = true;
				s = s.substr(0, s.length - 1);
				break;
			}

		date = s.split("-");
		var precision = Math.min(date.length, 3);

		for (var i = 0; i < date.length; i++)
			date[i] = parseInt(date[i], 10);

		if (date.length == 2)
			date.push(1);	//	assume first of day of month
		else if (date.length == 1)
			{
			date.push(1);	//	assume January 1st
			date.push(1);
			}
		date = new Date(date[0], date[1] - 1, date[2]);
		date.circa = circa;
		date.precision = precision;
		return date;
		}

	//*****************************************************************************

	var formats	=
		[
			["", "yyyy", "yyyy-mm", "yyyy-mm-dd"],			//	used with TD elements
			["", "yyyy", "mmmm yyyy", "mmmm d, yyyy"]		//	used with SPAN elements
		];

	var spans	= document.getElementsByTagName("span");

	for (var i = 0; i < spans.length; i++)
		{
		var className = spans[i].className.split(":");
		if (className[0] == "Date")
			{
			var format;

			if (className.length > 1)
				format = className[1];

			var dates = spans[i].innerHTML.split("/");

			var k = 3;
			for (var j = 0; j < dates.length; j++)
				{
				dates[j] = ParseDate(dates[j]);
				k = Math.min(k, dates[j].precision);
				}
			if (typeof format != "undefined" && dates.length == 1)
				spans[i].innerHTML = FormatDateRange(dates, format);
			else
				spans[i].innerHTML = FormatDateRange(dates, formats[1][k]);
			}
		}

	/*
	var tds	= document.getElementsByTagName("td");

	for (var i = 0; i < tds.length; i++)
		{
		var className = tds[i].className.split(":");
		if (className[0] == "Date")
			{
			var format;

			if (className.length > 1)
				format = className[1];

			var dates = tds[i].innerHTML.split("/");
			var k = 3;
			for (var j = 0; j < dates.length; j++)
				{
				dates[j] = ParseDate(dates[j]);
				k = Math.min(k, dates[j].precision);
				}			
			tds[i].innerHTML = FormatDateRange(dates, formats[1][k]);
			}
		}
	*/
	}

document.write('<style type="text/css">.tabber{display:none;}<\/style>');

