memcached-manager 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/.travis.yml +1 -1
- data/CONTRIBUTING.md +4 -4
- data/Dockerfile +7 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +23 -19
- data/README.rdoc +8 -5
- data/Rakefile +6 -6
- data/VERSION +1 -1
- data/features/api/run_command.feature +6 -0
- data/features/api/search_memcached_keys.feature +6 -0
- data/features/step_definitions/api/create_memcached_key.rb +1 -1
- data/features/step_definitions/api/list_memcached_keys.rb +1 -0
- data/features/step_definitions/api/run_command.rb +12 -0
- data/features/step_definitions/api/search_memcached_keys.rb +6 -0
- data/features/step_definitions/webapp/create_memcached_key.rb +13 -7
- data/features/step_definitions/webapp/delete_memcached_key.rb +7 -13
- data/features/step_definitions/webapp/edit_configs.rb +7 -0
- data/features/support/env.rb +3 -2
- data/features/webapp/edit_configs.feature +9 -0
- data/features/webapp/edit_memcached_key.feature +1 -1
- data/fig.yml +13 -0
- data/githubpage_idea +23 -0
- data/lib/api.rb +25 -7
- data/lib/extensions.rb +6 -0
- data/lib/extensions/memcached_command.rb +14 -0
- data/lib/extensions/memcached_connection.rb +9 -0
- data/lib/extensions/memcached_inspector.rb +12 -5
- data/lib/extensions/memcached_settings.rb +2 -2
- data/lib/public/images/favicon.png +0 -0
- data/lib/public/images/glyphicons-halflings.png +0 -0
- data/lib/public/images/logo.png +0 -0
- data/lib/public/images/org-logo.png +0 -0
- data/lib/public/images/search.png +0 -0
- data/lib/public/javascripts/angular/controllers.js +48 -3
- data/lib/public/javascripts/angular/filters.js +85 -0
- data/lib/public/javascripts/angular/routes.js +26 -0
- data/lib/public/javascripts/angular/services/notification.js +41 -6
- data/lib/public/javascripts/angular/services/query_params_singleton.js +10 -0
- data/lib/public/javascripts/angular/services/resources.js +13 -0
- data/lib/public/javascripts/application.js +38 -1
- data/lib/public/javascripts/humanize.js +473 -0
- data/lib/public/javascripts/humanize_duration.js +329 -0
- data/lib/public/javascripts/jquery-terminal.js +4335 -0
- data/lib/public/javascripts/underscore.js +5 -0
- data/lib/public/stylesheets/app.css +196 -10
- data/lib/public/stylesheets/buttons.css +107 -0
- data/lib/public/stylesheets/inputs.css +119 -0
- data/lib/public/stylesheets/jquery-terminal.css +184 -0
- data/lib/public/stylesheets/media_queries.css +162 -0
- data/lib/public/templates/config.html.erb +8 -0
- data/lib/public/templates/edit.html.erb +5 -3
- data/lib/public/templates/keys.html.erb +42 -31
- data/lib/public/templates/new.html.erb +6 -4
- data/lib/public/templates/show.html.erb +1 -1
- data/lib/public/templates/stats.html.erb +1 -2
- data/lib/routes.rb +3 -0
- data/lib/views/index.erb +24 -3
- data/lib/views/layout.erb +14 -1
- data/memcached-manager.gemspec +31 -5
- data/spec/lib/extensions/api_response_spec.rb +9 -7
- data/spec/lib/extensions/memcached_command_spec.rb +13 -0
- data/spec/lib/extensions/memcached_connection_spec.rb +9 -4
- data/spec/lib/extensions/memcached_inspector_spec.rb +38 -17
- data/spec/lib/extensions/memcached_settings_spec.rb +16 -16
- data/spec/spec_helper.rb +2 -4
- metadata +48 -21
@@ -0,0 +1,473 @@
|
|
1
|
+
(function() {
|
2
|
+
|
3
|
+
// Baseline setup
|
4
|
+
// --------------
|
5
|
+
|
6
|
+
// Establish the root object, `window` in the browser, or `global` on the server.
|
7
|
+
var root = this;
|
8
|
+
|
9
|
+
// Save the previous value of the `humanize` variable.
|
10
|
+
var previousHumanize = root.humanize;
|
11
|
+
|
12
|
+
var humanize = {};
|
13
|
+
|
14
|
+
if (typeof exports !== 'undefined') {
|
15
|
+
if (typeof module !== 'undefined' && module.exports) {
|
16
|
+
exports = module.exports = humanize;
|
17
|
+
}
|
18
|
+
exports.humanize = humanize;
|
19
|
+
} else {
|
20
|
+
if (typeof define === 'function' && define.amd) {
|
21
|
+
define('humanize', function() {
|
22
|
+
return humanize;
|
23
|
+
});
|
24
|
+
}
|
25
|
+
root.humanize = humanize;
|
26
|
+
}
|
27
|
+
|
28
|
+
humanize.noConflict = function() {
|
29
|
+
root.humanize = previousHumanize;
|
30
|
+
return this;
|
31
|
+
};
|
32
|
+
|
33
|
+
humanize.pad = function(str, count, padChar, type) {
|
34
|
+
str += '';
|
35
|
+
if (!padChar) {
|
36
|
+
padChar = ' ';
|
37
|
+
} else if (padChar.length > 1) {
|
38
|
+
padChar = padChar.charAt(0);
|
39
|
+
}
|
40
|
+
type = (type === undefined) ? 'left' : 'right';
|
41
|
+
|
42
|
+
if (type === 'right') {
|
43
|
+
while (str.length < count) {
|
44
|
+
str = str + padChar;
|
45
|
+
}
|
46
|
+
} else {
|
47
|
+
// default to left
|
48
|
+
while (str.length < count) {
|
49
|
+
str = padChar + str;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
return str;
|
54
|
+
};
|
55
|
+
|
56
|
+
// gets current unix time
|
57
|
+
humanize.time = function() {
|
58
|
+
return new Date().getTime() / 1000;
|
59
|
+
};
|
60
|
+
|
61
|
+
/**
|
62
|
+
* PHP-inspired date
|
63
|
+
*/
|
64
|
+
|
65
|
+
/* jan feb mar apr may jun jul aug sep oct nov dec */
|
66
|
+
var dayTableCommon = [ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
|
67
|
+
var dayTableLeap = [ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
|
68
|
+
// var mtable_common[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
69
|
+
// static int ml_table_leap[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
70
|
+
|
71
|
+
|
72
|
+
humanize.date = function(format, timestamp) {
|
73
|
+
var jsdate = ((timestamp === undefined) ? new Date() : // Not provided
|
74
|
+
(timestamp instanceof Date) ? new Date(timestamp) : // JS Date()
|
75
|
+
new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
|
76
|
+
);
|
77
|
+
|
78
|
+
var formatChr = /\\?([a-z])/gi;
|
79
|
+
var formatChrCb = function (t, s) {
|
80
|
+
return f[t] ? f[t]() : s;
|
81
|
+
};
|
82
|
+
|
83
|
+
var shortDayTxt = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
84
|
+
var monthTxt = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
85
|
+
|
86
|
+
var f = {
|
87
|
+
/* Day */
|
88
|
+
// Day of month w/leading 0; 01..31
|
89
|
+
d: function () { return humanize.pad(f.j(), 2, '0'); },
|
90
|
+
|
91
|
+
// Shorthand day name; Mon..Sun
|
92
|
+
D: function () { return f.l().slice(0, 3); },
|
93
|
+
|
94
|
+
// Day of month; 1..31
|
95
|
+
j: function () { return jsdate.getDate(); },
|
96
|
+
|
97
|
+
// Full day name; Monday..Sunday
|
98
|
+
l: function () { return shortDayTxt[f.w()]; },
|
99
|
+
|
100
|
+
// ISO-8601 day of week; 1[Mon]..7[Sun]
|
101
|
+
N: function () { return f.w() || 7; },
|
102
|
+
|
103
|
+
// Ordinal suffix for day of month; st, nd, rd, th
|
104
|
+
S: function () {
|
105
|
+
var j = f.j();
|
106
|
+
return j > 4 && j < 21 ? 'th' : {1: 'st', 2: 'nd', 3: 'rd'}[j % 10] || 'th';
|
107
|
+
},
|
108
|
+
|
109
|
+
// Day of week; 0[Sun]..6[Sat]
|
110
|
+
w: function () { return jsdate.getDay(); },
|
111
|
+
|
112
|
+
// Day of year; 0..365
|
113
|
+
z: function () {
|
114
|
+
return (f.L() ? dayTableLeap[f.n()] : dayTableCommon[f.n()]) + f.j() - 1;
|
115
|
+
},
|
116
|
+
|
117
|
+
/* Week */
|
118
|
+
// ISO-8601 week number
|
119
|
+
W: function () {
|
120
|
+
// days between midweek of this week and jan 4
|
121
|
+
// (f.z() - f.N() + 1 + 3.5) - 3
|
122
|
+
var midWeekDaysFromJan4 = f.z() - f.N() + 1.5;
|
123
|
+
// 1 + number of weeks + rounded week
|
124
|
+
return humanize.pad(1 + Math.floor(Math.abs(midWeekDaysFromJan4) / 7) + (midWeekDaysFromJan4 % 7 > 3.5 ? 1 : 0), 2, '0');
|
125
|
+
},
|
126
|
+
|
127
|
+
/* Month */
|
128
|
+
// Full month name; January..December
|
129
|
+
F: function () { return monthTxt[jsdate.getMonth()]; },
|
130
|
+
|
131
|
+
// Month w/leading 0; 01..12
|
132
|
+
m: function () { return humanize.pad(f.n(), 2, '0'); },
|
133
|
+
|
134
|
+
// Shorthand month name; Jan..Dec
|
135
|
+
M: function () { return f.F().slice(0, 3); },
|
136
|
+
|
137
|
+
// Month; 1..12
|
138
|
+
n: function () { return jsdate.getMonth() + 1; },
|
139
|
+
|
140
|
+
// Days in month; 28..31
|
141
|
+
t: function () { return (new Date(f.Y(), f.n(), 0)).getDate(); },
|
142
|
+
|
143
|
+
/* Year */
|
144
|
+
// Is leap year?; 0 or 1
|
145
|
+
L: function () { return new Date(f.Y(), 1, 29).getMonth() === 1 ? 1 : 0; },
|
146
|
+
|
147
|
+
// ISO-8601 year
|
148
|
+
o: function () {
|
149
|
+
var n = f.n();
|
150
|
+
var W = f.W();
|
151
|
+
return f.Y() + (n === 12 && W < 9 ? -1 : n === 1 && W > 9);
|
152
|
+
},
|
153
|
+
|
154
|
+
// Full year; e.g. 1980..2010
|
155
|
+
Y: function () { return jsdate.getFullYear(); },
|
156
|
+
|
157
|
+
// Last two digits of year; 00..99
|
158
|
+
y: function () { return (String(f.Y())).slice(-2); },
|
159
|
+
|
160
|
+
/* Time */
|
161
|
+
// am or pm
|
162
|
+
a: function () { return jsdate.getHours() > 11 ? 'pm' : 'am'; },
|
163
|
+
|
164
|
+
// AM or PM
|
165
|
+
A: function () { return f.a().toUpperCase(); },
|
166
|
+
|
167
|
+
// Swatch Internet time; 000..999
|
168
|
+
B: function () {
|
169
|
+
var unixTime = jsdate.getTime() / 1000;
|
170
|
+
var secondsPassedToday = unixTime % 86400 + 3600; // since it's based off of UTC+1
|
171
|
+
if (secondsPassedToday < 0) { secondsPassedToday += 86400; }
|
172
|
+
var beats = ((secondsPassedToday) / 86.4) % 1000;
|
173
|
+
if (unixTime < 0) {
|
174
|
+
return Math.ceil(beats);
|
175
|
+
}
|
176
|
+
return Math.floor(beats);
|
177
|
+
},
|
178
|
+
|
179
|
+
// 12-Hours; 1..12
|
180
|
+
g: function () { return f.G() % 12 || 12; },
|
181
|
+
|
182
|
+
// 24-Hours; 0..23
|
183
|
+
G: function () { return jsdate.getHours(); },
|
184
|
+
|
185
|
+
// 12-Hours w/leading 0; 01..12
|
186
|
+
h: function () { return humanize.pad(f.g(), 2, '0'); },
|
187
|
+
|
188
|
+
// 24-Hours w/leading 0; 00..23
|
189
|
+
H: function () { return humanize.pad(f.G(), 2, '0'); },
|
190
|
+
|
191
|
+
// Minutes w/leading 0; 00..59
|
192
|
+
i: function () { return humanize.pad(jsdate.getMinutes(), 2, '0'); },
|
193
|
+
|
194
|
+
// Seconds w/leading 0; 00..59
|
195
|
+
s: function () { return humanize.pad(jsdate.getSeconds(), 2, '0'); },
|
196
|
+
|
197
|
+
// Microseconds; 000000-999000
|
198
|
+
u: function () { return humanize.pad(jsdate.getMilliseconds() * 1000, 6, '0'); },
|
199
|
+
|
200
|
+
// Whether or not the date is in daylight savings time
|
201
|
+
/*
|
202
|
+
I: function () {
|
203
|
+
// Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
|
204
|
+
// If they are not equal, then DST is observed.
|
205
|
+
var Y = f.Y();
|
206
|
+
return 0 + ((new Date(Y, 0) - Date.UTC(Y, 0)) !== (new Date(Y, 6) - Date.UTC(Y, 6)));
|
207
|
+
},
|
208
|
+
*/
|
209
|
+
|
210
|
+
// Difference to GMT in hour format; e.g. +0200
|
211
|
+
O: function () {
|
212
|
+
var tzo = jsdate.getTimezoneOffset();
|
213
|
+
var tzoNum = Math.abs(tzo);
|
214
|
+
return (tzo > 0 ? '-' : '+') + humanize.pad(Math.floor(tzoNum / 60) * 100 + tzoNum % 60, 4, '0');
|
215
|
+
},
|
216
|
+
|
217
|
+
// Difference to GMT w/colon; e.g. +02:00
|
218
|
+
P: function () {
|
219
|
+
var O = f.O();
|
220
|
+
return (O.substr(0, 3) + ':' + O.substr(3, 2));
|
221
|
+
},
|
222
|
+
|
223
|
+
// Timezone offset in seconds (-43200..50400)
|
224
|
+
Z: function () { return -jsdate.getTimezoneOffset() * 60; },
|
225
|
+
|
226
|
+
// Full Date/Time, ISO-8601 date
|
227
|
+
c: function () { return 'Y-m-d\\TH:i:sP'.replace(formatChr, formatChrCb); },
|
228
|
+
|
229
|
+
// RFC 2822
|
230
|
+
r: function () { return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb); },
|
231
|
+
|
232
|
+
// Seconds since UNIX epoch
|
233
|
+
U: function () { return jsdate.getTime() / 1000 || 0; }
|
234
|
+
};
|
235
|
+
|
236
|
+
return format.replace(formatChr, formatChrCb);
|
237
|
+
};
|
238
|
+
|
239
|
+
|
240
|
+
/**
|
241
|
+
* format number by adding thousands separaters and significant digits while rounding
|
242
|
+
*/
|
243
|
+
humanize.numberFormat = function(number, decimals, decPoint, thousandsSep) {
|
244
|
+
decimals = isNaN(decimals) ? 2 : Math.abs(decimals);
|
245
|
+
decPoint = (decPoint === undefined) ? '.' : decPoint;
|
246
|
+
thousandsSep = (thousandsSep === undefined) ? ',' : thousandsSep;
|
247
|
+
|
248
|
+
var sign = number < 0 ? '-' : '';
|
249
|
+
number = Math.abs(+number || 0);
|
250
|
+
|
251
|
+
var intPart = parseInt(number.toFixed(decimals), 10) + '';
|
252
|
+
var j = intPart.length > 3 ? intPart.length % 3 : 0;
|
253
|
+
|
254
|
+
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) : '');
|
255
|
+
};
|
256
|
+
|
257
|
+
|
258
|
+
/**
|
259
|
+
* For dates that are the current day or within one day, return 'today', 'tomorrow' or 'yesterday', as appropriate.
|
260
|
+
* Otherwise, format the date using the passed in format string.
|
261
|
+
*
|
262
|
+
* Examples (when 'today' is 17 Feb 2007):
|
263
|
+
* 16 Feb 2007 becomes yesterday.
|
264
|
+
* 17 Feb 2007 becomes today.
|
265
|
+
* 18 Feb 2007 becomes tomorrow.
|
266
|
+
* Any other day is formatted according to given argument or the DATE_FORMAT setting if no argument is given.
|
267
|
+
*/
|
268
|
+
humanize.naturalDay = function(timestamp, format) {
|
269
|
+
timestamp = (timestamp === undefined) ? humanize.time() : timestamp;
|
270
|
+
format = (format === undefined) ? 'Y-m-d' : format;
|
271
|
+
|
272
|
+
var oneDay = 86400;
|
273
|
+
var d = new Date();
|
274
|
+
var today = (new Date(d.getFullYear(), d.getMonth(), d.getDate())).getTime() / 1000;
|
275
|
+
|
276
|
+
if (timestamp < today && timestamp >= today - oneDay) {
|
277
|
+
return 'yesterday';
|
278
|
+
} else if (timestamp >= today && timestamp < today + oneDay) {
|
279
|
+
return 'today';
|
280
|
+
} else if (timestamp >= today + oneDay && timestamp < today + 2 * oneDay) {
|
281
|
+
return 'tomorrow';
|
282
|
+
}
|
283
|
+
|
284
|
+
return humanize.date(format, timestamp);
|
285
|
+
};
|
286
|
+
|
287
|
+
/**
|
288
|
+
* returns a string representing how many seconds, minutes or hours ago it was or will be in the future
|
289
|
+
* Will always return a relative time, most granular of seconds to least granular of years. See unit tests for more details
|
290
|
+
*/
|
291
|
+
humanize.relativeTime = function(timestamp) {
|
292
|
+
timestamp = (timestamp === undefined) ? humanize.time() : timestamp;
|
293
|
+
|
294
|
+
var currTime = humanize.time();
|
295
|
+
var timeDiff = currTime - timestamp;
|
296
|
+
|
297
|
+
// within 2 seconds
|
298
|
+
if (timeDiff < 2 && timeDiff > -2) {
|
299
|
+
return (timeDiff >= 0 ? 'just ' : '') + 'now';
|
300
|
+
}
|
301
|
+
|
302
|
+
// within a minute
|
303
|
+
if (timeDiff < 60 && timeDiff > -60) {
|
304
|
+
return (timeDiff >= 0 ? Math.floor(timeDiff) + ' seconds ago' : 'in ' + Math.floor(-timeDiff) + ' seconds');
|
305
|
+
}
|
306
|
+
|
307
|
+
// within 2 minutes
|
308
|
+
if (timeDiff < 120 && timeDiff > -120) {
|
309
|
+
return (timeDiff >= 0 ? 'about a minute ago' : 'in about a minute');
|
310
|
+
}
|
311
|
+
|
312
|
+
// within an hour
|
313
|
+
if (timeDiff < 3600 && timeDiff > -3600) {
|
314
|
+
return (timeDiff >= 0 ? Math.floor(timeDiff / 60) + ' minutes ago' : 'in ' + Math.floor(-timeDiff / 60) + ' minutes');
|
315
|
+
}
|
316
|
+
|
317
|
+
// within 2 hours
|
318
|
+
if (timeDiff < 7200 && timeDiff > -7200) {
|
319
|
+
return (timeDiff >= 0 ? 'about an hour ago' : 'in about an hour');
|
320
|
+
}
|
321
|
+
|
322
|
+
// within 24 hours
|
323
|
+
if (timeDiff < 86400 && timeDiff > -86400) {
|
324
|
+
return (timeDiff >= 0 ? Math.floor(timeDiff / 3600) + ' hours ago' : 'in ' + Math.floor(-timeDiff / 3600) + ' hours');
|
325
|
+
}
|
326
|
+
|
327
|
+
// within 2 days
|
328
|
+
var days2 = 2 * 86400;
|
329
|
+
if (timeDiff < days2 && timeDiff > -days2) {
|
330
|
+
return (timeDiff >= 0 ? '1 day ago' : 'in 1 day');
|
331
|
+
}
|
332
|
+
|
333
|
+
// within 29 days
|
334
|
+
var days29 = 29 * 86400;
|
335
|
+
if (timeDiff < days29 && timeDiff > -days29) {
|
336
|
+
return (timeDiff >= 0 ? Math.floor(timeDiff / 86400) + ' days ago' : 'in ' + Math.floor(-timeDiff / 86400) + ' days');
|
337
|
+
}
|
338
|
+
|
339
|
+
// within 60 days
|
340
|
+
var days60 = 60 * 86400;
|
341
|
+
if (timeDiff < days60 && timeDiff > -days60) {
|
342
|
+
return (timeDiff >= 0 ? 'about a month ago' : 'in about a month');
|
343
|
+
}
|
344
|
+
|
345
|
+
var currTimeYears = parseInt(humanize.date('Y', currTime), 10);
|
346
|
+
var timestampYears = parseInt(humanize.date('Y', timestamp), 10);
|
347
|
+
var currTimeMonths = currTimeYears * 12 + parseInt(humanize.date('n', currTime), 10);
|
348
|
+
var timestampMonths = timestampYears * 12 + parseInt(humanize.date('n', timestamp), 10);
|
349
|
+
|
350
|
+
// within a year
|
351
|
+
var monthDiff = currTimeMonths - timestampMonths;
|
352
|
+
if (monthDiff < 12 && monthDiff > -12) {
|
353
|
+
return (monthDiff >= 0 ? monthDiff + ' months ago' : 'in ' + (-monthDiff) + ' months');
|
354
|
+
}
|
355
|
+
|
356
|
+
var yearDiff = currTimeYears - timestampYears;
|
357
|
+
if (yearDiff < 2 && yearDiff > -2) {
|
358
|
+
return (yearDiff >= 0 ? 'a year ago' : 'in a year');
|
359
|
+
}
|
360
|
+
|
361
|
+
return (yearDiff >= 0 ? yearDiff + ' years ago' : 'in ' + (-yearDiff) + ' years');
|
362
|
+
};
|
363
|
+
|
364
|
+
/**
|
365
|
+
* Converts an integer to its ordinal as a string.
|
366
|
+
*
|
367
|
+
* 1 becomes 1st
|
368
|
+
* 2 becomes 2nd
|
369
|
+
* 3 becomes 3rd etc
|
370
|
+
*/
|
371
|
+
humanize.ordinal = function(number) {
|
372
|
+
number = parseInt(number, 10);
|
373
|
+
number = isNaN(number) ? 0 : number;
|
374
|
+
var sign = number < 0 ? '-' : '';
|
375
|
+
number = Math.abs(number);
|
376
|
+
var tens = number % 100;
|
377
|
+
|
378
|
+
return sign + number + (tens > 4 && tens < 21 ? 'th' : {1: 'st', 2: 'nd', 3: 'rd'}[number % 10] || 'th');
|
379
|
+
};
|
380
|
+
|
381
|
+
/**
|
382
|
+
* Formats the value like a 'human-readable' file size (i.e. '13 KB', '4.1 MB', '102 bytes', etc).
|
383
|
+
*
|
384
|
+
* For example:
|
385
|
+
* If value is 123456789, the output would be 117.7 MB.
|
386
|
+
*/
|
387
|
+
humanize.filesize = function(filesize, kilo, decimals, decPoint, thousandsSep, suffixSep) {
|
388
|
+
kilo = (kilo === undefined) ? 1024 : kilo;
|
389
|
+
if (filesize <= 0) { return '0 bytes'; }
|
390
|
+
if (filesize < kilo && decimals === undefined) { decimals = 0; }
|
391
|
+
if (suffixSep === undefined) { suffixSep = ' '; }
|
392
|
+
return humanize.intword(filesize, ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'], kilo, decimals, decPoint, thousandsSep, suffixSep);
|
393
|
+
};
|
394
|
+
|
395
|
+
/**
|
396
|
+
* Formats the value like a 'human-readable' number (i.e. '13 K', '4.1 M', '102', etc).
|
397
|
+
*
|
398
|
+
* For example:
|
399
|
+
* If value is 123456789, the output would be 117.7 M.
|
400
|
+
*/
|
401
|
+
humanize.intword = function(number, units, kilo, decimals, decPoint, thousandsSep, suffixSep) {
|
402
|
+
var humanized, unit;
|
403
|
+
|
404
|
+
units = units || ['', 'K', 'M', 'B', 'T'],
|
405
|
+
unit = units.length - 1,
|
406
|
+
kilo = kilo || 1000,
|
407
|
+
decimals = isNaN(decimals) ? 2 : Math.abs(decimals),
|
408
|
+
decPoint = decPoint || '.',
|
409
|
+
thousandsSep = thousandsSep || ',',
|
410
|
+
suffixSep = suffixSep || '';
|
411
|
+
|
412
|
+
for (var i=0; i < units.length; i++) {
|
413
|
+
if (number < Math.pow(kilo, i+1)) {
|
414
|
+
unit = i;
|
415
|
+
break;
|
416
|
+
}
|
417
|
+
}
|
418
|
+
humanized = number / Math.pow(kilo, unit);
|
419
|
+
|
420
|
+
var suffix = units[unit] ? suffixSep + units[unit] : '';
|
421
|
+
return humanize.numberFormat(humanized, decimals, decPoint, thousandsSep) + suffix;
|
422
|
+
};
|
423
|
+
|
424
|
+
/**
|
425
|
+
* Replaces line breaks in plain text with appropriate HTML
|
426
|
+
* A single newline becomes an HTML line break (<br />) and a new line followed by a blank line becomes a paragraph break (</p>).
|
427
|
+
*
|
428
|
+
* For example:
|
429
|
+
* If value is Joel\nis a\n\nslug, the output will be <p>Joel<br />is a</p><p>slug</p>
|
430
|
+
*/
|
431
|
+
humanize.linebreaks = function(str) {
|
432
|
+
// remove beginning and ending newlines
|
433
|
+
str = str.replace(/^([\n|\r]*)/, '');
|
434
|
+
str = str.replace(/([\n|\r]*)$/, '');
|
435
|
+
|
436
|
+
// normalize all to \n
|
437
|
+
str = str.replace(/(\r\n|\n|\r)/g, "\n");
|
438
|
+
|
439
|
+
// any consecutive new lines more than 2 gets turned into p tags
|
440
|
+
str = str.replace(/(\n{2,})/g, '</p><p>');
|
441
|
+
|
442
|
+
// any that are singletons get turned into br
|
443
|
+
str = str.replace(/\n/g, '<br />');
|
444
|
+
return '<p>' + str + '</p>';
|
445
|
+
};
|
446
|
+
|
447
|
+
/**
|
448
|
+
* Converts all newlines in a piece of plain text to HTML line breaks (<br />).
|
449
|
+
*/
|
450
|
+
humanize.nl2br = function(str) {
|
451
|
+
return str.replace(/(\r\n|\n|\r)/g, '<br />');
|
452
|
+
};
|
453
|
+
|
454
|
+
/**
|
455
|
+
* Truncates a string if it is longer than the specified number of characters.
|
456
|
+
* Truncated strings will end with a translatable ellipsis sequence ('…').
|
457
|
+
*/
|
458
|
+
humanize.truncatechars = function(string, length) {
|
459
|
+
if (string.length <= length) { return string; }
|
460
|
+
return string.substr(0, length) + '…';
|
461
|
+
};
|
462
|
+
|
463
|
+
/**
|
464
|
+
* Truncates a string after a certain number of words.
|
465
|
+
* Newlines within the string will be removed.
|
466
|
+
*/
|
467
|
+
humanize.truncatewords = function(string, numWords) {
|
468
|
+
var words = string.split(' ');
|
469
|
+
if (words.length < numWords) { return string; }
|
470
|
+
return words.slice(0, numWords).join(' ') + '…';
|
471
|
+
};
|
472
|
+
|
473
|
+
}).call(this);
|