| @@ -11,8 +11,18 @@ | ||
| 11 | 11 | // so that we know which charts belong to our library. |
| 12 | 12 | var rendered_charts = []; |
| 13 | 13 | |
| 14 | 14 | function renderChart(id) { |
| 15 | + var chart = all_charts[id]; | |
| 16 | + var hasAnnotation = false; | |
| 17 | + if(id !== 'canvas' && typeof chart.series !== 'undefined' && typeof chart.settings.series !== 'undefined'){ | |
| 18 | + hasAnnotation = chart.series.length - chart.settings.series.length > 1; | |
| 19 | + } | |
| 20 | + // re-render the chart only if it doesn't have annotations and it is on the front-end | |
| 21 | + // this is to prevent the chart from showing "All series on a given axis must be of the same data type" during resize. | |
| 22 | + if(hasAnnotation){ | |
| 23 | + return; | |
| 24 | + } | |
| 15 | 25 | renderSpecificChart(id, all_charts[id]); |
| 16 | 26 | } |
| 17 | 27 | |
| 18 | 28 | function renderSpecificChart(id, chart) { |
| @@ -54,8 +64,42 @@ | ||
| 54 | 64 | settings['animation']['startup'] = true; |
| 55 | 65 | settings['animation']['duration'] = parseInt(settings['animation']['duration']); |
| 56 | 66 | } |
| 57 | 67 | |
| 68 | + // mark roles for series that have specified a role | |
| 69 | + // and then remove them from future processing | |
| 70 | + // and also adjust the indices of the series array so that | |
| 71 | + // the ones with a role are ignored | |
| 72 | + // e.g. if there are 6 columns (0-5) out of which 1, 3 and 5 are annotations | |
| 73 | + // the final series will only include 0, 2, 4 (reindexed as 0, 1, 2) | |
| 74 | + if (settings.series) { | |
| 75 | + var adjusted_series = []; | |
| 76 | + for (i = 0; i < settings.series.length; i++) { | |
| 77 | + if (!series[i + 1] || typeof settings.series[i] === 'undefined') { | |
| 78 | + continue; | |
| 79 | + } | |
| 80 | + if(typeof settings.series[i].role !== 'undefined'){ | |
| 81 | + table.setColumnProperty(i + 1, 'role', settings.series[i].role); | |
| 82 | + if(settings.series[i].role === '') { | |
| 83 | + adjusted_series.push(settings.series[i]); | |
| 84 | + } | |
| 85 | + } | |
| 86 | + } | |
| 87 | + if(adjusted_series.length > 0){ | |
| 88 | + settings.series = adjusted_series; | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + if ( settings['explorer_enabled'] && settings['explorer_enabled'] == 'true' ) { // jshint ignore:line | |
| 93 | + var $explorer = {}; | |
| 94 | + $explorer['keepInBounds'] = true; | |
| 95 | + | |
| 96 | + if ( settings['explorer_actions'] ) { | |
| 97 | + $explorer['actions'] = settings['explorer_actions']; | |
| 98 | + } | |
| 99 | + settings['explorer'] = $explorer; | |
| 100 | + } | |
| 101 | + | |
| 58 | 102 | switch (chart.type) { |
| 59 | 103 | case 'pie': |
| 60 | 104 | if (settings.slices) { |
| 61 | 105 | for (i in settings.slices) { |
| @@ -96,8 +140,11 @@ | ||
| 96 | 140 | } |
| 97 | 141 | break; |
| 98 | 142 | case 'gauge': |
| 99 | 143 | break; |
| 144 | + case 'bubble': | |
| 145 | + settings.sortBubblesBySize = settings.sortBubblesBySize ? settings.sortBubblesBySize == 1 : false; // jshint ignore:line | |
| 146 | + break; | |
| 100 | 147 | case 'timeline': |
| 101 | 148 | settings['timeline'] = []; |
| 102 | 149 | settings['timeline']['groupByRowLabel'] = settings['groupByRowLabel'] ? true : false; |
| 103 | 150 | settings['timeline']['colorByRowLabel'] = settings['colorByRowLabel'] ? true : false; |
| @@ -176,16 +223,30 @@ | ||
| 176 | 223 | |
| 177 | 224 | for (i = 0; i < data.length; i++) { |
| 178 | 225 | row = []; |
| 179 | 226 | for (j = 0; j < series.length; j++) { |
| 180 | - if (series[j].type === 'date' || series[j].type === 'datetime') { | |
| 181 | - date = new Date(data[i][j]); | |
| 182 | - data[i][j] = null; | |
| 183 | - if (Object.prototype.toString.call(date) === "[object Date]") { | |
| 184 | - if (!isNaN(date.getTime())) { | |
| 185 | - data[i][j] = date; | |
| 186 | - } | |
| 187 | - } | |
| 227 | + switch(series[j].type) { | |
| 228 | + case 'string': | |
| 229 | + if(data[i][j] === ''){ | |
| 230 | + data[i][j] = null; | |
| 231 | + } | |
| 232 | + break; | |
| 233 | + case 'boolean': | |
| 234 | + if (typeof data[i][j] === 'string'){ | |
| 235 | + data[i][j] = data[i][j] === 'true'; | |
| 236 | + } | |
| 237 | + break; | |
| 238 | + case 'date': | |
| 239 | + // fall-through. | |
| 240 | + case 'datetime': | |
| 241 | + date = new Date(data[i][j]); | |
| 242 | + data[i][j] = null; | |
| 243 | + if (Object.prototype.toString.call(date) === "[object Date]") { | |
| 244 | + if (!isNaN(date.getTime())) { | |
| 245 | + data[i][j] = date; | |
| 246 | + } | |
| 247 | + } | |
| 248 | + break; | |
| 188 | 249 | } |
| 189 | 250 | row.push(data[i][j]); |
| 190 | 251 | } |
| 191 | 252 | table.addRow(row); |
| @@ -203,9 +264,9 @@ | ||
| 203 | 264 | } |
| 204 | 265 | break; |
| 205 | 266 | default: |
| 206 | 267 | for (i = 0; i < settings.series.length; i++) { |
| 207 | - if (!series[i + 1]) { | |
| 268 | + if (!series[i + 1] || typeof settings.series[i] === 'undefined') { | |
| 208 | 269 | continue; |
| 209 | 270 | } |
| 210 | 271 | format_data(id, table, series[i + 1].type, settings.series[i].format, i + 1); |
| 211 | 272 | } |
| @@ -213,8 +274,13 @@ | ||
| 213 | 274 | } |
| 214 | 275 | } else if (chart.type === 'pie' && settings.format && settings.format !== '') { |
| 215 | 276 | format_data(id, table, 'number', settings.format, 1); |
| 216 | 277 | } |
| 278 | + | |
| 279 | + if(settings.hAxis && series[0]) { | |
| 280 | + format_data(id, table, series[0].type, settings.hAxis.format, 0); | |
| 281 | + } | |
| 282 | + | |
| 217 | 283 | override(settings); |
| 218 | 284 | |
| 219 | 285 | gv.events.addListener(render, 'ready', function () { |
| 220 | 286 | var arr = id.split('-'); |
| @@ -227,8 +293,10 @@ | ||
| 227 | 293 | console.warn('render.getImageURI not defined for ' + arr[0] + '-' + arr[1]); |
| 228 | 294 | } |
| 229 | 295 | }); |
| 230 | 296 | |
| 297 | + $('body').trigger('visualizer:chart:settings:extend', {id: id, chart: chart, settings: settings, data: table}); | |
| 298 | + | |
| 231 | 299 | render.draw(table, settings); |
| 232 | 300 | } |
| 233 | 301 | |
| 234 | 302 | function format_data(id, table, type, format, index) { |
| @@ -274,16 +342,8 @@ | ||
| 274 | 342 | renderChart(id); |
| 275 | 343 | } |
| 276 | 344 | } |
| 277 | 345 | |
| 278 | - if(typeof visualizer !== 'undefined'){ | |
| 279 | - // called while updating the chart. | |
| 280 | - visualizer.update = function(){ | |
| 281 | - renderChart('canvas'); | |
| 282 | - }; | |
| 283 | - } | |
| 284 | - | |
| 285 | - | |
| 286 | 346 | var resizeTimeout; |
| 287 | 347 | |
| 288 | 348 | $(document).ready(function() { |
| 289 | 349 | $(window).resize(function() { |
| @@ -324,10 +384,47 @@ | ||
| 324 | 384 | }); |
| 325 | 385 | } |
| 326 | 386 | |
| 327 | 387 | $('body').on('visualizer:render:chart:start', function(event, v){ |
| 388 | + var $chart_types = ['corechart', 'geochart', 'gauge', 'table', 'timeline']; | |
| 389 | + if(v.is_front == true){ // jshint ignore:line | |
| 390 | + // check what all chart types to load. | |
| 391 | + $chart_types = []; | |
| 392 | + $.each(v.charts, function(i, c){ | |
| 393 | + var $type = c.type; | |
| 394 | + switch($type){ | |
| 395 | + case 'bar': | |
| 396 | + case 'column': | |
| 397 | + case 'line': | |
| 398 | + case 'area': | |
| 399 | + case 'stepped area': | |
| 400 | + case 'bubble': | |
| 401 | + case 'pie': | |
| 402 | + case 'donut': | |
| 403 | + case 'combo': | |
| 404 | + case 'candlestick': | |
| 405 | + case 'histogram': | |
| 406 | + case 'scatter': | |
| 407 | + case 'bubble': | |
| 408 | + $type = 'corechart'; | |
| 409 | + break; | |
| 410 | + case 'geo': | |
| 411 | + $type = 'geochart'; | |
| 412 | + break; | |
| 413 | + case 'dataTable': | |
| 414 | + case 'polarArea': | |
| 415 | + case 'radar': | |
| 416 | + $type = null; | |
| 417 | + break; | |
| 418 | + } | |
| 419 | + if($type != null){ | |
| 420 | + $chart_types.push($type); | |
| 421 | + } | |
| 422 | + }); | |
| 423 | + } | |
| 424 | + | |
| 328 | 425 | objects = {}; |
| 329 | - google.charts.load("current", {packages: ["corechart", "geochart", "gauge", "table", "timeline"], mapsApiKey: v.map_api_key, 'language' : v.language}); | |
| 426 | + google.charts.load("current", {packages: $chart_types, mapsApiKey: v.map_api_key, 'language' : v.language}); | |
| 330 | 427 | google.charts.setOnLoadCallback(function() { |
| 331 | 428 | gv = google.visualization; |
| 332 | 429 | all_charts = v.charts; |
| 333 | 430 | render(); |
| @@ -339,18 +436,23 @@ | ||
| 339 | 436 | gv = google.visualization; |
| 340 | 437 | renderSpecificChart(v.id, v.chart); |
| 341 | 438 | }); |
| 342 | 439 | |
| 440 | + $('body').on('visualizer:render:currentchart:update', function(event, v){ | |
| 441 | + renderChart('canvas'); | |
| 442 | + }); | |
| 443 | + | |
| 343 | 444 | // front end actions |
| 445 | + // 'image' is also called from the library | |
| 344 | 446 | $('body').on('visualizer:action:specificchart', function(event, v){ |
| 447 | + var id = v.id; | |
| 448 | + if(typeof rendered_charts[id] === 'undefined'){ | |
| 449 | + return; | |
| 450 | + } | |
| 451 | + var arr = id.split('-'); | |
| 452 | + var img = __visualizer_chart_images[ arr[0] + '-' + arr[1] ]; | |
| 345 | 453 | switch(v.action){ |
| 346 | 454 | case 'print': |
| 347 | - var id = v.id; | |
| 348 | - if(typeof rendered_charts[id] === 'undefined'){ | |
| 349 | - return; | |
| 350 | - } | |
| 351 | - var arr = id.split('-'); | |
| 352 | - var img = __visualizer_chart_images[ arr[0] + '-' + arr[1] ]; | |
| 353 | 455 | // for charts that have no rendered image defined, we print the data instead. |
| 354 | 456 | var html = v.data; |
| 355 | 457 | if(img !== ''){ |
| 356 | 458 | html = "<html><body><img src='" + img + "' /></body></html>"; |
| @@ -355,8 +457,20 @@ | ||
| 355 | 457 | if(img !== ''){ |
| 356 | 458 | html = "<html><body><img src='" + img + "' /></body></html>"; |
| 357 | 459 | } |
| 358 | 460 | $('body').trigger('visualizer:action:specificchart:defaultprint', {data: html}); |
| 461 | + break; | |
| 462 | + case 'image': | |
| 463 | + if(img !== ''){ | |
| 464 | + var $a = $("<a>"); // jshint ignore:line | |
| 465 | + $a.attr("href", img); | |
| 466 | + $("body").append($a); | |
| 467 | + $a.attr("download", v.dataObj.name); | |
| 468 | + $a[0].click(); | |
| 469 | + $a.remove(); | |
| 470 | + }else{ | |
| 471 | + console.warn("No image generated"); | |
| 472 | + } | |
| 359 | 473 | break; |
| 360 | 474 | } |
| 361 | 475 | }); |
| 362 | 476 | |