kivi.Validator
[kivitendo-erp.git] / js / kivi.Validator.js
1 namespace("kivi.Validator", function(ns) {
2   "use strict";
3
4   // Performs various validation steps on the descendants of
5   // 'selector'. Elements that should be validated must have an
6   // attribute named "data-validate" which is set to a space-separated
7   // list of tests to perform. Additionally, the attribute
8   // "data-title" must be set to a human-readable name of the field
9   // that can be shown as part of an error message.
10   //
11   // Supported validation tests are:
12   // - "required": the field must be set (its .val() must not be empty)
13   //
14   // The validation will abort and return "false" as soon as
15   // validation routine fails.
16   //
17   // The function returns "true" if all validations succeed for all
18   // elements.
19   ns.validate_all = function(selector) {
20     selector = selector || '#form';
21     var to_check = $(selector + ' [data-validate]').toArray();
22
23     for (var to_check_idx in to_check)
24       if (!ns.validate($(to_check[to_check_idx])))
25         return false;
26
27     return true;
28   };
29
30   ns.validate = function($e) {
31     var tests = $e.data('validate').split(/ +/);
32
33     for (var test_idx in tests) {
34       var test = tests[test_idx];
35
36       if (ns.checks[test]) {
37         if (!ns.checks[test]($e))
38           return false;
39       } else {
40         var error = "kivi.validate_form: unknown test '" + test + "' for element ID '" + $e.prop('id') + "'";
41         console.error(error);
42         alert(error);
43         return false;
44       }
45     }
46
47     return true;
48   }
49
50   ns.checks = {
51     required: function($e) {
52       if ($e.val() === '') {
53         ns.annotate($e, kivi.t8("This field must not be empty."));
54         return false;
55       } else {
56         ns.annotate($e);
57         return true;
58       }
59     },
60     number: function($e) {
61       var number_string = $e.val();
62
63       var parsed_number = kivi.parse_amount(number_string);
64
65       if (parsed_number === null) {
66         $e.val('');
67         ns.annotate($e);
68         return true;
69       } else
70       if (parsed_number === undefined) {
71         ns.annotate($e, kivi.t8('Wrong number format (#1)', [ kivi.myconfig.numberformat ]));
72         return false;
73       } else
74       {
75         var formatted_number = kivi.format_amount(parsed_number);
76         if (formatted_number != number_string)
77           $e.val(formatted_number);
78         ns.annotate($e);
79         return true;
80       }
81     },
82     date: function($e) {
83       var date_string = $e.val();
84
85       var parsed_date = kivi.parse_date(date_string);
86
87       if (parsed_number === null) {
88         $e.val('');
89         ns.annotate($e);
90         return true;
91       } else
92       if (parsed_date === undefined) {
93         ns.annotate($e, kivi.t8('Wrong date format (#1)', [ kivi.myconfig.dateformat ]));
94         return false;
95       } else
96       {
97         var formatted_date = kivi.format_date(parsed_date);
98         if (formatted_date != date_string)
99           $e.val(formatted_date);
100         ns.annotate($e);
101         return true;
102       }
103     }
104   };
105
106   ns.annotate = function($e, error) {
107     if (error) {
108       $e.addClass('kivi-validator-invalid');
109       if ($e.hasClass('tooltipstered'))
110         $e.tooltipster('destroy');
111
112       $e.tooltipster({
113         content: error,
114         theme: 'tooltipster-light',
115       });
116       $e.tooltipster('show');
117     } else {
118       $e.removeClass('kivi-validator-invalid');
119       if ($e.hasClass('tooltipstered'))
120         $e.tooltipster('destroy');
121     }
122   };
123
124   ns.reinit_widgets = function() {
125     kivi.run_once_for('[data-validate]', 'data-validate', function(elt) {
126       $(elt).change(function(event){ ns.validate($(elt), event) });
127     });
128   }
129
130   ns.init = ns.reinit_widgets;
131
132   $(ns.init);
133 });