/*
AJAX transport class
Copyright by Assis Ltd. 2005
*/

function Transport(){
	// Registering in global scape with unique name
	do{
		this.name = 'transpObject' + Math.round(Math.random() * 10000000000);
	}while(window[this.name]);
	
	window[this.name] = this;
	
	// Initializing object
	this.xmlr = false;
	this.readyState = 0; // Reserved
	this.status = null; // Reserved
	this.statusText = null; // Reserved
	this.returnData = {};
	
	// Loading XMLHttpRequest object
	if (window.ActiveXObject && !this.XMLHttpRequest) {
    var xmlObjs = new Array('Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP');
    for (var i = 0; i < xmlObjs.length; i++) {
      try {
        this.xmlr = new ActiveXObject(xmlObjs[i]);
				break;
      } catch (e) {
				
      }
    }
	}else{
		// Loading in Other browsers
		if(window.XMLHttpRequest){
			this.xmlr = new XMLHttpRequest();
		}
	}
	
	if(!this.xmlr){ // Client doesn't support XMLHttpRequest
    return null;
	}
	
	/************************
	* Methods
	************************/
	
	// Requesting XML data by GET request
	this.get = function(url, path, name, pass){
		// Checking for event handlers
		var async = false;
		
		// Event function
		var event = 'var o = window.' + this.name + '; o.readyState = o.xmlr.readyState; if(o.readyState == 4){ o.status = o.xmlr.status; o.statusText = o.xmlr.statusText; }';
		
		// If onreadystatechange() method is set then we can use async mode
		if(this.onreadystatechange){
			event += 'o.onreadystatechange(o);';
			var async = true;
		}
		
		// If onload() method is set then we can use async mode
		if(this.onload){
			event += ' if(o.xmlr.readyState==4&&o.xmlr.status==200){o.onload(o);}; ';
			var async = true;
		}
		
		this.xmlr.onreadystatechange = new Function(event);
		
		this.xmlr.open('GET', url, async, name, pass);
		this.xmlr.send(null);
		
		if(async){
			return true;
		}else{
			return this.getResultArray(path);
		}
	}
	
	// Requesting XML data by POST request
	this.post = function(url, path, name, pass, data){
		
		// Event function
		var event = 'var o = window.' + this.name + ';o.readyState=o.xmlr.readyState; if(o.readyState == 4){ o.status=o.xmlr.status; o.statusText=o.xmlr.statusText; }';
		var async = false;

		// If onreadystatechange() method is set then we can use async mode
		if(this.onreadystatechange){
			event += 'o.onreadystatechange(o);';
			var async = true;
		}
		
		// If onload() method is set then we can use async mode
		if(this.onload){
			event += ' if(o.xmlr.readyState==4&&o.xmlr.status==200){o.onload(o);}; ';
			var async = true;
		}
		
		// Opening connection
		this.xmlr.open('POST', url, async, name, pass);
		
		this.xmlr.onreadystatechange = new Function(event);
		
		// Setting headers
		this.xmlr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
		//this.xmlr.setRequestHeader('Connection','close'); // Removed until we make deeper investigation, because it causes problems in IE
		
		// Preparing data to post
		var postdata = '';
		for(i in data){
			postdata += i + '='+encodeURIComponent(data[i])+'&';
		}
		
		this.xmlr.send(postdata);
		
		if(async){
			return true;
		}else{
			return this.getResultArray(path);
		}
	}
	
	// returns prepared array from result, if no result yet returns NULL
	this.getResultArray = function( path ){
		if(!this.xmlr.responseXML || !this.xmlr.responseXML.documentElement){
			return this.xmlr.responseText;
		}
		
		var document = this.xmlr.responseXML.documentElement;
		
		// Normalize XML code for mozilla and opera
		if(!window.ActiveXObject){
			this.cleanWhitespace(document);
		}
		
		if(!document){
			return this.xmlr.responseText;
		}
		
		// Checking if path is provided
		if(typeof path == 'undefined' || !path){
			return this._iterateXML(document);
		}else{
			
			// the following two lines are needed for IE
			if( window.ActiveXObject ){
				this.xmlr.responseXML.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
				this.xmlr.responseXML.setProperty("SelectionLanguage", "XPath");
			}
			
			var elements = this.selectNodes(this.xmlr.responseXML, path);
			
			var out = new Array();
	    for(var i = 0; i < elements.length; i++){
	    	out[i] = this._iterateXML(elements[i]);
			}
			

			return out;
		}
	}
	
	// iterates node childs
	this._iterateXML = function(node){
		var out = {};
		var elCount = {};
		
		// Checking if element's last child is text, then we suppose whole element is text
		if(node.lastChild && (node.lastChild.nodeType == 3 || node.lastChild.nodeType == 4)){
			return node.lastChild.nodeValue;
		}
		
		for(var i = 0; i < node.childNodes.length; i++){
			var nName = node.childNodes[i].nodeName;
			
			if(elCount[nName]){ // If there is more than one node with same name, 
				// we must create an array
				if(elCount[nName] == 1){ // We have to replace element with array of elements
					out[nName] = new Array(out[nName]);
				}
				
				if(node.childNodes[i].childNodes.length){ // if Node has Childs get them
					out[nName][out[nName].length] = this._iterateXML(node.childNodes[i]);
				}else{ // Else get node value
					out[nName][out[nName].length] = node.childNodes[i].nodeValue;
				}
				
				elCount[nName]++;
			}else{
				if(node.childNodes[i].childNodes.length){ // if Node has Childs get them
					out[nName] = this._iterateXML(node.childNodes[i]);
				}else{
					out[nName] = node.childNodes[i].nodeValue;
				}
				
				elCount[nName] = 1;
			}
		}
		
		return out;
	}
	
	this.cleanWhitespace = function(node){
		var notWhitespace = /\S/;
		
		for (var x = 0; x < node.childNodes.length; x++) {
			var childNode = node.childNodes[x];
			if ((childNode.nodeType == 3) && (!notWhitespace.test(childNode.nodeValue))) {
				// that is, if it's a whitespace text node
				node.removeChild(node.childNodes[x]);
				x--;
			}
			
			if (childNode.nodeType == 1) {
				// elements can have text child nodes of their own
				this.cleanWhitespace(childNode);
			}
		}
	}
	
	this.selectNodes = function(document, xpath){
		if ( window.ActiveXObject ){
			return document.selectNodes( xpath ) ;
		}else{ // Alternative way
			var aNodeArray = new Array();
			
			var xPathResult = document.evaluate( xpath, document, 
			document.createNSResolver(document.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null) ;
			
			if ( xPathResult ) {
				var oNode = xPathResult.iterateNext() ;
				while( oNode )		{
					aNodeArray[aNodeArray.length] = oNode ;
					oNode = xPathResult.iterateNext();
				}
			}
			
			return aNodeArray;
		}
	}
	
	this.selectSingleNode = function( document, xpath ){
		if ( window.ActiveXObject )
			return document.selectSingleNode( xpath ) ;
		else{
			var xPathResult = document.evaluate( xpath, element, document.createNSResolver( document.documentElement), 9, null);
			
			if ( xPathResult && xPathResult.singleNodeValue ){
				return xPathResult.singleNodeValue ;
			}
			else{
				return null ;
			}
		}
	}
	
	
	this.debug = function(variable){
		var str = 'Type: ' + typeof(variable) + '\n';
		str += 'Value: '+ variable +'\n';
		
		if(typeof(variable) == 'object'){
			str += '\nProperties:\n';
			
			for(i in variable){
				str += i + ': ' + variable[i] + '\n';
			}
		}
		
		//alert(str);
		return str;
	}
}

if(typeof encodeURIComponent + '' != 'function'){
	window.encodeURIComponent = function(string){
		return escape(string).replace(/@/g, "%40").replace(/\//g, "%2F").replace(/\+/g, "%2B");
	}
}