// on server need:
// response.setContentType("text/xml");
// response.setHeader("Cache-Control", "no-cache");

// in the parent html set:
// var xml_validation_path = "xml-validation.xml";
// var xsl_validation_path = "xsl-validation.xml";

var ajaxConsole = "";

var createXMLHttp = null;
var xmlText = null;
var xmlHtml = null;
var xslTransform = null;

function canUseAjaxRequest()
{
  ajaxInit();
  return (createXMLHttp!=null);
}

function canUseAjaxXSL()
{
  ajaxInit();
  return (xslTransform!=null);
}

function ajaxInit()
{
  if( ajaxInit.init == true )
    return;
  ajaxInit.init = true;
  
  ajaxConsole += "start ajaxInit()\n";
  
  if(createXMLHttp==null)
  {
    try{
      ajaxConsole += "Try mozilla\n";
      createXMLHttp = createXMLHttp_MOZILLA;
      xmlText = xmlText_MOZILLA;
      xmlHtml = xmlHtml_MOZILLA;
      xslTransform = xslTransform_MOZILLA;
      if(validateXMLHttp())
        ajaxConsole += "Succeeded in Mozilla mode\n";
    }catch(e){
      createXMLHttp = null;
      xmlText = null;
      xmlHtml = null;
      xslTransform = null;
      ajaxConsole += "Exception: "+errorMsg(e)+"\n";
    }
  }
  if(createXMLHttp==null)
  {
    try{
      ajaxConsole += "Try IE\n";
      createXMLHttp = createXMLHttp_IE;
      xmlText = xmlText_IE;
      xmlHtml = xmlHtml_IE;
      xslTransform = xslTransform_IE;
      if(validateXMLHttp())
        ajaxConsole += "Succeeded in IE mode\n";
    }catch(e){
      createXMLHttp = null;
      xmlText = null;
      xmlHtml = null;
      xslTransform = null;
      ajaxConsole += "Exception: "+errorMsg(e)+"\n";
    }
  }
  ajaxConsole += "end ajaxInit()\n";
}

function errorMsg( e )
{
  var msg = "";
  if(e!=null)
  {
    try { msg = e.description; } catch(e) {}
    if( msg==null || msg=="" )
      try { msg = e.toString(); } catch(e) {}
    if( msg==null )
      msg = "";
  }
  return msg;
}

function validateXMLHttp() // mode = 1 IE, mode = 2 Mozilla
{
  ajaxConsole += "  Load "+xml_validation_path+"\n";
  var xmlDoc = syncLoadXML( xml_validation_path );
  var root = xmlDoc.documentElement;
  if( root.nodeName!="xml-validation" )
    throw "Expected xml-validation node";

  ajaxConsole += "  text from node\n";
  var text = xmlText(root);
  var checkText = "\x75\x6E\xA0\xE9\x74\xE9";
  if( text != checkText )
    throw "Text does not match '"+text+"' != '"+checkText+"'";
  
  ajaxConsole += "  html from node\n";
  var html = xmlHtml(root);
  var checkHtml = "<xml-validation>"+checkText+"<\/xml-validation>";
  if( html != checkHtml )
    throw "Html does not match '"+html+"' != '"+checkHtml+"'";
  
  ajaxConsole += "  test xsl\n";
  try
  {
    var html2 = xslTransform(root,xsl_validation_path);
    var checkHtml2 = "{xml-validation}"+checkText+"{\/xml-validation}";
    if( html2 != checkHtml2 )
      throw "Html does not match '"+html2+"' != '"+checkHtml2+"'";
    ajaxConsole += "  XSL Succeeded\n";
  }
  catch(e)
  {
    ajaxConsole += "  XSL Error: "+errorMsg(e)+"\n";
    xslTransform = null;
  }
  return true;
}

function showXMLStatus()
{
  ajaxInit();
  alert(ajaxConsole);
}

function createXMLHttp_MOZILLA()
{
  if( window.XMLHttpRequest )
    return new window.XMLHttpRequest();
  else
    throw "window.XMLHttpRequest is not available";
}
function createXMLHttp_IE()
{
  if( window.ActiveXObject )
  {
    try      { return new window.ActiveXObject("Msxml2.XMLHTTP"); }
    catch(e) { return new window.ActiveXObject("Microsoft.XMLHTTP"); }
  }
  else throw "Microsoft.XMLHTTP is not available";
}

function xmlText_MOZILLA( node )
{
  var res = "";
  if( node!=null )
  {
    if( node.nodeType==2 || node.nodeType==3 || node.nodeType==4 ) // attribute, text, cdata
    {
       if(node.nodeValue!=null)
         res += node.nodeValue;
    }
    else if( node.nodeType==1 || node.nodeType==9 || node.nodeType==11 ) // element, document, document fragment
    {
      var child = node.firstChild;
      while( child!=null )
      {
        res += xmlText_MOZILLA( child );
        child = child.nextSibling;
      }
    }
  }
  return res;
}

function xmlText_IE( node )
{
  if( node!=null )
    return node.text;
  else
    return "";
}

function xmlHtml_MOZILLA( node )
{
  if( node!=null )
  {
    if( xmlHtml_MOZILLA.serializer==null )
        xmlHtml_MOZILLA.serializer = new window.XMLSerializer();
    return xmlHtml_MOZILLA.serializer.serializeToString( node );
  }
  else return "";
}

function xmlHtml_IE( node )
{
  if( node!=null )
    return node.xml;
  else
    return "";
}

function xmlInnerHtml( node )
{
  if( node!=null )
  {
    var html = "", child = node.firstChild;
    while( child!=null )
    {
      html += xmlHtml(child);
      child=child.nextSibling;
    }
    return html;
  }
  else return "";
}

