/************************************************************************
 * ilikeAjax 0.9  (2006/12/24)
 * Copyright (c) 2006 Richard Flachs ( http://www.ilikethis.cz )
 * See http://ilikeajax.ilikethis.cz
 ************************************************************************/
 


/******************************************************************************
 * Tato metoda posle dotaz na server.
 * Neceka na odpoved - odpoved bude zaslana jine metode objektu 
 */
function ilikeAjaxRun()
{
// 1. vytvoreni HTTP objektu pro komunikaci - ruzne v ruznych prohlizecich
	this.XmlHttp = null;
	if ( window.XMLHttpRequest )
	{
		this.XmlHttp = new XMLHttpRequest;
	}
	else
	if ( window.ActiveXObject )
	{
		this.XmlHttp = new ActiveXObject( "Microsoft.XMLHTTP" );
	}
	else
	{
		return false;
	}
	if ( this.XmlHttp == null )
	{
		return false;
	}
	// 2. priprava dotazu - doplneni parametru
	var parString = "";
	if ( this.parameters.length > 0 )
	{
		for( var i = 0; i < this.parameters.length; i++ )
		{
			// parametr, ktery je zasilan hodnotou
			if ( this.parameters[ i ][ 2 ] == 0 )
			{
				if ( parString.length > 0 )
				{
					parString += "&";
				}
				parString += this.parameters[ i ][ 0 ] + "=";
				if ( typeof( this.parameters[ i ][ 1 ] ) == "function" )
				{
					parString += encodeURIComponent( this.parameters[ i ][ 1 ]() );
				}
				else
				{
					parString += encodeURIComponent( this.parameters[ i ][ 1 ] );
				}
			}
			else
			// parametr, ktery je zasilan odkazem (obsahuje id elementu, ve kterem je skutecna hodnota)
			if ( this.parameters[ i ][ 2 ] == 1 )
			{			
				if ( document.getElementById( this.parameters[ i ][ 1 ] ) != null )
				{
					if ( document.getElementById( this.parameters[ i ][ 1 ] ).value != null )
					{
						if ( parString.length > 0 )
						{
							parString += "&";
						}
						parString += this.parameters[ i ][ 0 ] + "=";
						parString += encodeURIComponent( document.getElementById( this.parameters[ i ][ 1 ] ).value );
					}
				}
				else
				if ( document.getElementsByName( this.parameters[ i ][ 1 ] ).length > 0 )
				{
					if ( document.getElementsByName( this.parameters[ i ][ 1 ] )[0].value != null )
					{
						if ( parString.length > 0 )
						{
							parString += "&";
						}
						parString += this.parameters[ i ][ 0 ] + "=";
						parString += encodeURIComponent( document.getElementsByName( this.parameters[ i ][ 1 ] )[0].value );
					}
				}
			}
			else
			// parametr, ktery je zasilan jako odkaz na formular (zpracuji se vsechny vstupy)
			if ( this.parameters[ i ][ 2 ] == 2 )
			{		
				if ( document.getElementById( this.parameters[ i ][ 0 ] ) != null )
				{
					var tags = document.getElementById( this.parameters[ i ][ 0 ] ).getElementsByTagName( "INPUT" );
					// TODO: opera nebere vnorene inputy pokud je definovano DTD XHTML ???
					for ( var j = 0; j < tags.length; j++ )
					{
						if ( tags[j].name != null && tags[j].name != "" && tags[j].value != null )
						{
							if ( parString.length > 0 )
							{
								parString += "&";
							}
							parString += tags[j].name + "=";
							parString += encodeURIComponent( tags[j].value );
						}
						else
						if ( tags[j].id != null && tags[j].id != "" && tags[j].value != null )
						{
							if ( parString.length > 0 )
							{
								parString += "&";
							}
							parString += tags[j].id + "=";
							parString += encodeURIComponent( tags[j].value );
						}
					}
					tags = document.getElementById( this.parameters[ i ][ 0 ] ).getElementsByTagName( "SELECT" );
					for ( var j = 0; j < tags.length; j++ )
					{
						if ( tags[j].name != null && tags[j].name != "" && tags[j].value != null )
						{
							if ( parString.length > 0 )
							{
								parString += "&";
							}
							parString += tags[j].name + "=";
							parString += encodeURIComponent( tags[j].value );
						}
						else
						if ( tags[j].id != null && tags[j].id != "" && tags[j].value != null )
						{
							if ( parString.length > 0 )
							{
								parString += "&";
							}
							parString += tags[j].id + "=";
							parString += encodeURIComponent( tags[j].value );
						}
					}
					tags = document.getElementById( this.parameters[ i ][ 0 ] ).getElementsByTagName( "TEXTAREA" );
					for ( var j = 0; j < tags.length; j++ )
					{
						if ( tags[j].name != null && tags[j].name != "" && tags[j].value != null )
						{
							if ( parString.length > 0 )
							{
								parString += "&";
							}
							parString += tags[j].name + "=";
							parString += encodeURIComponent( tags[j].value );
						}
						else
						if ( tags[j].id != null && tags[j].id != "" && tags[j].value != null )
						{
							if ( parString.length > 0 )
							{
								parString += "&";
							}
							parString += tags[j].id + "=";
							parString += encodeURIComponent( tags[j].value );
						}
					}
				}
			}
		}
		// vsechny parametry, ktere jsou nastaveny jako docasne se odstrani
		// pokud je znovu nenastavime, pri pristim pozadavku se jiz nebudou posilat
		for( var i = this.parameters.length - 1; i >= 0; i-- )
		{
			if ( this.parameters[ i ][ 3 ] == true )
			{
				for( var j = i; j < this.parameters.length - 1; j++ )
				{
					this.parameters[ j ] = this.parameters[ j + 1 ];
				}
				this.parameters.pop();
			}
		}
	}
	// 3. pripraveni dotazu vybranou metodou
	if ( this.method.toUpperCase() == "GET" )
	{
		if ( this.url.indexOf( '?' ) > 0 )
		{
			this.XmlHttp.open( "GET", this.url + "&" + parString );
		}
		else
		{
			this.XmlHttp.open( "GET", this.url + "?" + parString );
		}
	}
	else
	{
		this.XmlHttp.open( "POST", this.url );
	}
	this.XmlHttp.onreadystatechange = new Function( "window." + this.name + ".ResponseHandler();" );
	this.XmlHttp.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded; charset=utf-8' );
	// TODO: iso-8859-2
	// TODO: headers, upload obrazku
	/* TODO: headers
	if (headers) {
        for (var key in headers) {
            xmlhttp.setRequestHeader(key, headers[key]);
    if (this.options.method == 'post') {
      requestHeaders.push('Content-type',
        'application/x-www-form-urlencoded');
    if (this.options.requestHeaders)
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
    for (var i = 0; i < requestHeaders.length; i += 2)
      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
        }
    }
    var body = this.options.postBody ? this.options.postBody : parameters;
    this.transport.send(this.options.method == 'post' ? body : null);
	*/
	// 4. vyvolani onStart
	if ( this.onStart != null )
	{
		this.onStart();
	}
	// nastaveni timeoutu
	this.isTimeOuted = false;
	if ( this.timeOutId != null )
	{
		clearTimeout( this.timeOutId );
		this.timeOutId = null;
	}
	if ( this.timeOut != null )
	{
		this.timeOutId = setTimeout( "window." + this.name + ".OnTimeOut()", this.timeOut );
	}
	
	// 5. odeslani dotazu
	if ( this.method.toUpperCase() == "GET" && navigator.appName == "Microsoft Internet Explorer" )
	{
		// v IE by se pri odeslani doplnil i POST
		this.XmlHttp.send();
	}
	else
	{
		this.XmlHttp.send( parString );
	}
	return true;
}


