function hideSpan(elem)
{
	elem.style.display = "none";
}

function baseURL()
{
	return location.protocol + "//" + location.hostname;
}

//Note: Can't use inline-block as the display type as this needs to work on Firefox
//which does not support inline-block
function showBlockSpan(elem)
{
	elem.style.display = "block";
}

function showInlineSpan(elem)
{
	elem.style.display = "inline";
}

// Assumes element has the following custom tags:
//  enabledImgUrl
//  disabledImgUrl
function disableImageButton(elem)
{
   elem.src = elem.disabledImgUrl;
   elem.disabled = 'disabled';
}

function enableImageButton(elem)
{
  elem.src = elem.enabledImgUrl;
  elem.disabled = '';
}

function formatNumberFixed (num, decplaces, commarise) 
{
	// convert in case it arrives as a string value
	num = parseFloat(num);
	// make sure it passes conversion
	if (!isNaN(num)) {
		// multiply value by 10 to the decplaces power;
		// round the result to the nearest integer;
		// convert the result to a string
		var str = "" + Math.round (eval(num) * Math.pow(10,decplaces));
		// exponent means value is too big or small for this routine
		if (str.indexOf("e") != -1) {
			return "Out of Range";
		}
		// if needed for small values, pad zeros
		// to the left of the number
		while (str.length <= decplaces) {
			str = "0" + str;
		}
		// calculate decimal point position
		var decpoint = str.length - decplaces;

		//format the number in the form 1,000,000 if required
		var wholeNum = str.substring(0,decpoint);
		if(commarise && wholeNum.length > 3) {
			newWholeNum = "";
			count = 1;
			for(x = wholeNum.length - 1; x > -1; x--)
			{
				newWholeNum = wholeNum.substr(x, 1) + newWholeNum;
				if(count % 3 == 0) newWholeNum = "," + newWholeNum;
				count++;
			}
		}
		else
		{
			newWholeNum = wholeNum;
		}

		// assemble final result from: (a) the string up to the position of
		// the decimal point; (b) the decimal point; and (c) the balance
		// of the string. Return finished product.
		return newWholeNum + (decplaces > 0 ? "." : "") +  str.substring(decpoint,str.length);
	} else {
		return "NaN";
	}
}

function getDropdownValue(dropdownCtrl)
{
	var selectedIndex = dropdownCtrl.selectedIndex;
	var selectedItem = dropdownCtrl.options[selectedIndex];
	return selectedItem.value;
}


//TODO: May need to extend for cross-browser compatibility
function getElementReference(elementId)
{
  var obj = document.getElementById(elementId);
  
  //Returns the object whether or not it found anything
  return obj;
}

//TODO: May need to extend for cross-browser compatibility
function elementReferenceExists(elementId)
{
	var obj = document.getElementById(elementId);

	//Check to make sure the object returned is null
	if (obj == null)
	{
		return false;
	}
	else
	{
		return true;
	}  
}

function $InForm(formId, elementId)
{
	var objForm = document.getElementById(formId);

	if (obj != nothing)
	{
		var objCtl = objForm.getElementById(elementId);
		return objCtl;
	}
	else
	{
		return nothing;
	}
}

function openPopupWindow(url, windowName)
{
	openWindow(url, windowName, windowName, 299, 300, "no", "yes", "auto");
}

function openBigPopupWindow(url, windowName)
{
	openWindow(url, windowName, windowName, 780, 700, "no", "yes", "auto");
}

// [JSS] Allow more control over the popup windows.
function openPopupWindowCustom(url, windowName, width, height, scrollable, resizable)
{
	var scroll = scrollable <= 0 ? "no"   : "yes";
	var resize = resizable  <= 0 ? "auto" : "yes";

	openWindow(url, windowName, windowName, width, height, "no", scroll, resize);
}

function scrollToAnchor(anchorName)
{
	var position = 0;

	//Scroll to the top of the screen to get a true offset
	window.scrollTo(0, 0);

	location.hash = anchorName;
}

function getOffset(ctl)
{
	var offsetValue;

	if (ctl.offsetParent != null)
	{
		offsetValue = getOffset(ctl.offsetParent);
	}
	else
	{
		offsetValue = 0;
	}

	return offsetValue + ctl.offsetTop;
	return 1;
}

