// ===============================================================
// CBkort version 2.x, copyright Carl Bro GIS&IT, 2006
// ===============================================================
// $Archive: /Products/CBKort2/development/2.3/standard_patch_03/wwwroot/js/standard/cbhttp.js $ 
// $Date: 14-02-08 15:28 $
// $Revision: 8 $ 
// $Author: Kpo $
// =============================================================== 


// **********************************************************
//  CBHTTP request
//
//  Denne javascript bruges til at kalde CBkort (CBInfo)
//  WEB services med en URL. Det forventede response 
//  fra den kaldte service er PCollections på XML format.
//  Den modtagne pcollection (i form af et DOM objekt), bliver
//  wrappet i javascript klasser som modsvarer java PCollections 
//
//  Niels Mørck, Carl Bro GIS & IT
//
//  Afhængigheder
//     ingen
//
//  Der er følgende klasser i denne fil.
//
//  --------------------------------------------------------------------
//  Klasse CBhttp  
//    Kald af CBinfo
//
//  Metoder 
//    executeUrl (url : string, showErrors : boolean) return PCollection  
//
//    url skal være en fuldstændig url inkl. parametre.
//    
//    Hvis showErrors er sand, vises en alertboks, hvis der modtages andet end
//    en pcollection fra serveren. Hvis den er falsk kastes en exception.   
//
//  --------------------------------------------------------------------  
//  Klasse PCollection 
//    Abstract superklasse for PComposite, RowList, Row og Column
//
//  Metoder 
//    getName      () return String     : returnerer indholdet af "name"   attributten
//    getId        () return String     : returnerer indholdet af "pcolid" attributten
//    isPComposite () return boolean    : sand hvis elementet er en <pcomposite> 
//    isRowList    () return boolean    : sand hvis elementet er en <rowlist> 
//    isRow        () return boolean    : sand hvis elementet er en <row> 
//    isColumn     () return boolean    : sand hvis elementet er en <column> 
//
//  --------------------------------------------------------------------  
//  Klasse PComposite
//    Repæsentation af et XML <pcomposite> element.
//  Metoder 
//    get  (index : integer)  return PCollection   : returnere subelementet ud fra et indeks
//    get  (name  : string)   return PCollection   : returnere subelementet ud fra et navn
//    size ()                 return integer       : antallet af subelementer
//
//  --------------------------------------------------------------------  
//  Klasse RowList
//    Repæsentation af et XML <rowlist> element.
//
//  Metoder 
//    row  (index : integer)  return Row        : returnerer subrækken udfra et index
//    size ()                 return integer    : antallet af rækker
//
//  --------------------------------------------------------------------  
//  Klasse Row
//    Repæsentation af XML <row> element.
//
//  Metoder 
//    column  (index : integer)  return Column     : returnerer kolonnen udfra et index
//    column  (name  : string)   return Column     : returnerer kolonnen udfra et navn
//    size ()                    return integer    : antallet af kolonner
//
//  --------------------------------------------------------------------  
//  Klasse Column
//    Repæsentation af XML <col> element.
//
//  Metoder 
//    getValue ()  return string   : returnerer kolonnens værdi
//
// 
//  --------------------------------------------------------------------  
//  Eksempel
//
//
//  try
//  {  
//     var cbHttp  = new CBhttp();
//
//     // -- Udfør request - der returneres altid en "envelope", som er en PComposite
//
//     var pcomp = cbHttp.executeUrl ("http://webkort:8080/cbkort?page=get-rowlist", false);
//
//     // -- Tag første - og i dette tilfælde det eneste - element ud af pcomp.
//     var rowList = pcomp.get(0);
//      
//     if (rowList == null || ! rowList.isRowList() )
//        {  alert ("Forkert response - rowlist forventet");
//        }
//     else
//        {  var str = "";
//
//           // Iterer gennem alle rows
//           for (var rowIx=0; rowIx<rowList.size(); rowIx++)
//           {  
//              // -- Tag næste row 
//              var row = rowList.row(rowIx);
//
//              str += "Row " + rowIx + ":\n"; 
//
//              // -- Iterer gennem alle columns 
//              for (var colIx=0; colIx<row.size(); colIx++)
//              {  
//                 // -- Tag næste colomn
//                 var column = row.column(colIx);
//
//                 // -- Udskriv column navn og værdi
//                 var name   = column.getName();
//                 var value  = column.getValue();
//
//                 str += " " + name + "=" + value + "\n";  
//              }
//           }  
//
//           alert (str);
//        }
//  }
//  catch (e)
//  {  if (e instanceof Error)
//     {  alert (e.message);
//     }
//     else
//     {  alert (e);
//     }
//  } 
//
// **********************************************************