function ilikeAjaxOnTimeOut()
{
	// vyvolani onTimeOut
	if ( this.onTimeOut != null && this.XmlHttp.readyState != 4 )
	{
		this.onTimeOut();
	}
	this.timeOutId   = null;
	this.isTimeOuted = true;
}

/******************************************************************************
 * Tato metoda je vyvolana po ziskani odpovedi
 * Pokud je odpoved OK, zpracuje vracene XML
 */
function ilikeAjaxResponseHandler()
{
	//0	Uninitialized - open() has not been called yet.
	//1	Loading - send() has not been called yet.
	//2	Loaded - send() has been called, headers and status are available.
	//3	Interactive - Downloading, responseText holds the partial data. 
	//4	Completed - Finished with all operations.
	if ( this.XmlHttp.readyState == 4 && !this.isTimeOuted ) 
	{
		// switch off actual nesting level
		this.actualLevel = -100;
		if ( this.timeOutId != null )
		{
			clearTimeout( this.timeOutId );
			this.timeOutId = null;
		}

		// osetruje protokol file:// u IE
		if ( !this.XmlHttp.responseXML.documentElement && this.XmlHttp.responseStream ) 
		{
			this.XmlHttp.responseXML.load( this.XmlHttp.responseStream );
		}
		
		this.ExecuteResponse( this.XmlHttp.responseXML );
		// vyvolani onComplete
		if ( this.onComplete != null )
		{
			this.onComplete();
		}
		return true;
	}
	//alert( 'error, status ' + this.XmlHttp.readyState )
	// TODO : ostatni stavy???
}




/******************************************************************************
 * Zpracuje jeden node v odpovedi, vlozi hodnoty na prislusna mista v HTML kodu a projde podnody
 */
