// -------------------------------
// KNOWLEDGE MAP SUPPORT FUNCTIONS
// -------------------------------
// Copyright (c) 2004-2007 The Salamander Organization Ltd.  All Rights Reserved.
//
// THIS WORK IS SUBJECT TO U.K. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
//
// DISCLAIMER:
//
// The Salamander Organization Ltd. (hereto referred as "Salamander") makes no representations or warranties
// with respect to the contents or use of this code, and specifically disclaims any express or implied
// warranties of merchantability or fitness for any particular purpose.  Further, Salamander reserves the right
// to revise this publication and to make changes to its content, at any time, without obligation to notify any
// person or entity of such revisions or changes.
//
// Further, Salamander makes no representations or warranties with respect to any software, and specifically
// disclaims any express or implied warranties of merchantability or fitness for any particular purpose.  Salamander
// reserves the right to make changes to any and all parts of the software, at any time, without obligation to notify
// any person or entity of such changes.
//
// Inclusion of the above notice does not necessarily imply publication.


// ########################
// ### SYSTEM VARIABLES ###

var iterNumber = 1;  // must initialise as 1
var nameArray = new Array();
var nameCount = 0;  // must initialise as 0


// #########################
// ### GENERIC FUNCTIONS ###

// write today's date into the document
function ShowTodaysDate() 
{
	var date = new Date();
	var weekday = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
	var monthname = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
	var daynumber = date.getDate();
	var daystring = daynumber.toString();
	
	if (daynumber < 10)
	{
		daystring = "0" + daystring;
	}
	
	document.write(weekday[date.getDay()] + ", ");
	document.write(monthname[date.getMonth()] + " ");
	document.write(daystring + ", ");
	document.write(date.getFullYear());
}

// navigate "back" in the browser history
function GoBack()
{
	// protect against empty history lists
	if (history.length > 0)
	{
		history.back();
	}
}

// a function to do nothing
// -- used by function pointers to give a null result to a function
// -- should never be called directly
function DoNothing()
{
	// does nothing
}

// applies an alternate class to odd rows in a table
// tableId = the DOM id of the table
function StripeTableRows(tableId)
{
	if (tableId)
	{
		var table = document.getElementById(tableId);

		if (table)
		{
			if (table.rows)
			{
				for (var i = 0; i < table.rows.length; i++)
				{
					// for odd numbered cells (remembering indexing starts at 0)
					if ((i % 2) == 1)
					{
						table.rows[i].className += " oddColumn";
					}
				}
			}
		}
	}
}

// applies an alternate class to odd columns in a table
// tableId = the DOM id of the table
function StripeTableColumns(tableId)
{
	if (tableId)
	{
		var table = document.getElementById(tableId);

		if (table)
		{
			if (table.rows)
			{
				for (var i = 0; i < table.rows.length; i++)
				{
					for (var j = 0; j < table.rows[i].cells.length; j++)
					{
						// for odd numbered cells (remembering indexing starts at 0)
						if ((j % 2) == 1)
						{
							table.rows[i].cells[j].className += " oddColumn";
						}
					}
				}
			}
		}
	}
}

// get a computed style value for an element as the element.style object only returns inline styles
// element = a DOM element
// cssProperty = the CSS property to read
function GetStyleValue(element, cssProperty)
{
	var styleValue = "";
	
	if (element)
	{
		if (element.currentStyle)
		{
			styleValue = element.currentStyle[cssProperty];
		}
	}
	
	return styleValue;
}

// return the minimum of two number values
function Min(number1, number2)
{
	if (number1 < number2)
	{
		return number1;
	}
	else
	{
		return number2;
	}
}

// return the minimum of two number values, but if number1 = 0 then return number2
function MinNotZero(number1, number2)
{	
	if (number1 < number2 && number1 > 0)
	{
		return number1;
	}
	else
	{
		return number2;
	}
}


// ###############################
// ### MOOD-SPECIFIC FUNCTIONS ###

