Initial OpenECOMP policy/engine commit
[policy/engine.git] / ecomp-sdk-app / src / main / webapp / static / fusion / raptor / d3 / js / models / stackedArea.js
1
2 nv.models.stackedArea = function() {
3   "use strict";
4   //============================================================
5   // Public Variables with Default Settings
6   //------------------------------------------------------------
7
8   var margin = {top: 0, right: 0, bottom: 0, left: 0}
9     , width = 960
10     , height = 500
11     , color = nv.utils.defaultColor() // a function that computes the color
12     , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one
13     , getX = function(d) { return d.x } // accessor to get the x value from a data point
14     , getY = function(d) { return d.y } // accessor to get the y value from a data point
15     , style = 'stack'
16     , offset = 'zero'
17     , order = 'default'
18     , interpolate = 'linear'  // controls the line interpolation
19     , clipEdge = false // if true, masks lines within x and y scale
20     , x //can be accessed via chart.xScale()
21     , y //can be accessed via chart.yScale()
22     , scatter = nv.models.scatter()
23     , dispatch =  d3.dispatch('tooltipShow', 'tooltipHide', 'areaClick', 'areaMouseover', 'areaMouseout')
24     ;
25
26   scatter
27     .size(2.2) // default size
28     .sizeDomain([2.2,2.2]) // all the same size by default
29     ;
30
31   /************************************
32    * offset:
33    *   'wiggle' (stream)
34    *   'zero' (stacked)
35    *   'expand' (normalize to 100%)
36    *   'silhouette' (simple centered)
37    *
38    * order:
39    *   'inside-out' (stream)
40    *   'default' (input order)
41    ************************************/
42
43   //============================================================
44
45
46   function chart(selection) {
47     selection.each(function(data) {
48       var availableWidth = width - margin.left - margin.right,
49           availableHeight = height - margin.top - margin.bottom,
50           container = d3.select(this);
51
52       //------------------------------------------------------------
53       // Setup Scales
54
55       x = scatter.xScale();
56       y = scatter.yScale();
57
58       //------------------------------------------------------------
59
60       var dataRaw = data;
61       // Injecting point index into each point because d3.layout.stack().out does not give index
62       data.forEach(function(aseries, i) {
63         aseries.seriesIndex = i;
64         aseries.values = aseries.values.map(function(d, j) {
65           d.index = j;
66           d.seriesIndex = i;
67           return d;
68         });
69       });
70
71       var dataFiltered = data.filter(function(series) {
72             return !series.disabled;
73       });
74
75       data = d3.layout.stack()
76                .order(order)
77                .offset(offset)
78                .values(function(d) { return d.values })  //TODO: make values customizeable in EVERY model in this fashion
79                .x(getX)
80                .y(getY)
81                .out(function(d, y0, y) {
82                     var yHeight = (getY(d) === 0) ? 0 : y;
83                     d.display = {
84                       y: yHeight,
85                      y0: y0
86                     };
87                 })
88               (dataFiltered);
89
90
91       //------------------------------------------------------------
92       // Setup containers and skeleton of chart
93
94       var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]);
95       var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea');
96       var defsEnter = wrapEnter.append('defs');
97       var gEnter = wrapEnter.append('g');
98       var g = wrap.select('g');
99
100       gEnter.append('g').attr('class', 'nv-areaWrap');
101       gEnter.append('g').attr('class', 'nv-scatterWrap');
102
103       wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
104
105       //------------------------------------------------------------
106
107
108       scatter
109         .width(availableWidth)
110         .height(availableHeight)
111         .x(getX)
112         .y(function(d) { return d.display.y + d.display.y0 })
113         .forceY([0])
114         .color(data.map(function(d,i) {
115           return d.color || color(d, d.seriesIndex);
116         }));
117
118
119       var scatterWrap = g.select('.nv-scatterWrap')
120           .datum(data);
121
122       scatterWrap.call(scatter);
123
124       defsEnter.append('clipPath')
125           .attr('id', 'nv-edge-clip-' + id)
126         .append('rect');
127
128       wrap.select('#nv-edge-clip-' + id + ' rect')
129           .attr('width', availableWidth)
130           .attr('height', availableHeight);
131
132       g   .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
133
134       var area = d3.svg.area()
135           .x(function(d,i)  { return x(getX(d,i)) })
136           .y0(function(d) {
137               return y(d.display.y0)
138           })
139           .y1(function(d) {
140               return y(d.display.y + d.display.y0)
141           })
142           .interpolate(interpolate);
143
144       var zeroArea = d3.svg.area()
145           .x(function(d,i)  { return x(getX(d,i)) })
146           .y0(function(d) { return y(d.display.y0) })
147           .y1(function(d) { return y(d.display.y0) });
148
149
150       var path = g.select('.nv-areaWrap').selectAll('path.nv-area')
151           .data(function(d) { return d });
152
153       path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i })
154           .attr('d', function(d,i){
155             return zeroArea(d.values, d.seriesIndex);
156           })
157           .on('mouseover', function(d,i) {
158             d3.select(this).classed('hover', true);
159             dispatch.areaMouseover({
160               point: d,
161               series: d.key,
162               pos: [d3.event.pageX, d3.event.pageY],
163               seriesIndex: i
164             });
165           })
166           .on('mouseout', function(d,i) {
167             d3.select(this).classed('hover', false);
168             dispatch.areaMouseout({
169               point: d,
170               series: d.key,
171               pos: [d3.event.pageX, d3.event.pageY],
172               seriesIndex: i
173             });
174           })
175           .on('click', function(d,i) {
176             d3.select(this).classed('hover', false);
177             dispatch.areaClick({
178               point: d,
179               series: d.key,
180               pos: [d3.event.pageX, d3.event.pageY],
181               seriesIndex: i
182             });
183           })
184       path.exit().transition()
185           .attr('d', function(d,i) { return zeroArea(d.values,i) })
186           .remove();
187       path
188           .style('fill', function(d,i){
189             return d.color || color(d, d.seriesIndex)
190           })
191           .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) });
192       path.transition()
193           .attr('d', function(d,i) {
194             return area(d.values,i)
195           });
196
197
198
199       //============================================================
200       // Event Handling/Dispatching (in chart's scope)
201       //------------------------------------------------------------
202
203       scatter.dispatch.on('elementMouseover.area', function(e) {
204         g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true);
205       });
206       scatter.dispatch.on('elementMouseout.area', function(e) {
207         g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false);
208       });
209
210       //============================================================
211       //Special offset functions
212       chart.d3_stackedOffset_stackPercent = function(stackData) {
213           var n = stackData.length,    //How many series
214           m = stackData[0].length,     //how many points per series
215           k = 1 / n,
216            i,
217            j,
218            o,
219            y0 = [];
220
221           for (j = 0; j < m; ++j) { //Looping through all points
222             for (i = 0, o = 0; i < dataRaw.length; i++)  //looping through series'
223                 o += getY(dataRaw[i].values[j])   //total value of all points at a certian point in time.
224
225             if (o) for (i = 0; i < n; i++)
226                stackData[i][j][1] /= o;
227             else
228               for (i = 0; i < n; i++)
229                stackData[i][j][1] = k;
230           }
231           for (j = 0; j < m; ++j) y0[j] = 0;
232           return y0;
233       };
234
235     });
236
237
238     return chart;
239   }
240
241
242   //============================================================
243   // Event Handling/Dispatching (out of chart's scope)
244   //------------------------------------------------------------
245
246   scatter.dispatch.on('elementClick.area', function(e) {
247     dispatch.areaClick(e);
248   })
249   scatter.dispatch.on('elementMouseover.tooltip', function(e) {
250         e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],
251         dispatch.tooltipShow(e);
252   });
253   scatter.dispatch.on('elementMouseout.tooltip', function(e) {
254         dispatch.tooltipHide(e);
255   });
256
257   //============================================================
258
259   //============================================================
260   // Global getters and setters
261   //------------------------------------------------------------
262
263   chart.dispatch = dispatch;
264   chart.scatter = scatter;
265
266   d3.rebind(chart, scatter, 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange',
267     'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'useVoronoi','clipRadius','highlightPoint','clearHighlights');
268
269   chart.options = nv.utils.optionsFunc.bind(chart);
270
271   chart.x = function(_) {
272     if (!arguments.length) return getX;
273     getX = d3.functor(_);
274     return chart;
275   };
276
277   chart.y = function(_) {
278     if (!arguments.length) return getY;
279     getY = d3.functor(_);
280     return chart;
281   }
282
283   chart.margin = function(_) {
284     if (!arguments.length) return margin;
285     margin.top    = typeof _.top    != 'undefined' ? _.top    : margin.top;
286     margin.right  = typeof _.right  != 'undefined' ? _.right  : margin.right;
287     margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
288     margin.left   = typeof _.left   != 'undefined' ? _.left   : margin.left;
289     return chart;
290   };
291
292   chart.width = function(_) {
293     if (!arguments.length) return width;
294     width = _;
295     return chart;
296   };
297
298   chart.height = function(_) {
299     if (!arguments.length) return height;
300     height = _;
301     return chart;
302   };
303
304   chart.clipEdge = function(_) {
305     if (!arguments.length) return clipEdge;
306     clipEdge = _;
307     return chart;
308   };
309
310   chart.color = function(_) {
311     if (!arguments.length) return color;
312     color = nv.utils.getColor(_);
313     return chart;
314   };
315
316   chart.offset = function(_) {
317     if (!arguments.length) return offset;
318     offset = _;
319     return chart;
320   };
321
322   chart.order = function(_) {
323     if (!arguments.length) return order;
324     order = _;
325     return chart;
326   };
327
328   //shortcut for offset + order
329   chart.style = function(_) {
330     if (!arguments.length) return style;
331     style = _;
332
333     switch (style) {
334       case 'stack':
335         chart.offset('zero');
336         chart.order('default');
337         break;
338       case 'stream':
339         chart.offset('wiggle');
340         chart.order('inside-out');
341         break;
342       case 'stream-center':
343           chart.offset('silhouette');
344           chart.order('inside-out');
345           break;
346       case 'expand':
347         chart.offset('expand');
348         chart.order('default');
349         break;
350       case 'stack_percent':
351         chart.offset(chart.d3_stackedOffset_stackPercent);
352         chart.order('default');
353         break;
354     }
355
356     return chart;
357   };
358
359   chart.interpolate = function(_) {
360             if (!arguments.length) return interpolate;
361             interpolate = _;
362             return chart;
363   };
364   //============================================================
365
366
367   return chart;
368 }