function ilikeAjaxExecuteResponse( xmlNode )
{
	if ( xmlNode == null )
	{
		return false;
	}
	// aktualni uroven vnoreni - pouziva se pro uzavreni tagu
	var level           = this.actualLevel;
	// aktualni mod zpracovani odpovedi - pouziva se pro uzavreni tagu
	var responseMode   = this.actualResponseMode;
	var responseAction = this.actualResponseAction;
	var responseParent = this.actualResponseParent;
	// prvni node, ktery se bude vkladat do kodu ma index 0
	if ( this.actualLevel < -1 )
	{
		// response je korenovy nod - nezpracovava se, jen se nastavi na -1
		if ( xmlNode.nodeType == 1 && xmlNode.hasChildNodes() ) //nodeName == 'response' )
		{
			this.actualLevel          = -1;
			this.actualResponseMode   = "xml";
			this.actualResponseParent = document.body;
		}
	}
	else
	{
		// pri kazdem dalsim volani se uroven vnoreni zvysi
		this.actualLevel++;
	}
	// node se bude vkladat, jen pokud se jedna o element a je uvnitr response nodu
	//alert(xmlNode.nodeType + " - " + xmlNode.nodeName + " - " + this.actualLevel + " - " +xmlNode.childNodes.length )
	if ( xmlNode.nodeType == 1 && this.actualLevel >= 0 )
	{
		// node name function je rezervovan pro pridani/nahrazeni javascriptove funkce
		if ( this.enabledSpecialTags && ( xmlNode.nodeName.toLowerCase() == "script" || xmlNode.nodeName.toLowerCase() == "html" ) )
		{
			this.actualResponseMode = xmlNode.nodeName.toLowerCase();
		}
		if( xmlNode.getAttribute( "responseMode" ) != null )
		{
			if ( xmlNode.getAttribute( "responseMode" ).toLowerCase() == "function" )
			{
				this.actualResponseMode = "function";
			}
			else
			if ( xmlNode.getAttribute( "responseMode" ).toLowerCase() == "script" )
			{
				this.actualResponseMode = "script";
			}
		}
		// na urovni nule je typ vracenych dat (HTML,XML...)
/*		if ( this.actualLevel == 0 )
		{
			if ( xmlNode.nodeName.toLowerCase() == "xml"  || xmlNode.nodeName.toLowerCase() == "function" )
				this.actualResponseMode = xmlNode.nodeName;
			// jedna se o JAVASCRIPT kod
			if ( this.actualResponseMode == "event" )
			{
				for( var ij = 0; ij < xmlNode.childNodes.length; ij++ )
				{
					if ( xmlNode.childNodes[ij].nodeType == 4 )
					{
						var newFunction = new Function( xmlNode.childNodes[ij].data );
						newFunction();
					}
				}
			}
		}*/


		// v modu "pridani funkce" se vytvori nova javascriptova funkce
		if ( this.actualResponseMode == "function" )
		{
			//if ( xmlNode.getAttribute( "name" ) != null )
			{
				for( var ij = 0; ij < xmlNode.childNodes.length; ij++ )
				{
					// pro telo funkce se pouzije prvni nalezena CDATA sekce
					if ( xmlNode.childNodes[ij].nodeType == 4 )
					{
						if ( xmlNode.getAttribute( "parameters" ) != null )
						{
							var p = xmlNode.getAttribute( "parameters" ).split(",");
							for( i in p )
							{
								p[ i ] = "'" + p[ i ] + "'";
							}
							var newFunction = eval( "new Function( " + p.join("," ) + ", xmlNode.childNodes[ij].data ); " );
							eval( "window." + xmlNode.nodeName + " = newFunction" );
						}
						else
						{
							var newFunction = new Function( xmlNode.childNodes[ij].data );
							eval( "window." + xmlNode.nodeName + " = newFunction" );
						}
						break;
					}
				}
			}
		}
		else
		// v modu "javascript kod" se spusti obsah jako javascript
		if ( this.actualResponseMode == "script" )
		{
			for( var ij = 0; ij < xmlNode.childNodes.length; ij++ )
			{
				// pro telo funkce se pouzije prvni nalezena CDATA sekce
				if ( xmlNode.childNodes[ij].nodeType == 4 )
				{
					var newFunction = new Function( xmlNode.childNodes[ij].data );
					newFunction();
					break;
				}
			}
		}
		else
		// v modu vkladani HTML kodu se vklada obsah jako html
		if ( this.actualResponseMode == "html" && xmlNode.tagName != "html" )
		{
//alert( this.actualResponseParent.tagName + ' < ' + xmlNode.tagName  );
			var newNode = document.createElement( xmlNode.tagName );
//			for ( var i=0; i < xmlNode.attributes.length; i++ ) 
			{
				// pokud ma element prirazene id (prozatim nutne)
//				if ( xmlNode.attributes[i].name == "id" )
				{
//					if ( document.getElementById( xmlNode.attributes[i].value ) == null )
					{
//						newNode.setAttribute( "id", xmlNode.attributes[i].value );
//						document.body.appendChild( newNode );
					}
					// nastavime atributy
//					ilikeAjaxSetAttributes( document.getElementById( xmlNode.attributes[i].value ), xmlNode.attributes, 'p' );
					// nastavime novy obsah (innerHTML)
//					ilikeAjaxSetContent( document.getElementById( xmlNode.attributes[i].value ), xmlNode.childNodes, 'p' );
//r += " has id " + xmlNode.attributes[i].name + " = " + xmlNode.attributes[i].value;
				}
			}
//			alert( xmlNode.nodeName )
			
			if ( navigator.appName == "Microsoft Internet Explorer"
					&& this.actualResponseParent.nodeName.toUpperCase() == "TABLE" && xmlNode.nodeName.toUpperCase() == "TR" )
			{
				// v IE musi byt TR uvnitr TBODY, nelze je mit primo v TABLE
				var addedTbody = document.createElement( "TBODY" )
				this.actualResponseParent.appendChild( addedTbody );
			  this.actualResponseParent = addedTbody;
			}
			// attribut musi byt primo u tagu, jinak se zacnou prohazovat poradi td
			if ( xmlNode.getAttribute( "responseAction" ) != null
				&& xmlNode.getAttribute( "responseAction" ) == "insertBefore"
				&& this.actualResponseParent.hasChildNodes()
			)
			{
				var addedNode = this.actualResponseParent.insertBefore( newNode, this.actualResponseParent.firstChild );
			}
			else
			{
				var addedNode = this.actualResponseParent.appendChild( newNode );
			}
			// nastavime atributy v novem tagu
			ilikeAjaxSetAttributes( addedNode, xmlNode.attributes, 'p' );
			// nenastavujeme novy obsah zde, ale az pozdeji
			// nastavime noveho rodice pro dalsi pruchod
//alert( this.actualResponseParent.innerHTML );
			this.actualResponseParent = addedNode;
		}
		else
		// ve standardnim modu se mapuje jmeno nodu na nalezene id
		if ( this.actualResponseMode == "xml" )
		{
//alert( xmlNode.nodeName + " - "+ document.getElementById( xmlNode.name ) );
				// pouze pokud element existuje, jinak ne
				this.parents[ this.actualLevel ] = new Array( xmlNode.nodeName, 0, 0 );
				var nodeNameModified = "";
				var mmm = xmlNode.nodeName+": ";
				
				// projdeme vsechny rodice tagu a vytvorime plne jmeno, ktere se pouzije jako id
				// napr. z <person><name> se vytvori id = personName
				for( var z = 0; z <= this.actualLevel; z++ )
				{
					// vylouceni predefined xml tagu
					// array - for groups
					// value - for elements, that can contain concurrent elements
					// option - for select boxes
					if ( this.parents[z][0].toLowerCase() != "array" && this.parents[z][0].toLowerCase() != "value" && this.parents[z][0].toLowerCase() != "option" )
					{
						if ( nodeNameModified == "" )
						{
							nodeNameModified += this.parents[z][0];
						}
						else
						{
							nodeNameModified 
								+= this.parents[z][0].charAt(0).toUpperCase() 
								+ this.parents[z][0].substring(1);
						}
//						alert( nodeNameModified );
					}
					if ( z > 0 && this.parents[z-1][0].toLowerCase() == "array" )
					{
						if ( z == this.actualLevel )
						{
							var templateName   = "Template";
							var templateSuffix = "";
							if ( xmlNode.getAttribute( "template" ) != null )
							{
								templateSuffix = xmlNode.getAttribute( "template" );
							}
							// zkusime najit template
							// zkusime vytvorit item
							if ( document.getElementById( nodeNameModified + templateName + templateSuffix ) != null )
							{
								var templateNode = document.getElementById( nodeNameModified + templateName + templateSuffix );
								var newNode = templateNode.cloneNode( true );
								newNode.setAttribute( "id", newNode.id.replace( templateName + templateSuffix, this.parents[z-1][1] ) );
								this.ModifyIdInTree( newNode, templateName + templateSuffix, this.parents[z-1][1] );
								newNode.style.display="";
								if ( templateSuffix != "" )
								{
									if ( document.getElementById( nodeNameModified + templateName ) != null )
									{
										templateNode.parentNode.insertBefore( newNode, document.getElementById( nodeNameModified + templateName ) );
										this.parents[z-1][1]++;
									}
								}
								else
								{
									templateNode.parentNode.insertBefore( newNode, templateNode );
									this.parents[z-1][1]++;
								}
							}
							nodeNameModified = "";
							break;
						}
						nodeNameModified += (this.parents[z-1][1] - 1);
					}
					/*
					if ( xmlNode.getAttribute( "value" ) != null )//&& !xmlNode.hasChildNodes() )
					{
						//var oldSBox = selectBox; 
						var selectBox = document.getElementById( nodeNameModified );
						if ( selectBox != null && selectBox.nodeName.toUpperCase() == "SELECT" )
						{
							//alert( xmlNode.getAttribute( "value" ) )
							alert( 'someSELECTSET before = ' + xmlNode.getAttribute( "value" ) )
							document.getElementById( nodeNameModified ).setAttribute( "value", xmlNode.getAttribute( "value" ) );
//alert(xmlNode.getAttribute( "value" ))
							//document.getElementById( nodeNameModified ).value = xmlNode.getAttribute( "value" );
						}
						else
						{
							selectBox = null;
						}
					}
					*/
				}
				
				// aktualni tag je OPTION
				if ( xmlNode.nodeName.toUpperCase() == "OPTION" )
				{
					//alert( xmlNode.nodeType + ' - ' + xmlNode.nodeName + ' -  START' )
					// najdeme jeho select box
					//alert(nodeNameModified)
					var selectBox = document.getElementById( nodeNameModified );
					//alert(selectBox)
					// overime, ze se jedna o SELECT
					if ( selectBox != null && selectBox.nodeName.toUpperCase() == "SELECT"  )
					{
						// vytvorime OPTION tag
						var cop = document.createElement( "OPTION" );
						var copi = document.createTextNode( xmlNode.firstChild.data );
						cop.appendChild( copi );
						cop.setAttribute( "value", xmlNode.getAttribute( "value" ) );

						if ( this.parents[ this.actualLevel - 1 ][ 2 ] < 1 )
						{
							// u prvniho option v selectu, odstranime vsechny stare selecty
							//for( var ich = selectBox.childNodes.length - 1; ich >= 0; ich-- )
							{
								//selectBox.removeChild( selectBox.childNodes[ ich ] );
							}
							while( selectBox.childNodes.length > 0 )
							{
								while( selectBox.childNodes[ 0 ].childNodes.length > 0 )
							  {
								  selectBox.childNodes[ 0 ].removeChild( selectBox.childNodes[ 0 ].childNodes[ 0 ] );
								}
								selectBox.removeChild( selectBox.childNodes[ 0 ] );
							}
							this.parents[ this.actualLevel - 1 ][ 2 ] = 1;
							// pridani vytvoreneho OPTION tagu
							// IE specialita - IE nesnasi kopirovane selecty bez options - bez tohoto necha length pouze 1
							if ( navigator.appName == "Microsoft Internet Explorer" )
							{
								selectBox.length = 1;
								selectBox.replaceChild( cop, selectBox.childNodes[ 0 ] );
							}
							else
							{
						//	alert( selectBox.innerHTML )
								selectBox.appendChild( cop );
//								selectBox.length = 0;
							}
						}
						else
						{
							// tag se pouze prida
							selectBox.appendChild( cop );
						}
						
						var selectedValue = 0;
						if ( xmlNode.parentNode.getAttribute( "value" ) != null )
						{
							selectedValue = xmlNode.parentNode.getAttribute( "value" );
							//alert( selectedValue )
						}
						//Box.getAttribute( "value" )
//						alert(selectBox.getAttribute( "value" ))
						if ( this.parents[ this.actualLevel - 1 ][ 2 ] < 2 && cop.getAttribute("value") == selectedValue )
						{
							selectBox.lastChild.setAttribute( "selected", "selected" );
							this.parents[ this.actualLevel - 1 ][ 2 ] = 2;
//							alert( nodeNameModified + "\n" + document.getElementById( nodeNameModified ).value );
//alert(cop.getAttribute("value"))
//							if ( !document.all )
//							{
//								document.getElementById( nodeNameModified ).selectedValue = selectBox.getAttribute( "selectedValue" );
//							}
//							else
							{
								document.getElementById( nodeNameModified ).value = selectedValue;
//								document.getElementById( nodeNameModified ).selectedIndex = 2;
							//alert( selectBox.id + ' - ' + selectedValue + ' - '+ nodeNameModified )
							}
						}
/*yu = "";
for( z in selectBox )
yu+=", " + z;
selectedIndex, selectedOptions, selectionEnd, selectionStart
alert( 
//yu + 
selectBox.selectedIndex + ' .. '
+ selectBox.selectedOptions + ' ._. '
+ selectBox.selectionEnd + ' ._. '
+ selectBox.selectionStart + ' .. '
+ '... ' +selectBox.id + " - " + selectBox.childNodes.length + ".. " + selectBox.innerHTML );
*/
					}
				}
				else
				if ( xmlNode.nodeName.toLowerCase() == "array" )
				{
					// smazat stare items in array
					if ( xmlNode.getAttribute( "itemName" ) != null )
					{
						var delName = nodeNameModified
								+ xmlNode.getAttribute( "itemName" ).charAt(0).toUpperCase() 
								+ xmlNode.getAttribute( "itemName" ).substring(1);
						for( var y = 0; y<100;y++ )
						{
							if ( document.getElementById( delName + y ) == null )
								break;
							document.getElementById( delName + y ).parentNode.removeChild( document.getElementById( delName + y ) );
						}
						if ( document.getElementById( delName + "Template" ) != null )
						{
							// zkusime skryt i alternativni
							var next = document.getElementById( delName + "Template" );
							next.style.display = "none";
							for( var yy = 0; yy<30; yy++ )
							{
								next = next.nextSibling;
								if ( next == null )
								{
									break;
								}
								if ( next.nodeType == 1 )
								{
									if ( next.id == null || next.id.indexOf( delName + "Template" ) == -1 )
									{
										break;
									}
									next.style.display = "none";
								}
							}
						}
					}
				}
				else
				if ( document.getElementById( nodeNameModified ) != null )
				{
					// jedna se o value
/*					if ( xmlNode.nodeName == "value" && document.getElementById( nodeNameModified ).nodeName == "SELECT"  )
					{
						document.getElementById( nodeNameModified ).value = xmlNode.firstChild.data;
						for( var ich = 0; ich < document.getElementById( nodeNameModified ).childNodes.length; ich++ )
						{
							if ( document.getElementById( nodeNameModified ).childNodes[ ich ].getAttribute( "value" ) == xmlNode.firstChild.data )
							{
								document.getElementById( nodeNameModified ).childNodes[ ich ].setAttribute( "selected", "selected" );
								break;
							}
						}
//						alert(d);
					}
					else*/
					{
						// nastavime atributy
						ilikeAjaxSetAttributes( document.getElementById( nodeNameModified ), xmlNode.attributes, 'p' );
						
						// pokud mezi atributy najdeme atribut pro zmenu modu odpovedi, nastavime zmenu
						// je to jen v XML modu, uvnitr function, script, html se nelze prepnout do XML modu
						// napr. responseMode="HTML" prepne do html modu
//////////////////////////////////////////////////////
						if( xmlNode.getAttribute( "responseMode" ) != null )
						{
							this.actualResponseMode   = xmlNode.getAttribute( "responseMode" ).toLowerCase();
							if ( xmlNode.getAttribute( "responseAction" ) != null )
							{
								this.actualResponseAction = xmlNode.getAttribute( "responseAction" ).toLowerCase();
							} 
							this.actualResponseParent = document.getElementById( nodeNameModified );
							//this.actualResponseParent = document.getElementById( nodeNameModified );
						}
						// nastavime novy obsah (innerHTML)
						ilikeAjaxSetContent( document.getElementById( nodeNameModified )
							, xmlNode.childNodes
							, this.actualResponseMode + "-" + this.actualResponseAction 
						);
						
						if( xmlNode.getAttribute( "responseAction" ) != null )
						{
							if( xmlNode.getAttribute( "responseAction" ) == "clean" )
							{
								var nodeActual = document.getElementById( nodeNameModified );
								for( var ich = nodeActual.childNodes.length - 1; ich >= 0; ich-- )
								{
									nodeActual.removeChild( nodeActual.childNodes[ ich ] );
								}
/*							this.parents[ this.actualLevel - 1 ][ 2 ] = 1;
							// pridani vytvoreneho OPTION tagu
							// IE specialita - IE nesnasi kopirovane selecty bez options - bez tohoto necha length pouze 1
							if ( navigator.appName == "Microsoft Internet Explorer" )
							{
								selectBox.length = 1;
								selectBox.replaceChild( cop, selectBox.childNodes[ 0 ] );
							}
							else
							{
								selectBox.appendChild( cop );
							}
*/
							}
						}
						
					}
				}
		}
	}
	else
	// pro HTML mod zapiseme textovy obsah ihned
	// pro XML mod je nutne pouzit metodu setContent,
	//   ktera podle kontextu vlozi text do value, select, innerHTML atd...)
	if ( this.actualResponseMode == "html" && this.actualLevel >= 0 )
	{
		// pro CData sekci muzeme pouzit innerHTML
		// pokud pouzijeme innerHTML, &nbsp; <br>... se vlozi jako HTML
		// pokud pouzijeme node, &nbsp; <br>... se vlozi jako text
		/* TODO: pridat prepinac innerHTML x node(napr. setCDataParsing() )  
		 */
		if ( xmlNode.nodeType == 4 )
		{
//			var newNode = document.createText( xmlNode.innerHTML );
//			this.actualResponseParent.appendChild( newNode );
			this.actualResponseParent.innerHTML = xmlNode.data;
		}
		else
		// pro TEXT sekci je nutne pridavat textove sekce jako nody.
		// Pri pouziti innerHTML by white spaces pred konci tagu mazaly zpetne cely obsah 
		if ( xmlNode.nodeType == 3 )
		{
//			this.actualResponseParent.innerHTML = xmlNode.data;
			var newNode = document.createTextNode( xmlNode.data );
			this.actualResponseParent.appendChild( newNode );
		}
	}
//	r+="\n";


	// pro vsechny nody (vc. response ) se projdou podnody a zavola se tato funkce rekurzivne
//	this.actualResponseNode = xmlNode;
	var elements            = xmlNode.childNodes;
	for ( var i=0; i < elements.length; i++ ) 
	{
		this.ExecuteResponse( elements[i] );
	}
	// po dokonceni zpracovani nodu se aktualni uroven vnoreni a mod zpracovani odpovedi vrati na puvodni hodnotu
	this.actualLevel          = level;
/*	if ( this.actualResponseMode == "html" && responseMode == "xml" && this.actualResponseParent != document.body )
	{
		this.actualResponseParent.style.backgroundColor = "red";
//		this.actualResponseParent.style.display = '';
		//alert( this.actualResponseParent.id );
	}*/
	this.actualResponseMode   = responseMode;
	this.actualResponseParent = responseParent;

//		r += elements[i].nodeType + " - " + elements[i].nodeName + ", ";//.getAttribute('id')).innerHTML = odpovedi[i].firstChild.data;
//	r += ;
//	alert(r);
//        document.getElementById('stav-anketa').innerHTML = 'Uloženo';*/
}


