var sAjax = function () {

	var getHrObj = function () {
		var HR = null;
		try {
			HR       = new window.XMLHttpRequest();
			getHrObj = function () { 
				return new window.XMLHttpRequest(); 
			};
		} catch (e) {
			var msxml = ['MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];
			for (var i = 0, j = msxml.length; i < j; i += 1) {
				try {
					HR       = new window.ActiveXObject(msxml[i]);
					getHrObj = function () { 
						return new window.ActiveXObject(msxml[i]); 
					};
					break;
				} catch (e1) { }
			}
		}
		return HR;
	};

	return function (uri, qs, fn, opts) {
		opts         = opts || {};
		opts.method  = (opts.method && /post/i.test(opts.method)) ? 'POST' : 'GET';
		opts.async   = typeof opts.async !== 'boolean' ? true : opts.async;
		opts.mime    = typeof opts.mime !== 'string' ? 'xml' : opts.mime;
		opts.timeout = typeof opts.timeout !== 'number' ? 40000 : opts.timeout;
		var t, HR = getHrObj();
		if (HR === null) {
			window.alert('Can not create server connection');
		} else {
			uri += '?timestamp=' + new Date().getTime();
			if (qs !== null && opts.method === 'GET') {
				uri += '&' + qs;
				qs   = null;
			}
			HR.onreadystatechange = function () {
				if (HR.readyState === 4) {
					clearTimeout(t);
					if (typeof fn === 'function') { 
						fn(HR); 
					}
				}
			};
			HR.open(opts.method, uri, opts.async);
			HR.setRequestHeader('x-sajax-version', '0.9');
			if (opts.method === 'POST') {
				HR.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
				HR.setRequestHeader('Content-length', qs.length);
				HR.setRequestHeader('Connection', 'close');
			}
			if (HR.overrideMimeType) {
				HR.overrideMimeType('text/' + opts.mime);
			}	
		
			HR.send(qs);
			t = setTimeout( function () { HR.abort(); alert('the request timed out. Did you lose network connectivity for some reason?'); }, opts.timeout);
			return HR;
		}
	};
}();

