sugar-rails 1.2.5.1 → 1.3.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.
Files changed (39) hide show
  1. data/README.md +110 -28
  2. data/lib/generators/sugar/build/build_generator.rb +107 -0
  3. data/lib/generators/sugar/install/install_generator.rb +2 -2
  4. data/lib/sugar/rails/version.rb +2 -2
  5. data/sugar-rails.gemspec +1 -1
  6. data/vendor/assets/javascripts/precompiled/development/array.js +1212 -0
  7. data/vendor/assets/javascripts/precompiled/development/core.js +329 -0
  8. data/vendor/assets/javascripts/precompiled/development/date.js +2179 -0
  9. data/vendor/assets/javascripts/precompiled/development/date_locales.js +952 -0
  10. data/vendor/assets/javascripts/precompiled/development/date_ranges.js +183 -0
  11. data/vendor/assets/javascripts/precompiled/development/es5.js +443 -0
  12. data/vendor/assets/javascripts/precompiled/development/function.js +222 -0
  13. data/vendor/assets/javascripts/{sugar-inflections.js → precompiled/development/inflections.js} +51 -162
  14. data/vendor/assets/javascripts/precompiled/development/language.js +383 -0
  15. data/vendor/assets/javascripts/precompiled/development/number.js +422 -0
  16. data/vendor/assets/javascripts/precompiled/development/object.js +348 -0
  17. data/vendor/assets/javascripts/precompiled/development/regexp.js +92 -0
  18. data/vendor/assets/javascripts/precompiled/development/string.js +871 -0
  19. data/vendor/assets/javascripts/precompiled/minified/array.js +16 -0
  20. data/vendor/assets/javascripts/precompiled/minified/core.js +8 -0
  21. data/vendor/assets/javascripts/precompiled/minified/date.js +40 -0
  22. data/vendor/assets/javascripts/precompiled/minified/date_locales.js +38 -0
  23. data/vendor/assets/javascripts/precompiled/minified/date_ranges.js +3 -0
  24. data/vendor/assets/javascripts/precompiled/minified/es5.js +7 -0
  25. data/vendor/assets/javascripts/precompiled/minified/function.js +4 -0
  26. data/vendor/assets/javascripts/precompiled/minified/inflections.js +11 -0
  27. data/vendor/assets/javascripts/precompiled/minified/language.js +19 -0
  28. data/vendor/assets/javascripts/precompiled/minified/number.js +5 -0
  29. data/vendor/assets/javascripts/precompiled/minified/object.js +6 -0
  30. data/vendor/assets/javascripts/precompiled/minified/regexp.js +2 -0
  31. data/vendor/assets/javascripts/precompiled/minified/string.js +12 -0
  32. data/vendor/assets/javascripts/precompiled/readme.txt +3 -0
  33. data/vendor/assets/javascripts/sugar-development.js +8054 -0
  34. data/vendor/assets/javascripts/sugar-full.js +179 -0
  35. data/vendor/assets/javascripts/sugar.js +111 -6211
  36. metadata +35 -9
  37. data/vendor/assets/javascripts/sugar-core.js +0 -4001
  38. data/vendor/assets/javascripts/sugar-dates-only.js +0 -3121
  39. data/vendor/assets/javascripts/sugar-dates.js +0 -2210
