root / hci / trunk / eneraptor-web-app / web-app / js / flot / jquery.flot.stack.js @ 11
History | View | Annotate | Download (5.33 KB)
1 | 11 | alexbesir | /*
|
---|---|---|---|
2 | Flot plugin for stacking data sets, i.e. putting them on top of each
|
||
3 | other, for accumulative graphs. Note that the plugin assumes the data
|
||
4 | is sorted on x. Also note that stacking a mix of positive and negative
|
||
5 | values in most instances doesn't make sense (so it looks weird).
|
||
6 | |||
7 | Two or more series are stacked when their "stack" attribute is set to
|
||
8 | the same key (which can be any number or string or just "true"). To
|
||
9 | specify the default stack, you can set
|
||
10 | |||
11 | series: {
|
||
12 | stack: null or true or key (number/string)
|
||
13 | }
|
||
14 | |||
15 | or specify it for a specific series
|
||
16 | |||
17 | $.plot($("#placeholder"), [{ data: [ ... ], stack: true ])
|
||
18 | |||
19 | The stacking order is determined by the order of the data series in
|
||
20 | the array (later series end up on top of the previous).
|
||
21 | |||
22 | Internally, the plugin modifies the datapoints in each series, adding
|
||
23 | an offset to the y value. For line series, extra data points are
|
||
24 | inserted through interpolation. For bar charts, the second y value is
|
||
25 | also adjusted.
|
||
26 | */
|
||
27 | |||
28 | (function ($) { |
||
29 | var options = {
|
||
30 | series: { stack: null } // or number/string |
||
31 | }; |
||
32 | |||
33 | function init(plot) { |
||
34 | function findMatchingSeries(s, allseries) { |
||
35 | var res = null |
||
36 | for (var i = 0; i < allseries.length; ++i) { |
||
37 | if (s == allseries[i])
|
||
38 | break;
|
||
39 | |||
40 | if (allseries[i].stack == s.stack)
|
||
41 | res = allseries[i]; |
||
42 | } |
||
43 | |||
44 | return res;
|
||
45 | } |
||
46 | |||
47 | function stackData(plot, s, datapoints) { |
||
48 | if (s.stack == null) |
||
49 | return;
|
||
50 | |||
51 | var other = findMatchingSeries(s, plot.getData());
|
||
52 | if (!other)
|
||
53 | return;
|
||
54 | |||
55 | var ps = datapoints.pointsize,
|
||
56 | points = datapoints.points, |
||
57 | otherps = other.datapoints.pointsize, |
||
58 | otherpoints = other.datapoints.points, |
||
59 | newpoints = [], |
||
60 | px, py, intery, qx, qy, bottom, |
||
61 | withlines = s.lines.show, withbars = s.bars.show, |
||
62 | withsteps = withlines && s.lines.steps, |
||
63 | i = 0, j = 0, l; |
||
64 | |||
65 | while (true) { |
||
66 | if (i >= points.length)
|
||
67 | break;
|
||
68 | |||
69 | l = newpoints.length; |
||
70 | |||
71 | if (j >= otherpoints.length
|
||
72 | || otherpoints[j] == null
|
||
73 | || points[i] == null) {
|
||
74 | // degenerate cases
|
||
75 | for (m = 0; m < ps; ++m) |
||
76 | newpoints.push(points[i + m]); |
||
77 | i += ps; |
||
78 | } |
||
79 | else {
|
||
80 | // cases where we actually got two points
|
||
81 | px = points[i]; |
||
82 | py = points[i + 1];
|
||
83 | qx = otherpoints[j]; |
||
84 | qy = otherpoints[j + 1];
|
||
85 | bottom = 0;
|
||
86 | |||
87 | if (px == qx) {
|
||
88 | for (m = 0; m < ps; ++m) |
||
89 | newpoints.push(points[i + m]); |
||
90 | |||
91 | newpoints[l + 1] += qy;
|
||
92 | bottom = qy; |
||
93 | |||
94 | i += ps; |
||
95 | j += otherps; |
||
96 | } |
||
97 | else if (px > qx) { |
||
98 | // we got past point below, might need to
|
||
99 | // insert interpolated extra point
|
||
100 | if (withlines && i > 0 && points[i - ps] != null) { |
||
101 | intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
|
||
102 | newpoints.push(qx); |
||
103 | newpoints.push(intery + qy) |
||
104 | for (m = 2; m < ps; ++m) |
||
105 | newpoints.push(points[i + m]); |
||
106 | bottom = qy; |
||
107 | } |
||
108 | |||
109 | j += otherps; |
||
110 | } |
||
111 | else {
|
||
112 | for (m = 0; m < ps; ++m) |
||
113 | newpoints.push(points[i + m]); |
||
114 | |||
115 | // we might be able to interpolate a point below,
|
||
116 | // this can give us a better y
|
||
117 | if (withlines && j > 0 && otherpoints[j - ps] != null) |
||
118 | bottom = qy + (otherpoints[j - ps + 1] - qy) * (px - qx) / (otherpoints[j - ps] - qx);
|
||
119 | |||
120 | newpoints[l + 1] += bottom;
|
||
121 | |||
122 | i += ps; |
||
123 | } |
||
124 | |||
125 | if (l != newpoints.length && withbars)
|
||
126 | newpoints[l + 2] += bottom;
|
||
127 | } |
||
128 | |||
129 | // maintain the line steps invariant
|
||
130 | if (withsteps && l != newpoints.length && l > 0 |
||
131 | && newpoints[l] != null
|
||
132 | && newpoints[l] != newpoints[l - ps] |
||
133 | && newpoints[l + 1] != newpoints[l - ps + 1]) { |
||
134 | for (m = 0; m < ps; ++m) |
||
135 | newpoints[l + ps + m] = newpoints[l + m]; |
||
136 | newpoints[l + 1] = newpoints[l - ps + 1]; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | datapoints.points = newpoints; |
||
141 | } |
||
142 | |||
143 | plot.hooks.processDatapoints.push(stackData); |
||
144 | } |
||
145 | |||
146 | $.plot.plugins.push({
|
||
147 | init: init,
|
||
148 | options: options,
|
||
149 | name: 'stack', |
||
150 | version: '1.0' |
||
151 | }); |
||
152 | })(jQuery); |