/*******************************

 *  Dependencies:
 *  1. hashtable.js

  property
  
    sendList:   the list of the controls that will be upload.
      true:                send all parameters in the form;
      false/null:          send checkbox only;
      Array:               send the control in the List;
  
    actionUrl:  the page that you have to request, like grid.jsp
    
    cancelSendRequest:  do the sending or not.
    
    cancelResult:  do the handling of the result or not.
    
    async: sends an asynchronous request if true
  
  mothod
  
    XmlRequest(anId, aCriteriaForm);      constructor.
      param
        aContainerId:      the Id of the XmlRequest
        aCriteriaForm:     the form that has criteria
    
    
    addEventListener(aListener, anEvent);  add the specified event to the xmlRequest.
      param
        aListener:         the Object who add the events.
        anEvnet:           the type of anEvent.(BOFORE/AFTER_SEND_REQUEST_EVENT,BOFORE/AFTER_ASSIGN_RESPONSE_EVENT)
    
    clearEventListeners(anEvent); clear the specified event.
      param
        anEvent:           the Event you want to clear.
        
    doSendRequest();  send the request to the server.
    
    addCustomCleanUrl(aCleanUrl);  add a clean url to the xmlRequest
      param
        aCleanUrl:         the clean url

    setCustomCleanUrl = function(aCleanUrl);  set a clean url to the xmlRequest
      param
        aCleanUrl:         the clean url


  the object that contain xmlRequest must have a function 
called "processResponse(responseObject)" to handle the response

  after adding the listener the object that contain xmlRequest
must have a function called "handleEvent(xmlRequest,eventType)" 
to handle the event.

looked at the gridRequest as an example.

**********************************/

var BEFORE_SEND_REQUEST_EVENT="before_send_request";
var AFTER_SEND_REQUEST_EVENT="after_send_request";
var BEFORE_ASSIGN_RESPONSE_EVENT="before_assign_response";
var AFTER_ASSIGN_RESPONSE_EVENT="after_assign_response";

var XmlRequests = new Object();

XmlRequests.addRequest = function (aRequest){
  this[aRequest.id] = aRequest;
}

XmlRequests.getRequest = function (anAlias){
  return this[anAlias];
}

XmlRequests.removeRequest = function (anId) {
  this[anId] = null;
}

function XmlRequest(anId, aCriteriaForm) {
//alert('XmlRequest');
  this.id = anId;	
  this.count = 0;
  this.criteriaForm = aCriteriaForm;
  this.sendList=null;
  this.criteria='';
  this.async = true;
  this.cleanUrl = '';
  this.actionUrl = '';
  this.skipCount = false;
  this.cancelSendRequest = false;
  this.cancelResult = false;
  this.eventListeners = new Object();
  if (XmlRequests.getRequest(anId)) {
    // cleanup the old request
    var xhr = XmlRequests.getRequest(anId);
    if (!xhr.skipCount) {
      activeRequests--;
    }
    xhr.requestObject.onreadystatechange = new Function();
  } 
  XmlRequests.addRequest(this);
}

XmlRequest.prototype.addEventListener = function (aListener, anEvent){
//alert('addEventListener');
  if (typeof(anEvent)=="object"){
    if (!anEvent[0])throw "invalid event " + anEvent;
    var i;
    for (i=0;i<anEvent.length;i++){
      this.addEventListener(aListener,anEvent[i]);
    }    
  } else if (typeof(anEvent)=="string") {
    if (!this.eventListeners[anEvent]){
      this.eventListeners[anEvent]=new Array();
    }
    this.eventListeners[anEvent][this.eventListeners[anEvent].length]=aListener;
  }
}

XmlRequest.prototype.clearEventListeners = function (anEvent){
//alert('clearEventListeners');
  this.eventListeners[anEvent]= new Array();
}

XmlRequest.prototype.notifyEventListeners = function (anEvent){
//alert('notifyEventListeners');
  var i;
  var arListeners = this.eventListeners[anEvent];
  //no event listeners for this event
  if (!arListeners)return;  
  for (i=0;i<arListeners.length;i++){
    arListeners[i].handleEvent(this,anEvent);
  }
}

XmlRequest.prototype.doSendRequest=function(){
//alert('doSendRequest');
  this.cancelSendRequest = false;
  this.generateQuery();
  this.notifyEventListeners(BEFORE_SEND_REQUEST_EVENT);
  if(this.cancelSendRequest) return;
  this.sendRequest();  
  this.notifyEventListeners(AFTER_SEND_REQUEST_EVENT);
}

XmlRequest.prototype.generateQuery = function(){
//alert('generateQuery');
	this.criteria = this.getParameters(this.criteriaForm);
}

