Passed
Push — main ( c21323...650a85 )
by Stefan
02:47
created

script/FormDataValidator.js   D

Complexity

Total Complexity 58
Complexity/F 3.87

Size

Lines of Code 313
Function Count 15

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 58
eloc 191
mnd 43
bc 43
fnc 15
dl 0
loc 313
rs 4.5599
bpm 2.8666
cpm 3.8666
noi 0
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
F FormDataValidator.js ➔ closeErrorPopup 0 5 57

How to fix   Complexity   

Complexity

Complex classes like script/FormDataValidator.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
function FormDataValidator(id)
2
{
3
    this.id = id;
4
    this.focusItem = null;
5
    this.focusTabIndex = null;
6
    this.errors = 0;
7
}
8
    
9
FormDataValidator.prototype.validate = function()
10
{
11
    var i;
12
    var aValidationElements = this.getValidationElements();
13
    var length = aValidationElements.length;
14
    for (i = 0; i < length; i++) {
15
        var validate = aValidationElements[i].getAttribute('data-validation');
16
        var aValidate = validate.split(':');
17
        switch (aValidate[0]) {
18
            case 'int':
19
                this.checkInteger(aValidationElements[i]);
20
                break;
21
            case 'cur':
22
                this.checkCurrency(aValidationElements[i]);
23
                break;
24
            case 'date':
25
                this.checkDate(aValidationElements[i]);
26
                break;
27
            case 'time':
28
                this.checkTime(aValidationElements[i]);
29
                break;
30
            default:
31
                break;
32
        }
33
    }
34
    // if errors found, dispplay message and set focus to last input
35
    if (this.errors > 0) {
36
        // TODO: language
37
        var strMsg = 
38
            "Das Formular entält ungültige Angaben, die rot markiert sind!<br/><br/>" +
39
            "Korrigieren oder vervollständigen Sie bitte Ihre Eingaben.";
40
        
41
        var popup = document.getElementById('errorPopup');
42
        if (popup) {
43
            popup.innerHTML = strMsg;
44
            popup.style.display = 'block';
45
        }
46
        if (this.focusItem !== null) {
47
            this.focusItem.focus();
48
        }
49
        return false;
50
    }
51
    return true;
52
}
53
    
