function ajax_form(container_id, url, init_on_create)
{ 
  this.ajaxURL = url;
  
  this.containerId = container_id;
  this.containerElement = null;
  
  this.contentWrapperClass = 'aform_content_wrapper';
  this.contentWrapperElement = null;
  
  this.contentClass = 'aform_content';
  this.contentElement = null;
  
  this.formWrapperClass = 'aform_form_wrapper';
  this.formWrapperElement = null;
  
  this.formClass = 'aform_form';
  this.formElement = null;
  
  this.switchButtonClass = 'aform_switch';
  this.switchButtonElements = [];
  
  this.submitButtonClass = 'aform_submit';
  this.submitButtonElements = [];
  
  this.containerContentOnClass = 'content_on';
  this.containerFormOnClass = 'form_on';
  this.containerLoadingClass = 'loading_now';
  
  this.fancySwitching = true;
  
  this.submitIndicatorClass = 'aform_indicator';
  this.submitIndicatorElement = null;
  
  this.init_on_create = init_on_create===undefined?true:init_on_create;
  
  ajax_form.prototype.initialize = function() { 
    this.containerElement = document.getElementById(this.containerId);
    var elements = this.getDescendantsByClass(this.contentWrapperClass, this.containerElement);
    this.contentWrapperElement = elements[0];
    elements = this.getDescendantsByClass(this.contentClass, this.containerElement);
    this.contentElement = elements[0];
    elements = this.getDescendantsByClass(this.formWrapperClass, this.containerElement);
    this.formWrapperElement = elements[0];
    this.switchButtonElements = this.getDescendantsByClass(this.switchButtonClass, this.containerElement);
    elements = this.getDescendantsByClass(this.submitButtonClass, this.containerElement);
    this.submitButtonElement = elements[0];
    elements = this.getDescendantsByClass(this.formClass, this.containerElement);
    this.formElement = elements[0];
    elements = this.getDescendantsByClass(this.submitIndicatorClass, this.containerElement);
    this.submitIndicatorElement = elements[0];
    this.initializeButtons();
  };
  
  ajax_form.prototype.initializeButtons = function() { 
    for (var i = 0; i < this.switchButtonElements.length; i++) { 
      this.addEventListener(this.switchButtonElements[i], "click", this.createSwitchCallback(), this);
    }
    if(this.submitButtonElement!==undefined) {
      this.addEventListener(this.submitButtonElement, "click", this.createSubmitCallback(), this);
    }
  };
  
  ajax_form.prototype.createSwitchCallback = function() {
    var ajax_formObj = this;
    return function () {
      ajax_formObj.switchIt();
    };
  };
  
  ajax_form.prototype.switchIt = function(value) {
    if(this.hasClassName(this.containerElement, this.containerFormOnClass)) {
      this.removeClassName(this.containerElement, this.containerFormOnClass);
      if(this.fancySwitching) {
        this.contentWrapperElement.style.display = 'none';
        Effect.Appear(this.contentWrapperElement);
      }
      this.addClassName(this.containerElement, this.containerContentOnClass);
    } else {
      this.removeClassName(this.containerElement, this.containerContentOnClass);
      if(this.fancySwitching) {
        this.formWrapperElement.style.display = 'none';
        Effect.Appear(this.formWrapperElement); //.style.display = '';
      }
      this.addClassName(this.containerElement, this.containerFormOnClass);
    }
  };
  
  ajax_form.prototype.createSubmitCallback = function() {
    var ajax_formObj = this;
    return function () {
      ajax_formObj.submitIt();
      return false;
    };
  };

  ajax_form.prototype.submitIt = function(value) {
    this.addClassName(this.containerElement, this.containerLoadingClass);

    var ajaxRequest = new ajaxObject(this.ajaxURL);
    var ajax_formObj = this;
    ajaxRequest.callback = function(responseText, responseStatus, responseXML) {
      ajax_formObj.processResponse(responseText, responseStatus, responseXML);
    };
    ajaxRequest.update(this.serializeForm(this.formElement),'POST');
  };
  
  ajax_form.prototype.serializeForm = function(formElement) {
    var innerElements = formElement.getElementsByTagName('*');
    var values = [];
    for(var i = 0; i < innerElements.length; i++) {
      var element = innerElements[i];
      if((element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') && 
        !element.disabled && element.name && 
        element.type != 'FILE' && 
        ((element.type != 'CHECKBOX' && element.type != 'RADIO') || element.checked)) {
          var key = element.name;
          var value = element.value?element.value:null;
          if (key in values) {
            if(values[key] !== null && values[key].constructor == Array) { // isArray
              values[key] = [values[key]];
            }
            values[key].push(value);
          }
          else { values[key] = value; }
      }
    } 
    return this.http_build_query(values);
  };
  
  ajax_form.prototype.processResponse = function(responseText, responseStatus, responseXML) {
    this.removeClassName(this.containerElement, this.containerLoadingClass);

    if (responseStatus==200)
    {
      var xmldoc = responseXML;
      
      var root = xmldoc.getElementsByTagName("root").item(0);
      
      var all_ok = root.getElementsByTagName("all_ok").item(0).firstChild.nodeValue;
      
      var messages = [];
      var content = '';
      
      var xml_message_elements = root.getElementsByTagName("message");
      for (var i=0; i<xml_message_elements.length; i++)
      {
        if(xml_message_elements[i].firstChild!==undefined && xml_message_elements[i].firstChild!==null && xml_message_elements[i].firstChild.nodeValue != '') {
          messages[i] = xml_message_elements[i].firstChild.nodeValue;
        }
      }
      var xml_content_elements = root.getElementsByTagName("content");
      content = (xml_content_elements.length<1 || xml_content_elements.item(0).firstChild===undefined)?'':xml_content_elements.item(0).firstChild.nodeValue;
      
      this.displayMessages(messages);
      
      if(all_ok) {
        this.updateContent(content);
      }
      
      this.switchIt();
    }
  };
  
  ajax_form.prototype.updateContent = function(content) {
    this.contentElement.innerHTML = content;
  };
  
  ajax_form.prototype.displayMessages = function(messages) {
    for(var i = 0; i < messages.length; i++) {
      alert(messages[i]);
    }
  };
  
  ajax_form.prototype.getDescendantsByClass = function(class_name, container_element) {
    if(container_element === undefined) { return false;}
    var elements = [];
    var reg = new RegExp('\\b'+class_name+'\\b');
    var all = container_element.getElementsByTagName('*');
    for (var i = 0; i < all.length; i++) {
      if (reg.test(all[i].className)) {
        elements.push(all[i]);
      }
    }
    return elements;
  };
  
  ajax_form.prototype.addEventListener = function(obj,evt,fnc,scope,useCapture) {
    if (!useCapture) { useCapture=false; }
    var scoped = scope ? function(e) { fnc.apply(scope, [e]); } : fnc;
    if(obj.addEventListener){ 
      obj.addEventListener(evt,scoped,useCapture);
      return true;
    } else if (obj.attachEvent) {
      return obj.attachEvent("on"+evt,scoped);
    }
  };
  
  ajax_form.prototype.hasClassName = function(element, class_name) {
    return element.className.match(new RegExp('(\\s|^)'+class_name+'(\\s|$)'));
  };
  
  ajax_form.prototype.addClassName = function(element, class_name) {
    if(!element.className) {
      element.className = class_name;
    } else if(!this.hasClassName(element, class_name)) {
      element.className = element.className + " " + class_name;
    }
  };
  
  ajax_form.prototype.removeClassName = function(element, class_name) {
    if (this.hasClassName(element, class_name)) {
      var reg = new RegExp('(\\s|^)'+class_name+'(\\s|$)');
      element.className = element.className.replace(reg, ' ');
    }
  };
  
  ajax_form.prototype.http_build_query = function(values, prefix, suffix) {
    var str = "";
    if(str.length) { str += "&"; }
    if(prefix === undefined || !prefix) { prefix = ""; }
    if(suffix === undefined || !suffix) { suffix = ""; }
    for(var key in values) {
      if(values.hasOwnProperty(key)) {
        if(values[key] === null) { values[key] = ''; }
        if(values[key] !== null && values[key].constructor == Array) {
          str += "&" + this.http_build_query(values[key], prefix + key + "[", "]" + suffix);
        } else if(typeof values[key] != 'function' && typeof values[key] != 'object') {
          str += "&" + prefix + encodeURIComponent(key) + suffix + "=" + encodeURIComponent(values[key]);
        }
      }
    }
    return str;
  };
  
  if(this.init_on_create) {
    this.initialize();
  }
}