	//Common code: Copyright 2008 Made Headway Limited

	var cTabIdx = -1;

	//Handle loading:
	function HandleLoaded()
	{
		var i;
		for ( i=0;i<loadHandlers.length;i++)
		{
			loadHandlers[i]();
		}
		loadHandlers = [];
	}
	function closeTab()
	{
		if ( cTabIdx != -1 )
		{
			var tab = GetElem( "tab"+cTabIdx );
			var content = GetElem( "tabContent"+cTabIdx );
			if ( tab && content )
			{
				tab.className = "unselTab";
				content.className = "unselTabContent";
			}
		}
		cTabIdx = 0;
	}
	function openTab(_idx)
	{
		closeTab();
		var tab = GetElem( "tab"+_idx );
		var content = GetElem( "tabContent"+_idx );
		if ( tab && content )
		{
			tab.className = "selTab";
			content.className = "selTabContent";
			cTabIdx = _idx;
		}	
	}
	function NewsletterSignUp( _signUp )
	{
		RequestURL( "staticMessage.php?f=newsletter&signup="+(_signUp?1:0), null, "receiveBlock", function() {} );
	}
	function SubmitMessage( _message, _id )
	{
		GetElem('sendBlock').innerHTML = RemoveHTML(_message);
		GetElem('receiveBlock').innerHTML = '';
		var extraParams = '';
		if ( !g_loggedIn )
		{
			var fromName = GetElem( 'messageSubmitForm_name'+_id );
			var fromEmail = GetElem( 'messageSubmitForm_email'+_id );
			var fromPhone = GetElem( 'messageSubmitForm_phone'+_id );

			if ( !fromName || !fromEmail || !fromPhone )
			{
				return;
			}
			fromName = fromName.value;
			fromEmail = fromEmail.value;
			fromPhone = fromPhone.value;

			if ( !fromEmail.length && !fromPhone.length )
			{
				alert( "Please specify an e-mail address or telephone number so we can contact you!" );
				return;
			}
			extraParams = "&fromName="+encodeURIComponent(fromName)+"&fromEmail="+encodeURIComponent(fromEmail)+"&fromPhone="+encodeURIComponent(fromPhone);
		}
		RequestURL( "staticMessage.php?f=message"+extraParams, "sendBlock", "receiveBlock", MessageDeliveredCallback );
	}
	function MessageDeliveredCallback()
	{
		alert( 'Message delivered to Saxonbury. We will respond as quickly as possible.' );
	}


	/////////////////////////
	// Fully common code:

	function ReconcileEvent( _evt )
	{
		_evt = (_evt?_evt:(window.event?window.event:null));
		if ( _evt )
		{	
			if (!_evt.target && _evt.srcElement )
			{
				_evt.target = _evt.srcElement;
			}
			if (!_evt.clientX && _evt.pageX )
			{
				_evt.clientX = _evt.pageX;
				_evt.clientY = _evt.pageY;
			}
		}
		return _evt;
	}

	//Get an element in a browser-friendly fashion
	function GetElem( id ) 
	{
        if ( id == null || id == '' )
        {
            return null;
        }

		if (document.getElementById) 
		{
			return document.getElementById(id);
		} 
		else if (document.all) 
		{
			return document.all[id];
		} 
		else if (document.layers)	
		{
			return document.layers[id];
		}
		return null;
	}
	function GetWindowHeight()
	{
		var winHeight = (window.innerHeight?window.innerHeight:document.documentElement.clientHeight);
		if ( !winHeight )
		{
			winHeight = document.clientHeight;
		}
		if ( !winHeight )
		{
			winHeight = 600;
		}
		return winHeight;
	}
	function GetWindowWidth()
	{
		var winWidth = (window.innerWidth?window.innerWidth:document.documentElement.clientWidth);
		if ( !winWidth )
		{
			winWidth = document.clientWidth;
		}
		if ( !winWidth )
		{
			winWidth = 800;
		}
		return winWidth;
	}	
	function OpenDialog( _sizeX, _sizeY, _title )
	{
		var guiElem = GetElem( "GUILayer" );
		if ( guiElem )
		{
			var winWidth = GetWindowWidth();
			var winHeight = GetWindowHeight();
			guiElem.style.width = winWidth;
			guiElem.style.height = winHeight;

			guiElem.style.visibility = 'visible';

			var titleHeight = 20;
			var dialogHeight = Math.min( _sizeY, winHeight - titleHeight - 20 );	//Make a smaller dialog if necessary
			var fullHeight = (dialogHeight == _sizeY);
			var dialogWidth = _sizeX;

			var dialogTop = (winHeight - dialogHeight)/2;
			var dialogLeft = (winWidth - dialogWidth)/2;
			var newWin = document.createElement( 'div' );

            newWin.innerHTML = '\
                    <div style="position:absolute;top:0px;left:0px;width:'+winWidth+'px;height:'+winHeight+'px"></div>\
                    <div class="sxb_dialog" style="width:'+dialogWidth+'px;top:'+dialogTop+'px;left:'+dialogLeft+'px;position:absolute;padding:0px 0px 0px 0px;">\
                        <div class="sxb_titlebar" style="height:'+titleHeight+'px;width:100%;">\
                                <img class="editButton" src="editImages/close.gif" onclick="javascript:CancelDialog();"/>\
                                '+_title+'\
                        </div>\
                        <div class="sxb_dialog_content" style="'+(fullHeight?'overflow-y:hidden;':'height:'+(dialogHeight-titleHeight-4)+'px;overflow-y:auto;') + '">\
                        </div>\
                    </div>'; 
			guiElem.appendChild( newWin );

			return FindDialogContent( guiElem.lastChild ); //Assumes DOM constructed correctly...
		}
		return null;
	}
	//Return the content pane of the dialog:
	function FindDialogContent( _dialogRoot )
	{
		var newDialog = _dialogRoot;
		var i;
		for (i=0;i<newDialog.childNodes.length;i++)
		{
			var child = newDialog.childNodes[i];
			if ( child.tagName == 'DIV' && child.className == 'sxb_dialog' )
			{
				var j;
				for (j=0;j<child.childNodes.length;j++)
				{
					var contentDiv = child.childNodes[j];
					if ( contentDiv.tagName == 'DIV' && contentDiv.className == 'sxb_dialog_content' )
					{
						return contentDiv;
					}
				}
				break;	          
			}
		}
	}
	function GetTopDialog()
	{
		var guiElem = GetElem( 'GUILayer' );
		if ( guiElem )
		{
			//Get the last child:
			if ( guiElem.hasChildNodes() )
			{
				var topDiv = null;
				var i;
				for(i=guiElem.childNodes.length-1;i>=0;i--)
				{
					var elem = guiElem.childNodes[i];
					if (elem.tagName == 'DIV')
					{ 
						return elem;
					}
				}
			}
		}
		return null;
	}
	function CancelDialog()
	{
		var guiElem = GetElem( 'GUILayer' );
		if ( guiElem )
		{
			//Get the last child:
			if ( guiElem.hasChildNodes() )
			{
				var prevDiv = null;
				var topDiv = null;
				var i;
				for(i=guiElem.childNodes.length-1;i>=0;i--)
				{
					var elem = guiElem.childNodes[i];
					if (elem.tagName == 'DIV')
					{ 
						if (topDiv == null)
						{
							topDiv = elem;
						}
						else
						{
							prevDiv = elem;
							break;
						}
					}
				}
				if ( topDiv )
				{
					DestroyChildren( topDiv );
					guiElem.removeChild( topDiv );
				}
				if ( !prevDiv )
				{
					DestroyChildren( guiElem );	//Clean up
					guiElem.style.visibility = 'hidden';
				}
			}
		}
	}
	function DestroyChildren( _elem )
	{
		while ( _elem && _elem.hasChildNodes() )
		{
			_elem.removeChild( _elem.firstChild );	
		}
	}

	var isIE = /*@cc_on!@*/false;
	var xmlhttp = null;	
	var requestOutBlock = null;
	var requestCallback = null;
	var EventType = { Completed:0, URLRequest:1, URLProcessing:3, Error:4, Refresh:5 };
	var currentEventType = 0;

	//Request class:
	function Request( _url, _sendBlock, _receiveBlock, _requestCallback )
	{
		this.m_url = _url;
		this.m_sendBlock = _sendBlock;
		this.m_receiveBlock = _receiveBlock;
		this.m_requestCallback = _requestCallback;
	}
	var pendingRequests = new Array();

	function HandleError( _error )
	{
		//For now, just alert
		alert( _error );
		HandleEvent( EventType.Error );
	}

	function HandleEvent( _eventType )
	{
		if ( _eventType == EventType.Refresh )
		{
			_eventType = currentEventType;
		}
		currentEventType = _eventType;		

		var eventIcon = ( _eventType == EventType.Completed ) ? "event_completed" :
				( _eventType == EventType.URLRequest ) ? "event_processUrl" :
				( _eventType == EventType.URLProcessing ) ? "event_processUrl" : "event_error";

		var eventTxt  = ( _eventType == EventType.Completed ) ? "Completed" :
			      	( _eventType == EventType.URLRequest ) ? "Transmitting data..." :
       			 	( _eventType == EventType.URLProcessing ) ? "Processing data" : "Error!";

		var pendingTxt = '';
		if ( pendingRequests.length )
		{
			pendingTxt = ' (+ '+pendingRequests.length+' pending requests...)';
		}

		eventIcon = 'planning/prototype/' + eventIcon + '.png';
		var eventImg = GetElem( 'eventImg' );
		if ( eventImg )
		{
			eventImg.src = eventIcon;
		}
		
		var statusTxt = GetElem( 'statusTxt' );
		if ( statusTxt )
		{
			statusTxt.innerHTML = "Status: "+eventTxt+pendingTxt;
		}
	}

	//Setup request logic
	function InitXMLHttp()
	{
		xmlhttp = null;
		// code for Mozilla, etc.
		if (window.XMLHttpRequest)
		{
			xmlhttp=new XMLHttpRequest();
		}
		// code for IE
		else if (window.ActiveXObject)
		{
			xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
		}
	}

	//Save the current instance
	function RequestURL( _url, _sendBlock, _receiveBlock, _requestCallback )
	{
		HandleEvent( EventType.URLRequest );
		
		//The problem with waiting for this is that _requestCallback needs to be textualised. :)
		if ( requestOutBlock != null )
		{
			var request = new Request( _url, _sendBlock, _receiveBlock, _requestCallback );
			pendingRequests.push( request );
			HandleEvent( EventType.Refresh );
			return;
		}

		var url = _url;
		var data = '';

		var sBlock = GetElem( _sendBlock );
		var rBlock = GetElem( _receiveBlock );		

		requestOutBlock = rBlock;
		requestCallback = _requestCallback;

		if ( sBlock )
		{
			data = "block="+SmartEscape( sBlock.innerHTML );
		}

		if ( rBlock )
		{
			InitXMLHttp();
			if (xmlhttp!=null)
			{
                                //To try to reduce 406 errors:
                                if ( url)
                                {
                                        var questionPos = url.indexOf('?');
                                        if ( questionPos>=0 )
                                        {
                                                if ( data != '' )
                                                {
                                                        data += '&';
                                                }
                                                data += url.substr( questionPos+1 );
                                                url = url.substr(0,questionPos );
                                        }
                                }


				xmlhttp.open("POST",url,true);
				xmlhttp.onreadystatechange=RequestURLResponse;
				xmlhttp.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' ); 
				xmlhttp.send(data);
			}
			else
			{
				HandleError("Could not get URL! (Error 0x1000; Browser incompatibility)");
			}
		}
		else
		{
			HandleError("Could not get URL into non-existant element!");
		}
	}

	function ProcessNextPendingRequest()
	{
		//Handle any deferred requests:
		var request = pendingRequests.shift();
		if ( request )
		{
			RequestURL( request.m_url, request.m_sendBlock, request.m_receiveBlock, request.m_requestCallback );
		}
	}

    //Window size:
    function GetWindowHeight()
    {
        var winHeight = (window.innerHeight?window.innerHeight:document.documentElement.clientHeight);
        if ( !winHeight )
        {
            winHeight = document.clientHeight;
        }
        if ( !winHeight )
        {
            winHeight = 600;
        }
        return winHeight;
    }
    function GetWindowWidth()
    {
        var winWidth = (window.innerWidth?window.innerWidth:document.documentElement.clientWidth);
        if ( !winWidth )
        {
            winWidth = document.clientWidth;
        }
        if ( !winWidth )
        {
            winWidth = 800;
        }
        return winWidth;
    }   

	//Got data back!
	function RequestURLResponse()
	{
		if (xmlhttp.readyState==4)		//Done
		{
			if (xmlhttp.status==200)	//Success!
			{
				HandleEvent( EventType.URLProcessing );
				if ( requestOutBlock )
				{
					var xmlBlock = xmlhttp.responseText;
					requestOutBlock.innerHTML = xmlBlock;
				
									
					//check for error values:
					if ( requestOutBlock.hasChildNodes() )
					{
							var errorBlock = requestOutBlock.firstChild;
					        if ( errorBlock.getAttribute && errorBlock.getAttribute( 'err' ) )
					        {
					                HandleError( errorBlock.getAttribute('errDesc') );
					        }
					}
					//***

					requestOutBlock = null;
					var callback = requestCallback;
					requestCallback = null;

					if ( callback )
					{
						callback();
					}
					HandleEvent( EventType.Completed );
					ProcessNextPendingRequest();
				}
				else
				{
					HandleError( "Received data not set to be inserted anywhere!" );
					ProcessNextPendingRequest();
				}
			}
			else
			{
				//HandleError("Could not get URL! (Error "+xmlhttp.status+")");
				ProcessNextPendingRequest();
			}
		}
	}

	//Escapes us so we don't get confused by the separators, etc:
	function SmartEscape( _input )
	{
		//Removed smartness
		return encodeURIComponent( _input );
	}

	//Remove html from a string
	function RemoveHTML( _str )
	{
		if ( isIE )
		{
			//Strip any breaks to new lines, and get rid of all other tags
			var outStr = _str.replace(/<BR>/g,'\n').replace( /<[^>]*>/g, '' );	//Strip all tags. Can trick...
			return outStr;
		}

		var div = document.createElement( 'div' );
		div.innerHTML = _str;
		if ( div.textContent )
		{
			return div.textContent;
		}
		else if ( div.innerText )
		{
			return div.innerText;
		}
		else
		{
			return '';	//Unsupported browser.
		}
	}

	//File upload stuff:
	FU = 
	{
		index : 1,

		makeFrame : function(c) 
		{
			var div = document.createElement('DIV');
			var name = 'uploadFrame_' + (FU.index++);
			div.innerHTML = '<iframe style="display:none" src="about:blank" id="'+name+'" name="'+name+'" onload="FU.loaded(\''+name+'\')"></iframe>';
			document.body.appendChild(div);

			var frame = GetElem( name );
			if (c && typeof(c.onComplete) == 'function') 
			{
				frame.onComplete = c.onComplete;
			}
			return name;
		},

		form : function(f, name) 
		{
			f.setAttribute('target', name);
		},

		submit : function(f, c)
		{
			FU.form(f, FU.makeFrame(c));
			if (c && typeof(c.onStart) == 'function') 
			{
				return c.onStart();
			}
			else 
			{
				return true;
			}
		},

		loaded : function(id) 
		{
			var i = document.getElementById(id);
			if (i.contentDocument)
			{
				var d = i.contentDocument;
			}
			else if (i.contentWindow)
			{
				var d = i.contentWindow.document;
			}
			else
			{
				var d = window.frames[id].document;
			}
			if (d.location.href == "about:blank") 
			{
				return;
			}

			if (typeof(i.onComplete) == 'function')
			{
				i.onComplete(d.body.innerHTML);
			}
		}
	};

	/*
	function NoteReferrer()
	{
		//How did we get here?
		try {
			if ( document.referrer )
			{
				var referUrl = document.referrer;
				var match = referUrl.match( /:\/\/([^\/\\ ]*)/ );
				if ( match[1] )
				{
					var referRoot = match[1];
					var docRoot = location.href.match( /:\/\/([^\/\\ ]*)/ )[1];

					if ( docRoot != referRoot )
					{
						RequestURL( "noteReferrer.php?url="+encodeURIComponent(referRoot), null, "receiveBlock", function() {} );
					}
				}
			}
		}
		catch (_e)
		{ //Carry on if permission denied
		}
	}
	loadHandlers.push( NoteReferrer );
	*/

	//Generic cookie code
	function writeCookie(name,value,days) 
	{
		var expires = '';
		if (days) 
		{
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			expires = "; expires="+date.toGMTString();
		}
		document.cookie = name+"="+value+expires+"; path=/";
	}
	
	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 eraseCookie(name) 
	{
		writeCookie(name,"",-1);
	}

	function GetDefaultBtn()
	{
		return GetElem('defaultBtn');
	}

	//Shopping stuff:
	function CartAddToCart( _idx )
	{
		var idx = parseInt( _idx );
		if ( idx )
		{
			//Very simple cart addition
			var items = [];
			var added = false;
			var cart = readCookie( 'sxbCart' );

			if ( cart )
			{
				items = cart.split(':');
				var i;
				for (i=0;i+1<items.length;i+=2)
				{
					if ( parseInt(items[i]) == idx )
					{
						if ( items[i+1]<100 ) //Limit to prevent overflow!
						{
							items[i+1]++;
						}
						added = true;
						break;
					}
				}
			}
			if ( !added )
			{
				//Append to the end of the list:
				items.push(idx);
				items.push(1);
				added = true;
			}

			writeCookie( 'sxbCart', items.join(':'), 1 );
			CartUpdateBasketTotals();
		}
	}
	function CartRemoveFromCart( _idx )
	{
		var idx = parseInt( _idx );
		if ( idx )
		{
			//Very simple cart removal
			var items = [];
			var cart = readCookie( 'sxbCart' );

			if ( cart )
			{
				items = cart.split(':');
				var i;
				for (i=0;i+1<items.length;i+=2)
				{
					if ( parseInt(items[i]) == idx )
					{
						if ( items[i+1] > 1 ) 
						{
							items[i+1]--;
						}
						else
						{
							if ( confirm( 'Really remove this item from your basket?' ) )
							{
								items.splice( i, 2 );
							}
						}
						break;
					}
				}
			}
			writeCookie( 'sxbCart', items.join(':'), 1 );
		}
		CartUpdateBasketTotals();
	}
	function CartBuyNow( _idx )
	{
		//TODO: Immediately buy item
		//For now, drop into basket
		CartAddToCard( _idx );
	}
	function CartUpdateBasketTotals()
	{
		//HACK: Update if we're in a suitable state. TOO MUCH SXB STUFF HERE
		if ( g_pageIdx == 'Basket' && typeof(sxb_immediateRefresh) != 'undefined' )
		{
			var dc = GetElem('deliveryChoice');
			if ( dc )
			{
				writeCookie( 'sxbDeliveryOption', dc.value, 1 );
			}
			var pc = GetElem( 'promoCode' );
			if ( pc && pc.value != '' )
			{
				writeCookie( 'sxbPromo', pc.value, 1 );
				alert( 'Promotion has been applied to the basket.' );
			}

			sxb_immediateRefresh();
		}

		//Update the interface when we change the contents of our basket:
		RequestURL( 'cartItems.php?f=sumBasket', null, 'receiveBlock', CartDoUpdateBasketTotals );
	}
	function CartDoUpdateBasketTotals()
	{
		var bs = GetElem( 'basketSummary' );
		if ( bs )
		{
			var result = GetElem( 'receiveBlock' ).innerHTML.split(':');
			if ( result.length == 2 )
			{
				bs.innerHTML = result[0]+" items = "+PrettyPrintPrice(result[1]);
			}
		}
	}
	//Put all values into form and submit.
	function CartDoCheckout()
	{
		GetElem('cartSubmitForm').submit();
	}
	
	function PayInvoice()
	{
		var name = GetElem('invoiceNumber').value;
		if ( name == '' )
		{
			alert('Please enter an invoice number!');
			return false;
		}
		var amountPence = parseInt( parseFloat(GetElem('invoiceAmount').value)*100 );
		var amount = PrettyPrintPrice( amountPence ).substr(7);
		if ( amountPence <= 0 )
		{
			alert('Please enter the invoice amount!');
			return false;
		}

		if ( confirm( "Proceed to PayPal to pay securely for 'Invoice #"+name+"' of value £"+amount+"?" ) )
		{
			GetElem('invoiceFrm_invoiceNumber').value = 'Invoice #'+name;
			GetElem('invoiceFrm_invoiceAmount').value = amount;
			GetElem('invoiceSubmitForm').submit();
			return true;
		}
		return false;
	}

	//Print as quid:
	function PrettyPrintPrice(_price)
	{
		var priceStr = ''+_price;
		while ( priceStr.length < 3 ) { priceStr = '0' + priceStr; } 
		priceStr = '&pound;'+ priceStr.substr(0,priceStr.length - 2) + '.' + priceStr.substr(priceStr.length-2);
		return priceStr;
	}

	//Prevent enter key from submitting forms (it gets confusing with open windows):
	function RedirectEnterKey(_evt) 
	{
  		var evt = ReconcileEvent(_evt);
		if ( evt.target )
		{
  			if ( (evt.keyCode == 13) && (evt.target.type=="text" || evt.target.type=="password") )
			{
				if ( !GetTopDialog() ) //Discard all enter presses if in a dialog
				{
					if ( GetDefaultBtn() )
					{
						GetDefaultBtn().onclick();
					}
				}

				return false;
			}
		}
		return true;
	}
	document.onkeypress = RedirectEnterKey;

	//loadHandlers.push( CartUpdateBasketTotals );
