| Conditions | 32 |
| Total Lines | 183 |
| Code Lines | 97 |
| Lines | 0 |
| Ratio | 0 % |
| Tests | 81 |
| CRAP Score | 32 |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like floatify.js ➔ floatify 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 | 'use strict'; |
||
| 3 | 1 | var floatify = function floatify(str, preferDecimalSeparator) { |
|
| 4 | // by default we prefer thousands separators |
||
| 5 | 281 | var preferThousandsSeparators = preferDecimalSeparator !== true; |
|
| 6 | |||
| 7 | 281 | var toFloatFormat = function toFloatFormat(str, ts, ds) { |
|
| 8 | 231 | var string = str; |
|
| 9 | 231 | var decimalSeparator = ds || ''; |
|
| 10 | |||
| 11 | 231 | string = string.split(ts || '').join(''); |
|
| 12 | 231 | if (decimalSeparator !== '') { |
|
| 13 | 197 | string = string.split(decimalSeparator).join('.'); |
|
| 14 | } |
||
| 15 | |||
| 16 | 231 | return parseFloat(string); |
|
| 17 | }; |
||
| 18 | |||
| 19 | 281 | var parseParts = function parseParts(str, ele, count, preferThousandsSeparators) { |
|
| 20 | 167 | var string = str; |
|
| 21 | 167 | var element = ele; |
|
| 22 | 167 | var parts = string.split(element); |
|
| 23 | |||
| 24 | function parseMidPart() { |
||
| 25 | 25 | if (current.length !== 3) { |
|
| 26 | 16 | return Number.NaN; |
|
| 27 | } |
||
| 28 | |||
| 29 | 9 | if (left.length > 3) { |
|
| 30 | 2 | return Number.NaN; |
|
| 31 | } |
||
| 32 | |||
| 33 | // no decision, continue |
||
| 34 | 7 | return null; |
|
| 35 | } |
||
| 36 | |||
| 37 | function parseEndPart() { |
||
| 38 | 149 | if ((leftVal === 0 || isNaN(leftVal) || left.length > 3)) { |
|
| 39 | 94 | return toFloatFormat(string, '', element); |
|
| 40 | } |
||
| 41 | |||
| 42 | 55 | if (current.length === 3) { |
|
| 43 | 13 | if (preferThousandsSeparators) { |
|
| 44 | 11 | return toFloatFormat(string, element, ''); |
|
| 45 | } |
||
| 46 | 2 | return toFloatFormat(string, '', element); |
|
| 47 | } |
||
| 48 | |||
| 49 | 42 | if (count === 1) { |
|
| 50 | 38 | return toFloatFormat(string, '', element); |
|
| 51 | } |
||
| 52 | |||
| 53 | 4 | return Number.NaN; |
|
| 54 | } |
||
| 55 | |||
| 56 | 167 | for (var i = 1; i < parts.length; i++) { |
|
| 57 | 174 | var current = parts[i]; |
|
| 58 | 174 | var left = parts[i - 1]; |
|
| 59 | 174 | var leftVal = parseInt(left, 10); |
|
| 60 | 174 | var isLast = parts.length - 1 === i; |
|
| 61 | var parseResult; |
||
| 62 | |||
| 63 | 174 | if (!isLast) { |
|
| 64 | 25 | parseResult = parseMidPart(); |
|
| 65 | } else { |
||
| 66 | 149 | parseResult = parseEndPart(); |
|
| 67 | } |
||
| 68 | |||
| 69 | 174 | if (parseResult !== null) { |
|
| 70 | 167 | break; |
|
| 71 | } |
||
| 72 | } |
||
| 73 | 167 | return parseResult || Number.NaN; |
|
| 74 | }; |
||
| 75 | |||
| 76 | 281 | var parse = function parse(str, preferThousandsSeparators) { |
|
| 77 | 281 | var string = str; |
|
| 78 | var spacePos; |
||
| 79 | var spaceSplit; |
||
| 80 | var spaceCount; |
||
| 81 | var dotPos; |
||
| 82 | var commaPos; |
||
| 83 | var lDotPos; |
||
| 84 | var lCommaPos; |
||
| 85 | var dotCount; |
||
| 86 | var commaCount; |
||
| 87 | |||
| 88 | function parseMixedSeparators() { |
||
| 89 | // format is using dot and comma |
||
| 90 | |||
| 91 | // last dot position |
||
| 92 | 68 | lDotPos = string.lastIndexOf('.'); |
|
| 93 | // last comma position |
||
| 94 | 68 | lCommaPos = string.lastIndexOf(','); |
|
| 95 | |||
| 96 | // order of 1st dot -> comma must be same as last dot -> comma |
||
| 97 | // 123.123.123,123 -> ok 123.123,123.123 -> not ok |
||
| 98 | 68 | if (Math.sign(dotPos - commaPos) !== Math.sign(lDotPos - lCommaPos)) { |
|
| 99 | 3 | return Number.NaN; |
|
| 100 | } |
||
| 101 | |||
| 102 | // check positions to guess the thousands separator |
||
| 103 | 65 | if (dotPos > commaPos) { |
|
| 104 | 57 | if (dotCount > 1) { |
|
| 105 | 1 | return Number.NaN; |
|
| 106 | } |
||
| 107 | // best guess: . is thousands separator and , is decimal point |
||
| 108 | 56 | return toFloatFormat(string, ',', '.'); |
|
| 109 | } |
||
| 110 | |||
| 111 | 8 | if (commaCount > 1) { |
|
| 112 | 1 | return Number.NaN; |
|
| 113 | } |
||
| 114 | // best guess: , is thousands separator and . is decimal point |
||
| 115 | 7 | return toFloatFormat(string, '.', ','); |
|
| 116 | } |
||
| 117 | |||
| 118 | function parseSingleSeparators() { |
||
| 119 | 172 | if (dotPos !== -1) { |
|
| 120 | // only dot(s) in format |
||
| 121 | 86 | return parseParts(string, '.', dotCount, preferThousandsSeparators); |
|
| 122 | } |
||
| 123 | |||
| 124 | 86 | if (commaPos !== -1) { |
|
| 125 | // only comma(s) in format |
||
| 126 | 81 | return parseParts(string, ',', commaCount, preferThousandsSeparators); |
|
| 127 | } |
||
| 128 | |||
| 129 | 5 | return toFloatFormat(string); |
|
| 130 | } |
||
| 131 | |||
| 132 | function precheckFormat() { |
||
| 133 | // only combination of 2 separators allowed |
||
| 134 | 263 | if (dotCount > 0 && commaCount > 0 && spaceCount > 0) { |
|
| 135 | 1 | return false; |
|
| 136 | } |
||
| 137 | |||
| 138 | // if there is any separator (space, comma, dot) found more than once, |
||
| 139 | // all other must not be found more than once |
||
| 140 | 262 | if (dotCount > 1 && (commaCount > 1 || spaceCount > 1)) { |
|
| 141 | 4 | return false; |
|
| 142 | } |
||
| 143 | |||
| 144 | 258 | return !(commaCount > 1 && spaceCount > 1); |
|
| 145 | } |
||
| 146 | |||
| 147 | 281 | string = string.trim(); |
|
| 148 | |||
| 149 | // 1st dot position |
||
| 150 | 281 | dotPos = string.indexOf('.'); |
|
| 151 | // 1st comma position |
||
| 152 | 281 | commaPos = string.indexOf(','); |
|
| 153 | // 1st space position |
||
| 154 | 281 | spacePos = string.indexOf(' '); |
|
| 155 | |||
| 156 | 281 | if (dotPos + commaPos + spacePos === -3) { |
|
| 157 | // life is good, no separators |
||
| 158 | 18 | return toFloatFormat(string); |
|
| 159 | } |
||
| 160 | |||
| 161 | 263 | spaceSplit = string.split(' '); |
|
| 162 | 263 | spaceCount = spaceSplit.length - 1; |
|
| 163 | 263 | dotCount = string.split('.').length - 1; |
|
| 164 | 263 | commaCount = string.split(',').length - 1; |
|
| 165 | |||
| 166 | 263 | if (!precheckFormat()) { |
|
| 167 | 6 | return Number.NaN; |
|
| 168 | } |
||
| 169 | |||
| 170 | 257 | if (spaceCount > 0) { |
|
| 171 | 72 | if (!string.match(/^(\d{1,3})?(\s\d{3})*([,\.]\d+)?$/)) { |
|
| 172 | 17 | return Number.NaN; |
|
| 173 | } |
||
| 174 | 55 | string = spaceSplit.join(''); |
|
| 175 | } |
||
| 176 | |||
| 177 | 240 | if (dotPos !== -1 && commaPos !== -1) { |
|
| 178 | 68 | return parseMixedSeparators(); |
|
| 179 | } |
||
| 180 | |||
| 181 | 172 | return parseSingleSeparators(); |
|
| 182 | }; |
||
| 183 | |||
| 184 | 281 | return parse(str, preferThousandsSeparators); |
|
| 185 | }; |
||
| 186 | |||
| 192 |