function ajax(url, selectElement, onreadyFunction)
{	
	if (typeof selectElement == 'string')
	{
		selectElement = document.getElementById(selectElement);
	}
	
	if (selectElement != null && !selectElement.disabled)
	{
		try
		{
			if (typeof XMLHttpRequest == 'undefined')
			{
				XMLHttpRequest = function() { return new ActiveXObject('Microsoft.XMLHTTP') }; // Internet Explorer 5, 6
			}
			
			var xmlHttp = new XMLHttpRequest(); // Firefox, Opera 8.0+, Safari, Internet Explorer 7+
		}
		catch (e)
		{
			//alert('browser does not support standard XMLHttpRequest AJAX'); // debug
			return false;
		}
		
		xmlHttp.onreadystatechange = function()
		{
			if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
			{
				//alert(xmlHttp.responseText); // debug
				
				while (selectElement.firstChild)
				{
					selectElement.removeChild(selectElement.firstChild);
				}
				
				if (xmlHttp.responseText != '')
				{
					// the first replace() removes all quoted text, the second one removes all other valid characters
					var invalidChars = xmlHttp.responseText.replace(/"(\\.|[^"\\])*"/g, '').replace(/[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/g, '');
					
					if (invalidChars == '')
					{
						var json = eval('(' + xmlHttp.responseText + ')');
					}
					else
					{
						alert('invalid JSON characters: ' + invalidChars);
					}
					
					for (var i in json.optgroup)
					{
						var optGroup = document.createElement('optgroup');
						optGroup.label = '\u00a0';
						selectElement.appendChild(optGroup);
						
						var optGroup = document.createElement('optgroup');
						optGroup.label = json.optgroup[i].label;
						
						for (var j in json.optgroup[i].options)
						{
							var opt = document.createElement('option');
							opt.value = json.optgroup[i].options[j].value;
							opt.appendChild(document.createTextNode(json.optgroup[i].options[j].text));
							
							optGroup.appendChild(opt);
						}
						
						selectElement.appendChild(optGroup);
					}
					
					for (var i in json.options)
					{
						selectElement.options[i] = new Option(json.options[i].text, json.options[i].value);
					}
					
					if (selectElement.options.length == 1)
					{
						selectElement.selectedIndex = 0;
					}
				}
				
				if (onreadyFunction)
				{
					onreadyFunction();
				}
			}
		}
		
		url = url + '&dummy=' + new Date().getTime(); // avoid cache effect: http://weblogs.asp.net/pleloup/archive/2006/06/08/451583.aspx
		
		xmlHttp.open('GET', url, true);
		xmlHttp.send(null);
	}
}


