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