﻿// JQuery Web Services Proxy
// based on Matthias Hertel's js webservice soap implementation
// author: omer / started on 22.04.2008
(function ($) {
	$.WebServices = {
	    author:"MagiClick - Omer DUZYOL",
	    version: "1.1.7",
	    _call : function(args){
            var p = args.callee;
        
            // envelope start
            var soap = "<?xml version='1.0' encoding='utf-8'?>"
            + "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"
            + "<soap:Body>"
            + "<" + p.fname + " xmlns='" + p.service.ns + "'>";

            // parameters
            if(p.params!=null)
            {
            for (n = 0; (n < p.params.length) && (n < args.length); n++) {
            var val = args[n];
            var typ = p.params[n].split(':');

            if ((typ.length == 1) || (typ[1] == "string")) {
              val = String(args[n]).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

            } else if (typ[1] == "int") {
              val = parseInt(args[n]);
            } else if(typ[1]=="decimal"){
              val = parseFloat(args[n])
            } else if(typ[1]=="short"){
              val = parseFloat(args[n])
            } else if(typ[1]=="long"){
              val = parseInt(args[n])      
            } else if (typ[1] == "float") {
              val = parseFloat(args[n]);

            } else if ((typ[1] == "x") && (typeof(args[n]) == "string")) {
              val = args[n];

            } else if ((typ[1] == "x") && (typeof(XMLSerializer) != "undefined")) {
              val = (new XMLSerializer()).serializeToString(args[n].firstChild);

            } else if (typ[1] == "x") {
              if (args[n] != null)
                val = args[n].xml;

            } else if ((typ[1] == "bool") && (typeof(args[n]) == "string")) {
              val = args[n].toLowerCase();

            } else if (typ[1] == "bool") {
              val = String(args[n]).toLowerCase();

            } else if (typ[1] == "date") {
              // calculate the xml format for datetime objects from a javascript date object
              if(val!=null){
                
                  var s, ret;
                  ret = this._makeDigit(String(val.getFullYear()),4);
                  ret += "-";
                  s = this._makeDigit(String(val.getMonth() + 1),2);
                  ret += (s.length == 1 ? "0" + s : s);
                  ret += "-";
                  s = this._makeDigit(String(val.getDate()),2);
                  ret += (s.length == 1 ? "0" + s : s);
                  ret += "T";
                  s = this._makeDigit(String(val.getHours()),2);
                  ret += (s.length == 1 ? "0" + s : s);
                  ret += ":";
                  s = this._makeDigit(String(val.getMinutes()),2);
                  ret += (s.length == 1 ? "0" + s : s);
                  ret += ":";
                  s = this._makeDigit(String(val.getSeconds()),2);
                  ret += (s.length == 1 ? "0" + s : s);
                  val = ret;
              } else {
                val = "0001-01-01T00:00:00";
              }

            } else if (typ[1] == "s[]") {
              if(args[n]!=null)
                val = "<string>" + args[n].join("</string><string>") + "</string>";
              else val="";

            } else if (typ[1] == "int[]") {
              if(args[n]!=null)
              val = "<int>" + args[n].join("</int><int>") + "</int>";
              else val="";
            } else if (typ[1] == "short[]") {
              if(args[n]!=null)
              val = "<short>" + args[n].join("</short><short>") + "</short>";
              else val="";	  
            } else if (typ[1] == "decimal[]") {
              if(args[n]!=null)
              val = "<decimal>" + args[n].join("</decimal><decimal>") + "</decimal>";
              else val="";
            } else if (typ[1] == "long[]") {
              if(args[n]!=null)
              val = "<long>" + args[n].join("</long><long>") + "</long>";
              else val="";	  
            } else if (typ[1] == "float[]") {
              if(args[n]!=null)
              val = "<float>" + args[n].join("</float><float>") + "</float>";
              else val="";

            } else if (typ[1] == "bool[]") {
              if(args[n]!=null)
              val = "<boolean>" + args[n].join("</boolean><boolean>") + "</boolean>";
              else val ="";

            } // if
            soap += "<" + typ[0] + ">" + val + "</" + typ[0] + ">"
            } // for
            }//if

            // envelope end
            soap += "</" + p.fname + ">"
            + "</soap:Body>"
            + "</soap:Envelope>";
            
            // enable cookieless sessions:
            var u = p.service.url;
            var cs = document.location.href.match(/\/\(.*\)\//);
            if (cs != null) {
                u = p.service.url.split('/');
                u[3] += cs[0].substr(0, cs[0].length-1);
                u = u.join('/');
            }
            
            // raise onCall event
            if(p.onBeforeCall !=null){
                p.onBeforeCall(u,soap);
            } else {
                $.WebServices.onBeforeCall(u,soap);
            }
            
            // finally call web services with jquery
            var soapXhr = $.ajax({
                url: u,
                type: "POST",
                timeout: 20000,
                data: soap,
                beforeSend: function(xhr) {                
                    xhr.setRequestHeader("SOAPAction", p.action);
                    xhr.setRequestHeader("X-Requested-With", "");
                },
                contentType: "text/xml; charset=utf-8",
                dataType: "xml",
                success: function(responseXML,textStatus){                 
                    var ret = null;
                    var cc = p;

                    if (cc==null) return;
                    var rtype = null;

                    if ((cc.rtype.length > 0) && (cc.rtype[0] != null))
                    rtype = cc.rtype[0].split(':');

                      var xNode = null;

                      if (rtype != null)
                        xNode = responseXML.getElementsByTagName(rtype[0])[0];

                      if (xNode == null) {
                        ret = null;

                      } else if (xNode.firstChild == null) { // 27.12.2005: empty string return values
                        ret = ((rtype.length == 1) || (rtype[1] == "string") ? "" : null);

                      } else if ((rtype.length == 1) || (rtype[1] == "string")) {
                        ret = xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue;

                      } else if (rtype[1] == "bool") {
                        ret = xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue;
                        ret = (ret == "true");

                      } else if (rtype[1] == "int") {
                        ret = xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue;
                        ret = parseInt(ret);

                      } else if (rtype[1] == "float") {
                        ret = xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue;
                        ret = parseFloat(ret);

                      } else if ((rtype[1] == "x") && (typeof(XMLSerializer) != "undefined")) {
                        ret = (new XMLSerializer()).serializeToString(xNode.firstChild);
                        ret = $.WebServices._getXMLDOM(ret);

                      } else if ((rtype[1] == "ds") && (typeof(XMLSerializer) != "undefined")) {
                        // serialize dataset object to xml and finally to json
                        ret = (new XMLSerializer()).serializeToString(xNode);
                        ret = $.WebServices._getXMLDOM(ret);
                        ret = $.WebServices._xml2json(ret);

                      } else if (rtype[1] == "x") {
                        ret = xNode.firstChild.xml;
                        ret = $.WebServices._getXMLDOM(ret);

                      } else if (rtype[1] == "ds") {
                        // serialize dataset object to xml and finally to json
                        ret = xNode.xml;
                        ret = $.WebServices._getXMLDOM(ret);
                        ret = $.WebServices._xml2json(ret);

                      } else if (rtype[1] == "s[]") {
                        // Array of strings
                        ret = new Array();
                        xNode = xNode.firstChild;
                        while (xNode != null) {
                          ret.push(xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue);
                          xNode = xNode.nextSibling;
                        } // while

                      } else if (rtype[1] == "int[]") {
                        // Array of int
                        ret = new Array();
                        xNode = xNode.firstChild;
                        while (xNode != null) {
                          ret.push(parseInt(xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue));
                          xNode = xNode.nextSibling;
                        } // while

                      } else if (rtype[1] == "float[]") {
                        // Array of float
                        ret = new Array();
                        xNode = xNode.firstChild;
                        while (xNode != null) {
                          ret.push(parseFloat(xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue));
                          xNode = xNode.nextSibling;
                        } // while

                      } else if (rtype[1] == "bool[]") {
                        // Array of bool
                        ret = new Array();
                        xNode = xNode.firstChild;
                        while (xNode != null) {
                          ret.push((xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue).toLowerCase() == "true");
                          xNode = xNode.nextSibling;
                        } // while

                      } else  {
                        ret = xNode.textContent || xNode.innerText || xNode.text || xNode.childNodes[0].nodeValue;
                      } // if
                      
                      // sycronize call response
                      if(cc.Callback == null){
                        return ret;
                      } else {
                        cc.Callback(ret);
                        return;
                      }
                    //}
                },
                error: function(xhr, textStatus, errorThrown){
                    var extraDetails = "";
                    var skipError = false;
                    
                    if(textStatus == "timeout") 
                        skipError = true;
                        
                    // raise an exception
                    ret = new Error();
                    try
                    {
                        if (xhr.status == 404) {
                        ret.message = "The webservice could not be found.";

                        } else if (xhr.status == 500) {
                            var ret_name,ret_message,ret_description;
                            ret_name = "SoapException";
                            //ret.name = "SoapException";
                            var n = xhr.responseXML.documentElement.firstChild.firstChild.firstChild;
                            while (n != null) {
                              if (n.nodeName == "faultcode") ret_message= n.firstChild.nodeValue;//ret.message = n.firstChild.nodeValue;
                              if (n.nodeName == "faultstring") ret_description = n.firstChild.nodeValue;//ret.description = n.firstChild.nodeValue;
                              n = n.nextSibling;
                            } // while
                            ret.name=ret_name;
                            ret.message=ret_message;
                            ret.description=ret_description;

                        } else if ((xhr.status == 502) || (xhr.status == 12031)) {
                        ret.message = "The server could not be found.";

                        } else {
                            // no classified response.
                            ret.message = "Result-Status:" + xhr.status + "\n" + xhr.responseText;
                        } // if

                        
                     } catch(err)
                     {
                        if(err.name == "NS_ERROR_NOT_AVAILABLE"){
                        
                            skipError = true;
                        } else {
                            ret.name = "XMLHttpBrokenConnectionException";
                            ret.message = "Connection closed unexpectedly. You may not have access to get request.";
                            ret.description = "";
                            extraDetails = err;
                        }
                     }
                     
                    if(!skipError){
                         if(p.onError !=null){
                            p.onError(ret,extraDetails);
                        } else {
                            $.WebServices.onError(ret,extraDetails);
                        }
                    }
	            },
                complete: function(XMLHttpRequest, textStatus)
                {
                   if(p.onFinally !=null){
                        p.onFinally(XMLHttpRequest, textStatus);
                   } else {
                        $.WebServices.onFinally(XMLHttpRequest, textStatus);
                   }
                }
            });
            p.xhr = soapXhr;
	    },
	    onError: function(err,extraDetails){
            alert("Web Service error\r\n" + err.name + "\r\nMessage: " + err.message + "\r\n" + err.description);
        }
        ,
        onBeforeCall: function(){
            return;
        },
        onFinally: function(){
            return;
        },
        _getXMLDOM: function (xmlText) {
            var obj = null;

            if ((document.implementation != null) && (typeof document.implementation.createDocument == "function")) {
            // Gecko / Mozilla / Firefox
            var parser = new DOMParser();
            obj = parser.parseFromString(xmlText, "text/xml");

            } else {
            // IE
            try {
              obj = new ActiveXObject("MSXML2.DOMDocument");
            } catch (e) { }

            if (obj == null) {
              try {
                obj = new ActiveXObject("Microsoft.XMLDOM");
              } catch (e) { }
            } // if

            if (obj != null) {
              obj.async = false;
              obj.validateOnParse = false;
            } // if
            obj.loadXML(xmlText);
            } // if
            return(obj);
        }, // _getXMLDOM
        _xml2json : function (xObj) {
            if (xObj.nodeType == 9)
            return(this._xml2json(xObj.documentElement));

            var n = xObj.firstChild;
            if (n.nodeType == 3) {
            // just a text node.
            ret = n.nodeValue;

            } else {
            // a complex node.
            var ret = { };

            // analyse all subnodes
            while (n != null) {
              var nn = n.nodeName;
              var nv = this._xml2json(n); // recursion !
              if (ret[nn] == null) {
                // maybe just a simple nested value
                ret[nn] = nv;
              } else if (ret[nn].constructor == Array) {
                // nn is already an array, now with another value
                ret[nn].push(nv);
              } else {
                // if more than 1 element with the same name is present
                // an array is used to collect them all.
                var tmp = new Array();
                tmp[0] = ret[nn];
                tmp[1] = nv;
                ret[nn] = tmp;
              } // if
              n = n.nextSibling;
            } // while
            } // if
            return(ret);
        }, // xml2json
        _makeDigit:function(strData,intDigits){
            var ret = strData;
            for(var t=0;t<intDigits;t++)
                ret = "0" + ret;
            
            ret = ret.substring(ret.length-intDigits)
            return ret;
        }
	}
})(jQuery);