]> Dogcows Code - chaz/p5-CGI-Ex/blob - lib/CGI/Ex/validate.js
CGI::Ex 2.22
[chaz/p5-CGI-Ex] / lib / CGI / Ex / validate.js
1 // Copyright 2007 - Paul Seamons - $Revision: 1.62 $
2 // Distributed under the Perl Artistic License without warranty
3 // See perldoc CGI::Ex::Validate for usage
4
5 var v_did_inline = {};
6
7 function ValidateError (errors, extra) {
8 this.errors = errors;
9 this.extra = extra;
10 this.as_string = eob_as_string;
11 this.as_array = eob_as_array;
12 this.as_hash = eob_as_hash;
13 this.first_field = eob_first_field;
14 }
15
16 //
17
18 function v_error (err) { alert (err); return 1 }
19
20 function v_clean_val_hash (val_hash) {
21 if (typeof(val_hash) != 'object') return {error: v_error("Validation must be an associative array (hash)")};
22
23 var order = [];
24 for (var key in val_hash) {
25 if (key == 'extend') continue; // Protoype Array()
26 if (key.match(/^general\s/)) {
27 var new_key = key.replace(/^general\s+/, 'group ');
28 val_hash[new_key] = val_hash[key];
29 delete(val_hash[key]);
30 key = new_key;
31 }
32 order.push(key);
33 }
34 order = order.sort();
35
36 var f = val_hash['group set_hook'];
37 if (f && typeof(f) == 'string') val_hash['group set_hook'] = eval(f);
38 f = val_hash['group clear_hook'];
39 if (f && typeof(f) == 'string') val_hash['group clear_hook'] = eval(f);
40
41 var fields = val_hash['group fields'];
42 if (fields) {
43 if (typeof(fields) != 'object' || ! fields.length)
44 return {error:v_error("'group fields' must be a non-empty array")};
45 } else {
46 fields = [];
47 var _order = (val_hash['group order']) ? val_hash['group order'] : order;
48 if (typeof(_order) != 'object' || ! _order.length)
49 return {error:v_error("'group order' must be a non-empty array")};
50 for (var i = 0; i < _order.length; i++) {
51 var field = _order[i];
52 if (field.match(/^group\s/)) continue;
53 var field_val = val_hash[field];
54 if (! field_val) {
55 if (field == 'OR') field_val = 'OR';
56 else return {error:v_error('No element found in group for '+field)};
57 }
58 if (typeof(field_val) == 'object' && ! field_val['field']) field_val['field'] = field;
59 fields.push(field_val);
60 }
61 }
62
63 var found = {};
64 for (var i = 0; i < fields.length; i++) {
65 var field_val = fields[i];
66 var field = field_val.field;
67 if (! field) return {error:v_error("Missing field key in validation")};
68 found[field] = 1;
69 }
70
71 for (var i = 0; i < order.length; i++) {
72 var field = order[i];
73 if (found[field] || field.match(/^group\s/)) continue;
74 var field_val = val_hash[field];
75 if (typeof(field_val) != 'object' || field_val.length) {debug(val_hash);alert(field);return {error:v_error('Found a non-hash value on field '+field)};}
76 if (! field_val.field) field_val.field = field;
77 fields.push(field_val);
78 }
79
80 for (var i = 0; i < fields.length; i++) v_clean_field_val(fields[i]);
81
82 return {'fields':fields, 'order':order};
83 }
84
85 function v_clean_field_val (field_val) {
86 if (! field_val.order) field_val.order = v_field_order(field_val);
87 if (! field_val.deps) field_val.deps = {};
88 for (var i = 0; i < field_val.order.length; i++) {
89 var k = field_val.order[i];
90 var v = field_val[k];
91 if (typeof(v) == 'undefined') return {error:v_error('No matching validation found on field '+field+' for type '+k)};
92 if (k.match(/^(min|max)_in_set(\d*)$/)) {
93 if (typeof(v) == 'string') {
94 if (! (m = v.match(/^\s*(\d+)(?:\s*[oO][fF])?\s+(.+)\s*$/))) return {error:v_error("Invalid "+k+" check "+v)};
95 field_val[k] = m[2].split(/[\s,]+/);
96 field_val[k].unshift(m[1]);
97 }
98 for (var j = 1; j < field_val[k].length; j++) if (field_val[k][j] != field_val.field) field_val.deps[field_val[k][j]] = 1;
99 } else if (k.match(/^(enum|compare)\d*$/)) {
100 if (typeof(v) == 'string') field_val[k] = v.split(/\s*\|\|\s*/);
101 } else if (k.match(/^match\d*$/)) {
102 if (typeof(v) == 'string') v = field_val[k] = v.split(/\s*\|\|\s*/);
103 for (var j = 0; j < v.length; j++) {
104 if (typeof(v[j]) != 'string' || v[j] == '!') continue;
105 var m = v[j].match(/^\s*(!\s*|)m([^\s\w])(.*)\2([eigsmx]*)\s*$/);
106 if (! m) return {error:v_error("Not sure how to parse that match ("+v[j]+")")};
107 var not = m[1];
108 var pat = m[3];
109 var opt = m[4];
110 if (opt.indexOf('e') != -1) return {error:v_error("The e option cannot be used on field "+field_val.field+", test "+k)};
111 opt = opt.replace(/[sg]/g,'');
112 v[j] = new RegExp(pat, opt);
113 if (not) v.splice(j, 0, '!');
114 }
115 } else if (k.match(/^custom_js\d*$/)) {
116 if (typeof(v) == 'string' && v.match(/^\s*function\s*/)) field_val[k] = eval(v);
117 }
118 }
119 }
120
121 function v_validate (form, val_hash) {
122 var clean = v_clean_val_hash(val_hash);
123 if (clean.error) return;
124 var order = clean.order;
125 var fields = clean.fields;
126
127 var ERRORS = [];
128 var EXTRA = [];
129 var title = val_hash['group title'];
130 var validate_if = val_hash['group validate_if'];
131 if (validate_if && ! v_check_conditional(form, validate_if)) return;
132
133 var is_found = 1;
134 var errors = [];
135 var hold_error;
136
137 for (var j = 0; j < fields.length; j++) {
138 var ref = fields[j];
139 if (typeof(ref) != 'object' && ref == 'OR') {
140 if (is_found) j++;
141 is_found = 1;
142 continue;
143 }
144 is_found = 1;
145 if (! ref.field) return v_error("Missing field key during normal validation");
146 var err = v_validate_buddy(form, ref.field, ref);
147
148 if (err.length) {
149 if (j <= fields.length && typeof(fields[j + 1] != 'object') && fields[j + 1] == 'OR') {
150 hold_error = err;
151 } else {
152 if (hold_error) err = hold_error;
153 for (var k = 0; k < err.length; k++) errors.push(err[k]);
154 hold_error = '';
155 }
156 } else {
157 hold_error = '';
158 }
159 }
160
161 if (errors.length) {
162 if (title) ERRORS.push(title);
163 for (var j = 0; j < errors.length; j++) ERRORS.push(errors[j]);
164 }
165
166 var m;
167 for (var j = 0; j < order.length; j++) {
168 var field = order[j];
169 if (! (m = field.match(/^group\s+(\w+)$/))) continue;
170 if (errors.length == 0 || m[1].match(/^(field|order|title|validate_if)$/)) continue;
171 EXTRA[m[1]] = val_hash[field];
172 }
173
174 if (ERRORS.length) return new ValidateError(ERRORS, EXTRA);
175 return;
176 }
177
178 function v_check_conditional (form, ifs, N_level, ifs_match) {
179 if (! N_level) N_level = 0;
180 N_level++;
181
182 if (! ifs) return v_error("Need reference passed to check_conditional");
183 if (typeof(ifs) != 'object' || ! ifs.length) ifs = [ifs];
184
185 var is_found = 1;
186 var m;
187 for (var i = 0; i < ifs.length; i++) {
188 var ref = ifs[i];
189 if (typeof(ref) != 'object') {
190 if (ref == 'OR') {
191 if (is_found) i++;
192 is_found = 1;
193 continue;
194 } else {
195 var field = ref;
196 ref = {};
197 if (m = field.match(/^(\s*!\s*)/)) {
198 field = field.substring(m[1].length);
199 ref.max_in_set = [0, field];
200 } else {
201 ref.required = 1;
202 }
203 ref.field = field;
204 }
205 }
206 if (! is_found) break;
207
208 var field = ref.field;
209 if (! field) return v_error("Missing field key during validate_if");
210 field = field.replace(/\$(\d+)/g, function (all, N) {
211 return (typeof(ifs_match) != 'object' || typeof(ifs_match[N]) == 'undefined') ? '' : ifs_match[N];
212 });
213
214 v_clean_field_val(ref);
215 var err = v_validate_buddy(form, field, ref, N_level);
216 if (err.length) is_found = 0;
217 }
218 return is_found;
219 }
220
221 function v_filter_types (type, types) {
222 var values = [];
223 var regexp = new RegExp('^'+type+'_?\\d*$');
224 for (var i = 0; i < types.length; i++)
225 if (types[i].match(regexp)) values.push(types[i]);
226 return values;
227 }
228
229 function v_add_error (errors,field,type,field_val,ifs_match,form) {
230 errors.push([field, type, field_val, ifs_match]);
231 if (field_val.clear_on_error) {
232 var el = form[field];
233 if (el && el.type && el.type.match(/(hidden|password|text|textarea|submit)/)) el.value = '';
234 }
235 return errors;
236 }
237
238 function v_field_order (field_val) {
239 var o = [];
240 for (var k in field_val) if (! k.match(/^(extend|field|name)$/) && ! k.match(/_error$/)) o.push(k);
241 return o.sort();
242 }
243
244 function v_validate_buddy (form, field, field_val, N_level, ifs_match) {
245 var errors = [];
246 if (! N_level) N_level = 0;
247 if (++N_level > 10) { v_error("Max dependency level reached " + N_level); return errors }
248 if (! form.elements || field_val.exclude_js) return errors;
249 var types = field_val.order || v_field_order(field_val);
250
251 var m;
252 if (m = field.match(/^(!\s*|)m([^\s\w])(.*)\2([eigsmx]*)$/)) {
253 var not = m[1];
254 var pat = m[3];
255 var opt = m[4];
256 if (opt.indexOf('e') != -1) { v_error("The e option cannot be used on field "+field); return errors }
257 opt = opt.replace(/[sg]/g,'');
258 var reg = new RegExp(pat, opt);
259
260 for (var i = 0; i < form.elements.length; i++) {
261 var _field = form.elements[i].name;
262 if (! _field) continue;
263 if ( (not && ! (m = _field.match(reg))) || (m = _field.match(reg))) {
264 var err = v_validate_buddy(form, _field, field_val, N_level, m);
265 for (var j = 0; j < err.length; j++) errors.push(err[j]);
266 }
267 }
268 return errors;
269 }
270
271 var _value = v_get_form_value(form[field]);
272 var modified = 0;
273
274 if (typeof(field_val['default']) != 'undefined'
275 && (typeof(_value) == 'undefined'
276 || (typeof(_value) == 'object' && _value.length == 0)
277 || ! _value.length)) {
278 _value = field_val['default'];
279 modified = 1;
280 }
281
282 var values = (typeof(_value) == 'object') ? _value : [_value];
283 var n_values = (typeof(_value) == 'undefined') ? 0 : values.length;
284
285 for (var i = 0; i < values.length; i++) {
286 if (typeof(values[i]) == 'undefined') continue;
287 var orig = values[i];
288 if (! field_val.do_not_trim) values[i] = values[i].replace(/^\s+/,'').replace(/\s+$/,'');
289 if (field_val.trim_control_chars) values[i] = values[i].replace(/\t/g,' ').replace(/[\x00-\x1F]/g,'');
290 if (field_val.to_upper_case) values[i] = values[i].toUpperCase();
291 if (field_val.to_lower_case) values[i] = values[i].toLowerCase();
292
293 var tests = v_filter_types('replace', types);
294 for (var k = 0; k < tests.length; k++) {
295 var ref = field_val[tests[k]];
296 ref = (typeof(ref) == 'object') ? ref : ref.split(/\s*\|\|\s*/);
297 for (var j = 0; j < ref.length; j++) {
298 if (! (m = ref[j].match(/^\s*s([^\s\w])(.+)\1(.*)\1([eigmx]*)$/)))
299 return v_error("Not sure how to parse that replace "+ref[j]);
300 var pat = m[2];
301 var swap = m[3];
302 var opt = m[4];
303 if (opt.indexOf('e') != -1) { v_error("The e option cannot be used on field "+field+", replace "+tests[i]); return errors }
304 var regexp = new RegExp(pat, opt);
305 values[i] = values[i].replace(regexp, swap);
306 }
307 }
308
309 if (orig != values[i]) modified = 1;
310 }
311 if (modified && n_values == 1) {
312 var el = form[field];
313 if (el && el.type && el.type.match(/(hidden|password|text|textarea|submit)/)) el.value = values[0];
314 }
315
316 var needs_val = 0;
317 var n_vif = 0;
318 var tests = v_filter_types('validate_if', types);
319 for (var i = 0; i < tests.length; i++) {
320 n_vif++;
321 var ifs = field_val[tests[i]];
322 var ret = v_check_conditional(form, ifs, N_level, ifs_match);
323 if (ret) needs_val++;
324 }
325 if (! needs_val && n_vif) return errors;
326
327 var is_required = '';
328 var tests = v_filter_types('required', types);
329 for (var i = 0; i < tests.length; i++) {
330 if (! field_val[tests[i]] || field_val[tests[i]] == 0) continue;
331 is_required = tests[i];
332 break;
333 }
334 if (! is_required) {
335 var tests = v_filter_types('required_if', types);
336 for (var i = 0; i < tests.length; i++) {
337 var ifs = field_val[tests[i]];
338 if (! v_check_conditional(form, ifs, N_level, ifs_match)) continue;
339 is_required = tests[i];
340 break;
341 }
342 }
343 if (is_required) {
344 var found;
345 for (var i = 0; i < values.length; i++) {
346 if (values[i].length) {
347 found = 1;
348 break;
349 }
350 }
351 if (! found) return v_add_error(errors, field, is_required, field_val, ifs_match, form);
352 }
353
354 if (field_val.min_values && n_values < field_val.min_values)
355 return v_add_error(errors, field, 'min_values', field_val, ifs_match, form);
356
357 if (typeof(field_val.max_values) == 'undefined') field_val.max_values = 1;
358 if (field_val.max_values && n_values > field_val.max_values)
359 return v_add_error(errors, field, 'max_values', field_val, ifs_match, form);
360
361 for (var h = 0; h < 2 ; h++) {
362 var minmax = (h == 0) ? 'min' : 'max';
363 var tests = v_filter_types(minmax+'_in_set', types);
364 for (var i = 0; i < tests.length; i++) {
365 var a = field_val[tests[i]];
366 var n = a[0];
367 for (var k = 1; k < a.length; k++) {
368 var _value = v_get_form_value(form[a[k]]);
369 var _values;
370 if (typeof(_value) == 'undefined') continue;
371 _values = (typeof(_value) == 'object') ? _value : [_value];
372 for (var l = 0; l < _values.length; l++) {
373 var _value = _values[l];
374 if (typeof(_value) != 'undefined' && _value.length) n--;
375 }
376 }
377 if ( (minmax == 'min' && n > 0)
378 || (minmax == 'max' && n < 0)) {
379 v_add_error(errors, field, tests[i], field_val, ifs_match, form);
380 return errors;
381 }
382 }
383 }
384
385 for (var i = 0; i < types.length; i++) {
386 var type = types[i];
387 var _fv = field_val[type];
388 for (var n = 0; n < values.length; n++) {
389 var value = values[n];
390
391 if (type.match(/^enum\d*$/)) {
392 var is_found = 0;
393 for (var j = 0; j < _fv.length; j++) if (value == _fv[j]) { is_found = 1; break }
394 if (! is_found) v_add_error(errors, field, type, field_val, ifs_match, form);
395 }
396
397 if (type.match(/^equals\d*$/)) {
398 var not = _fv.match(/^!\s*/);
399 if (not) _fv = _fv.substring(not[0].length);
400 var success = 0;
401 if (m = _fv.match(/^([\"\'])(.*)\1$/)) {
402 if (value == m[2]) success = 1;
403 } else {
404 var value2 = v_get_form_value(form[_fv]);
405 if (typeof(value2) == 'undefined') value2 = '';
406 if (value == value2) success = 1;
407 }
408 if (not && success || ! not && ! success)
409 v_add_error(errors, field, type, field_val, ifs_match, form);
410 }
411
412 if (type == 'min_len' && value.length < _fv) v_add_error(errors, field, 'min_len', field_val, ifs_match, form);
413 if (type == 'max_len' && value.length > _fv) v_add_error(errors, field, 'max_len', field_val, ifs_match, form);
414
415 if (type.match(/^match\d*$/)) {
416 for (var j = 0; j < _fv.length; j++) {
417 if (typeof(_fv[j]) == 'string') continue;
418 var not = (j > 0 && typeof(_fv[j-1]) == 'string' && _fv[j-1] == '!') ? 1 : 0;
419 if ( ( not && value.match(_fv[j]))
420 || (! not && ! value.match(_fv[j]))) v_add_error(errors, field, type, field_val, ifs_match, form);
421 }
422 }
423
424 if (type.match(/^compare\d*$/)) {
425 for (var j = 0; j < _fv.length; j++) {
426 var comp = _fv[j];
427 if (! comp) continue;
428 var hold = false;
429 var copy = value;
430 if (m = comp.match(/^\s*(>|<|[><!=]=)\s*([\d\.\-]+)\s*$/)) {
431 if (! copy) copy = 0;
432 copy *= 1;
433 if (m[1] == '>' ) hold = (copy > m[2])
434 else if (m[1] == '<' ) hold = (copy < m[2])
435 else if (m[1] == '>=') hold = (copy >= m[2])
436 else if (m[1] == '<=') hold = (copy <= m[2])
437 else if (m[1] == '!=') hold = (copy != m[2])
438 else if (m[1] == '==') hold = (copy == m[2])
439 } else if (m = comp.match(/^\s*(eq|ne|gt|ge|lt|le)\s+(.+?)\s*$/)) {
440 if ( m[2].match(/^\"/)) m[2] = m[2].replace(/^"(.*)"$/,'$1');
441 else if (m[2].match(/^\'/)) m[2] = m[2].replace(/^'(.*)'$/,'$1');
442 if (m[1] == 'gt') hold = (copy > m[2])
443 else if (m[1] == 'lt') hold = (copy < m[2])
444 else if (m[1] == 'ge') hold = (copy >= m[2])
445 else if (m[1] == 'le') hold = (copy <= m[2])
446 else if (m[1] == 'ne') hold = (copy != m[2])
447 else if (m[1] == 'eq') hold = (copy == m[2])
448 } else {
449 v_error("Not sure how to compare \""+comp+"\"");
450 return errors;
451 }
452 if (! hold) v_add_error(errors, field, type, field_val, ifs_match, form);
453 }
454 }
455
456 if (type.match(/^type\d*$/))
457 if (! v_check_type(value, _fv, field, form))
458 v_add_error(errors, field, type, field_val, ifs_match, form);
459 }
460
461 // the js is evaluated and should return 1 for success
462 // or 0 for failure - the variables field, value, and field_val (the hash) are available
463 if (type.match(/^custom_js\d*$/)) {
464 var value = values.length == 1 ? values[0] : values;
465 if (typeof(_fv) == 'function'
466 ? ! _fv({'value':value, 'field_val':field_val, 'form':form, 'key':field_val.field})
467 : ! eval(_fv)) v_add_error(errors, field, type, field_val, ifs_match, form);
468 }
469 }
470
471 return errors;
472 }
473
474 function v_check_type (value, type, field, form) {
475 var m;
476 type = type.toUpperCase();
477
478 if (type == 'EMAIL') {
479 if (! value) return 0;
480 if (! (m = value.match(/^(.+)@(.+?)$/))) return 0;
481 if (m[1].length > 60) return 0;
482 if (m[2].length > 100) return 0;
483 if (! v_check_type(m[2],'DOMAIN') && ! v_check_type(m[2],'IP')) return 0;
484 if (! v_check_type(m[1],'LOCAL_PART')) return 0;
485
486 } else if (type == 'LOCAL_PART') {
487 if (typeof(value) == 'undefined' || ! value.length) return 0;
488 if (typeof(v_local_part) != 'undefined') return (value.match(v_local_part) ? 1 : 0);
489 if (value.match(/[^a-z0-9.\-!&+]/)) return 0;
490 if (value.match(/^[.\-]/)) return 0;
491 if (value.match(/[.\-&]$/)) return 0;
492 if (value.match(/(\.-|-\.|\.\.)/)) return 0;
493
494 } else if (type == 'IP') {
495 if (! value) return 0;
496 var dig = value.split(/\./);
497 if (dig.length != 4) return 0;
498 for (var i = 0; i < 4; i++)
499 if (typeof(dig[i]) == 'undefined' || dig[i].match(/\D/) || dig[i] > 255) return 0;
500
501 } else if (type == 'DOMAIN') {
502 if (! value) return 0;
503 if (! value.match(/^[a-z0-9.-]{4,255}$/)) return 0;
504 if (value.match(/^[.\-]/)) return 0;
505 if (value.match(/(\.-|-\.|\.\.)/)) return 0;
506 if (! (m = value.match(/\.([a-z]+)$/))) return 0;
507 value = value.substring(0,value.lastIndexOf('.'));
508 if (m[1] == 'name') {
509 if (! value.match(/^[a-z0-9][a-z0-9\-]{0,62}\.[a-z0-9][a-z0-9\-]{0,62}$/)) return 0;
510 } else
511 if (! value.match(/^([a-z0-9][a-z0-9\-]{0,62}\.)*[a-z0-9][a-z0-9\-]{0,62}$/)) return 0;
512
513 } else if (type == 'URL') {
514 if (! value) return 0;
515 if (! (m = value.match(/^https?:\/\/([^\/]+)/i))) return 0;
516 value = value.substring(m[0].length);
517 var dom = m[1].replace(/:\d+$/).replace(/\.$/);
518 if (! v_check_type(dom,'DOMAIN') && ! v_check_type(m[1],'IP')) return 0;
519 if (value && ! v_check_type(value,'URI')) return 0;
520
521 } else if (type == 'URI') {
522 if (! value) return 0;
523 if (value.match(/\s/)) return 0;
524
525 } else if (type == 'CC') {
526 if (! value) return 0;
527 if (value.match(/[^\d\- ]/)) return 0;
528 value = value.replace(/[\- ]/g, '');
529 if (value.length > 16 || value.length < 13) return 0;
530 // mod10
531 var sum = 0;
532 var swc = 0;
533 for (var i = value.length - 1; i >= 0; i--) {
534 if (++swc > 2) swc = 1;
535 var y = value.charAt(i) * swc;
536 if (y > 9) y -= 9;
537 sum += y;
538 }
539 if (sum % 10) return 0;
540 }
541
542 return 1;
543 }
544
545 function v_get_form_value (el) {
546 if (! el) return '';
547 if (el.disabled) return '';
548 var type = el.type ? el.type.toLowerCase() : '';
549 if (el.length && type != 'select-one') {
550 var a = [];
551 for (var j=0;j<el.length;j++) {
552 if (type.indexOf('multiple') != -1) {
553 if (el[j].selected) a.push(el[j].value);
554 } else {
555 if (el[j].checked) a.push(v_get_form_value(el[j]));
556 }
557 }
558 if (a.length == 0) return '';
559 if (a.length == 1) return a[0];
560 return a;
561 }
562 if (! type) return '';
563 if (type.match(/(hidden|password|text|textarea|submit)/)) return el.value;
564 if (type.indexOf('select') != -1) {
565 if (! el.length) return '';
566 return el[el.selectedIndex].value;
567 }
568 if (type == 'checkbox' || type == 'radio') return el.checked ? el.value : '';
569 if (type == 'file') return el.value;
570
571 alert('Unknown form type for '+el.name+': '+type);
572 return '';
573 }
574
575 function v_find_val () {
576 var key = arguments[0];
577 for (var i = 1; i < arguments.length; i++) {
578 if (typeof(arguments[i]) == 'string') return arguments[i];
579 if (typeof(arguments[i]) == 'undefined') continue;
580 if (typeof(arguments[i][key]) != 'undefined') return arguments[i][key];
581 }
582 return '';
583 }
584
585 function v_get_error_text (err, extra1, extra2) {
586 var field = err[0];
587 var type = err[1];
588 var field_val = err[2];
589 var ifs_match = err[3];
590 var m;
591
592 var dig = (m = type.match(/(_?\d+)$/)) ? m[1] : '';
593 var type_lc = type.toLowerCase();
594 var v = field_val[type + dig];
595
596 if (field_val.delegate_error) {
597 field = field_val.delegate_error;
598 field = field.replace(/\$(\d+)/g, function (all, N) {
599 if (typeof(ifs_match) != 'object'
600 || typeof(ifs_match[N]) == 'undefined') return ''
601 return ifs_match[N];
602 });
603 }
604
605 var name = field_val.name || "The field " +field;
606 name = name.replace(/\$(\d+)/g, function (all, N) {
607 if (typeof(ifs_match) != 'object'
608 || typeof(ifs_match[N]) == 'undefined') return ''
609 return ifs_match[N];
610 });
611
612 var msg = v_find_val(type + '_error', extra1, extra2);
613 if (! msg) {
614 if (dig.length) msg = field_val[type + dig + '_error'];
615 if (! msg) msg = field_val[type + '_error'];
616 }
617 if (msg) {
618 msg = msg.replace(/\$(\d+)/g, function (all, N) {
619 if (typeof(ifs_match) != 'object' || typeof(ifs_match[N]) == 'undefined') return '';
620 return ifs_match[N];
621 });
622 msg = msg.replace(/\$field/g, field);
623 msg = msg.replace(/\$name/g, name);
624 if (v && typeof(v) == 'string') msg = msg.replace(/\$value/g, v);
625 return msg;
626 }
627
628 if (type == 'equals') {
629 var field2 = field_val["equals" + dig];
630 var name2 = field_val["equals" +dig+ "_name"];
631 if (! name2) name2 = "the field " +field2;
632 name2 = name2.replace(/\$(\d+)/g, function (all, N) {
633 return (typeof(ifs_match) != 'object' || typeof(ifs_match[N]) == 'undefined') ? '' : ifs_match[N];
634 });
635 return name + " did not equal " + name2 +".";
636 }
637 if (type == 'min_in_set') return "Not enough fields were chosen from the set ("+v[0]+' of '+v.join(", ").replace(/^\d+,\s*/,'')+")";
638 if (type == 'max_in_set') return "Too many fields were chosen from the set (" +v[0]+' of '+v.join(", ").replace(/^\d+,\s*/,'')+")";
639
640 return name + (
641 (type == 'required' || type == 'required_if') ? " is required."
642 : type == 'match' ? " contains invalid characters."
643 : type == 'compare' ? " did not fit comparison."
644 : type == 'custom_js' ? " did not match custom_js"+dig+" check."
645 : type == 'enum' ? " is not in the given list."
646 : type == 'min_values' ? " had less than "+v+" value"+(v == 1 ? '' : 's')+"."
647 : type == 'max_values' ? " had more than "+v+" value"+(v == 1 ? '' : 's')+"."
648 : type == 'min_len' ? " was less than "+v+" character"+(v == 1 ? '' : 's')+"."
649 : type == 'max_len' ? " was more than "+v+" character"+(v == 1 ? '' : 's')+"."
650 : type == 'type' ? " did not match type "+v+"."
651 : alert("Missing error on field "+field+" for type "+type+dig));
652 }
653
654 //
655
656 function eob_as_string (extra) {
657 var joiner = v_find_val('as_string_join', extra, this.extra, '\n');
658 var header = v_find_val('as_string_header', extra, this.extra, '');
659 var footer = v_find_val('as_string_footer', extra, this.extra, '');
660 return header + this.as_array(extra).join(joiner) + footer;
661 }
662
663 function eob_as_array (extra) {
664 var errors = this.errors;
665 var title = v_find_val('as_array_title', extra, this.extra, 'Please correct the following items:');
666
667 var has_headings;
668 if (title) has_headings = 1;
669 else for (var i = 0; i < errors.length; i++) if (typeof(errors[i]) == 'string') has_headings = 1;
670
671 var prefix = v_find_val('as_array_prefix', extra, this.extra, (has_headings ? ' ' : ''));
672
673 var arr = [];
674 if (title && title.length) arr.push(title);
675
676 var found = {};
677 for (var i = 0; i < errors.length; i++) {
678 if (typeof(errors[i]) == 'string') {
679 arr.push(errors[i]);
680 found = {};
681 } else {
682 var text = v_get_error_text(errors[i], extra, this.extra);
683 if (found[text]) continue;
684 found[text] = 1;
685 arr.push(prefix + text);
686 }
687 }
688
689 return arr;
690 }
691
692 function eob_as_hash (extra) {
693 var errors = this.errors;
694 var suffix = v_find_val('as_hash_suffix', extra, this.extra, '_error');
695 var joiner = v_find_val('as_hash_join', extra, this.extra, '<br/>');
696
697 var found = {};
698 var ret = {};
699 for (var i = 0; i < errors.length; i++) {
700 if (typeof(errors[i]) == 'string') continue;
701 if (! errors[i].length) continue;
702
703 var field = errors[i][0];
704 var type = errors[i][1];
705 var field_val = errors[i][2];
706 var ifs_match = errors[i][3];
707
708 if (! field) return alert("Missing field name");
709 if (field_val['delegate_error']) {
710 field = field_val['delegate_error'];
711 field = field.replace(/\$(\d+)/g, function (all, N) {
712 if (typeof(ifs_match) != 'object'
713 || typeof(ifs_match[N]) == 'undefined') return ''
714 return ifs_match[N];
715 });
716 }
717
718 var text = v_get_error_text(errors[i], extra, this.extra);
719 if (! found[field]) found[field] = {};
720 if (found[field][text]) continue;
721 found[field][text] = 1;
722
723 field += suffix;
724 if (! ret[field]) ret[field] = [];
725 ret[field].push(text);
726 }
727
728 if (joiner) {
729 var header = v_find_val('as_hash_header', extra, this.extra, '');
730 var footer = v_find_val('as_hash_footer', extra, this.extra, '');
731 for (var key in ret) {
732 if (key == 'extend') continue; // Protoype Array()
733 ret[key] = header + ret[key].join(joiner) + footer;
734 }
735 }
736
737 return ret;
738 }
739
740 function eob_first_field () {
741 for (var i = 0; i < this.errors.length; i++) {
742 if (typeof(this.errors[i]) != 'object') continue;
743 if (! this.errors[i][0]) continue;
744 return this.errors[i][0];
745 }
746 return;
747 }
748
749 //
750
751 document.validate = function (form, val_hash) {
752 val_hash = document.load_val_hash(form, val_hash);
753 if (typeof(val_hash) == 'undefined') return true;
754
755 for (var key in v_did_inline) {
756 if (key == 'extend') continue; // Protoype Array()
757 v_inline_error_clear(key, val_hash, form);
758 }
759
760 var err_obj = v_validate(form, val_hash);
761 if (! err_obj) return true;
762
763 var field = err_obj.first_field();
764 if (field && form[field]) {
765 if (form[field].focus) form[field].focus();
766 else if (form[field].length && form[field][0].focus) form[field][0].focus();
767 }
768
769 if (! val_hash['group no_inline']) {
770 var hash = err_obj.as_hash({as_hash_suffix:""});
771 for (var key in hash) {
772 if (key == 'extend') continue; // Protoype Array()
773 v_inline_error_set(key, hash[key], val_hash, form);
774 }
775 }
776
777 if (! val_hash['group no_confirm']) {
778 return confirm(err_obj.as_string()) ? false : true;
779 } else if (! val_hash['group no_alert']) {
780 alert(err_obj.as_string());
781 return false;
782 } else if (! val_hash['group no_inline']) {
783 return false;
784 } else {
785 return true;
786 }
787 }
788
789 document.load_val_hash = function (form, val_hash) {
790 if (! form) return alert('Missing form or form name');
791 if (typeof(form) == 'string') {
792 if (! document[form]) return alert('No form by name '+form);
793 form = document[form];
794 }
795
796 if (form.val_hash) return form.val_hash;
797
798 if (typeof(val_hash) != 'object') {
799 if (typeof(val_hash) == 'function') {
800 val_hash = val_hash(formname);
801 } else if (typeof(val_hash) == 'undefined') {
802 var el;
803 if (typeof(document.validation) != 'undefined') {
804 val_hash = document.validation;
805 } else if (el = document.getElementById('validation')) {
806 val_hash = el.innerHTML.replace(/&lt;/ig,'<').replace(/&gt;/ig,'>').replace(/&amp;/ig,'&');
807 } else {
808 var order = [];
809 var str = '';
810 var yaml = form.getAttribute('validation');
811 if (yaml) {
812 if (m = yaml.match(/^( +)/)) yaml = yaml.replace(new RegExp('^'+m[1], 'g'), '');
813 yaml = yaml.replace(/\s*$/,'\n');
814 str += yaml;
815 }
816 var m;
817 for (var i = 0; i < form.elements.length; i++) {
818 var name = form.elements[i].name;
819 var yaml = form.elements[i].getAttribute('validation');
820 if (! name || ! yaml) continue;
821 yaml = yaml.replace(/\s*$/,'\n').replace(/^(.)/mg,' $1').replace(/^( *[^\s&*\[\{])/,'\n$1');
822 str += name +':' + yaml;
823 order.push(name);
824 }
825 if (str) val_hash = str + "group order: [" + order.join(', ') + "]\n";
826 }
827 }
828 if (typeof(val_hash) == 'string') {
829 if (! document.yaml_load) return;
830 document.hide_yaml_errors = (! document.show_yaml_errors);
831 if (location.search && location.search.indexOf('show_yaml_errors') != -1)
832 document.hide_yaml_errors = 0;
833 val_hash = document.yaml_load(val_hash);
834 if (document.yaml_error_occured) return;
835 val_hash = val_hash[0];
836 }
837 }
838
839 form.val_hash = val_hash;
840 return form.val_hash;
841 }
842
843 document.check_form = function (form, val_hash) {
844 if (! form) return alert('Missing form or form name');
845 if (typeof(form) == 'string') {
846 if (! document[form]) return alert('No form by name '+form);
847 form = document[form];
848 }
849
850 val_hash = document.load_val_hash(form, val_hash);
851 if (! val_hash) return;
852
853 var types = val_hash['group onevent'] || {submit:1};
854 if (typeof(types) == 'string') types = types.split(/\s*,\s*/);
855 if (typeof(types.length) != 'undefined') {
856 var t = {};
857 for (var i = 0; i < types.length; i++) t[types[i]] = 1;
858 types = t;
859 }
860 val_hash['group onevent'] = types;
861
862 if (types.change || types.blur) {
863 var clean = v_clean_val_hash(val_hash);
864 if (clean.error) return clean.error;
865 var h = {};
866 _add = function (k, v) { if (! h[k]) h[k] = []; h[k].push(v) };
867 for (var i = 0; i < clean.fields.length; i++) {
868 _add(clean.fields[i].field, clean.fields[i]);
869 for (var j in clean.fields[i].deps) if (j != clean.fields[i].field) _add(j, clean.fields[i]);
870 }
871 for (var k in h) {
872 if (k == 'extend') continue; // Protoype Array()
873 var el = form[k];
874 if (! el) return v_error("No form element by the name "+k);
875 v_el_attach(el, h[k], form, val_hash);
876 }
877 }
878
879 if (types.submit) {
880 var orig_submit = form.onsubmit || function () { return true };
881 form.onsubmit = function (e) { return document.validate(this) && orig_submit(e, this) };
882 }
883 }
884
885 function v_el_attach (el, fvs, form, val_hash) {
886 if (! el.type) {
887 if (el.length) for (var i = 0; i < el.length; i++) v_el_attach(el[i], fvs, form, val_hash);
888 return;
889 }
890 var types = val_hash['group onevent'];
891 var func = function () {
892 var e = [];
893 var f = {};
894 for (var i = 0; i < fvs.length; i++) {
895 var field_val = fvs[i];
896 var _e = v_validate_buddy(form, field_val.field, field_val);
897 for (var j = 0; j < _e.length; j++) e.push(_e[j]);
898 f[field_val.delegate_error || field_val.field] = 1;
899 }
900 if (! e.length) {
901 for (var k in f) v_inline_error_clear(k, val_hash, form);
902 return;
903 }
904 e = new ValidateError(e, {});
905 e = e.as_hash({as_hash_suffix:"", first_only:(val_hash['group first_only']?1:0)});
906 for (var k in e) {
907 if (k == 'extend') continue; // Protoype Array()
908 v_inline_error_set(k, e[k], val_hash, form);
909 }
910 };
911 if (types.blur) el.onblur = func;
912 if (types.change) {
913 if (el.type.match(/(password|text|textarea)/)) el.onkeyup = func;
914 else if (el.type.match(/(checkbox|radio)/)) el.onclick = func;
915 else if (el.type.match(/(select)/)) el.onchange = func;
916 }
917 }
918
919 function v_inline_error_clear (key, val_hash, form) {
920 delete(v_did_inline[key]);
921 var f = val_hash['group clear_hook'] || document.validate_clear_hook;
922 if (typeof(f) == 'function') if (f(key, val_hash, form)) return 1;
923 var el = document.getElementById(key + v_find_val('as_hash_suffix', val_hash, '_error'));
924 if (el) el.innerHTML = '';
925 }
926
927 function v_inline_error_set (key, val, val_hash, form) {
928 v_did_inline[key] = 1;
929 var f = val_hash['group set_hook'] || document.validate_set_hook;
930 if (typeof(f) == 'function') if(f(key, val, val_hash, form)) return 1;
931 var el = document.getElementById(key + v_find_val('as_hash_suffix', val_hash, '_error'));
932 if (el) el.innerHTML = val;
933 }
This page took 0.104225 seconds and 4 git commands to generate.