vendor: 9,439 bytes, lines 1-381
1(function(factory) { 2 if (typeof define === "function" && define.amd) { 3 // AMD. Register as an anonymous module. 4 define([], factory); 5 } else if (typeof exports === "object") { 6 // Node/CommonJS 7 module.exports = factory(); 8 } else { 9 // Browser globals 10 window.wNumb = factory(); 11 } 12})(function() { 13 "use strict"; 14 15 var FormatOptions = [ 16 "decimals", 17 "thousand", 18 "mark", 19 "prefix", 20 "suffix", 21 "encoder", 22 "decoder", 23 "negativeBefore", 24 "negative", 25 "edit", 26 "undo" 27 ]; 28 29 // General 30 31 // Reverse a string 32 function strReverse(a) { 33 return a 34 .split("") 35 .reverse() 36 .join(""); 37 } 38 39 // Check if a string starts with a specified prefix. 40 function strStartsWith(input, match) { 41 return input.substring(0, match.length) === match; 42 } 43 44 // Check is a string ends in a specified suffix. 45 function strEndsWith(input, match) { 46 return input.slice(-1 * match.length) === match; 47 } 48 49 // Throw an error if formatting options are incompatible. 50 function throwEqualError(F, a, b) { 51 if ((F[a] || F[b]) && F[a] === F[b]) { 52 throw new Error(a); 53 } 54 } 55 56 // Check if a number is finite and not NaN 57 function isValidNumber(input) { 58 return typeof input === "number" && isFinite(input); 59 } 60 61 // Provide rounding-accurate toFixed method. 62 // Borrowed: http://stackoverflow.com/a/21323330/775265 63 function toFixed(value, exp) { 64 value = value.toString().split("e"); 65 value = Math.round(+(value[0] + "e" + (value[1] ? +value[1] + exp : exp))); 66 value = value.toString().split("e"); 67 return (+(value[0] + "e" + (value[1] ? +value[1] - exp : -exp))).toFixed(exp); 68 } 69 70 // Formatting 71 72 // Accept a number as input, output formatted string. 73 function formatTo( 74 decimals, 75 thousand, 76 mark, 77 prefix, 78 suffix, 79 encoder, 80 decoder, 81 negativeBefore, 82 negative, 83 edit, 84 undo, 85 input 86 ) { 87 var originalInput = input, 88 inputIsNegative, 89 inputPieces, 90 inputBase, 91 inputDecimals = "", 92 output = ""; 93 94 // Apply user encoder to the input. 95 // Expected outcome: number. 96 if (encoder) { 97 input = encoder(input); 98 } 99 100 // Stop if no valid number was provided, the number is infinite or NaN. 101 if (!isValidNumber(input)) { 102 return false; 103 } 104 105 // Rounding away decimals might cause a value of -0 106 // when using very small ranges. Remove those cases. 107 if (decimals !== false && parseFloat(input.toFixed(decimals)) === 0) { 108 input = 0; 109 } 110 111 // Formatting is done on absolute numbers, 112 // decorated by an optional negative symbol. 113 if (input < 0) { 114 inputIsNegative = true; 115 input = Math.abs(input); 116 } 117 118 // Reduce the number of decimals to the specified option. 119 if (decimals !== false) { 120 input = toFixed(input, decimals); 121 } 122 123 // Transform the number into a string, so it can be split. 124 input = input.toString(); 125 126 // Break the number on the decimal separator. 127 if (input.indexOf(".") !== -1) { 128 inputPieces = input.split("."); 129 130 inputBase = inputPieces[0]; 131 132 if (mark) { 133 inputDecimals = mark + inputPieces[1]; 134 } 135 } else { 136 // If it isn't split, the entire number will do. 137 inputBase = input; 138 } 139 140 // Group numbers in sets of three. 141 if (thousand) { 142 inputBase = strReverse(inputBase).match(/.{1,3}/g); 143 inputBase = strReverse(inputBase.join(strReverse(thousand))); 144 } 145 146 // If the number is negative, prefix with negation symbol. 147 if (inputIsNegative && negativeBefore) { 148 output += negativeBefore; 149 } 150 151 // Prefix the number 152 if (prefix) { 153 output += prefix; 154 } 155 156 // Normal negative option comes after the prefix. Defaults to '-'. 157 if (inputIsNegative && negative) { 158 output += negative; 159 } 160 161 // Append the actual number. 162 output += inputBase; 163 output += inputDecimals; 164 165 // Apply the suffix. 166 if (suffix) { 167 output += suffix; 168 } 169 170 // Run the output through a user-specified post-formatter. 171 if (edit) { 172 output = edit(output, originalInput); 173 } 174 175 // All done. 176 return output; 177 } 178 179 // Accept a sting as input, output decoded number. 180 function formatFrom( 181 decimals, 182 thousand, 183 mark, 184 prefix, 185 suffix, 186 encoder, 187 decoder, 188 negativeBefore, 189 negative, 190 edit, 191 undo, 192 input 193 ) { 194 var originalInput = input, 195 inputIsNegative, 196 output = ""; 197 198 // User defined pre-decoder. Result must be a non empty string. 199 if (undo) { 200 input = undo(input); 201 } 202 203 // Test the input. Can't be empty. 204 if (!input || typeof input !== "string") { 205 return false; 206 } 207 208 // If the string starts with the negativeBefore value: remove it. 209 // Remember is was there, the number is negative. 210 if (negativeBefore && strStartsWith(input, negativeBefore)) { 211 input = input.replace(negativeBefore, ""); 212 inputIsNegative = true; 213 } 214 215 // Repeat the same procedure for the prefix. 216 if (prefix && strStartsWith(input, prefix)) { 217 input = input.replace(prefix, ""); 218 } 219 220 // And again for negative. 221 if (negative && strStartsWith(input, negative)) { 222 input = input.replace(negative, ""); 223 inputIsNegative = true; 224 } 225 226 // Remove the suffix. 227 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice 228 if (suffix && strEndsWith(input, suffix)) { 229 input = input.slice(0, -1 * suffix.length); 230 } 231 232 // Remove the thousand grouping. 233 if (thousand) { 234 input = input.split(thousand).join(""); 235 } 236 237 // Set the decimal separator back to period. 238 if (mark) { 239 input = input.replace(mark, "."); 240 } 241 242 // Prepend the negative symbol. 243 if (inputIsNegative) { 244 output += "-"; 245 } 246 247 // Add the number 248 output += input; 249 250 // Trim all non-numeric characters (allow '.' and '-'); 251 output = output.replace(/[^0-9\.\-.]/g, ""); 252 253 // The value contains no parse-able number. 254 if (output === "") { 255 return false; 256 } 257 258 // Covert to number. 259 output = Number(output); 260 261 // Run the user-specified post-decoder. 262 if (decoder) { 263 output = decoder(output); 264 } 265 266 // Check is the output is valid, otherwise: return false. 267 if (!isValidNumber(output)) { 268 return false; 269 } 270 271 return output; 272 } 273 274 // Framework 275 276 // Validate formatting options 277 function validate(inputOptions) { 278 var i, 279 optionName, 280 optionValue, 281 filteredOptions = {}; 282 283 if (inputOptions["suffix"] === undefined) { 284 inputOptions["suffix"] = inputOptions["postfix"]; 285 } 286 287 for (i = 0; i < FormatOptions.length; i += 1) { 288 optionName = FormatOptions[i]; 289 optionValue = inputOptions[optionName]; 290 291 if (optionValue === undefined) { 292 // Only default if negativeBefore isn't set. 293 if (optionName === "negative" && !filteredOptions.negativeBefore) { 294 filteredOptions[optionName] = "-"; 295 // Don't set a default for mark when 'thousand' is set. 296 } else if (optionName === "mark" && filteredOptions.thousand !== ".") { 297 filteredOptions[optionName] = "."; 298 } else { 299 filteredOptions[optionName] = false; 300 } 301 302 // Floating points in JS are stable up to 7 decimals. 303 } else if (optionName === "decimals") { 304 if (optionValue >= 0 && optionValue < 8) { 305 filteredOptions[optionName] = optionValue; 306 } else { 307 throw new Error(optionName); 308 } 309 310 // These options, when provided, must be functions. 311 } else if ( 312 optionName === "encoder" || 313 optionName === "decoder" || 314 optionName === "edit" || 315 optionName === "undo" 316 ) { 317 if (typeof optionValue === "function") { 318 filteredOptions[optionName] = optionValue; 319 } else { 320 throw new Error(optionName); 321 } 322 323 // Other options are strings. 324 } else { 325 if (typeof optionValue === "string") { 326 filteredOptions[optionName] = optionValue; 327 } else { 328 throw new Error(optionName); 329 } 330 } 331 } 332 333 // Some values can't be extracted from a 334 // string if certain combinations are present. 335 throwEqualError(filteredOptions, "mark", "thousand"); 336 throwEqualError(filteredOptions, "prefix", "negative"); 337 throwEqualError(filteredOptions, "prefix", "negativeBefore"); 338 339 return filteredOptions; 340 } 341 342 // Pass all options as function arguments 343 function passAll(options, method, input) { 344 var i, 345 args = []; 346 347 // Add all options in order of FormatOptions 348 for (i = 0; i < FormatOptions.length; i += 1) { 349 args.push(options[FormatOptions[i]]); 350 } 351 352 // Append the input, then call the method, presenting all 353 // options as arguments. 354 args.push(input); 355 return method.apply("", args); 356 } 357 358 function wNumb(options) { 359 if (!(this instanceof wNumb)) { 360 return new wNumb(options); 361 } 362 363 if (typeof options !== "object") { 364 return; 365 } 366 367 options = validate(options); 368 369 // Call 'formatTo' with proper arguments. 370 this.to = function(input) { 371 return passAll(options, formatTo, input); 372 }; 373 374 // Call 'formatFrom' with proper arguments. 375 this.from = function(input) { 376 return passAll(options, formatFrom, input); 377 }; 378 } 379 380 return wNumb; 381});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.