// perform the navigation for a model title (usually the name)
function DoTitleNav(parentLink, contextLink) 
{
	// the MooD tag PARENT_LINK is intended to be a literal, not parsed by Web Publisher
	if (!parentLink || (parentLink == "__PARENT_LINK__"))
	{
		parentLink = "";
	}
	
	// the MooD tag PARENT_LINK is intended to be a literal, not parsed by Web Publisher
	if (!contextLink || (contextLink == "__CONTEXT_LINK__"))
	{
		contextLink = "";
	}
	
	// if there is a Parent Link then use that
	if (parentLink != "") 
	{
		location.href = parentLink;
	} 
	else 
	{
		// if no Parent Link there should be a Context Link
		if (contextLink != "") 
		{
			location.href = contextLink;
		} 
		else 
		{
			// not found either Parent or Context Link, try going back if possible
			GoBack();
		}
	}
}

// navigate to a defined link, using mood user tags for the link contents
function DoNavigation(linkType)
{
	var linkURL = "";
	var linkLayer = "";
	
	linkType = linkType.toUpperCase();  // case protection
	
	switch (linkType)
	{
		case "FAQ_LINK" :
			linkURL = faqLink;
			break;
		case "HELP_LINK" :
			linkURL = helpLink;
			break;
		case "HOMEPAGE_LINK" :
			linkURL = homeLink;
			break;
		case "INDEXPAGES_LINK" :
			linkURL = "HelperPages/indexPages" + outputExtension;
			break;
		case "KNOWLEDGEINDEX_LINK" :
			linkURL = "Indexes/KnowledgeIndex" + outputExtension;
			break;
		case "STARTPAGE_LINK" :
			linkURL = startLink;
			break;
		case "ARCHITECTURE_RV_LINK" :
			linkURL = architectureRVLink;
			break;
		default :
			//do nothing
	}
	
	if (!(linkURL == "")) location.href = (pageUrlPath + linkURL);
}

// write out an image
function WriteImage(imagePath, usePageUrlPath)
{
	var image = "";
	var outputString = "";
	var invalidImage = false;
	
	if (imagePath != "")
	{
		if (usePageUrlPath)
		{
			// check for well-known images, using pageUrlPath
			switch (imagePath)
			{
				case "LOGO_TOP_LEFT" :
					image = pageUrlPath + logoTopLeft;
					break;
				case "LOGO_TOP_RIGHT" :
					image = pageUrlPath + logoTopRight;
					break;
				case "POWEREDBY_LOGO" :
					image = pageUrlPath + poweredbyLogo;
					break;
				default :
					image = pageUrlPath + imagePath;
					break;
			}
			
			if (image == pageUrlPath)
			{
				// there's no image, only the url path, so this isn't an image at all
				invalidImage = true;
			}
		}
		else
		{
			// an image with an absolute path
			image = imagePath;
		}
		
		if (!invalidImage)
		{
			outputString = "<img src='" + image + "' />";
		}
	}
	else
	{
		invalidImage = true;
	}
	
	if (invalidImage)
	{
		// if no valid image was provided then write out a non-breaking space
		outputString = "&#160;";
	}
	
	document.write(outputString);
}

// write out defined content to the page, based on contentType
function WriteContent(contentType)
{
	var outputContent = GetContent(contentType);
	
	document.write(outputContent);
}

// get defined content for a page, based on contentType
function GetContent(contentType)
{
	var outputContent = "";
	
	contentType = contentType.toUpperCase();  // case protection
	
	switch (contentType)
	{
		case "GENERATION_DATE" :
			outputContent = generationDate;
			break;
		case "KMAP_NAME" :
			outputContent = kmapName;
			break;
		case "FOOTER_TEXT" :
			outputContent = footerText;
			break;
		case "PAGE_NAME" :
			outputContent = pageName;
			break;
		case "COPYRIGHT_TEXT" :
			outputContent = copyrightText;
			break;
		default :
			// no content
			break;
	}
	
	return outputContent;
}

