Initial OpenECOMP policy/engine commit
[policy/engine.git] / ecomp-sdk-app / src / main / webapp / static / fusion / raptor / d3 / js / models / parallelCoordinates.js
1
2 //Code adapted from Jason Davies' "Parallel Coordinates"
3 // http://bl.ocks.org/jasondavies/1341281
4
5 nv.models.parallelCoordinates = function() {
6   "use strict";
7   //============================================================
8   // Public Variables with Default Settings
9   //------------------------------------------------------------
10
11
12   var margin = {top: 30, right: 10, bottom: 10, left: 10}
13     , width = 960
14     , height = 500
15     , x = d3.scale.ordinal()
16     , y = {}
17     , dimensions = []
18     , color = nv.utils.getColor(d3.scale.category20c().range())
19     , axisLabel = function(d) { return d; }
20     , filters = []
21     , active = []
22     , dispatch = d3.dispatch('brush')
23     ;
24
25   //============================================================
26
27
28   //============================================================
29   // Private Variables
30   //------------------------------------------------------------
31
32
33   //============================================================
34
35
36   function chart(selection) {
37     selection.each(function(data) {
38       var availableWidth = width - margin.left - margin.right,
39           availableHeight = height - margin.top - margin.bottom,
40           container = d3.select(this);
41
42       active = data; //set all active before first brush call
43
44       chart.update = function() { }; //This is a placeholder until this chart is made resizeable
45
46       //------------------------------------------------------------
47       // Setup Scales
48
49       x
50         .rangePoints([0, availableWidth], 1)
51         .domain(dimensions);
52
53       // Extract the list of dimensions and create a scale for each.
54       dimensions.forEach(function(d) {
55           y[d] = d3.scale.linear()
56               .domain(d3.extent(data, function(p) { return +p[d]; }))
57               .range([availableHeight, 0]);
58
59           y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush);
60
61           return d != 'name';
62         })
63
64
65       //------------------------------------------------------------
66
67
68       //------------------------------------------------------------
69       // Setup containers and skeleton of chart
70
71       var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinates').data([data]);
72       var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinates');
73       var gEnter = wrapEnter.append('g');
74       var g = wrap.select('g')
75
76       gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap');
77
78       wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
79
80       //------------------------------------------------------------
81
82
83       var line = d3.svg.line(),
84           axis = d3.svg.axis().orient('left'),
85           background,
86           foreground;
87
88
89       // Add grey background lines for context.
90       background = gEnter.append('g')
91           .attr('class', 'background')
92         .selectAll('path')
93           .data(data)
94         .enter().append('path')
95           .attr('d', path)
96         ;
97
98       // Add blue foreground lines for focus.
99       foreground = gEnter.append('g')
100           .attr('class', 'foreground')
101         .selectAll('path')
102           .data(data)
103         .enter().append('path')
104           .attr('d', path)
105         ;
106
107       // Add a group element for each dimension.
108       var dimension = g.selectAll('.dimension')
109           .data(dimensions)
110         .enter().append('g')
111           .attr('class', 'dimension')
112           .attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; });
113
114       // Add an axis and title.
115       dimension.append('g')
116           .attr('class', 'axis')
117           .each(function(d) { d3.select(this).call(axis.scale(y[d])); })
118         .append('text')
119           .attr('text-anchor', 'middle')
120           .attr('y', -9)
121           .text(String);
122
123       // Add and store a brush for each axis.
124       dimension.append('g')
125           .attr('class', 'brush')
126           .each(function(d) { d3.select(this).call(y[d].brush); })
127         .selectAll('rect')
128           .attr('x', -8)
129           .attr('width', 16);
130
131
132       // Returns the path for a given data point.
133       function path(d) {
134         return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; }));
135       }
136
137       // Handles a brush event, toggling the display of foreground lines.
138       function brush() {
139         var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }),
140             extents = actives.map(function(p) { return y[p].brush.extent(); });
141
142         filters = []; //erase current filters
143         actives.forEach(function(d,i) {
144           filters[i] = {
145             dimension: d,
146             extent: extents[i]
147           }
148         });
149
150         active = []; //erase current active list
151         foreground.style('display', function(d) {
152           var isActive = actives.every(function(p, i) {
153             return extents[i][0] <= d[p] && d[p] <= extents[i][1];
154           });
155           if (isActive) active.push(d);
156           return isActive ? null : 'none';
157         });
158
159         dispatch.brush({
160           filters: filters,
161           active: active
162         });
163
164       }
165
166
167
168     });
169
170     return chart;
171   }
172
173
174   //============================================================
175   // Expose Public Variables
176   //------------------------------------------------------------
177
178
179   chart.dispatch = dispatch;
180   chart.options = nv.utils.optionsFunc.bind(chart);
181   
182   chart.margin = function(_) {
183     if (!arguments.length) return margin;
184     margin.top    = typeof _.top    != 'undefined' ? _.top    : margin.top;
185     margin.right  = typeof _.right  != 'undefined' ? _.right  : margin.right;
186     margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
187     margin.left   = typeof _.left   != 'undefined' ? _.left   : margin.left;
188     return chart;
189   };
190
191   chart.width = function(_) {
192     if (!arguments.length) return width;
193     width = _;
194     return chart;
195   };
196
197   chart.height = function(_) {
198     if (!arguments.length) return height;
199     height = _;
200     return chart;
201   };
202
203   chart.color = function(_) {
204     if (!arguments.length) return color;
205     color = nv.utils.getColor(_)
206     return chart;
207   };
208
209   chart.xScale = function(_) {
210     if (!arguments.length) return x;
211     x = _;
212     return chart;
213   };
214
215   chart.yScale = function(_) {
216     if (!arguments.length) return y;
217     y = _;
218     return chart;
219   };
220
221   chart.dimensions = function(_) {
222     if (!arguments.length) return dimensions;
223     dimensions = _;
224     return chart;
225   };
226
227   chart.filters = function() {
228     return filters;
229   };
230
231   chart.active = function() {
232     return active;
233   };
234
235   //============================================================
236
237
238   return chart;
239 }