/* ### JAVASCRIPT CODE USED BY ALL PAGES ### */

/* for demo JSP build of Perisher, all initial functions except browser sniffer code, 'addEvent' and the main part of 'compensateMissingCSS', written by Adrian Neilson Hall for RSVP 160206; David Connard has since added several refinements and new functions */
/* note re ad imports - IE5/6/7 does not understand 'setAttribute' method with certain attributes, e.g.  iFrame.setAttribute('marginwidth','0'); it also passes over 'getAttribute('class')' */
/* note re 'length' - in an array of 7 items, the length is '7' which is one more than the number corresponding to the last item in the array */

/* browser sniffer code */
var agt=navigator.userAgent.toLowerCase();
var appVer = navigator.appVersion.toLowerCase();

var is_minor = parseFloat(appVer);
var is_major = parseInt(is_minor);

var is_opera = (agt.indexOf("opera") != -1);
var is_opera2 = (agt.indexOf("opera 2") != -1 || agt.indexOf("opera/2") != -1);
var is_opera3 = (agt.indexOf("opera 3") != -1 || agt.indexOf("opera/3") != -1);
var is_opera4 = (agt.indexOf("opera 4") != -1 || agt.indexOf("opera/4") != -1);
var is_opera5 = (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1);
var is_opera6 = (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1);
var is_opera6down = (is_opera && (is_opera2 || is_opera3 || is_opera4  || is_opera5 || is_opera6));

var iePos  = appVer.indexOf('msie');
if (iePos !=-1) {
   is_minor = parseFloat(appVer.substring(iePos+5,appVer.indexOf(';',iePos)))
   is_major = parseInt(is_minor);
}

var is_ie   = ((iePos!=-1) && (!is_opera));
var is_ie5   = (is_ie && is_major == 5);
var is_ie5_5  = (is_ie && (agt.indexOf("msie 5.5") !=-1));
var is_ie6 = (is_ie && is_minor == 6);
var is_ie6down = (is_ie && is_minor <= 6);

/* extra - less often used - sniffer code */

var is_mac = (agt.indexOf("mac")!=-1);
var iePos  = appVer.indexOf('msie');
if (iePos !=-1) {
	 if(is_mac) {
			 var iePos = agt.indexOf('msie');
			 is_minor = parseFloat(agt.substring(iePos+5,agt.indexOf(';',iePos)));
	 }
	 else is_minor = parseFloat(appVer.substring(iePos+5,appVer.indexOf(';',iePos)));
	 is_major = parseInt(is_minor);
}

var is_konq = false;
var kqPos   = agt.indexOf('konqueror');
if (kqPos !=-1) {
	 is_konq  = true;
	 is_minor = parseFloat(agt.substring(kqPos+10,agt.indexOf(';',kqPos)));
	 is_major = parseInt(is_minor);
}

var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
var is_khtml  = (is_safari || is_konq);

var is_gecko = ((!is_khtml)&&(navigator.product)&&(navigator.product.toLowerCase()=="gecko"))?true:false;
var is_gver  = 0;
if (is_gecko) is_gver=navigator.productSub;