// perform a mailto function for this page name
function MailFeedback(subjectName)
{
	// if the special name "PAGE_NAME" is provided, use the javascript meta data pageName for the subject
	if (subjectName.toUpperCase() == "PAGE_NAME")
	{
		subjectName = pageName;
	}
	
	location.href = ("mailto:" + feedbackAddress + "?subject=" + escape(kmapName) + " - " + escape(subjectName) + " (" + generationDate + ")&body=Please type your comments below:");
}

// ################################
// ### GLOBAL SUPPORT FUNCTIONS ###

// [facade] gets a unique section ID
function GetUniqueSectionID(sectionName)
{
	var uniqueSectionName = MakeUniqueName(sectionName, 1);
	var sectionID = ConvertNameToID(uniqueSectionName);
	return sectionID;
}

// [factory] a unique name factory - first call should always send uniqueNumber of integer 1 or undefined
function MakeUniqueName(someName, uniqueNumber)
{
	if (!uniqueNumber) uniqueNumber = iterNumber;
	
	for (var i = 0; i < nameCount; i++)
	{
		if (someName.toLowerCase() == nameArray[i].toLowerCase())
		{
			someName = StripChars(someName, "uniques");
			someName += " (" + uniqueNumber + ")";
			someName = MakeUniqueName(someName, iterNumber++);
		}
	}
	
	//reset the iterator now we've finished dealing with this name
	iterNumber = 1;	
	
	return someName;
}

// convert real element names into an ID suitable format - i.e. no spaces, all in lower case
function ConvertNameToID(sectionName)
{
	sectionName = StripChars(StripChars(StripChars(StripChars(StripChars(sectionName, "parentheses"), "spaces"), "punctuation"), "quotes"), "dashes");
	sectionName = sectionName.toLowerCase();
	return sectionName;
}