function ilikeAjaxModifyIdInTree( node, template, number )
{
	for ( var y = 0; y < node.childNodes.length; y++ )
	{
		if ( node.childNodes[y].nodeType == 1 )
		{
			if ( node.childNodes[y].id != null && node.childNodes[y].id != "" )
			{
				if ( document.getElementById( node.childNodes[y].id ) != null 
					&& document.getElementById( node.childNodes[y].id ).onclick != null )
				{
					node.childNodes[y].onclick = document.getElementById( node.childNodes[y].id ).onclick;
				}
				node.childNodes[y].setAttribute( "id", node.childNodes[y].id.replace( template, number ) );
				if ( node.childNodes[y].name != null )
				{
					node.childNodes[y].setAttribute( "name", node.childNodes[y].name.replace( template, number ) );
				}
			}
			this.ModifyIdInTree( node.childNodes[y], template, number );
		}
	}
}


/**
 * Zmeni (nebo prida) atributy k elementu
 * TODO: implementovat mode (napr. remove, add, join, replace...)
 **/
function ilikeAjaxSetAttributes( element, attributes, mode )
{
//m = 'Attributes of element ' + element.tagName + ' (' +element.id + ')';
//m += ":\n";
	for( var i = 0; i < attributes.length; i++ )
	{
		//alert(attributes[i].name)
//m += "NEW: " + newAttribute.nodeName+" = "+newAttribute.nodeValue+"\n";
		var newAttribute = attributes[i];
		var oldAttribute = element.getAttributeNode( newAttribute.name );
		// atribut id nemuze by zmenen
		if ( newAttribute.nodeName.toLowerCase() == "id" )
		{
			continue;
		}
		if ( newAttribute.nodeName.toLowerCase() == "value" )
		{
		  // nutne pro Firefox - ma problemy s nastavenim value in INPUTU
			element.value = newAttribute.value;
	    }
    	else
		// vyjimka pro styly - u IE je nelze nastavit primo pres atribut
		if ( newAttribute.nodeName.toLowerCase() == "style" )
		{
			//alert(newAttribute.nodeName + " " + newAttribute.nodeValue );
			var styleList = ilikeAjaxStyleToArray( newAttribute.nodeValue );
			// nastaveni stylu primo pres "."
			// TODO: check for ', "
			for ( var j = 0; j < styleList.length; j++ )
			{
//				alert( styleList[j][0] + " = " );
	//			alert( eval( "element.style." + styleList[j][0] ) );
        //alert(styleList[j][0] + " " + styleList[j][1] );
				eval( "element.style." + styleList[j][0].trim() + "='" + styleList[j][1].trim() + "';" );
			}
		}
		else
		if ( newAttribute.nodeName.indexOf( "on" ) == 0 )
		{
			// zkopirovani udalosti
			var newFunction = new Function( newAttribute.nodeValue );
			eval( "element." + newAttribute.nodeName + " = newFunction;" );
		}
		else
		{
			// ostatni atributy lze nastavit primo
			element.setAttribute( newAttribute.name, newAttribute.value );
		}
	}
//alert(m);
}