@@ -0,0 +1,383 @@
1
+
2
+ /***
3
+ *
4
+ * @package Language
5
+ * @dependency string
6
+ * @description Normalizing accented characters, character width conversion, Hiragana and Katakana conversions.
7
+ *
8
+ ***/
9
+
10
+ /***
11
+ * String module
12
+ *
13
+ ***/
14
+
15
+
16
+
17
+ var NormalizeMap,
18
+ NormalizeReg = '',
19
+ NormalizeSource;
20
+
21
+
22
+ /***
23
+ * @method has[Script]()
24
+ * @returns Boolean
25
+ * @short Returns true if the string contains any characters in that script.
26
+ *
27
+ * @set
28
+ * hasArabic
29
+ * hasCyrillic
30
+ * hasGreek
31
+ * hasHangul
32
+ * hasHan
33
+ * hasKanji
34
+ * hasHebrew
35
+ * hasHiragana
36
+ * hasKana
37
+ * hasKatakana
38
+ * hasLatin
39
+ * hasThai
40
+ * hasDevanagari
41
+ *
42
+ * @example
43
+ *
44
+ * 'أتكلم'.hasArabic() -> true
45
+ * 'визит'.hasCyrillic() -> true
46
+ * '잘 먹겠습니다!'.hasHangul() -> true
47
+ * 'ミックスです'.hasKatakana() -> true
48
+ * "l'année".hasLatin() -> true
49
+ *
50
+ ***
51
+ * @method is[Script]()
52
+ * @returns Boolean
53
+ * @short Returns true if the string contains only characters in that script. Whitespace is ignored.
54
+ *
55
+ * @set
56
+ * isArabic
57
+ * isCyrillic
58
+ * isGreek
59
+ * isHangul
60
+ * isHan
61
+ * isKanji
62
+ * isHebrew
63
+ * isHiragana
64
+ * isKana
65
+ * isKatakana
66
+ * isKatakana
67
+ * isThai
68
+ * isDevanagari
69
+ *
70
+ * @example
71
+ *
72
+ * 'أتكلم'.isArabic() -> true
73
+ * 'визит'.isCyrillic() -> true
74
+ * '잘 먹겠습니다!'.isHangul() -> true
75
+ * 'ミックスです'.isKatakana() -> false
76
+ * "l'année".isLatin() -> true
77
+ *
78
+ ***/
79
+ var unicodeScripts = [
80
+ { names: ['Arabic'], source: '\u0600-\u06FF' },
81
+ { names: ['Cyrillic'], source: '\u0400-\u04FF' },
82
+ { names: ['Devanagari'], source: '\u0900-\u097F' },
83
+ { names: ['Greek'], source: '\u0370-\u03FF' },
84
+ { names: ['Hangul'], source: '\uAC00-\uD7AF\u1100-\u11FF' },
85
+ { names: ['Han','Kanji'], source: '\u4E00-\u9FFF\uF900-\uFAFF' },
86
+ { names: ['Hebrew'], source: '\u0590-\u05FF' },
87
+ { names: ['Hiragana'], source: '\u3040-\u309F\u30FB-\u30FC' },
88
+ { names: ['Kana'], source: '\u3040-\u30FF\uFF61-\uFF9F' },
89
+ { names: ['Katakana'], source: '\u30A0-\u30FF\uFF61-\uFF9F' },
90
+ { names: ['Latin'], source: '\u0001-\u007F\u0080-\u00FF\u0100-\u017F\u0180-\u024F' },
91
+ { names: ['Thai'], source: '\u0E00-\u0E7F' }
92
+ ];
93
+
94
+ function buildUnicodeScripts() {
95
+ unicodeScripts.forEach(function(s) {
96
+ var is = regexp('^['+s.source+'\\s]+$');
97
+ var has = regexp('['+s.source+']');
98
+ s.names.forEach(function(name) {
99
+ defineProperty(string.prototype, 'is' + name, function() { return is.test(this.trim()); });
100
+ defineProperty(string.prototype, 'has' + name, function() { return has.test(this); });
101
+ });
102
+ });
103
+ }
104
+
105
+ // Support for converting character widths and katakana to hiragana.
106
+
107
+ var widthConversionRanges = [
108
+ { type: 'a', shift: 65248, start: 65, end: 90 },
109
+ { type: 'a', shift: 65248, start: 97, end: 122 },
110
+ { type: 'n', shift: 65248, start: 48, end: 57 },
111
+ { type: 'p', shift: 65248, start: 33, end: 47 },
112
+ { type: 'p', shift: 65248, start: 58, end: 64 },
113
+ { type: 'p', shift: 65248, start: 91, end: 96 },
114
+ { type: 'p', shift: 65248, start: 123, end: 126 }
115
+ ];
116
+
117
+ var WidthConversionTable;
118
+ var allHankaku = /[\u0020-\u00A5]|[\uFF61-\uFF9F][゙゚]?/g;
119
+ var allZenkaku = /[\u3000-\u301C]|[\u301A-\u30FC]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g;
120
+ var hankakuPunctuation = '。、「」¥¢£';
121
+ var zenkakuPunctuation = '。、「」¥¢£';
122
+ var voicedKatakana = /[カキクケコサシスセソタチツテトハヒフヘホ]/;
123
+ var semiVoicedKatakana = /[ハヒフヘホヲ]/;
124
+ var hankakuKatakana = 'アイウエオァィゥェォカキクケコサシスセソタチツッテトナニヌネノハヒフヘホマミムメモヤャユュヨョラリルレロワヲンー・';
125
+ var zenkakuKatakana = 'アイウエオァィゥェォカキクケコサシスセソタチツッテトナニヌネノハヒフヘホマミムメモヤャユュヨョラリルレロワヲンー・';
126
+
127
+ function convertCharacterWidth(str, args, reg, type) {
128
+ if(!WidthConversionTable) {
129
+ buildWidthConversionTables();
130
+ }
131
+ var mode = multiArgs(args).join(''), table = WidthConversionTable[type];
132
+ mode = mode.replace(/all/, '').replace(/(\w)lphabet|umbers?|atakana|paces?|unctuation/g, '$1');
133
+ return str.replace(reg, function(c) {
134
+ if(table[c] && (!mode || mode.has(table[c].type))) {
135
+ return table[c].to;
136
+ } else {
137
+ return c;
138
+ }
139
+ });
140
+ }
141
+
142
+ function buildWidthConversionTables() {
143
+ var hankaku;
144
+ WidthConversionTable = {
145
+ 'zenkaku': {},
146
+ 'hankaku': {}
147
+ };
148
+ widthConversionRanges.forEach(function(r) {
149
+ getRange(r.start, r.end, function(n) {
150
+ setWidthConversion(r.type, chr(n), chr(n + r.shift));
151
+ });
152
+ });
153
+ zenkakuKatakana.each(function(c, i) {
154
+ hankaku = hankakuKatakana.charAt(i);
155
+ setWidthConversion('k', hankaku, c);
156
+ if(c.match(voicedKatakana)) {
157
+ setWidthConversion('k', hankaku + '゙', c.shift(1));
158
+ }
159
+ if(c.match(semiVoicedKatakana)) {
160
+ setWidthConversion('k', hankaku + '゚', c.shift(2));
161
+ }
162
+ });
163
+ zenkakuPunctuation.each(function(c, i) {
164
+ setWidthConversion('p', hankakuPunctuation.charAt(i), c);
165
+ });
166
+ setWidthConversion('k', 'ヴ', 'ヴ');
167
+ setWidthConversion('k', 'ヺ', 'ヺ');
168
+ setWidthConversion('s', ' ', ' ');
169
+ }
170
+
171
+ function setWidthConversion(type, half, full) {
172
+ WidthConversionTable['zenkaku'][half] = { type: type, to: full };
173
+ WidthConversionTable['hankaku'][full] = { type: type, to: half };
174
+ }
175
+
176
+
177
+
178
+
179
+ function buildNormalizeMap() {
180
+ NormalizeMap = {};
181
+ iterateOverObject(NormalizeSource, function(normalized, str) {
182
+ str.split('').forEach(function(character) {
183
+ NormalizeMap[character] = normalized;
184
+ });
185
+ NormalizeReg += str;
186
+ });
187
+ NormalizeReg = regexp('[' + NormalizeReg + ']', 'g');
188
+ }
189
+
190
+ NormalizeSource = {
191
+ 'A': 'AⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ',
192
+ 'B': 'BⒷBḂḄḆɃƂƁ',
193
+ 'C': 'CⒸCĆĈĊČÇḈƇȻꜾ',
194
+ 'D': 'DⒹDḊĎḌḐḒḎĐƋƊƉꝹ',
195
+ 'E': 'EⒺEÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ',
196
+ 'F': 'FⒻFḞƑꝻ',
197
+ 'G': 'GⒼGǴĜḠĞĠǦĢǤƓꞠꝽꝾ',
198
+ 'H': 'HⒽHĤḢḦȞḤḨḪĦⱧⱵꞍ',
199
+ 'I': 'IⒾIÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ',
200
+ 'J': 'JⒿJĴɈ',
201
+ 'K': 'KⓀKḰǨḲĶḴƘⱩꝀꝂꝄꞢ',
202
+ 'L': 'LⓁLĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ',
203
+ 'M': 'MⓂMḾṀṂⱮƜ',
204
+ 'N': 'NⓃNǸŃÑṄŇṆŅṊṈȠƝꞐꞤ',
205
+ 'O': 'OⓄOÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ',
206
+ 'P': 'PⓅPṔṖƤⱣꝐꝒꝔ',
207
+ 'Q': 'QⓆQꝖꝘɊ',
208
+ 'R': 'RⓇRŔṘŘȐȒṚṜŖṞɌⱤꝚꞦꞂ',
209
+ 'S': 'SⓈSẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ',
210
+ 'T': 'TⓉTṪŤṬȚŢṰṮŦƬƮȾꞆ',
211
+ 'U': 'UⓊUÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ',
212
+ 'V': 'VⓋVṼṾƲꝞɅ',
213
+ 'W': 'WⓌWẀẂŴẆẄẈⱲ',
214
+ 'X': 'XⓍXẊẌ',
215
+ 'Y': 'YⓎYỲÝŶỸȲẎŸỶỴƳɎỾ',
216
+ 'Z': 'ZⓏZŹẐŻŽẒẔƵȤⱿⱫꝢ',
217
+ 'a': 'aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ',
218
+ 'b': 'bⓑbḃḅḇƀƃɓ',
219
+ 'c': 'cⓒcćĉċčçḉƈȼꜿↄ',
220
+ 'd': 'dⓓdḋďḍḑḓḏđƌɖɗꝺ',
221
+ 'e': 'eⓔeèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ',
222
+ 'f': 'fⓕfḟƒꝼ',
223
+ 'g': 'gⓖgǵĝḡğġǧģǥɠꞡᵹꝿ',
224
+ 'h': 'hⓗhĥḣḧȟḥḩḫẖħⱨⱶɥ',
225
+ 'i': 'iⓘiìíîĩīĭïḯỉǐȉȋịįḭɨı',
226
+ 'j': 'jⓙjĵǰɉ',
227
+ 'k': 'kⓚkḱǩḳķḵƙⱪꝁꝃꝅꞣ',
228
+ 'l': 'lⓛlŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ',
229
+ 'm': 'mⓜmḿṁṃɱɯ',
230
+ 'n': 'nⓝnǹńñṅňṇņṋṉƞɲʼnꞑꞥ',
231
+ 'o': 'oⓞoòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ',
232
+ 'p': 'pⓟpṕṗƥᵽꝑꝓꝕ',
233
+ 'q': 'qⓠqɋꝗꝙ',
234
+ 'r': 'rⓡrŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ',
235
+ 's': 'sⓢsśṥŝṡšṧṣṩșşȿꞩꞅẛ',
236
+ 't': 'tⓣtṫẗťṭțţṱṯŧƭʈⱦꞇ',
237
+ 'u': 'uⓤuùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ',
238
+ 'v': 'vⓥvṽṿʋꝟʌ',
239
+ 'w': 'wⓦwẁẃŵẇẅẘẉⱳ',
240
+ 'x': 'xⓧxẋẍ',
241
+ 'y': 'yⓨyỳýŷỹȳẏÿỷẙỵƴɏỿ',
242
+ 'z': 'zⓩzźẑżžẓẕƶȥɀⱬꝣ',
243
+ 'AA': 'Ꜳ',
244
+ 'AE': 'ÆǼǢ',
245
+ 'AO': 'Ꜵ',
246
+ 'AU': 'Ꜷ',
247
+ 'AV': 'ꜸꜺ',
248
+ 'AY': 'Ꜽ',
249
+ 'DZ': 'DZDŽ',
250
+ 'Dz': 'DzDž',
251
+ 'LJ': 'LJ',
252
+ 'Lj': 'Lj',
253
+ 'NJ': 'NJ',
254
+ 'Nj': 'Nj',
255
+ 'OI': 'Ƣ',
256
+ 'OO': 'Ꝏ',
257
+ 'OU': 'Ȣ',
258
+ 'TZ': 'Ꜩ',
259
+ 'VY': 'Ꝡ',
260
+ 'aa': 'ꜳ',
261
+ 'ae': 'æǽǣ',
262
+ 'ao': 'ꜵ',
263
+ 'au': 'ꜷ',
264
+ 'av': 'ꜹꜻ',
265
+ 'ay': 'ꜽ',
266
+ 'dz': 'dzdž',
267
+ 'hv': 'ƕ',
268
+ 'lj': 'lj',
269
+ 'nj': 'nj',
270
+ 'oi': 'ƣ',
271
+ 'ou': 'ȣ',
272
+ 'oo': 'ꝏ',
273
+ 'ss': 'ß',
274
+ 'tz': 'ꜩ',
275
+ 'vy': 'ꝡ'
276
+ };
277
+
278
+ extend(string, true, false, {
279
+ /***
280
+ * @method normalize()
281
+ * @returns String
282
+ * @short Returns the string with accented and non-standard Latin-based characters converted into ASCII approximate equivalents.
283
+ * @example
284
+ *
285
+ * 'á'.normalize() -> 'a'
286
+ * 'Ménage à trois'.normalize() -> 'Menage a trois'
287
+ * 'Volkswagen'.normalize() -> 'Volkswagen'
288
+ * 'FULLWIDTH'.normalize() -> 'FULLWIDTH'
289
+ *
290
+ ***/
291
+ 'normalize': function() {
292
+ if(!NormalizeMap) {
293
+ buildNormalizeMap();
294
+ }
295
+ return this.replace(NormalizeReg, function(character) {
296
+ return NormalizeMap[character];
297
+ });
298
+ },
299
+
300
+ /***
301
+ * @method hankaku([mode] = 'all')
302
+ * @returns String
303
+ * @short Converts full-width characters (zenkaku) to half-width (hankaku).
304
+ * @extra [mode] accepts any combination of "a" (alphabet), "n" (numbers), "k" (katakana), "s" (spaces), "p" (punctuation), or "all".
305
+ * @example
306
+ *
307
+ * 'タロウ YAMADAです!'.hankaku() -> 'タロウ YAMADAです!'
308
+ * 'タロウ YAMADAです!'.hankaku('a') -> 'タロウ YAMADAです!'
309
+ * 'タロウ YAMADAです!'.hankaku('alphabet') -> 'タロウ YAMADAです!'
310
+ * 'タロウです! 25歳です!'.hankaku('katakana', 'numbers') -> 'タロウです! 25歳です!'
311
+ * 'タロウです! 25歳です!'.hankaku('k', 'n') -> 'タロウです! 25歳です!'
312
+ * 'タロウです! 25歳です!'.hankaku('kn') -> 'タロウです! 25歳です!'
313
+ * 'タロウです! 25歳です!'.hankaku('sp') -> 'タロウです! 25歳です!'
314
+ *
315
+ ***/
316
+ 'hankaku': function() {
317
+ return convertCharacterWidth(this, arguments, allZenkaku, 'hankaku');
318
+ },
319
+
320
+ /***
321
+ * @method zenkaku([mode] = 'all')
322
+ * @returns String
323
+ * @short Converts half-width characters (hankaku) to full-width (zenkaku).
324
+ * @extra [mode] accepts any combination of "a" (alphabet), "n" (numbers), "k" (katakana), "s" (spaces), "p" (punctuation), or "all".
325
+ * @example
326
+ *
327
+ * 'タロウ YAMADAです!'.zenkaku() -> 'タロウ YAMADAです!'
328
+ * 'タロウ YAMADAです!'.zenkaku('a') -> 'タロウ YAMADAです!'
329
+ * 'タロウ YAMADAです!'.zenkaku('alphabet') -> 'タロウ YAMADAです!'
330
+ * 'タロウです! 25歳です!'.zenkaku('katakana', 'numbers') -> 'タロウです! 25歳です!'
331
+ * 'タロウです! 25歳です!'.zenkaku('k', 'n') -> 'タロウです! 25歳です!'
332
+ * 'タロウです! 25歳です!'.zenkaku('kn') -> 'タロウです! 25歳です!'
333
+ * 'タロウです! 25歳です!'.zenkaku('sp') -> 'タロウです! 25歳です!'
334
+ *
335
+ ***/
336
+ 'zenkaku': function() {
337
+ return convertCharacterWidth(this, arguments, allHankaku, 'zenkaku');
338
+ },
339
+
340
+ /***
341
+ * @method hiragana([all] = true)
342
+ * @returns String
343
+ * @short Converts katakana into hiragana.
344
+ * @extra If [all] is false, only full-width katakana will be converted.
345
+ * @example
346
+ *
347
+ * 'カタカナ'.hiragana() -> 'かたかな'
348
+ * 'コンニチハ'.hiragana() -> 'こんにちは'
349
+ * 'カタカナ'.hiragana() -> 'かたかな'
350
+ * 'カタカナ'.hiragana(false) -> 'カタカナ'
351
+ *
352
+ ***/
353
+ 'hiragana': function(all) {
354
+ var str = this;
355
+ if(all !== false) {
356
+ str = str.zenkaku('k');
357
+ }
358
+ return str.replace(/[\u30A1-\u30F6]/g, function(c) {
359
+ return c.shift(-96);
360
+ });
361
+ },
362
+
363
+ /***
364
+ * @method katakana()
365
+ * @returns String
366
+ * @short Converts hiragana into katakana.
367
+ * @example
368
+ *
369
+ * 'かたかな'.katakana() -> 'カタカナ'
370
+ * 'こんにちは'.katakana() -> 'コンニチハ'
371
+ *
372
+ ***/
373
+ 'katakana': function() {
374
+ return this.replace(/[\u3041-\u3096]/g, function(c) {
375
+ return c.shift(96);
376
+ });
377
+ }
378
+
379
+
380
+ });
381
+
382
+ buildUnicodeScripts();
383
+
@@ -0,0 +1,422 @@
1
+
2
+ /***
3
+ * @package Number
4
+ * @dependency core
5
+ * @description Number formatting, rounding (with precision), and ranges. Aliases to Math methods.
6
+ *
7
+ ***/
8
+
9
+
10
+ function abbreviateNumber(num, roundTo, str, mid, limit, bytes) {
11
+ var fixed = num.toFixed(20),
12
+ decimalPlace = fixed.search(/\./),
13
+ numeralPlace = fixed.search(/[1-9]/),
14
+ significant = decimalPlace - numeralPlace,
15
+ unit, i, divisor;
16
+ if(significant > 0) {
17
+ significant -= 1;
18
+ }
19
+ i = math.max(math.min((significant / 3).floor(), limit === false ? str.length : limit), -mid);
20
+ unit = str.charAt(i + mid - 1);
21
+ if(significant < -9) {
22
+ i = -3;
23
+ roundTo = significant.abs() - 9;
24
+ unit = str.slice(0,1);
25
+ }
26
+ divisor = bytes ? (2).pow(10 * i) : (10).pow(i * 3);
27
+ return (num / divisor).round(roundTo || 0).format() + unit.trim();
28
+ }
29
+
30
+
31
+ extend(number, false, false, {
32
+
33
+ /***
34
+ * @method Number.random([n1], [n2])
35
+ * @returns Number
36
+ * @short Returns a random integer between [n1] and [n2].
37
+ * @extra If only 1 number is passed, the other will be 0. If none are passed, the number will be either 0 or 1.
38
+ * @example
39
+ *
40
+ * Number.random(50, 100) -> ex. 85
41
+ * Number.random(50) -> ex. 27
42
+ * Number.random() -> ex. 0
43
+ *
44
+ ***/
45
+ 'random': function(n1, n2) {
46
+ var min, max;
47
+ if(arguments.length == 1) n2 = n1, n1 = 0;
48
+ min = math.min(n1 || 0, isUndefined(n2) ? 1 : n2);
49
+ max = math.max(n1 || 0, isUndefined(n2) ? 1 : n2);
50
+ return round((math.random() * (max - min)) + min);
51
+ }
52
+
53
+ });
54
+
55
+ extend(number, true, false, {
56
+
57
+ /***
58
+ * @method log(<base> = Math.E)
59
+ * @returns Number
60
+ * @short Returns the logarithm of the number with base <base>, or natural logarithm of the number if <base> is undefined.
61
+ * @example
62
+ *
63
+ * (64).log(2) -> 6
64
+ * (9).log(3) -> 2
65
+ * (5).log() -> 1.6094379124341003
66
+ *
67
+ ***/
68
+
69
+ 'log': function(base) {
70
+ return math.log(this) / (base ? math.log(base) : 1);
71
+ },
72
+
73
+ /***
74
+ * @method abbr([precision] = 0)
75
+ * @returns String
76
+ * @short Returns an abbreviated form of the number.
77
+ * @extra [precision] will round to the given precision.
78
+ * @example
79
+ *
80
+ * (1000).abbr() -> "1k"
81
+ * (1000000).abbr() -> "1m"
82
+ * (1280).abbr(1) -> "1.3k"
83
+ *
84
+ ***/
85
+ 'abbr': function(precision) {
86
+ return abbreviateNumber(this, precision, 'kmbt', 0, 4);
87
+ },
88
+
89
+ /***
90
+ * @method metric([precision] = 0, [limit] = 1)
91
+ * @returns String
92
+ * @short Returns the number as a string in metric notation.
93
+ * @extra [precision] will round to the given precision. Both very large numbers and very small numbers are supported. [limit] is the upper limit for the units. The default is %1%, which is "kilo". If [limit] is %false%, the upper limit will be "exa". The lower limit is "nano", and cannot be changed.
94
+ * @example
95
+ *
96
+ * (1000).metric() -> "1k"
97
+ * (1000000).metric() -> "1,000k"
98
+ * (1000000).metric(0, false) -> "1M"
99
+ * (1249).metric(2) + 'g' -> "1.25kg"
100
+ * (0.025).metric() + 'm' -> "25mm"
101
+ *
102
+ ***/
103
+ 'metric': function(precision, limit) {
104
+ return abbreviateNumber(this, precision, 'nμm kMGTPE', 4, isUndefined(limit) ? 1 : limit);
105
+ },
106
+
107
+ /***
108
+ * @method bytes([precision] = 0, [limit] = 4)
109
+ * @returns String
110
+ * @short Returns an abbreviated form of the number, considered to be "Bytes".
111
+ * @extra [precision] will round to the given precision. [limit] is the upper limit for the units. The default is %4%, which is "terabytes" (TB). If [limit] is %false%, the upper limit will be "exa".
112
+ * @example
113
+ *
114
+ * (1000).bytes() -> "1kB"
115
+ * (1000).bytes(2) -> "0.98kB"
116
+ * ((10).pow(20)).bytes() -> "90,949,470TB"
117
+ * ((10).pow(20)).bytes(0, false) -> "87EB"
118
+ *
119
+ ***/
120
+ 'bytes': function(precision, limit) {
121
+ return abbreviateNumber(this, precision, 'kMGTPE', 0, isUndefined(limit) ? 4 : limit, true) + 'B';
122
+ },
123
+
124
+ /***
125
+ * @method isInteger()
126
+ * @returns Boolean
127
+ * @short Returns true if the number has no trailing decimal.
128
+ * @example
129
+ *
130
+ * (420).isInteger() -> true
131
+ * (4.5).isInteger() -> false
132
+ *
133
+ ***/
134
+ 'isInteger': function() {
135
+ return this % 1 == 0;
136
+ },
137
+
138
+ /***
139
+ * @method isOdd()
140
+ * @returns Boolean
141
+ * @short Returns true if the number is odd.
142
+ * @example
143
+ *
144
+ * (3).isOdd() -> true
145
+ * (18).isOdd() -> false
146
+ *
147
+ ***/
148
+ 'isOdd': function() {
149
+ return !this.isMultipleOf(2);
150
+ },
151
+
152
+ /***
153
+ * @method isEven()
154
+ * @returns Boolean
155
+ * @short Returns true if the number is even.
156
+ * @example
157
+ *
158
+ * (6).isEven() -> true
159
+ * (17).isEven() -> false
160
+ *
161
+ ***/
162
+ 'isEven': function() {
163
+ return this.isMultipleOf(2);
164
+ },
165
+
166
+ /***
167
+ * @method isMultipleOf(<num>)
168
+ * @returns Boolean
169
+ * @short Returns true if the number is a multiple of <num>.
170
+ * @example
171
+ *
172
+ * (6).isMultipleOf(2) -> true
173
+ * (17).isMultipleOf(2) -> false
174
+ * (32).isMultipleOf(4) -> true
175
+ * (34).isMultipleOf(4) -> false
176
+ *
177
+ ***/
178
+ 'isMultipleOf': function(num) {
179
+ return this % num === 0;
180
+ },
181
+
182
+
183
+ /***
184
+ * @method format([place] = 0, [thousands] = ',', [decimal] = '.')
185
+ * @returns String
186
+ * @short Formats the number to a readable string.
187
+ * @extra If [place] is %undefined%, will automatically determine the place. [thousands] is the character used for the thousands separator. [decimal] is the character used for the decimal point.
188
+ * @example
189
+ *
190
+ * (56782).format() -> '56,782'
191
+ * (56782).format(2) -> '56,782.00'
192
+ * (4388.43).format(2, ' ') -> '4 388.43'
193
+ * (4388.43).format(2, '.', ',') -> '4.388,43'
194
+ *
195
+ ***/
196
+ 'format': function(place, thousands, decimal) {
197
+ var str, split, method, after, r = /(\d+)(\d{3})/;
198
+ if(string(thousands).match(/\d/)) throw new TypeError('Thousands separator cannot contain numbers.');
199
+ str = isNumber(place) ? round(this, place || 0).toFixed(math.max(place, 0)) : this.toString();
200
+ thousands = thousands || ',';
201
+ decimal = decimal || '.';
202
+ split = str.split('.');
203
+ str = split[0];
204
+ after = split[1] || '';
205
+ while (str.match(r)) {
206
+ str = str.replace(r, '$1' + thousands + '$2');
207
+ }
208
+ if(after.length > 0) {
209
+ str += decimal + repeatString((place || 0) - after.length, '0') + after;
210
+ }
211
+ return str;
212
+ },
213
+
214
+ /***
215
+ * @method hex([pad] = 1)
216
+ * @returns String
217
+ * @short Converts the number to hexidecimal.
218
+ * @extra [pad] will pad the resulting string to that many places.
219
+ * @example
220
+ *
221
+ * (255).hex() -> 'ff';
222
+ * (255).hex(4) -> '00ff';
223
+ * (23654).hex() -> '5c66';
224
+ *
225
+ ***/
226
+ 'hex': function(pad) {
227
+ return this.pad(pad || 1, false, 16);
228
+ },
229
+
230
+ /***
231
+ * @method upto(<num>, [fn], [step] = 1)
232
+ * @returns Array
233
+ * @short Returns an array containing numbers from the number up to <num>.
234
+ * @extra Optionally calls [fn] callback for each number in that array. [step] allows multiples greater than 1.
235
+ * @example
236
+ *
237
+ * (2).upto(6) -> [2, 3, 4, 5, 6]
238
+ * (2).upto(6, function(n) {
239
+ * // This function is called 5 times receiving n as the value.
240
+ * });
241
+ * (2).upto(8, null, 2) -> [2, 4, 6, 8]
242
+ *
243
+ ***/
244
+ 'upto': function(num, fn, step) {
245
+ return getRange(this, num, fn, step || 1);
246
+ },
247
+
248
+ /***
249
+ * @method downto(<num>, [fn], [step] = 1)
250
+ * @returns Array
251
+ * @short Returns an array containing numbers from the number down to <num>.
252
+ * @extra Optionally calls [fn] callback for each number in that array. [step] allows multiples greater than 1.
253
+ * @example
254
+ *
255
+ * (8).downto(3) -> [8, 7, 6, 5, 4, 3]
256
+ * (8).downto(3, function(n) {
257
+ * // This function is called 6 times receiving n as the value.
258
+ * });
259
+ * (8).downto(2, null, 2) -> [8, 6, 4, 2]
260
+ *
261
+ ***/
262
+ 'downto': function(num, fn, step) {
263
+ return getRange(this, num, fn, -(step || 1));
264
+ },
265
+
266
+ /***
267
+ * @method times(<fn>)
268
+ * @returns Number
269
+ * @short Calls <fn> a number of times equivalent to the number.
270
+ * @example
271
+ *
272
+ * (8).times(function(i) {
273
+ * // This function is called 8 times.
274
+ * });
275
+ *
276
+ ***/
277
+ 'times': function(fn) {
278
+ if(fn) {
279
+ for(var i = 0; i < this; i++) {
280
+ fn.call(this, i);
281
+ }
282
+ }
283
+ return this.toNumber();
284
+ },
285
+
286
+ /***
287
+ * @method chr()
288
+ * @returns String
289
+ * @short Returns a string at the code point of the number.
290
+ * @example
291
+ *
292
+ * (65).chr() -> "A"
293
+ * (75).chr() -> "K"
294
+ *
295
+ ***/
296
+ 'chr': function() {
297
+ return string.fromCharCode(this);
298
+ },
299
+
300
+ /***
301
+ * @method pad(<place> = 0, [sign] = false, [base] = 10)
302
+ * @returns String
303
+ * @short Pads a number with "0" to <place>.
304
+ * @extra [sign] allows you to force the sign as well (+05, etc). [base] can change the base for numeral conversion.
305
+ * @example
306
+ *
307
+ * (5).pad(2) -> '05'
308
+ * (-5).pad(4) -> '-0005'
309
+ * (82).pad(3, true) -> '+082'
310
+ *
311
+ ***/
312
+ 'pad': function(place, sign, base) {
313
+ return padNumber(this, place, sign, base);
314
+ },
315
+
316
+ /***
317
+ * @method ordinalize()
318
+ * @returns String
319
+ * @short Returns an ordinalized (English) string, i.e. "1st", "2nd", etc.
320
+ * @example
321
+ *
322
+ * (1).ordinalize() -> '1st';
323
+ * (2).ordinalize() -> '2nd';
324
+ * (8).ordinalize() -> '8th';
325
+ *
326
+ ***/
327
+ 'ordinalize': function() {
328
+ var suffix, num = this.abs(), last = parseInt(num.toString().slice(-2));
329
+ return this + getOrdinalizedSuffix(last);
330
+ },
331
+
332
+ /***
333
+ * @method toNumber()
334
+ * @returns Number
335
+ * @short Returns a number. This is mostly for compatibility reasons.
336
+ * @example
337
+ *
338
+ * (420).toNumber() -> 420
339
+ *
340
+ ***/
341
+ 'toNumber': function() {
342
+ return parseFloat(this, 10);
343
+ }
344
+
345
+ });
346
+
347
+ /***
348
+ * @method round(<precision> = 0)
349
+ * @returns Number
350
+ * @short Shortcut for %Math.round% that also allows a <precision>.
351
+ *
352
+ * @example
353
+ *
354
+ * (3.241).round() -> 3
355
+ * (-3.841).round() -> -4
356
+ * (3.241).round(2) -> 3.24
357
+ * (3748).round(-2) -> 3800
358
+ *
359
+ ***
360
+ * @method ceil(<precision> = 0)
361
+ * @returns Number
362
+ * @short Shortcut for %Math.ceil% that also allows a <precision>.
363
+ *
364
+ * @example
365
+ *
366
+ * (3.241).ceil() -> 4
367
+ * (-3.241).ceil() -> -3
368
+ * (3.241).ceil(2) -> 3.25
369
+ * (3748).ceil(-2) -> 3800
370
+ *
371
+ ***
372
+ * @method floor(<precision> = 0)
373
+ * @returns Number
374
+ * @short Shortcut for %Math.floor% that also allows a <precision>.
375
+ *
376
+ * @example
377
+ *
378
+ * (3.241).floor() -> 3
379
+ * (-3.841).floor() -> -4
380
+ * (3.241).floor(2) -> 3.24
381
+ * (3748).floor(-2) -> 3700
382
+ *
383
+ ***
384
+ * @method [math]()
385
+ * @returns Number
386
+ * @short Math related functions are mapped as shortcuts to numbers and are identical. Note that %Number#log% provides some special defaults.
387
+ *
388
+ * @set
389
+ * abs
390
+ * sin
391
+ * asin
392
+ * cos
393
+ * acos
394
+ * tan
395
+ * atan
396
+ * sqrt
397
+ * exp
398
+ * pow
399
+ *
400
+ * @example
401
+ *
402
+ * (3).pow(3) -> 27
403
+ * (-3).abs() -> 3
404
+ * (1024).sqrt() -> 32
405
+ *
406
+ ***/
407
+
408
+ function buildNumber() {
409
+ extendSimilar(number, true, false, 'round,floor,ceil', function(methods, name) {
410
+ methods[name] = function(precision) {
411
+ return round(this, precision, name);
412
+ }
413
+ });
414
+ extendSimilar(number, true, false, 'abs,pow,sin,asin,cos,acos,tan,atan,exp,pow,sqrt', function(methods, name) {
415
+ methods[name] = function(a, b) {
416
+ return math[name](this, a, b);
417
+ }
418
+ });
419
+ }
420
+
421
+ buildNumber();
422
+