// [decorator] strip characters in charString according to stripType
function StripChars(charString, stripType)
{
	var pattOpenParen = /\(/gi;								// opening parenthesis (
	var pattCloseParen = /\)/gi;							// closing parenthesis )
	var pattSpaces = / /gi;									// spaces
	var pattUniqueNrs = / \(\d+\)/gi;						// one or more digits between parenthesis, e.g. (13)
	var pattFullstops = /\./gi;								// full stops .
	var pattCommas = /\,/gi;								// commas ,
	var pattColons = /\:/gi;								// colons :
	var pattSemiColons = new RegExp("\;", "gi");			// semicolons ;
	var pattSingleQuotes = /\'/gi;							// single quotes
	var pattDoubleQuotes = /\"/gi;							// double quotes "
	var pattDashes = /-/gi;									// minus signs -
	var pattAmpersands = /&/gi;								// ampersands &
	var pattQuestionMarks = /\?/gi;							// question marks ?
	var pattExclamationMarks = /\!/gi;						// exclamation marks !
	var pattAsterisks = /\*/gi;								// asterisks *
	var pattPercentSigns = /\%/gi;							// percent symbols %
	var pattPoundSigns = /\u00A3/gi;							// pound signs £
	var pattDollarSigns = /\$/gi;							// dollar signs $
	var pattHashSymbols = /\#/gi;							// hash symbols #
	var pattAtSymbols = /\@/gi;								// at symbols @
	var pattHatSymbols = /\^/gi;							// hat symbols ^
	var pattLeftSquareBrackets = /\[/gi;					// left square brackets [
	var pattRightSquareBrackets = /\]/gi;					// right square brackets ]
	var pattLeftCurlyBraces = /\{/gi;						// left curly braces {
	var pattRightCurlyBraces = /\}/gi;						// left curly braces }
	var pattGreaterThan = new RegExp("\>", "gi");			// greater than >
	var pattLessThan = new RegExp("\<", "gi");				// less than <
	var pattTilda = /\~/gi;									// tilda ~
	var pattForwardSlash = new RegExp("/", "gi");			// forward slash /
	var pattBackSlash = /\\/gi;								// back slash \
	var pattSectionFooterIE = new RegExp("<scriptlanguage=JavaScripttype=text/javascript>WriteSectionFooter", "gi");  // section footer for IE
	var pattSectionFooterMoz = new RegExp("<scripttype=\"text/javascript\"language=\"JavaScript\">WriteSectionFooter", "gi");  // section footer for Gecko
	var pattClosingScript = /\<\/script\>/gi;				// closing script tag </script>
	var pattFormFeed = new RegExp("\f", "gi");				// form feed
	var pattLineFeed = new RegExp("\n", "gi");				// line feed
	var pattCarriageReturn = new RegExp("\r", "gi");		// carriage return
	var pattTabs = new RegExp("\t", "gi");					// tabs
	var pattSectionPrefix = new RegExp(sectionPrefix, "gi");	// section prefix variable, e.g. section_
	var pattSimpleHTMLTags = new RegExp("</?[A-Za-z]*>", "gi");	// any simple HTML tag <*> || </*>
	var pattWhiteSpace = new RegExp("\\s", "gi");			// white space
	var pattPixelUnits = /px/gi;							// pixel abbreviation e.g. px
	
	stripType = stripType.toLowerCase();  // case protection
	
	switch (stripType)
	{
		case "parentheses" :
			// parentheses, both opening and closing, straight, curly and square
			patterns = [pattOpenParen, pattCloseParen, pattLeftSquareBrackets, pattRightSquareBrackets, pattLeftCurlyBraces, pattRightCurlyBraces];
			break;
		case "spaces" :
			// spaces, tabs
			patterns = [pattSpaces, pattTabs];
			break;
		case "uniques" :
			// unique numbers, e.g. (1)
			patterns = [pattUniqueNrs];
			break;
		case "punctuation" :
			// fullstops, commas, colons, semi-colons, ampersand, question mark, exclamation mark, asterisk, percent sign, pound sign, dollar sign, hash symbols, at symbols, hat symbols, greater than, less than, tilda, forward slash, back slash
			patterns = [pattFullstops, pattCommas, pattColons, pattSemiColons, pattAmpersands, pattQuestionMarks, pattExclamationMarks, pattAsterisks, pattPercentSigns, pattPoundSigns, pattDollarSigns, pattHashSymbols, pattAtSymbols, pattHatSymbols, pattGreaterThan, pattLessThan, pattTilda, pattForwardSlash, pattBackSlash];
			break;
		case "semicolons" :
			// semi-colons
			patterns = [pattSemiColons];
			break;
		case "quotes" :
			// double and single quotes
			patterns = [pattSingleQuotes, pattDoubleQuotes];
			break;
		case "dashes" :
			// minus signs
			patterns = [pattDashes];
			break;
		case "sectionfooter" :
			// semi-colons, '<script language=JavaScript>WriteSectionHeader', '(', ')', '/script>'
			patterns = [pattSemiColons, pattSectionFooterIE, pattSectionFooterMoz, pattOpenParen, pattCloseParen, pattClosingScript];
			break;
		case "newlines" :
			// form feed, line feed, carriage return
			patterns = [pattFormFeed, pattLineFeed, pattCarriageReturn];
			break;
		case "sectionprefix" :
			// section prefix
			patterns = [pattSectionPrefix];
			break;
		case "simplehtmltags" :
			// simple html tags, e.g. <p>, </p>, <br>, not <p class="body">
			patterns = [pattSimpleHTMLTags];
			break;
		case "whitespace" :
			// all white space
			patterns = [pattWhiteSpace];
			break;
		case "units" :
			// all measurement units, e.g. px
			patterns = [pattPixelUnits];
			break;
		default :
			// do nothing
			patterns = false;
	}
	
	if (patterns)
	{
		for (j=0; j < patterns.length; j++)
		{
			charString = charString.replace(patterns[j], "");
		}
	}
	
	return charString;
}