/*
 * Zmeni obsah elementu
 * TODO: implementovat mode (napr. remove, add, join, replace...)
 * TODO: co delat s nechtenymi prazdnymi texty
 */
function ilikeAjaxSetContent( element, nodes, mode )
{
	var content = "";
	var found   = false;
	// pokud se nic vkladat nebude, nebude se ani cistit
	if( nodes.length == 0 )
	{
		return;
	}
  for( var i = element.childNodes.length - 1; i >= 0; i-- )
	{
		// mazani puvodniho obsahu jen pokud
		// a. mod xml - vzdy
		// b. mod html - jen je-li nastaveno replace
		// c. jedna se o text - vycisten vzdy
		if ( mode == "xml" 
			|| mode == "html" 
			|| mode == "html-replace" 
			|| ( element.childNodes[i].nodeType == 4 || element.childNodes[i].nodeType == 3 ) 
		)
		{
			if ( element.tagName != "SELECT" )
			{
				// smazeme vsechny podnody (nebo jen textove?) - priklad B2
				element.removeChild( element.childNodes[i] );
			}
		}
	}

  var hasOptions = false;
  if ( element.tagName == "SELECT" )
  {
		for( var i = 0; i < nodes.length; i++ )
		{
			if ( nodes[i].tagName == "OPTION" )
			{
				hasOptions = true;
			}
		}
	}
	//alert('a')
	// projdeme vsechny vkladane nody
	for( var i = 0; i < nodes.length; i++ )
	{
			//alert(nodes[i].tagName)
		// pokud se jedna o CDATA sekci
		if ( nodes[i].nodeType == 4 )
		{
			content = nodes[i].data;
			if ( element.tagName == "INPUT" || element.tagName == "TEXTAREA" )
			{
				element.value = content;
			}
			else
			if ( element.tagName == "SELECT" )
			{
				if ( !hasOptions )
				{
					element.value = content;
				}
			}
			else
			{
				// nastavi se obsah pomoci innerHTML - bezpecnejsi, nebude obsahovat zadne childNodes
				element.innerHTML = content;
				//content;
				//element.innerText = 'bbb'
			}
			break;
		}
		else
		// pokud se jedna o TEXT sekci
		if ( nodes[i].nodeType == 3 )
		{
			content = nodes[i].data;
			if ( element.tagName == "INPUT" || element.tagName == "TEXTAREA" )
			{
				element.value = content;
			}
			else
			if ( element.tagName == "SELECT" )
			{
				if ( !hasOptions )
				{
					element.value = content;
				}
			}
			else
			{
				var newTextNode = document.createTextNode( content );
				element.appendChild( newTextNode );
			}
		}
	}
//	element.normalize();
	/*if ( found )
	{
		if ( element.tagName == "INPUT" || element.tagName == "TEXTAREA" )
		{
			element.value = content;
		}
		else
		{
//		alert( element.tagName + " .. " + element.innerHTML + " .. " + content );
			element.innerHTML = content;
		}
	}*/
//alert(m);
}



