/**
 * @namespace GA_project
 * @sdoc ga.sdoc
 * @id GA.validateClass
 */
GA.validateClass = function(formID, oElemetsParamsOfValidate, errorClass){
  var i, o,
  b = Number(arguments.length > 2),
  s = '(?:\\s|^)'+arguments[1+b]+'(\\s|$)';
  function validateParams(obj) {
    var i;
    for (i in obj) {
      this[i] = obj[i]
    }
  };
  validateParams.prototype = {
    'pattern': false,
    'maxLength': false,
    'minLength': false,
    'max': false,
    'min': false,
    'test': function(sValue) {
      var i , o;
      if ((o = this.pattern) && !o[0].test(sValue)) {
        this.errorText = o[1];
        return false
      } else if ((o = this.maxLength) && o[0] < sValue.length) {
        this.errorText = o[1];
        return false
      } else if ((o = this.minLength) && o[0] > sValue.length) {
        this.errorText = o[1];
        return false
      } else if ((o = this.max) && o[0] < Number(sValue)) {
        this.errorText = o[1];
        return false
      } else if ((o = this.min) && o[0] > Number(sValue)) {
        this.errorText = o[1];
        return false
      }
      return true
    }
  };
  this.oElemetsParamsOfValidate = {};
  o = arguments[0+b];
  for (i in o) {
    if (o[i].constructor == Array) {
      this.oElemetsParamsOfValidate[i]= new validateParams({'pattern': o[i]})
    } else {
      this.oElemetsParamsOfValidate[i] = new validateParams(o[i])
    }
  }
  this.errorClass = arguments[1+b];
  this.formID = b? formID: '';
  this.regExpErrClass = new RegExp(s);
  if (typeof this.regExpErrClass.compile != 'undefined') {
    this.regExpErrClass.compile(s)
  }
  //как только полностью построится дерево документа,
  //подключим обработчики на все формы.
  if (document.addEventListener) {
    e = (function(obj) {
      var closure = function() {
        var f = document.forms, i = f.length;
        document.removeEventListener('DOMContentLoaded', closure, false);
        document.removeEventListener('load', closure, false);
        while (i--) {
          if ( !obj.formID || (f[i].id == obj.formID || f[i].name == obj.formID) ) {
            obj.addWathingForm(f[i])
          }
        }
      }
      return closure
    })(this);
    document.addEventListener('DOMContentLoaded', e, false);
    document.addEventListener('load', e, false)
  } else if (document.attachEvent && !window.opera) {
    document.attachEvent('onpropertychange', (function (obj) {
      var closure = function() {
        var f = document.forms, i = f.length;
        if (event.propertyName == 'activeElement' && document.activeElement) {
          document.detachEvent('onpropertychange', closure);
          while (i--) {
            if ( !obj.formID || (f[i].id == obj.formID || f[i].name == obj.formID) ) {
              obj.addWathingForm(f[i])
            }
          }
        }
      }
      return closure;
    })(this))
  }
}
GA.validateClass.prototype = {
  'addWathingForm': (document.attachEvent && !window.opera)?
    function(oForm) {
      var k;
      this.methodIntoEventProcessing('onFieldFocus', 'focus', oForm);
      this.methodIntoEventProcessing('onSubmit', 'submit', oForm);
      //подключаем_к_событиям_обработчики, проверяющие_значения_в_полях_ввода.
      for(k in this.oElemetsParamsOfValidate) {
        typeof oForm[k] != 'undefined' &&
        this.methodIntoEventProcessing('toggleErrorClass', 'propertychange', oForm[k])
      }
    }:
    function(oForm) {
      var k, evs = {'input': 0, 'keydown':0, 'change':0};
      this.methodIntoEventProcessing('onFieldFocus', 'focus', oForm);
      this.methodIntoEventProcessing('onSubmit', 'submit', oForm);
      //подключаем_к_событиям_обработчики, проверяющие_значения_в_полях_ввода.
      for (k in evs) {
        this.methodIntoEventProcessing('toggleErrorClass', k, oForm)
      }
    },
  'shake': function(node) {
    var n = 6;
    //node.style.position = 'relative'; - глюки.
    (
      function closureFunc() {
        if (--n) {
          if (n % 2) {
            node.style.left = '-1px'
          } else {
            node.style.left = '1px'
          }
          window.setTimeout(closureFunc, 100 / (n+1))
        } else {
          node.style.left = '';
        }
      }
    )()
  },
  'toggleErrorClass': function(node, pos, e) {
    var b = this.regExpErrClass.test(node.className),
    o = this.oElemetsParamsOfValidate[node.getAttribute('name')] || false;
    if (
      typeof node.value == 'undefined' ||
      !o ||
      (e.type == 'propertychange' && e.propertyName != 'value') ||
      node.form.haveStopSubmit
    ) return;
    if ( node.value === '' || o.test(node.value) ) {
      b && (node.className = node.className.replace(this.regExpErrClass, '$1'))
    } else if (!b) {
      node.className += ' '+this.errorClass;
      this.shake(node)
    }
    return
  },
  'onFieldFocus': function(oNode, pos, e) {
    var o = this.oElemetsParamsOfValidate[oNode.getAttribute('name')] || false;
    if (!o) return
    if (typeof oNode[eName].scrollIntoView != 'undefined') {
      oNode[eName].scrollIntoView()
    }
  },
  'onSubmit': function(node, pos, e) {
    var o = this.oElemetsParamsOfValidate;
    if (node.nodeName != 'FORM') return;
    for (var eName in o) {
      if (!o[eName].test(node[eName].value)){;
        node.haveStopSubmit = true;
        this.regExpErrClass.test(node[eName].className) || (
          node[eName].className += ' '+this.errorClass
        );
        node[eName].focus();
        node[eName].select();
        this.shake(node[eName]);
        alert(o[eName].errorText);
        node.haveStopSubmit = false;
        return false
      }
    }
    return
  }
};
GA.validateClass.prototype.methodIntoEventProcessing = GA.eventWatcherClass.prototype.methodIntoEventProcessing;
