]>
Dogcows Code - chaz/p5-CGI-Ex/blob - lib/CGI/Ex/validate.js
1 /**----------------------------------------------------------------***
2 * Copyright 2007 - Paul Seamons *
3 * Distributed under the Perl Artistic License without warranty *
4 * Based upon CGI/Ex/Validate.pm v1.14 from Perl *
5 * For instructions on usage, see perldoc of CGI::Ex::Validate *
6 ***----------------------------------------------------------------**/
10 this.error
= vob_error
;
11 this.validate
= vob_validate
;
12 this.check_conditional
= vob_check_conditional
;
13 this.filter_types
= vob_filter_types
;
14 this.add_error
= vob_add_error
;
15 this.validate_buddy
= vob_validate_buddy
;
16 this.check_type
= vob_check_type
;
17 this.get_form_value
= vob_get_form_value
;
20 function ValidateError (errors
, extra
) {
24 this.as_string
= eob_as_string
;
25 this.as_array
= eob_as_array
;
26 this.as_hash
= eob_as_hash
;
27 this.get_error_text
= eob_get_error_text
;
28 this.first_field
= eob_first_field
;
31 ///----------------------------------------------------------------///
33 function vob_error (err
) {
37 function vob_validate (form
, val_hash
) {
38 if (typeof(val_hash
) == 'string') {
39 if (! document
.yaml_load
)
40 return this.error("Cannot parse yaml string - document.yaml_load is not loaded");
41 val_hash
= document
.yaml_load(val_hash
);
44 var ERRORS
= new Array ();
45 var EXTRA
= new Array ();
46 // var USED_GROUPS = new Array();
48 // distinguishing between associative and index based arrays is harder than in perl
49 if (! val_hash
.length
) val_hash
= new Array(val_hash
);
50 for (var i
= 0; i
< val_hash
.length
; i
++) {
51 var group_val
= val_hash
[i
];
52 if (typeof(group_val
) != 'object' || group_val
.length
) return this.error("Validation groups must be a hash");
53 var title
= group_val
['group title'];
54 var validate_if
= group_val
['group validate_if'];
56 if (validate_if
&& ! this.check_conditional(form
, validate_if
)) continue;
57 // USED_GROUPS.push(group_val);
59 /// if the validation items were not passed as an arrayref
60 /// look for a group order and then fail back to the keys of the group
61 var fields
= group_val
['group fields'];
62 var order
= new Array();
63 for (var key
in group_val
) {
64 if (key
== 'extend') continue; // Protoype Array() fix
65 order
[order
.length
] = key
;
69 if (typeof(fields
) != 'object' || ! fields
.length
)
70 return this.error("'group fields' must be a non-empty array");
73 var _order
= (group_val
['group order']) ? group_val
['group order'] : order
;
74 if (typeof(_order
) != 'object' || ! _order
.length
)
75 return this.error("'group order' must be a non-empty array");
76 for (var j
= 0; j
< _order
.length
; j
++) {
77 var field
= _order
[j
];
78 if (field
.match('^(group|general)\\s')) continue;
79 var field_val
= group_val
[field
];
81 if (field
== 'OR') field_val
= 'OR';
82 else return this.error('No element found in group for '+field
);
84 if (typeof(field_val
) == 'object' && ! field_val
['field']) field_val
['field'] = field
;
85 fields
[fields
.length
] = field_val
;
89 /// check which fields have been used
90 var found
= new Array();
91 for (var j
= 0; j
< fields
.length
; j
++) {
92 var field_val
= fields
[j
];
93 var field
= field_val
['field'];
94 if (! field
) return this.error("Missing field key in validation");
95 // if (found[field]) return this.error('Duplicate order found for '+field+' in group order or fields');
99 /// add any remaining fields from the order
100 for (var j
= 0; j
< order
.length
; j
++) {
101 var field
= order
[j
];
102 if (found
[field
] || field
.match('^(group|general)\\s')) continue;
103 var field_val
= group_val
[field
];
104 if (typeof(field_val
) != 'object' || field_val
.length
) return this.error('Found a non-hash value on field '+field
);
105 if (! field_val
['field']) field_val
['field'] = field
;
106 fields
[fields
.length
] = field_val
;
109 /// now lets do the validation
111 var errors
= new Array();
114 for (var j
= 0; j
< fields
.length
; j
++) {
116 if (typeof(ref
) != 'object' && ref
== 'OR') {
122 if (! ref
['field']) return this.error("Missing field key during normal validation");
123 var err
= this.validate_buddy(form
, ref
['field'], ref
);
125 /// test the error - if errors occur allow for OR - if OR fails use errors from first fail
127 if (j
<= fields
.length
&& typeof(fields
[j
+ 1] != 'object') && fields
[j
+ 1] == 'OR') {
130 if (hold_error
) err
= hold_error
;
131 for (var k
= 0; k
< err
.length
; k
++) errors
[errors
.length
] = err
[k
];
139 /// add on errors as requested
141 if (title
) ERRORS
[ERRORS
.length
] = title
;
142 for (var j
= 0; j
< errors
.length
; j
++) ERRORS
[ERRORS
.length
] = errors
[j
];
145 /// add on general options, and group options if errors in group occurred
147 for (var j
= 0; j
< order
.length
; j
++) {
148 var field
= order
[j
];
149 if (! (m
= field
.match('^(general|group)\\s+(\\w+)$'))) continue;
150 if (m
[1] == 'group' && (errors
.length
== 0 || m
[2].match('^(field|order|title)$'))) continue;
151 EXTRA
[m
[2]] = group_val
[field
];
155 /// store any extra items from self
156 for (var key
in this) {
157 if (key
== 'extend') continue; // Protoype Array() fix
158 if (! key
.match('_error$')
159 && ! key
.match('^(raise_error|as_hash_\\w+|as_array_\\w+|as_string_\\w+)$')) continue;
160 EXTRA
[key
] = this[key
];
163 /// allow for checking for unused keys
164 // if (EXTRA['no_extra_fields'])
165 // won't do anything about this for now - let the server handle it
167 /// return what they want
168 if (ERRORS
.length
) return new ValidateError(ERRORS
, EXTRA
);
173 /// allow for optional validation on groups and on individual items
174 function vob_check_conditional (form
, ifs
, N_level
, ifs_match
) {
176 if (! N_level
) N_level
= 0;
179 /// can pass a single hash - or an array ref of hashes
181 return this.error("Need reference passed to check_conditional");
182 } else if (typeof(ifs
) != 'object') {
183 ifs
= new Array(ifs
);
184 } else if (! ifs
.length
) { // turn hash into array of hash
185 ifs
= new Array(ifs
);
188 /// run the if options here
189 /// multiple items can be passed - all are required unless OR is used to separate
192 for (var i
= 0; i
< ifs
.length
; i
++) {
194 if (typeof(ref
) != 'object') {
202 if (m
= field
.match('^(\\s*!\\s*)')) {
203 field
= field
.substring(m
[1].length
);
204 ref
['max_in_set'] = '0 of ' + field
;
208 ref
['field'] = field
;
211 if (! is_found
) break;
213 /// get the field - allow for custom variables based upon a match
214 var field
= ref
['field'];
215 if (! field
) return this.error("Missing field key during validate_if");
216 field
= field
.replace(new RegExp('\\$(\\d+)','g'), function (all
, N
) {
217 if (typeof(ifs_match
) != 'object'
218 || typeof(ifs_match
[N
]) == 'undefined') return ''
222 var err
= this.validate_buddy(form
, field
, ref
, N_level
);
223 if (err
.length
) is_found
= 0;
228 function vob_filter_types (type
, types
) {
229 var values
= new Array();
230 var regexp
= new RegExp('^'+type
+'_?\\d*$');
231 for (var i
= 0; i
< types
.length
; i
++)
232 if (types
[i
].match(regexp
)) values
[values
.length
] = types
[i
];
236 function vob_add_error (errors
,field
,type
,field_val
,ifs_match
,form
) {
237 errors
[errors
.length
] = new Array(field
, type
, field_val
, ifs_match
);
238 if (field_val
['clear_on_error']) {
239 var el
= form
[field
];
242 if (type
&& (type
== 'hidden' || type
== 'password' || type
== 'text' || type
== 'textarea' || type
== 'submit'))
248 /// this is where the main checking goes on
249 function vob_validate_buddy (form
, field
, field_val
, N_level
, ifs_match
) {
250 if (! N_level
) N_level
= 0;
251 if (++ N_level
> 10) return this.error("Max dependency level reached " + N_level
);
252 if (! form
.elements
) return;
254 var errors
= new Array();
255 var types
= new Array();
256 for (var key
in field_val
) {
257 if (key
== 'extend') continue; // Protoype Array() fix
258 types
[types
.length
] = key
;
260 types
= types
.sort();
262 /// allow for not running some tests in the cgi
263 if (this.filter_types('exclude_js', types
).length
) return errors
;
265 /// allow for field names that contain regular expressions
267 if (m
= field
.match('^(!\\s*|)m([^\\s\\w])(.*)\\2([eigsmx]*)$')) {
271 if (opt
.indexOf('e') != -1) return this.error("The e option cannot be used on field "+field
);
272 opt
= opt
.replace(new RegExp('[sg]','g'),'');
273 var reg
= new RegExp(pat
, opt
);
275 var keys
= new Array();
276 for (var i
= 0; i
< form
.elements
.length
; i
++) {
277 var _field
= form
.elements
[i
].name
;
278 if (! _field
) continue;
279 if ( (not
&& ! (m
= _field
.match(reg
))) || (m
= _field
.match(reg
))) {
280 var err
= this.validate_buddy(form
, _field
, field_val
, N_level
, m
);
281 for (var j
= 0; j
< err
.length
; j
++) errors
[errors
.length
] = err
[j
];
287 var _value
= this.get_form_value(form
[field
]);
289 if (typeof(_value
) == 'object') {
292 values
= new Array();
293 values
[values
.length
] = _value
;
295 var n_values
= (typeof(_value
) == 'undefined') ? 0 : values
.length
;
297 /// allow for default value
298 var tests
= this.filter_types('default', types
);
299 if (n_values
== 0 || (n_values
== 1 && values
[0].length
== 0)) {
300 for (var i
= 0; i
< tests
.length
; i
++) {
301 var el
= form
[field
];
304 if (type
&& (type
== 'hidden' || type
== 'password' || type
== 'text' || type
== 'textarea' || type
== 'submit'))
305 el
.value
= values
[0] = '' + field_val
[tests
[i
]];
309 /// allow for a few form modifiers
311 for (var i
= 0; i
< values
.length
; i
++) {
312 if (typeof(values
[i
]) == 'undefined') continue;
313 if (! this.filter_types('do_not_trim',types
).length
)
314 values
[i
] = values
[i
].replace('^\\s+','').replace(new RegExp('\\s+$',''),'');
315 if (this.filter_types('trim_control_chars',types
).length
)
316 values
[i
] = values
[i
].replace(new RegExp('\t', 'g'),' ').replace(new RegExp('[\\x00-\\x1F]+','g'),'');
317 if (this.filter_types('to_upper_case',types
).length
) {
318 values
[i
] = values
[i
].toUpperCase();
319 } else if (this.filter_types('to_lower_case',types
).length
) {
320 values
[i
] = values
[i
].toLowerCase();
323 var tests
= this.filter_types('replace', types
);
324 for (var i
= 0; i
< tests
.length
; i
++) {
325 var ref
= field_val
[tests
[i
]];
326 ref
= (typeof(ref
) == 'object') ? ref : ref
.split(new RegExp('\\s*\\|\\|\\s*'));
327 for (var j
= 0; j
< ref
.length
; j
++) {
328 if (! (m
= ref
[j
].match('^\\s*s([^\\s\\w])(.+)\\1(.*)\\1([eigmx]*)$')))
329 return this.error("Not sure how to parse that replace "+ref
[j
]);
333 if (opt
.indexOf('e') != -1)
334 return this.error("The e option cannot be used on field "+field
+", replace "+tests
[i
]);
335 var regexp
= new RegExp(pat
, opt
);
336 for (var k
= 0; k
< values
.length
; k
++) {
337 if (values
[k
].match(regexp
)) modified
= 1;
338 values
[k
] = values
[k
].replace(regexp
,swap
);
342 if (modified
&& n_values
== 1) {
343 var el
= form
[field
];
345 if (! type
) return '';
346 if (type
== 'hidden' || type
== 'password' || type
== 'text' || type
== 'textarea' || type
== 'submit')
347 el
.value
= values
[0];
350 /// only continue if a validate_if is not present or passes test
353 var tests
= this.filter_types('validate_if', types
);
354 for (var i
= 0; i
< tests
.length
; i
++) {
356 var ifs
= field_val
[tests
[i
]];
357 var ret
= this.check_conditional(form
, ifs
, N_level
, ifs_match
);
358 if (ret
) needs_val
++;
360 if (! needs_val
&& n_vif
) return errors
;
363 /// check for simple existence
364 /// optionally check only if another condition is met
365 var is_required
= '';
366 var tests
= this.filter_types('required', types
);
367 for (var i
= 0; i
< tests
.length
; i
++) {
368 if (! field_val
[tests
[i
]] || field_val
[tests
[i
]] == 0) continue;
369 is_required
= tests
[i
];
373 var tests
= this.filter_types('required_if', types
);
374 for (var i
= 0; i
< tests
.length
; i
++) {
375 var ifs
= field_val
[tests
[i
]];
376 if (! this.check_conditional(form
, ifs
, N_level
, ifs_match
)) continue;
377 is_required
= tests
[i
];
381 if (is_required
&& (typeof(_value
) == 'undefined'
382 || ((typeof(_value
) == 'object' && _value
.length
== 0)
383 || ! _value
.length
))) {
384 this.add_error(errors
, field
, is_required
, field_val
, ifs_match
, form
);
389 var tests
= this.filter_types('min_values', types
);
390 for (var i
= 0; i
< tests
.length
; i
++) {
391 var n
= field_val
[tests
[i
]];
393 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
399 var tests
= this.filter_types('max_values', types
);
400 if (! tests
.length
) {
401 tests
[tests
.length
] = 'max_values';
402 field_val
['max_values'] = 1;
404 for (var i
= 0; i
< tests
.length
; i
++) {
405 var n
= field_val
[tests
[i
]];
407 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
412 /// min_in_set and max_in_set check
413 for (var h
= 0; h
< 2 ; h
++) {
414 var minmax
= (h
== 0) ? 'min' : 'max';
415 var tests
= this.filter_types(minmax
+'_in_set', types
);
416 for (var i
= 0; i
< tests
.length
; i
++) {
417 if (! (m
= field_val
[tests
[i
]].match('^\\s*(\\d+)(?:\\s*[oO][fF])?\\s+(.+)\\s*$')))
418 return this.error("Invalid in_set check "+field_val
[tests
[i
]]);
420 var _fields
= m
[2].split(new RegExp('[\\s,]+'));
421 for (var k
= 0; k
< _fields
.length
; k
++) {
422 var _value
= this.get_form_value(form
[_fields
[k
]]);
424 if (typeof(_value
) == 'undefined') continue;
425 if (typeof(_value
) == 'object') {
428 _values
= new Array();
429 _values
[_values
.length
] = _value
;
431 for (var l
= 0; l
< _values
.length
; l
++) {
432 var _value
= _values
[l
];
433 if (typeof(_value
) != 'undefined' && _value
.length
) n
--;
436 if ( (minmax
== 'min' && n
> 0)
437 || (minmax
== 'max' && n
< 0)) {
438 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
444 // the remaining tests operate on each value of a field
445 for (var n
= 0; n
< values
.length
; n
++) {
446 var value
= values
[n
];
448 /// allow for enum types
449 var tests
= this.filter_types('enum', types
);
450 for (var i
= 0; i
< tests
.length
; i
++) {
451 var hold
= field_val
[tests
[i
]];
452 var _enum
= (typeof(hold
) == 'object') ? hold : hold
.split(new RegExp('\\s*\\|\\|\\s*'));
454 for (var j
= 0; j
< _enum
.length
; j
++) {
455 if (value
!= _enum
[j
]) continue;
459 if (! is_found
) this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
462 /// field equality test
463 var tests
= this.filter_types('equals', types
);
464 for (var i
= 0; i
< tests
.length
; i
++) {
465 var field2
= field_val
[tests
[i
]];
466 var not
= field2
.match('^!\\s*');
467 if (not
) field2
= field2
.substring(not
[0].length
);
469 if (m
= field2
.match('^(["\'])(.*)\\1$')) {
470 if (value
== m
[2]) success
= 1;
472 var value2
= this.get_form_value(form
[field2
]);
473 if (typeof(value2
) == 'undefined') value2
= '';
474 if (value
== value2
) success
= 1;
476 if (not
&& success
|| ! not
&& ! success
)
477 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
481 var tests
= this.filter_types('min_len', types
);
482 for (var i
= 0; i
< tests
.length
; i
++) {
483 var n
= field_val
[tests
[i
]];
484 if (value
.length
< n
) this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
488 var tests
= this.filter_types('max_len', types
);
489 for (var i
= 0; i
< tests
.length
; i
++) {
490 var n
= field_val
[tests
[i
]];
491 if (value
.length
> n
) this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
494 /// now do match types
495 var tests
= this.filter_types('match', types
);
496 for (var i
= 0; i
< tests
.length
; i
++) {
497 var ref
= field_val
[tests
[i
]];
498 ref
= (typeof(ref
) == 'object') ? ref
499 : (typeof(ref
) == 'function') ? new Array(ref
)
500 : ref
.split(new RegExp('\\s*\\|\\|\\s*'));
501 for (var j
= 0; j
< ref
.length
; j
++) {
502 if (typeof(ref
[j
]) == 'function') {
503 if (! value
.match(ref
[j
])) this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
505 if (! (m
= ref
[j
].match('^\\s*(!\\s*|)m([^\\s\\w])(.*)\\2([eigsmx]*)\\s*$')))
506 return this.error("Not sure how to parse that match ("+ref
[j
]+")");
510 if (opt
.indexOf('e') != -1)
511 return this.error("The e option cannot be used on field "+field
+", test "+tests
[i
]);
512 opt
= opt
.replace(new RegExp('[sg]','g'),'');
513 var regexp
= new RegExp(pat
, opt
);
514 if ( ( not
&& value
.match(regexp
))
515 || (! not
&& ! value
.match(regexp
))) {
516 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
522 /// allow for comparison checks
523 var tests
= this.filter_types('compare', types
);
524 for (var i
= 0; i
< tests
.length
; i
++) {
525 var ref
= field_val
[tests
[i
]];
526 ref
= (typeof(ref
) == 'object') ? ref : ref
.split(new RegExp('\\s*\\|\\|\\s*'));
527 for (var j
= 0; j
< ref
.length
; j
++) {
529 if (! comp
) continue;
532 if (m
= comp
.match('^\\s*(>|<|[><!=]=)\\s*([\\d\.\-]+)\\s*$')) {
533 if (! copy
) copy
= 0;
535 if (m
[1] == '>' ) hold
= (copy
> m
[2])
536 else if (m
[1] == '<' ) hold
= (copy
< m
[2])
537 else if (m
[1] == '>=') hold
= (copy
>= m
[2])
538 else if (m
[1] == '<=') hold
= (copy
<= m
[2])
539 else if (m
[1] == '!=') hold
= (copy
!= m
[2])
540 else if (m
[1] == '==') hold
= (copy
== m
[2])
541 } else if (m
= comp
.match('^\\s*(eq|ne|gt|ge|lt|le)\\s+(.+?)\\s*$')) {
542 m
[2] = m
[2].replace('^(["\'])(.*)\\1$','$1');
543 if (m
[1] == 'gt') hold
= (copy
> m
[2])
544 else if (m
[1] == 'lt') hold
= (copy
< m
[2])
545 else if (m
[1] == 'ge') hold
= (copy
>= m
[2])
546 else if (m
[1] == 'le') hold
= (copy
<= m
[2])
547 else if (m
[1] == 'ne') hold
= (copy
!= m
[2])
548 else if (m
[1] == 'eq') hold
= (copy
== m
[2])
550 return this.error("Not sure how to compare \""+comp
+"\"");
552 if (! hold
) this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
556 /// do specific type checks
557 var tests
= this.filter_types('type',types
);
558 for (var i
= 0; i
< tests
.length
; i
++)
559 if (! this.check_type(value
, field_val
[tests
[i
]], field
, form
))
560 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
562 /// do custom_js type checks
563 // this will allow for a custom piece of javascript
564 // the js is evaluated and should return 1 for success
565 // or 0 for failure - the variables field, value, and field_val (the hash) are available
566 var tests
= this.filter_types('custom_js',types
);
567 for (var i
= 0; i
< tests
.length
; i
++)
568 if (! eval(field_val
[tests
[i
]]))
569 this.add_error(errors
, field
, tests
[i
], field_val
, ifs_match
, form
);
572 /// all done - time to return
576 /// used to validate specific types
577 function vob_check_type (value
, type
, field
, form
) {
580 /// do valid email address for our system
581 if (type
== 'EMAIL') {
582 if (! value
) return 0;
583 if (! (m
= value
.match('^(.+)\@(.+?)$'))) return 0;
584 if (m
[1].length
> 60) return 0;
585 if (m
[2].length
> 100) return 0;
586 if (! this.check_type(m
[2],'DOMAIN') && ! this.check_type(m
[2],'IP')) return 0;
587 if (! this.check_type(m
[1],'LOCAL_PART')) return 0;
589 /// the "username" portion of an email address
590 } else if (type
== 'LOCAL_PART') {
591 if (typeof(value
) == 'undefined' || ! value
.length
) return 0;
592 if (value
.match('[^a-z0-9.\\-!&+]')) return 0;
593 if (value
.match('^[.\\-]')) return 0;
594 if (value
.match('[.\\-&]$')) return 0;
595 if (value
.match('(\\.-|-\\.|\\.\\.)')) return 0;
597 /// standard IP address
598 } else if (type
== 'IP') {
599 if (! value
) return 0;
600 var dig
= value
.split(new RegExp('\\.'));
601 if (dig
.length
!= 4) return 0;
602 for (var i
= 0; i
< 4; i
++)
603 if (typeof(dig
[i
]) == 'undefined' || dig
[i
].match('\\D') || dig
[i
] > 255) return 0;
605 /// domain name - including tld and subdomains (which are all domains)
606 } else if (type
== 'DOMAIN') {
607 if (! value
) return 0;
608 if (! value
.match('^[a-z0-9.-]{4,255}$')) return 0;
609 if (value
.match('^[.\\-]')) return 0;
610 if (value
.match('(\\.-|-\\.|\\.\\.)')) return 0;
611 if (! (m
= value
.match('\.([a-z]+)$'))) return 0;
612 value
= value
.substring(0,value
.lastIndexOf('.'));
614 if (m
[1] == 'name') {
615 if (! value
.match('^[a-z0-9][a-z0-9\\-]{0,62}\\.[a-z0-9][a-z0-9\\-]{0,62}$')) return 0;
617 if (! value
.match('^([a-z0-9][a-z0-9\\-]{0,62}\\.)*[a-z0-9][a-z0-9\\-]{0,62}$')) return 0;
620 } else if (type
== 'URL') {
621 if (! value
) return 0;
622 if (! (m
= value
.match(new RegExp('^https?://([^/]+)','i'),''))) return 0;
623 value
= value
.substring(m
[0].length
);
624 if (! this.check_type(m
[1],'DOMAIN') && ! this.check_type(m
[1],'IP')) return 0;
625 if (value
&& ! this.check_type(value
,'URI')) return 0;
627 /// validate a uri - the path portion of a request
628 } else if (type
== 'URI') {
629 if (! value
) return 0;
630 if (value
.match('\\s')) return 0;
632 } else if (type
== 'CC') {
633 if (! value
) return 0;
634 if (value
.match('[^\\d\\- ]') || value
.length
> 16 || value
.length
< 13) return;
635 /// simple mod10 check
636 value
= value
.replace(new RegExp('[\\- ]','g'), '');
640 for (var i
= value
.length
- 1; i
>= 0; i
--) {
641 if (++ swc
> 2) swc
= 1;
642 var y
= value
.charAt(i
) * swc
;
646 if (sum
% 10) return 0;
653 // little routine that will get the values from the form
654 // it will return multiple values as an array
655 function vob_get_form_value (el
) {
657 if (el
.disabled
) return '';
658 var type
= el
.type
? el
.type
.toLowerCase() : '';
659 if (el
.length
&& type
!= 'select-one') {
661 for (var j
=0;j
<el
.length
;j
++) {
662 if (type
.indexOf('multiple') != -1) {
663 if (el
[j
].selected
) a
[a
.length
] = el
[j
].value
;
665 if (el
[j
].checked
) a
[a
.length
] = vob_get_form_value(el
[j
]);
668 if (a
.length
== 0) return '';
669 if (a
.length
== 1) return a
[0];
672 if (! type
) return '';
673 if (type
== 'hidden' || type
== 'password' || type
== 'text' || type
== 'textarea' || type
== 'submit')
675 if (type
.indexOf('select') != -1) {
676 if (! el
.length
) return '';
677 return el
[el
.selectedIndex
].value
;
679 if (type
== 'checkbox' || type
== 'radio') {
680 return el
.checked
? el
.value : '';
682 if (type
== 'file') {
683 return el
.value
; // hope this works
685 alert('Unknown form type for '+el
.name
+': '+type
);
689 ///----------------------------------------------------------------///
691 function eob_get_val (key
, extra2
, extra1
, _default
) {
692 if (typeof(extra2
[key
]) != 'undefined') return extra2
[key
];
693 if (typeof(extra1
[key
]) != 'undefined') return extra1
[key
];
697 function eob_as_string (extra2
) {
698 var extra1
= this.extra
;
699 if (! extra2
) extra2
= new Array();
701 var joiner
= eob_get_val('as_string_join', extra2
, extra1
, '\n');
702 var header
= eob_get_val('as_string_header', extra2
, extra1
, '');
703 var footer
= eob_get_val('as_string_footer', extra2
, extra1
, '');
705 return header
+ this.as_array(extra2
).join(joiner
) + footer
;
708 /// return an array of applicable errors
709 function eob_as_array (extra2
) {
710 var errors
= this.errors
;
711 var extra1
= this.extra
;
712 if (! extra2
) extra2
= new Array();
714 var title
= eob_get_val('as_array_title', extra2
, extra1
, 'Please correct the following items:');
716 /// if there are heading items then we may end up needing a prefix
718 if (title
) has_headings
= 1;
720 for (var i
= 0; i
< errors
.length
; i
++) {
721 if (typeof(errors
[i
]) != 'string') continue;
727 var prefix
= eob_get_val('as_array_prefix', extra2
, extra1
, has_headings
? ' ' : '');
729 /// get the array ready
730 var arr
= new Array();
731 if (title
&& title
.length
) arr
[arr
.length
] = title
;
733 var found
= new Array();
734 for (var i
= 0; i
< errors
.length
; i
++) {
735 if (typeof(errors
[i
]) == 'string') {
736 arr
[arr
.length
] = errors
[i
];
739 var text
= this.get_error_text(errors
[i
]);
740 if (found
[text
]) continue;
742 arr
[arr
.length
] = prefix
+ text
;
749 /// return a hash of applicable errors
750 function eob_as_hash (extra2
) {
751 var errors
= this.errors
;
752 var extra1
= this.extra
;
753 if (! extra2
) extra2
= new Array();
754 var suffix
= eob_get_val('as_hash_suffix', extra2
, extra1
, '_error');
755 var joiner
= eob_get_val('as_hash_join', extra2
, extra1
, '<br />');
757 /// now add to the hash
758 var found
= new Array();
759 var ret
= new Array();
760 for (var i
= 0; i
< errors
.length
; i
++) {
761 if (typeof(errors
[i
]) == 'string') continue;
762 if (! errors
[i
].length
) continue;
764 var field
= errors
[i
][0];
765 var type
= errors
[i
][1];
766 var field_val
= errors
[i
][2];
767 var ifs_match
= errors
[i
][3];
769 if (! field
) return alert("Missing field name");
770 if (field_val
['delegate_error']) {
771 field
= field_val
['delegate_error'];
772 field
= field
.replace(new RegExp('\\$(\\d+)','g'), function (all
, N
) {
773 if (typeof(ifs_match
) != 'object'
774 || typeof(ifs_match
[N
]) == 'undefined') return ''
779 var text
= this.get_error_text(errors
[i
]);
780 if (! found
[field
]) found
[field
] = new Array();
781 if (found
[field
][text
]) continue;
782 found
[field
][text
] = 1;
785 if (! ret
[field
]) ret
[field
] = new Array();
786 ret
[field
].push(text
);
789 /// allow for elements returned as
791 var header
= eob_get_val('as_hash_header', extra2
, extra1
, '');
792 var footer
= eob_get_val('as_hash_footer', extra2
, extra1
, '');
793 for (var key
in ret
) {
794 if (key
== 'extend') continue; // Protoype Array() fix
795 ret
[key
] = header
+ ret
[key
].join(joiner
) + footer
;
802 /// return a user friendly error message
803 function eob_get_error_text (err
) {
804 var extra
= this.extra
;
807 var field_val
= err
[2];
808 var ifs_match
= err
[3];
811 var dig
= (m
= type
.match('(_?\\d+)$')) ? m
[1] : '';
812 var type_lc
= type
.toLowerCase();
814 /// allow for delegated field names - only used for defaults
815 if (field_val
['delegate_error']) {
816 field
= field_val
['delegate_error'];
817 field
= field
.replace(new RegExp('\\$(\\d+)','g'), function (all
, N
) {
818 if (typeof(ifs_match
) != 'object'
819 || typeof(ifs_match
[N
]) == 'undefined') return ''
824 /// the the name of this thing
825 var name
= (field_val
['name']) ? field_val
['name'] : "The field " +field
;
826 name
= name
.replace(new RegExp('\\$(\\d+)','g'), function (all
, N
) {
827 if (typeof(ifs_match
) != 'object'
828 || typeof(ifs_match
[N
]) == 'undefined') return ''
833 /// type can look like "required" or "required2" or "required100023"
834 /// allow for fallback from required100023_error through required_error
835 var possible_keys
= new Array(type
+ '_error');
836 if (dig
.length
) possible_keys
.unshift(type
+ dig
+ '_error');
838 /// look in the passed hash or self first
839 for (var i
= 0; i
< possible_keys
.length
; i
++) {
840 var key
= possible_keys
[i
];
841 var ret
= field_val
[key
];
843 if (extra
[key
]) ret
= extra
[key
];
846 ret
= ret
.replace(new RegExp('\\$(\\d+)','g'), function (all
, N
) {
847 if (typeof(ifs_match
) != 'object'
848 || typeof(ifs_match
[N
]) == 'undefined') return ''
851 ret
= ret
.replace(new RegExp('\\$field','g'), field
);
852 ret
= ret
.replace(new RegExp('\\$name' ,'g'), name
);
853 if (field_val
[type
+ dig
] && typeof(field_val
[type
+ dig
]) == 'string')
854 ret
= ret
.replace(new RegExp('\\$value' ,'g'), field_val
[type
+ dig
]);
858 /// set default messages
859 if (type
== 'required' || type
== 'required_if') {
860 return name
+ " is required.";
862 } else if (type
== 'min_values') {
863 var n
= field_val
["min_values" + dig
];
864 var values
= (n
== 1) ? 'value' : 'values';
865 return name
+ " had less than "+n
+" "+values
+".";
867 } else if (type
== 'max_values') {
868 var n
= field_val
["max_values" + dig
];
869 var values
= (n
== 1) ? 'value' : 'values';
870 return name
+ " had more than "+n
+" "+values
+".";
872 } else if (type
== 'min_in_set') {
873 var set = field_val
["min_in_set" + dig
];
874 return "Not enough fields were chosen from the set ("+set+")";
875 return "Too many fields were chosen from the set ("+set+")";
877 } else if (type
== 'max_in_set') {
878 var set = field_val
["max_in_set" + dig
];
879 return "Too many fields were chosen from the set ("+set+")";
881 } else if (type
== 'enum') {
882 return name
+ " is not in the given list.";
884 } else if (type
== 'equals') {
885 var field2
= field_val
["equals" + dig
];
886 var name2
= field_val
["equals" +dig
+ "_name"];
887 if (! name2
) name2
= "the field " +field2
;
888 name2
= name2
.replace(new RegExp('\\$(\\d+)','g'), function (all
, N
) {
889 if (typeof(ifs_match
) != 'object'
890 || typeof(ifs_match
[N
]) == 'undefined') return ''
893 return name
+ " did not equal " + name2
+".";
895 } else if (type
== 'min_len') {
896 var n
= field_val
["min_len"+dig
];
897 var chars
= (n
== 1) ? 'character' : 'characters';
898 return name
+ " was less than "+n
+" "+chars
+".";
900 } else if (type
== 'max_len') {
901 var n
= field_val
["max_len"+dig
];
902 var chars
= (n
== 1) ? 'character' : 'characters';
903 return name
+ " was more than "+n
+" "+chars
+".";
905 } else if (type
== 'match') {
906 return name
+ " contains invalid characters.";
908 } else if (type
== 'compare') {
909 return name
+ " did not fit comparison.";
911 } else if (type
== 'type') {
912 var _type
= field_val
["type"+dig
];
913 return name
+ " did not match type "+_type
+".";
915 } else if (type
== 'custom_js') {
916 return name
+ " did not match custom_js"+dig
+" check.";
920 return alert("Missing error on field "+field
+" for type "+type
+dig
);
923 function eob_first_field () {
924 for (var i
= 0; i
< this.errors
.length
; i
++) {
925 if (typeof(this.errors
[i
]) != 'object') continue;
926 if (! this.errors
[i
][0]) continue;
927 return this.errors
[i
][0];
932 ///----------------------------------------------------------------///
934 document
.validate = function (form
, val_hash
) {
935 // undo previous inline
936 if (document
.did_inline
) {
937 for (var key
in document
.did_inline
) {
938 if (key
== 'extend') continue; // Protoype Array() fix
939 var el
= document
.getElementById(key
);
940 if (el
) el
.innerHTML
= '';
942 document
.did_inline
= undefined;
946 val_hash
= document
.load_val_hash(form
, val_hash
);
947 if (typeof(val_hash
) == 'undefined') return true;
948 if (! document
.val_obj
) document
.val_obj
= new Validate();
949 var err_obj
= document
.val_obj
.validate(form
, val_hash
);
952 if (! err_obj
) return true;
955 var field
= err_obj
.first_field();
956 if (field
&& form
[field
] && form
[field
].focus
) form
[field
].focus();
959 if (! err_obj
.extra
.no_inline
) {
960 var d
= document
.did_inline
= new Array();
961 var hash
= err_obj
.as_hash();
962 for (var key
in hash
) {
963 if (key
== 'extend') continue; // Protoype Array() fix
964 var el
= document
.getElementById(key
);
965 if (el
) el
.innerHTML
= hash
[key
];
971 if (! err_obj
.extra
.no_confirm
) {
972 return confirm(err_obj
.as_string()) ? false : true;
973 } else if (! err_obj
.extra
.no_alert
) {
974 alert(err_obj
.as_string());
976 } else if (! err_obj
.extra
.no_inline
) {
983 document
.load_val_hash = function (form
, val_hash
) {
984 // check the form we are using
985 if (! form
) return alert('Missing form or form name');
986 if (typeof(form
) == 'string') {
987 if (! document
[form
]) return alert('No form by name '+form
);
988 form
= document
[form
];
991 // if we already have validation - use it
992 if (form
.val_hash
) return form
.val_hash
;
994 // load in the validation and save it for future use
995 if (typeof(val_hash
) != 'object') {
996 // get the hash from a javascript function
997 if (typeof(val_hash
) == 'function') {
998 val_hash
= val_hash(formname
);
999 } else if (typeof(val_hash
) == 'undefined') {
1001 // get hash from a global js variable
1002 if (typeof(document
.validation
) != 'undefined') {
1003 val_hash
= document
.validation
;
1004 // get hash from a element by if of validation
1005 } else if (el
= document
.getElementById('validation')) {
1006 val_hash
= el
.innerHTML
;
1007 val_hash
= val_hash
.replace(new RegExp('<', 'ig'),'<');
1008 val_hash
= val_hash
.replace(new RegExp('>', 'ig'),'>');
1009 val_hash
= val_hash
.replace(new RegExp('&','ig'),'&');
1010 // read hash from <input name=foo validation="">
1012 var order
= new Array();
1014 var yaml
= form
.getAttribute('validation');
1016 if (m
= yaml
.match('^( +)')) yaml
= yaml
.replace(new RegExp('^'+m
[1], 'g'), ''); //unindent
1017 yaml
= yaml
.replace(new RegExp('\\s*$',''),'\n'); // add trailing
1021 for (var i
= 0; i
< form
.elements
.length
; i
++) {
1022 var name
= form
.elements
[i
].name
;
1023 var yaml
= form
.elements
[i
].getAttribute('validation');
1024 if (! name
|| ! yaml
) continue;
1025 yaml
= yaml
.replace(new RegExp('\\s*$',''),'\n'); // add trailing
1026 yaml
= yaml
.replace(new RegExp('^(.)','mg'),' $1'); // indent all
1027 yaml
= yaml
.replace(new RegExp('^( *[^\\s&*\\[\\{])',''),'\n$1'); // add newline
1028 str
+= name
+':' + yaml
;
1029 order
[order
.length
] = name
;
1031 if (str
) val_hash
= str
+ "group order: [" + order
.join(', ') + "]\n";
1034 if (typeof(val_hash
) == 'string') {
1035 if (! document
.yaml_load
) return;
1036 document
.hide_yaml_errors
= (! document
.show_yaml_errors
);
1037 if (location
.search
&& location
.search
.indexOf('show_yaml_errors') != -1)
1038 document
.hide_yaml_errors
= 0;
1039 val_hash
= document
.yaml_load(val_hash
);
1040 if (document
.yaml_error_occured
) return;
1044 // attach to the form
1045 form
.val_hash
= val_hash
;
1046 return form
.val_hash
;
1050 document
.check_form = function (form
, val_hash
) {
1051 // check the form we are using
1052 if (! form
) return alert('Missing form or form name');
1053 if (typeof(form
) == 'string') {
1054 if (! document
[form
]) return alert('No form by name '+form
);
1055 form
= document
[form
];
1058 // void call - allow for getting it at run time rather than later
1059 document
.load_val_hash(form
, val_hash
);
1062 var orig_submit
= form
.onsubmit
|| function () { return true };
1063 form
.onsubmit = function (e
) { return document
.validate(this) && orig_submit(e
, this) };
This page took 0.119761 seconds and 5 git commands to generate.