/*
 * Prevede retezec obsahujici styly na pole obsahujici jednotlive styly v camel forme
 * IE neumi nastavovat styly primo zmenou atributu
 * TODO: implementovat mode (napr. remove, add, join, replace...)
 */
function ilikeAjaxStyleToArray( s )
{
	var listOfStyles = s.split( ';' );
	var r = new Array();
//var rr="parsin " + s + "\n";
	var styleItem = 0;
	for ( styleItem = 0; styleItem < listOfStyles.length; styleItem++ )
	{
		var styleSeparatorPosition = listOfStyles[ styleItem ].indexOf( ":" );
		var styleItemName = '';
		var styleItemValue = '';
		// if style item contains ":"
		if ( styleSeparatorPosition > 0 )
		{
			// set 2nd part (behind :) as style value
			styleItemValue = listOfStyles[ styleItem ].substring( styleSeparatorPosition + 1 );
			// set 1nd part (before :) as style name
			styleItemName = listOfStyles[ styleItem ].substring( 0, styleSeparatorPosition );
			// position of "-" inside name
			var n = styleItemName.split( '-' );
			// if style name contains "-", we need change style name to camel form
			if ( n.length > 1)
			{
				styleItemName = "";
				for ( c in n )
				{
					if ( styleItemName == "" )
					{
						styleItemName += n[c];
					}
					else
					{
						styleItemName += n[c].charAt(0).toUpperCase() + n[c].substring(1);
					}
				}
			}
		}
		if ( styleItemName != "" )
		{
			r[r.length] = new Array(styleItemName,styleItemValue);
		}
	}
//rr += 		styleItemName + ' = ' + styleItemValue + "\n";
	return r;
}





