  /**
   *  fProcess JS Frontend for JSON/iframe
	*  -----------------------------------------------------------------------
	*  @copyright Copyright (c) 2006-2008 fCMS Development Team
   *  @author Arne Blankerts <theseer@fcms.de>
	*	
	*  $Id: fprocess.fscript.js,v 1.32 2009/01/20 14:54:45 theseer Exp $
	* 
   *  fProcess/JSON Usage:
   * 
	*    var foo = new fProcess();
	*    foo.init(formId, 'http://server.domain.tld/en/binary/action.xml');
	*    // foo.useIframe=true; // use hidden iframe rather then json-rpc
	*    foo.onsubmit  = function(payload) { ... }; // json-rpc mode only
	*    foo.onsuccess = function(result) { ... };
	*    foo.onerror   = function(result) { ... };
	*    foo.submit();
	* 
	*  Helper functions that can be used in on*-handlers:
	* 
	*    foo.applyErrorStyles(errorNodes);  - update styles for errornous elements
	*    foo.resetStyles();                 - reset styles after applyErrorStyles has been run
	* 
	*/

   function fProcess() {};
	fProcess.prototype = {
	   
	   // callback eventh functions
	   onsubmit: null,
	   onsuccess: null,
	   onerror: null,
	   
	   // debug swtich
	   debug: false,
	   
	   // target url
	   url: null,	 
	   
	   // form object
	   form: null,
	   
	   // backup style data
	   styleData: null,
	   
	   useIframe:false,
      
      iframe: null,
	   
	   // public init function
	   init: function(id,uri) {
	      this.form=document.getElementById(id);
	      if (!this.form) {
	         throw 'Requested form with id "'+id+'" not found in document';
	      }
	      if (uri) {
   	      this.url=uri;
   	      this.form.action=uri;
	      } else {
	         this.url=this.form.action;
	      }
	      
	      var inputs=this.form.getElementsByTagName('input');
	      for(var x=0; x<inputs.length; x++) {
	         if (inputs[x].type.toLowerCase()=='file') {
	            this.useIframe=true;
	            break;
	         }
	      }
	      
	   },
	   
	   // public submit function
	   submit: function() {	      
	      var myself=this;
	      
	      if (this.useIframe) {
	         
            if (this.iframe) {
               // safari <3 does not handle display:none for target
               this.iframe.style.display='block';
            } else {
	           this.iframe=document.createElement('iframe');
	            var iFrameID='__fUpload__'+new Date().getTime();
	            this.iframe.name=iFrameID;         
	            this.iframe.id=iFrameID;
	            fScript.registerEvent('load',function(){ 
	               var iFrame = document.getElementById(iFrameID); 
	               var doc = (iFrame.contentDocument)?(iFrame.contentDocument):((iFrame.contentWindow)?(iFrame.contentWindow.document):(self.frames[iFrameID].document));
	               if (doc.location.href == 'about:blank') { return; }
	               myself.__iframeOnload.call(myself,doc.getElementsByTagName('body')[0].innerHTML); 
	               },this.iframe); 
	            
	            // Safari < 3 does not support display:none here - so set height/width to 0 
	            this.iframe.style.position='absolute';
	            this.iframe.style.top='0px';
	            this.iframe.style.left='0px';
	            this.iframe.style.width="0px";
	            this.iframe.style.height="0px";
	            document.getElementsByTagName('body')[0].appendChild(this.iframe);
               
	            // Fix for br0ken Internet Explorer 
	            try {
	              if (self.frames[iFrameID].name != iFrameID) self.frames[iFrameID].name = iFrameID;
	            } catch (e) {}
               
            }
	         this.form.target=this.iframe.id;
	         
	         this.form.submit();
	         
	      } else {
	      
   	      var xhttp=fScript.xmlHttpRequest();
   	      var Req={
   	         form: this.form.getAttribute('id'),
   	         params: this.__getPayload()
   	      };
   	      
            if (typeof this.onsubmit == 'function') {	         
             	var x=this.onsubmit(Req.params);
             	if (x) { Req.params=x; }
        	   }
            
            if (this.debug) {
               alert('Palyoad: '+fJson.encode(Req));
            }
   	      
   	      xhttp.onreadystatechange = function() { myself.__submitHandler.call(myself,xhttp); };	      
   	      xhttp.open('POST',this.url,true);
   	      xhttp.send(fJson.encode(Req));	      
	      }
	      
	      return true;	      
	      	      
	   },
	   

	   // internal onload handler
	   __submitHandler: function(xhttp) {
	      
	      if (xhttp.readyState!=4) {
	         return;
	      }
	      
	      try {	
	         if (this.debug) {
	            alert('Service reply: '+xhttp.responseText);
	         }
            try {
               var res=fJson.decode(xhttp.responseText);   
            } catch (ex) {
               throw 'Empty reply from server';               
            }
	         		         
          	if (res.result==null) {
         	   if (res.error) {
            	   throw res.error;
            	}
            	throw 'Unexpected Object structure';
         	}
        	
         	if (res.state) {
         	    if (typeof this.onsuccess == 'function') {	         
                    this.onsuccess(res.result);
        	       }
        	   } else {
     	         if (typeof this.onerror == 'function') {	         
                  this.onerror(res.result);
  		      	}
        	   }
		      			      
		   } catch (e) {
	         fScript.handleException(e,'fProcess.__submitHandler');
		   }
	      
	   },
	   
	   // in iframe mode this is the onload handler
	   __iframeOnload: function(data) {	      
         
	      try {
            
            //this.iframe.parentNode.removeChild(this.iframe);
            this.iframe.style.display='none';
            
	         //alert(data);
            if (this.debug) {
               alert('Service reply: '+data);
            }
            
	         var res=fJson.decode(data);		         
           	if (res.result==null) {
         	   if (res.error) {
            	   throw res.error;
            	}
            	throw 'Result is not a JSON string';
         	}
            	
         	if (res.state) {
         	  if (typeof this.onsuccess == 'function') {	         
               this.onsuccess(res.result);
         	  }
         	} else {
      	      if (typeof this.onerror == 'function') {
                  this.onerror(res.result);
   		      }
         	}
	      } catch (e) {
	         fScript.handleException(e,'fProcess.__iframeOnload');
	      }
	   },
      
      // build Payload Object
      __getPayload: function() {      
         
         var payload=new Object;
         var keyArray=new Array();
         
         // get inputs, selects, textareas
         
         var objectList=new Array(
               this.form.getElementsByTagName('input'),
               this.form.getElementsByTagName('select'),
               this.form.getElementsByTagName('textarea')
         );
         
         for (var x=0; x<3; x++) {

            var inputList=objectList[x];
            if (!inputList) continue;
         
            for (var t=0; t<inputList.length; t++) {
               var input=inputList[t];
               var key;
               if (input.getAttribute('name')) {
                  key=input.getAttribute('name');
               } else if (input.getAttribute('id')) {
                  key=input.getAttribute('id');
               } else { // skip anonymous elements
                  continue;
               }
               
               // get value
               var value;               
               if (input.nodeName=='TEXTAREA') {
                  value=input.value;
               } else if (input.nodeName=='SELECT') {
                  if (input.type=='select-multiple') {
                     var optList=input.getElementsByTagName('option');
                     value=new Array();
                     for (var i=0; i<optList.length; i++) {
                        if (optList[i].selected) {
                           value.push(optList[i].value);
                        }
                     }
                  } else {
                     if (input.selectedIndex!=-1) {
                        value=input.options[input.selectedIndex].value;
                     }
                  }
               } else {
                  
                  switch (input.getAttribute('type')) {
   
                     case 'image':
                     case 'button':
                     case 'password':
                     case 'hidden':
                     case 'text': {
                        value=input.value;
                        break;
                     }
                     
                     case 'checkbox':
                     case 'radio': {
                        if (!input.checked) {
                           continue;
                        }
                        value=input.value;
                        break;
                     }
                     
                  }
                  
               }
             
               var kpos=key.indexOf('[');
               if (kpos!=-1) {
                  var regex= /\[(\w*)\]/g;                           
                  var m;
                  var kList=[];
                  while (m=regex.exec(key)) {
                     kList.push(m[1]);
                  }
                  
                  var base=key.substring(0,kpos);
                  if (!payload[base]) {
                     payload[base]={};
                  }
                  obj=payload[base];
                  
                  for (k=0; k<kList.length-1; k++)  {                      
                     var ck=kList[k];
                     if (!obj[ck]) {
                        obj[ck]={};                     
                     }
                     obj=obj[ck];                  
                  }
                  obj[kList[kList.length-1]]=value;
                  
               } else {
                  payload[key]=value;
               }
               
            } // inputList - loop            
            
         } // objectList - loop
         
         return payload;
         
      },            
      
      applyErrorStyles: function(nodeList) {
         if (this.styleData!=null) {
            this.resetStyles();
         }
         this.styleData=new Array();         
         
         for (var i in nodeList) {
            var obj=document.getElementById(nodeList[i]['id']);
            if (!obj) continue;
            
            var styleValue=null;
            var classValue=null;
            
            if (nodeList[i]['styleValue']) {               
               if (obj.runtimeStyle) { // ie propietary
                  styleValue=obj.runtimeStyle.cssText;
                  obj.runtimeStyle.cssText=nodeList[i]['styleValue'];
               } else { // w3c
                  styleValue=obj.getAttribute('style');
                  obj.setAttribute('style',nodeList[i]['styleValue']);
               }
            }
            if (nodeList[i]['classValue']) {
               classValue=obj.className;
               obj.className=nodeList[i]['classValue'];
            }
            
            this.styleData.push( {
               id: nodeList[i]['id'],
               classValue: classValue,
               styleValue: styleValue
            });
            
         }
         return true;
      },
      
      resetStyles: function() {         
         if (this.styleData==null) {
           return false;
         }
         for (var i in this.styleData) {
            var node=this.styleData[i];
            var obj=document.getElementById(node.id);
            if (!obj) continue;
            
            if (node.classValue) {
               obj.setAttribute('class',node.classValue);
            } else {
               obj.removeAttribute('class');
            }
            if (node.styleValue) {
               obj.setAttribute('style',node.styleValue);
            } else {
               obj.removeAttribute('style');
            }
         }
         this.styleData=null;         
         return true;
      }
	
	}

		