// *************************************************
//  CBhttp
// *************************************************

function CBhttp () 
{
    this.responsePCollection = null;
    this.responseDOM = null;
    this.xmlHttp = cbhttp_createXMLHttpRequestObject ();
    this.errorText = null;
    this.method = "post";
}

CBhttp.prototype.setMethod = function (method)
{
    this.method = method;
}

CBhttp.prototype.executeUrl = function (url, showErrors)
{     
    this.responseDOM = null;
    this.errorText   = null;
    
    if (showErrors == null)
    {  showErrors = true;
    }

    if (this.method == "get")
    {  this.xmlHttp.open ("get", url, false);
       this.xmlHttp.send(null);
    }
    else
    {  var a = url.split("?");
       var data = null;
       url = a[0];
    
       if (a.length>1)
       {  
          data = a[1];
       }
       this.xmlHttp.open ("post", url, false);
       this.xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
       this.xmlHttp.send(data);
    } 
    

    if (this.xmlHttp.readyState == 4) 
    {
        if (ie)
        {  
           this.responseDOM = this.xmlHttp.responseXML;
           this.responseDOM.validateOnParse = false;
        }  
        else 
        {  
           var objDOMParser = new DOMParser();
           this.responseDOM = objDOMParser.parseFromString(this.xmlHttp.responseText, "text/xml");
        }
        
        if (this.responseDOM!=null)
        {   
          this.responsePCollection = cbhttp_docToPCollection(this.responseDOM);
        }

        if (this.responsePCollection==null)
        {  
           var s = cbhttp_getError (this.responseDOM);
           if (s!=null && s!="")
           {   this.errorText = s;
               if (showErrors)
                  alert ("Forkert response fra server.\nUrl: " + url + "\n" + this.xmlHttp.responseText);
               else
                  throw new Error (this.errorText);
           }
        }
        else
        {  return this.responsePCollection;
        }
    }
} 


CBhttp.prototype.executeUrlAsync = function (url, showErrors, responseHandler)
{  
	var xmlHttpObj = cbhttp_createXMLHttpRequestObject (); 
	var responseDOM = null;
	var errorText   = null;

	if (showErrors == null)
	{  
		showErrors = true;
	}

	xmlHttpObj.open ("get", url, true);

	xmlHttpObj.onreadystatechange=function() 
	{
		if (xmlHttpObj.readyState == 0)		{ /* uninitialized */ }
		else if (xmlHttpObj.readyState == 1)	{ /* loading */}			
		else if (xmlHttpObj.readyState == 2)	{ /* loaded */ }
		else if (xmlHttpObj.readyState == 3)	{ /* interactive */ }		
		else if (xmlHttpObj.readyState == 4)   	  /* complete */
		{
			if (ie)
			{  
				responseDOM = xmlHttpObj.responseXML;
				responseDOM.validateOnParse = false;
			}  
			else 
			{  
				var objDOMParser = new DOMParser();
				responseDOM = objDOMParser.parseFromString(xmlHttpObj.responseText, "text/xml");
			}        

			if (responseDOM != null)
			{   
				CBhttp.responsePCollection = cbhttp_docToPCollection(responseDOM);
			}

			if (CBhttp.responsePCollection==null)
			{  
				if (showErrors)
		  {  
		     alert ("Forkert response fra server.\nUrl: " + url + "\n" + xmlHttpObj.responseText);
		  }
		  else
		  {   errorText = cbhttp_getError (responseDOM);
		      throw new Error (errorText);
		  }
	      }    

			responseHandler(CBhttp.responsePCollection);
		}
	}
	xmlHttpObj.send(null);
} 