var is_moz   = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
								(agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
								(agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
								(is_gecko) &&
								((navigator.vendor=="")||(navigator.vendor=="Mozilla")||(navigator.vendor=="Debian")));

var dhtmlBrowser = (document.getElementById && !is_opera6down) ? true: false;

/* a small DHTML library */

/* ### CREATE NEW ELEMENT ### creates and inserts a new element into the current page; takes between 3 and 9 arguments:
0 - tagName, 1 - id, 2 - class name, 3 - destination element, 4 - innerHTML, 5 - handler, 6 - function, 7 - attribute, 8 - attribute value;
note - arguments which aren't required can simply be left out, if they are sequential and the last of the arguments to be left out also happens to be the last possible argument - attribute value; however if the arguments which are not required are non-sequential or do not include the last possible argument, assign a value of 0 to each of them; e.g. if an attribute is required but a function isn't - assign value of 0 to arguments [5] & [6] ; additional attributes/value and handler/function pairs can be added to the new element, but this must be done in the function which calls this function: get the new element by its id and add additional handler+function or attribute+value */
function insertNewElement() {
	var element = document.createElement(insertNewElement.arguments[0]);
	if (insertNewElement.arguments[1]!=0) {
		element.id = insertNewElement.arguments[1];
	}
	if (insertNewElement.arguments[2]) {
		element.className = insertNewElement.arguments[2];
	}
	if (insertNewElement.arguments[4]&&(insertNewElement.arguments[4]!=0)) {
		element.innerHTML = insertNewElement.arguments[4];
	}
	if (insertNewElement.arguments[5]&&(insertNewElement.arguments[5]!=0)) {
		eval('element.' + insertNewElement.arguments[5] + ' = ' + insertNewElement.arguments[6]);
	}
	if (insertNewElement.arguments[7]) {
		element.setAttribute(insertNewElement.arguments[7],insertNewElement.arguments[8]);
	}
	insertNewElement.arguments[3].appendChild(element);
}

/* CHANGE OPACITY of an object (fade-in and/or fade-out) */
/* initialise global variables */
var startingOpacity;
var fullOpacity;
var fadeObject;
var interval;

/* fade in an object; takes 5 arguments: 1) object to be faded, 2) start opacity, 3) full opacity, 4) interval between opacity changes (in hundredths of a second), 5) delay before fade out (in seconds); note - if the last argument is not required, pass value as 0 */
function fadeIn(myFadeObject,myStartingOpacity,myFullOpacity,myInterval,myDelay) {
	myFadeObject.style.visibility = 'visible';
	/* set the value of global variables to the arguments passed */
	fadeObject = myFadeObject;
	startingOpacity = myStartingOpacity;
	fullOpacity = myFullOpacity;
	interval = 10*myInterval;
	if (is_ie||is_moz) {
		/* set the starting opacity - note: the style sheet setting doesn't suffice for Mozilla for some reason */
		setOpacity(startingOpacity);
		/* execute the function 'increaseOpacity' every x milliseconds (where x = 10*myInterval) */
		intermittentFadeIn=setInterval('increaseOpacity()',interval);
	}
	if (myDelay!=0) {
		setTimeout('fadeOut()',myDelay*1000);
	}
}

function fadeOut() {
	if (is_ie||is_moz) {
		setOpacity(fullOpacity);
		intermittentFadeOut=setInterval('reduceOpacity()',interval);
	}
	else {
		fadeObject.style.visibility = 'hidden';
		fadeObject.style.zIndex = '-1';
	}
}

function setOpacity(myOpacity) {
	if (is_moz) {
		fadeObject.style.MozOpacity=myOpacity/100;
	}
	else if (is_ie) {
		fadeObject.filters.alpha.opacity=myOpacity;
	}
}

function increaseOpacity() {
	if (is_moz && fadeObject.style.MozOpacity<(fullOpacity/100)) {
	/* 'Math.min()' method returns the number with the lowest value of two specified numbers; 'parseFloat' function determines if the first character in the specified string is a number; if it is, it parses the string until it reaches the end of the number, and returns the number as a number, not as a string; if mozilla, add .1 to the opacity as long as the result isn't full opacity value or greater; note, simply adding .1 to the opacity doesn't work, hence need to reduce the maximum 'MozOpacity' value slightly */
		fadeObject.style.MozOpacity=Math.min(parseFloat(fadeObject.style.MozOpacity)+0.1, ((fullOpacity/100)-.01));
	}
	/* if IE, add 10 to the opacity as long as the result isn't '1' or greater */
	else if (is_ie && fadeObject.filters.alpha.opacity<fullOpacity) {
		fadeObject.filters.alpha.opacity+=10;
	}
	/* otherwise (i.e. if opacity is 100%), if the 'intermittentFadeIn' function is running, stop it (i.e. remove the interval at which it is run) */
	else if (window.intermittentFadeIn) {
		clearInterval(intermittentFadeIn);
	}
}

function reduceOpacity() {
	if (is_moz && fadeObject.style.MozOpacity>0) {
		fadeObject.style.MozOpacity-=.1;
	}
	else if (is_ie && fadeObject.filters.alpha.opacity>0) {
		fadeObject.filters.alpha.opacity-=10;
	}
	else if (window.intermittentFadeOut) {
		clearInterval(intermittentFadeOut);
		fadeObject.style.zIndex = '-1';
	}
}

/* move an object: (to come) */

/* end DHTML library */


/* adjust height of #container and position of Fairfax footer on pages */
var adjustedOnce = false;
function adjustContainerHeight() {
	// don't readjust more than once, as this seems to lockup IE
	if (adjustedOnce)
		return;

	readjustContainerHeight();

	adjustedOnce = true;
}

function readjustContainerHeight() {
	var windowHeight = (is_ie) ? document.documentElement.clientHeight : window.innerHeight;
	if (document.getElementById('container').offsetHeight < windowHeight) {
		if (document.getElementById('container')) document.getElementById('container').style.height = windowHeight + 'px';
		if (document.getElementById('botStrip')) document.getElementById('botStrip').style.position = 'absolute';
		if (document.getElementById('botStrip')) document.getElementById('botStrip').style.bottom = '0px';
	}
	else {
		if (document.getElementById('botStrip')) document.getElementById('botStrip').style.position = 'relative';
	}
}

/* flip ad classes if width change requires it */
function checkForMastheadAdChange() {
	// masthead banner type is dependant on the width mode of the page, so we need to switch this too...
	var widthToLookAt = document.body.clientWidth;
	var adCat = widthToLookAt < 1000 ? 'ban' : 'lb';
	var insertLocation = document.getElementById('mastheadAd');
	if (insertLocation && insertLocation.className != adCat)
	{
		try { importAd('mastheadAd', adCat); } catch (e) { /* eh, advertising, don't care if it fails */ }
	}
}

/* ### START FORM FUNCTIONS ### */

/* alert the user if the number of characters entered equals the maximum length set for the input field or text area */
function limitEntry() {
	/* the character limit is either the value of the 'maxlength' attribute for an input field, or the number following 'maxlength_' in the class name of a text area */
	var limit = (this.getAttribute('maxlength')) ? this.getAttribute('maxlength') : this.className.split('maxlength_')[1];
	if (limit <= 0)
		return;

	/* loop through all the spans in the containing element (i.e. the parent of the textarea or input) */
	var spans = this.parentNode.getElementsByTagName('span');
	var counter;
	for (i=0; i<spans.length; i++) {
		/* if the span is inside a para with class 'count' */
		if (spans[i].parentNode.className=='count') {
			counter = spans[i];
			break;
		}
	}
	/* write the current tally of character entries in the textarea/input, to that span */
	if (counter!=null) {
		counter.innerHTML = this.value.length;
	}
	/* if the character limit is reached, alert the user */
	if ((this.value.length == limit)&&(limit>4)) {
		alert('Your text has reached the ' + limit + ' character limit.');
	}
	/* in a textarea, prevent user from typing additional text beyond the limit */
	if (this.value.length > limit) {
		this.value = this.value.substring(0, Math.min(limit, this.value.length-1));
		alert('Sorry, but we can\'t accept any more characters.');
	}
}

/* prevent double submission of forms by users - disable each form after first click on submit button */
var submitted = false;
function disableDoubleSubmit() {
	if (submitted == false) {
		submitted = true;
		return(true);
	}
	else {
		return(false);
	}
}

function resetSubmitted() {
	submitted = false;
}

/* loop through all 'input' and 'textarea' elements; if a 'maxlength' attribute is specified in an input field or the class name of a text area contains the string 'maxlength_', attach the function 'limitBox' - to be triggered on key up; NB - 'maxlength' is not an allowable attribute in 'textarea' in XHTML */
function attachFormFunctions() {
	var fieldTypes = new Array('input','textarea');
	for (j=0; j<fieldTypes.length; j++) {
		var fields = document.getElementsByTagName(fieldTypes[j]);
		for (i=0; i<fields.length; i++) {
			if ((fields[i].getAttribute('maxlength')) || (fields[i].className.indexOf('maxlength_')!=-1)) {
				// figure out what the maxlength would be...
				var limit = (fields[i].getAttribute('maxlength')) ? fields[i].getAttribute('maxlength') : fields[i].className.split('maxlength_')[1];
				if (limit > 0) {
					fields[i].onkeyup = limitEntry;
				}
			}
		}
	}
	/* attach 'disableDoubleSubmit' function to every form in #rsvpcontent, to be triggered on submit */
	var forms = document.getElementById('rsvpcontent').getElementsByTagName('form');
	for (k=0; k<forms.length; k++) {
		forms[k].onsubmit = disableDoubleSubmit;
	}
}
/* ### END FORM FUNCTIONS ### */

/* removes spaces in text strings and replaces them with underscores, to enable string manipulation in javscript */
function jsFormat(myString) {
	while (myString.indexOf(" ") != -1) {
		myString = myString.replace(" ","_");
	}
	return myString;
}

/* show/hide/toggle */
var docObj = 'document.getElementById' + '(';
var styleObj = ')' + '.style';

/* set the display of an element to either 'block', 'inline' or 'none'; (can be applied to multiple elements) */
function setDisplay() {
	/* loop through all arguments except the 1st */
	for (var i=1; i<(setDisplay.arguments.length); i++) {
		dom = eval(docObj + 'setDisplay.arguments[i]' + styleObj);
		/* set the elements display to the value held in 1st argument */
		dom.display = setDisplay.arguments[0];
	}
}

/* set the display of an element to 'block' if it is currently 'none', and vice versa; (can be applied to multiple elements)  */
function toggle() {
	/* loop through all arguments */
	for (var i=0; i<(toggle.arguments.length); i++) {
		dom = eval(docObj + 'toggle.arguments[i]' + styleObj);
		dom.display = (dom.display!='block') ? 'block' : 'none';
	}
}

/* create hover (rollover) effect on current element (for IE5/6) - append class name 'mouseover' */
function hoverStyle() {
	this.className += ' over';
}

/* remove hover (rollover) effect on current element (for IE5/6) - remove class name 'mouseover' */
function defaultStyle() {
	this.className = this.className.replace(' over','');
}

/* note re MENUS & NAV HIGHLIGHTING -
by default, function 'showActiveTabs' will look at the text of the first <h1> in the #rsvpcontent div, and if there is a match with the text of a nav item in the main menu, it will highlight that nav item; similarly, if there is a match between the text of the first <h2> (if any) in the #rsvpcontent div and the text of a nav item in the supplementary menu, it will highlight that nav item; however if there is an element with id 'primary', 'showActiveTabs' will match its text rather than that of the first <h1>, and if there is an element with id 'secondary', 'showActiveTabs' will match its text rather than that of the first <h2>; this allows us to display in the browser a different set of headings to the ones which trigger nav highlighting (e.g. 'competition' is displayed as the page title, but 'win prizes' is the corresponding nav in the main menu); we can also give prominence to a secondary title by tagging it as <h1> with id="secondary" (e.g. 'terms and conditions' is displayed as the page title, though this corresponds to a nav in the supplementary menu, while 'help' is its corresponding nav in the main menu) */

/* replace HTML code for ampersand with simple ampersand in document title (for 'showActiveTabs()' below) */
function titleFormat(myString) {
	while (myString.indexOf("&amp;") != -1) {
		myString = myString.replace("&amp;","&");
	}
	return myString;
}

/* initialise 2 variables for 'showActiveTabs()' below */
var titlesInitialised = false;
var primaryTitle;
var secondaryTitle;
var firstLastTagged = false;

/* if the page has a main menu or a supplementary menu in CSS layout, highlight the menu tabs that correspond to the page titles */
function showActiveTabs()
{
	initialiseTitles();
	/* if the page has a main menu in CSS layout */
	if (document.getElementById('menu')) {
		/* loop through all the <a> elements in the main menu */
		var tabs = document.getElementById('menu').getElementsByTagName('a');
		for (var i=0; i<tabs.length; i++) {
			/* if  the text of an <a> element is the same as the primary page title */
			if ((primaryTitle&&(tabs[i].innerHTML==primaryTitle.innerHTML))||(secondaryTitle&&(tabs[i].innerHTML==secondaryTitle.innerHTML))) {
			/* make that <a> element the 'current' tab; i.e. give the <a> element the class 'current' */
				tabs[i].className += ' current';
			}
		}
	}
	/* write document title to browser title bar, based on primary title and secondary title (if latter exists and is different) */
	var titleA = (primaryTitle!=null) ? titleFormat(primaryTitle.innerHTML) : null;
	var titleB = (secondaryTitle!=null) ? titleFormat(secondaryTitle.innerHTML) : null;
	var titles = (titleB!=null) ? titleA + ' : ' + titleB : titleA;
	/* use default title for home page and any page without an 'h1' in #rsvpcontent */
	if ((titleA!=null)&&(titleA!='Home')) {
		/* prevent duplication in page title */
		document.title = (titleA==titleB) ? 'RSVP : ' + titleA : 'RSVP : ' + titles;
	}
}

/* adjust following javascript so that secondaryTitle is null (and thus ignored for title bar) if there is no h5.pageTitle and the first h2's parent node isn't #rsvpcontent; also write class="pageTitle" to h1 if secondary title is null; replace all id="secondary" with class="pageTitle"; also - remove unique ids form h1 tags and place in footer as a variable to be filled by serverside code which reads ofroma table  */

function initialiseTitles()
{
	if (!titlesInitialised)
	{
		/* if there's an element with id #primary, make it the primary title, otherwise make the first <h1> in #rsvpcontent the  primary title */
		primaryTitle = (document.getElementById('primary')) ? document.getElementById('primary') : document.getElementById('rsvpcontent').getElementsByTagName('h1')[0];
		/* if there's an element with id #secondary, make it the secondary title, otherwise make the first <h2> in #rsvpcontent the  secondary title */
		if ((document.getElementById('rsvpcontent').getElementsByTagName('h2')) || (document.getElementById('secondary')))
		{
			secondaryTitle = (document.getElementById('secondary')) ? document.getElementById('secondary') : document.getElementById('rsvpcontent').getElementsByTagName('h2')[0];
		}

		titlesInitialised = true;
	}
}

/* ### IMPORT ADS ### */

/* MULTI-LINK ADS */
/* initialise flag to prevent Opera creating new iframes ad infinitum */
var multiLinksImported = false;
function importMultiLinkAds() {
	/* if the page has a div#textLinkAds */
	if (document.getElementById('multiLinkAds')) {
		// create an iframe for the multi links.  Unfortunately, the multi links (sometimes) require hacking of the document.domain
		// property, which in turn interacts badly with (ie. breaks) with  chat system, so, we have to keep the multi links
		// in their own document body outright
		if (!multiLinksImported) {
			var iFrame=document.createElement('iframe');
			/* give it some attributes to remove margin, border and scrollbars */
			iFrame.marginWidth='0';
			iFrame.marginHeight='0';
			iFrame.frameBorder='0';
			iFrame.scrolling='no';
			iFrame.width='98%';
			iFrame.height='70px';
			/* set the source of the iframe content */
			var bust = Math.floor(1000000*Math.random());
			iFrame.setAttribute('src','/multilinks.jsp' + tomcatSessionArgs + '?ord='+bust);
			/* insert the new iFrame in div#textLinkAds */
			document.getElementById('multiLinkAds').appendChild(iFrame);
			multiLinksImported = true;
		}
	}
}

/* ADs */
/* if the current page is to serve an ad, import the ad via a new iframe */
function importAd(insertLocationId, cat)
{
	initialiseTitles();
	var insertLocation = document.getElementById(insertLocationId);
	if (insertLocation)
	{
		var adPage = null;
		if ("mastheadAd" == insertLocationId)
		{
			adPage = '/adMH.jsp';
			// cat must be specified
		}
		else if ("MRecAd" == insertLocationId)
		{
			adPage = '/adMR.jsp';
			cat = "mr";
		}
		else if ("searchAd" == insertLocationId)
		{
			adPage = '/adSearch.jsp';
			cat = "ban";
		}
		else if ("kissAd" == insertLocationId)
		{
			adPage = '/adKiss.jsp';
			cat = "lb";
		}

		if (adPage != null)
		{
			/* presume banner size */
			var ifWidth = 468;
			var ifHeight = 60;
			if ("lb" == cat)
			{
				ifWidth = 728;
				ifHeight = 90;
			}
			else if ("mr" == cat)
			{
				ifWidth = 300;
				ifHeight = 250;
			}

			var primaryTitleText = !primaryTitle || primaryTitle == null ? 'na' : primaryTitle.innerHTML;
			var secondaryTitleText = !secondaryTitle || secondaryTitle == null ? 'na' : secondaryTitle.innerHTML;
			var localBust = Math.floor(1000000*Math.random());

			var srcStr = adPage + tomcatSessionArgs + '?pt=' + primaryTitleText + '&st=' + secondaryTitleText + '&ct=' + cat + '&ord=' + localBust;
			//alert(srcStr);

			insertLocation.className = cat;

			ffx_swap(insertLocationId, '<IFRAME WIDTH="' + ifWidth + '" HEIGHT="' + ifHeight + '" MARGINWIDTH="0" MARGINHEIGHT="0" HSPACE="0" VSPACE="0" FRAMEBORDER="0" SCROLLING="no" BORDERCOLOR="#000000" SRC="' + srcStr + '"></IFRAME>');
		}
	}
}

/* attach to all <a> elements with class name 'ext', target='blank' */
function attachTarget() {
	/* loop through all the <a> elements in the page */
	var aTags = document.getElementsByTagName('a');
	for (var i=0; i<aTags.length; i++) {
		/* if  the <a> element has class name 'ext' */
		if (aTags[i].className == 'ext') {
		/* attach the target attribute with value 'blank' */
			aTags[i].target = 'blank';
		}
	}
	/* loop through all nodes; note - 'wildcard' tag name doesn't work in IE5 so use 'all' instead */
	var nodes = (is_ie5) ? document.getElementById('rsvpcontent').all : document.getElementById('rsvpcontent').getElementsByTagName('*');
	for (i=0; i<nodes.length; i++) {
		/* if  the <a> element has class name 'alert' */
		if (nodes[i].className.indexOf('alert')!=-1) {
		/* attach a function which alerts the title attribute value on click */
			nodes[i].onclick = function() {
				alert(this.title);
			}
		}
		/* if  the <a> element has class name 'chat' */
		if (nodes[i].className.indexOf('function')!=-1) {
		/* attach a function (passed as title attribute value) which is triggered on click */
			nodes[i].onclick = function() {
				eval(this.title);
			}
		}
	}
}

/* create rounded corners in any element with class 'feature', in any button and in any link within div.actions */
/* note the need for a flag to stop Opera from continuing to loop through the array and create and insert elements */
/* IE5.5 is excluded because it inserts a gap of 1px between each of the 'b' elements (despite 'overflow:hidden') */
var cornersAreRounded = false;
function roundCorners() {
	if (!cornersAreRounded&&!is_ie5_5) {
		/* loop through all nodes; note - 'wildcard' tag name doesn't work in IE5 so use 'all' instead */
		var nodes = (is_ie5) ? document.getElementById('rsvpcontent').all : document.getElementById('rsvpcontent').getElementsByTagName('*');
		for (i=0; i<nodes.length; i++)
			roundCornersForNode(nodes[i]);
		cornersAreRounded = true;
	}
}

function roundCornersForNode(node) {
	if (!is_ie5_5) {
		/* set up some variables to identify the different types of elements affected */
		var featureClass = (node.className.indexOf('feature')!=-1) ? true : false;
		var sectionHd = (node.className.indexOf('sectionHead')!=-1) ? true : false;
		/* if the node has class name 'feature' OR if it is a button OR if it is a link in div.actions */
		if (featureClass) {
			/* create bottom corner container element */
			var newBot = document.createElement('b');
			newBot.className = 'rb';
			/* insert 4 bottom corner step elements for all affected nodes, except if section head - which takes 2 only */
			newBot.innerHTML = (sectionHd) ? '<b></b><b class="c"></b>' : '<b class="d"></b><b class="c"></b><b class="b"></b><b class="a"></b>';
			/* insert bottom corner elements in the node & remove existing padding */
			node.appendChild(newBot);
			node.style.padding='0';
			/* if the node's class name doesn't include 'details' */
			if (node.className.indexOf('details')==-1) {
				/* create top corner container element */
				var newTop = document.createElement('b');
				newTop.className = 'rt';
				/* insert top corner step elements */
				newTop.innerHTML = (sectionHd) ? '<b class="c"></b><b></b>' : '<b class="a"></b><b class="b"></b><b class="c"></b><b class="d"></b>';
				/* insert top corner elements in the node */				
				node.appendChild(newTop);
				node.insertBefore(newTop,node.firstChild);
			}
		}
	}
}

/* declare a global variable for an array of select boxes which are hidden on mouseover and shown on mouseout (to prevent obscuring of submenu list) */
var hiddenSelects = new Array;

/* override a number of deficiencies in IE5x/6 only (missing CSS capabaility and window objects which ignore z-index) */
function compensateMissingCSS() {
	if (is_ie6down) {
		/* in lieu of 'first-child' pseudo class, insert class name 'first' in first 'li' in #footer and div.sectionHead */
		if (document.getElementById('footer') &&
			document.getElementById('footer').getElementsByTagName('li').length > 0) {
			document.getElementById('footer').getElementsByTagName('li')[0].className='first';
		}
		var divs = document.getElementsByTagName('div');
		for (i=0; i<divs.length; i++) {
			if (divs[i].className.indexOf('sectionHead')!=-1) {
				/* note - only this syntax (in following line) will prevent js error:*/
				if (divs[i].getElementsByTagName('li')[0]) {
					divs[i].getElementsByTagName('li')[0].className+=' first';
				}
			}
		}
		/* insert class 'over' in menu list items to enable show & hide of nested lists, on hover */
		if (document.getElementById('menu')) {
			menuList = document.getElementById('menu').getElementsByTagName('ul')[0];
			if (menuList) {
				for (i=0; i<menuList.childNodes.length; i++) {
					node = menuList.childNodes[i];
					if (node.nodeName=='LI') {
						node.onmouseover=function() {
							this.className+=" over";
							/* ### hide any select boxes that might obscure the current submenu list ### */
							var list = this.getElementsByTagName('ul')[0];
							var	selects = document.getElementById('rsvpcontent').getElementsByTagName('select');
							/* if a submenu exists for the current nav and there are select boxes in #rsvpcontent, */
							if ((list!=null)&&(selects[0]!=null)) {
								/* declare a set of variables to mark the 'x' coordinates of the top 2 corners and the 'y' coordinates of the bottom 2 corners of the current list */
								var lxa = findPos(list)[0];
								var lxb = (findPos(list)[0]) + list.offsetWidth;
								var lya = findPos(list)[1];
								var lyb = (findPos(list)[1]) + list.offsetHeight;
								/* ensure that the 'hiddenSelects' array is empty */
								hiddenSelects.length = 0;
								/* loop through all the select boxes in #rsvpcontent */
								for (i=0; i<selects.length; i++) {
									/* declare a set of variables to mark the 'x' coordinates of the top 2 corners and the 'y' coordinates of the bottom 2 corners of the current select box */
									var sxa = findPos(selects[i])[0];
									var sxb = (findPos(selects[i])[0]) + selects[i].offsetWidth;
									var sya = findPos(selects[i])[1];
									var syb = (findPos(selects[i])[1]) + selects[i].offsetHeight;
									/* declare a set of variables to determine whether the coordinate range of the currrent list has any points in common with coordinate range of the current select box */
									var leftOverlap = ((lxa<sxa)&&(lxb>sxa)) ? true : false;
									var rightOverlap = ((lxa<sxb)&&(lxb>sxb)) ?  true : false;
									var topOverlap = ((lya<sya)&&(lyb>sya)) ? true : false;
									var botOverlap = ((lya<syb)&&(lyb>syb)) ?  true : false;
									/* if there is an overlap, */
									if ((leftOverlap||rightOverlap)&&(topOverlap||botOverlap)) {
										/* hide the select box to prevent obscuring of submenu list */
										selects[i].style.visibility = 'hidden';
										/* add the select box to the array 'hiddenSelects' */
										hiddenSelects.push(selects[i]);
									}
								}
							}
							/* and hide media objects in page (if they would obscure the current submenu) */
							setMediaVisibility(this, false);
						}
						node.onmouseout=function() {
							this.className=this.className.replace(" over", "");
							var label = this.getElementsByTagName('a')[0].innerHTML;
							/* show any select boxes which were hidden on mouse over */
							if (hiddenSelects.length!=0) {
								showSelectBoxes();
							}
							/* show hidden media objects */
							setMediaVisibility(this, true);
						}
					}
				}
			}
		}
	}
}

/* find the position of any element in current page; note - returns an array of 2 items */
function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return [curleft,curtop];
}

