nutcracker-web 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +4 -13
  4. data/Rakefile +33 -7
  5. data/lib/nutcracker/web.rb +6 -6
  6. data/lib/nutcracker/web/app.rb +10 -8
  7. data/lib/nutcracker/web/version.rb +1 -1
  8. data/{assets/stylesheets/bootstrap.css → public/assets/application.css} +1136 -0
  9. data/public/assets/application.js +263 -0
  10. metadata +59 -32
  11. data/assets/javascripts/application.js +0 -10
  12. data/assets/javascripts/collections/clusters.js.coffee +0 -4
  13. data/assets/javascripts/collections/nodes.js.coffee +0 -19
  14. data/assets/javascripts/models/cluster.js.coffee +0 -16
  15. data/assets/javascripts/models/node.js.coffee +0 -14
  16. data/assets/javascripts/models/overview.js.coffee +0 -27
  17. data/assets/javascripts/nutcracker.js.coffee +0 -20
  18. data/assets/javascripts/routers/nutcracker_router.js.coffee +0 -29
  19. data/assets/javascripts/utils/region_manager.js.coffee +0 -12
  20. data/assets/javascripts/utils/underscore_ext.js.coffee +0 -6
  21. data/assets/javascripts/vendor/backbone.js +0 -1571
  22. data/assets/javascripts/vendor/bootstrap.js +0 -2276
  23. data/assets/javascripts/vendor/google_chart.js.coffee +0 -124
  24. data/assets/javascripts/vendor/humanize.js +0 -459
  25. data/assets/javascripts/vendor/jquery.js +0 -8842
  26. data/assets/javascripts/vendor/underscore.js +0 -1227
  27. data/assets/javascripts/views/cluster.js.coffee +0 -58
  28. data/assets/javascripts/views/config.js.coffee +0 -6
  29. data/assets/javascripts/views/footer.js.coffee +0 -8
  30. data/assets/javascripts/views/navbar.js.coffee +0 -28
  31. data/assets/javascripts/views/node.js.coffee +0 -54
  32. data/assets/javascripts/views/overview.js.coffee +0 -6
  33. data/assets/stylesheets/application.css +0 -24
  34. data/assets/stylesheets/bootstrap-responsive.css +0 -1109
  35. data/assets/templates/cluster.jst.eco +0 -87
  36. data/assets/templates/config.jst.eco +0 -15
  37. data/assets/templates/footer.jst.eco +0 -1
  38. data/assets/templates/navbar.jst.eco +0 -55
  39. data/assets/templates/node.jst.eco +0 -73
  40. data/assets/templates/overview.jst.eco +0 -32