CBhttp.prototype.getResponsePCollection = function ()
{  return this.responsePCollection;
}

CBhttp.prototype.getResponsetext = function ()
{  return this.xmlHttp.responseText;
}

CBhttp.prototype.getResponseDOM = function ()
{  return this.xmlHttp.responseDOM;
}

CBhttp.prototype.getErrorText = function ()
{  return this.xmlHttp.errorText;
}


// *************************************************
//  PCollection
// *************************************************

function PCollection ()
{   this.node = null;
}

PCollection.prototype.getName = function ()
{ if (this.node!=null) 
     return this.node.getAttribute("name").toLowerCase();
  else
     return null;    
}

PCollection.prototype.getType = function ()
{  this.node.tagName;
}

PCollection.prototype.getId = function ()
{  if (this.node!=null) 
      return this.node.getAttribute("pcolid");
   else
      return null;    
}

PCollection.prototype.setNode = function (node)
{  this.node = node;
}

PCollection.prototype.getNode = function ()
{  return this.node;
}

PCollection.prototype.isPComposite = function ()
{  return this.node.tagName.toLowerCase() == "pcomposite";
}

PCollection.prototype.isRowList = function ()
{  return this.node.tagName.toLowerCase() == "rowlist";
}

PCollection.prototype.isRow = function ()
{  return this.node.tagName.toLowerCase() == "row";
}

PCollection.prototype.isColumn = function ()
{  return this.node.tagName.toLowerCase() == "col";
}

PCollection.prototype.toString = function ()
{  return "PCollection '" + this.getName() + "'";
}

// *************************************************
//   Pcomposite
// *************************************************

PComposite.prototype = new PCollection();
PComposite.prototype.constructor=PComposite;

function PComposite (node)
{       
   	PCollection.prototype.setNode.call(this, node);
    this.elements = cbhttp_getPCollectionChilds (node);
}

PComposite.prototype.size = function ()
{   
    return this.elements.length;
}

PComposite.prototype.get = function (nameOrIndex)
{   
    if (! isNaN(nameOrIndex))
    {   var n = this.elements[nameOrIndex];
    
        if (n==null)
        {  return null;
        }
    
        return cbhttp_toPCollection (n);
    }
    else
    {  var size = this.size();
       nameOrIndex = nameOrIndex.toLowerCase();
       for (var pc_i2=0; pc_i2<size; pc_i2++)
       {
          var n = this.get(pc_i2);
          if (n!=null && n.getName() == nameOrIndex)
          {  return n;
          }
       }
    
       return null;
    }      
}

PComposite.prototype.toString = function ()
{  var str = "BEGIN PComposite '" + this.getName() + "'\n";
   
   for (var pc_i1=0; pc_i1<this.size(); pc_i1++)
   {   str += this.get(pc_i1).toString() + "\n";
   }
   
   str += "END PComposite '" + this.getName() + "'\n";
   
   return str;
}


// *************************************************
//   RowList
// *************************************************

RowList.prototype = new PCollection();
RowList.prototype.constructor=RowList;

function RowList (node)
{  
   	PCollection.prototype.setNode.call(this, node);
    this.elements = cbhttp_getPCollectionChilds (node);   	
}

RowList.prototype.size = function ()
{   
    return this.elements.length;
}


RowList.prototype.row = function (index)
{   
    var n = this.elements[index];   
    
    if (n!=null)
       return new Row(n);
    else
       return null;   
}

