chartx 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.gitignore +17 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +145 -0
  6. data/Rakefile +1 -0
  7. data/chartx.gemspec +40 -0
  8. data/lib/chartx/engine.rb +11 -0
  9. data/lib/chartx/helper.rb +184 -0
  10. data/lib/chartx/version.rb +3 -0
  11. data/lib/chartx.rb +3 -0
  12. data/screenshots/barchart.png +0 -0
  13. data/screenshots/bulletchart.png +0 -0
  14. data/screenshots/horizontalbarchart.png +0 -0
  15. data/screenshots/linechart.png +0 -0
  16. data/screenshots/linewithfocuschart.png +0 -0
  17. data/screenshots/multibarchart2.png +0 -0
  18. data/screenshots/piechart.png +0 -0
  19. data/screenshots/scatterchart.png +0 -0
  20. data/screenshots/stackedareachart.png +0 -0
  21. data/screenshots/stackedareachart3.png +0 -0
  22. data/vendor/assets/javascripts/chartx-core.js +9 -0
  23. data/vendor/assets/javascripts/chartx-models.js +2 -0
  24. data/vendor/assets/javascripts/nvd3/.gitignore +27 -0
  25. data/vendor/assets/javascripts/nvd3/.jshintrc +3 -0
  26. data/vendor/assets/javascripts/nvd3/LICENSE.md +49 -0
  27. data/vendor/assets/javascripts/nvd3/README.md +1 -0
  28. data/vendor/assets/javascripts/nvd3/lib/cie.js +155 -0
  29. data/vendor/assets/javascripts/nvd3/lib/crossfilter.js +1180 -0
  30. data/vendor/assets/javascripts/nvd3/lib/crossfilter.min.js +1 -0
  31. data/vendor/assets/javascripts/nvd3/lib/d3.js +8798 -0
  32. data/vendor/assets/javascripts/nvd3/lib/d3.min.js +5 -0
  33. data/vendor/assets/javascripts/nvd3/lib/fisheye.js +86 -0
  34. data/vendor/assets/javascripts/nvd3/lib/hive.js +80 -0
  35. data/vendor/assets/javascripts/nvd3/lib/horizon.js +192 -0
  36. data/vendor/assets/javascripts/nvd3/lib/sankey.js +292 -0
  37. data/vendor/assets/javascripts/nvd3/nv.d3.js +13048 -0
  38. data/vendor/assets/javascripts/nvd3/nv.d3.min.js +6 -0
  39. data/vendor/assets/javascripts/nvd3/src/core.js +118 -0
  40. data/vendor/assets/javascripts/nvd3/src/intro.js +1 -0
  41. data/vendor/assets/javascripts/nvd3/src/models/axis.js +398 -0
  42. data/vendor/assets/javascripts/nvd3/src/models/boilerplate.js +102 -0
  43. data/vendor/assets/javascripts/nvd3/src/models/bullet.js +377 -0
  44. data/vendor/assets/javascripts/nvd3/src/models/bulletChart.js +341 -0
  45. data/vendor/assets/javascripts/nvd3/src/models/cumulativeLineChart.js +685 -0
  46. data/vendor/assets/javascripts/nvd3/src/models/discreteBar.js +327 -0
  47. data/vendor/assets/javascripts/nvd3/src/models/discreteBarChart.js +290 -0
  48. data/vendor/assets/javascripts/nvd3/src/models/distribution.js +146 -0
  49. data/vendor/assets/javascripts/nvd3/src/models/historicalBar.js +289 -0
  50. data/vendor/assets/javascripts/nvd3/src/models/historicalBarChart.js +421 -0
  51. data/vendor/assets/javascripts/nvd3/src/models/indentedTree.js +317 -0
  52. data/vendor/assets/javascripts/nvd3/src/models/legend.js +207 -0
  53. data/vendor/assets/javascripts/nvd3/src/models/line.js +284 -0
  54. data/vendor/assets/javascripts/nvd3/src/models/lineChart.js +421 -0
  55. data/vendor/assets/javascripts/nvd3/src/models/linePlusBarChart.js +455 -0
  56. data/vendor/assets/javascripts/nvd3/src/models/linePlusBarWithFocusChart.js +665 -0
  57. data/vendor/assets/javascripts/nvd3/src/models/lineWithFisheye.js +197 -0
  58. data/vendor/assets/javascripts/nvd3/src/models/lineWithFisheyeChart.js +319 -0
  59. data/vendor/assets/javascripts/nvd3/src/models/lineWithFocusChart.js +560 -0
  60. data/vendor/assets/javascripts/nvd3/src/models/multiBar.js +442 -0
  61. data/vendor/assets/javascripts/nvd3/src/models/multiBarChart.js +506 -0
  62. data/vendor/assets/javascripts/nvd3/src/models/multiBarHorizontal.js +420 -0
  63. data/vendor/assets/javascripts/nvd3/src/models/multiBarHorizontalChart.js +448 -0
  64. data/vendor/assets/javascripts/nvd3/src/models/multiBarTimeSeries.js +371 -0
  65. data/vendor/assets/javascripts/nvd3/src/models/multiBarTimeSeriesChart.js +403 -0
  66. data/vendor/assets/javascripts/nvd3/src/models/multiChart.js +444 -0
  67. data/vendor/assets/javascripts/nvd3/src/models/ohlcBar.js +365 -0
  68. data/vendor/assets/javascripts/nvd3/src/models/parallelCoordinates.js +238 -0
  69. data/vendor/assets/javascripts/nvd3/src/models/pie.js +386 -0
  70. data/vendor/assets/javascripts/nvd3/src/models/pieChart.js +302 -0
  71. data/vendor/assets/javascripts/nvd3/src/models/scatter.js +660 -0
  72. data/vendor/assets/javascripts/nvd3/src/models/scatterChart.js +614 -0
  73. data/vendor/assets/javascripts/nvd3/src/models/scatterPlusLineChart.js +610 -0
  74. data/vendor/assets/javascripts/nvd3/src/models/sparkline.js +179 -0
  75. data/vendor/assets/javascripts/nvd3/src/models/sparklinePlus.js +293 -0
  76. data/vendor/assets/javascripts/nvd3/src/models/stackedArea.js +336 -0
  77. data/vendor/assets/javascripts/nvd3/src/models/stackedAreaChart.js +490 -0
  78. data/vendor/assets/javascripts/nvd3/src/nv.d3.css +704 -0
  79. data/vendor/assets/javascripts/nvd3/src/outro.js +1 -0
  80. data/vendor/assets/javascripts/nvd3/src/tooltip.js +133 -0
  81. data/vendor/assets/javascripts/nvd3/src/utils.js +118 -0
  82. data/vendor/assets/javascripts/set-env.js.erb +1 -0
  83. data/vendor/assets/stylesheets/chartx.css +3 -0
  84. metadata +189 -0