/* hide select boxes if visible; and show if hidden */
function toggleSelectBoxes() {
	selects = document.getElementById('rsvpcontent').getElementsByTagName('select');
	for (i=0; i<selects.length; i++) {
		selects[i].style.visibility = (selects[i].style.visibility!='hidden') ? 'hidden' : 'visible';
	}
}

/* show hidden select boxes */
function showSelectBoxes() {
	for (i=0; i<hiddenSelects.length; i++) {
		hiddenSelects[i].style.visibility = 'visible';
	}
}

/* in all browsers - hide embedded media (audio/video) when mousing over certain menu tabs, to prevent obscuring of child menu lists */
function addToggleMediaVisibility() {
	menuList = document.getElementById('menu').getElementsByTagName('ul')[0];
	if (menuList) {
		for (i=0; i<menuList.childNodes.length; i++) {
			node = menuList.childNodes[i];
			if (node.nodeName=='LI') {
				/* when mousing over a menu tab, */
				node.onmouseover=function() {
					/* hide media objects in page (if they would obscure the current submenu) */
					setMediaVisibility(this, false);
				}
				/* when mousing out of a menu tab, */
				node.onmouseout=function() {
					/* show the hidden media objects */
					setMediaVisibility(this, true);
				}
			}
		}
	}
}