//
// This function is required to round numbers to a specified number of decimal places
// as the toFixed method does not work on the Safari browser on Apple Macintosh as it 
// does not support JavaScript 1.5
//
function roundNumber(number, numDecimalPlaces) 
{ 
	if (number == 0)
	{
		return "0." & padEndOfString("", "0", numDecimalPlaces);
	}

	if (numDecimalPlaces == 0)
	{
		return "" + Math.round(number); 
	}

	var Multiple = Math.pow(10, numDecimalPlaces);
	var result = "" + Math.round(number * Multiple); 

	//Determine if the number is negative
	var NumberIsNegative = (number < 0);
	result = result.replace("-", "")

	var length = result.length; 
	var val = result.substring(0, length - numDecimalPlaces) + "." + padStartOfString(result.substring(length - numDecimalPlaces, length), '0', numDecimalPlaces);

	//Prefix the value with a zero if necessary
	if (val.substring(0, 1) == ".")
		val = "0" + val;

	//Add a minus sign if needed
	if (NumberIsNegative == true)
		val = "-" + val;

	return parseFloat(val); 
}

function padStartOfString(val, padChar, paddedLength)
{
	var stringVal = '' + val;

	if (padChar.length > 0)
	{
		while(stringVal.length < paddedLength)
		{
			stringVal = padChar + stringVal;
		}
	}

	return stringVal;
}

function padEndOfString(val, padChar, paddedLength)
{
	var stringVal = '' + val;

	if (padChar.length > 0)
		while(stringVal.length < paddedLength)
			stringVal = stringVal + padChar;

	return stringVal;
}

function appendChars(val, appendChar, numChars)
{
	var stringVal = '' + val;

	for (var i = 0; i < numChars; i++)
		stringVal = stringVal + appendChar;

	return stringVal;
}

function replace(string, text, by)
{ 
	// Replaces text with by in string 
	var i = string.indexOf(text); 
	if ((!i) || (i == -1)) return string; 
	var newstr = string.substring(0,i) + by; 
	if (i + text.length < string.length) 
	  newstr += replace(string.substring(i + text.length,string.length),text,by); 
	return newstr;
} 

function disableImageButtonAndUpdateImage(id, disabledImageURL)
{
	var btn = document.getElementById(id);
	btn.disabled = true;
	btn.src = disabledImageURL;
}

/**
 * window.createCookie
 * Creates a cookie
 */
function createCookie(name, value, days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*86400000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

/**
 * window.readCookie
 * Read a cookie
 */
function readCookie(name) {
	var nameEQ = name + "=";
	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 c.substring(nameEQ.length,c.length);
	}
	return null;
}

function isReferral(name)
{
	if (getQueryVariable('referrer').toLowerCase() == name.toLowerCase())
	{
		return true;
	}
	else
	{
		return false;
	}
}

function showOrHideControl( show, ctlID, block )
{
	var ctl = $(ctlID);

	if (show == true)
	{
		if (block == true)
		{
			showBlockSpan(ctl);
		}
		else
		{
			showInlineSpan(ctl);
		}
	}
	else
	{
		hideSpan(ctl);
	}
}

// [AJB] Toggles the "drop down details" panel ( <asp:panel>, rendered as a <div> block ),
// and the show/hide URL of the specified button image.
function DDDC_ToggleDetails( idShowHideDetailsButton, idDetailsPanel, urlShow, urlHide )
{
	var objButton = document.getElementById( idShowHideDetailsButton );
	if( objButton )
	{
		// Swap image URL
		if( objButton.src.indexOf( urlHide ) >= 0 )
		{
			objButton.src = urlShow;
		}
		else
		{
			objButton.src = urlHide;
		}
	}

	var objDetailsPanel = document.getElementById( idDetailsPanel );
	if( objDetailsPanel )
	{
		// Show or hide panel 
		if( objDetailsPanel.style.display == "block" )
		{
			objDetailsPanel.style.display = "none";
		}
		else
		{
			objDetailsPanel.style.display = "block";
		}
	}

}

// [AJB] Looks for specified <input> button and disables it,
// so that spurious button clicks don't get queued up while
// the server is processing a request.
function disableInputButton( button )
{
	var objButton = document.getElementById( button );
	if( objButton )
	{
		objButton.disabled = true;
	}
}

var thisQueryString;

function getQueryString() {
	if(!thisQueryString) thisQueryString = window.location.search.parseQuery();
	return thisQueryString;
}

function getQueryVariable(variable) {
	var queryString = getQueryString();
	return typeof queryString[variable] != 'undefined' ? queryString[variable] : '';
} 

