Initial OpenECOMP policy/engine commit
[policy/engine.git] / ecomp-sdk-app / src / main / webapp / app / fusion / external / d3 / js / models / linePlusBarChart.js
1
2 nv.models.linePlusBarChart = function() {
3   "use strict";
4   //============================================================
5   // Public Variables with Default Settings
6   //------------------------------------------------------------
7
8   var lines = nv.models.line()
9     , bars = nv.models.historicalBar()
10     , xAxis = nv.models.axis()
11     , y1Axis = nv.models.axis()
12     , y2Axis = nv.models.axis()
13     , legend = nv.models.legend()
14     ;
15
16   var margin = {top: 30, right: 60, bottom: 50, left: 60}
17     , width = null
18     , height = null
19     , getX = function(d) { return d.x }
20     , getY = function(d) { return d.y }
21     , color = nv.utils.defaultColor()
22     , showLegend = true
23     , tooltips = true
24     , tooltip = function(key, x, y, e, graph) {
25         return '<h3>' + key + '</h3>' +
26                '<p>' +  y + ' at ' + x + '</p>';
27       }
28     , x
29     , y1
30     , y2
31     , state = {}
32     , defaultState = null
33     , noData = "No Data Available."
34     , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
35     ;
36
37   bars
38     .padData(true)
39     ;
40   lines
41     .clipEdge(false)
42     .padData(true)
43     ;
44   xAxis
45     .orient('bottom')
46     .tickPadding(7)
47     .highlightZero(false)
48     ;
49   y1Axis
50     .orient('left')
51     ;
52   y2Axis
53     .orient('right')
54     ;
55
56   //============================================================
57
58
59   //============================================================
60   // Private Variables
61   //------------------------------------------------------------
62
63   var showTooltip = function(e, offsetElement) {
64       var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
65           top = e.pos[1] + ( offsetElement.offsetTop || 0),
66           x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
67           y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
68           content = tooltip(e.series.key, x, y, e, chart);
69
70       nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
71     }
72     ;
73
74   //------------------------------------------------------------
75
76
77
78   function chart(selection) {
79     selection.each(function(data) {
80       var container = d3.select(this),
81           that = this;
82
83       var availableWidth = (width  || parseInt(container.style('width')) || 960)
84                              - margin.left - margin.right,
85           availableHeight = (height || parseInt(container.style('height')) || 400)
86                              - margin.top - margin.bottom;
87
88       chart.update = function() { container.transition().call(chart); };
89       // chart.container = this;
90
91       //set state.disabled
92       state.disabled = data.map(function(d) { return !!d.disabled });
93
94       if (!defaultState) {
95         var key;
96         defaultState = {};
97         for (key in state) {
98           if (state[key] instanceof Array)
99             defaultState[key] = state[key].slice(0);
100           else
101             defaultState[key] = state[key];
102         }
103       }
104
105       //------------------------------------------------------------
106       // Display No Data message if there's nothing to show.
107
108       if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
109         var noDataText = container.selectAll('.nv-noData').data([noData]);
110
111         noDataText.enter().append('text')
112           .attr('class', 'nvd3 nv-noData')
113           .attr('dy', '-.7em')
114           .style('text-anchor', 'middle');
115
116         noDataText
117           .attr('x', margin.left + availableWidth / 2)
118           .attr('y', margin.top + availableHeight / 2)
119           .text(function(d) { return d });
120
121         return chart;
122       } else {
123         container.selectAll('.nv-noData').remove();
124       }
125
126       //------------------------------------------------------------
127
128
129       //------------------------------------------------------------
130       // Setup Scales
131
132       var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
133       var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
134
135       //x = xAxis.scale();
136        x = dataLines.filter(function(d) { return !d.disabled; }).length && dataLines.filter(function(d) { return !d.disabled; })[0].values.length ? lines.xScale() : bars.xScale();
137       //x = dataLines.filter(function(d) { return !d.disabled; }).length ? lines.xScale() : bars.xScale(); //old code before change above
138       y1 = bars.yScale();
139       y2 = lines.yScale();
140
141       //------------------------------------------------------------
142
143       //------------------------------------------------------------
144       // Setup containers and skeleton of chart
145
146       var wrap = d3.select(this).selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
147       var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
148       var g = wrap.select('g');
149
150       gEnter.append('g').attr('class', 'nv-x nv-axis');
151       gEnter.append('g').attr('class', 'nv-y1 nv-axis');
152       gEnter.append('g').attr('class', 'nv-y2 nv-axis');
153       gEnter.append('g').attr('class', 'nv-barsWrap');
154       gEnter.append('g').attr('class', 'nv-linesWrap');
155       gEnter.append('g').attr('class', 'nv-legendWrap');
156
157       //------------------------------------------------------------
158
159
160       //------------------------------------------------------------
161       // Legend
162
163       if (showLegend) {
164         legend.width( availableWidth / 2 );
165
166         g.select('.nv-legendWrap')
167             .datum(data.map(function(series) {
168               series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
169               series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');
170               return series;
171             }))
172           .call(legend);
173
174         if ( margin.top != legend.height()) {
175           margin.top = legend.height();
176           availableHeight = (height || parseInt(container.style('height')) || 400)
177                              - margin.top - margin.bottom;
178         }
179
180         g.select('.nv-legendWrap')
181             .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');
182       }
183
184       //------------------------------------------------------------
185
186
187       wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
188
189
190       //------------------------------------------------------------
191       // Main Chart Component(s)
192
193
194       lines
195         .width(availableWidth)
196         .height(availableHeight)
197         .color(data.map(function(d,i) {
198           return d.color || color(d, i);
199         }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }))
200
201       bars
202         .width(availableWidth)
203         .height(availableHeight)
204         .color(data.map(function(d,i) {
205           return d.color || color(d, i);
206         }).filter(function(d,i) { return !data[i].disabled && data[i].bar }))
207
208
209
210       var barsWrap = g.select('.nv-barsWrap')
211           .datum(dataBars.length ? dataBars : [{values:[]}])
212
213       var linesWrap = g.select('.nv-linesWrap')
214           .datum(dataLines[0] && !dataLines[0].disabled ? dataLines : [{values:[]}] );
215           //.datum(!dataLines[0].disabled ? dataLines : [{values:dataLines[0].values.map(function(d) { return [d[0], null] }) }] );
216
217       d3.transition(barsWrap).call(bars);
218       d3.transition(linesWrap).call(lines);
219
220       //------------------------------------------------------------
221
222
223       //------------------------------------------------------------
224       // Setup Axes
225
226       xAxis
227         .scale(x)
228         .ticks( availableWidth / 100 )
229         .tickSize(-availableHeight, 0);
230
231       g.select('.nv-x.nv-axis')
232           .attr('transform', 'translate(0,' + y1.range()[0] + ')');
233       d3.transition(g.select('.nv-x.nv-axis'))
234           .call(xAxis);
235
236
237       y1Axis
238         .scale(y1)
239         .ticks( availableHeight / 36 )
240         .tickSize(-availableWidth, 0);
241
242       d3.transition(g.select('.nv-y1.nv-axis'))
243           .style('opacity', dataBars.length ? 1 : 0)
244           .call(y1Axis);
245
246
247       y2Axis
248         .scale(y2)
249         .ticks( availableHeight / 36 )
250         .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
251
252       g.select('.nv-y2.nv-axis')
253           .style('opacity', dataLines.length ? 1 : 0)
254           .attr('transform', 'translate(' + availableWidth + ',0)');
255           //.attr('transform', 'translate(' + x.range()[1] + ',0)');
256
257       d3.transition(g.select('.nv-y2.nv-axis'))
258           .call(y2Axis);
259
260       //------------------------------------------------------------
261
262
263       //============================================================
264       // Event Handling/Dispatching (in chart's scope)
265       //------------------------------------------------------------
266
267       legend.dispatch.on('stateChange', function(newState) { 
268         state = newState;
269         dispatch.stateChange(state);
270         chart.update();
271       });
272
273       dispatch.on('tooltipShow', function(e) {
274         if (tooltips) showTooltip(e, that.parentNode);
275       });
276
277
278       // Update chart from a state object passed to event handler
279       dispatch.on('changeState', function(e) {
280
281         if (typeof e.disabled !== 'undefined') {
282           data.forEach(function(series,i) {
283             series.disabled = e.disabled[i];
284           });
285
286           state.disabled = e.disabled;
287         }
288
289         chart.update();
290       });
291
292       //============================================================
293
294
295     });
296
297     return chart;
298   }
299
300
301   //============================================================
302   // Event Handling/Dispatching (out of chart's scope)
303   //------------------------------------------------------------
304
305   lines.dispatch.on('elementMouseover.tooltip', function(e) {
306     e.pos = [e.pos[0] +  margin.left, e.pos[1] + margin.top];
307     dispatch.tooltipShow(e);
308   });
309
310   lines.dispatch.on('elementMouseout.tooltip', function(e) {
311     dispatch.tooltipHide(e);
312   });
313
314   bars.dispatch.on('elementMouseover.tooltip', function(e) {
315     e.pos = [e.pos[0] +  margin.left, e.pos[1] + margin.top];
316     dispatch.tooltipShow(e);
317   });
318
319   bars.dispatch.on('elementMouseout.tooltip', function(e) {
320     dispatch.tooltipHide(e);
321   });
322
323   dispatch.on('tooltipHide', function() {
324     if (tooltips) nv.tooltip.cleanup();
325   });
326
327   //============================================================
328
329
330   //============================================================
331   // Expose Public Variables
332   //------------------------------------------------------------
333
334   // expose chart's sub-components
335   chart.dispatch = dispatch;
336   chart.legend = legend;
337   chart.lines = lines;
338   chart.bars = bars;
339   chart.xAxis = xAxis;
340   chart.y1Axis = y1Axis;
341   chart.y2Axis = y2Axis;
342
343   d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');
344   //TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.
345   //d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
346
347   chart.options = nv.utils.optionsFunc.bind(chart);
348   
349   chart.x = function(_) {
350     if (!arguments.length) return getX;
351     getX = _;
352     lines.x(_);
353     bars.x(_);
354     return chart;
355   };
356
357   chart.y = function(_) {
358     if (!arguments.length) return getY;
359     getY = _;
360     lines.y(_);
361     bars.y(_);
362     return chart;
363   };
364
365   chart.margin = function(_) {
366     if (!arguments.length) return margin;
367     margin.top    = typeof _.top    != 'undefined' ? _.top    : margin.top;
368     margin.right  = typeof _.right  != 'undefined' ? _.right  : margin.right;
369     margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
370     margin.left   = typeof _.left   != 'undefined' ? _.left   : margin.left;
371     return chart;
372   };
373
374   chart.width = function(_) {
375     if (!arguments.length) return width;
376     width = _;
377     return chart;
378   };
379
380   chart.height = function(_) {
381     if (!arguments.length) return height;
382     height = _;
383     return chart;
384   };
385
386   chart.color = function(_) {
387     if (!arguments.length) return color;
388     color = nv.utils.getColor(_);
389     legend.color(color);
390     return chart;
391   };
392
393   chart.showLegend = function(_) {
394     if (!arguments.length) return showLegend;
395     showLegend = _;
396     return chart;
397   };
398
399   chart.tooltips = function(_) {
400     if (!arguments.length) return tooltips;
401     tooltips = _;
402     return chart;
403   };
404
405   chart.tooltipContent = function(_) {
406     if (!arguments.length) return tooltip;
407     tooltip = _;
408     return chart;
409   };
410
411   chart.state = function(_) {
412     if (!arguments.length) return state;
413     state = _;
414     return chart;
415   };
416
417   chart.defaultState = function(_) {
418     if (!arguments.length) return defaultState;
419     defaultState = _;
420     return chart;
421   };
422
423   chart.noData = function(_) {
424     if (!arguments.length) return noData;
425     noData = _;
426     return chart;
427   };
428
429   //============================================================
430
431
432   return chart;
433 }