function setMediaVisibility(myNode, vis) {
	var label = myNode.getElementsByTagName('a')[0].innerHTML;
	var mediaEmbedded = ((document.getElementById('MediaPlayerObj'))||(document.getElementById('MediaPlayerEmbed'))) ? true : false;
	var navAffected = ((label=='My Profile')||(label=='Stamps')||(label=='Favourites')||(label=='Mailbox')) ? true : false;
	/* if media is currently embedded in the page and the currently moused over menu tab is 1 of the 4 named above, */
	if (mediaEmbedded&&navAffected) {
		/* hide the #media div which contains embedded media - works in Mozilla * IE */
		var newVis = vis ? 'visible' : 'hidden';
		var oldVis = document.getElementById('media').style.visibility;
		if (newVis != oldVis) {
			document.getElementById('media').style.visibility = newVis;
		}
	}
}

/* note re function above  - hiding the embedded media itself doesn't work in IE; hence we can't use:
var mediaArray = new Array('MediaPlayerObj','MediaPlayerEmbed');
for (i=0; i<mediaArray.length; i++) {
	document.getElementById(mediaArray[i]).style.visibility = (document.getElementById(mediaArray[i]).style.visibility!='hidden') ? 'hidden' : 'visible';
}*/

// wtf... I hear you say?  take a look at: http://www.peterbe.com/plog/button-tag-in-IE
function attachButtonDisables() {
	var buttons = document.getElementsByTagName("button");
	if (buttons) {
		for (i=0; i < buttons.length; i++) {
			if (buttons[i].getAttribute('type')=='submit') {
				buttons[i].onclick=disableOtherButtons;
			}
		}
	}
}