@@ -0,0 +1,317 @@
1
+ nv.models.indentedTree = function() {
2
+
3
+ //============================================================
4
+ // Public Variables with Default Settings
5
+ //------------------------------------------------------------
6
+
7
+ var margin = {top: 0, right: 0, bottom: 0, left: 0} //TODO: implement, maybe as margin on the containing div
8
+ , width = 960
9
+ , height = 500
10
+ , color = nv.utils.defaultColor()
11
+ , id = Math.floor(Math.random() * 10000)
12
+ , header = true
13
+ , filterZero = false
14
+ , noData = "No Data Available."
15
+ , childIndent = 20
16
+ , columns = [{key:'key', label: 'Name', type:'text'}] //TODO: consider functions like chart.addColumn, chart.removeColumn, instead of a block like this
17
+ , tableClass = null
18
+ , iconOpen = 'images/grey-plus.png' //TODO: consider removing this and replacing with a '+' or '-' unless user defines images
19
+ , iconClose = 'images/grey-minus.png'
20
+ , dispatch = d3.dispatch('elementClick', 'elementDblclick', 'elementMouseover', 'elementMouseout')
21
+ ;
22
+
23
+ //============================================================
24
+
25
+ var idx = 0;
26
+
27
+ function chart(selection) {
28
+ selection.each(function(data) {
29
+ var depth = 1,
30
+ container = d3.select(this);
31
+
32
+ var tree = d3.layout.tree()
33
+ .children(function(d) { return d.values })
34
+ .size([height, childIndent]); //Not sure if this is needed now that the result is HTML
35
+
36
+ chart.update = function() { container.transition().duration(600).call(chart) };
37
+
38
+
39
+ //------------------------------------------------------------
40
+ // Display No Data message if there's nothing to show.
41
+ if (!data[0]) data[0] = {key: noData};
42
+
43
+ //------------------------------------------------------------
44
+
45
+
46
+ var nodes = tree.nodes(data[0]);
47
+
48
+ // nodes.map(function(d) {
49
+ // d.id = i++;
50
+ // })
51
+
52
+ //------------------------------------------------------------
53
+ // Setup containers and skeleton of chart
54
+
55
+ var wrap = d3.select(this).selectAll('div').data([[nodes]]);
56
+ var wrapEnter = wrap.enter().append('div').attr('class', 'nvd3 nv-wrap nv-indentedtree');
57
+ var tableEnter = wrapEnter.append('table');
58
+ var table = wrap.select('table').attr('width', '100%').attr('class', tableClass);
59
+
60
+ //------------------------------------------------------------
61
+
62
+
63
+ if (header) {
64
+ var thead = tableEnter.append('thead');
65
+
66
+ var theadRow1 = thead.append('tr');
67
+
68
+ columns.forEach(function(column) {
69
+ theadRow1
70
+ .append('th')
71
+ .attr('width', column.width ? column.width : '10%')
72
+ .style('text-align', column.type == 'numeric' ? 'right' : 'left')
73
+ .append('span')
74
+ .text(column.label);
75
+ });
76
+ }
77
+
78
+
79
+ var tbody = table.selectAll('tbody')
80
+ .data(function(d) { return d });
81
+ tbody.enter().append('tbody');
82
+
83
+
84
+
85
+ //compute max generations
86
+ depth = d3.max(nodes, function(node) { return node.depth });
87
+ tree.size([height, depth * childIndent]); //TODO: see if this is necessary at all
88
+
89
+
90
+ // Update the nodes…
91
+ var node = tbody.selectAll('tr')
92
+ // .data(function(d) { return d; }, function(d) { return d.id || (d.id == ++i)});
93
+ .data(function(d) { return d.filter(function(d) { return (filterZero && !d.children) ? filterZero(d) : true; } )}, function(d,i) { return d.id || (d.id || ++idx)});
94
+ //.style('display', 'table-row'); //TODO: see if this does anything
95
+
96
+ node.exit().remove();
97
+
98
+ node.select('img.nv-treeicon')
99
+ .attr('src', icon)
100
+ .classed('folded', folded);
101
+
102
+ var nodeEnter = node.enter().append('tr');
103
+
104
+
105
+ columns.forEach(function(column, index) {
106
+
107
+ var nodeName = nodeEnter.append('td')
108
+ .style('padding-left', function(d) { return (index ? 0 : d.depth * childIndent + 12 + (icon(d) ? 0 : 16)) + 'px' }, 'important') //TODO: check why I did the ternary here
109
+ .style('text-align', column.type == 'numeric' ? 'right' : 'left');
110
+
111
+
112
+ if (index == 0) {
113
+ nodeName.append('img')
114
+ .classed('nv-treeicon', true)
115
+ .classed('nv-folded', folded)
116
+ .attr('src', icon)
117
+ .style('width', '14px')
118
+ .style('height', '14px')
119
+ .style('padding', '0 1px')
120
+ .style('display', function(d) { return icon(d) ? 'inline-block' : 'none'; })
121
+ .on('click', click);
122
+ }
123
+
124
+
125
+ nodeName.append('span')
126
+ .attr('class', d3.functor(column.classes) )
127
+ .text(function(d) { return column.format ? column.format(d) :
128
+ (d[column.key] || '-') });
129
+
130
+ if (column.showCount) {
131
+ nodeName.append('span')
132
+ .attr('class', 'nv-childrenCount');
133
+
134
+ node.selectAll('span.nv-childrenCount').text(function(d) {
135
+ return ((d.values && d.values.length) || (d._values && d._values.length)) ? //If this is a parent
136
+ '(' + ((d.values && (d.values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length)) //If children are in values check its children and filter
137
+ || (d._values && d._values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length) //Otherwise, do the same, but with the other name, _values...
138
+ || 0) + ')' //This is the catch-all in case there are no children after a filter
139
+ : '' //If this is not a parent, just give an empty string
140
+ });
141
+ }
142
+
143
+ if (column.click)
144
+ nodeName.select('span').on('click', column.click);
145
+
146
+ });
147
+
148
+ node
149
+ .order()
150
+ .on('click', function(d) {
151
+ dispatch.elementClick({
152
+ row: this, //TODO: decide whether or not this should be consistent with scatter/line events or should be an html link (a href)
153
+ data: d,
154
+ pos: [d.x, d.y]
155
+ });
156
+ })
157
+ .on('dblclick', function(d) {
158
+ dispatch.elementDblclick({
159
+ row: this,
160
+ data: d,
161
+ pos: [d.x, d.y]
162
+ });
163
+ })
164
+ .on('mouseover', function(d) {
165
+ dispatch.elementMouseover({
166
+ row: this,
167
+ data: d,
168
+ pos: [d.x, d.y]
169
+ });
170
+ })
171
+ .on('mouseout', function(d) {
172
+ dispatch.elementMouseout({
173
+ row: this,
174
+ data: d,
175
+ pos: [d.x, d.y]
176
+ });
177
+ });
178
+
179
+
180
+
181
+
182
+ // Toggle children on click.
183
+ function click(d, _, unshift) {
184
+ d3.event.stopPropagation();
185
+
186
+ if(d3.event.shiftKey && !unshift) {
187
+ //If you shift-click, it'll toggle fold all the children, instead of itself
188
+ d3.event.shiftKey = false;
189
+ d.values && d.values.forEach(function(node){
190
+ if (node.values || node._values) {
191
+ click(node, 0, true);
192
+ }
193
+ });
194
+ return true;
195
+ }
196
+ if(!hasChildren(d)) {
197
+ //download file
198
+ //window.location.href = d.url;
199
+ return true;
200
+ }
201
+ if (d.values) {
202
+ d._values = d.values;
203
+ d.values = null;
204
+ } else {
205
+ d.values = d._values;
206
+ d._values = null;
207
+ }
208
+ chart.update();
209
+ }
210
+
211
+
212
+ function icon(d) {
213
+ return (d._values && d._values.length) ? iconOpen : (d.values && d.values.length) ? iconClose : '';
214
+ }
215
+
216
+ function folded(d) {
217
+ return (d._values && d._values.length);
218
+ }
219
+
220
+ function hasChildren(d) {
221
+ var values = d.values || d._values;
222
+
223
+ return (values && values.length);
224
+ }
225
+
226
+
227
+ });
228
+
229
+ return chart;
230
+ }
231
+
232
+
233
+ //============================================================
234
+ // Expose Public Variables
235
+ //------------------------------------------------------------
236
+
237
+ chart.margin = function(_) {
238
+ if (!arguments.length) return margin;
239
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
240
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
241
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
242
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
243
+ return chart;
244
+ };
245
+
246
+ chart.width = function(_) {
247
+ if (!arguments.length) return width;
248
+ width = _;
249
+ return chart;
250
+ };
251
+
252
+ chart.height = function(_) {
253
+ if (!arguments.length) return height;
254
+ height = _;
255
+ return chart;
256
+ };
257
+
258
+ chart.color = function(_) {
259
+ if (!arguments.length) return color;
260
+ color = nv.utils.getColor(_);
261
+ scatter.color(color);
262
+ return chart;
263
+ };
264
+
265
+ chart.id = function(_) {
266
+ if (!arguments.length) return id;
267
+ id = _;
268
+ return chart;
269
+ };
270
+
271
+ chart.header = function(_) {
272
+ if (!arguments.length) return header;
273
+ header = _;
274
+ return chart;
275
+ };
276
+
277
+ chart.noData = function(_) {
278
+ if (!arguments.length) return noData;
279
+ noData = _;
280
+ return chart;
281
+ };
282
+
283
+ chart.filterZero = function(_) {
284
+ if (!arguments.length) return filterZero;
285
+ filterZero = _;
286
+ return chart;
287
+ };
288
+
289
+ chart.columns = function(_) {
290
+ if (!arguments.length) return columns;
291
+ columns = _;
292
+ return chart;
293
+ };
294
+
295
+ chart.tableClass = function(_) {
296
+ if (!arguments.length) return tableClass;
297
+ tableClass = _;
298
+ return chart;
299
+ };
300
+
301
+ chart.iconOpen = function(_){
302
+ if (!arguments.length) return iconOpen;
303
+ iconOpen = _;
304
+ return chart;
305
+ }
306
+
307
+ chart.iconClose = function(_){
308
+ if (!arguments.length) return iconClose;
309
+ iconClose = _;
310
+ return chart;
311
+ }
312
+
313
+ //============================================================
314
+
315
+
316
+ return chart;
317
+ };
@@ -0,0 +1,207 @@
1
+ nv.models.legend = function() {
2
+
3
+ //============================================================
4
+ // Public Variables with Default Settings
5
+ //------------------------------------------------------------
6
+
7
+ var margin = {top: 5, right: 0, bottom: 5, left: 0}
8
+ , width = 400
9
+ , height = 20
10
+ , getKey = function(d) { return d.key }
11
+ , color = nv.utils.defaultColor()
12
+ , align = true
13
+ , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout')
14
+ ;
15
+
16
+ //============================================================
17
+
18
+
19
+ function chart(selection) {
20
+ selection.each(function(data) {
21
+ var availableWidth = width - margin.left - margin.right,
22
+ container = d3.select(this);
23
+
24
+
25
+ //------------------------------------------------------------
26
+ // Setup containers and skeleton of chart
27
+
28
+ var wrap = container.selectAll('g.nv-legend').data([data]);
29
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');
30
+ var g = wrap.select('g');
31
+
32
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
33
+
34
+ //------------------------------------------------------------
35
+
36
+
37
+ var series = g.selectAll('.nv-series')
38
+ .data(function(d) { return d });
39
+ var seriesEnter = series.enter().append('g').attr('class', 'nv-series')
40
+ .on('mouseover', function(d,i) {
41
+ dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects
42
+ })
43
+ .on('mouseout', function(d,i) {
44
+ dispatch.legendMouseout(d,i);
45
+ })
46
+ .on('click', function(d,i) {
47
+ dispatch.legendClick(d,i);
48
+ })
49
+ .on('dblclick', function(d,i) {
50
+ dispatch.legendDblclick(d,i);
51
+ });
52
+ seriesEnter.append('circle')
53
+ .style('stroke-width', 2)
54
+ .attr('r', 5);
55
+ seriesEnter.append('text')
56
+ .attr('text-anchor', 'start')
57
+ .attr('dy', '.32em')
58
+ .attr('dx', '8');
59
+ series.classed('disabled', function(d) { return d.disabled });
60
+ series.exit().remove();
61
+ series.select('circle')
62
+ .style('fill', function(d,i) { return d.color || color(d,i)})
63
+ .style('stroke', function(d,i) { return d.color || color(d, i) });
64
+ series.select('text').text(getKey);
65
+
66
+
67
+ //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
68
+
69
+ // NEW ALIGNING CODE, TODO: clean up
70
+ if (align) {
71
+
72
+ var seriesWidths = [];
73
+ series.each(function(d,i) {
74
+ var legendText = d3.select(this).select('text');
75
+ var svgComputedTextLength = legendText.node().getComputedTextLength()
76
+ || nv.utils.calcApproxTextWidth(legendText);
77
+ seriesWidths.push(svgComputedTextLength + 28); // 28 is ~ the width of the circle plus some padding
78
+ });
79
+
80
+ //nv.log('Series Widths: ', JSON.stringify(seriesWidths));
81
+
82
+ var seriesPerRow = 0;
83
+ var legendWidth = 0;
84
+ var columnWidths = [];
85
+
86
+ while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {
87
+ columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];
88
+ legendWidth += seriesWidths[seriesPerRow++];
89
+ }
90
+
91
+
92
+ while ( legendWidth > availableWidth && seriesPerRow > 1 ) {
93
+ columnWidths = [];
94
+ seriesPerRow--;
95
+
96
+ for (k = 0; k < seriesWidths.length; k++) {
97
+ if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )
98
+ columnWidths[k % seriesPerRow] = seriesWidths[k];
99
+ }
100
+
101
+ legendWidth = columnWidths.reduce(function(prev, cur, index, array) {
102
+ return prev + cur;
103
+ });
104
+ }
105
+ //console.log(columnWidths, legendWidth, seriesPerRow);
106
+
107
+ var xPositions = [];
108
+ for (var i = 0, curX = 0; i < seriesPerRow; i++) {
109
+ xPositions[i] = curX;
110
+ curX += columnWidths[i];
111
+ }
112
+
113
+ series
114
+ .attr('transform', function(d, i) {
115
+ return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * 20) + ')';
116
+ });
117
+
118
+ //position legend as far right as possible within the total width
119
+ g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');
120
+
121
+ height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * 20);
122
+
123
+ } else {
124
+
125
+ var ypos = 5,
126
+ newxpos = 5,
127
+ maxwidth = 0,
128
+ xpos;
129
+ series
130
+ .attr('transform', function(d, i) {
131
+ var length = d3.select(this).select('text').node().getComputedTextLength() + 28;
132
+ xpos = newxpos;
133
+
134
+ if (width < margin.left + margin.right + xpos + length) {
135
+ newxpos = xpos = 5;
136
+ ypos += 20;
137
+ }
138
+
139
+ newxpos += length;
140
+ if (newxpos > maxwidth) maxwidth = newxpos;
141
+
142
+ return 'translate(' + xpos + ',' + ypos + ')';
143
+ });
144
+
145
+ //position legend as far right as possible within the total width
146
+ g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');
147
+
148
+ height = margin.top + margin.bottom + ypos + 15;
149
+
150
+ }
151
+
152
+ });
153
+
154
+ return chart;
155
+ }
156
+
157
+
158
+ //============================================================
159
+ // Expose Public Variables
160
+ //------------------------------------------------------------
161
+
162
+ chart.dispatch = dispatch;
163
+
164
+ chart.margin = function(_) {
165
+ if (!arguments.length) return margin;
166
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
167
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
168
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
169
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
170
+ return chart;
171
+ };
172
+
173
+ chart.width = function(_) {
174
+ if (!arguments.length) return width;
175
+ width = _;
176
+ return chart;
177
+ };
178
+
179
+ chart.height = function(_) {
180
+ if (!arguments.length) return height;
181
+ height = _;
182
+ return chart;
183
+ };
184
+
185
+ chart.key = function(_) {
186
+ if (!arguments.length) return getKey;
187
+ getKey = _;
188
+ return chart;
189
+ };
190
+
191
+ chart.color = function(_) {
192
+ if (!arguments.length) return color;
193
+ color = nv.utils.getColor(_);
194
+ return chart;
195
+ };
196
+
197
+ chart.align = function(_) {
198
+ if (!arguments.length) return align;
199
+ align = _;
200
+ return chart;
201
+ };
202
+
203
+ //============================================================
204
+
205
+
206
+ return chart;
207
+ }