ultimate-base 0.3.5.0 → 0.4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)