summaryrefslogtreecommitdiff
path: root/jquery.flot.stack.js
diff options
context:
space:
mode:
authorIgor Sfiligoi <isfiligoi@ucsd.edu>2009-10-23 09:07:01 -0400
committerIgor Sfiligoi <isfiligoi@ucsd.edu>2009-10-23 09:07:01 -0400
commitaf26aaa53d073a7b2d25caee93e1cb5ceb2e099c (patch)
treebcb8d15baea1f07375d1dedea414b1b95d58caa6 /jquery.flot.stack.js
parentbf64e197b39d3f10b6145612802a6f169248cb45 (diff)
flot-0.6
Diffstat (limited to 'jquery.flot.stack.js')
-rw-r--r--jquery.flot.stack.js152
1 files changed, 152 insertions, 0 deletions
diff --git a/jquery.flot.stack.js b/jquery.flot.stack.js
new file mode 100644
index 0000000..4dbd29f
--- /dev/null
+++ b/jquery.flot.stack.js
@@ -0,0 +1,152 @@
+/*
+Flot plugin for stacking data sets, i.e. putting them on top of each
+other, for accumulative graphs. Note that the plugin assumes the data
+is sorted on x. Also note that stacking a mix of positive and negative
+values in most instances doesn't make sense (so it looks weird).
+
+Two or more series are stacked when their "stack" attribute is set to
+the same key (which can be any number or string or just "true"). To
+specify the default stack, you can set
+
+ series: {
+ stack: null or true or key (number/string)
+ }
+
+or specify it for a specific series
+
+ $.plot($("#placeholder"), [{ data: [ ... ], stack: true ])
+
+The stacking order is determined by the order of the data series in
+the array (later series end up on top of the previous).
+
+Internally, the plugin modifies the datapoints in each series, adding
+an offset to the y value. For line series, extra data points are
+inserted through interpolation. For bar charts, the second y value is
+also adjusted.
+*/
+
+(function ($) {
+ var options = {
+ series: { stack: null } // or number/string
+ };
+
+ function init(plot) {
+ function findMatchingSeries(s, allseries) {
+ var res = null
+ for (var i = 0; i < allseries.length; ++i) {
+ if (s == allseries[i])
+ break;
+
+ if (allseries[i].stack == s.stack)
+ res = allseries[i];
+ }
+
+ return res;
+ }
+
+ function stackData(plot, s, datapoints) {
+ if (s.stack == null)
+ return;
+
+ var other = findMatchingSeries(s, plot.getData());
+ if (!other)
+ return;
+
+ var ps = datapoints.pointsize,
+ points = datapoints.points,
+ otherps = other.datapoints.pointsize,
+ otherpoints = other.datapoints.points,
+ newpoints = [],
+ px, py, intery, qx, qy, bottom,
+ withlines = s.lines.show, withbars = s.bars.show,
+ withsteps = withlines && s.lines.steps,
+ i = 0, j = 0, l;
+
+ while (true) {
+ if (i >= points.length)
+ break;
+
+ l = newpoints.length;
+
+ if (j >= otherpoints.length
+ || otherpoints[j] == null
+ || points[i] == null) {
+ // degenerate cases
+ for (m = 0; m < ps; ++m)
+ newpoints.push(points[i + m]);
+ i += ps;
+ }
+ else {
+ // cases where we actually got two points
+ px = points[i];
+ py = points[i + 1];
+ qx = otherpoints[j];
+ qy = otherpoints[j + 1];
+ bottom = 0;
+
+ if (px == qx) {
+ for (m = 0; m < ps; ++m)
+ newpoints.push(points[i + m]);
+
+ newpoints[l + 1] += qy;
+ bottom = qy;
+
+ i += ps;
+ j += otherps;
+ }
+ else if (px > qx) {
+ // we got past point below, might need to
+ // insert interpolated extra point
+ if (withlines && i > 0 && points[i - ps] != null) {
+ intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
+ newpoints.push(qx);
+ newpoints.push(intery + qy)
+ for (m = 2; m < ps; ++m)
+ newpoints.push(points[i + m]);
+ bottom = qy;
+ }
+
+ j += otherps;
+ }
+ else {
+ for (m = 0; m < ps; ++m)
+ newpoints.push(points[i + m]);
+
+ // we might be able to interpolate a point below,
+ // this can give us a better y
+ if (withlines && j > 0 && otherpoints[j - ps] != null)
+ bottom = qy + (otherpoints[j - ps + 1] - qy) * (px - qx) / (otherpoints[j - ps] - qx);
+
+ newpoints[l + 1] += bottom;
+
+ i += ps;
+ }
+
+ if (l != newpoints.length && withbars)
+ newpoints[l + 2] += bottom;
+ }
+
+ // maintain the line steps invariant
+ if (withsteps && l != newpoints.length && l > 0
+ && newpoints[l] != null
+ && newpoints[l] != newpoints[l - ps]
+ && newpoints[l + 1] != newpoints[l - ps + 1]) {
+ for (m = 0; m < ps; ++m)
+ newpoints[l + ps + m] = newpoints[l + m];
+ newpoints[l + 1] = newpoints[l - ps + 1];
+ }
+ }
+
+ datapoints.points = newpoints;
+ }
+
+ plot.hooks.processDatapoints.push(stackData);
+ }
+
+ $.plot.plugins.push({
+ init: init,
+ options: options,
+ name: 'stack',
+ version: '1.0'
+ });
+})(jQuery);