ajaxValidate = {
  errorClass: 'form-error',
  containerErrorClass: 'formElementContainerWithErrors',
  containerClass: 'formElementContainer',

  /**
  * This method builds a new form observer with correct options
  *
  */
  observeField: function(element, beforeCallback)
  {
    Element.addClassName(element, 'ajax_validation');
    new Form.Element.EventObserver(element, ajaxValidate.onChange);
  },

  /**
  * This method is being called if the an element value changes
  *
  */
  onChange: function(element, value)
  {

    // collect all elements needed for this operation
    // this line leads to the major limitation of the ajax validation system:
    // it can only be used for one form at a time
    ajaxValidate.form = element.form;
    var form = element.form;
    var url = form.action;
    var method = form.method ? form.method : 'post';

    /*if (form.elements['commit'] && form.elements['commit'].onclick) {
      form.elements['commit'].onclick();
    }*/

    //tell the element to display an error if one occured
    element.changedInSession = true;

    //get the serialized data and add _ajax_validation to let the server know not to execute the success action
    var serializedData = Form.serializeElements(
      Form.getElements(ajaxValidate.form).collect(function(element) {
        if (element.type == 'hidden' || element.hasClassName('ajax_validation')) {
          return element;
        }
      }).compact()
    )+'&_ajax_validation=1';

    //var serializedData = Form.serialize(form)+'&_ajax_validation=1';
    /*var ajax_elements = document.getElementsByClassName('ajax_validation').collect(function(elm) {
      return elm.id
    });*/


    var req = new Ajax.Request(url, {
      'method': method,
      onSuccess: function(transport, json) {
        var errors = $H(json);
        var form = errors.keys().length > 0 ? $(errors.keys().first()).form : ajaxValidate.form;
        for (var i = 0; i < form.elements.length; i++) {
          try {
            var element = form.elements[i];
            var errorMsg = $('error_for_'+element.id);
            if (!errors[element.id] && element.changedInSession) {
              ajaxValidate.swapInvalid(element, false)
            } else {
              Element.update(errorMsg, errors[element.id]);
              if (element.changedInSession) {
                ajaxValidate.swapInvalid(element, true)
              }
            }
          }catch(e){}
        }

      },
      'asynchronous': true,
      'parameters': serializedData
    });
    req.elm = element;
  },

  swapInvalid: function(element, invalid)
  {
    var errorMsg = $('error_for_'+element.id);
    var errorContainer = errorMsg.parentNode;
    var fieldContainer = $('container_for_'+element.id);

    if(invalid) {
      Element.show(errorContainer);
      Element.show(errorMsg);
      fieldContainer.addClassName(this.containerErrorClass);
      fieldContainer.removeClassName(this.containerClass);
    } else {
      Element.hide(errorContainer);
      Element.hide(errorMsg);
      fieldContainer.addClassName(this.containerClass);
      fieldContainer.removeClassName(this.containerErrorClass);
    }
  }
}