RowList.prototype.toString = function ()
{  var str = "BEGIN RowList '" + this.getName() + "'\n";
   
   for (var r_i1=0; r_i1<this.size(); r_i1++)
   {  str += this.row(r_i1).toString() + "\n";
   }
   
   str += "END RowList '" + this.getName() + "'\n";
   
   return str;
}


// *************************************************
//   Row
// *************************************************

Row.prototype = new PCollection();
Row.prototype.constructor=Row;

function Row (node)
{  
   	PCollection.prototype.setNode.call(this, node);
    this.elements = cbhttp_getPCollectionChilds (node);   	
}

Row.prototype.size = function ()
{   
    return this.elements.length;
}

Row.prototype.column = function (nameOrIndex)
{   
    if (! isNaN(nameOrIndex))
    {  var n = this.elements[nameOrIndex];   
    
       if (n!=null)
          return new Column(n);
       else
          return null;   
    }
    else
    {
       var size = this.size();
       nameOrIndex = nameOrIndex.toLowerCase();    
       for (var c_i1=0; c_i1<size; c_i1++)
       {
          var n = this.column(c_i1);
          if (n!=null && n.getName() == nameOrIndex)
          {  return n;
          }
       }
    
       return null;
    }      
}

Row.prototype.toString = function ()
{  var str = "BEGIN Row '" + this.getName() + "'\n";
   
   str += "Columns: ";
   for (var i=0;i<this.size(); i++)
   {  str += this.column(i).toString() + ", ";
   }
   
   str += "\nEND Row '" + this.getName() + "'\n";

   return str;
}


// *************************************************
//   Column
// *************************************************

Column.prototype = new PCollection();
Column.prototype.constructor=Column;

function Column (node)
{  
   PCollection.prototype.setNode.call(this, node);
}

Column.prototype.getValue = function  ()
{  var n = this.getNode();

   if (n!=null && n.firstChild!=null)
      return n.firstChild.nodeValue;
   else      
      return null;   
}

Column.prototype.toString = function ()
{  return  this.getName() + "='" + this.getValue() + "'";
}


// *************************************************
//  Utility funtioner
// *************************************************


function cbhttp_docToPCollection (doc)
{
    var rootElm = doc.getElementsByTagName("pcollection").item(0)
    
    var pcol = cbhttp_toPCollection (rootElm);
    
    return pcol;
}       
  
function cbhttp_toPCollection (node)
{
    var pcol = null;
 
    if (node!=null)
    {  
       if (node.tagName == "pcollection")
          pcol = cbhttp_toPCollection (cbhttp_getPCollectionChilds (node)[0]);
       else if (node.tagName == "pcomposite")
          pcol = new PComposite(node);
       else if (node.tagName == "rowlist")
          pcol = new RowList(node);
       else if (node.tagName == "row")
          pcol = new Row(node);
       else if (node.tagName == "col")
          pcol = new Column(node);
    }      
    
    return pcol;
}     

function cbhttp_getPCollectionChilds (node)
{
   var result = new Array();
   var count = 0;
   
   var nl = node.childNodes;
   for (var i=0; node!=null && i<nl.length; i++)
   { 
      var n = nl.item(i);
      
      if (n.tagName=="pcollection" || n.tagName=="pcomposite" || n.tagName=="rowlist" || n.tagName=="row" || n.tagName=="col")
      {  result[count] = n;
         count++;
      }
   }

   return result;
}   

function cbhttp_createXMLHttpRequestObject ()
{
    var xmlhttpreq = false;
    try
    {
        if(window.XMLHttpRequest)
        {
           xmlhttpreq = new XMLHttpRequest(); 
        }
        else if(window.ActiveXObject)
        {
            try 
            { xmlhttpreq = new ActiveXObject("Msxml2.XMLHTTP.3.0"); 
            }
            catch(e)
            {
                try 
                { xmlhttpreq = new ActiveXObject("Microsoft.XMLHTTP"); 
                }
                catch(e) 
                {  throw new Error ("Kunne ikke oprette et XMLHTTP objekt!");
                }
            }
        }
    }
    catch (e)
    {
       throw new Error ("Kunne ikke oprette et XMLHTTP objekt!");    
    }

    return xmlhttpreq;    
}

