-
Notifications
You must be signed in to change notification settings - Fork 525
/
Copy pathcontext.js
138 lines (116 loc) · 4.48 KB
/
context.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
cubism.context = function() {
var context = new cubism_context,
step = 1e4, // ten seconds, in milliseconds
size = 1440, // four hours at ten seconds, in pixels
start0, stop0, // the start and stop for the previous change event
start1, stop1, // the start and stop for the next prepare event
serverDelay = 5e3,
clientDelay = 5e3,
event = d3.dispatch("prepare", "beforechange", "change", "focus"),
scale = context.scale = d3.time.scale().range([0, size]),
timeout,
focus;
function update() {
var now = Date.now();
stop0 = new Date(Math.floor((now - serverDelay - clientDelay) / step) * step);
start0 = new Date(stop0 - size * step);
stop1 = new Date(Math.floor((now - serverDelay) / step) * step);
start1 = new Date(stop1 - size * step);
scale.domain([start0, stop0]);
return context;
}
context.start = function() {
if (timeout) clearTimeout(timeout);
var delay = +stop1 + serverDelay - Date.now();
// If we're too late for the first prepare event, skip it.
if (delay < clientDelay) delay += step;
timeout = setTimeout(function prepare() {
stop1 = new Date(Math.floor((Date.now() - serverDelay) / step) * step);
start1 = new Date(stop1 - size * step);
event.prepare.call(context, start1, stop1);
setTimeout(function() {
scale.domain([start0 = start1, stop0 = stop1]);
event.beforechange.call(context, start1, stop1);
event.change.call(context, start1, stop1);
event.focus.call(context, focus);
}, clientDelay);
timeout = setTimeout(prepare, step);
}, delay);
return context;
};
context.stop = function() {
timeout = clearTimeout(timeout);
return context;
};
timeout = setTimeout(context.start, 10);
// Set or get the step interval in milliseconds.
// Defaults to ten seconds.
context.step = function(_) {
if (!arguments.length) return step;
step = +_;
return update();
};
// Set or get the context size (the count of metric values).
// Defaults to 1440 (four hours at ten seconds).
context.size = function(_) {
if (!arguments.length) return size;
scale.range([0, size = +_]);
return update();
};
// The server delay is the amount of time we wait for the server to compute a
// metric. This delay may result from clock skew or from delays collecting
// metrics from various hosts. Defaults to 4 seconds.
context.serverDelay = function(_) {
if (!arguments.length) return serverDelay;
serverDelay = +_;
return update();
};
// The client delay is the amount of additional time we wait to fetch those
// metrics from the server. The client and server delay combined represent the
// age of the most recent displayed metric. Defaults to 1 second.
context.clientDelay = function(_) {
if (!arguments.length) return clientDelay;
clientDelay = +_;
return update();
};
// Sets the focus to the specified index, and dispatches a "focus" event.
context.focus = function(i) {
event.focus.call(context, focus = i);
return context;
};
// Add, remove or get listeners for events.
context.on = function(type, listener) {
if (arguments.length < 2) return event.on(type);
event.on(type, listener);
// Notify the listener of the current start and stop time, as appropriate.
// This way, metrics can make requests for data immediately,
// and likewise the axis can display itself synchronously.
if (listener != null) {
if (/^prepare(\.|$)/.test(type)) listener.call(context, start1, stop1);
if (/^beforechange(\.|$)/.test(type)) listener.call(context, start0, stop0);
if (/^change(\.|$)/.test(type)) listener.call(context, start0, stop0);
if (/^focus(\.|$)/.test(type)) listener.call(context, focus);
}
return context;
};
d3.select(window).on("keydown.context-" + ++cubism_id, function() {
switch (!d3.event.metaKey && d3.event.keyCode) {
case 37: // left
if (focus == null) focus = size - 1;
if (focus > 0) context.focus(--focus);
break;
case 39: // right
if (focus == null) focus = size - 2;
if (focus < size - 1) context.focus(++focus);
break;
default: return;
}
d3.event.preventDefault();
});
return update();
};
function cubism_context() {}
var cubism_contextPrototype = cubism.context.prototype = cubism_context.prototype;
cubism_contextPrototype.constant = function(value) {
return new cubism_metricConstant(this, +value);
};