ultimate-base 0.3.5.0 → 0.4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +0,0 @@
1
- #= require ./base
2
- #= require ./tag
3
-
4
- JS_ESCAPE_MAP =
5
- '\\' : '\\\\'
6
- '</' : '<\\/'
7
- "\r\n" : '\\n'
8
- "\n" : '\\n'
9
- "\r" : '\\n'
10
- '"' : '\\"'
11
- "'" : "\\'"
12
-
13
- @Ultimate.Helpers.Javascript =
14
-
15
- escape_javascript: (javascript) ->
16
- return '' unless _.isString(javascript)
17
- javascript.replace( /(\\|<\/|\r\n|[\n\r"'])/g, (match) -> JS_ESCAPE_MAP[match] )
18
-
19
- j: -> @escape_javascript arguments...
20
-
21
- javascript_tag: (content_or_options_with_block = null, html_options = {}, block = null) ->
22
- content =
23
- if block = _.outcasts.blockGiven(arguments)
24
- html_options = content_or_options_with_block if $.isPlainObject(content_or_options_with_block)
25
- block()
26
- else
27
- content_or_options_with_block
28
- Ultimate.Helpers.Tag.content_tag 'script', @javascript_cdata_section(content), html_options, false
29
-
30
- javascript_cdata_section: (content) ->
31
- "\n//#{Ultimate.Helpers.Tag.cdata_section("\n#{content}\n//")}\n"
@@ -1,600 +0,0 @@
1
- #= require ./base
2
-
3
- @Ultimate.Helpers.Number =
4
-
5
- DEFAULTS:
6
- # Used in number_to_delimited
7
- # These are also the defaults for 'currency', 'percentage', 'precision', and 'human'
8
- format:
9
- # Sets the separator between the units, for more precision (e.g. 1.0 / 2.0 == 0.5)
10
- separator: "."
11
- # Delimits thousands (e.g. 1,000,000 is a million) (always in groups of three)
12
- delimiter: ","
13
- # Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
14
- precision: 3
15
- # If set to true, precision will mean the number of significant digits instead
16
- # of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
17
- significant: false
18
- # If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2)
19
- strip_insignificant_zeros: false
20
-
21
- # Used in number_to_currency
22
- currency:
23
- format:
24
- format: "%u%n"
25
- negative_format: "-%u%n"
26
- unit: "$"
27
- # These five are to override number.format and are optional
28
- separator: "."
29
- delimiter: ","
30
- precision: 2
31
- significant: false
32
- strip_insignificant_zeros: false
33
-
34
- # Used in number_to_percentage
35
- percentage:
36
- format:
37
- delimiter: ""
38
- format: "%n%"
39
-
40
- # Used in number_to_rounded
41
- precision:
42
- format:
43
- delimiter: ""
44
-
45
- # Used in number_to_human_size and number_to_human
46
- human:
47
- format:
48
- # These five are to override number.format and are optional
49
- delimiter: ""
50
- precision: 3
51
- significant: true
52
- strip_insignificant_zeros: true
53
- # Used in number_to_human_size
54
- storage_units:
55
- # Storage units output formatting.
56
- # %u is the storage unit, %n is the number (default: 2 MB)
57
- format: "%n %u"
58
- units:
59
- byte: "Bytes"
60
- kb: "KB"
61
- mb: "MB"
62
- gb: "GB"
63
- tb: "TB"
64
- # Used in number_to_human
65
- decimal_units:
66
- format: "%n %u"
67
- # Decimal units output formatting
68
- # By default we will only quantify some of the exponents
69
- # but the commented ones might be defined or overridden
70
- # by the user.
71
- units:
72
- # femto: Quadrillionth
73
- # pico: Trillionth
74
- # nano: Billionth
75
- # micro: Millionth
76
- # mili: Thousandth
77
- # centi: Hundredth
78
- # deci: Tenth
79
- unit: ""
80
- # ten:
81
- # one: Ten
82
- # other: Tens
83
- # hundred: Hundred
84
- thousand: "Thousand"
85
- million: "Million"
86
- billion: "Billion"
87
- trillion: "Trillion"
88
- quadrillion: "Quadrillion"
89
-
90
- DECIMAL_UNITS:
91
- '0' : 'unit'
92
- '1' : 'ten'
93
- '2' : 'hundred'
94
- '3' : 'thousand'
95
- '6' : 'million'
96
- '9' : 'billion'
97
- '12' : 'trillion'
98
- '15' : 'quadrillion'
99
- '-1' : 'deci'
100
- '-2' : 'centi'
101
- '-3' : 'mili'
102
- '-6' : 'micro'
103
- '-9' : 'nano'
104
- '-12': 'pico'
105
- '-15': 'femto'
106
-
107
- STORAGE_UNITS: ['byte', 'kb', 'mb', 'gb', 'tb']
108
-
109
-
110
-
111
- ###**
112
- * Formats a +number+ into a US phone number (e.g., (555)
113
- * 123-9876). You can customize the format in the +options+ hash.
114
- *
115
- * ==== Options
116
- *
117
- * * <tt>'area_code'</tt> - Adds parentheses around the area code.
118
- * * <tt>'delimiter'</tt> - Specifies the delimiter to use
119
- * (defaults to "-").
120
- * * <tt>'extension'</tt> - Specifies an extension to add to the
121
- * end of the generated number.
122
- * * <tt>'country_code'</tt> - Sets the country code for the phone
123
- * number.
124
- * ==== Examples
125
- *
126
- * number_to_phone(5551234) # => 555-1234
127
- * number_to_phone("5551234") # => 555-1234
128
- * number_to_phone(1235551234) # => 123-555-1234
129
- * number_to_phone(1235551234, area_code: true) # => (123) 555-1234
130
- * number_to_phone(1235551234, delimiter: ' ') # => 123 555 1234
131
- * number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
132
- * number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
133
- * number_to_phone("123a456") # => 123a456
134
- *
135
- * number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: '.')
136
- * # => +1.123.555.1234 x 1343
137
- ###
138
- number_to_phone: (number, options = {}) ->
139
- return "" unless number?
140
- number = _.string.strip(String(number))
141
- area_code = options['area_code']
142
- delimiter = options['delimiter'] ? "-"
143
- extension = options['extension']
144
- country_code = options['country_code']
145
- if area_code
146
- number = number.replace(/(\d{1,3})(\d{3})(\d{4}$)/, "($1) $2#{delimiter}$3")
147
- else
148
- number = number.replace(/(\d{0,3})(\d{3})(\d{4})$/, "$1#{delimiter}$2#{delimiter}$3")
149
- number = number.slice(1) if _.string.startsWith(number, delimiter) and not _.string.isBlank(delimiter)
150
- buf = []
151
- buf.push "+#{country_code}#{delimiter}" unless _.string.isBlank(country_code)
152
- buf.push number
153
- buf.push " x #{extension}" unless _.string.isBlank(extension)
154
- buf.join('')
155
-
156
- ###**
157
- * Formats a +number+ into a currency string (e.g., $13.65). You
158
- * can customize the format in the +options+ hash.
159
- *
160
- * ==== Options
161
- *
162
- * * <tt>'locale'</tt> - Sets the locale to be used for formatting
163
- * (defaults to current locale).
164
- * * <tt>'precision'</tt> - Sets the level of precision (defaults
165
- * to 2).
166
- * * <tt>'unit'</tt> - Sets the denomination of the currency
167
- * (defaults to "$").
168
- * * <tt>'separator'</tt> - Sets the separator between the units
169
- * (defaults to ".").
170
- * * <tt>'delimiter'</tt> - Sets the thousands delimiter (defaults
171
- * to ",").
172
- * * <tt>'format'</tt> - Sets the format for non-negative numbers
173
- * (defaults to "%u%n"). Fields are <tt>%u</tt> for the
174
- * currency, and <tt>%n</tt> for the number.
175
- * * <tt>'negative_format'</tt> - Sets the format for negative
176
- * numbers (defaults to prepending an hyphen to the formatted
177
- * number given by <tt>'format'</tt>). Accepts the same fields
178
- * than <tt>'format'</tt>, except <tt>%n</tt> is here the
179
- * absolute value of the number.
180
- *
181
- * ==== Examples
182
- *
183
- * number_to_currency(1234567890.50) # => $1,234,567,890.50
184
- * number_to_currency(1234567890.506) # => $1,234,567,890.51
185
- * number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
186
- * number_to_currency(1234567890.506, locale: 'fr') # => 1 234 567 890,51 €
187
- * number_to_currency('123a456') # => $123a456
188
- *
189
- * number_to_currency(-1234567890.50, negative_format: '(%u%n)')
190
- * # => ($1,234,567,890.50)
191
- * number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '')
192
- * # => &pound;1234567890,50
193
- * number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
194
- * # => 1234567890,50 &pound;
195
- ###
196
- number_to_currency: (number, options = {}) ->
197
- return "" unless number?
198
-
199
- # TODO replace `currency` with `defaults`
200
- currency = @i18n_format_options(options['locale'], 'currency')
201
- currency['negative_format'] ||= "-" + currency['format'] if currency['format']
202
-
203
- defaults = _.extend(@default_format_options('currency'), currency)
204
- defaults['negative_format'] = "-" + options['format'] if options['format']
205
- options = _.extend(defaults, options)
206
-
207
- unit = _.outcasts.delete(options, 'unit')
208
- format = _.outcasts.delete(options, 'format')
209
-
210
- if number < 0
211
- format = _.outcasts.delete(options, 'negative_format')
212
- number = Math.abs(number)
213
-
214
- format.replace('%n', @number_to_rounded(number, options)).replace('%u', unit)
215
-
216
-
217
- ###**
218
- * Formats a +number+ as a percentage string (e.g., 65%). You can
219
- * customize the format in the +options+ hash.
220
- *
221
- * ==== Options
222
- *
223
- * * <tt>'locale'</tt> - Sets the locale to be used for formatting
224
- * (defaults to current locale).
225
- * * <tt>'precision'</tt> - Sets the precision of the number
226
- * (defaults to 3).
227
- * * <tt>'significant'</tt> - If +true+, precision will be the #
228
- * of significant_digits. If +false+, the # of fractional
229
- * digits (defaults to +false+).
230
- * * <tt>'separator'</tt> - Sets the separator between the
231
- * fractional and integer digits (defaults to ".").
232
- * * <tt>'delimiter'</tt> - Sets the thousands delimiter (defaults
233
- * to "").
234
- * * <tt>'strip_insignificant_zeros'</tt> - If +true+ removes
235
- * insignificant zeros after the decimal separator (defaults to
236
- * +false+).
237
- * * <tt>'format'</tt> - Specifies the format of the percentage
238
- * string The number field is <tt>%n</tt> (defaults to "%n%").
239
- *
240
- * ==== Examples
241
- *
242
- * number_to_percentage(100) # => 100.000%
243
- * number_to_percentage('98') # => 98.000%
244
- * number_to_percentage(100, precision: 0) # => 100%
245
- * number_to_percentage(1000, delimiter: '.', separator: ,') # => 1.000,000%
246
- * number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
247
- * number_to_percentage(1000, 'locale' => 'fr') # => 1 000,000%
248
- * number_to_percentage('98a') # => 98a%
249
- * number_to_percentage(100, format: '%n %') # => 100 %
250
- ###
251
- number_to_percentage: (number, options = {}) ->
252
- return "" unless number?
253
- defaults = @format_options(options['locale'], 'percentage')
254
- options = _.extend(defaults, options)
255
- format = options['format'] or "%n%"
256
- format.replace('%n', @number_to_rounded(number, options))
257
-
258
- ###**
259
- * Formats a +number+ with grouped thousands using +delimiter+
260
- * (e.g., 12,324). You can customize the format in the +options+
261
- * hash.
262
- *
263
- * ==== Options
264
- *
265
- * * <tt>'locale'</tt> - Sets the locale to be used for formatting
266
- * (defaults to current locale).
267
- * * <tt>'delimiter'</tt> - Sets the thousands delimiter (defaults
268
- * to ",").
269
- * * <tt>'separator'</tt> - Sets the separator between the
270
- * fractional and integer digits (defaults to ".").
271
- *
272
- * ==== Examples
273
- *
274
- * number_to_delimited(12345678) # => 12,345,678
275
- * number_to_delimited('123456') # => 123,456
276
- * number_to_delimited(12345678.05) # => 12,345,678.05
277
- * number_to_delimited(12345678, delimiter: '.') # => 12.345.678
278
- * number_to_delimited(12345678, delimiter: ',') # => 12,345,678
279
- * number_to_delimited(12345678.05, separator: ' ') # => 12,345,678 05
280
- * number_to_delimited(12345678.05, locale: 'fr') # => 12 345 678,05
281
- * number_to_delimited('112a') # => 112a
282
- * number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
283
- * # => 98 765 432,98
284
- ###
285
- number_to_delimited: (number, options = {}) ->
286
- return "" unless number?
287
- return number unless @valid_float(number)
288
- options = _.extend(@format_options(options['locale']), options)
289
- parts = String(number).split('.')
290
- parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1#{options['delimiter']}")
291
- parts.join(options['separator'])
292
-
293
-
294
- round_with_precision: (number, precision = 2) ->
295
- precision = Math.pow(10, precision)
296
- Math.round(number * precision) / precision
297
-
298
- ###**
299
- * Formats a +number+ with the specified level of
300
- * <tt>'precision'</tt> (e.g., 112.32 has a precision of 2 if
301
- * +'significant'+ is +false+, and 5 if +'significant'+ is +true+).
302
- * You can customize the format in the +options+ hash.
303
- *
304
- * ==== Options
305
- *
306
- * * <tt>'locale'</tt> - Sets the locale to be used for formatting
307
- * (defaults to current locale).
308
- * * <tt>'precision'</tt> - Sets the precision of the number
309
- * (defaults to 3).
310
- * * <tt>'significant'</tt> - If +true+, precision will be the #
311
- * of significant_digits. If +false+, the # of fractional
312
- * digits (defaults to +false+).
313
- * * <tt>'separator'</tt> - Sets the separator between the
314
- * fractional and integer digits (defaults to ".").
315
- * * <tt>'delimiter'</tt> - Sets the thousands delimiter (defaults
316
- * to "").
317
- * * <tt>'strip_insignificant_zeros'</tt> - If +true+ removes
318
- * insignificant zeros after the decimal separator (defaults to
319
- * +false+).
320
- *
321
- * ==== Examples
322
- *
323
- * number_to_rounded(111.2345) # => 111.235
324
- * number_to_rounded(111.2345, precision: 2) # => 111.23
325
- * number_to_rounded(13, precision: 5) # => 13.00000
326
- * number_to_rounded(389.32314, precision: 0) # => 389
327
- * number_to_rounded(111.2345, significant: true) # => 111
328
- * number_to_rounded(111.2345, precision: 1, significant: true) # => 100
329
- * number_to_rounded(13, precision: 5, significant: true) # => 13.000
330
- * number_to_rounded(111.234, locale: 'fr') # => 111,234
331
- *
332
- * number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
333
- * # => 13
334
- *
335
- * number_to_rounded(389.32314, precision: 4, significant: true) # => 389.3
336
- * number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
337
- * # => 1.111,23
338
- ###
339
- number_to_rounded: (number, options = {}) ->
340
- return "" unless number?
341
- return number unless @valid_float(number)
342
- number = Number(number)
343
- options = _.extend(@format_options(options['locale'], 'precision'), options)
344
-
345
- precision = _.outcasts.delete(options, 'precision')
346
- significant = _.outcasts.delete(options, 'significant')
347
- strip_insignificant_zeros = _.outcasts.delete(options, 'strip_insignificant_zeros')
348
-
349
- if significant and precision > 0
350
- if number == 0
351
- [digits, rounded_number] = [1, 0]
352
- else
353
- digits = Math.floor(Math.log(Math.abs(number)) / Math.LN10 + 1)
354
- rounded_number = @round_with_precision(number, precision - digits)
355
- digits = Math.floor(Math.log(Math.abs(rounded_number)) / Math.LN10 + 1) # After rounding, the number of digits may have changed
356
- precision -= digits
357
- precision = 0 if precision < 0 # don't let it be negative
358
- else
359
- rounded_number = @round_with_precision(number, precision)
360
- formatted_number = @number_to_delimited(_.string.sprintf("%01.#{precision}f", rounded_number), options)
361
- if strip_insignificant_zeros
362
- escaped_separator = _.string.escapeRegExp(options['separator'])
363
- formatted_number
364
- .replace(new RegExp("(#{escaped_separator})(\\d*[1-9])?0+$"), '$1$2')
365
- .replace(new RegExp("#{escaped_separator}$"), '')
366
- else
367
- formatted_number
368
-
369
- ###**
370
- * Formats the bytes in +number+ into a more understandable
371
- * representation (e.g., giving it 1500 yields 1.5 KB). This
372
- * method is useful for reporting file sizes to users. You can
373
- * customize the format in the +options+ hash.
374
- *
375
- * See <tt>number_to_human</tt> if you want to pretty-print a
376
- * generic number.
377
- *
378
- * ==== Options
379
- *
380
- * * <tt>'locale'</tt> - Sets the locale to be used for formatting
381
- * (defaults to current locale).
382
- * * <tt>'precision'</tt> - Sets the precision of the number
383
- * (defaults to 3).
384
- * * <tt>'significant'</tt> - If +true+, precision will be the #
385
- * of significant_digits. If +false+, the # of fractional
386
- * digits (defaults to +true+)
387
- * * <tt>'separator'</tt> - Sets the separator between the
388
- * fractional and integer digits (defaults to ".").
389
- * * <tt>'delimiter'</tt> - Sets the thousands delimiter (defaults
390
- * to "").
391
- * * <tt>'strip_insignificant_zeros'</tt> - If +true+ removes
392
- * insignificant zeros after the decimal separator (defaults to
393
- * +true+)
394
- * * <tt>'prefix'</tt> - If +'si'+ formats the number using the SI
395
- * prefix (defaults to 'binary')
396
- *
397
- * ==== Examples
398
- *
399
- * number_to_human_size(123) # => 123 Bytes
400
- * number_to_human_size(1234) # => 1.21 KB
401
- * number_to_human_size(12345) # => 12.1 KB
402
- * number_to_human_size(1234567) # => 1.18 MB
403
- * number_to_human_size(1234567890) # => 1.15 GB
404
- * number_to_human_size(1234567890123) # => 1.12 TB
405
- * number_to_human_size(1234567, precision: 2) # => 1.2 MB
406
- * number_to_human_size(483989, precision: 2) # => 470 KB
407
- * number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
408
- *
409
- * Non-significant zeros after the fractional separator are stripped out by
410
- * default (set <tt>'strip_insignificant_zeros'</tt> to +false+ to change that):
411
- *
412
- * number_to_human_size(1234567890123, precision: 5) # => "1.1229 TB"
413
- * number_to_human_size(524288000, precision: 5) # => "500 MB"
414
- ###
415
- number_to_human_size: (number, options = {}) ->
416
- return "" unless number?
417
- return number unless @valid_float(number)
418
-
419
- number = Number(number)
420
- defaults = @format_options(options['locale'], 'human')
421
- options = _.extend(defaults, options)
422
-
423
- #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
424
- options['strip_insignificant_zeros'] = true if not _.has(options, 'strip_insignificant_zeros')
425
- storage_units_format = @translate_number_value_with_default('human.storage_units.format', locale: options['locale'], raise: true)
426
-
427
- base = if options['prefix'] is 'si' then 1000 else 1024
428
- if parseInt(number) < base
429
- unit = @translate_number_value_with_default('human.storage_units.units.byte', locale: options['locale'], count: parseInt(number), raise: true)
430
- storage_units_format.replace(/%n/, parseInt(number)).replace(/%u/, unit)
431
- else
432
- max_exp = @STORAGE_UNITS.length - 1
433
- exponent = parseInt(Math.log(number) / Math.log(base)) # Convert to base
434
- exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
435
- number /= Math.pow(base, exponent)
436
- unit_key = @STORAGE_UNITS[exponent]
437
- unit = @translate_number_value_with_default("human.storage_units.units.#{unit_key}", locale: options['locale'], count: number, raise: true)
438
- formatted_number = @number_to_rounded(number, options)
439
- storage_units_format.replace(/%n/, formatted_number).replace(/%u/, unit)
440
-
441
- ###**
442
- * Pretty prints (formats and approximates) a number in a way it
443
- * is more readable by humans (eg.: 1200000000 becomes "1.2
444
- * Billion"). This is useful for numbers that can get very large
445
- * (and too hard to read).
446
- *
447
- * See <tt>number_to_human_size</tt> if you want to print a file
448
- * size.
449
- *
450
- * You can also define you own unit-quantifier names if you want
451
- * to use other decimal units (eg.: 1500 becomes "1.5
452
- * kilometers", 0.150 becomes "150 milliliters", etc). You may
453
- * define a wide range of unit quantifiers, even fractional ones
454
- * (centi, deci, mili, etc).
455
- *
456
- * ==== Options
457
- *
458
- * * <tt>'locale'</tt> - Sets the locale to be used for formatting
459
- * (defaults to current locale).
460
- * * <tt>'precision'</tt> - Sets the precision of the number
461
- * (defaults to 3).
462
- * * <tt>'significant'</tt> - If +true+, precision will be the #
463
- * of significant_digits. If +false+, the # of fractional
464
- * digits (defaults to +true+)
465
- * * <tt>'separator'</tt> - Sets the separator between the
466
- * fractional and integer digits (defaults to ".").
467
- * * <tt>'delimiter'</tt> - Sets the thousands delimiter (defaults
468
- * to "").
469
- * * <tt>'strip_insignificant_zeros'</tt> - If +true+ removes
470
- * insignificant zeros after the decimal separator (defaults to
471
- * +true+)
472
- * * <tt>'units'</tt> - A Hash of unit quantifier names. Or a
473
- * string containing an i18n scope where to find this hash. It
474
- * might have the following keys:
475
- * * *integers*: <tt>'unit'</tt>, <tt>'ten'</tt>,
476
- * *<tt>'hundred'</tt>, <tt>'thousand'</tt>, <tt>'million'</tt>,
477
- * *<tt>'billion'</tt>, <tt>'trillion'</tt>,
478
- * *<tt>'quadrillion'</tt>
479
- * * *fractionals*: <tt>'deci'</tt>, <tt>'centi'</tt>,
480
- * *<tt>'mili'</tt>, <tt>'micro'</tt>, <tt>'nano'</tt>,
481
- * *<tt>'pico'</tt>, <tt>'femto'</tt>
482
- * * <tt>'format'</tt> - Sets the format of the output string
483
- * (defaults to "%n %u"). The field types are:
484
- * * %u - The quantifier (ex.: 'thousand')
485
- * * %n - The number
486
- *
487
- * ==== Examples
488
- *
489
- * number_to_human(123) # => "123"
490
- * number_to_human(1234) # => "1.23 Thousand"
491
- * number_to_human(12345) # => "12.3 Thousand"
492
- * number_to_human(1234567) # => "1.23 Million"
493
- * number_to_human(1234567890) # => "1.23 Billion"
494
- * number_to_human(1234567890123) # => "1.23 Trillion"
495
- * number_to_human(1234567890123456) # => "1.23 Quadrillion"
496
- * number_to_human(1234567890123456789) # => "1230 Quadrillion"
497
- * number_to_human(489939, precision: 2) # => "490 Thousand"
498
- * number_to_human(489939, precision: 4) # => "489.9 Thousand"
499
- * number_to_human(1234567, precision: 4,
500
- * significant: false) # => "1.2346 Million"
501
- * number_to_human(1234567, precision: 1,
502
- * separator: ',',
503
- * significant: false) # => "1,2 Million"
504
- *
505
- * Non-significant zeros after the decimal separator are stripped
506
- * out by default (set <tt>'strip_insignificant_zeros'</tt> to
507
- * +false+ to change that):
508
- *
509
- * number_to_human(12345012345, significant_digits: 6) # => "12.345 Billion"
510
- * number_to_human(500000000, precision: 5) # => "500 Million"
511
- *
512
- * ==== Custom Unit Quantifiers
513
- *
514
- * You can also use your own custom unit quantifiers:
515
- * number_to_human(500000, 'units' => {'unit' => "ml", 'thousand' => "lt"}) # => "500 lt"
516
- *
517
- * If in your I18n locale you have:
518
- *
519
- * distance:
520
- * centi:
521
- * one: "centimeter"
522
- * other: "centimeters"
523
- * unit:
524
- * one: "meter"
525
- * other: "meters"
526
- * thousand:
527
- * one: "kilometer"
528
- * other: "kilometers"
529
- * billion: "gazillion-distance"
530
- *
531
- * Then you could do:
532
- *
533
- * number_to_human(543934, 'units' => 'distance') # => "544 kilometers"
534
- * number_to_human(54393498, 'units' => 'distance') # => "54400 kilometers"
535
- * number_to_human(54393498000, 'units' => 'distance') # => "54.4 gazillion-distance"
536
- * number_to_human(343, 'units' => 'distance', 'precision' => 1) # => "300 meters"
537
- * number_to_human(1, 'units' => 'distance') # => "1 meter"
538
- * number_to_human(0.34, 'units' => 'distance') # => "34 centimeters"
539
- ###
540
- number_to_human: (number, options = {}) ->
541
- return "" unless number?
542
- return number unless @valid_float(number)
543
- number = Number(number)
544
- defaults = @format_options(options['locale'], 'human')
545
- options = _.extend(defaults, options)
546
- #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
547
- options['strip_insignificant_zeros'] = true unless _.has(options, 'strip_insignificant_zeros')
548
- inverted_du = _.outcasts.invert(@DECIMAL_UNITS)
549
- units = _.outcasts.delete options, 'units'
550
- unit_exponents = if _.isObject(units)
551
- units
552
- else if _.isString(units)
553
- I18n.translate(units, locale: options['locale'], raise: true)
554
- else unless units?
555
- @translate_number_value_with_default("human.decimal_units.units", locale: options['locale'], raise: true)
556
- else
557
- throw new Error "'units' must be a Hash or String translation scope."
558
- unit_exponents = _.map(_.keys(unit_exponents), (e_name) -> parseInt(inverted_du[e_name])).sort((a, b) -> a < b)
559
- number_exponent = if number isnt 0 then Math.floor(Math.log(Math.abs(number)) / Math.LN10) else 0
560
- display_exponent = _.find(unit_exponents, (e) -> number_exponent >= e) or 0
561
- number /= Math.pow(10, display_exponent)
562
- unit = if _.isObject(units)
563
- units[@DECIMAL_UNITS[display_exponent]]
564
- else if _.isString(units)
565
- I18n.translate("#{units}.#{@DECIMAL_UNITS[display_exponent]}", locale: options['locale'], count: parseInt(number))
566
- else
567
- @translate_number_value_with_default("human.decimal_units.units.#{@DECIMAL_UNITS[display_exponent]}", locale: options['locale'], count: parseInt(number))
568
- decimal_format = options['format'] or @translate_number_value_with_default('human.decimal_units.format', locale: options['locale'])
569
- formatted_number = @number_to_rounded(number, options)
570
- _.string.strip decimal_format.replace(/%n/, formatted_number).replace(/%u/, unit)
571
-
572
-
573
-
574
- #################### Private ####################
575
-
576
- #:nodoc:
577
- format_options: (locale, namespace = null) ->
578
- _.extend(@default_format_options(namespace), @i18n_format_options(locale, namespace))
579
-
580
- #:nodoc:
581
- default_format_options: (namespace = null) ->
582
- options = _.clone(@DEFAULTS['format'])
583
- _.extend(options, @DEFAULTS[namespace]['format']) if namespace?
584
- options
585
-
586
- #:nodoc:
587
- i18n_format_options: (locale, namespace = null) ->
588
- options = _.clone(I18n.translate('number.format', locale: locale, default: {}))
589
- if namespace?
590
- _.extend(options, I18n.translate("number.#{namespace}.format", locale: locale, default: {}))
591
- options
592
-
593
- #:nodoc:
594
- translate_number_value_with_default: (key, i18n_options = {}) ->
595
- _default = _.reduce(key.split('.'), ((defaults, k) -> defaults[k]), @DEFAULTS)
596
- I18n.translate(key, _.extend({default: _default, scope: 'number'}, i18n_options))
597
-
598
- #:nodoc:
599
- valid_float: (number) ->
600
- not isNaN(number)