XmlRequest.prototype.sendRequest = function (){	
//alert('sendRequest');
	this.requestObject=null;
	this.requestObject = this.createRequestObject();
	this.requestObject.onreadystatechange = function() {
	  closeWindow();
	}
	this.requestObject.open("POST",this.actionUrl,true);
  //this.requestObject.setRequestHeader('Content-Type','application/x-www-form-urlencoded;' );
  //this.requestObject.setRequestHeader('Method', 'POST ' + this.actionUrl + "HTTP/1.1");  
  this.requestObject.send(null);
  if (this.skipCount != true) {
    activeRequests++;
  }
}

XmlRequest.prototype.createRequestObject = function (){	
//alert('createRequestObject');
  var xmlhttp=false;
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.4.0");
  } catch (ex1){
    xmlhttp=false;
  }  
  if (!xmlhttp) {
    try {
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }catch (e){
      try {
        xmlhttp= new ActiveXObject("Microsoft.XMLHTTP");
      } catch (ex){
        xmlhttp=false;
      }          
    }
  }
  if (!xmlhttp && typeof XMLHttpRequest != 'undefined'){
    try {
      xmlhttp = new XMLHttpRequest();
    } catch (e){
      xmlhttp = false;
    }
  }
  return xmlhttp;
}

XmlRequest.prototype.getParameters = function(aForm){ 
//alert('getParameters');
  var mainForm = aForm;  
  var sParamList = "";  
  if (mainForm) {
    var bCheckboxOnly = (!this.sendList);
    var oParamList = this.getSendList();
    var e;
    for (e=0; e<mainForm.elements.length; e++) {
      if(!mainForm.elements[e].disabled){
        if (this.isFieldParam(mainForm.elements[e],bCheckboxOnly, oParamList)) {
          sParamList +=  mainForm.elements[e].name + '=' + encodeURIComponent(mainForm.elements[e].value) +'&' ; 
        }
      }
    }    
    if (sParamList.charAt(sParamList.length-1)=='&')
    sParamList = sParamList.substr(0,sParamList.length-1);
	}
  return sParamList;
}  

XmlRequest.prototype.isFieldParam = function(aField, aCheckBoxOnly, aParamList){
//alert('isFieldParam');
  var sType = aField.type;
  var bChecked= (sType=='checkbox' && aField.checked); 
  var bRadio = (sType=='radio' && aField.checked);
  var bOthers = (sType!='button' && sType!='checkbox' && sType!='radio');
  if (aParamList){
    if (!aParamList.containsKey(aField.name)) return false;
    return bChecked || bRadio || bOthers;
  } else {
    if (aCheckBoxOnly) {
      return bChecked;
    } else {
      return bChecked || bRadio || bOthers;
    }
  }  
} 

XmlRequest.prototype.getSendList = function(){
//alert('getSendList');
  if (!this.sendList) return null;
  var sType = typeof(this.sendList);
  if (sType=='boolean') return null;

  if (sType=='object' && this.sendList[0]!=null) { 
    var oResult=new Hashtable();
    var i;
    for (i=0;i<this.sendList.length;i++){
      oResult.put(this.sendList[i],true);
    }
    return oResult;
  }
  if (sType=='string') {
    var oResult=new Hashtable();
    oResult.put(this.sendList,true);
    return oResult;
  }
  return null;
}

XmlRequest.prototype.formatQuery = function(){
//alert('formatQuery');
  var sUrl = this.criteria+this.cleanUrl;
  this.cleanUrl = '';
  sUrl = sUrl.replace(/&&/gi,'&');
  if (sUrl.charAt(0)=='&')
    sUrl = sUrl.substr(1); 
  if (sUrl.charAt(sUrl.length-1)=='&')
    sUrl = sUrl.substr(0,sUrl.length-1);
  return sUrl;
}

//add the custom url
XmlRequest.prototype.addCustomCleanUrl = function(aCleanUrl){
  this.cleanUrl += '&' + aCleanUrl;
}

XmlRequest.prototype.setCustomCleanUrl = function(aCleanUrl){
  this.cleanUrl = '&' + aCleanUrl;
}

XmlRequest.prototype.handleResponse = function (){
//alert('handleResponse');
  this.XmlResponseProcessor.processResponse(this.requestObject);
}

function handleChange(anId){
//alert('handleChange');
  var xr = XmlRequests.getRequest(anId);
  if (xr) {
    if (xr.requestObject.readyState==4){
      if (xr.skipCount != true) {
        activeRequests--;
      }
      if ((xr.requestObject.status == 200) || (xr.count > 3)) {
        xr.cancelResult=false; 
        xr.notifyEventListeners(BEFORE_ASSIGN_RESPONSE_EVENT);
        if (xr.cancelResult) return;
        xr.handleResponse();      
        xr.notifyEventListeners(AFTER_ASSIGN_RESPONSE_EVENT);
        XmlRequests.removeRequest(anId);
      } else {
        xr.sendRequest(); 
        xr.count++;
      }
    }
  }
}

var activeRequests = 0;
