riemann-dash 0.1.1 → 0.2.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.
- data/lib/riemann/dash/controller/index.rb +46 -1
- data/lib/riemann/dash/public/dash.js +6 -3
- data/lib/riemann/dash/public/persistence.js +2 -2
- data/lib/riemann/dash/public/subs.js +117 -12
- data/lib/riemann/dash/public/toastr.css +174 -0
- data/lib/riemann/dash/public/toastr.js +207 -0
- data/lib/riemann/dash/public/util.js +31 -0
- data/lib/riemann/dash/public/views/gauge.js +4 -4
- data/lib/riemann/dash/public/views/grid.js +11 -11
- data/lib/riemann/dash/public/views/title.js +4 -2
- data/lib/riemann/dash/version.rb +1 -1
- data/lib/riemann/dash/views/css.scss +83 -57
- data/lib/riemann/dash/views/index.erubis +200 -6
- data/lib/riemann/dash.rb +7 -38
- metadata +35 -66
- data/lib/riemann/dash/controller/websockets.rb +0 -50
- data/lib/riemann/dash/helper/renderer.rb +0 -266
- data/lib/riemann/dash/views/websockets.erubis +0 -201
@@ -1,4 +1,5 @@
|
|
1
1
|
var util = (function() {
|
2
|
+
// Unique IDs
|
2
3
|
var uniqueId = function(bytes) {
|
3
4
|
bytes = bytes || 20;
|
4
5
|
var s = '';
|
@@ -13,8 +14,38 @@ var util = (function() {
|
|
13
14
|
return _.extend(_.clone(m1), m2);
|
14
15
|
}
|
15
16
|
|
17
|
+
// Wraps a function in another, which calls f at most once every period
|
18
|
+
// milliseconds. Tries to minimize latency.
|
19
|
+
var slur = function(period, f) {
|
20
|
+
var lastRun = new Date();
|
21
|
+
lastRun.setYear(0);
|
22
|
+
var queued = false;
|
23
|
+
var execute = function(context, args) {
|
24
|
+
f.apply(context, args);
|
25
|
+
lastRun = new Date();
|
26
|
+
queued = false;
|
27
|
+
};
|
28
|
+
|
29
|
+
return function() {
|
30
|
+
// If queued, do nothing
|
31
|
+
if (queued) {
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
35
|
+
var dt = (new Date()) - lastRun;
|
36
|
+
if (period <= dt) {
|
37
|
+
// We're free to go
|
38
|
+
execute(this, arguments);
|
39
|
+
} else {
|
40
|
+
// Too soon, enqueue a new job.
|
41
|
+
window.setTimeout(execute, period - dt, this, arguments);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
16
46
|
return {
|
17
47
|
merge: merge,
|
48
|
+
slur: slur,
|
18
49
|
uniqueId: uniqueId
|
19
50
|
}
|
20
51
|
})();
|
@@ -10,12 +10,12 @@
|
|
10
10
|
this.el.append(
|
11
11
|
'<div class="box">' +
|
12
12
|
'<div class="quickfit metric value">?</div>' +
|
13
|
-
'<
|
13
|
+
'<h2 class="quickfit"></div>' +
|
14
14
|
'</div>'
|
15
15
|
);
|
16
16
|
|
17
17
|
this.box = this.el.find('.box');
|
18
|
-
this.el.find('
|
18
|
+
this.el.find('h2').text(this.title);
|
19
19
|
|
20
20
|
if (this.query) {
|
21
21
|
var reflowed = false;
|
@@ -63,13 +63,13 @@
|
|
63
63
|
value.quickfit({min: 6, max: 1000, font_height_scale: 1});
|
64
64
|
|
65
65
|
// Size title
|
66
|
-
var title = this.el.find('
|
66
|
+
var title = this.el.find('h2');
|
67
67
|
title.quickfit(fitopts);
|
68
68
|
}
|
69
69
|
|
70
70
|
Gauge.prototype.delete = function() {
|
71
71
|
if (this.sub) {
|
72
|
-
this.sub
|
72
|
+
subs.unsubscribe(this.sub);
|
73
73
|
}
|
74
74
|
view.View.prototype.delete.call(this);
|
75
75
|
}
|
@@ -11,11 +11,11 @@
|
|
11
11
|
// Initial display
|
12
12
|
this.el.addClass('grid');
|
13
13
|
this.el.append(
|
14
|
-
'<
|
15
|
-
'<table></table>'
|
14
|
+
'<h2></h2>' +
|
15
|
+
'<div class="container"><table></table></div>'
|
16
16
|
);
|
17
17
|
this.box = this.el.find('.box');
|
18
|
-
this.el.find('
|
18
|
+
this.el.find('h2').text(this.title);
|
19
19
|
|
20
20
|
// State
|
21
21
|
this.hosts = [];
|
@@ -115,7 +115,7 @@
|
|
115
115
|
}
|
116
116
|
|
117
117
|
// Rerender the table
|
118
|
-
Grid.prototype.render = function() {
|
118
|
+
Grid.prototype.render = util.slur(200, function() {
|
119
119
|
var table = this.el.find('table');
|
120
120
|
table.empty();
|
121
121
|
|
@@ -134,12 +134,12 @@
|
|
134
134
|
row.find('th').text(host);
|
135
135
|
this.services.forEach(function(service) {
|
136
136
|
var event = this.events[host][service];
|
137
|
-
var element = $('<td><span class="
|
137
|
+
var element = $('<td><span class="bar"><span class="metric"/></span></td>');
|
138
138
|
this.renderElement(element, event);
|
139
139
|
row.append(element);
|
140
140
|
}, this);
|
141
141
|
}, this);
|
142
|
-
};
|
142
|
+
});
|
143
143
|
|
144
144
|
// Update cached maxima with a new event. Returns true if maxima changed.
|
145
145
|
Grid.prototype.updateMax = function(event) {
|
@@ -263,15 +263,15 @@
|
|
263
263
|
}
|
264
264
|
|
265
265
|
Grid.prototype.reflow = function() {
|
266
|
-
this.el.find('table').height(
|
267
|
-
|
268
|
-
|
269
|
-
|
266
|
+
// this.el.find('table').height(
|
267
|
+
// this.height() -
|
268
|
+
// this.el.find('h2').height()
|
269
|
+
// );
|
270
270
|
}
|
271
271
|
|
272
272
|
Grid.prototype.delete = function() {
|
273
273
|
if (this.sub != undefined) {
|
274
|
-
this.sub
|
274
|
+
subs.unsubscribe(this.sub);
|
275
275
|
}
|
276
276
|
this.update = function() {};
|
277
277
|
view.View.prototype.delete.call(this);
|
@@ -6,7 +6,9 @@
|
|
6
6
|
this.title = json.title;
|
7
7
|
this.clickFocusable = true;
|
8
8
|
this.el.addClass("title");
|
9
|
-
this.
|
9
|
+
this.h2 = $('<h2/>');
|
10
|
+
this.el.append(this.h2);
|
11
|
+
this.h2.text(this.title);
|
10
12
|
this.reflow();
|
11
13
|
}
|
12
14
|
|
@@ -28,6 +30,6 @@
|
|
28
30
|
}
|
29
31
|
|
30
32
|
Title.prototype.reflow = function() {
|
31
|
-
this.
|
33
|
+
this.h2.quickfit(fitopts);
|
32
34
|
}
|
33
35
|
})();
|
data/lib/riemann/dash/version.rb
CHANGED
@@ -8,7 +8,9 @@ $amber: #FFC712;
|
|
8
8
|
$light-blue: #2CCCFE;
|
9
9
|
$blue: #2C55FF;
|
10
10
|
$dark-grey: #1F1F1F;
|
11
|
-
$grey: #
|
11
|
+
$light-grey: #ccc;
|
12
|
+
$off-white: #dedede;
|
13
|
+
$grey: #888;
|
12
14
|
$green: #06FA23;
|
13
15
|
$yellow: #FEF206;
|
14
16
|
|
@@ -23,36 +25,35 @@ body {
|
|
23
25
|
height: 100%;
|
24
26
|
margin: 0;
|
25
27
|
padding: 0;
|
26
|
-
background: #
|
27
|
-
color:
|
28
|
+
background: #fff;
|
29
|
+
color: $dark-grey;
|
28
30
|
}
|
29
31
|
|
30
32
|
html,table {
|
31
|
-
font-family: Helvetica
|
32
|
-
font-
|
33
|
-
|
34
|
-
|
35
|
-
margin-bottom: 0.2em;
|
36
|
-
}
|
37
|
-
h2 {
|
38
|
-
margin-top: 0;
|
39
|
-
margin-bottom: 0.1em;
|
33
|
+
font-family: "HelveticaNeue", "Helvetica Neue", "HelveticaNeueRoman", "HelveticaNeue-Roman", "Helvetica Neue Roman", 'TeXGyreHerosRegular', "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
34
|
+
font-weight:400;
|
35
|
+
font-stretch:normal;
|
36
|
+
font-size: 14px;
|
40
37
|
}
|
41
38
|
|
42
39
|
#toolbar {
|
43
|
-
width: 100%;
|
44
40
|
height: 28px;
|
45
41
|
overflow: hidden;
|
46
42
|
position: absolute;
|
43
|
+
top: 3px;
|
44
|
+
left: 3px;
|
45
|
+
right: 3px;
|
47
46
|
font-size: 12px;
|
48
47
|
|
49
48
|
input {
|
50
|
-
background: $
|
51
|
-
|
52
|
-
border: 1px solid $grey;
|
49
|
+
background: $off-white;
|
50
|
+
border: 1px solid $dark-grey;
|
53
51
|
margin: 3px;
|
54
52
|
padding: 3px 6px;
|
55
53
|
}
|
54
|
+
input:hover {
|
55
|
+
background: lighten($off-white, 5%);
|
56
|
+
}
|
56
57
|
|
57
58
|
.server {
|
58
59
|
float: right;
|
@@ -62,14 +63,15 @@ h2 {
|
|
62
63
|
position: relative;
|
63
64
|
margin: 3px;
|
64
65
|
float: right;
|
65
|
-
border: 1px solid $grey;
|
66
66
|
width: 100px;
|
67
|
-
padding: 3px 6px;
|
67
|
+
padding: 4px 6px 3px 6px;
|
68
|
+
border: 1px solid $dark-grey;
|
68
69
|
span {
|
69
70
|
z-index: -1;
|
70
71
|
}
|
71
72
|
.bar {
|
72
|
-
|
73
|
+
border-radius: 0;
|
74
|
+
background: rgba(0,0,0,0.25);
|
73
75
|
width: 1%;
|
74
76
|
}
|
75
77
|
}
|
@@ -78,11 +80,13 @@ h2 {
|
|
78
80
|
display: inline-block;
|
79
81
|
margin: 3px;
|
80
82
|
padding: 3px 6px;
|
81
|
-
border: 1px solid $grey;
|
82
|
-
|
83
|
-
background: $dark-grey;
|
83
|
+
border: 1px solid $light-grey;
|
84
|
+
background: $off-white;
|
84
85
|
cursor: pointer;
|
85
86
|
}
|
87
|
+
.button:hover {
|
88
|
+
background: lighten($off-white, 5%);
|
89
|
+
}
|
86
90
|
|
87
91
|
.pager {
|
88
92
|
margin: 0;
|
@@ -103,11 +107,11 @@ h2 {
|
|
103
107
|
}
|
104
108
|
|
105
109
|
li:hover {
|
106
|
-
background: $
|
110
|
+
background: lighten($off-white, 10%);
|
107
111
|
}
|
108
112
|
|
109
113
|
li.current {
|
110
|
-
border-color:
|
114
|
+
border-color: $dark-grey;
|
111
115
|
|
112
116
|
.delete {
|
113
117
|
display: inline;
|
@@ -118,10 +122,11 @@ h2 {
|
|
118
122
|
}
|
119
123
|
|
120
124
|
#view {
|
121
|
-
width: 100%;
|
122
125
|
position: absolute;
|
126
|
+
left: 3px;
|
127
|
+
right: 3px;
|
123
128
|
top: 28px;
|
124
|
-
bottom:
|
129
|
+
bottom: 3px;
|
125
130
|
}
|
126
131
|
|
127
132
|
.box {
|
@@ -134,7 +139,7 @@ h2 {
|
|
134
139
|
right: 0;
|
135
140
|
margin: 3px;
|
136
141
|
padding: 3px;
|
137
|
-
background: $
|
142
|
+
background: $light-grey;
|
138
143
|
border-radius: 3px;
|
139
144
|
}
|
140
145
|
|
@@ -144,7 +149,8 @@ h2 {
|
|
144
149
|
top: 0;
|
145
150
|
bottom: 0;
|
146
151
|
height: 100%;
|
147
|
-
background: rgba(0, 0, 0, 0.
|
152
|
+
background: rgba(0, 0, 0, 0.2);
|
153
|
+
border-radius: 3px;
|
148
154
|
}
|
149
155
|
|
150
156
|
.state.ok, .bar.ok {
|
@@ -243,7 +249,7 @@ h2 {
|
|
243
249
|
position: absolute;
|
244
250
|
z-index: 1000;
|
245
251
|
border-radius: 5px;
|
246
|
-
background: rgba(
|
252
|
+
background: rgba(0,0,0,0.5);
|
247
253
|
}
|
248
254
|
|
249
255
|
#simplemodal-overlay {
|
@@ -269,15 +275,16 @@ h2 {
|
|
269
275
|
cursor:pointer;
|
270
276
|
}
|
271
277
|
|
272
|
-
|
273
278
|
.quickfit {
|
274
279
|
display: block;
|
275
280
|
white-space: nowrap;
|
276
281
|
width: 100%;
|
277
282
|
}
|
278
283
|
|
279
|
-
|
280
|
-
|
284
|
+
h2 {
|
285
|
+
display: block;
|
286
|
+
padding: 3px;
|
287
|
+
margin: 0;
|
281
288
|
}
|
282
289
|
|
283
290
|
.metric {
|
@@ -285,8 +292,16 @@ h2 {
|
|
285
292
|
text-align: right;
|
286
293
|
}
|
287
294
|
|
295
|
+
.title h2 {
|
296
|
+
position: absolute;
|
297
|
+
left: 3px;
|
298
|
+
right: 3px;
|
299
|
+
top: 3px;
|
300
|
+
bottom: 3px;
|
301
|
+
}
|
302
|
+
|
288
303
|
.gauge {
|
289
|
-
|
304
|
+
h2 {
|
290
305
|
position: absolute;
|
291
306
|
height: 25%;
|
292
307
|
width: 75%;
|
@@ -306,46 +321,57 @@ h2 {
|
|
306
321
|
}
|
307
322
|
|
308
323
|
.grid {
|
309
|
-
|
310
|
-
height:
|
324
|
+
h2 {
|
325
|
+
height: 28px;
|
311
326
|
font-size: 24px;
|
312
|
-
text-align: right;
|
313
327
|
}
|
314
328
|
|
315
|
-
|
329
|
+
.container {
|
316
330
|
position: absolute;
|
317
|
-
|
318
|
-
|
331
|
+
top: 28px;
|
332
|
+
left: 0;
|
333
|
+
right: 0;
|
334
|
+
bottom: 0;
|
335
|
+
}
|
319
336
|
|
320
|
-
|
321
|
-
|
322
|
-
|
337
|
+
.bar {
|
338
|
+
position: static;
|
339
|
+
display: block;
|
340
|
+
height: 100%;
|
341
|
+
}
|
323
342
|
|
324
|
-
|
343
|
+
.box {
|
344
|
+
margin: 0;
|
345
|
+
padding: 0;
|
346
|
+
position: static;
|
347
|
+
|
348
|
+
.metric {
|
349
|
+
padding: 3px;
|
325
350
|
font-weight: normal;
|
326
|
-
vertical-align: top;
|
327
|
-
text-align: right;
|
328
|
-
padding: 0 3px;
|
329
351
|
}
|
352
|
+
}
|
353
|
+
|
354
|
+
table {
|
355
|
+
font-size: 12px;
|
356
|
+
position: absolute;
|
357
|
+
width: 100%;
|
358
|
+
border-spacing: 3px;
|
330
359
|
|
331
360
|
thead {
|
332
361
|
margin: 0;
|
333
362
|
padding: 0;
|
334
363
|
|
335
|
-
tr {
|
336
|
-
padding: 0;
|
337
|
-
}
|
338
|
-
|
339
364
|
th {
|
340
|
-
|
365
|
+
// Work around https://bugs.webkit.org/show_bug.cgi?id=20040
|
366
|
+
position: relative;
|
367
|
+
top: 3px;
|
341
368
|
vertical-align: bottom;
|
369
|
+
text-align: right;
|
342
370
|
}
|
343
371
|
}
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
text-align: right;
|
349
|
-
}
|
372
|
+
}
|
373
|
+
|
374
|
+
tr > *:first-child {
|
375
|
+
width: 1px;
|
350
376
|
}
|
351
377
|
}
|
@@ -1,8 +1,202 @@
|
|
1
|
-
|
2
|
-
<
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title>Riemann</title>
|
6
|
+
<link rel="stylesheet" href="/css" type="text/css" />
|
7
|
+
<link rel="stylesheet" href="/toastr.css" type="text/css" />
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<div id="toolbar"></div>
|
11
|
+
<div id="view"></div>
|
3
12
|
|
4
|
-
<
|
5
|
-
|
6
|
-
|
13
|
+
<script type="text/javascript" src="/underscore-min.js"></script>
|
14
|
+
<script type="text/javascript" src="/jquery-1.7.2.min.js"></script>
|
15
|
+
<script type="text/javascript" src="/jquery-ui-1.9.0.custom.min.js"></script>
|
16
|
+
<script type="text/javascript" src="/jquery.json-2.2.min.js"></script>
|
17
|
+
<script type="text/javascript" src="/jquery.simplemodal.1.4.3.min.js"></script>
|
18
|
+
<script type="text/javascript" src="/toastr.js"></script>
|
19
|
+
<script type="text/javascript" src="/jquery.quickfit.js"></script>
|
20
|
+
<script type="text/javascript" src="/util.js"></script>
|
21
|
+
<script type="text/javascript" src="/mustache.js"></script>
|
22
|
+
<script src="http://d3js.org/d3.v2.js"></script>
|
23
|
+
<script type="text/javascript" src="/profile.js"></script>
|
24
|
+
<script type="text/javascript" src="/clock.js"></script>
|
25
|
+
<script type="text/javascript" src="/persistence.js"></script>
|
26
|
+
<script type="text/javascript" src="/keys.js"></script>
|
27
|
+
<script type="text/javascript" src="/subs.js"></script>
|
28
|
+
<script type="text/javascript" src="/format.js"></script>
|
29
|
+
<script type="text/javascript" src="/toolbar.js"></script>
|
30
|
+
<script type="text/javascript" src="/view.js"></script>
|
31
|
+
<script type="text/javascript" src="/views/title.js"></script>
|
32
|
+
<script type="text/javascript" src="/views/help.js"></script>
|
33
|
+
<script type="text/javascript" src="/views/gauge.js"></script>
|
34
|
+
<script type="text/javascript" src="/views/grid.js"></script>
|
35
|
+
<script type="text/javascript" src="/dash.js"></script>
|
7
36
|
|
8
|
-
<
|
37
|
+
<script type="text/javascript">
|
38
|
+
function logTable(container, query) {
|
39
|
+
var $container = $(container);
|
40
|
+
$container.addClass("log-table");
|
41
|
+
$container.append('<input type="text" class="query"></input>');
|
42
|
+
var prompt = $container.find('input');
|
43
|
+
$container.append('<div class="scroll"><table><thead><tr>' +
|
44
|
+
'<th>host</th>' +
|
45
|
+
'<th>service</th>' +
|
46
|
+
'<th>state</th>' +
|
47
|
+
'<th>metric</th>' +
|
48
|
+
'<th>description</th>' +
|
49
|
+
'</tr></thead><tbody></tbody></table></div>');
|
50
|
+
var scroll = $container.find('.scroll');
|
51
|
+
var log = $container.find('tbody');
|
52
|
+
var sub = null;
|
53
|
+
var tracking = true;
|
54
|
+
|
55
|
+
var template = "<tr><td>{{host}}</td><td>{{service}}</td><td>{{state}}</td><td>{{{metric}}}</td><td>{{description}}</td></tr>";
|
56
|
+
|
57
|
+
// Are we following the bottom of the log?
|
58
|
+
scroll.scroll(function(e) {
|
59
|
+
if (scroll.scrollTop() > (log.height() - scroll.height())) {
|
60
|
+
tracking = true;
|
61
|
+
} else {
|
62
|
+
tracking = false;
|
63
|
+
}
|
64
|
+
});
|
65
|
+
|
66
|
+
var scrollToBottom = function() {
|
67
|
+
scroll.stop().animate({
|
68
|
+
scrollTop: (log.height() - scroll.height() + 20)
|
69
|
+
}, 1000, "swing");
|
70
|
+
}
|
71
|
+
|
72
|
+
var atBottom = function() {
|
73
|
+
console.log(scroll.scrollTop());
|
74
|
+
console.log(log.height() - scroll.height());
|
75
|
+
return (scroll.scrollTop() > (log.height() - scroll.height()));
|
76
|
+
}
|
77
|
+
|
78
|
+
// Add an event
|
79
|
+
var append = function(e) {
|
80
|
+
$.extend(e, {
|
81
|
+
metric: format.metric(e)
|
82
|
+
});
|
83
|
+
log.append(Mustache.render(template, e));
|
84
|
+
if (tracking) { scrollToBottom() };
|
85
|
+
}
|
86
|
+
|
87
|
+
// Set up our query
|
88
|
+
var startQuery = function(query) {
|
89
|
+
// Cancel existing sub
|
90
|
+
if (sub != null) { sub.close(); }
|
91
|
+
|
92
|
+
// Subscribe
|
93
|
+
sub = subs.subscribe(query, function(e) {
|
94
|
+
e.time = d3.time.format.iso.parse(e.time);
|
95
|
+
clock.advance(e.time);
|
96
|
+
append(e);
|
97
|
+
});
|
98
|
+
}
|
99
|
+
|
100
|
+
// Initial subscription
|
101
|
+
if (query) { prompt[0].value = query; startQuery(query); }
|
102
|
+
|
103
|
+
// Prompt entry
|
104
|
+
prompt.change(function() { startQuery(this.value) });
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
function timeSeries(container) {
|
109
|
+
// Container
|
110
|
+
var $container = $(container);
|
111
|
+
var container = d3.select(container);
|
112
|
+
$container.append('<input type=\"text\" style="display: block"></input>');
|
113
|
+
var prompt = $container.children().last();
|
114
|
+
|
115
|
+
// Data structures
|
116
|
+
var data = [];
|
117
|
+
var n = 60;
|
118
|
+
var sub = null;
|
119
|
+
|
120
|
+
// Scale
|
121
|
+
var w = 20;
|
122
|
+
var h = 80;
|
123
|
+
|
124
|
+
var x = d3.time.scale()
|
125
|
+
.domain([0,1])
|
126
|
+
.range([0, w * n]);
|
127
|
+
var y = d3.scale.linear()
|
128
|
+
.domain([0,100])
|
129
|
+
.rangeRound([0,h]);
|
130
|
+
|
131
|
+
var updateTime = function(max) {
|
132
|
+
var min = d3.time.minute.offset(max, -1);
|
133
|
+
x.domain([min, max]);
|
134
|
+
}
|
135
|
+
updateTime(new Date());
|
136
|
+
|
137
|
+
// Chart itself
|
138
|
+
var chart = container.append("svg")
|
139
|
+
.attr("class", "timeSeries")
|
140
|
+
.attr("width", w * (n - 1))
|
141
|
+
.attr("height", h);
|
142
|
+
|
143
|
+
// Baseline
|
144
|
+
chart.append("line")
|
145
|
+
.attr("x1", 0)
|
146
|
+
.attr("x2", w * n)
|
147
|
+
.attr("y1", h - .5)
|
148
|
+
.attr("y2", h - .5)
|
149
|
+
.style("stroke", "#000");
|
150
|
+
|
151
|
+
// Subscribe
|
152
|
+
prompt.change(function() {
|
153
|
+
if (sub != null) { sub.close(); }
|
154
|
+
|
155
|
+
sub = subscribe(this.value, function(e) {
|
156
|
+
// Move time
|
157
|
+
e.time = d3.time.format.iso.parse(e.time);
|
158
|
+
clock.advance(e.time);
|
159
|
+
|
160
|
+
// Append to window
|
161
|
+
if (data.length >= n) {
|
162
|
+
data.shift();
|
163
|
+
}
|
164
|
+
data.push(e);
|
165
|
+
|
166
|
+
console.log(e.time, "maps to", x(e.time), "in", x.domain(), x.range());
|
167
|
+
});
|
168
|
+
});
|
169
|
+
|
170
|
+
var clockSub = clock.register(function(t) {
|
171
|
+
updateTime(t);
|
172
|
+
|
173
|
+
// Move events
|
174
|
+
var rect = chart.selectAll("rect")
|
175
|
+
.data(data, function(e) { if (e) { return e.time } });
|
176
|
+
|
177
|
+
rect.enter().insert("rect", "line")
|
178
|
+
.attr("x", function(e, i) {
|
179
|
+
return x(e.time) - .5; })
|
180
|
+
.attr("y", function(e) { return h - y(e.metric) - .5 })
|
181
|
+
.attr("width", w)
|
182
|
+
.attr("height", function(e) { return y(e.metric); })
|
183
|
+
.transition()
|
184
|
+
.duration(1000)
|
185
|
+
.attr("x", function(e, i) { return x(e.time) - .5 });
|
186
|
+
|
187
|
+
rect.transition()
|
188
|
+
.duration(1000)
|
189
|
+
.attr("x", function(e) { return x(e.time) - .5; });
|
190
|
+
|
191
|
+
rect.exit().transition()
|
192
|
+
.duration(1000)
|
193
|
+
.attr("x", function(e) { return x(e.time) - .5 })
|
194
|
+
.remove();
|
195
|
+
});
|
196
|
+
|
197
|
+
}
|
198
|
+
|
199
|
+
dash.reload();
|
200
|
+
</script>
|
201
|
+
</body>
|
202
|
+
</html>
|