function disableOtherButtons() {
	var buttons = document.getElementsByTagName("button");
	if (buttons) {
		for (i=0; i < buttons.length; i++) {
			if ((buttons[i] != this)&&(buttons[i].getAttribute('type')!='button')) {
				buttons[i].disabled=true;
			}
		}
	}
}

function enableOtherButtons() {
	var buttons = document.getElementsByTagName("button");
	if (buttons) {
		for (i=0; i < buttons.length; i++) {
			if (buttons[i] != this) {
				buttons[i].disabled=false;
			}
		}
	}
}

function scrollToSelection(selectBox)
{
	try
	{
		if ((selectBox == null) || (!selectBox)) return;

		var options = selectBox.options;
		var selectedCounter = 0;
		var firstSelectedIndex = -1;
		var allSelected = new Array();
		//alert(options.length);
		for (var i=0; i<options.length; i++)
		{
			if (options[i].selected)
			{
				if (firstSelectedIndex == -1) firstSelectedIndex = i;
				allSelected.push(i);
			}
		}
		// this line seems to make the script work in Firefox :-)
		selectBox.selectedIndex = firstSelectedIndex;

		// start from last one
		for (var i = allSelected.length-1; i > 0; i--)
		{
			options[allSelected[i]].selected = true;
		}

	}
	catch (ex)
	{
		//alert(ex + ', on select box named ' + selectBox.name);
	}

}

