var _HForm = {};
_HForm.Form = function (arr_id) {
    function $id(id) {
        return (document.getElementById) ? document.getElementById(id) : document.all[id]
    };

    function $tn(e, c, r) {
        r = r || document;
        _e = r.getElementsByTagName(e);
        er = _e;
        if (c) {
            er = [];
            for (var i in _e) {
                if (c.test(_e.className)) er.push(_e[i])
            }
        };
        return er
    };

    function trim(v) {
        return v.replace(/(^\s+|\s+$)/, '').replace(/\s{2,}/g, ' ')
    };
    var _rae = false;
    this.raiseAllErrors = function (b) {
        _rae = !!b
    };
    var _fc = 'fieldset';
    this.setFieldContainer = function (e) {
        _fc = e
    };
    var _callback = null;
    this.addCallback = function (callback) {
        _callback = callback
    };
    this.reset = function () {
        resetError(this.form);
    };
    this.validate = function (f) {
        resetError(f);
        var v = true;
        var fld = $i(f);

        function notifyError(cnt, el) {
            if (v) {
                el.focus()
            };
            v = false;
            cnt.className += ' wrong';
        };
        for (i in fld) {
            if (isNaN(i)) continue;
            if (fld[i].el.value && !(/file/.test(fld[i].el.type))) fld[i].el.value = trim(fld[i].el.value);
            el = fld[i].el;
            re = fld[i].re;
            rq = fld[i].rq;
            var cnt = _getContainer(el);
            if (el.disabled) continue;
            if (/(text|password)/.test(el.type) && el.value == '' && !rq) continue;
            if ((/select/i.test(el.tagName) && rq && el.selectedIndex == 0) || (/(text|password)/.test(el.type) && !re.test(el.value)) || (/file/.test(el.type) && !el.changed) || (/checkbox/.test(el.type) && !el.checked)) {
                notifyError(cnt, el);
                if (!v && !_rae) break
            } else {
                try {
                    var fcallback = ('H_').concat(el.id.toString());
                    if (typeof(window[fcallback]) == 'function') {
                        if (!window[fcallback](el)) notifyError(cnt, el)
                    }
                } catch(e) {}
            }
        };
        return v
    };
    initialize(this, arr_id);

    function initialize(self, arr_id) {
        for (var i = 0; i < arr_id.length; i++) {
            setOnSubmitEvt(self, $id(arr_id[i]))
        }
    };

    function setOnSubmitEvt(self, f) {
        self.form = f;
        f.onsubmit = function () {
            if (!_callback) return self.validate(this);
            if (self.validate(this)) {
                return _callback()
            };
            return false
        };
        var is = $tn('input', '', f);
        for (var i = 0; i < is.length; i++) {
            if ((/file/.test(is[i].type)) && (/required/.test(is[i].accept))) {
                is[i].onkeypress = function () {
                    return false
                };
                if (! (/safari/i.test(navigator.userAgent))) {
                    is[i].onmousedown = function () {
                        return false
                    }
                };
                is[i].onchange = function () {
                    this.changed = 'changed'
                }
            }
        }
    };

    function $i(f) {
        var c = 0;
        var els = [];
        var e = $tn('*', '', f);
        for (i = 0; i < e.length; i++) {
            if (((e[i].accept) || (/requiredselect/.test(e[i].className))) && !(/disabled/.test(e[i].className))) {
                if (e[i].accept) {
                    els[c++] = {
                        el: e[i],
                        rq: (/required/.test(e[i].accept)),
                        re: _HForm.Regexp[trim(e[i].accept.toString().replace(/required/, ''))]
                    }
                } else {
                    els[c++] = {
                        el: e[i],
                        rq: true,
                        re: /.+/
                    }
                }
            }
        };
        return els
    };

    function _getContainer(el) {
        while (el.tagName.toLowerCase() != _fc) {
            el = el.parentNode;
        };
        return el
    };

    function resetError(cf) {
        var cnt = $tn(_fc, '', cf);
        for (var i = 0; i < cnt.length; i++) {
            cnt[i].className = cnt[i].className.replace(/wrong/, '')
        }
    }
}