function cbhttp_getError (responseDOM) 
{
   var msg = "";

   if (responseDOM==null)
   {  msg = "Forkert response fra server";
   }
   else 
   {     
      var node = responseDOM.getElementsByTagName('error');
      
      if (node!=null)
      {   
         var e = "";
         var m = "";

         var eNode = responseDOM.getElementsByTagName('exception');
         if (eNode!=null && eNode.length > 0)
         {  e = eNode[0].firstChild.nodeValue;
         } 

         var mNode  = responseDOM.getElementsByTagName('message');
         if (mNode != null && mNode.length > 0)
         {  
            for (i=0; i<mNode.length; i++) 
            {  if (m=="")
               {  m = m + ". ";
               }   
               m = m + mNode[i].firstChild.nodeValue;
            }   
         } 
      
         if (m != "")
         {  msg = m;
            if (e != "")
            {  msg = msg + " (" + e + ")";  
            }            
         }
         else
         {  msg = e;
         }
      }
      else
      {  msg = "Forkert response fra server"; 
      }
   }   
   
   return msg;
}



// *************************************************
//   Additional functions (kpo)
// *************************************************

//returns the dom
function cbhttp_getRequestDom(url,get)
{
    var xmlhttpreq = cbhttp_createXMLHttpRequestObject();
    try
    {
        if(get)
        {
            xmlhttpreq.open('GET', url, false);
            xmlhttpreq.send(null);
        }
        else
        {
            var baseurl = url.split('?');
            xmlhttpreq.open('POST', baseurl[0], false);
            xmlhttpreq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            xmlhttpreq.send(baseurl[1]);
        }
        return xmlhttpreq.responseXML;
    }
    catch (e)
    {
        alert("Der opstod en fejl: " + e);
        return null;
    }
}

//returns number of childnodes (not grandchilds and so on)
function cbhttp_getLength(node)
{
    var l=0;
    var lnode = cbhttp_getFirstChild(node);
    if(!lnode)
        return l;
    for (var inode = 0; inode < 99999; inode++) 
    {
        if(lnode.nodeType!=3)
            l++;
        lnode = lnode.nextSibling;
        if(!lnode)
            inode = 100000;
    }
    return l;
}
//returns the first child of a node
function cbhttp_getFirstChild(node)
{
    if(ie)
    {
        if(node)
        {
            if(!node.hasChildNodes())
                return null;
        }
        else
            return null;
    }
    var l = 99999;
    var returnnode = node.firstChild;
    for (var inode=0;inode<l;inode++) 
    {
        if(returnnode.nodeType!=3)
            return returnnode;
        returnnode = returnnode.nextSibling;
        if(!returnnode)
            inode = l+1;
    }
    return null;
}

//returns the next sisternode
function cbhttp_getNextNode(node)
{
    var l = 99999;
    var returnnode = node.nextSibling;
    if(!returnnode)
        return null;
    for (var inode=0;inode<l;inode++) 
    {
        if(returnnode.nodeType!=3)
            return returnnode;
        returnnode = returnnode.nextSibling;
        if(!returnnode)
            inode = l+1;
    }
    return null;
}

//returns a node at the next level with a specific attribute name and value
function cbhttp_getNodeByAttributeName(node,attributeName,attributeValue)
{
    var l = 99999;
    var returnnode = cbhttp_getFirstChild(node);
    if(!returnnode)
        return null;

    for (var inode=0;inode<l;inode++) 
    {
        if(returnnode.getAttribute(attributeName) == attributeValue)
            return returnnode;
        returnnode = cbhttp_getNextNode(returnnode);
        if(!returnnode)
            inode = l+1;
    }
    return null;
}


// Returns the value of the embedded textnode
function cbhttp_getNodeValue  (node)
{  
   if (node!=null && node.firstChild!=null)
      return node.firstChild.nodeValue;
   else      
      return null;   
}