/* a function for ie7 and below only; insert quotation marks that should (but don't) appear inside the 'q' tag */
function insertQuoteMarks() {
	var quotes = document.getElementById('rsvpcontent').getElementsByTagName('q');
	if (quotes[0]) {
		for (i=0; i<quotes.length; i++) {
			quotes[i].innerHTML = '&quot;' + quotes[i].innerHTML + '&quot;';
		}
	}	
}

/* functions to be run from footer: */
function runGlobalFunctions() {
	showActiveTabs();
	roundCorners();
	if (!is_ie6down) {
		addToggleMediaVisibility();
	}
	if (is_ie) {
		insertQuoteMarks();
	}
	importMultiLinkAds();
}

/* enable functions to be added to a specified object and to be triggered by a specified event; e.g. run the 'attachTarget' function when the window loads */
function addEvent(obj, evType, fn) {
	if (obj.addEventListener) {
		obj.addEventListener(evType, fn, true);
		return true;
	}
	else if (obj.attachEvent) {
		var r = obj.attachEvent("on"+evType, fn);
		return r;
	}
	else {
		return false;
	}
}

/* for IE4, NS3/4  and Opera 5-*/
function ignoreErrors() {
	return true;
}
if (!dhtmlBrowser) {
	window.onerror = ignoreErrors;
}

/* on load, call the following functions: */
/* note - some of the calls that were orignally made here have been shifted to the footer (/jsf/global.js); note - for some reason, IE5x/6 cannot run 'compensateMissingCSS' or 'addToggleMediaVisibility' from the footer; consequently the common script from function 'addToggleMediaVisibility' has been split off into a module - 'toggleMediaVisibility(myNode)' which is now called from 'compensateMissingCSS' (for IE only) on load; note also that these functions will not work in IE if the 'is_ie6down' test is run on them in the add event function on load; bottom line - Mozilla & Opera runs the hide media function before the page loads, while IE runs it as part of the submenu dropdown function on load */
if (dhtmlBrowser) {
	addEvent(window, 'load', compensateMissingCSS);
	addEvent(window, 'load', attachTarget);
	addEvent(window, 'load', attachFormFunctions);
	addEvent(window, 'load', adjustContainerHeight);
	addEvent(window, 'resize', adjustContainerHeight);
	addEvent(window, 'resize', checkForMastheadAdChange);
	addEvent(window, 'pageshow', resetSubmitted); // to handle firefox "fastcache" to allow submit buttons to be used after back
	if (is_ie6down) {
		addEvent(window, 'load', attachButtonDisables);
	}
}