@@ -1,124 +0,0 @@
1
- class Backbone.GoogleChart extends Backbone.View
2
- ###
3
- # Initialize a new GoogleChart object
4
- #
5
- # Example:
6
- # lineChart = new Backbone.GoogleChart({
7
- # chartType: 'ColumnChart',
8
- # dataTable: [['Germany', 'USA', 'Brazil', 'Canada', 'France', 'RU'],
9
- # [700, 300, 400, 500, 600, 800]],
10
- # options: {'title': 'Countries'},
11
- # });
12
- #
13
- # $('body').append( lineChart.render().el );
14
- #
15
- # For the complete list of options please checkout
16
- # https://developers.google.com/chart/interactive/docs/reference#chartwrapperobject
17
- #
18
- ###
19
- initialize: ( options ) ->
20
- chartOptions = _.extend({},options)
21
- ['el','id','attributes','className','tagName'].map (key)=>
22
- delete chartOptions[key]
23
-
24
- google.load 'visualization', '1', packages: ['corechart'], callback: =>
25
- @onGoogleLoad "loaded"
26
-
27
- @onGoogleLoad =>
28
- @google = google.visualization
29
- if chartOptions.dataTable instanceof Array
30
- chartOptions.dataTable = @google.arrayToDataTable chartOptions.dataTable
31
- (chartOptions.beforeDraw||->) @, chartOptions
32
-
33
- if formatter = chartOptions.formatter
34
- [0..chartOptions.dataTable.getNumberOfRows()-1].map (index)=>
35
- formatter.columns.map (column)=>
36
- chartOptions.dataTable.setFormattedValue(
37
- index, column, formatter.callback(
38
- chartOptions.dataTable.getValue index, column
39
- )
40
- )
41
-
42
- @wrapper = new @google.ChartWrapper chartOptions
43
- ['ready','select', 'error'].map @listen
44
-
45
- ###
46
- # Execute a callback once google visualization fully loaded
47
- ###
48
- onGoogleLoad: ( callback )=>
49
- if callback == "loaded"
50
- @googleLoaded = true
51
- _( @onGoogleLoadItems ).map (fn)-> fn()
52
- else
53
- if @googleLoaded
54
- callback()
55
- else
56
- (@onGoogleLoadItems ||= []).push callback
57
-
58
- ###
59
- # Execute a callback once a given element ID appears in DOM ( mini livequery ).
60
- #
61
- # We need it because GoogleChart object only draw itself on DOM elements
62
- # so we first need to wait for our element to be added to the DOM before
63
- # we call GoogleChart.draw().
64
- #
65
- # Usage:
66
- # Backbone.GoogleChart.watch("#myid", function() { console.log("I'm in") });
67
- # $("body").append("<div id='myid'></div>"); // 'I"m in' should be printed to console
68
- #
69
- ###
70
- @watch: ( id, fn ) =>
71
- (@_list ||= {})[id] = fn
72
- return if @_watching
73
- @_watching = true
74
-
75
- timeout = 10
76
- (func = =>
77
- _(@_list).map ( fn, id ) =>
78
- fn() || delete @_list[id] if $(id)[0]
79
- if _(@_list).isEmpty()
80
- @_watching = false
81
- else
82
- setTimeout(func, timeout+=10)
83
- )()
84
-
85
- ###
86
- # Returns the wrapping element id
87
- # if no id was specified on initialization a random one will be returned
88
- ###
89
- id: =>
90
- @el?.id or @randomID()
91
-
92
- ###
93
- # "Instruct" the current graph instance to draw itself once its visiable on DOM
94
- # return the current instance
95
- ###
96
- render: =>
97
- @onGoogleLoad =>
98
- @constructor.watch "##{@el.id}", =>
99
- @wrapper.draw @el.id
100
- this
101
-
102
- ###
103
- # Register for ChartWrapper events
104
- # For the complete event list please look at the events section under
105
- # https://developers.google.com/chart/interactive/docs/reference#chartwrapperobject
106
- #
107
- # By default the ready, select and error events are register automatically on initialization
108
- # so instead of calling this function directly consider this:
109
- # graph = new Backbone.GoogleChart({chartOptions: options});
110
- # graph.on("select",function(graph) { console.log("Someone click on me!") })
111
- # graph.on("error",function(graph) { console.log("Oops") })
112
- # graph.on("ready",function(graph) { console.log("I'm ready!") })
113
- #
114
- ###
115
- listen: ( event ) =>
116
- @google.events.addListener @wrapper, event, =>
117
- @trigger event, @wrapper.getChart()
118
-
119
- ###
120
- # Generate a random ID, gc_XXX
121
- ###
122
- randomID: ->
123
- _.uniqueId "gc_"
124
-
@@ -1,459 +0,0 @@
1
- // https://github.com/taijinlee/humanize
2
- (function() {
3
-
4
- // Baseline setup
5
- // --------------
6
-
7
- // Establish the root object, `window` in the browser, or `global` on the server.
8
- var root = this;
9
-
10
- // Save the previous value of the `humanize` variable.
11
- var previousHumanize = root.humanize;
12
-
13
- var humanize = {};
14
-
15
- if (typeof exports !== 'undefined') {
16
- if (typeof module !== 'undefined' && module.exports) {
17
- exports = module.exports = humanize;
18
- }
19
- exports.humanize = humanize;
20
- } else {
21
- if (typeof define === 'function' && define.amd) {
22
- define('humanize', function() {
23
- return humanize;
24
- });
25
- }
26
- root.humanize = humanize;
27
- }
28
-
29
- humanize.noConflict = function() {
30
- root.humanize = previousHumanize;
31
- return this;
32
- };
33
-
34
- humanize.pad = function(str, count, padChar, type) {
35
- str += '';
36
- if (!padChar) {
37
- padChar = ' ';
38
- } else if (padChar.length > 1) {
39
- padChar = padChar.charAt(0);
40
- }
41
- type = (type === undefined) ? 'left' : 'right';
42
-
43
- if (type === 'right') {
44
- while (str.length < count) {
45
- str = str + padChar;
46
- }
47
- } else {
48
- // default to left
49
- while (str.length < count) {
50
- str = padChar + str;
51
- }
52
- }
53
-
54
- return str;
55
- };
56
-
57
- // gets current unix time
58
- humanize.time = function() {
59
- return new Date().getTime() / 1000;
60
- };
61
-
62
- /**
63
- * PHP-inspired date
64
- */
65
-
66
- /* jan feb mar apr may jun jul aug sep oct nov dec */
67
- var dayTableCommon = [ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
68
- var dayTableLeap = [ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
69
- // var mtable_common[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
70
- // static int ml_table_leap[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
71
-
72
-
73
- humanize.date = function(format, timestamp) {
74
- var jsdate = ((timestamp === undefined) ? new Date() : // Not provided
75
- (timestamp instanceof Date) ? new Date(timestamp) : // JS Date()
76
- new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
77
- );
78
-
79
- var formatChr = /\\?([a-z])/gi;
80
- var formatChrCb = function (t, s) {
81
- return f[t] ? f[t]() : s;
82
- };
83
-
84
- var shortDayTxt = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
85
- var monthTxt = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
86
-
87
- var f = {
88
- /* Day */
89
- // Day of month w/leading 0; 01..31
90
- d: function () { return humanize.pad(f.j(), 2, '0'); },
91
-
92
- // Shorthand day name; Mon..Sun
93
- D: function () { return f.l().slice(0, 3); },
94
-
95
- // Day of month; 1..31
96
- j: function () { return jsdate.getDate(); },
97
-
98
- // Full day name; Monday..Sunday
99
- l: function () { return shortDayTxt[f.w()]; },
100
-
101
- // ISO-8601 day of week; 1[Mon]..7[Sun]
102
- N: function () { return f.w() || 7; },
103
-
104
- // Ordinal suffix for day of month; st, nd, rd, th
105
- S: function () {
106
- var j = f.j();
107
- return j > 4 && j < 21 ? 'th' : {1: 'st', 2: 'nd', 3: 'rd'}[j % 10] || 'th';
108
- },
109
-
110
- // Day of week; 0[Sun]..6[Sat]
111
- w: function () { return jsdate.getDay(); },
112
-
113
- // Day of year; 0..365
114
- z: function () {
115
- return (f.L() ? dayTableLeap[f.n()] : dayTableCommon[f.n()]) + f.j() - 1;
116
- },
117
-
118
- /* Week */
119
- // ISO-8601 week number
120
- W: function () {
121
- // days between midweek of this week and jan 4
122
- // (f.z() - f.N() + 1 + 3.5) - 3
123
- var midWeekDaysFromJan4 = f.z() - f.N() + 1.5;
124
- // 1 + number of weeks + rounded week
125
- return humanize.pad(1 + Math.floor(Math.abs(midWeekDaysFromJan4) / 7) + (midWeekDaysFromJan4 % 7 > 3.5 ? 1 : 0), 2, '0');
126
- },
127
-
128
- /* Month */
129
- // Full month name; January..December
130
- F: function () { return monthTxt[jsdate.getMonth()]; },
131
-
132
- // Month w/leading 0; 01..12
133
- m: function () { return humanize.pad(f.n(), 2, '0'); },
134
-
135
- // Shorthand month name; Jan..Dec
136
- M: function () { return f.F().slice(0, 3); },
137
-
138
- // Month; 1..12
139
- n: function () { return jsdate.getMonth() + 1; },
140
-
141
- // Days in month; 28..31
142
- t: function () { return (new Date(f.Y(), f.n(), 0)).getDate(); },
143
-
144
- /* Year */
145
- // Is leap year?; 0 or 1
146
- L: function () { return new Date(f.Y(), 1, 29).getMonth() === 1 ? 1 : 0; },
147
-
148
- // ISO-8601 year
149
- o: function () {
150
- var n = f.n();
151
- var W = f.W();
152
- return f.Y() + (n === 12 && W < 9 ? -1 : n === 1 && W > 9);
153
- },
154
-
155
- // Full year; e.g. 1980..2010
156
- Y: function () { return jsdate.getFullYear(); },
157
-
158
- // Last two digits of year; 00..99
159
- y: function () { return (String(f.Y())).slice(-2); },
160
-
161
- /* Time */
162
- // am or pm
163
- a: function () { return jsdate.getHours() > 11 ? 'pm' : 'am'; },
164
-
165
- // AM or PM
166
- A: function () { return f.a().toUpperCase(); },
167
-
168
- // Swatch Internet time; 000..999
169
- B: function () {
170
- var unixTime = jsdate.getTime() / 1000;
171
- var secondsPassedToday = unixTime % 86400 + 3600; // since it's based off of UTC+1
172
- if (secondsPassedToday < 0) { secondsPassedToday += 86400; }
173
- var beats = ((secondsPassedToday) / 86.4) % 1000;
174
- if (unixTime < 0) {
175
- return Math.ceil(beats);
176
- }
177
- return Math.floor(beats);
178
- },
179
-
180
- // 12-Hours; 1..12
181
- g: function () { return f.G() % 12 || 12; },
182
-
183
- // 24-Hours; 0..23
184
- G: function () { return jsdate.getHours(); },
185
-
186
- // 12-Hours w/leading 0; 01..12
187
- h: function () { return humanize.pad(f.g(), 2, '0'); },
188
-
189
- // 24-Hours w/leading 0; 00..23
190
- H: function () { return humanize.pad(f.G(), 2, '0'); },
191
-
192
- // Minutes w/leading 0; 00..59
193
- i: function () { return humanize.pad(jsdate.getMinutes(), 2, '0'); },
194
-
195
- // Seconds w/leading 0; 00..59
196
- s: function () { return humanize.pad(jsdate.getSeconds(), 2, '0'); },
197
-
198
- // Microseconds; 000000-999000
199
- u: function () { return humanize.pad(jsdate.getMilliseconds() * 1000, 6, '0'); },
200
-
201
- // Whether or not the date is in daylight savings time
202
- /*
203
- I: function () {
204
- // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
205
- // If they are not equal, then DST is observed.
206
- var Y = f.Y();
207
- return 0 + ((new Date(Y, 0) - Date.UTC(Y, 0)) !== (new Date(Y, 6) - Date.UTC(Y, 6)));
208
- },
209
- */
210
-
211
- // Difference to GMT in hour format; e.g. +0200
212
- O: function () {
213
- var tzo = jsdate.getTimezoneOffset();
214
- var tzoNum = Math.abs(tzo);
215
- return (tzo > 0 ? '-' : '+') + humanize.pad(Math.floor(tzoNum / 60) * 100 + tzoNum % 60, 4, '0');
216
- },
217
-
218
- // Difference to GMT w/colon; e.g. +02:00
219
- P: function () {
220
- var O = f.O();
221
- return (O.substr(0, 3) + ':' + O.substr(3, 2));
222
- },
223
-
224
- // Timezone offset in seconds (-43200..50400)
225
- Z: function () { return -jsdate.getTimezoneOffset() * 60; },
226
-
227
- // Full Date/Time, ISO-8601 date
228
- c: function () { return 'Y-m-d\\TH:i:sP'.replace(formatChr, formatChrCb); },
229
-
230
- // RFC 2822
231
- r: function () { return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb); },
232
-
233
- // Seconds since UNIX epoch
234
- U: function () { return jsdate.getTime() / 1000 || 0; }
235
- };
236
-
237
- return format.replace(formatChr, formatChrCb);
238
- };
239
-
240
-
241
- /**
242
- * format number by adding thousands separaters and significant digits while rounding
243
- */
244
- humanize.numberFormat = function(number, decimals, decPoint, thousandsSep) {
245
- decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
246
- decPoint = (decPoint === undefined) ? '.' : decPoint;
247
- thousandsSep = (thousandsSep === undefined) ? ',' : thousandsSep;
248
-
249
- var sign = number < 0 ? '-' : '';
250
- number = Math.abs(+number || 0);
251
-
252
- var intPart = parseInt(number.toFixed(decimals), 10) + '';
253
- var j = intPart.length > 3 ? intPart.length % 3 : 0;
254
-
255
- return sign + (j ? intPart.substr(0, j) + thousandsSep : '') + intPart.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep) + (decimals ? decPoint + Math.abs(number - intPart).toFixed(decimals).slice(2) : '');
256
- };
257
-
258
-
259
- /**
260
- * For dates that are the current day or within one day, return 'today', 'tomorrow' or 'yesterday', as appropriate.
261
- * Otherwise, format the date using the passed in format string.
262
- *
263
- * Examples (when 'today' is 17 Feb 2007):
264
- * 16 Feb 2007 becomes yesterday.
265
- * 17 Feb 2007 becomes today.
266
- * 18 Feb 2007 becomes tomorrow.
267
- * Any other day is formatted according to given argument or the DATE_FORMAT setting if no argument is given.
268
- */
269
- humanize.naturalDay = function(timestamp, format) {
270
- timestamp = (timestamp === undefined) ? humanize.time() : timestamp;
271
- format = (format === undefined) ? 'Y-m-d' : format;
272
-
273
- var oneDay = 86400;
274
- var d = new Date();
275
- var today = (new Date(d.getFullYear(), d.getMonth(), d.getDate())).getTime() / 1000;
276
-
277
- if (timestamp < today && timestamp >= today - oneDay) {
278
- return 'yesterday';
279
- } else if (timestamp >= today && timestamp < today + oneDay) {
280
- return 'today';
281
- } else if (timestamp >= today + oneDay && timestamp < today + 2 * oneDay) {
282
- return 'tomorrow';
283
- }
284
-
285
- return humanize.date(format, timestamp);
286
- };
287
-
288
- /**
289
- * returns a string representing how many seconds, minutes or hours ago it was or will be in the future
290
- * Will always return a relative time, most granular of seconds to least granular of years. See unit tests for more details
291
- */
292
- humanize.relativeTime = function(timestamp) {
293
- timestamp = (timestamp === undefined) ? humanize.time() : timestamp;
294
-
295
- var currTime = humanize.time();
296
- var timeDiff = currTime - timestamp;
297
-
298
- // within 2 seconds
299
- if (timeDiff < 2 && timeDiff > -2) {
300
- return (timeDiff >= 0 ? 'just ' : '') + 'now';
301
- }
302
-
303
- // within a minute
304
- if (timeDiff < 60 && timeDiff > -60) {
305
- return (timeDiff >= 0 ? Math.floor(timeDiff) + ' seconds ago' : 'in ' + Math.floor(-timeDiff) + ' seconds');
306
- }
307
-
308
- // within 2 minutes
309
- if (timeDiff < 120 && timeDiff > -120) {
310
- return (timeDiff >= 0 ? 'about a minute ago' : 'in about a minute');
311
- }
312
-
313
- // within an hour
314
- if (timeDiff < 3600 && timeDiff > -3600) {
315
- return (timeDiff >= 0 ? Math.floor(timeDiff / 60) + ' minutes ago' : 'in ' + Math.floor(-timeDiff / 60) + ' minutes');
316
- }
317
-
318
- // within 2 hours
319
- if (timeDiff < 7200 && timeDiff > -7200) {
320
- return (timeDiff >= 0 ? 'about an hour ago' : 'in about an hour');
321
- }
322
-
323
- // within 24 hours
324
- if (timeDiff < 86400 && timeDiff > -86400) {
325
- return (timeDiff >= 0 ? Math.floor(timeDiff / 3600) + ' hours ago' : 'in ' + Math.floor(-timeDiff / 3600) + ' hours');
326
- }
327
-
328
- // within 2 days
329
- var days2 = 2 * 86400;
330
- if (timeDiff < days2 && timeDiff > -days2) {
331
- return (timeDiff >= 0 ? '1 day ago' : 'in 1 day');
332
- }
333
-
334
- // within 29 days
335
- var days29 = 29 * 86400;
336
- if (timeDiff < days29 && timeDiff > -days29) {
337
- return (timeDiff >= 0 ? Math.floor(timeDiff / 86400) + ' days ago' : 'in ' + Math.floor(-timeDiff / 86400) + ' days');
338
- }
339
-
340
- // within 60 days
341
- var days60 = 60 * 86400;
342
- if (timeDiff < days60 && timeDiff > -days60) {
343
- return (timeDiff >= 0 ? 'about a month ago' : 'in about a month');
344
- }
345
-
346
- var currTimeYears = parseInt(humanize.date('Y', currTime), 10);
347
- var timestampYears = parseInt(humanize.date('Y', timestamp), 10);
348
- var currTimeMonths = currTimeYears * 12 + parseInt(humanize.date('n', currTime), 10);
349
- var timestampMonths = timestampYears * 12 + parseInt(humanize.date('n', timestamp), 10);
350
-
351
- // within a year
352
- var monthDiff = currTimeMonths - timestampMonths;
353
- if (monthDiff < 12 && monthDiff > -12) {
354
- return (monthDiff >= 0 ? monthDiff + ' months ago' : 'in ' + (-monthDiff) + ' months');
355
- }
356
-
357
- var yearDiff = currTimeYears - timestampYears;
358
- if (yearDiff < 2 && yearDiff > -2) {
359
- return (yearDiff >= 0 ? 'a year ago' : 'in a year');
360
- }
361
-
362
- return (yearDiff >= 0 ? yearDiff + ' years ago' : 'in ' + (-yearDiff) + ' years');
363
- };
364
-
365
- /**
366
- * Converts an integer to its ordinal as a string.
367
- *
368
- * 1 becomes 1st
369
- * 2 becomes 2nd
370
- * 3 becomes 3rd etc
371
- */
372
- humanize.ordinal = function(number) {
373
- number = parseInt(number, 10);
374
- number = isNaN(number) ? 0 : number;
375
- var sign = number < 0 ? '-' : '';
376
- number = Math.abs(number);
377
- var tens = number % 100;
378
-
379
- return sign + number + (tens > 4 && tens < 21 ? 'th' : {1: 'st', 2: 'nd', 3: 'rd'}[number % 10] || 'th');
380
- };
381
-
382
- /**
383
- * Formats the value like a 'human-readable' file size (i.e. '13 KB', '4.1 MB', '102 bytes', etc).
384
- *
385
- * For example:
386
- * If value is 123456789, the output would be 117.7 MB.
387
- */
388
- humanize.filesize = function(filesize, kilo, decimals, decPoint, thousandsSep) {
389
- kilo = (kilo === undefined) ? 1024 : kilo;
390
- decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
391
- decPoint = (decPoint === undefined) ? '.' : decPoint;
392
- thousandsSep = (thousandsSep === undefined) ? ',' : thousandsSep;
393
- if (filesize <= 0) { return '0 bytes'; }
394
-
395
- var thresholds = [1];
396
- var units = ['bytes', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb'];
397
- if (filesize < kilo) { return humanize.numberFormat(filesize, 0) + ' ' + units[0]; }
398
-
399
- for (var i = 1; i < units.length; i++) {
400
- thresholds[i] = thresholds[i-1] * kilo;
401
- if (filesize < thresholds[i]) {
402
- return humanize.numberFormat(filesize / thresholds[i-1], decimals, decPoint, thousandsSep) + ' ' + units[i-1];
403
- }
404
- }
405
-
406
- // use the last unit if we drop out to here
407
- return humanize.numberFormat(filesize / thresholds[units.length - 1], decimals, decPoint, thousandsSep) + ' ' + units[units.length - 1];
408
- };
409
-
410
- /**
411
- * Replaces line breaks in plain text with appropriate HTML
412
- * A single newline becomes an HTML line break (<br />) and a new line followed by a blank line becomes a paragraph break (</p>).
413
- *
414
- * For example:
415
- * If value is Joel\nis a\n\nslug, the output will be <p>Joel<br />is a</p><p>slug</p>
416
- */
417
- humanize.linebreaks = function(str) {
418
- // remove beginning and ending newlines
419
- str = str.replace(/^([\n|\r]*)/, '');
420
- str = str.replace(/([\n|\r]*)$/, '');
421
-
422
- // normalize all to \n
423
- str = str.replace(/(\r\n|\n|\r)/g, "\n");
424
-
425
- // any consecutive new lines more than 2 gets turned into p tags
426
- str = str.replace(/(\n{2,})/g, '</p><p>');
427
-
428
- // any that are singletons get turned into br
429
- str = str.replace(/\n/g, '<br />');
430
- return '<p>' + str + '</p>';
431
- };
432
-
433
- /**
434
- * Converts all newlines in a piece of plain text to HTML line breaks (<br />).
435
- */
436
- humanize.nl2br = function(str) {
437
- return str.replace(/(\r\n|\n|\r)/g, '<br />');
438
- };
439
-
440
- /**
441
- * Truncates a string if it is longer than the specified number of characters.
442
- * Truncated strings will end with a translatable ellipsis sequence ('…').
443
- */
444
- humanize.truncatechars = function(string, length) {
445
- if (string.length <= length) { return string; }
446
- return string.substr(0, length) + '…';
447
- };
448
-
449
- /**
450
- * Truncates a string after a certain number of words.
451
- * Newlines within the string will be removed.
452
- */
453
- humanize.truncatewords = function(string, numWords) {
454
- var words = string.split(' ');
455
- if (words.length < numWords) { return string; }
456
- return words.slice(0, numWords).join(' ') + '…';
457
- };
458
-
459
- }).call(this);