riemann-dash 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/riemann/dash/public/clock.js +12 -8
- data/lib/riemann/dash/public/strings.js +8 -2
- data/lib/riemann/dash/public/subs.js +8 -4
- data/lib/riemann/dash/public/util.js +19 -5
- data/lib/riemann/dash/public/vendor/flot/jquery.colorhelpers.js +179 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.colorhelpers.min.js +21 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.canvas.js +345 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.canvas.min.js +28 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.categories.js +190 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.categories.min.js +44 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.crosshair.js +176 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.crosshair.min.js +59 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.errorbars.js +353 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.errorbars.min.js +63 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.fillbetween.js +226 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.fillbetween.min.js +30 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.image.js +241 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.image.min.js +53 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.js +3061 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.min.js +29 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.navigate.js +346 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.navigate.min.js +86 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.pie.js +817 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.pie.min.js +56 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.resize.js +60 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.resize.min.js +19 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.selection.js +360 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.selection.min.js +79 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.stack.js +188 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.stack.min.js +36 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.symbol.js +71 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.symbol.min.js +14 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.threshold.js +142 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.threshold.min.js +43 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.time.js +431 -0
- data/lib/riemann/dash/public/vendor/flot/jquery.flot.time.min.js +9 -0
- data/lib/riemann/dash/public/view.js +11 -7
- data/lib/riemann/dash/public/views/flot.js +248 -0
- data/lib/riemann/dash/public/views/grid.js +1 -5
- data/lib/riemann/dash/version.rb +1 -1
- data/lib/riemann/dash/views/css.scss +24 -0
- data/lib/riemann/dash/views/index.erubis +6 -0
- metadata +35 -2
@@ -0,0 +1,353 @@
|
|
1
|
+
/* Flot plugin for plotting error bars.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2013 IOLA and Ole Laursen.
|
4
|
+
Licensed under the MIT license.
|
5
|
+
|
6
|
+
Error bars are used to show standard deviation and other statistical
|
7
|
+
properties in a plot.
|
8
|
+
|
9
|
+
* Created by Rui Pereira - rui (dot) pereira (at) gmail (dot) com
|
10
|
+
|
11
|
+
This plugin allows you to plot error-bars over points. Set "errorbars" inside
|
12
|
+
the points series to the axis name over which there will be error values in
|
13
|
+
your data array (*even* if you do not intend to plot them later, by setting
|
14
|
+
"show: null" on xerr/yerr).
|
15
|
+
|
16
|
+
The plugin supports these options:
|
17
|
+
|
18
|
+
series: {
|
19
|
+
points: {
|
20
|
+
errorbars: "x" or "y" or "xy",
|
21
|
+
xerr: {
|
22
|
+
show: null/false or true,
|
23
|
+
asymmetric: null/false or true,
|
24
|
+
upperCap: null or "-" or function,
|
25
|
+
lowerCap: null or "-" or function,
|
26
|
+
color: null or color,
|
27
|
+
radius: null or number
|
28
|
+
},
|
29
|
+
yerr: { same options as xerr }
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
Each data point array is expected to be of the type:
|
34
|
+
|
35
|
+
"x" [ x, y, xerr ]
|
36
|
+
"y" [ x, y, yerr ]
|
37
|
+
"xy" [ x, y, xerr, yerr ]
|
38
|
+
|
39
|
+
Where xerr becomes xerr_lower,xerr_upper for the asymmetric error case, and
|
40
|
+
equivalently for yerr. Eg., a datapoint for the "xy" case with symmetric
|
41
|
+
error-bars on X and asymmetric on Y would be:
|
42
|
+
|
43
|
+
[ x, y, xerr, yerr_lower, yerr_upper ]
|
44
|
+
|
45
|
+
By default no end caps are drawn. Setting upperCap and/or lowerCap to "-" will
|
46
|
+
draw a small cap perpendicular to the error bar. They can also be set to a
|
47
|
+
user-defined drawing function, with (ctx, x, y, radius) as parameters, as eg.
|
48
|
+
|
49
|
+
function drawSemiCircle( ctx, x, y, radius ) {
|
50
|
+
ctx.beginPath();
|
51
|
+
ctx.arc( x, y, radius, 0, Math.PI, false );
|
52
|
+
ctx.moveTo( x - radius, y );
|
53
|
+
ctx.lineTo( x + radius, y );
|
54
|
+
ctx.stroke();
|
55
|
+
}
|
56
|
+
|
57
|
+
Color and radius both default to the same ones of the points series if not
|
58
|
+
set. The independent radius parameter on xerr/yerr is useful for the case when
|
59
|
+
we may want to add error-bars to a line, without showing the interconnecting
|
60
|
+
points (with radius: 0), and still showing end caps on the error-bars.
|
61
|
+
shadowSize and lineWidth are derived as well from the points series.
|
62
|
+
|
63
|
+
*/
|
64
|
+
|
65
|
+
(function ($) {
|
66
|
+
var options = {
|
67
|
+
series: {
|
68
|
+
points: {
|
69
|
+
errorbars: null, //should be 'x', 'y' or 'xy'
|
70
|
+
xerr: { err: 'x', show: null, asymmetric: null, upperCap: null, lowerCap: null, color: null, radius: null},
|
71
|
+
yerr: { err: 'y', show: null, asymmetric: null, upperCap: null, lowerCap: null, color: null, radius: null}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
};
|
75
|
+
|
76
|
+
function processRawData(plot, series, data, datapoints){
|
77
|
+
if (!series.points.errorbars)
|
78
|
+
return;
|
79
|
+
|
80
|
+
// x,y values
|
81
|
+
var format = [
|
82
|
+
{ x: true, number: true, required: true },
|
83
|
+
{ y: true, number: true, required: true }
|
84
|
+
];
|
85
|
+
|
86
|
+
var errors = series.points.errorbars;
|
87
|
+
// error bars - first X then Y
|
88
|
+
if (errors == 'x' || errors == 'xy') {
|
89
|
+
// lower / upper error
|
90
|
+
if (series.points.xerr.asymmetric) {
|
91
|
+
format.push({ x: true, number: true, required: true });
|
92
|
+
format.push({ x: true, number: true, required: true });
|
93
|
+
} else
|
94
|
+
format.push({ x: true, number: true, required: true });
|
95
|
+
}
|
96
|
+
if (errors == 'y' || errors == 'xy') {
|
97
|
+
// lower / upper error
|
98
|
+
if (series.points.yerr.asymmetric) {
|
99
|
+
format.push({ y: true, number: true, required: true });
|
100
|
+
format.push({ y: true, number: true, required: true });
|
101
|
+
} else
|
102
|
+
format.push({ y: true, number: true, required: true });
|
103
|
+
}
|
104
|
+
datapoints.format = format;
|
105
|
+
}
|
106
|
+
|
107
|
+
function parseErrors(series, i){
|
108
|
+
|
109
|
+
var points = series.datapoints.points;
|
110
|
+
|
111
|
+
// read errors from points array
|
112
|
+
var exl = null,
|
113
|
+
exu = null,
|
114
|
+
eyl = null,
|
115
|
+
eyu = null;
|
116
|
+
var xerr = series.points.xerr,
|
117
|
+
yerr = series.points.yerr;
|
118
|
+
|
119
|
+
var eb = series.points.errorbars;
|
120
|
+
// error bars - first X
|
121
|
+
if (eb == 'x' || eb == 'xy') {
|
122
|
+
if (xerr.asymmetric) {
|
123
|
+
exl = points[i + 2];
|
124
|
+
exu = points[i + 3];
|
125
|
+
if (eb == 'xy')
|
126
|
+
if (yerr.asymmetric){
|
127
|
+
eyl = points[i + 4];
|
128
|
+
eyu = points[i + 5];
|
129
|
+
} else eyl = points[i + 4];
|
130
|
+
} else {
|
131
|
+
exl = points[i + 2];
|
132
|
+
if (eb == 'xy')
|
133
|
+
if (yerr.asymmetric) {
|
134
|
+
eyl = points[i + 3];
|
135
|
+
eyu = points[i + 4];
|
136
|
+
} else eyl = points[i + 3];
|
137
|
+
}
|
138
|
+
// only Y
|
139
|
+
} else if (eb == 'y')
|
140
|
+
if (yerr.asymmetric) {
|
141
|
+
eyl = points[i + 2];
|
142
|
+
eyu = points[i + 3];
|
143
|
+
} else eyl = points[i + 2];
|
144
|
+
|
145
|
+
// symmetric errors?
|
146
|
+
if (exu == null) exu = exl;
|
147
|
+
if (eyu == null) eyu = eyl;
|
148
|
+
|
149
|
+
var errRanges = [exl, exu, eyl, eyu];
|
150
|
+
// nullify if not showing
|
151
|
+
if (!xerr.show){
|
152
|
+
errRanges[0] = null;
|
153
|
+
errRanges[1] = null;
|
154
|
+
}
|
155
|
+
if (!yerr.show){
|
156
|
+
errRanges[2] = null;
|
157
|
+
errRanges[3] = null;
|
158
|
+
}
|
159
|
+
return errRanges;
|
160
|
+
}
|
161
|
+
|
162
|
+
function drawSeriesErrors(plot, ctx, s){
|
163
|
+
|
164
|
+
var points = s.datapoints.points,
|
165
|
+
ps = s.datapoints.pointsize,
|
166
|
+
ax = [s.xaxis, s.yaxis],
|
167
|
+
radius = s.points.radius,
|
168
|
+
err = [s.points.xerr, s.points.yerr];
|
169
|
+
|
170
|
+
//sanity check, in case some inverted axis hack is applied to flot
|
171
|
+
var invertX = false;
|
172
|
+
if (ax[0].p2c(ax[0].max) < ax[0].p2c(ax[0].min)) {
|
173
|
+
invertX = true;
|
174
|
+
var tmp = err[0].lowerCap;
|
175
|
+
err[0].lowerCap = err[0].upperCap;
|
176
|
+
err[0].upperCap = tmp;
|
177
|
+
}
|
178
|
+
|
179
|
+
var invertY = false;
|
180
|
+
if (ax[1].p2c(ax[1].min) < ax[1].p2c(ax[1].max)) {
|
181
|
+
invertY = true;
|
182
|
+
var tmp = err[1].lowerCap;
|
183
|
+
err[1].lowerCap = err[1].upperCap;
|
184
|
+
err[1].upperCap = tmp;
|
185
|
+
}
|
186
|
+
|
187
|
+
for (var i = 0; i < s.datapoints.points.length; i += ps) {
|
188
|
+
|
189
|
+
//parse
|
190
|
+
var errRanges = parseErrors(s, i);
|
191
|
+
|
192
|
+
//cycle xerr & yerr
|
193
|
+
for (var e = 0; e < err.length; e++){
|
194
|
+
|
195
|
+
var minmax = [ax[e].min, ax[e].max];
|
196
|
+
|
197
|
+
//draw this error?
|
198
|
+
if (errRanges[e * err.length]){
|
199
|
+
|
200
|
+
//data coordinates
|
201
|
+
var x = points[i],
|
202
|
+
y = points[i + 1];
|
203
|
+
|
204
|
+
//errorbar ranges
|
205
|
+
var upper = [x, y][e] + errRanges[e * err.length + 1],
|
206
|
+
lower = [x, y][e] - errRanges[e * err.length];
|
207
|
+
|
208
|
+
//points outside of the canvas
|
209
|
+
if (err[e].err == 'x')
|
210
|
+
if (y > ax[1].max || y < ax[1].min || upper < ax[0].min || lower > ax[0].max)
|
211
|
+
continue;
|
212
|
+
if (err[e].err == 'y')
|
213
|
+
if (x > ax[0].max || x < ax[0].min || upper < ax[1].min || lower > ax[1].max)
|
214
|
+
continue;
|
215
|
+
|
216
|
+
// prevent errorbars getting out of the canvas
|
217
|
+
var drawUpper = true,
|
218
|
+
drawLower = true;
|
219
|
+
|
220
|
+
if (upper > minmax[1]) {
|
221
|
+
drawUpper = false;
|
222
|
+
upper = minmax[1];
|
223
|
+
}
|
224
|
+
if (lower < minmax[0]) {
|
225
|
+
drawLower = false;
|
226
|
+
lower = minmax[0];
|
227
|
+
}
|
228
|
+
|
229
|
+
//sanity check, in case some inverted axis hack is applied to flot
|
230
|
+
if ((err[e].err == 'x' && invertX) || (err[e].err == 'y' && invertY)) {
|
231
|
+
//swap coordinates
|
232
|
+
var tmp = lower;
|
233
|
+
lower = upper;
|
234
|
+
upper = tmp;
|
235
|
+
tmp = drawLower;
|
236
|
+
drawLower = drawUpper;
|
237
|
+
drawUpper = tmp;
|
238
|
+
tmp = minmax[0];
|
239
|
+
minmax[0] = minmax[1];
|
240
|
+
minmax[1] = tmp;
|
241
|
+
}
|
242
|
+
|
243
|
+
// convert to pixels
|
244
|
+
x = ax[0].p2c(x),
|
245
|
+
y = ax[1].p2c(y),
|
246
|
+
upper = ax[e].p2c(upper);
|
247
|
+
lower = ax[e].p2c(lower);
|
248
|
+
minmax[0] = ax[e].p2c(minmax[0]);
|
249
|
+
minmax[1] = ax[e].p2c(minmax[1]);
|
250
|
+
|
251
|
+
//same style as points by default
|
252
|
+
var lw = err[e].lineWidth ? err[e].lineWidth : s.points.lineWidth,
|
253
|
+
sw = s.points.shadowSize != null ? s.points.shadowSize : s.shadowSize;
|
254
|
+
|
255
|
+
//shadow as for points
|
256
|
+
if (lw > 0 && sw > 0) {
|
257
|
+
var w = sw / 2;
|
258
|
+
ctx.lineWidth = w;
|
259
|
+
ctx.strokeStyle = "rgba(0,0,0,0.1)";
|
260
|
+
drawError(ctx, err[e], x, y, upper, lower, drawUpper, drawLower, radius, w + w/2, minmax);
|
261
|
+
|
262
|
+
ctx.strokeStyle = "rgba(0,0,0,0.2)";
|
263
|
+
drawError(ctx, err[e], x, y, upper, lower, drawUpper, drawLower, radius, w/2, minmax);
|
264
|
+
}
|
265
|
+
|
266
|
+
ctx.strokeStyle = err[e].color? err[e].color: s.color;
|
267
|
+
ctx.lineWidth = lw;
|
268
|
+
//draw it
|
269
|
+
drawError(ctx, err[e], x, y, upper, lower, drawUpper, drawLower, radius, 0, minmax);
|
270
|
+
}
|
271
|
+
}
|
272
|
+
}
|
273
|
+
}
|
274
|
+
|
275
|
+
function drawError(ctx,err,x,y,upper,lower,drawUpper,drawLower,radius,offset,minmax){
|
276
|
+
|
277
|
+
//shadow offset
|
278
|
+
y += offset;
|
279
|
+
upper += offset;
|
280
|
+
lower += offset;
|
281
|
+
|
282
|
+
// error bar - avoid plotting over circles
|
283
|
+
if (err.err == 'x'){
|
284
|
+
if (upper > x + radius) drawPath(ctx, [[upper,y],[Math.max(x + radius,minmax[0]),y]]);
|
285
|
+
else drawUpper = false;
|
286
|
+
if (lower < x - radius) drawPath(ctx, [[Math.min(x - radius,minmax[1]),y],[lower,y]] );
|
287
|
+
else drawLower = false;
|
288
|
+
}
|
289
|
+
else {
|
290
|
+
if (upper < y - radius) drawPath(ctx, [[x,upper],[x,Math.min(y - radius,minmax[0])]] );
|
291
|
+
else drawUpper = false;
|
292
|
+
if (lower > y + radius) drawPath(ctx, [[x,Math.max(y + radius,minmax[1])],[x,lower]] );
|
293
|
+
else drawLower = false;
|
294
|
+
}
|
295
|
+
|
296
|
+
//internal radius value in errorbar, allows to plot radius 0 points and still keep proper sized caps
|
297
|
+
//this is a way to get errorbars on lines without visible connecting dots
|
298
|
+
radius = err.radius != null? err.radius: radius;
|
299
|
+
|
300
|
+
// upper cap
|
301
|
+
if (drawUpper) {
|
302
|
+
if (err.upperCap == '-'){
|
303
|
+
if (err.err=='x') drawPath(ctx, [[upper,y - radius],[upper,y + radius]] );
|
304
|
+
else drawPath(ctx, [[x - radius,upper],[x + radius,upper]] );
|
305
|
+
} else if ($.isFunction(err.upperCap)){
|
306
|
+
if (err.err=='x') err.upperCap(ctx, upper, y, radius);
|
307
|
+
else err.upperCap(ctx, x, upper, radius);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
// lower cap
|
311
|
+
if (drawLower) {
|
312
|
+
if (err.lowerCap == '-'){
|
313
|
+
if (err.err=='x') drawPath(ctx, [[lower,y - radius],[lower,y + radius]] );
|
314
|
+
else drawPath(ctx, [[x - radius,lower],[x + radius,lower]] );
|
315
|
+
} else if ($.isFunction(err.lowerCap)){
|
316
|
+
if (err.err=='x') err.lowerCap(ctx, lower, y, radius);
|
317
|
+
else err.lowerCap(ctx, x, lower, radius);
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
function drawPath(ctx, pts){
|
323
|
+
ctx.beginPath();
|
324
|
+
ctx.moveTo(pts[0][0], pts[0][1]);
|
325
|
+
for (var p=1; p < pts.length; p++)
|
326
|
+
ctx.lineTo(pts[p][0], pts[p][1]);
|
327
|
+
ctx.stroke();
|
328
|
+
}
|
329
|
+
|
330
|
+
function draw(plot, ctx){
|
331
|
+
var plotOffset = plot.getPlotOffset();
|
332
|
+
|
333
|
+
ctx.save();
|
334
|
+
ctx.translate(plotOffset.left, plotOffset.top);
|
335
|
+
$.each(plot.getData(), function (i, s) {
|
336
|
+
if (s.points.errorbars && (s.points.xerr.show || s.points.yerr.show))
|
337
|
+
drawSeriesErrors(plot, ctx, s);
|
338
|
+
});
|
339
|
+
ctx.restore();
|
340
|
+
}
|
341
|
+
|
342
|
+
function init(plot) {
|
343
|
+
plot.hooks.processRawData.push(processRawData);
|
344
|
+
plot.hooks.draw.push(draw);
|
345
|
+
}
|
346
|
+
|
347
|
+
$.plot.plugins.push({
|
348
|
+
init: init,
|
349
|
+
options: options,
|
350
|
+
name: 'errorbars',
|
351
|
+
version: '1.0'
|
352
|
+
});
|
353
|
+
})(jQuery);
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/* Flot plugin for plotting error bars.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2013 IOLA and Ole Laursen.
|
4
|
+
Licensed under the MIT license.
|
5
|
+
|
6
|
+
Error bars are used to show standard deviation and other statistical
|
7
|
+
properties in a plot.
|
8
|
+
|
9
|
+
* Created by Rui Pereira - rui (dot) pereira (at) gmail (dot) com
|
10
|
+
|
11
|
+
This plugin allows you to plot error-bars over points. Set "errorbars" inside
|
12
|
+
the points series to the axis name over which there will be error values in
|
13
|
+
your data array (*even* if you do not intend to plot them later, by setting
|
14
|
+
"show: null" on xerr/yerr).
|
15
|
+
|
16
|
+
The plugin supports these options:
|
17
|
+
|
18
|
+
series: {
|
19
|
+
points: {
|
20
|
+
errorbars: "x" or "y" or "xy",
|
21
|
+
xerr: {
|
22
|
+
show: null/false or true,
|
23
|
+
asymmetric: null/false or true,
|
24
|
+
upperCap: null or "-" or function,
|
25
|
+
lowerCap: null or "-" or function,
|
26
|
+
color: null or color,
|
27
|
+
radius: null or number
|
28
|
+
},
|
29
|
+
yerr: { same options as xerr }
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
Each data point array is expected to be of the type:
|
34
|
+
|
35
|
+
"x" [ x, y, xerr ]
|
36
|
+
"y" [ x, y, yerr ]
|
37
|
+
"xy" [ x, y, xerr, yerr ]
|
38
|
+
|
39
|
+
Where xerr becomes xerr_lower,xerr_upper for the asymmetric error case, and
|
40
|
+
equivalently for yerr. Eg., a datapoint for the "xy" case with symmetric
|
41
|
+
error-bars on X and asymmetric on Y would be:
|
42
|
+
|
43
|
+
[ x, y, xerr, yerr_lower, yerr_upper ]
|
44
|
+
|
45
|
+
By default no end caps are drawn. Setting upperCap and/or lowerCap to "-" will
|
46
|
+
draw a small cap perpendicular to the error bar. They can also be set to a
|
47
|
+
user-defined drawing function, with (ctx, x, y, radius) as parameters, as eg.
|
48
|
+
|
49
|
+
function drawSemiCircle( ctx, x, y, radius ) {
|
50
|
+
ctx.beginPath();
|
51
|
+
ctx.arc( x, y, radius, 0, Math.PI, false );
|
52
|
+
ctx.moveTo( x - radius, y );
|
53
|
+
ctx.lineTo( x + radius, y );
|
54
|
+
ctx.stroke();
|
55
|
+
}
|
56
|
+
|
57
|
+
Color and radius both default to the same ones of the points series if not
|
58
|
+
set. The independent radius parameter on xerr/yerr is useful for the case when
|
59
|
+
we may want to add error-bars to a line, without showing the interconnecting
|
60
|
+
points (with radius: 0), and still showing end caps on the error-bars.
|
61
|
+
shadowSize and lineWidth are derived as well from the points series.
|
62
|
+
|
63
|
+
*/(function(e){function n(e,t,n,r){if(!t.points.errorbars)return;var i=[{x:!0,number:!0,required:!0},{y:!0,number:!0,required:!0}],s=t.points.errorbars;if(s=="x"||s=="xy")t.points.xerr.asymmetric?(i.push({x:!0,number:!0,required:!0}),i.push({x:!0,number:!0,required:!0})):i.push({x:!0,number:!0,required:!0});if(s=="y"||s=="xy")t.points.yerr.asymmetric?(i.push({y:!0,number:!0,required:!0}),i.push({y:!0,number:!0,required:!0})):i.push({y:!0,number:!0,required:!0});r.format=i}function r(e,t){var n=e.datapoints.points,r=null,i=null,s=null,o=null,u=e.points.xerr,a=e.points.yerr,f=e.points.errorbars;f=="x"||f=="xy"?u.asymmetric?(r=n[t+2],i=n[t+3],f=="xy"&&(a.asymmetric?(s=n[t+4],o=n[t+5]):s=n[t+4])):(r=n[t+2],f=="xy"&&(a.asymmetric?(s=n[t+3],o=n[t+4]):s=n[t+3])):f=="y"&&(a.asymmetric?(s=n[t+2],o=n[t+3]):s=n[t+2]),i==null&&(i=r),o==null&&(o=s);var l=[r,i,s,o];return u.show||(l[0]=null,l[1]=null),a.show||(l[2]=null,l[3]=null),l}function i(e,t,n){var i=n.datapoints.points,o=n.datapoints.pointsize,u=[n.xaxis,n.yaxis],a=n.points.radius,f=[n.points.xerr,n.points.yerr],l=!1;if(u[0].p2c(u[0].max)<u[0].p2c(u[0].min)){l=!0;var c=f[0].lowerCap;f[0].lowerCap=f[0].upperCap,f[0].upperCap=c}var h=!1;if(u[1].p2c(u[1].min)<u[1].p2c(u[1].max)){h=!0;var c=f[1].lowerCap;f[1].lowerCap=f[1].upperCap,f[1].upperCap=c}for(var p=0;p<n.datapoints.points.length;p+=o){var d=r(n,p);for(var v=0;v<f.length;v++){var m=[u[v].min,u[v].max];if(d[v*f.length]){var g=i[p],y=i[p+1],b=[g,y][v]+d[v*f.length+1],w=[g,y][v]-d[v*f.length];if(f[v].err=="x")if(y>u[1].max||y<u[1].min||b<u[0].min||w>u[0].max)continue;if(f[v].err=="y")if(g>u[0].max||g<u[0].min||b<u[1].min||w>u[1].max)continue;var E=!0,S=!0;b>m[1]&&(E=!1,b=m[1]),w<m[0]&&(S=!1,w=m[0]);if(f[v].err=="x"&&l||f[v].err=="y"&&h){var c=w;w=b,b=c,c=S,S=E,E=c,c=m[0],m[0]=m[1],m[1]=c}g=u[0].p2c(g),y=u[1].p2c(y),b=u[v].p2c(b),w=u[v].p2c(w),m[0]=u[v].p2c(m[0]),m[1]=u[v].p2c(m[1]);var x=f[v].lineWidth?f[v].lineWidth:n.points.lineWidth,T=n.points.shadowSize!=null?n.points.shadowSize:n.shadowSize;if(x>0&&T>0){var N=T/2;t.lineWidth=N,t.strokeStyle="rgba(0,0,0,0.1)",s(t,f[v],g,y,b,w,E,S,a,N+N/2,m),t.strokeStyle="rgba(0,0,0,0.2)",s(t,f[v],g,y,b,w,E,S,a,N/2,m)}t.strokeStyle=f[v].color?f[v].color:n.color,t.lineWidth=x,s(t,f[v],g,y,b,w,E,S,a,0,m)}}}}function s(t,n,r,i,s,u,a,f,l,c,h){i+=c,s+=c,u+=c,n.err=="x"?(s>r+l?o(t,[[s,i],[Math.max(r+l,h[0]),i]]):a=!1,u<r-l?o(t,[[Math.min(r-l,h[1]),i],[u,i]]):f=!1):(s<i-l?o(t,[[r,s],[r,Math.min(i-l,h[0])]]):a=!1,u>i+l?o(t,[[r,Math.max(i+l,h[1])],[r,u]]):f=!1),l=n.radius!=null?n.radius:l,a&&(n.upperCap=="-"?n.err=="x"?o(t,[[s,i-l],[s,i+l]]):o(t,[[r-l,s],[r+l,s]]):e.isFunction(n.upperCap)&&(n.err=="x"?n.upperCap(t,s,i,l):n.upperCap(t,r,s,l))),f&&(n.lowerCap=="-"?n.err=="x"?o(t,[[u,i-l],[u,i+l]]):o(t,[[r-l,u],[r+l,u]]):e.isFunction(n.lowerCap)&&(n.err=="x"?n.lowerCap(t,u,i,l):n.lowerCap(t,r,u,l)))}function o(e,t){e.beginPath(),e.moveTo(t[0][0],t[0][1]);for(var n=1;n<t.length;n++)e.lineTo(t[n][0],t[n][1]);e.stroke()}function u(t,n){var r=t.getPlotOffset();n.save(),n.translate(r.left,r.top),e.each(t.getData(),function(e,r){r.points.errorbars&&(r.points.xerr.show||r.points.yerr.show)&&i(t,n,r)}),n.restore()}function a(e){e.hooks.processRawData.push(n),e.hooks.draw.push(u)}var t={series:{points:{errorbars:null,xerr:{err:"x",show:null,asymmetric:null,upperCap:null,lowerCap:null,color:null,radius:null},yerr:{err:"y",show:null,asymmetric:null,upperCap:null,lowerCap:null,color:null,radius:null}}}};e.plot.plugins.push({init:a,options:t,name:"errorbars",version:"1.0"})})(jQuery);
|
@@ -0,0 +1,226 @@
|
|
1
|
+
/* Flot plugin for computing bottoms for filled line and bar charts.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2013 IOLA and Ole Laursen.
|
4
|
+
Licensed under the MIT license.
|
5
|
+
|
6
|
+
The case: you've got two series that you want to fill the area between. In Flot
|
7
|
+
terms, you need to use one as the fill bottom of the other. You can specify the
|
8
|
+
bottom of each data point as the third coordinate manually, or you can use this
|
9
|
+
plugin to compute it for you.
|
10
|
+
|
11
|
+
In order to name the other series, you need to give it an id, like this:
|
12
|
+
|
13
|
+
var dataset = [
|
14
|
+
{ data: [ ... ], id: "foo" } , // use default bottom
|
15
|
+
{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
|
16
|
+
];
|
17
|
+
|
18
|
+
$.plot($("#placeholder"), dataset, { lines: { show: true, fill: true }});
|
19
|
+
|
20
|
+
As a convenience, if the id given is a number that doesn't appear as an id in
|
21
|
+
the series, it is interpreted as the index in the array instead (so fillBetween:
|
22
|
+
0 can also mean the first series).
|
23
|
+
|
24
|
+
Internally, the plugin modifies the datapoints in each series. For line series,
|
25
|
+
extra data points might be inserted through interpolation. Note that at points
|
26
|
+
where the bottom line is not defined (due to a null point or start/end of line),
|
27
|
+
the current line will show a gap too. The algorithm comes from the
|
28
|
+
jquery.flot.stack.js plugin, possibly some code could be shared.
|
29
|
+
|
30
|
+
*/
|
31
|
+
|
32
|
+
(function ( $ ) {
|
33
|
+
|
34
|
+
var options = {
|
35
|
+
series: {
|
36
|
+
fillBetween: null // or number
|
37
|
+
}
|
38
|
+
};
|
39
|
+
|
40
|
+
function init( plot ) {
|
41
|
+
|
42
|
+
function findBottomSeries( s, allseries ) {
|
43
|
+
|
44
|
+
var i;
|
45
|
+
|
46
|
+
for ( i = 0; i < allseries.length; ++i ) {
|
47
|
+
if ( allseries[ i ].id === s.fillBetween ) {
|
48
|
+
return allseries[ i ];
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
if ( typeof s.fillBetween === "number" ) {
|
53
|
+
if ( s.fillBetween < 0 || s.fillBetween >= allseries.length ) {
|
54
|
+
return null;
|
55
|
+
}
|
56
|
+
return allseries[ s.fillBetween ];
|
57
|
+
}
|
58
|
+
|
59
|
+
return null;
|
60
|
+
}
|
61
|
+
|
62
|
+
function computeFillBottoms( plot, s, datapoints ) {
|
63
|
+
|
64
|
+
if ( s.fillBetween == null ) {
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
|
68
|
+
var other = findBottomSeries( s, plot.getData() );
|
69
|
+
|
70
|
+
if ( !other ) {
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
|
74
|
+
var ps = datapoints.pointsize,
|
75
|
+
points = datapoints.points,
|
76
|
+
otherps = other.datapoints.pointsize,
|
77
|
+
otherpoints = other.datapoints.points,
|
78
|
+
newpoints = [],
|
79
|
+
px, py, intery, qx, qy, bottom,
|
80
|
+
withlines = s.lines.show,
|
81
|
+
withbottom = ps > 2 && datapoints.format[2].y,
|
82
|
+
withsteps = withlines && s.lines.steps,
|
83
|
+
fromgap = true,
|
84
|
+
i = 0,
|
85
|
+
j = 0,
|
86
|
+
l, m;
|
87
|
+
|
88
|
+
while ( true ) {
|
89
|
+
|
90
|
+
if ( i >= points.length ) {
|
91
|
+
break;
|
92
|
+
}
|
93
|
+
|
94
|
+
l = newpoints.length;
|
95
|
+
|
96
|
+
if ( points[ i ] == null ) {
|
97
|
+
|
98
|
+
// copy gaps
|
99
|
+
|
100
|
+
for ( m = 0; m < ps; ++m ) {
|
101
|
+
newpoints.push( points[ i + m ] );
|
102
|
+
}
|
103
|
+
|
104
|
+
i += ps;
|
105
|
+
|
106
|
+
} else if ( j >= otherpoints.length ) {
|
107
|
+
|
108
|
+
// for lines, we can't use the rest of the points
|
109
|
+
|
110
|
+
if ( !withlines ) {
|
111
|
+
for ( m = 0; m < ps; ++m ) {
|
112
|
+
newpoints.push( points[ i + m ] );
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
i += ps;
|
117
|
+
|
118
|
+
} else if ( otherpoints[ j ] == null ) {
|
119
|
+
|
120
|
+
// oops, got a gap
|
121
|
+
|
122
|
+
for ( m = 0; m < ps; ++m ) {
|
123
|
+
newpoints.push( null );
|
124
|
+
}
|
125
|
+
|
126
|
+
fromgap = true;
|
127
|
+
j += otherps;
|
128
|
+
|
129
|
+
} else {
|
130
|
+
|
131
|
+
// cases where we actually got two points
|
132
|
+
|
133
|
+
px = points[ i ];
|
134
|
+
py = points[ i + 1 ];
|
135
|
+
qx = otherpoints[ j ];
|
136
|
+
qy = otherpoints[ j + 1 ];
|
137
|
+
bottom = 0;
|
138
|
+
|
139
|
+
if ( px === qx ) {
|
140
|
+
|
141
|
+
for ( m = 0; m < ps; ++m ) {
|
142
|
+
newpoints.push( points[ i + m ] );
|
143
|
+
}
|
144
|
+
|
145
|
+
//newpoints[ l + 1 ] += qy;
|
146
|
+
bottom = qy;
|
147
|
+
|
148
|
+
i += ps;
|
149
|
+
j += otherps;
|
150
|
+
|
151
|
+
} else if ( px > qx ) {
|
152
|
+
|
153
|
+
// we got past point below, might need to
|
154
|
+
// insert interpolated extra point
|
155
|
+
|
156
|
+
if ( withlines && i > 0 && points[ i - ps ] != null ) {
|
157
|
+
intery = py + ( points[ i - ps + 1 ] - py ) * ( qx - px ) / ( points[ i - ps ] - px );
|
158
|
+
newpoints.push( qx );
|
159
|
+
newpoints.push( intery );
|
160
|
+
for ( m = 2; m < ps; ++m ) {
|
161
|
+
newpoints.push( points[ i + m ] );
|
162
|
+
}
|
163
|
+
bottom = qy;
|
164
|
+
}
|
165
|
+
|
166
|
+
j += otherps;
|
167
|
+
|
168
|
+
} else { // px < qx
|
169
|
+
|
170
|
+
// if we come from a gap, we just skip this point
|
171
|
+
|
172
|
+
if ( fromgap && withlines ) {
|
173
|
+
i += ps;
|
174
|
+
continue;
|
175
|
+
}
|
176
|
+
|
177
|
+
for ( m = 0; m < ps; ++m ) {
|
178
|
+
newpoints.push( points[ i + m ] );
|
179
|
+
}
|
180
|
+
|
181
|
+
// we might be able to interpolate a point below,
|
182
|
+
// this can give us a better y
|
183
|
+
|
184
|
+
if ( withlines && j > 0 && otherpoints[ j - otherps ] != null ) {
|
185
|
+
bottom = qy + ( otherpoints[ j - otherps + 1 ] - qy ) * ( px - qx ) / ( otherpoints[ j - otherps ] - qx );
|
186
|
+
}
|
187
|
+
|
188
|
+
//newpoints[l + 1] += bottom;
|
189
|
+
|
190
|
+
i += ps;
|
191
|
+
}
|
192
|
+
|
193
|
+
fromgap = false;
|
194
|
+
|
195
|
+
if ( l !== newpoints.length && withbottom ) {
|
196
|
+
newpoints[ l + 2 ] = bottom;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
// maintain the line steps invariant
|
201
|
+
|
202
|
+
if ( withsteps && l !== newpoints.length && l > 0 &&
|
203
|
+
newpoints[ l ] !== null &&
|
204
|
+
newpoints[ l ] !== newpoints[ l - ps ] &&
|
205
|
+
newpoints[ l + 1 ] !== newpoints[ l - ps + 1 ] ) {
|
206
|
+
for (m = 0; m < ps; ++m) {
|
207
|
+
newpoints[ l + ps + m ] = newpoints[ l + m ];
|
208
|
+
}
|
209
|
+
newpoints[ l + 1 ] = newpoints[ l - ps + 1 ];
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
datapoints.points = newpoints;
|
214
|
+
}
|
215
|
+
|
216
|
+
plot.hooks.processDatapoints.push( computeFillBottoms );
|
217
|
+
}
|
218
|
+
|
219
|
+
$.plot.plugins.push({
|
220
|
+
init: init,
|
221
|
+
options: options,
|
222
|
+
name: "fillbetween",
|
223
|
+
version: "1.0"
|
224
|
+
});
|
225
|
+
|
226
|
+
})(jQuery);
|
@@ -0,0 +1,30 @@
|
|
1
|
+
/* Flot plugin for computing bottoms for filled line and bar charts.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2013 IOLA and Ole Laursen.
|
4
|
+
Licensed under the MIT license.
|
5
|
+
|
6
|
+
The case: you've got two series that you want to fill the area between. In Flot
|
7
|
+
terms, you need to use one as the fill bottom of the other. You can specify the
|
8
|
+
bottom of each data point as the third coordinate manually, or you can use this
|
9
|
+
plugin to compute it for you.
|
10
|
+
|
11
|
+
In order to name the other series, you need to give it an id, like this:
|
12
|
+
|
13
|
+
var dataset = [
|
14
|
+
{ data: [ ... ], id: "foo" } , // use default bottom
|
15
|
+
{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
|
16
|
+
];
|
17
|
+
|
18
|
+
$.plot($("#placeholder"), dataset, { lines: { show: true, fill: true }});
|
19
|
+
|
20
|
+
As a convenience, if the id given is a number that doesn't appear as an id in
|
21
|
+
the series, it is interpreted as the index in the array instead (so fillBetween:
|
22
|
+
0 can also mean the first series).
|
23
|
+
|
24
|
+
Internally, the plugin modifies the datapoints in each series. For line series,
|
25
|
+
extra data points might be inserted through interpolation. Note that at points
|
26
|
+
where the bottom line is not defined (due to a null point or start/end of line),
|
27
|
+
the current line will show a gap too. The algorithm comes from the
|
28
|
+
jquery.flot.stack.js plugin, possibly some code could be shared.
|
29
|
+
|
30
|
+
*/(function(e){function n(e){function t(e,t){var n;for(n=0;n<t.length;++n)if(t[n].id===e.fillBetween)return t[n];return typeof e.fillBetween=="number"?e.fillBetween<0||e.fillBetween>=t.length?null:t[e.fillBetween]:null}function n(e,n,r){if(n.fillBetween==null)return;var i=t(n,e.getData());if(!i)return;var s=r.pointsize,o=r.points,u=i.datapoints.pointsize,a=i.datapoints.points,f=[],l,c,h,p,d,v,m=n.lines.show,g=s>2&&r.format[2].y,y=m&&n.lines.steps,b=!0,w=0,E=0,S,x;for(;;){if(w>=o.length)break;S=f.length;if(o[w]==null){for(x=0;x<s;++x)f.push(o[w+x]);w+=s}else if(E>=a.length){if(!m)for(x=0;x<s;++x)f.push(o[w+x]);w+=s}else if(a[E]==null){for(x=0;x<s;++x)f.push(null);b=!0,E+=u}else{l=o[w],c=o[w+1],p=a[E],d=a[E+1],v=0;if(l===p){for(x=0;x<s;++x)f.push(o[w+x]);v=d,w+=s,E+=u}else if(l>p){if(m&&w>0&&o[w-s]!=null){h=c+(o[w-s+1]-c)*(p-l)/(o[w-s]-l),f.push(p),f.push(h);for(x=2;x<s;++x)f.push(o[w+x]);v=d}E+=u}else{if(b&&m){w+=s;continue}for(x=0;x<s;++x)f.push(o[w+x]);m&&E>0&&a[E-u]!=null&&(v=d+(a[E-u+1]-d)*(l-p)/(a[E-u]-p)),w+=s}b=!1,S!==f.length&&g&&(f[S+2]=v)}if(y&&S!==f.length&&S>0&&f[S]!==null&&f[S]!==f[S-s]&&f[S+1]!==f[S-s+1]){for(x=0;x<s;++x)f[S+s+x]=f[S+x];f[S+1]=f[S-s+1]}}r.points=f}e.hooks.processDatapoints.push(n)}var t={series:{fillBetween:null}};e.plot.plugins.push({init:n,options:t,name:"fillbetween",version:"1.0"})})(jQuery);
|