function AjaxRequest() {
  this.IsAsync = true;
  this.URL = null;
  this.RequestMethod = 'GET';
  this.CompletedCallback = null;
  this.FailedCallback = null;

  this.XmlHttpObj = null;
  this.IFrameCreated = false;
  this.IFrameName = 'ajIframe' + Math.floor(Math.random()*100000);

  this.UsedXmlHttp = null;
  this.forceIFrame = false;  //debug flag to force IFRAME use
}

AjaxRequest.prototype.ajaxEnabled = function() {

  if (this.XmlHttpObj != null) { return true; }

  if (window.XMLHttpRequest) {
	this.XmlHttpObj = new XMLHttpRequest();
  }
  else {
  	this.XmlHttpObj = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : null;
  }

  if (this.XmlHttpObj == null || this.forceIFrame == true) {
    this.UsedXmlHttp = false;
    return false;
  }

  this.UsedXmlHttp = true;
  return true;
}

//helper method used by MSIE to check if the iframe is in readyState
AjaxRequest.prototype.checkIframe = function() {
  var iframeObj;
  iframeObj = this.getIframe();

  try {
	  if (iframeObj.frameElement.readyState == 'complete') {
	    var result = iframeObj.document.body.innerHTML;  
	    clearInterval(this.checkIframeInterval);

	    this.performSuccessCallback(result);
	  }
  }
  catch(exception) { 
  	//todo catch the real exception and do something about it
  }
}

//helper method to return the active iframe for this request
AjaxRequest.prototype.getIframe = function() {

  if (this.IFrameCreated == false) {
    var iframeObj;

    iframeObj = document.createElement('iframe');
    iframeObj.id = this.IFrameName;
    iframeObj.name = this.IFrameName;

    iframeObj.style.border = '0px';
    iframeObj.style.width = '0px';
    iframeObj.style.height = '0px';

    iframeObj = document.body.appendChild(iframeObj);

    this.IFrameCreated = true;

    return iframeObj;
  }

  return window.frames[this.IFrameName];
}

//helper method trigged for non MSIE browsers after iframe in completed loading
AjaxRequest.prototype.onloadIframe = function() {
  var iframeObj = this.getIframe();
  var result;
  
  try {
	result = iframeObj.document.body.innerHTML;
  } catch(exception) { 
  	//some browsers do not let us get the result
  }

  this.performSuccessCallback(result);
}

//helper method to submit data to iframe
AjaxRequest.prototype.requestViaIFrame = function(payload) {
  var iframeObj = this.getIframe();

  var tmpUrl = this.URL;

  if (payload != null && tmpUrl.indexOf('?') > 0) {
    tmpUrl = tmpUrl + '&' + payload;
  }
  else if (payload != null) {
    tmpUrl = tmpUrl + '?' + payload;
  }
  tmpUrl = tmpUrl;

  iframeObj.src = tmpUrl;

  //if MSIE use timer and poll since onload event does not work for dynamically added iframes
  if (navigator.userAgent.indexOf("MSIE") >= 0) {
    var obj = this;
    var functionReference = this.checkIframe;
    var callback = function() { functionReference.call(obj) };
    this.checkIframeInterval = setInterval(callback, 500);
  }
  else {
    var obj = this;
    var functionReference = this.onloadIframe;
    var callback = function() { functionReference.call(obj) };
    iframeObj.onload = callback;
  }
}

//helper method to call once request is successful
AjaxRequest.prototype.performSuccessCallback = function(result) {
  if (this.IsAsync && this.CompletedCallback) {
    this.result = result;
    this.CompletedCallback(result);
  }
}

AjaxRequest.prototype.ajaxstatechange = function() {

  var curAjaxRequest = this;  

  this.XmlHttpObj.onreadystatechange = function() 
  {
    try {
      if (curAjaxRequest.XmlHttpObj.readyState == 4 && curAjaxRequest.XmlHttpObj.status == 200)
      {
        var result = curAjaxRequest.XmlHttpObj.responseText;
        curAjaxRequest.performSuccessCallback(result);
      }
      else if (curAjaxRequest.XmlHttpObj.readyState == 4 && curAjaxRequest.XmlHttpObj.status != 200) {
        if (curAjaxRequest.IsAsync && curAjaxRequest.FailedCallback) {
          curAjaxRequest.FailedCallback(curAjaxRequest.XmlHttpObj.status);
        }
      } 
    }
    catch (e) { }
  }
}

//helper method to submit data using ajax
AjaxRequest.prototype.requestViaXmlHttp = function(payload) {

  this.XmlHttpObj.open(this.RequestMethod, this.URL, this.IsAsync);

  if (this.RequestMethod.toLowerCase() == 'post') {
    this.XmlHttpObj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  }

  this.ajaxstatechange();

  try {
    this.XmlHttpObj.send(payload);
  }
  catch (e) { }

  if (!this.IsAsync) {
    return this.XmlHttpObj.responseText;
  }
}

AjaxRequest.prototype.StartRequestWithData = function(payload) {
  var isAjax = this.ajaxEnabled();
  this.fixUrl();

  if (isAjax) {
    this.requestViaXmlHttp(payload);
  }
  else {
    this.requestViaIFrame(payload);
  }
}

AjaxRequest.prototype.StartRequest = function() {
  return this.StartRequestWithData(null);
}

AjaxRequest.prototype.Cancel = function() {
  if (this.UsedXmlHttp && this.XmlHttpObj) {
    if (this.XmlHttpObj.readyState == 1 || this.XmlHttpObj.readyState == 2 || this.XmlHttpObj.readyState == 3)
    { 
      this.XmlHttpObj.abort();
    }
  }
}

AjaxRequest.prototype.SubmitForm = function(formName) {
  var form = document.getElementById(formName);

  if (!form) { return; }

  if (this.URL == null && (form.action != null && form.action != "")) {
    this.URL = form.action;
  }
  else {
    this.URL = window.location.href;
  }
  
  this.RequestMethod = form.method;

  var formData = "";

  for (i = 0; i < form.elements.length; i++) 
  {
    if (i != 0) { formData += "&"; }
    formData += form.elements[i].name;
    formData += "=";
    formData += escape(form.elements[i].value);
  }
  
  this.StartRequestWithData(formData);
}

AjaxRequest.prototype.fixUrl = function() {

  if (this.URL.indexOf('http://') < 0 && this.URL.indexOf('https://') < 0) {
    //append host to url
    var host = window.location.href;
    var prot = host.substr(0, host.indexOf('/', 0));
    if (prot == "https:"){
      host = host.substr(0, host.indexOf('/', "https://".length));
    }
    else{
      host = host.substr(0, host.indexOf('/', "http://".length));
    }
    this.URL = host + this.URL;
  }
}
