|
1 | 1 | <link rel="import" href="../polymer/polymer.html"> |
2 | 2 | <link rel="import" href="../iron-ajax/iron-request.html"> |
3 | 3 | <link rel="import" href="../promise-polyfill/promise-polyfill-lite.html"> |
4 | | -<script type="text/javascript" src="https://www.google.com/jsapi"></script> |
| 4 | +<script type="text/javascript" xsrc="https://www.google.com/jsapi"></script> |
| 5 | +<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> |
5 | 6 |
|
6 | 7 | <!-- |
7 | 8 | `google-chart` encapsulates Google Charts as a web component, allowing you to easily visualize |
8 | 9 | data. From simple line charts to complex hierarchical tree maps, the chart element provides a |
9 | 10 | number of ready-to-use chart types. |
10 | 11 |
|
11 | 12 | <google-chart |
12 | | - type='pie' |
| 13 | + type="pie" |
13 | 14 | options='{"title": "Distribution of days in 2001Q1"}' |
14 | 15 | cols='[{"label":"Month", "type":"string"}, {"label":"Days", "type":"number"}]' |
15 | 16 | rows='[["Jan", 31],["Feb", 28],["Mar", 31]]'> |
|
51 | 52 | <link rel="import" type="css" href="google-chart.css"> |
52 | 53 | <template> |
53 | 54 | <iron-request id="xhr"></iron-request> |
54 | | - <div id="chartdiv"></div> |
| 55 | + <div id="chart"></div> |
| 56 | + <div id="error"></div> |
55 | 57 | </template> |
56 | 58 | </dom-module> |
57 | 59 |
|
58 | 60 | <script> |
59 | 61 | (function() { |
60 | 62 | "use strict"; |
61 | 63 |
|
62 | | - // Most charts use this package. |
63 | | - var DEFACTO_CHART_PACKAGE = 'corechart'; |
64 | | - |
65 | | - // Loads a chart package and then calls the callback. |
66 | | - var chartConstructor = function(callback, opt_pkg) { |
67 | | - return function(chartElement) { |
68 | | - return getChartPackage(opt_pkg).then(callback).then(function(ctor) { |
69 | | - return new ctor(chartElement); |
70 | | - }); |
71 | | - }; |
72 | | - }; |
73 | | - |
74 | 64 | // A collection of chart types associated with a function that returns a |
75 | 65 | // Promise for the chart type's constructor. |
76 | | - var CHART_CONSTRUCTORS = { |
77 | | - 'area': chartConstructor(function(pkg) { |
78 | | - return pkg.AreaChart; |
79 | | - }), |
80 | | - 'bar': chartConstructor(function(pkg) { |
81 | | - return pkg.BarChart; |
82 | | - }), |
83 | | - 'bubble': chartConstructor(function(pkg) { |
84 | | - return pkg.BubbleChart; |
85 | | - }), |
86 | | - 'candlestick': chartConstructor(function(pkg) { |
87 | | - return pkg.CandlestickChart; |
88 | | - }), |
89 | | - 'column': chartConstructor(function(pkg) { |
90 | | - return pkg.ColumnChart; |
91 | | - }), |
92 | | - 'combo': chartConstructor(function(pkg) { |
93 | | - return pkg.ComboChart; |
94 | | - }), |
95 | | - 'geo': chartConstructor(function(pkg) { |
96 | | - return pkg.GeoChart; |
97 | | - }), |
98 | | - 'histogram': chartConstructor(function(pkg) { |
99 | | - return pkg.Histogram; |
100 | | - }), |
101 | | - 'line': chartConstructor(function(pkg) { |
102 | | - return pkg.LineChart; |
103 | | - }), |
104 | | - 'pie': chartConstructor(function(pkg) { |
105 | | - return pkg.PieChart; |
106 | | - }), |
107 | | - 'scatter': chartConstructor(function(pkg) { |
108 | | - return pkg.ScatterChart; |
109 | | - }), |
110 | | - 'stepped-area': chartConstructor(function(pkg) { |
111 | | - return pkg.SteppedAreaChart; |
112 | | - }), |
113 | | - 'table': chartConstructor(function(pkg) { |
114 | | - return pkg.Table; |
115 | | - }, 'table'), |
116 | | - 'timeline': chartConstructor(function(pkg) { |
117 | | - return pkg.Timeline; |
118 | | - }, 'timeline'), |
119 | | - 'gauge': chartConstructor(function(pkg) { |
120 | | - return pkg.Gauge; |
121 | | - }, 'gauge'), |
122 | | - 'treemap': chartConstructor(function(pkg) { |
123 | | - return pkg.TreeMap; |
124 | | - }, 'treemap') |
| 66 | + var CHART_TYPES = { |
| 67 | + 'area': 'AreaChart', |
| 68 | + 'bar': 'BarChart', |
| 69 | + 'bubble': 'BubbleChart', |
| 70 | + 'candlestick': 'CandlestickChart', |
| 71 | + 'column': 'ColumnChart', |
| 72 | + 'combo': 'ComboChart', |
| 73 | + 'gauge': 'Gauge', |
| 74 | + 'geo': 'GeoChart', |
| 75 | + 'histogram': 'Histogram', |
| 76 | + 'line': 'LineChart', |
| 77 | + 'pie': 'PieChart', |
| 78 | + 'scatter': 'ScatterChart', |
| 79 | + 'stepped-area': 'SteppedAreaChart', |
| 80 | + 'table': 'Table', |
| 81 | + 'timeline': 'Timeline', |
| 82 | + 'treemap': 'TreeMap', |
| 83 | + // Material Charts: |
| 84 | + 'md-bar': 'google.charts.Bar', |
| 85 | + 'md-gantt': 'google.charts.Gantt', |
| 86 | + 'md-scatter': 'google.charts.Scatter' |
125 | 87 | }; |
126 | 88 |
|
127 | | - // A cache of Package Promises so we can re-use them between charts. |
128 | | - var pkgPromises = {}; |
129 | | - |
130 | | - // Returns a Promise for a Chart package. |
131 | | - var getChartPackage = function(opt_pkg) { |
132 | | - var pkg = opt_pkg || DEFACTO_CHART_PACKAGE; |
133 | | - if (pkgPromises[pkg]) return pkgPromises[pkg]; |
134 | | - pkgPromises[pkg] = new Promise(function(resolve) { |
135 | | - google.load('visualization', '1', { |
136 | | - packages: [pkg], |
137 | | - callback: function() { |
138 | | - resolve(google.visualization); |
139 | | - } |
140 | | - }); |
| 89 | + var vizPkg = new Promise(function(resolve, reject) { |
| 90 | + google.charts.load('43', {packages: ['corechart']}); |
| 91 | + google.charts.setOnLoadCallback(function() { |
| 92 | + resolve(google.visualization); |
141 | 93 | }); |
142 | | - return pkgPromises[pkg]; |
143 | | - }; |
144 | | - |
145 | | - // Creates a chart of type on the chartElement. |
146 | | - // Returns a Promise for the new chart. |
147 | | - var createChart = function(type, chartElement) { |
148 | | - return CHART_CONSTRUCTORS[type](chartElement); |
149 | | - }; |
150 | | - |
151 | | - // We can go ahead and load the defacto package because we'll need it to do |
152 | | - // anything (e.g. creating the DataTable to render). |
153 | | - var vizPkg = getChartPackage(); |
| 94 | + return; |
| 95 | + google.load('visualization', '1.2', { |
| 96 | + callback: function() { |
| 97 | + resolve(google.visualization); |
| 98 | + } |
| 99 | + }); |
| 100 | + }); |
154 | 101 |
|
155 | 102 | Polymer({ |
156 | | - |
157 | 103 | is: 'google-chart', |
158 | 104 |
|
159 | 105 | /** |
|
162 | 108 | * @event google-chart-render |
163 | 109 | */ |
164 | 110 |
|
165 | | - /** |
166 | | - * Fired when the user makes a selection in the chart. |
167 | | - * |
168 | | - * @event google-chart-select |
169 | | - * @param {object} detail |
170 | | - * @param {array} detail.selection The user-defined selection. |
171 | | - */ |
172 | | - |
173 | 111 | properties: { |
174 | 112 | /** |
175 | 113 | * Sets the type of the chart. |
176 | 114 | * |
177 | 115 | * Should be one of: |
178 | | - * - `area`, `bar`, `bubble`, `candlestick`, `column`, `combo`, `geo`, |
179 | | - * `histogram`, `line`, `pie`, `scatter`, `stepped-area`, `treemap` |
| 116 | + * - `area`, |
| 117 | + * - `bar` |
| 118 | + * - `bubble` |
| 119 | + * - `candlestick` |
| 120 | + * - `column` |
| 121 | + * - `combo` |
| 122 | + * - `gauge` |
| 123 | + * - `geo` |
| 124 | + * - `histogram` |
| 125 | + * - `line` |
| 126 | + * - `pie` |
| 127 | + * - `scatter` |
| 128 | + * - `stepped-area` |
| 129 | + * - `table` |
| 130 | + * - `timeline` |
| 131 | + * - `treemap` |
| 132 | + * - `md-bar` |
| 133 | + * - `md-gantt` |
| 134 | + * - `md-scatter` |
180 | 135 | * |
181 | 136 | * See <a href="https://google-developers.appspot.com/chart/interactive/docs/gallery">Google Visualization API reference (Chart Gallery)</a> for details. |
182 | 137 | * |
|
206 | 161 | observer: 'drawChart' |
207 | 162 | }, |
208 | 163 |
|
209 | | - /** |
210 | | - * A Promise for the Google Visualization library. |
211 | | - * |
212 | | - * Example: |
213 | | - * <pre>myChart.pkg.then(function(viz) { |
214 | | - * // `viz` is equivalent to `google.visualization` |
215 | | - * myChart.view = new viz.DataView(myData); |
216 | | - * });</pre> |
217 | | - * |
218 | | - */ |
219 | | - pkg: { |
220 | | - type: Object, |
221 | | - value: vizPkg, |
222 | | - readOnly: true |
223 | | - }, |
224 | | - |
225 | 164 | /** |
226 | 165 | * Sets the data columns for this object. |
227 | 166 | * |
|
344 | 283 | // The current selection in the chart. |
345 | 284 | _selection: null, |
346 | 285 |
|
| 286 | + pkg: vizPkg, |
| 287 | + |
347 | 288 | // The chart type was changed. |
348 | 289 | // We need to create a new chart and redraw. |
349 | 290 | _typeChanged: function() { |
350 | | - this._chart = createChart(this.type, this.$.chartdiv) |
| 291 | + this._chart = vizPkg.then(function() { |
| 292 | + return new google.visualization.ChartWrapper({ |
| 293 | + chartType: CHART_TYPES[this.type], |
| 294 | + containerId: this.$.chart, |
| 295 | + options: this.options |
| 296 | + }); |
| 297 | + }.bind(this)) |
351 | 298 | .then(this._setupChart.bind(this)); |
352 | 299 | this.drawChart(); |
353 | 300 | }, |
|
374 | 321 | // Some charts (e.g. Gauge) do not support selection |
375 | 322 | if (chart.getSelection) { |
376 | 323 | google.visualization.events.addListener(chart, 'select', function() { |
377 | | - this.selection = this._selection = chart.getSelection(); |
| 324 | + this.selection = chart.getChart().getSelection(); |
| 325 | + this._selection = this.selection; |
378 | 326 | // This should be deprecated. |
379 | 327 | // The value for the new selection is here: |
380 | 328 | // event.detail.selection |
|
390 | 338 | return chart; |
391 | 339 | }, |
392 | 340 |
|
| 341 | + get chart() { |
| 342 | + return this._chart || Promise.reject('No chart'); |
| 343 | + }, |
| 344 | + |
| 345 | + get dataView() { |
| 346 | + return this._dataView || Promise.reject('No data'); |
| 347 | + }, |
| 348 | + |
393 | 349 | /** |
394 | 350 | * Redraws the chart. |
395 | 351 | * |
|
399 | 355 | * @method drawChart |
400 | 356 | */ |
401 | 357 | drawChart: function() { |
402 | | - if (!this._chart || !this._dataView) return; |
403 | | - this._chartDrawn = Promise.all([this._chart, this._dataView]) |
404 | | - .then(function(chartAndData) { |
405 | | - var chart = chartAndData[0]; |
406 | | - var data = chartAndData[1]; |
407 | | - google.visualization.events.addOneTimeListener(chart, 'ready', function() { |
408 | | - this.fire('google-chart-render'); |
409 | | - }.bind(this)); |
410 | | - chart.draw(data, this.options || {}); |
411 | | - return chart; |
412 | | - }.bind(this), function(error) { |
413 | | - this.$.chartdiv.innerHTML = error; |
414 | | - throw error; |
415 | | - }.bind(this)); |
416 | | - this._setSelection(); |
| 358 | + Promise.all([this.chart, this.dataView]).then(function(chartAndData) { |
| 359 | + var chart = chartAndData[0]; |
| 360 | + var data = chartAndData[1]; |
| 361 | + google.visualization.events.addOneTimeListener(chart, 'ready', function() { |
| 362 | + if (this.selection && chart.getChart().setSelection) { |
| 363 | + // Note: Some charts (e.g. TreeMap) must have a selection. |
| 364 | + chart.getChart().setSelection(this.selection); |
| 365 | + } |
| 366 | + this.fire('google-chart-render'); |
| 367 | + }.bind(this)); |
| 368 | + chart.setDataTable(data); |
| 369 | + chart.draw(); |
| 370 | + return chart; |
| 371 | + }.bind(this)) |
| 372 | + .then(function() { |
| 373 | + this.$.error.innerHTML = ''; |
| 374 | + }.bind(this), function(error) { |
| 375 | + this.$.error.innerHTML = error; |
| 376 | + }.bind(this)); |
417 | 377 | }, |
418 | 378 |
|
419 | 379 | /** |
|
424 | 384 | * @return {string} Returns image URI. |
425 | 385 | */ |
426 | 386 | getImageURI: function() { |
427 | | - return this._chartObject.getImageURI(); |
| 387 | + var chart = this._chartObject.getChart(); |
| 388 | + return chart ? chart.getImageURI() : null; |
428 | 389 | }, |
429 | 390 |
|
430 | 391 | // Handles changes to the DataView object attribute. |
|
0 commit comments