/**
 * Strips unwanted characters from string and parses as floating point value
 */
String.prototype.parseCurrency = function()
{
	var val = parseFloat(this.replace(/[^0-9\.\-]/g, ''));
	return val;
}
/**
 * Converts float to formatted currency display, handles NaN's possible generated by parseCurrency
 */
Number.prototype.formatCurrency = function(dp, comma)
{
	if(isNaN(this)) return '';
	if(typeof dp == 'undefined') dp = 2;
	var num = this.toFixed(dp);
	if(comma) {
		var parts = num.split('\.');
		var digits = [];
		while(parts[0].length) {
			digits.push(parts[0].substring(parts[0].length - 3, parts[0].length));
			parts[0] = parts[0].substring(0, Math.max(parts[0].length - 3, 0));
		}
		digits.reverse();
		num = digits.join(',') + (dp ? '.' + parts[1] : '');
	}
	return num;
}

document.observe('document:contentLoaded', function(event) {
	var icons = Selector.findChildElements(event.target || document, ['a[rel=Help]']);
	icons.each(function(icon) {
		icon.rel = 'HelpReplaced';
		var code = icon.href.replace(/.*\#/, "")
		var params = code.parseQuery();
		code = code.replace(/\?.*/, "")
		Zopa.HelpManager.addHelp(icon, code, params);
	});

	Event.observe(window, 'resize', function() {
		Zopa.HelpManager.helps.each(function(help) {
			if(help.visible)
				help.reposition();
		});
	})
	Event.observe(window, 'scroll', function() {
		Zopa.HelpManager.helps.each(function(help) {
			if(help.visible)
				help.reposition();
		});
	})
	document.observe('click', function(event) {
		Zopa.HelpManager.helps.each(function(help) {
			if(help.visible) {
				if(event.target != help.icon && !Element.descendantOf(event.target, help.icon) && event.target != help.container && !Element.descendantOf(event.target, help.container))
					help.close();
			}
		});
	});
});

/* The new Zopa namespace for all our shiny things */
var Zopa = {
	/* Context help */
	Help: Class.create({
		initialize: function(icon, code, params, noIcon) {
			this.icon = icon;
			this.icon.title = 'Cosa significa?';
			this.code = code;
			this.params = params
			if(!noIcon) {
				this.icon.appendChild(new Element('img', { src: '/ApplicationResources/images/spacer.gif', className: 'helpIcon', alt: '(?)' }));
				this.icon.observe('click', this.open.bindAsEventListener(this));
			}
		},

		open: function(event) {
			this.clickCoords = [Event.pointerX(event), Event.pointerY(event)];
			if(this.icon.blur) this.icon.blur();
			if(this.visible) {
				this.close();
				return;
			}
			Zopa.HelpManager.closeAll();
			if(!this.element) {
				this.element = ($$('form.listings')[0] || document.body).appendChild(new Element('div', { className: 'contextHelpContainer' }));
				this.hBorders = this.element.appendChild(new Element('div', { className: 'contextHelpHBorders sectionBorders sectionBackground' }));
				this.vBorders = this.element.appendChild(new Element('div', { className: 'contextHelpVBorders sectionBorders' }));
				this.container = this.element.appendChild(new Element('div', { className: 'contextHelpBubble' }));
				this.stem = this.element.appendChild(new Element('div', { className: 'contextHelpStem' }));
				var closeButton = this.container.appendChild(new Element('div', { className: 'contextHelpClose' }));
				closeButton.observe('click', this.close.bind(this));
				this.heading = this.container.appendChild(new Element('div', { className: 'contextHelpHeading' }));
				this.padding = this.container.appendChild(new Element('div', { className: 'contextHelpPadding' }));
				this.contents = this.padding.appendChild(new Element('div', { className: 'contextHelpContents' })).update('Loading...');
				new Ajax.Request('/ZopaWeb/public/context-help/' + this.code + '.htm', {
					method: 'get',
					onSuccess: this.load.bind(this),
					onFailure: this.fail.bind(this)
				});
				this.shadow = new Zopa.Shadow(this.element, this.container, 4, 4);
			} else {
				($$('form.listings')[0] || document.body).appendChild(this.element);
			}

			this.reposition();
			if(this.loaded)
				this.show();
			return false;
		},

		reposition: function() {
			var coords = this.icon.cumulativeOffset();
			var offset = Math.round(340 * Math.min(coords[0] / document.viewport.getWidth(), 1));

			this.stem.style.marginLeft = offset + 'px';
			this.element.style.left = (coords[0] - 22 - offset) + 'px';
			this.element.style.top = (this.clickCoords[1] + 11) + 'px';
			this.shadow.redraw();
		},

		load: function(transport) {
			var helpText = transport.responseText;
			$H(this.params).each(function(param) {
				var regExp = new RegExp('\{' + param[0] + '\}', 'g')
				helpText = helpText.replace(regExp, param[1]);
			});
			helpTextParts = helpText.split('</h2>');
			this.heading.update(helpTextParts[0] + '</h2>');
			this.contents.update(helpTextParts[1]);
			this.show(); // IE hack
			this.dotIR();
			this.show();
			this.loaded = true;
		},

		fail: function(transport) {
			this.load({ responseText: '<h2 class="dotIR">Oops!</h2>There was a problem loading this page.' });
		},

		show: function(transport) {
			if(typeof pageTracker != 'undefined')
				pageTracker._trackPageview('/ZopaWeb/public/context-help/' + this.code + '.htm');
			this.element.show();
			$$('body')[0].addClassName('iconOpen');
			this.icon.addClassName('open');

			var maxHeight = 430;
			var contentHeight = this.contents.getDimensions().height + 7;
			var bubbleHeight = contentHeight + this.heading.getDimensions().height;
			this.padding.style.height = Math.min(contentHeight, maxHeight - (bubbleHeight - contentHeight)) + 'px';
			this.hBorders.style.height = Math.min(bubbleHeight, maxHeight) + 17 + 'px';
			this.vBorders.style.height = Math.min(bubbleHeight, maxHeight) + 19 + 'px';
			this.container.style.height = Math.min(bubbleHeight, maxHeight) + 20 + 'px';
			this.visible = true;
			this.shadow.redraw();
		},

		close: function() {
			this.element.hide();
			$$('body')[0].removeClassName('iconOpen');
			this.icon.removeClassName('open');
			this.visible = false;
		},

		dotIR: function() {
			dotIR.replaceElement("body.listings h2.dotIR", "#a42187", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("form.listings h2.dotIR", "#a42187", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("body.borrowing h2.dotIR", "#f3cf03", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("body.lending h2.dotIR", "#fa8100", "#fff", 370, "left", 16, "AgBuch.ttf"); 
			dotIR.replaceElement("body.about-zopa h2.dotIR", "#b7bc08", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("body.community h2.dotIR", "#c70303", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("body.myzopa h2.dotIR", "#2ba1df", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("body.help h2.dotIR", "#b7bc08", "#fff", 370, "left", 16, "AgBuch.ttf");
			dotIR.replaceElement("h2.dotIR", "#b7b3a1", "#fff", 370, "left", 16, "AgBuch.ttf");
		}
	}),

	HelpManager: {
		helps: [],

		closeAll: function() {
			this.helps.each(function(help) {
			if(help.element)
				help.close();
			});
		},

		addHelp: function(icon, code, params, noIcon) {
			var help = new Zopa.Help(icon, code, params, noIcon);
			this.helps.push(help);
			return help;
		}
	},

	/* Drop shadows */
	Shadow: Class.create({
		initialize: function(container, contents) {
			this.contents = contents;
			this.container = container;

			this.shadowNE = container.appendChild(new Element('div', { className: 'shadowNE' }));
			this.shadowSW = container.appendChild(new Element('div', { className: 'shadowSW' }));
			this.shadowSE = container.appendChild(new Element('div', { className: 'shadowSE' }));
			this.shadowS = container.appendChild(new Element('div', { className: 'shadowS' }));
			this.shadowE = container.appendChild(new Element('div', { className: 'shadowE' }));
		},

		redraw: function() {
			var contentOffset = this.contents.cumulativeOffset();
			var containerOffset = this.container.cumulativeOffset();
			var w = this.contents.getWidth();
			var h = this.contents.getHeight();
			var x = contentOffset[0] - containerOffset[0];
			var y = contentOffset[1] - containerOffset[1];
			this.shadowNE.style.left = (w + x) + 'px';
			this.shadowSE.style.left = (w - 1 + x) + 'px';
			this.shadowE.style.left = (w + x) + 'px';
			this.shadowSW.style.top = (h + y) + 'px';
			this.shadowSE.style.top = (h - 1 + y) + 'px';
			this.shadowS.style.top = (h + y) + 'px';

			this.shadowE.style.top = (y + 6) + 'px';
			this.shadowNE.style.top = y + 'px';
			if(w > 6)
				this.shadowS.style.width = (w - 6) + 'px'
			if(h > 6)
				this.shadowE.style.height = (h - 6) + 'px';
		}
	}),

	/* Full screen overlay for popovers */
	Overlay: Class.create({
		initialize: function(element) {
			this.visible = false;
			this.element = $(element);
			this.overlay = new Element('div');
			this.overlay.style.position = 'absolute';
			this.overlay.style.backgroundColor = '#fff';
			this.overlay.setOpacity(0.8);
			this.element.insert({ before: this.overlay });
			Event.observe(window, 'resize', this.redraw.bind(this));
			Event.observe(window, 'scroll', this.redraw.bind(this));
			this.overlay.hide();
		},
		show: function() {
			this.visible = true;
			this.overlay.show();
			this.redraw();
			$$('body')[0].style.overflowX = 'hidden';
		},
		hide: function() {
			this.visible = false;
			this.overlay.hide();
			$$('body')[0].style.overflowX = 'auto';
		},
		redraw: function() {
			if(!this.visible) return;
			this.overlay.style.top = '0';
			this.overlay.style.left = '0';
			this.overlay.style.width = '0';
			this.overlay.style.height = '0';
			var viewSize = document.viewport.getSizes();
			var position = this.overlay.cumulativeOffset();

			this.overlay.style.left = - position[0] + 'px';
			this.overlay.style.top = - position[1] + 'px';
			this.overlay.style.width = viewSize.pageWidth + 'px';
			this.overlay.style.height = viewSize.pageHeight + 'px';
		}
	}),

	/* Set up behaviour for checkboxes to enable a button */
	CheckToEnableButton: Class.create({
		initialize: function(checkBoxes, button, enabledSrc, disabledSrc) {
			this.checkBoxes = checkBoxes instanceof Array ? checkBoxes : [checkBoxes];
			this.button = button;
			this.enabledSrc = enabledSrc;
			this.disabledSrc = disabledSrc;
			document.observe('document:contentLoaded', this.init.bind(this));
		},

		init: function() {
			this.button = $(this.button);
			this.checkBoxes.each(function(checkBox) {
				$(checkBox).observe('click', this.update.bind(this));
			}, this);
			this.update();
		},

		update: function() {
			var allChecked = true;
			this.checkBoxes.each(function(checkBox) {
				allChecked = allChecked && $(checkBox).checked;
			}, this);
			this.button.src = allChecked ? this.enabledSrc : this.disabledSrc;
			this.button.disabled = allChecked ? null : 'disabled';
		}
	}),

	/* Set up behaviour for checkboxes to show a panel */
	CheckToShow: Class.create({
		initialize: function(checkBoxes, element) {
			this.checkBoxes = checkBoxes instanceof Array ? checkBoxes : [checkBoxes];
			this.element = element;
			document.observe('document:contentLoaded', this.init.bindAsEventListener(this));
		},

		init: function(event) {
			this.element = $(this.element);
			// only (re-)initialise if we are within the element firirng :contentLoaded
			if(!Element.descendantOf(this.element, event.target)) return;
			this.checkBoxes.each(function(checkBox) {
				$(checkBox).observe('click', this.update.bind(this));
			}, this);
			this.update();
		},

		update: function() {
			var allChecked = true;
			this.checkBoxes.each(function(checkBox) {
				allChecked = allChecked && $(checkBox).checked;
			}, this);
			if(allChecked) {
				this.element.show();
				if(this.element.focus) this.element.focus();
				var inputs = Selector.findChildElements(this.element, ['input']);
				if(inputs.length && inputs[0].focus) inputs[0].focus();
			} else {
				this.element.hide();
			}
		}
	})
};

document.viewport.getSizes = function() {
	var xScroll, yScroll;

	if (window.innerHeight && window.scrollMaxY) {
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}

	var windowWidth, windowHeight;

	if (self.innerHeight) {	// all except Explorer
		if(document.documentElement.clientWidth){
			windowWidth = document.documentElement.clientWidth; 
		} else {
			windowWidth = self.innerWidth;
		}
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}

	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else { 
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){
		pageWidth = xScroll;
	} else {
		pageWidth = windowWidth;
	}

	return {pageWidth: pageWidth, pageHeight: pageHeight, viewWidth: windowWidth, viewHeight: windowHeight};
}
