Statistics
| Revision:

root / hci / trunk / eneraptor-web-app / web-app / js / flot / jquery.flot.stack.js @ 11

History | View | Annotate | Download (5.33 KB)

1
/*
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);