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.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/Gemfile.lock +4 -13
- data/Rakefile +33 -7
- data/lib/nutcracker/web.rb +6 -6
- data/lib/nutcracker/web/app.rb +10 -8
- data/lib/nutcracker/web/version.rb +1 -1
- data/{assets/stylesheets/bootstrap.css → public/assets/application.css} +1136 -0
- data/public/assets/application.js +263 -0
- metadata +59 -32
- data/assets/javascripts/application.js +0 -10
- data/assets/javascripts/collections/clusters.js.coffee +0 -4
- data/assets/javascripts/collections/nodes.js.coffee +0 -19
- data/assets/javascripts/models/cluster.js.coffee +0 -16
- data/assets/javascripts/models/node.js.coffee +0 -14
- data/assets/javascripts/models/overview.js.coffee +0 -27
- data/assets/javascripts/nutcracker.js.coffee +0 -20
- data/assets/javascripts/routers/nutcracker_router.js.coffee +0 -29
- data/assets/javascripts/utils/region_manager.js.coffee +0 -12
- data/assets/javascripts/utils/underscore_ext.js.coffee +0 -6
- data/assets/javascripts/vendor/backbone.js +0 -1571
- data/assets/javascripts/vendor/bootstrap.js +0 -2276
- data/assets/javascripts/vendor/google_chart.js.coffee +0 -124
- data/assets/javascripts/vendor/humanize.js +0 -459
- data/assets/javascripts/vendor/jquery.js +0 -8842
- data/assets/javascripts/vendor/underscore.js +0 -1227
- data/assets/javascripts/views/cluster.js.coffee +0 -58
- data/assets/javascripts/views/config.js.coffee +0 -6
- data/assets/javascripts/views/footer.js.coffee +0 -8
- data/assets/javascripts/views/navbar.js.coffee +0 -28
- data/assets/javascripts/views/node.js.coffee +0 -54
- data/assets/javascripts/views/overview.js.coffee +0 -6
- data/assets/stylesheets/application.css +0 -24
- data/assets/stylesheets/bootstrap-responsive.css +0 -1109
- data/assets/templates/cluster.jst.eco +0 -87
- data/assets/templates/config.jst.eco +0 -15
- data/assets/templates/footer.jst.eco +0 -1
- data/assets/templates/navbar.jst.eco +0 -55
- data/assets/templates/node.jst.eco +0 -73
- 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);
|