

var UnobtrusiveFormValidator = new Class({
    
  Extends: FormValidator,
    
  initialize: function(form, options) {
    this.parent(form, $merge(options, {
      evaluateOnSubmit: false
    }));
        
    this.prepareErrorList();
    this.addCustomSubmitEvent();
  },
    
  /**
    *   Simple check at submit if all fields are valid. If so, returns true, otherwise false,
    */
  addCustomSubmitEvent: function() {
    this.element.addEvent('submit', function(event) {
      if(this.validate()) return true;
      event.stop();
      return false;
    }.bind(this));
  },
    
  /**
    *   Overrides FormValidator method.
    */
  validate: function() {
    this.parent();
    return !this.fields.some(function(field) {
      return field.hasClass('validation-failed');
    });
  },
    
  /**
    *   Overrides parent method.
    */
  validateField: function(field, force) {
    this.parent(field, force);
    this.injectErrorMessages();
  },
    
  injectErrorMessages: function() {
    this.fields.each(function(field) {
      this.fireEvent('validation', field);
      if(field.hasClass('validation-failed')) {
        this.addErrorMessage(field);
      }
      else {
        this.removeErrorMessage(field);
      }
    }, this);
  },
    
  addErrorMessage: function(field) {
    this.injectMessage(field.get('id'), field.retrieve('errorMessage'));
  },
    
  removeErrorMessage: function(field) {
    this.disposeMessage(field.get('id'));
  },
    
  /**
    *   Adds an error to the error list if it's not already injected.
    */
  injectMessage: function(identifier, text) {
    if(!this.list.getElement('li[regarding=' + identifier + ']')) {
      this.list.grab(new Element('li', {
        text: text,
        regarding: identifier
      }));
    }
  },
    
  /**
    *   Removes an error message from list if present.
    */
  disposeMessage: function(identifier) {
    var item = this.list.getElement('li[regarding=' + identifier + ']');
    if(item) item.dispose();
  },
    
  /**
    *   Moves error messages from the field's title property to storage.
    *   Injects the list.
    */
  prepareErrorList: function() {
    // clear title properties
    this.fields.each(function(field) {
      field.store('errorMessage', field.get('title'));
      field.set('title', ''); // clear
    });
        
    // inject list
    this.list = new Element('ul', {
      'class': 'error_list'
    }).inject(this.element, 'before');
  }
    
});