/*
 * Zaregistruje Ajax pro jednotlive events
 */
function ilikeAjaxRegister( pid, paction, psetting )
{
	// prevedeni id na pole
	if ( typeof( pid ) != "object" )
	{
		pid = new Array( pid );
	}
	// prevedeni akci na pole
	if ( typeof( paction ) != "object" )
	{
		paction = new Array( paction );
	}
	// prevedeni settings na pole
	if ( typeof( psetting ) != "object" )
	{
		psetting = new Array( psetting );
	}

	// registrace vsech elementu
	for( var j = 0; j < pid.length; j++ )
	{
		var element = document.getElementById( pid[ j ] );
		if ( element != null )
		{
			// registrace vsech akci k elementu
			for( var i = 0; i < paction.length; i++ )
			{
//				alert(pid[ j ]+"-"+paction[i]);
				// vyjimka pro onclick u elementu A - musi vracet false
				if ( paction[ i ] == "onclick" && element.nodeName.toUpperCase() == "A" )
				{
					document.getElementById( pid[ j ] ).onclick = new Function( "window." + this.name + ".Run(); return false;" );
				}
				else
				if ( paction[ i ] == "onsubmit" && element.nodeName.toUpperCase() == "FORM" )
				{
					document.getElementById( pid[ j ] ).onsubmit = new Function( "window." + this.name + ".Run(); return false;" );
				}
				else
				if ( paction[ i ] == "onclick" && element.nodeName.toUpperCase() == "INPUT" 
					&& element.getAttribute( 'type' ) != null 
					&& ( element.getAttribute( 'type' ) == 'button' || element.getAttribute( 'type' ) == 'submit' ) 
				)
				{
//					alert(element.getAttribute( 'type' ));
//					document.getElementById( pid[ j ] ).onmouseover = new Function( "alert(this.id);" );
					document.getElementById( pid[ j ] ).onclick = new Function( "window." + this.name + ".AddValue('event',(this.name==null||this.name==''?this.id:this.name),true);window." + this.name + ".Run();return false;" );
				}
				else
				if ( psetting[ i ] == "noMoveKeys"
					&& ( paction[ i ] == "onkeyup" || paction[ i ] == "onkeydown" || paction[ i ] == "onkeypress" )
					&& element.nodeName.toUpperCase() == "INPUT" )
				{
					// pokud se jedna o udalost odchytavajici stisknuti klavesy a nechceme odchytavat pohyb kursoru (sipka zpet, nahoru...)
					// zavolame ajax jen pri stisku nesipkovych klaves
					ilikeJavascriptAddEvent( document.getElementById( pid[ j ] ), paction[ i ]
						, "if ( !ilikeJavascriptCheckEventKeyCode( event, new Array( 9, 'range', 33, 40 ) ) ) "
						+ " { window." + this.name + ".AddValue('event',(this.name==null||this.name==''?this.id:this.name),true);window." + this.name + ".Run(); } " 
					);
//					eval( "document.getElementById( pid[ j ] )." + paction[ i ] + " = newFunction;" );
				}
				else
				{
					var newFunction = new Function( "window." + this.name + ".Run(); return true;" );
					eval( "document.getElementById( pid[ j ] )." + paction[ i ] + " = newFunction;" );
				}
			}
		}
	}
}





var ilikeAjaxUniqueNameIndex = 0;
function ilikeAjaxGetUniqueName()
{
	ilikeAjaxUniqueNameIndex++;
	return "ilikeAjaxUniqueNameIndex" + ilikeAjaxUniqueNameIndex;
}

function ilikeAjaxSetUrl( purl )
{
	this.url = purl;
}

function ilikeAjaxSetMethod( pmethod )
{
	this.method = pmethod;
}
function ilikeAjaxSetOnStart( ponStart )
{
	this.onStart = ponStart;
}
function ilikeAjaxSetOnComplete( ponComplete )
{
	this.onComplete = ponComplete;
}
function ilikeAjaxSetOnError( ponError )
{
	this.onError = ponError;
}
function ilikeAjaxSetTimeOut( ptimeOut, ponTimeOut )
{
	this.timeOut   = ptimeOut;
	this.onTimeOut = ponTimeOut;
}


function ilikeAjaxEnableSpecialTags( pbool )
{
	this.enabledSpecialTags = pbool;
}



function ilikeAjaxAddValue( pname, pvalue, ptemporary )
{
	if ( ptemporary == null )
	{
		ptemporary = false;
	}
	var isThere = false;
	for ( var i = 0; i < this.parameters.length; i++ )
	{
		if ( this.parameters[ i ][ 0 ] == pname && this.parameters[ i ][ 2 ] == 0 )
		{
			this.parameters[ i ][ 1 ] == pvalue;
			this.parameters[ i ][ 3 ] == ptemporary;
			isThere = true;
		}
	}
	if ( !isThere )
	{
		this.parameters.push( new Array( pname, pvalue, 0, ptemporary ) );
	}
}


