+ val_hash = document.load_val_hash(form, val_hash);
+ if (! val_hash) return;
+
+ var types = val_hash['group onevent'] || {submit:1};
+ if (typeof(types) == 'string') types = types.split(/\s*,\s*/);
+ if (typeof(types.length) != 'undefined') {
+ var t = {};
+ for (var i = 0; i < types.length; i++) t[types[i]] = 1;
+ types = t;
+ }
+ val_hash['group onevent'] = types;
+
+ if (types.change || types.blur) {
+ var clean = v_get_ordered_fields(val_hash);
+ if (clean.error) return clean.error;
+ var h = {};
+ _add = function (k, v) { if (! h[k]) h[k] = []; h[k].push(v) };
+ for (var i = 0; i < clean.fields.length; i++) {
+ _add(clean.fields[i].field, clean.fields[i]);
+ for (var j in clean.fields[i].deps) if (j != clean.fields[i].field) _add(j, clean.fields[i]);
+ }
+ for (var k in h) {
+ if (!h.hasOwnProperty(k)) continue;
+ var el = form[k];
+ if (! el) return v_error("No form element by the name "+k);
+ var _change = !types.change ? 0 : typeof(types.change) == 'object' ? types.change[k] : 1;
+ var _blur = !types.blur ? 0 : typeof(types.blur) == 'object' ? types.blur[k] : 1;
+ v_el_attach(el, h[k], form, val_hash, _change, _blur);
+ }
+ }
+
+ if (types.submit) {
+ var orig_submit = form.onsubmit || function () { return true };
+ form.onsubmit = function (e) { v_event = 'submit'; return document.validate(this) && orig_submit(e, this) };
+ }
+
+ if (types.load) { v_event = 'load'; document.validate(form) }
+}
+
+function v_el_attach (el, fvs, form, val_hash, _change, _blur) {
+ if (!_change && !_blur) return;
+ if (! el.type) {
+ if (el.length) for (var i = 0; i < el.length; i++) v_el_attach(el[i], fvs, form, val_hash, _change, _blur);
+ return;
+ }
+ var types = val_hash['group onevent'];
+ var func = function () {
+ v_event = 'change';
+ var e = [];
+ var f = {};
+ var chk = {};
+ for (var i = 0; i < fvs.length; i++) {
+ var field_val = fvs[i];
+ var k = field_val.field;
+ if (! chk[k]) {
+ chk[k] = 1;
+ val_hash['group was_checked'][k] = 1;
+ val_hash['group was_valid'][k] = 1;
+ val_hash['group had_error'][k] = 0;
+ }
+ var _e = v_validate_buddy(form, k, field_val, val_hash);
+ if (_e.length) {
+ val_hash['group had_error'][k] = 1;
+ val_hash['group was_valid'][k] = 0;
+ for (var j = 0; j < _e.length; j++) e.push(_e[j]);
+ }
+ f[field_val.delegate_error || field_val.field] = _e.length ? 0 : 1;
+ }
+ for (var k in f) if (f[k]) v_inline_error_clear(k, val_hash, form);
+ if (! e.length) return;
+ e = new ValidateError(e, {});
+ e = e.as_hash({as_hash_suffix:"", first_only:(val_hash['group first_only']?1:0)});
+ for (var k in e) {
+ if (!e.hasOwnProperty(k)) continue;
+ v_inline_error_set(k, e[k], val_hash, form);
+ }
+ };
+ if (_blur) el.onblur = func;
+ if (_change && ! (''+el).match(/HTMLCollection/)) { // find better way on opera
+ var type = el.type ? el.type.toLowerCase() : '';
+ if (type.match(/(password|text|textarea)/)) el.onkeyup = func;
+ else if (type.match(/(checkbox|radio)/)) el.onclick = func;
+ else if (type.match(/(select)/)) el.onchange = func;
+ }
+}