	var gc_ajaxManager = {
		ajaxRequesters: new Array (),	// a storage array of ajax requesters
		identifier: undefined,

		use_requester: function (identifier) {
			this.identifier = identifier;
		},

		// start an ajax request,  but store a reference to this new ajax request
		// instance so it can be replaced by a new one later if need be
		request: function (url, sendOptions) {

			if (sendOptions == undefined)
				sendOptions = new Object ();

			if (sendOptions.onSuccess == undefined) {
				if (typeof (this.identifier) == 'string')
					eval ('sendOptions.onSuccess = function (transport)'
					+ '{	gc_ajaxManager.process_ajax_response (transport, \'' + this.identifier + '\'); };');
				else
					eval ('sendOptions.onSuccess = function (transport)'
					+ '{	gc_ajaxManager.process_ajax_response (transport, ' + this.identifier + '); };');
					
			}

			// create the new request
			var newAjaxHandler = new Ajax.Request (url, sendOptions);

			// if the user has specified a name for this ajax handler then..
			if (this.identifier != undefined) {

				// cancel the original http request
				if (this.ajaxRequesters[this.identifier] != undefined)
					try { this.ajaxRequesters[this.identifier].transport.abort (); } catch (e) {};

				// store this new request
				this.ajaxRequesters[this.identifier] = newAjaxHandler;
			}

			// forget the current identifier so that other anonymous requests can be made straight away without stopping the above request
			this.identifier = undefined;

			return true;
		},


		// process an xml ajax response,  and carry out it's instructions
		process_ajax_response: function (transport, identifier) {

			// remove the ajax requester object so it can be garbage collected
			this.ajaxRequesters[identifier] = undefined;

/**
			var response = transport.responseText || "no response text";
			alert("Suceeess! \n\n" + response);	
/**/
			if (transport.responseText.length == 0)
				return true;

			var xmlDoc = transport.responseXML;
			// alert the developer of a problem with the xml
//alert (transport.responseText);
//alert (xmlDoc.childNodes[0].nodeName);
//alert (xmlDoc.childNodes.length + " " + (xmlDoc.childNodes[0].nodeName == 'parsererror'));


			if ((xmlDoc == null) || (xmlDoc.childNodes.length == 0) || (xmlDoc.childNodes[0].nodeName == 'parsererror')) {
//				document.writeln ('<strong>Warning: invalid xml ajax response:</strong><br />\n<a href="' + this.uri + '">' + this.uri + '</a><br />\n' + this.httpRequestObject.responseText);
//				document.writeln ('<strong>Warning: invalid xml ajax response:</strong><br />\n' + transport.responseText);
				alert ('Warning: invalid xml ajax response:\n' + transport.responseText);
				return false;
			}

			this.process_xml (xmlDoc);
			return true;
		},

		process_xml: function (xmlDoc) {

			// find the root node
			for (var count = 0; count < xmlDoc.childNodes.length; count++) {

				if (xmlDoc.childNodes[count].nodeName == 'root') {
					var rootNode = xmlDoc.childNodes[count];

					// loop through the nodes and carry out their instructions
					for (var count2 = 0; count2 < rootNode.childNodes.length; count2++) {
						var currentNode = rootNode.childNodes[count2];

						switch (currentNode.nodeName) {
							case 'updateElement' :
								if ($(currentNode.getAttribute ('domId')) != null) {
									if (currentNode.hasChildNodes ())
										$(currentNode.getAttribute ('domId')).update (currentNode.firstChild.data);
									else
										$(currentNode.getAttribute ('domId')).update ('');
								}
								break;
							case 'showElement' :
								if ($(currentNode.getAttribute ('domId')) != null)
									$(currentNode.getAttribute ('domId')).show ();
								break;
							case 'hideElement' :
								if ($(currentNode.getAttribute ('domId')) != null)
									$(currentNode.getAttribute ('domId')).hide ();
								break;
							case 'enableElement' :
								if ($(currentNode.getAttribute ('domId')) != null)
									$(currentNode.getAttribute ('domId')).disabled = false;
								break;
							case 'disableElement' :
								if ($(currentNode.getAttribute ('domId')) != null)
									$(currentNode.getAttribute ('domId')).disabled = true;
								break;
							case 'setCookie' :
								gc_cookie.set (currentNode.getAttribute ('name'), currentNode.firstChild.data, currentNode.getAttribute ('expireSeconds'), currentNode.getAttribute ('path'), currentNode.getAttribute ('domain'), currentNode.getAttribute ('secure'));
								break;
							case 'removeCookie' :
								gc_cookie.remove (currentNode.getAttribute ('name'), currentNode.getAttribute ('path'), currentNode.getAttribute ('domain'));
								break;
							case 'alert' :
								alert (currentNode.firstChild.data);
								break;
							case 'redirect' :
								document.location.href = currentNode.firstChild.data;
								break;
							case 'eval' :
								if (currentNode.firstChild.data != '')
									gc_eval_js_response (currentNode.firstChild.data);
								break;
							case 'reload' :
								window.location.reload ();
								break;
						}
					}
				}
			}
			return true;
		}
	}

	// eval the given javascript,
	// called from the above process_ajax_response when eval'ing some js from an ajax response
	// so that the code is not running in the scope of the ajaxManager object
	var gc_eval_js_response = function (code) {
		eval (code);
	}








	// cookie addition to prototype.  adapted from:
	// http://wiki.script.aculo.us/scriptaculous/show/Cookie
	// http://gorondowtl.sourceforge.net/wiki/Cookie
	var gc_cookie = {
		// set the value of a cookie
		set: function (name, value, expireSeconds, path, domain, secure) {

			var expires = '';
			if (expireSeconds != undefined) {
				var d = new Date ();
//				d.setTime (d.getTime () + (86400000 * parseFloat (daysToExpire)));
				d.setTime (d.getTime () + parseFloat (expireSeconds));
				expires = d.toGMTString ();
			}
//			return (document.cookie = escape (name) + '=' + escape (value || '') + expire + ((path) ? "; path=" + path : ""));
			return document.cookie =	escape (name) + '=' + escape (value || '')
								+ (expires ? "; expires=" + d.toGMTString () : "")
								+ (path ? "; path=" + path : "")
								+ (domain ? "; domain=" + domain : "")
								+ (secure ? "; secure" : "");
		},
		// fetch the value of a cookie
		get: function (name) {
			var cookie = document.cookie.match (new RegExp ('(^|;)\\s*' + escape (name) + '=([^;\\s]*)'));
			return (cookie ? unescape (cookie[2]) : null);
		},
		// remove a cookie
		remove: function (name, path, domain, secure) {
			var cookie = ((gc_cookie.get (name)) || (true));
			gc_cookie.set (name, '', -1, path, domain, secure);
			return cookie;
		},
		// find out if javascript is allowed to access cookies
		accept: function () {
			if (typeof navigator.cookieEnabled == 'boolean')
				return navigator.cookieEnabled;
			gc_cookie.set ('_test_cookie_abcdef_', '1');
			return (gc_cookie.remove ('_test_cookie_abcdef_') === '1');
		}
	}