function ilikeAjaxAddForm( pname, ptemporary )
{
	if ( ptemporary == null )
	{
		ptemporary = false;
	}
	var isThere = false;
	for ( var i = 0; i < this.parameters.length; i++ )
	{
		if ( this.parameters[ i ][ 0 ] == pname && this.parameters[ i ][ 2 ] == 2 )
		{
			this.parameters[ i ][ 3 ] == ptemporary;
			isThere = true;
		}
	}
	if ( !isThere )
	{
		this.parameters.push( new Array( pname, "", 2, ptemporary ) );
	}
	/*
	if ( document.getElementById( pname ) != null )
	{
		var tags = document.getElementById( pname ).getElementsByTagName( "INPUT" );
		for ( var i = 0; i < tags.length; i++ )
		{
			if ( tags[i].name != null && tags[i].name != "" && tags[i].value != null )
			{
				this.AddValue( tags[i].name,
					new Function( "return document.getElementById('" + pname + "').getElementsByTagName( 'INPUT' )[" + i + "].value;" )
				);
			}
		}
	}*/
}

function ilikeAjaxAddElement( pid, pname, ptemporary )
{
	if ( pname == null )
	{
		if ( document.getElementById( pid ) != null && document.getElementById( pid ).name != null && document.getElementById( pid ).name != "" )
		{
			pname = document.getElementById( pid ).name;
		}
		else
		{
			pname = pid;
		}
	}
	if ( ptemporary == null )
	{
		ptemporary = false;
	}
	var isThere = false;
	for ( var i = 0; i < this.parameters.length; i++ )
	{
		if ( this.parameters[ i ][ 0 ] == pname && this.parameters[ i ][ 2 ] == 1 )
		{
			this.parameters[ i ][ 1 ] == pid;
			this.parameters[ i ][ 3 ] == ptemporary;
			isThere = true;
		}
	}
	if ( !isThere )
	{
		this.parameters.push( new Array( pname, pid, 1, ptemporary ) );
	}
}


//function ilikeAjaxAddValue( pname )
{
//	pvalue;
//alert(pname);
//pname();

/*
	var isThere = false;
	for ( var i = 0; i < this.actions.lenght; i++ )
	{
		if ( this.actions[ i ] == paction )
		{
			isThere = true;
		}
	}
	if ( !isThere )
	{
		this.actions.push( paction );
		this.Register();
	}*/
}


function ilikeAjaxService( purl )
{
	// unikatni jmeno objektu v globalnim prostoru, pres ktere se pristupuje k objektu
	// napr. pri registrovani udalosti se priradi zavolani metody objektu s timto jmenem
	this.name                  = ilikeAjaxGetUniqueName();
	// adresa, na kterou se bude odesilat pozadavek a ze ktere prijde XML odpoved
	this.url                   = purl;
	// 
	this.parameters            = new Array();
	// nesting level of element in response DOM tree (index in parent tree)
	// root tag <response> ma uroven 0
	this.actualLevel           = -2;
	// zda posilat parametry jako POST nebo GET, defaultne POST u PHP a GET u XML
	this.method                = "POST";
	// metoda, ktera se zavola pred odeslanim pozadavku
	this.onStart               = null;
	this.onComplete            = null;
	this.onError               = null;
	
	this.onTimeOut             = null;
	this.timeOut               = null;
	this.isTimeOuted           = false;
	// id timeout funkce objektu
	this.timeOutId             = null;
		
	this.enabledSpecialTags    = false;
	// mod zpracovani odpovedi - jak a kam se vkladaji ziskana data (napr. function, xml, html...)
	// xml - slozena jmeno nodu odpovidaji id elementu v HTML
	// html - jmena nodu odpovidaji HTML tagum
	// script - 
	this.actualResponseMode    = "xml";
	this.actualResponseAction  = "replace";
	// pouziva se pro mod HTML - kam se bude vkladat html kod (defaultne na konec tela html)
	this.actualResponseParent  = document.body;
	//---------------- PRIVATE METHODS ------------------//
	this.ResponseHandler       = window.ilikeAjaxResponseHandler;
	this.ExecuteResponse       = window.ilikeAjaxExecuteResponse;
	this.ModifyIdInTree        = window.ilikeAjaxModifyIdInTree;
	this.OnTimeOut             = window.ilikeAjaxOnTimeOut;

	//---------------- CONSTRUCTOR ------------------//
	// list of parents of element in response DOM tree
	this.parents = new Array();
	// vytvoreni globalniho odkazu na tento objekt
	// napr. pri vytvoreni udalosti se prida zavolani metody objektu s timto jmenem
	eval( "window." + this.name + " = this" );
	// nastaveni default hodnoty na GET, pokud se jedna pouze o XML
	if ( this.url.indexOf( ".xml" ) > 0 )
	{
		this.method = "GET";
	}





	//---------------- PUBLIC METHODS ------------------//
	// Prida hodnotu do pozadavku
	this.AddValue              = window.ilikeAjaxAddValue;
	// Prida hodnotu elementu do pozadavku
	this.AddElement            = window.ilikeAjaxAddElement;
	// Prida hodnotu elementu formulare do pozadavku
	this.AddForm               = window.ilikeAjaxAddForm;
	// Odesle pozadavek
	this.Run                   = window.ilikeAjaxRun;
	// Nastavi zpusob odeslani dat
	this.SetMethod             = window.ilikeAjaxSetMethod;
	// Umozni pouziti tagu HTML, SCRIPT
	this.EnableSpecialTags     = window.ilikeAjaxEnableSpecialTags;
	// Zaregistruje udalost pri ktere se spusti pozadavek
	this.Register              = window.ilikeAjaxRegister;
	// Nastavi funkci, ktera se zavola pred vyslanim pozadavku
	this.SetOnStart            = window.ilikeAjaxSetOnStart;
	// Nastavi funkci, ktera se zavola po zpracovani odpovedi
	this.SetOnComplete         = window.ilikeAjaxSetOnComplete;
	// Nastavi funkci, ktera se zavola pokud neni odpoved v poradku
	this.SetOnError            = window.ilikeAjaxSetOnError;
	// Nastavi timeout a popr. funkci, ktera se zavola po timeoutu
	this.SetTimeOut            = window.ilikeAjaxSetTimeOut;
}

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,""); }
String.prototype.ltrim = function() { return this.replace(/^\s+/,""); }
String.prototype.rtrim = function() { return this.replace(/\s+$/,""); }