54
FormDataValidator.prototype.checkMandatory = function(item)
55
{
56
    if (item !== null) {
57
        this.setError((item.value == '' || item.value == 'null'), item);
58
    }
59
}
60
61
FormDataValidator.prototype.checkDate = function(item)
62
{
63
    if (item !== null && item.value != '') {
64
        var date = this.isValidDate(item.value);
65
        if (date !== false) {
66
            item.value = date;
67
            this.setError(false, item);
68
        } else {
69
            this.setError(true, item);
70
        }
71
    }
72
}
73
74
FormDataValidator.prototype.checkTime = function(item)
75
{
76
    if (item !== null && item.value != '') {
77
        var time = this.isValidTime(item.value); 
78
        if (time !== false) {
79
            item.value = time;
80
            this.setError(false, item);
81
        } else {
82
            this.setError(true, item);
83
        }
84
    }
85
}
86
87
FormDataValidator.prototype.checkInteger = function(item)
88
{
89
    if (item !== null) {
90
        var integer = this.isValidInteger(item.value);
91
        if (integer !== false) {
92
            item.value = integer;
93
            this.setError(false, item);
94
        } else {
95
            this.setError(true, item);
96
        }
97
    }
98
}
99
100
FormDataValidator.prototype.checkCurrency = function(item)
101
{
102
    if (item !== null) {
103
        var currency = this.isValidCurrency(item.value);
104
        if (currency !== false) {
105
            item.value = currency;
106
            this.setError(false, item);
107
        } else {
108
            this.setError(true, item);
109
        }
110
    }
111
}
112
113
FormDataValidator.prototype.setError = function(set, item)
114
{
115
    if (set) {
116
        item.className = item.className.replace( /Mand/, 'MError' );
117
        item.className = item.className.replace( /OK/, 'Error' );
118
        this.setFocusItem(item);
119
        this.errors++;
120
    } else {
121
        item.className = item.className.replace( /MError/, 'Mand' );
122
        item.className = item.className.replace( /Error/, 'OK' );
123
    }
124
}
125
126
FormDataValidator.prototype.setFocusItem = function(item)
127
{
128
    if (!this.focusTabIndex || this.focusTabIndex > item.tabIndex) {
129
        this.focusTabIndex = item.tabIndex;
130
        this.focusItem = item;
131
    }
132
}
133
134
FormDataValidator.prototype.isValidDate = function(strDate)
135
{
136
    // remove all whitespace
137
    strDate = strDate.toString().trim();
138
139
    // ',' is replaced with '.' (fast input through num-pad...)
140
    strDate = strDate.replace(/,/g, ".");
141
    // we only accept sequence D.M.Y
142
    var aSplit = strDate.split(".");
143
144
    // First there must be three parts
145
    if (aSplit.length != 3) {
146
        return false;
147
    }
148
    
149
    // Caution: remove leading '0' otherwise parseInt treats values as octal and return '0' in case of '08' and '09' !!!!
150
    var iD = parseInt(aSplit[0].replace(/^0+/,""));
151
    var iM = parseInt(aSplit[1].replace(/^0+/,""));
152
    var iY = parseInt(aSplit[2].replace(/^0+/,""));
153
    if (isNaN(iD) || isNaN(iM) || isNaN(iY)) {
154
        return false;
155
    }
156
    // values < 25 are 21'st century and 25...99 20'st Century!
157
    if (iY < 100) {
158
        if (iY < 33) {
159
            iY += 2000;
160
        } else {
161
            iY += 1900;
162
        }
163
    }
164
    if (iY < 1900) {
165
        return false;
166
    }
167
    iM--;
168
    // initializte Date-Object
169
    var date = new Date(iY, iM, iD);
170
    
171
    // and compare all parts
172
    var iD2 = date.getDate();
173
    var iM2 = date.getMonth();
174
    var iY2 = date.getFullYear();
175
    if (iD != iD2 || iM != iM2 || iY != iY2) {
176
        // alert( 'In: ' + iD + '.' + iM + '.' + iY + '\nOut: ' + iD2 + '.' + iM2 + '.' + iY2 );
177
        return false;
178
    }
179
    var strDate = '';
180
    if (iD < 10) {
181
        strDate = '0';
182
    }
183
    strDate += iD + '.';
184
    if (iM < 10) {
185
        strDate += '0';
186
    }
187
    strDate += iM + '.' + iY;
188
    return strDate;
189
}
190
191
FormDataValidator.prototype.isValidTime = function(strTime)
192
{
193
    // remove all whitespace
194
    strTime = strTime.toString().trim();
195
196
    // we only accept ':' as Delimiter and expect sequence H:i[:s]
197
    var aSplit = strTime.split(":");
198
199
    var iH = 0;
200
    var iM = 0;
201
    var iS = 0;
202
    var iLength = aSplit.length;
203
    if (iLength > 3) {
204
        // more parts are invalid...
205
        return false;
206
    }
207
    if (iLength === 1) {
208
        // no separator - interpret value as minutes
209
        if (aSplit[0] != '0' && aSplit[0] != '00') {
210
            iM = parseInt(aSplit[0].replace(/^0+/,""));
211
        }
212
    } else {
213
        if (iLength > 2) {
214
            // hour:minutes:seconds specified
215
            if (aSplit[2] != '0' && aSplit[2] != '00') {
216
                iS = parseInt(aSplit[2].replace(/^0+/,""));
217
            }
218
        }
219
        if (aSplit[0] != '0' && aSplit[0] != '00') {
220
            iH = parseInt(aSplit[0].replace(/^0+/,""));
221
        }
222
        if (aSplit[1] != '0' && aSplit[1] != '00') {
223
            iM = parseInt(aSplit[1].replace(/^0+/,""));
224
        }
225
    }
226
    
227
    if ( isNaN(iM) || isNaN(iH) || isNaN(iS)) {
228
        return false;
229
    }
230
231
    if (iM > 59) {
232
        // javascript down know an operator like DIV (integer division)
233
        iH += (iM - (iM % 60)) / 60;
234
        iM = iM % 60;
235
    }
236
    // ... 23:59 is the end
237
    if (iH > 23) {
238
        return false;
239
    }
240
241
    // initializte Date-Object
242
    var date = new Date(0, 0, 0, iH, iM, iS);
243
    
244
    // and compare relevant parts
245
    var iH2 = date.getHours();
246
    var iM2 = date.getMinutes();
247
    if (iH != iH2 || iM != iM2) {
248
        return false;
249
    }
250
    strTime = '';
251
    if (iH < 10) {
252
        strTime = '0';
253
    }
254
    strTime += iH + ':';
255
    if (iM < 10) {
256
        strTime += '0';
257
    }
258
    strTime += iM; // + ':00';
259
    return strTime;
260
}
261
262
FormDataValidator.prototype.isValidInteger = function(strInt)
263
{
264
    // remove all whitespace
265
    strInt = strInt.toString().trim();
266
    if (isNaN(strInt) || strInt.indexOf('.') !== -1) {
267
        return false;
268
    }
269
    if (strInt == '') {
270
        strInt = '0';
271
    }
272
    return strInt;
273
}
274
275
FormDataValidator.prototype.isValidCurrency = function(strCur)
276
{
277
    // remove all whitespace
278
    strCur = strCur.toString().trim();
279
    
280
    // remove thousands separator and replace comma to point
281
    strCur = strCur.replace( ".", "" );
282
    strCur = strCur.replace( ",", "." );
283
    if (isNaN(strCur)) {
284
        return false;
285
    }
286
    if (strCur == '') {
287
        strCur = '0';
288
    }
289
    strCur = Number.parseFloat(strCur).toFixed(2);
290
    strCur = strCur.replace( ".", "," );
291
    strCur = strCur.replace(/\B(?=(\d{3})+(?!\d))/g, ".");        
292
    return strCur;
293
}
294
295
FormDataValidator.prototype.getValidationElements = function () 
296
{
297
    var validationElements = [];
298
    var form = document.getElementById(this.id);
299
    var formElements = form.getElementsByTagName('*');
300
    var n = formElements.length;
301
    for (var i = 0; i < n; i++) {
302
        if (formElements[i].getAttribute('data-validation') !== null) {
303
            validationElements.push(formElements[i]);
304
        }
305
    }
306
    return validationElements;    
307
}
308
309
function closeErrorPopup(popup)
310
{
311
    popup.innerHTML = '';
312
    popup.style.display = 'none';
313
}
314