function xmlFromCache( url )
{
  if( url==null || url=="" )
    throw "Can not load an xml in cache with an empty url";
  var xmlDoc = null;
  if( xmlFromCache.cache==null )
      xmlFromCache.cache = new Array();
  else
    xmlDoc = xmlFromCache.cache[url];

  if( xmlDoc == null )
  {
    xmlDoc = syncLoadXML( url );
    xmlFromCache.cache[url] = xmlDoc;
  }
  return xmlDoc;
}

function extractXmlDoc( req )
{
  if( req.status < 200 || req.status>=300 )
    throw "Http error "+req.status+" "+req.statusText;
  return validateXmlDoc( req.responseXML );
}

function validateXmlDoc( xmlDoc )
{
  if( xmlDoc==null )
    throw "XML Document is null";
  if( xmlDoc.parseError!=null && xmlDoc.parseError.errorCode!=0 )
    throw "XML Parse Error ( Code: "+xmlDoc.parseError.errorCode+", Line: "+xmlDoc.parseError.line+"): "+xmlDoc.parseError.reason;
  var documentElement = xmlDoc.documentElement;
  if( documentElement==null )
    throw "XML Document, documentElement is null";
  if( documentElement.nodeType!=1 )
    throw "Bad documentElement nodeType";
  return xmlDoc;
}

function syncLoadXML( url )
{
  var req = createXMLHttp();
	req.open("GET", url, false);
  req.send(null);
  return extractXmlDoc(req);
}

function ajaxApply( o )
{
  var ajaxNode = o.responseXML.documentElement;
  if( ajaxNode.nodeName != "ajax-response" )
  {
    vdpShowError("Ajax Error: Unknown documentElement "+ajaxNode.nodeName);
    return;
  }
  var errors = null;
  var child = ajaxNode.firstChild;
  while( child!=null )
  {
    try
    {
      if( child.nodeType==1)
      {
        if( child.nodeName == "ajax-script" )
          ajaxApplyScript( child );
        else if( child.nodeName == "ajax-html" )
          ajaxApplyHtml( child );
        else if( child.nodeName == "ajax-xml" )
          ajaxApplyXml( child );
        else
          throw "Unknown ajax commande: "+child.nodeName;
      }
    }
    catch(e)
    {
      if( errors==null )
        errors = "Exception: "+errorMsg(e);
      else
        errors += "\nException: "+errorMsg(e);
    }
    child=child.nextSibling;
  }
  if( errors!=null )
	  vdpShowError(errors);
}

function ajaxApplyScript( node )
{
  var code = xmlText( node );
  if( code!=null && code!="" )
    safeEval(code);
}

function ajaxApplyHtml( node )
{
  var elem = ajaxDestElem( node );
  var html = xmlText( node );
  if( html==null )
      html = "";
   elem.innerHTML = removeAndEvalScript(html);
}

function ajaxApplyXml( node )
{
  var elem = ajaxDestElem( node );
  var html = "";
  var xsl = node.getAttribute("xsl");
  if( xsl!=null && xsl!="" )
    html = xslTransform( node, xsl );
  else
    html = xmlInnerHtml( node );
  if( html==null )
      html = "";
   elem.innerHTML = removeAndEvalScript(html);
}

function ajaxDestElem( node )
{
  if( node==null )
    return null;
  var id = node.getAttribute("id");
  if( id==null || id=="" )
    throw "Empty ajax destination id";
  if( id=="document.body" )
    return document.body;
  var elem = document.getElementById(id);
  if( elem==null )
    throw "Bad ajax destination id: "+id;
  return elem;
}

function showError( msg )
{
  alert("Error:\n"+msg);
}

function xslTransform_MOZILLA( node, xslUrl )
{
  if( window.XSLTProcessor )
  {
    var xsltProcessor = new window.XSLTProcessor();
    xsltProcessor.importStylesheet(xmlFromCache( xslUrl )); 
    if( xslTransform_MOZILLA.dom==null )
        xslTransform_MOZILLA.dom = document.implementation.createDocument("", "validation", null);
    return xmlHtml_MOZILLA(xsltProcessor.transformToFragment(node,xslTransform_MOZILLA.dom));
  }
  else throw "window.XSLTProcessor is not available";
}

function xslTransform_IE( node, xslUrl )
{
  return removeProcessingInstruction(node.transformNode(xmlFromCache(xslUrl)));
}

function removeProcessingInstruction( html )
{
  if( html!=null )
  {
    if(html.substring(0,2)=="<?")
    {
      var end = html.indexOf("?>");
      if( end!=-1)
      {
        end += 2;
        if(html.charAt(end)=="\r") end++;
        if(html.charAt(end)=="\n") end++;
        html = html.substring(end);
      }
    }
  }
  return html;
}

function formEscape( text )
{
  if( text>"" )
    text = escape(text).replace(/\+/g,"%2B");
  return text;
}

function removeAndEvalScript( data )
{
	if( data==null )
		data = "";
	var html = "";
	var reStart = /<script[^>]*>/i, reEnd = /<\/script\s*>/i;
	var ar1 = reStart.exec(data);
	var ar2 = reEnd.exec(data);
	while( ar1!=null && ar2!=null && ar1.index < ar2.index )
	{
	  html += data.substring(0,ar1.index);
	  safeEval(data.substring(ar1.index+ar1[0].length,ar2.index));
	  data = data.substring(ar2.index+ar2[0].length);
	  ar1 = reStart.exec(data);
	  ar2 = reEnd.exec(data);
	}
	html += data;
	return html;
}

function safeEval( code )
{
	try
	{
		eval( code );
	}
	catch(e) 
	{ 
		alert("Function call error:\n" + e.message + "\nCode:\n" + code);
	}
}
