1
|
|
|
'use strict'; |
2
|
|
|
|
3
|
1 |
|
var floatify = function floatify(str) { |
4
|
231 |
|
var toFloatFormat = function toFloatFormat(str, ts, ds) { |
5
|
177 |
|
var string = str; |
6
|
177 |
|
var decimalSeparator = ds || ''; |
7
|
|
|
|
8
|
177 |
|
string = string.split(ts || '').join(''); |
9
|
177 |
|
if (decimalSeparator !== '') { |
10
|
145 |
|
string = string.split(decimalSeparator).join('.'); |
11
|
|
|
} |
12
|
|
|
|
13
|
177 |
|
return parseFloat(string); |
14
|
|
|
}; |
15
|
|
|
|
16
|
231 |
|
var parseParts = function parseParts(str, ele, count) { |
17
|
124 |
|
var string = str; |
18
|
124 |
|
var element = ele; |
19
|
124 |
|
var parts = string.split(element); |
20
|
|
|
|
21
|
124 |
|
for (var i = 1; i < parts.length; i++) { |
22
|
131 |
|
var left = parts[i - 1]; |
23
|
131 |
|
var leftVal = parseInt(left, 10); |
24
|
|
|
|
25
|
131 |
|
if (parts[i].length === 0) { |
26
|
8 |
|
return Number.NaN; |
27
|
|
|
} |
28
|
|
|
|
29
|
123 |
|
if (parts[i].length === 3) { |
30
|
31 |
|
if (left.length > 3 && parts.length - 1 !== i) { |
31
|
2 |
|
return Number.NaN; |
32
|
|
|
} |
33
|
|
|
|
34
|
29 |
|
if ( |
35
|
|
|
(leftVal === 0 || isNaN(leftVal) || left.length > 3) |
36
|
|
|
&& parts.length - 1 === i |
37
|
|
|
) { |
38
|
13 |
|
return toFloatFormat(string, '', element); |
39
|
|
|
} |
40
|
|
|
|
41
|
16 |
|
continue; |
42
|
|
|
} |
43
|
|
|
|
44
|
92 |
|
if (i < parts.length - 1) { |
45
|
|
|
// violation in midPart -> NaN |
46
|
12 |
|
return Number.NaN; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
// violation in end -> Could be decimalSeparator |
50
|
80 |
|
if (count === 1) { |
51
|
76 |
|
return toFloatFormat(string, '', element); |
52
|
|
|
} |
53
|
|
|
|
54
|
4 |
|
return Number.NaN; |
55
|
|
|
} |
56
|
|
|
|
57
|
9 |
|
return toFloatFormat(string, element, ''); |
58
|
|
|
}; |
59
|
|
|
|
60
|
231 |
|
var parse = function parse(str) { |
61
|
231 |
|
var string = str; |
62
|
|
|
var spacePos; |
63
|
|
|
var spaceSplit; |
64
|
|
|
var spaceCount; |
65
|
|
|
var dotPos; |
66
|
|
|
var commaPos; |
67
|
|
|
var lDotPos; |
68
|
|
|
var lCommaPos; |
69
|
|
|
var dotCount; |
70
|
|
|
var commaCount; |
71
|
|
|
|
72
|
231 |
|
string = string.trim(); |
73
|
|
|
|
74
|
|
|
// 1st dot position |
75
|
231 |
|
dotPos = string.indexOf('.'); |
76
|
|
|
// 1st comma position |
77
|
231 |
|
commaPos = string.indexOf(','); |
78
|
|
|
// 1st space position |
79
|
231 |
|
spacePos = string.indexOf(' '); |
80
|
|
|
|
81
|
231 |
|
if (dotPos + commaPos + spacePos === -3) { |
82
|
|
|
// life is good, no separators |
83
|
18 |
|
return toFloatFormat(string); |
84
|
|
|
} |
85
|
|
|
|
86
|
213 |
|
spaceSplit = string.split(' '); |
87
|
213 |
|
spaceCount = spaceSplit.length - 1; |
88
|
213 |
|
dotCount = string.split('.').length - 1; |
89
|
213 |
|
commaCount = string.split(',').length - 1; |
90
|
|
|
|
91
|
|
|
// only combination of 2 separators allowed |
92
|
213 |
|
if (dotCount > 0 && commaCount > 0 && spaceCount > 0) return Number.NaN; |
|
|
|
|
93
|
|
|
|
94
|
|
|
// if there is any separator (space, comma, dot) found more than once, |
95
|
|
|
// all other must not be found more than once |
96
|
212 |
|
if (dotCount > 1 && (commaCount > 1 || spaceCount > 1)) return Number.NaN; |
|
|
|
|
97
|
208 |
|
if (commaCount > 1 && (dotCount > 1 || spaceCount > 1)) return Number.NaN; |
|
|
|
|
98
|
207 |
|
if (spaceCount > 1 && (dotCount > 1 || commaCount > 1)) return Number.NaN; |
|
|
|
|
99
|
|
|
|
100
|
207 |
|
if (spaceCount > 0) { |
101
|
72 |
|
if (!string.match(/^(\d{1,3})?(\s\d{3})*([,\.]\d+)?$/)) { |
102
|
17 |
|
return Number.NaN; |
103
|
|
|
} |
104
|
55 |
|
string = spaceSplit.join(''); |
105
|
|
|
} |
106
|
|
|
|
107
|
190 |
|
if (dotPos !== -1 && commaPos !== -1) { |
108
|
|
|
// format is using dot and comma |
109
|
|
|
|
110
|
|
|
// last dot position |
111
|
61 |
|
lDotPos = string.lastIndexOf('.'); |
112
|
|
|
// last comma position |
113
|
61 |
|
lCommaPos = string.lastIndexOf(','); |
114
|
|
|
|
115
|
|
|
// order of 1st dot -> comma must be same as last dot -> comma |
116
|
|
|
// 123.123.123,123 -> ok 123.123,123.123 -> not ok |
117
|
61 |
|
if (Math.sign(dotPos - commaPos) !== Math.sign(lDotPos - lCommaPos)) { |
118
|
3 |
|
return Number.NaN; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
// check positions to guess the thousands separator |
122
|
58 |
|
if (dotPos > commaPos) { |
123
|
51 |
|
if (dotCount > 1) return Number.NaN; |
|
|
|
|
124
|
|
|
// best guess: . is thousands separator and , is decimal point |
125
|
50 |
|
return toFloatFormat(string, ',', '.'); |
126
|
|
|
} |
127
|
|
|
|
128
|
7 |
|
if (commaCount > 1) return Number.NaN; |
|
|
|
|
129
|
|
|
// best guess: , is thousands separator and . is decimal point |
130
|
6 |
|
return toFloatFormat(string, '.', ','); |
131
|
|
|
} |
132
|
|
|
|
133
|
129 |
|
if (dotPos !== -1) { |
134
|
|
|
// only dot(s) in format |
135
|
85 |
|
return parseParts(string, '.', dotCount); |
136
|
|
|
} |
137
|
|
|
|
138
|
44 |
|
if (commaPos !== -1) { |
139
|
|
|
// only comma(s) in format |
140
|
39 |
|
return parseParts(string, ',', commaCount); |
141
|
|
|
} |
142
|
|
|
|
143
|
5 |
|
return toFloatFormat(string); |
144
|
|
|
}; |
145
|
|
|
|
146
|
231 |
|
return parse(str); |
147
|
|
|
}; |
148
|
|
|
|
149
|
2 |
|
if (typeof exports !== 'undefined') { |
150
|
4 |
|
if (typeof module !== 'undefined' && module.exports) { |
151
|
1 |
|
exports = module.exports = floatify; |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.
Consider:
If you or someone else later decides to put another statement in, only the first statement will be executed.
In this case the statement
b = 42
will always be executed, while the logging statement will be executed conditionally.ensures that the proper code will be executed conditionally no matter how many statements are added or removed.