]>
Commit | Line | Data |
---|---|---|
31f18b77 FG |
1 | /* Flot plugin for thresholding data. |
2 | ||
3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. | |
4 | Licensed under the MIT license. | |
5 | ||
6 | The plugin supports these options: | |
7 | ||
8 | series: { | |
9 | threshold: { | |
10 | below: number | |
11 | color: colorspec | |
12 | } | |
13 | } | |
14 | ||
15 | It can also be applied to a single series, like this: | |
16 | ||
17 | $.plot( $("#placeholder"), [{ | |
18 | data: [ ... ], | |
19 | threshold: { ... } | |
20 | }]) | |
21 | ||
22 | An array can be passed for multiple thresholding, like this: | |
23 | ||
24 | threshold: [{ | |
25 | below: number1 | |
26 | color: color1 | |
27 | },{ | |
28 | below: number2 | |
29 | color: color2 | |
30 | }] | |
31 | ||
32 | These multiple threshold objects can be passed in any order since they are | |
33 | sorted by the processing function. | |
34 | ||
35 | The data points below "below" are drawn with the specified color. This makes | |
36 | it easy to mark points below 0, e.g. for budget data. | |
37 | ||
38 | Internally, the plugin works by splitting the data into two series, above and | |
39 | below the threshold. The extra series below the threshold will have its label | |
40 | cleared and the special "originSeries" attribute set to the original series. | |
41 | You may need to check for this in hover events. | |
42 | ||
43 | */ | |
44 | ||
45 | (function ($) { | |
46 | var options = { | |
47 | series: { threshold: null } // or { below: number, color: color spec} | |
48 | }; | |
49 | ||
50 | function init(plot) { | |
51 | function thresholdData(plot, s, datapoints, below, color) { | |
52 | var ps = datapoints.pointsize, i, x, y, p, prevp, | |
53 | thresholded = $.extend({}, s); // note: shallow copy | |
54 | ||
55 | thresholded.datapoints = { points: [], pointsize: ps, format: datapoints.format }; | |
56 | thresholded.label = null; | |
57 | thresholded.color = color; | |
58 | thresholded.threshold = null; | |
59 | thresholded.originSeries = s; | |
60 | thresholded.data = []; | |
61 | ||
62 | var origpoints = datapoints.points, | |
63 | addCrossingPoints = s.lines.show; | |
64 | ||
65 | var threspoints = []; | |
66 | var newpoints = []; | |
67 | var m; | |
68 | ||
69 | for (i = 0; i < origpoints.length; i += ps) { | |
70 | x = origpoints[i]; | |
71 | y = origpoints[i + 1]; | |
72 | ||
73 | prevp = p; | |
74 | if (y < below) | |
75 | p = threspoints; | |
76 | else | |
77 | p = newpoints; | |
78 | ||
79 | if (addCrossingPoints && prevp != p && x != null | |
80 | && i > 0 && origpoints[i - ps] != null) { | |
81 | var interx = x + (below - y) * (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]); | |
82 | prevp.push(interx); | |
83 | prevp.push(below); | |
84 | for (m = 2; m < ps; ++m) | |
85 | prevp.push(origpoints[i + m]); | |
86 | ||
87 | p.push(null); // start new segment | |
88 | p.push(null); | |
89 | for (m = 2; m < ps; ++m) | |
90 | p.push(origpoints[i + m]); | |
91 | p.push(interx); | |
92 | p.push(below); | |
93 | for (m = 2; m < ps; ++m) | |
94 | p.push(origpoints[i + m]); | |
95 | } | |
96 | ||
97 | p.push(x); | |
98 | p.push(y); | |
99 | for (m = 2; m < ps; ++m) | |
100 | p.push(origpoints[i + m]); | |
101 | } | |
102 | ||
103 | datapoints.points = newpoints; | |
104 | thresholded.datapoints.points = threspoints; | |
105 | ||
106 | if (thresholded.datapoints.points.length > 0) { | |
107 | var origIndex = $.inArray(s, plot.getData()); | |
108 | // Insert newly-generated series right after original one (to prevent it from becoming top-most) | |
109 | plot.getData().splice(origIndex + 1, 0, thresholded); | |
110 | } | |
111 | ||
112 | // FIXME: there are probably some edge cases left in bars | |
113 | } | |
114 | ||
115 | function processThresholds(plot, s, datapoints) { | |
116 | if (!s.threshold) | |
117 | return; | |
118 | ||
119 | if (s.threshold instanceof Array) { | |
120 | s.threshold.sort(function(a, b) { | |
121 | return a.below - b.below; | |
122 | }); | |
123 | ||
124 | $(s.threshold).each(function(i, th) { | |
125 | thresholdData(plot, s, datapoints, th.below, th.color); | |
126 | }); | |
127 | } | |
128 | else { | |
129 | thresholdData(plot, s, datapoints, s.threshold.below, s.threshold.color); | |
130 | } | |
131 | } | |
132 | ||
133 | plot.hooks.processDatapoints.push(processThresholds); | |
134 | } | |
135 | ||
136 | $.plot.plugins.push({ | |
137 | init: init, | |
138 | options: options, | |
139 | name: 'threshold', | |
140 | version: '1.2' | |
141 | }); | |
142 | })(jQuery); |