ext_sprockets 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
  "name": "chart.js",
3
3
  "homepage": "http://www.chartjs.org",
4
4
  "description": "Simple HTML5 charts using the canvas element.",
5
- "version": "2.7.1",
5
+ "version": "2.7.2",
6
6
  "license": "MIT",
7
7
  "main": "src/chart.js",
8
8
  "repository": {
@@ -10,30 +10,33 @@
10
10
  "url": "https://github.com/chartjs/Chart.js.git"
11
11
  },
12
12
  "devDependencies": {
13
- "browserify": "^14.3.0",
14
- "browserify-istanbul": "^2.0.0",
15
- "bundle-collapser": "^1.2.1",
13
+ "browserify": "^14.5.0",
14
+ "browserify-istanbul": "^3.0.1",
15
+ "bundle-collapser": "^1.3.0",
16
16
  "child-process-promise": "^2.2.1",
17
- "coveralls": "^2.13.1",
18
- "gitbook-cli": "^2.3.0",
17
+ "coveralls": "^3.0.0",
18
+ "eslint": "^4.9.0",
19
+ "eslint-config-chartjs": "^0.1.0",
20
+ "eslint-plugin-html": "^4.0.2",
21
+ "gitbook-cli": "^2.3.2",
19
22
  "gulp": "3.9.x",
20
23
  "gulp-concat": "~2.6.x",
21
24
  "gulp-connect": "~5.0.0",
22
- "gulp-eslint": "^3.0.1",
25
+ "gulp-eslint": "^4.0.0",
23
26
  "gulp-file": "^0.3.0",
24
- "gulp-html-validator": "^0.0.5",
27
+ "gulp-htmllint": "^0.0.15",
25
28
  "gulp-insert": "~0.5.0",
26
- "gulp-replace": "^0.5.4",
29
+ "gulp-replace": "^0.6.1",
27
30
  "gulp-size": "~2.1.0",
28
31
  "gulp-streamify": "^1.0.2",
29
32
  "gulp-uglify": "~3.0.x",
30
33
  "gulp-util": "~3.0.x",
31
34
  "gulp-zip": "~4.0.0",
32
- "jasmine": "^2.6.0",
33
- "jasmine-core": "^2.6.2",
34
- "karma": "^1.7.0",
35
+ "jasmine": "^2.8.0",
36
+ "jasmine-core": "^2.8.0",
37
+ "karma": "^1.7.1",
35
38
  "karma-browserify": "^5.1.1",
36
- "karma-chrome-launcher": "^2.1.1",
39
+ "karma-chrome-launcher": "^2.2.0",
37
40
  "karma-coverage": "^1.1.1",
38
41
  "karma-firefox-launcher": "^1.0.1",
39
42
  "karma-jasmine": "^1.1.0",
@@ -42,13 +45,13 @@
42
45
  "pixelmatch": "^4.0.2",
43
46
  "vinyl-source-stream": "^1.1.0",
44
47
  "watchify": "^3.9.0",
45
- "yargs": "^8.0.1"
48
+ "yargs": "^9.0.1"
46
49
  },
47
50
  "spm": {
48
51
  "main": "Chart.js"
49
52
  },
50
53
  "dependencies": {
51
- "chartjs-color": "~2.2.0",
52
- "moment": "~2.18.0"
54
+ "chartjs-color": "^2.1.0",
55
+ "moment": "^2.10.2"
53
56
  }
54
57
  }
@@ -174,7 +174,7 @@
174
174
 
175
175
  function runNext() {
176
176
  if (runningRequests < maxRequests) {
177
- var request = pendingRequests.shift();
177
+ var request = pendingRequests.shift()
178
178
  if (request) {
179
179
  runningRequests++;
180
180
  getJSON(request[0], request[1], request[2]);
@@ -369,1135 +369,1116 @@
369
369
  }
370
370
 
371
371
  function loadAdapters() {
372
- if (!ChartjsAdapter && "Chart" in window) {
373
- ChartjsAdapter = (function () {
374
- var Chart = window.Chart;
372
+ if (!HighchartsAdapter && "Highcharts" in window) {
373
+ HighchartsAdapter = new function () {
374
+ var Highcharts = window.Highcharts;
375
375
 
376
- var baseOptions = {
377
- maintainAspectRatio: false,
378
- animation: false,
379
- tooltips: {
380
- displayColors: false
381
- },
382
- legend: {},
383
- title: {fontSize: 20, fontColor: "#333"}
384
- };
376
+ this.name = "highcharts";
385
377
 
386
378
  var defaultOptions = {
387
- scales: {
388
- yAxes: [
389
- {
390
- ticks: {
391
- maxTicksLimit: 4
392
- },
393
- scaleLabel: {
394
- fontSize: 16,
395
- // fontStyle: "bold",
396
- fontColor: "#333"
397
- }
379
+ chart: {},
380
+ xAxis: {
381
+ title: {
382
+ text: null
383
+ },
384
+ labels: {
385
+ style: {
386
+ fontSize: "12px"
398
387
  }
399
- ],
400
- xAxes: [
401
- {
402
- gridLines: {
403
- drawOnChartArea: false
404
- },
405
- scaleLabel: {
406
- fontSize: 16,
407
- // fontStyle: "bold",
408
- fontColor: "#333"
409
- },
410
- time: {},
411
- ticks: {}
388
+ }
389
+ },
390
+ yAxis: {
391
+ title: {
392
+ text: null
393
+ },
394
+ labels: {
395
+ style: {
396
+ fontSize: "12px"
412
397
  }
413
- ]
398
+ }
399
+ },
400
+ title: {
401
+ text: null
402
+ },
403
+ credits: {
404
+ enabled: false
405
+ },
406
+ legend: {
407
+ borderWidth: 0
408
+ },
409
+ tooltip: {
410
+ style: {
411
+ fontSize: "12px"
412
+ }
413
+ },
414
+ plotOptions: {
415
+ areaspline: {},
416
+ series: {
417
+ marker: {}
418
+ }
414
419
  }
415
420
  };
416
421
 
417
- // http://there4.io/2012/05/02/google-chart-color-list/
418
- var defaultColors = [
419
- "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
420
- "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
421
- "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
422
- ];
423
-
424
422
  var hideLegend = function (options, legend, hideLegend) {
425
423
  if (legend !== undefined) {
426
- options.legend.display = !!legend;
424
+ options.legend.enabled = !!legend;
427
425
  if (legend && legend !== true) {
428
- options.legend.position = legend;
426
+ if (legend === "top" || legend === "bottom") {
427
+ options.legend.verticalAlign = legend;
428
+ } else {
429
+ options.legend.layout = "vertical";
430
+ options.legend.verticalAlign = "middle";
431
+ options.legend.align = legend;
432
+ }
429
433
  }
430
434
  } else if (hideLegend) {
431
- options.legend.display = false;
435
+ options.legend.enabled = false;
432
436
  }
433
437
  };
434
438
 
435
439
  var setTitle = function (options, title) {
436
- options.title.display = true;
437
440
  options.title.text = title;
438
441
  };
439
442
 
440
443
  var setMin = function (options, min) {
441
- if (min !== null) {
442
- options.scales.yAxes[0].ticks.min = toFloat(min);
443
- }
444
+ options.yAxis.min = min;
444
445
  };
445
446
 
446
447
  var setMax = function (options, max) {
447
- options.scales.yAxes[0].ticks.max = toFloat(max);
448
- };
449
-
450
- var setBarMin = function (options, min) {
451
- if (min !== null) {
452
- options.scales.xAxes[0].ticks.min = toFloat(min);
453
- }
454
- };
455
-
456
- var setBarMax = function (options, max) {
457
- options.scales.xAxes[0].ticks.max = toFloat(max);
448
+ options.yAxis.max = max;
458
449
  };
459
450
 
460
451
  var setStacked = function (options, stacked) {
461
- options.scales.xAxes[0].stacked = !!stacked;
462
- options.scales.yAxes[0].stacked = !!stacked;
452
+ options.plotOptions.series.stacking = stacked ? "normal" : null;
463
453
  };
464
454
 
465
455
  var setXtitle = function (options, title) {
466
- options.scales.xAxes[0].scaleLabel.display = true;
467
- options.scales.xAxes[0].scaleLabel.labelString = title;
456
+ options.xAxis.title.text = title;
468
457
  };
469
458
 
470
459
  var setYtitle = function (options, title) {
471
- options.scales.yAxes[0].scaleLabel.display = true;
472
- options.scales.yAxes[0].scaleLabel.labelString = title;
460
+ options.yAxis.title.text = title;
473
461
  };
474
462
 
475
- var drawChart = function(chart, type, data, options) {
476
- if (chart.chart) {
477
- chart.chart.destroy();
478
- } else {
479
- chart.element.innerHTML = "<canvas></canvas>";
480
- }
463
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
481
464
 
482
- var ctx = chart.element.getElementsByTagName("CANVAS")[0];
483
- chart.chart = new Chart(ctx, {
484
- type: type,
485
- data: data,
486
- options: options
487
- });
488
- };
465
+ this.renderLineChart = function (chart, chartType) {
466
+ chartType = chartType || "spline";
467
+ var chartOptions = {};
468
+ if (chartType === "areaspline") {
469
+ chartOptions = {
470
+ plotOptions: {
471
+ areaspline: {
472
+ stacking: "normal"
473
+ },
474
+ area: {
475
+ stacking: "normal"
476
+ },
477
+ series: {
478
+ marker: {
479
+ enabled: false
480
+ }
481
+ }
482
+ }
483
+ };
484
+ }
489
485
 
490
- // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
491
- var addOpacity = function(hex, opacity) {
492
- var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
493
- return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
494
- };
486
+ if (chart.options.curve === false) {
487
+ if (chartType === "areaspline") {
488
+ chartType = "area";
489
+ } else if (chartType === "spline") {
490
+ chartType = "line";
491
+ }
492
+ }
495
493
 
496
- var setLabelSize = function (chart, data, options) {
497
- var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
498
- if (maxLabelSize > 25) {
499
- maxLabelSize = 25;
494
+ var options = jsOptions(chart, chart.options, chartOptions), data, i, j;
495
+ options.xAxis.type = chart.discrete ? "category" : "datetime";
496
+ if (!options.chart.type) {
497
+ options.chart.type = chartType;
500
498
  }
501
- options.scales.xAxes[0].ticks.callback = function (value) {
502
- value = toStr(value);
503
- if (value.length > maxLabelSize) {
504
- return value.substring(0, maxLabelSize - 2) + "...";
505
- } else {
506
- return value;
499
+ options.chart.renderTo = chart.element.id;
500
+
501
+ var series = chart.data;
502
+ for (i = 0; i < series.length; i++) {
503
+ data = series[i].data;
504
+ if (!chart.discrete) {
505
+ for (j = 0; j < data.length; j++) {
506
+ data[j][0] = data[j][0].getTime();
507
+ }
507
508
  }
508
- };
509
+ series[i].marker = {symbol: "circle"};
510
+ if (chart.options.points === false) {
511
+ series[i].marker.enabled = false;
512
+ }
513
+ }
514
+ options.series = series;
515
+ chart.chart = new Highcharts.Chart(options);
509
516
  };
510
517
 
511
- var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
518
+ this.renderScatterChart = function (chart) {
519
+ var chartOptions = {};
520
+ var options = jsOptions(chart, chart.options, chartOptions);
521
+ options.chart.type = "scatter";
522
+ options.chart.renderTo = chart.element.id;
523
+ options.series = chart.data;
524
+ chart.chart = new Highcharts.Chart(options);
525
+ };
512
526
 
513
- var createDataTable = function (chart, options, chartType) {
514
- var datasets = [];
515
- var labels = [];
527
+ this.renderPieChart = function (chart) {
528
+ var chartOptions = merge(defaultOptions, {});
516
529
 
517
- var colors = chart.options.colors || defaultColors;
530
+ if (chart.options.colors) {
531
+ chartOptions.colors = chart.options.colors;
532
+ }
533
+ if (chart.options.donut) {
534
+ chartOptions.plotOptions = {pie: {innerSize: "50%"}};
535
+ }
518
536
 
519
- var day = true;
520
- var week = true;
521
- var dayOfWeek;
522
- var month = true;
523
- var year = true;
524
- var hour = true;
525
- var minute = true;
526
- var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
537
+ if ("legend" in chart.options) {
538
+ hideLegend(chartOptions, chart.options.legend);
539
+ }
527
540
 
528
- var series = chart.data;
541
+ if (chart.options.title) {
542
+ setTitle(chartOptions, chart.options.title);
543
+ }
529
544
 
530
- var sortedLabels = [];
545
+ var options = merge(chartOptions, chart.options.library || {});
546
+ options.chart.renderTo = chart.element.id;
547
+ options.series = [{
548
+ type: "pie",
549
+ name: chart.options.label || "Value",
550
+ data: chart.data
551
+ }];
552
+ chart.chart = new Highcharts.Chart(options);
553
+ };
554
+
555
+ this.renderColumnChart = function (chart, chartType) {
556
+ chartType = chartType || "column";
557
+ var series = chart.data;
558
+ var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
559
+ options.chart.type = chartType;
560
+ options.chart.renderTo = chart.element.id;
531
561
 
532
- var i, j, s, d, key, rows = [];
533
562
  for (i = 0; i < series.length; i++) {
534
563
  s = series[i];
535
564
 
536
565
  for (j = 0; j < s.data.length; j++) {
537
566
  d = s.data[j];
538
- key = detectType ? d[0].getTime() : d[0];
539
- if (!rows[key]) {
540
- rows[key] = new Array(series.length);
541
- }
542
- rows[key][i] = toFloat(d[1]);
543
- if (sortedLabels.indexOf(key) === -1) {
544
- sortedLabels.push(key);
567
+ if (!rows[d[0]]) {
568
+ rows[d[0]] = new Array(series.length);
569
+ categories.push(d[0]);
545
570
  }
571
+ rows[d[0]][i] = d[1];
546
572
  }
547
573
  }
548
574
 
549
- if (detectType || chart.options.xtype === "number") {
550
- sortedLabels.sort(sortByNumber);
575
+ if (chart.options.xtype === "number") {
576
+ categories.sort(sortByNumber);
551
577
  }
552
578
 
553
- var rows2 = [];
554
- for (j = 0; j < series.length; j++) {
555
- rows2.push([]);
556
- }
579
+ options.xAxis.categories = categories;
557
580
 
558
- var value;
559
- var k;
560
- for (k = 0; k < sortedLabels.length; k++) {
561
- i = sortedLabels[k];
562
- if (detectType) {
563
- value = new Date(toFloat(i));
564
- // TODO make this efficient
565
- day = day && isDay(value);
566
- if (!dayOfWeek) {
567
- dayOfWeek = value.getDay();
568
- }
569
- week = week && isWeek(value, dayOfWeek);
570
- month = month && isMonth(value);
571
- year = year && isYear(value);
572
- hour = hour && isHour(value);
573
- minute = minute && isMinute(value);
574
- } else {
575
- value = i;
581
+ var newSeries = [], d2;
582
+ for (i = 0; i < series.length; i++) {
583
+ d = [];
584
+ for (j = 0; j < categories.length; j++) {
585
+ d.push(rows[categories[j]][i] || 0);
576
586
  }
577
- labels.push(value);
578
- for (j = 0; j < series.length; j++) {
579
- // Chart.js doesn't like undefined
580
- rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
587
+
588
+ d2 = {
589
+ name: series[i].name,
590
+ data: d
591
+ }
592
+ if (series[i].stack) {
593
+ d2.stack = series[i].stack;
581
594
  }
595
+
596
+ newSeries.push(d2);
582
597
  }
598
+ options.series = newSeries;
583
599
 
584
- for (i = 0; i < series.length; i++) {
585
- s = series[i];
600
+ chart.chart = new Highcharts.Chart(options);
601
+ };
586
602
 
587
- var color = s.color || colors[i];
588
- var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
603
+ var self = this;
589
604
 
590
- var dataset = {
591
- label: s.name,
592
- data: rows2[i],
593
- fill: chartType === "area",
594
- borderColor: color,
595
- backgroundColor: backgroundColor,
596
- pointBackgroundColor: color,
597
- borderWidth: 2
598
- };
605
+ this.renderBarChart = function (chart) {
606
+ self.renderColumnChart(chart, "bar");
607
+ };
599
608
 
600
- if (s.stack) {
601
- dataset.stack = s.stack;
602
- }
609
+ this.renderAreaChart = function (chart) {
610
+ self.renderLineChart(chart, "areaspline");
611
+ };
612
+ };
613
+ adapters.push(HighchartsAdapter);
614
+ }
615
+ if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
616
+ GoogleChartsAdapter = new function () {
617
+ var google = window.google;
603
618
 
604
- // PATCH_BEGIN
605
- if (chart.options.y2 === true) {
606
- dataset.yAxisID = (s.y2 === true) ? 'y-axis-right' : 'y-axis-left';
607
- options.scales.yAxes = [
608
- { id: 'y-axis-left', position: 'left' },
609
- { id: 'y-axis-right', position: 'right' }
610
- ];
611
- }
612
- // PATCH_END
619
+ this.name = "google";
613
620
 
614
- if (chart.options.curve === false) {
615
- dataset.lineTension = 0;
616
- }
621
+ var loaded = {};
622
+ var callbacks = [];
617
623
 
618
- if (chart.options.points === false) {
619
- dataset.pointRadius = 0;
620
- dataset.pointHitRadius = 5;
624
+ var runCallbacks = function () {
625
+ var cb, call;
626
+ for (var i = 0; i < callbacks.length; i++) {
627
+ cb = callbacks[i];
628
+ call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
629
+ if (call) {
630
+ cb.callback();
631
+ callbacks.splice(i, 1);
632
+ i--;
621
633
  }
622
-
623
- datasets.push(merge(dataset, s.library || {}));
624
634
  }
635
+ };
625
636
 
626
- if (detectType && labels.length > 0) {
627
- var minTime = labels[0].getTime();
628
- var maxTime = labels[0].getTime();
629
- for (i = 1; i < labels.length; i++) {
630
- value = labels[i].getTime();
631
- if (value < minTime) {
632
- minTime = value;
633
- }
634
- if (value > maxTime) {
635
- maxTime = value;
636
- }
637
- }
637
+ var waitForLoaded = function (pack, callback) {
638
+ if (!callback) {
639
+ callback = pack;
640
+ pack = "corechart";
641
+ }
638
642
 
639
- var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
643
+ callbacks.push({pack: pack, callback: callback});
640
644
 
641
- if (!options.scales.xAxes[0].time.unit) {
642
- var step;
643
- if (year || timeDiff > 365 * 10) {
644
- options.scales.xAxes[0].time.unit = "year";
645
- step = 365;
646
- } else if (month || timeDiff > 30 * 10) {
647
- options.scales.xAxes[0].time.unit = "month";
648
- step = 30;
649
- } else if (day || timeDiff > 10) {
650
- options.scales.xAxes[0].time.unit = "day";
651
- step = 1;
652
- } else if (hour || timeDiff > 0.5) {
653
- options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
654
- options.scales.xAxes[0].time.unit = "hour";
655
- step = 1 / 24.0;
656
- } else if (minute) {
657
- options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
658
- options.scales.xAxes[0].time.unit = "minute";
659
- step = 1 / 24.0 / 60.0;
660
- }
645
+ if (loaded[pack]) {
646
+ runCallbacks();
647
+ } else {
648
+ loaded[pack] = true;
661
649
 
662
- if (step && timeDiff > 0) {
663
- var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
664
- if (week && step === 1) {
665
- unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
666
- }
667
- options.scales.xAxes[0].time.unitStepSize = unitStepSize;
668
- }
650
+ // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
651
+ var loadOptions = {
652
+ packages: [pack],
653
+ callback: runCallbacks
654
+ };
655
+ if (config.language) {
656
+ loadOptions.language = config.language;
657
+ }
658
+ if (pack === "corechart" && config.mapsApiKey) {
659
+ loadOptions.mapsApiKey = config.mapsApiKey;
669
660
  }
670
661
 
671
- if (!options.scales.xAxes[0].time.tooltipFormat) {
672
- if (day) {
673
- options.scales.xAxes[0].time.tooltipFormat = "ll";
674
- } else if (hour) {
675
- options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
676
- } else if (minute) {
677
- options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
678
- }
662
+ if (window.google.setOnLoadCallback) {
663
+ google.load("visualization", "1", loadOptions);
664
+ } else {
665
+ google.charts.load("current", loadOptions);
679
666
  }
680
667
  }
681
-
682
- var data = {
683
- labels: labels,
684
- datasets: datasets
685
- };
686
-
687
- return data;
688
668
  };
689
669
 
690
- var renderLineChart = function (chart, chartType) {
691
- if (chart.options.xtype === "number") {
692
- return renderScatterChart(chart, chartType, true);
670
+ // Set chart options
671
+ var defaultOptions = {
672
+ chartArea: {},
673
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
674
+ pointSize: 6,
675
+ legend: {
676
+ textStyle: {
677
+ fontSize: 12,
678
+ color: "#444"
679
+ },
680
+ alignment: "center",
681
+ position: "right"
682
+ },
683
+ curveType: "function",
684
+ hAxis: {
685
+ textStyle: {
686
+ color: "#666",
687
+ fontSize: 12
688
+ },
689
+ titleTextStyle: {},
690
+ gridlines: {
691
+ color: "transparent"
692
+ },
693
+ baselineColor: "#ccc",
694
+ viewWindow: {}
695
+ },
696
+ vAxis: {
697
+ textStyle: {
698
+ color: "#666",
699
+ fontSize: 12
700
+ },
701
+ titleTextStyle: {},
702
+ baselineColor: "#ccc",
703
+ viewWindow: {}
704
+ },
705
+ tooltip: {
706
+ textStyle: {
707
+ color: "#666",
708
+ fontSize: 12
709
+ }
693
710
  }
711
+ };
694
712
 
695
- var chartOptions = {};
696
- if (chartType === "area") {
697
- // TODO fix area stacked
698
- // chartOptions.stacked = true;
699
- }
700
- // fix for https://github.com/chartjs/Chart.js/issues/2441
701
- if (!chart.options.max && allZeros(chart.data)) {
702
- chartOptions.max = 1;
713
+ var hideLegend = function (options, legend, hideLegend) {
714
+ if (legend !== undefined) {
715
+ var position;
716
+ if (!legend) {
717
+ position = "none";
718
+ } else if (legend === true) {
719
+ position = "right";
720
+ } else {
721
+ position = legend;
722
+ }
723
+ options.legend.position = position;
724
+ } else if (hideLegend) {
725
+ options.legend.position = "none";
703
726
  }
727
+ };
704
728
 
705
- var options = jsOptions(chart, merge(chartOptions, chart.options));
706
-
707
- var data = createDataTable(chart, options, chartType || "line");
729
+ var setTitle = function (options, title) {
730
+ options.title = title;
731
+ options.titleTextStyle = {color: "#333", fontSize: "20px"};
732
+ };
708
733
 
709
- options.scales.xAxes[0].type = chart.discrete ? "category" : "time";
734
+ var setMin = function (options, min) {
735
+ options.vAxis.viewWindow.min = min;
736
+ };
710
737
 
711
- drawChart(chart, "line", data, options);
738
+ var setMax = function (options, max) {
739
+ options.vAxis.viewWindow.max = max;
712
740
  };
713
741
 
714
- var renderPieChart = function (chart) {
715
- var options = merge({}, baseOptions);
716
- if (chart.options.donut) {
717
- options.cutoutPercentage = 50;
718
- }
719
-
720
- if ("legend" in chart.options) {
721
- hideLegend(options, chart.options.legend);
722
- }
723
-
724
- if (chart.options.title) {
725
- setTitle(options, chart.options.title);
726
- }
727
-
728
- options = merge(options, chart.options.library || {});
729
-
730
- var labels = [];
731
- var values = [];
732
- for (var i = 0; i < chart.data.length; i++) {
733
- var point = chart.data[i];
734
- labels.push(point[0]);
735
- values.push(point[1]);
736
- }
737
-
738
- var data = {
739
- labels: labels,
740
- datasets: [
741
- {
742
- data: values,
743
- backgroundColor: chart.options.colors || defaultColors
744
- }
745
- ]
746
- };
747
-
748
- drawChart(chart, "pie", data, options);
742
+ var setBarMin = function (options, min) {
743
+ options.hAxis.viewWindow.min = min;
749
744
  };
750
745
 
751
- var renderColumnChart = function (chart, chartType) {
752
- var options;
753
- if (chartType === "bar") {
754
- options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
755
- } else {
756
- options = jsOptions(chart, chart.options);
757
- }
758
- var data = createDataTable(chart, options, "column");
759
- setLabelSize(chart, data, options);
760
- drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
746
+ var setBarMax = function (options, max) {
747
+ options.hAxis.viewWindow.max = max;
761
748
  };
762
749
 
763
- var renderAreaChart = function (chart) {
764
- renderLineChart(chart, "area");
750
+ var setStacked = function (options, stacked) {
751
+ options.isStacked = !!stacked;
765
752
  };
766
753
 
767
- var renderBarChart = function (chart) {
768
- renderColumnChart(chart, "bar");
754
+ var setXtitle = function (options, title) {
755
+ options.hAxis.title = title;
756
+ options.hAxis.titleTextStyle.italic = false;
769
757
  };
770
758
 
771
- var renderScatterChart = function (chart, chartType, lineChart) {
772
- chartType = chartType || "line";
759
+ var setYtitle = function (options, title) {
760
+ options.vAxis.title = title;
761
+ options.vAxis.titleTextStyle.italic = false;
762
+ };
773
763
 
774
- var options = jsOptions(chart, chart.options);
764
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
775
765
 
776
- var colors = chart.options.colors || defaultColors;
766
+ // cant use object as key
767
+ var createDataTable = function (series, columnType, xtype) {
768
+ var i, j, s, d, key, rows = [], sortedLabels = [];
769
+ for (i = 0; i < series.length; i++) {
770
+ s = series[i];
777
771
 
778
- var datasets = [];
779
- var series = chart.data;
780
- for (var i = 0; i < series.length; i++) {
781
- var s = series[i];
782
- var d = [];
783
- for (var j = 0; j < s.data.length; j++) {
784
- var point = {
785
- x: toFloat(s.data[j][0]),
786
- y: toFloat(s.data[j][1])
787
- };
788
- if (chartType === "bubble") {
789
- point.r = toFloat(s.data[j][2]);
772
+ for (j = 0; j < s.data.length; j++) {
773
+ d = s.data[j];
774
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
775
+ if (!rows[key]) {
776
+ rows[key] = new Array(series.length);
777
+ sortedLabels.push(key);
790
778
  }
791
- d.push(point);
779
+ rows[key][i] = toFloat(d[1]);
792
780
  }
793
-
794
- var color = s.color || colors[i];
795
- var backgroundColor = chartType === "area" ? addOpacity(color, 0.5) : color;
796
-
797
- datasets.push({
798
- label: s.name,
799
- showLine: lineChart || false,
800
- data: d,
801
- borderColor: color,
802
- backgroundColor: backgroundColor,
803
- pointBackgroundColor: color,
804
- fill: chartType === "area"
805
- });
806
781
  }
807
782
 
808
- if (chartType === "area") {
809
- chartType = "line";
783
+ var rows2 = [];
784
+ var day = true;
785
+ var value;
786
+ for (var j = 0; j < sortedLabels.length; j++) {
787
+ var i = sortedLabels[j];
788
+ if (columnType === "datetime") {
789
+ value = new Date(toFloat(i));
790
+ day = day && isDay(value);
791
+ } else if (columnType === "number") {
792
+ value = toFloat(i);
793
+ } else {
794
+ value = i;
795
+ }
796
+ rows2.push([value].concat(rows[i]));
797
+ }
798
+ if (columnType === "datetime") {
799
+ rows2.sort(sortByTime);
800
+ } else if (columnType === "number") {
801
+ rows2.sort(sortByNumberSeries);
810
802
  }
811
803
 
812
- var data = {datasets: datasets};
804
+ if (xtype === "number") {
805
+ rows2.sort(sortByNumberSeries);
813
806
 
814
- options.scales.xAxes[0].type = "linear";
815
- options.scales.xAxes[0].position = "bottom";
807
+ for (var i = 0; i < rows2.length; i++) {
808
+ rows2[i][0] = toStr(rows2[i][0]);
809
+ }
810
+ }
816
811
 
817
- drawChart(chart, chartType, data, options);
818
- };
812
+ // create datatable
813
+ var data = new google.visualization.DataTable();
814
+ columnType = columnType === "datetime" && day ? "date" : columnType;
815
+ data.addColumn(columnType, "");
816
+ for (i = 0; i < series.length; i++) {
817
+ data.addColumn("number", series[i].name);
818
+ }
819
+ data.addRows(rows2);
819
820
 
820
- var renderBubbleChart = function (chart) {
821
- renderScatterChart(chart, "bubble");
821
+ return data;
822
822
  };
823
823
 
824
- return {
825
- name: "chartjs",
826
- renderLineChart: renderLineChart,
827
- renderPieChart: renderPieChart,
828
- renderColumnChart: renderColumnChart,
829
- renderBarChart: renderBarChart,
830
- renderAreaChart: renderAreaChart,
831
- renderScatterChart: renderScatterChart,
832
- renderBubbleChart: renderBubbleChart
824
+ var resize = function (callback) {
825
+ if (window.attachEvent) {
826
+ window.attachEvent("onresize", callback);
827
+ } else if (window.addEventListener) {
828
+ window.addEventListener("resize", callback, true);
829
+ }
830
+ callback();
833
831
  };
834
- })();
835
-
836
- adapters.push(ChartjsAdapter);
837
- }
838
832
 
839
- if (!HighchartsAdapter && "Highcharts" in window) {
840
- HighchartsAdapter = (function () {
841
- var Highcharts = window.Highcharts;
833
+ this.renderLineChart = function (chart) {
834
+ waitForLoaded(function () {
835
+ var chartOptions = {};
842
836
 
843
- var defaultOptions = {
844
- chart: {},
845
- xAxis: {
846
- title: {
847
- text: null
848
- },
849
- labels: {
850
- style: {
851
- fontSize: "12px"
852
- }
853
- }
854
- },
855
- yAxis: {
856
- title: {
857
- text: null
858
- },
859
- labels: {
860
- style: {
861
- fontSize: "12px"
862
- }
837
+ if (chart.options.curve === false) {
838
+ chartOptions.curveType = "none";
863
839
  }
864
- },
865
- title: {
866
- text: null
867
- },
868
- credits: {
869
- enabled: false
870
- },
871
- legend: {
872
- borderWidth: 0
873
- },
874
- tooltip: {
875
- style: {
876
- fontSize: "12px"
840
+
841
+ if (chart.options.points === false) {
842
+ chartOptions.pointSize = 0;
877
843
  }
878
- },
879
- plotOptions: {
880
- areaspline: {},
881
- series: {
882
- marker: {}
844
+
845
+ var options = jsOptions(chart, chart.options, chartOptions);
846
+ var columnType = chart.discrete ? "string" : "datetime";
847
+ if (chart.options.xtype === "number") {
848
+ columnType = "number";
883
849
  }
884
- }
850
+ var data = createDataTable(chart.data, columnType);
851
+ chart.chart = new google.visualization.LineChart(chart.element);
852
+ resize(function () {
853
+ chart.chart.draw(data, options);
854
+ });
855
+ });
885
856
  };
886
857
 
887
- var hideLegend = function (options, legend, hideLegend) {
888
- if (legend !== undefined) {
889
- options.legend.enabled = !!legend;
890
- if (legend && legend !== true) {
891
- if (legend === "top" || legend === "bottom") {
892
- options.legend.verticalAlign = legend;
893
- } else {
894
- options.legend.layout = "vertical";
895
- options.legend.verticalAlign = "middle";
896
- options.legend.align = legend;
897
- }
858
+ this.renderPieChart = function (chart) {
859
+ waitForLoaded(function () {
860
+ var chartOptions = {
861
+ chartArea: {
862
+ top: "10%",
863
+ height: "80%"
864
+ },
865
+ legend: {}
866
+ };
867
+ if (chart.options.colors) {
868
+ chartOptions.colors = chart.options.colors;
898
869
  }
899
- } else if (hideLegend) {
900
- options.legend.enabled = false;
901
- }
902
- };
870
+ if (chart.options.donut) {
871
+ chartOptions.pieHole = 0.5;
872
+ }
873
+ if ("legend" in chart.options) {
874
+ hideLegend(chartOptions, chart.options.legend);
875
+ }
876
+ if (chart.options.title) {
877
+ setTitle(chartOptions, chart.options.title);
878
+ }
879
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
903
880
 
904
- var setTitle = function (options, title) {
905
- options.title.text = title;
906
- };
881
+ var data = new google.visualization.DataTable();
882
+ data.addColumn("string", "");
883
+ data.addColumn("number", "Value");
884
+ data.addRows(chart.data);
907
885
 
908
- var setMin = function (options, min) {
909
- options.yAxis.min = min;
886
+ chart.chart = new google.visualization.PieChart(chart.element);
887
+ resize(function () {
888
+ chart.chart.draw(data, options);
889
+ });
890
+ });
910
891
  };
911
892
 
912
- var setMax = function (options, max) {
913
- options.yAxis.max = max;
893
+ this.renderColumnChart = function (chart) {
894
+ waitForLoaded(function () {
895
+ var options = jsOptions(chart, chart.options);
896
+ var data = createDataTable(chart.data, "string", chart.options.xtype);
897
+ chart.chart = new google.visualization.ColumnChart(chart.element);
898
+ resize(function () {
899
+ chart.chart.draw(data, options);
900
+ });
901
+ });
914
902
  };
915
903
 
916
- var setStacked = function (options, stacked) {
917
- options.plotOptions.series.stacking = stacked ? "normal" : null;
918
- };
919
-
920
- var setXtitle = function (options, title) {
921
- options.xAxis.title.text = title;
922
- };
923
-
924
- var setYtitle = function (options, title) {
925
- options.yAxis.title.text = title;
926
- };
927
-
928
- var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
929
-
930
- var drawChart = function(chart, data, options) {
931
- if (chart.chart) {
932
- chart.chart.destroy();
933
- }
934
-
935
- options.chart.renderTo = chart.element.id;
936
- options.series = data;
937
- chart.chart = new Highcharts.Chart(options);
938
- };
939
-
940
- var renderLineChart = function (chart, chartType) {
941
- chartType = chartType || "spline";
942
- var chartOptions = {};
943
- if (chartType === "areaspline") {
944
- chartOptions = {
945
- plotOptions: {
946
- areaspline: {
947
- stacking: "normal"
948
- },
949
- area: {
950
- stacking: "normal"
951
- },
952
- series: {
953
- marker: {
954
- enabled: false
955
- }
904
+ this.renderBarChart = function (chart) {
905
+ waitForLoaded(function () {
906
+ var chartOptions = {
907
+ hAxis: {
908
+ gridlines: {
909
+ color: "#ccc"
956
910
  }
957
911
  }
958
912
  };
959
- }
960
-
961
- if (chart.options.curve === false) {
962
- if (chartType === "areaspline") {
963
- chartType = "area";
964
- } else if (chartType === "spline") {
965
- chartType = "line";
966
- }
967
- }
913
+ var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
914
+ var data = createDataTable(chart.data, "string", chart.options.xtype);
915
+ chart.chart = new google.visualization.BarChart(chart.element);
916
+ resize(function () {
917
+ chart.chart.draw(data, options);
918
+ });
919
+ });
920
+ };
968
921
 
969
- var options = jsOptions(chart, chart.options, chartOptions), data, i, j;
970
- options.xAxis.type = chart.discrete ? "category" : "datetime";
971
- if (!options.chart.type) {
972
- options.chart.type = chartType;
973
- }
922
+ this.renderAreaChart = function (chart) {
923
+ waitForLoaded(function () {
924
+ var chartOptions = {
925
+ isStacked: true,
926
+ pointSize: 0,
927
+ areaOpacity: 0.5
928
+ };
974
929
 
975
- var series = chart.data;
976
- for (i = 0; i < series.length; i++) {
977
- data = series[i].data;
978
- if (!chart.discrete) {
979
- for (j = 0; j < data.length; j++) {
980
- data[j][0] = data[j][0].getTime();
981
- }
982
- }
983
- series[i].marker = {symbol: "circle"};
984
- if (chart.options.points === false) {
985
- series[i].marker.enabled = false;
930
+ var options = jsOptions(chart, chart.options, chartOptions);
931
+ var columnType = chart.discrete ? "string" : "datetime";
932
+ if (chart.options.xtype === "number") {
933
+ columnType = "number";
986
934
  }
987
- }
988
-
989
- drawChart(chart, series, options);
990
- };
991
-
992
- var renderScatterChart = function (chart) {
993
- var options = jsOptions(chart, chart.options, {});
994
- options.chart.type = "scatter";
995
- drawChart(chart, chart.data, options);
935
+ var data = createDataTable(chart.data, columnType);
936
+ chart.chart = new google.visualization.AreaChart(chart.element);
937
+ resize(function () {
938
+ chart.chart.draw(data, options);
939
+ });
940
+ });
996
941
  };
997
942
 
998
- var renderPieChart = function (chart) {
999
- var chartOptions = merge(defaultOptions, {});
1000
-
1001
- if (chart.options.colors) {
1002
- chartOptions.colors = chart.options.colors;
1003
- }
1004
- if (chart.options.donut) {
1005
- chartOptions.plotOptions = {pie: {innerSize: "50%"}};
1006
- }
1007
-
1008
- if ("legend" in chart.options) {
1009
- hideLegend(chartOptions, chart.options.legend);
1010
- }
1011
-
1012
- if (chart.options.title) {
1013
- setTitle(chartOptions, chart.options.title);
1014
- }
943
+ this.renderGeoChart = function (chart) {
944
+ waitForLoaded(function () {
945
+ var chartOptions = {
946
+ legend: "none",
947
+ colorAxis: {
948
+ colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
949
+ }
950
+ };
951
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1015
952
 
1016
- var options = merge(chartOptions, chart.options.library || {});
1017
- var series = [{
1018
- type: "pie",
1019
- name: chart.options.label || "Value",
1020
- data: chart.data
1021
- }];
953
+ var data = new google.visualization.DataTable();
954
+ data.addColumn("string", "");
955
+ data.addColumn("number", chart.options.label || "Value");
956
+ data.addRows(chart.data);
1022
957
 
1023
- drawChart(chart, series, options);
958
+ chart.chart = new google.visualization.GeoChart(chart.element);
959
+ resize(function () {
960
+ chart.chart.draw(data, options);
961
+ });
962
+ });
1024
963
  };
1025
964
 
1026
- var renderColumnChart = function (chart, chartType) {
1027
- chartType = chartType || "column";
1028
- var series = chart.data;
1029
- var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
1030
- options.chart.type = chartType;
1031
-
1032
- for (i = 0; i < series.length; i++) {
1033
- s = series[i];
965
+ this.renderScatterChart = function (chart) {
966
+ waitForLoaded(function () {
967
+ var chartOptions = {};
968
+ var options = jsOptions(chart, chart.options, chartOptions);
1034
969
 
1035
- for (j = 0; j < s.data.length; j++) {
1036
- d = s.data[j];
1037
- if (!rows[d[0]]) {
1038
- rows[d[0]] = new Array(series.length);
1039
- categories.push(d[0]);
970
+ var series = chart.data, rows2 = [], i, j, data, d;
971
+ for (i = 0; i < series.length; i++) {
972
+ d = series[i].data;
973
+ for (j = 0; j < d.length; j++) {
974
+ var row = new Array(series.length + 1);
975
+ row[0] = d[j][0];
976
+ row[i + 1] = d[j][1];
977
+ rows2.push(row);
1040
978
  }
1041
- rows[d[0]][i] = d[1];
1042
979
  }
1043
- }
1044
980
 
1045
- if (chart.options.xtype === "number") {
1046
- categories.sort(sortByNumber);
1047
- }
1048
-
1049
- options.xAxis.categories = categories;
1050
-
1051
- var newSeries = [], d2;
1052
- for (i = 0; i < series.length; i++) {
1053
- d = [];
1054
- for (j = 0; j < categories.length; j++) {
1055
- d.push(rows[categories[j]][i] || 0);
1056
- }
1057
-
1058
- d2 = {
1059
- name: series[i].name,
1060
- data: d
1061
- };
1062
- if (series[i].stack) {
1063
- d2.stack = series[i].stack;
981
+ var data = new google.visualization.DataTable();
982
+ data.addColumn("number", "");
983
+ for (i = 0; i < series.length; i++) {
984
+ data.addColumn("number", series[i].name);
1064
985
  }
986
+ data.addRows(rows2);
1065
987
 
1066
- newSeries.push(d2);
1067
- }
1068
-
1069
- drawChart(chart, newSeries, options);
1070
- };
1071
-
1072
- var renderBarChart = function (chart) {
1073
- renderColumnChart(chart, "bar");
1074
- };
1075
-
1076
- var renderAreaChart = function (chart) {
1077
- renderLineChart(chart, "areaspline");
988
+ chart.chart = new google.visualization.ScatterChart(chart.element);
989
+ resize(function () {
990
+ chart.chart.draw(data, options);
991
+ });
992
+ });
1078
993
  };
1079
994
 
1080
- return {
1081
- name: "highcharts",
1082
- renderLineChart: renderLineChart,
1083
- renderPieChart: renderPieChart,
1084
- renderColumnChart: renderColumnChart,
1085
- renderBarChart: renderBarChart,
1086
- renderAreaChart: renderAreaChart,
1087
- renderScatterChart: renderScatterChart
1088
- };
1089
- })();
1090
- adapters.push(HighchartsAdapter);
1091
- }
1092
- if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
1093
- GoogleChartsAdapter = (function () {
1094
- var google = window.google;
1095
-
1096
- var loaded = {};
1097
- var callbacks = [];
995
+ this.renderTimeline = function (chart) {
996
+ waitForLoaded("timeline", function () {
997
+ var chartOptions = {
998
+ legend: "none"
999
+ };
1098
1000
 
1099
- var runCallbacks = function () {
1100
- var cb, call;
1101
- for (var i = 0; i < callbacks.length; i++) {
1102
- cb = callbacks[i];
1103
- call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
1104
- if (call) {
1105
- cb.callback();
1106
- callbacks.splice(i, 1);
1107
- i--;
1001
+ if (chart.options.colors) {
1002
+ chartOptions.colors = chart.options.colors;
1108
1003
  }
1109
- }
1110
- };
1004
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1111
1005
 
1112
- var waitForLoaded = function (pack, callback) {
1113
- if (!callback) {
1114
- callback = pack;
1115
- pack = "corechart";
1116
- }
1006
+ var data = new google.visualization.DataTable();
1007
+ data.addColumn({type: "string", id: "Name"});
1008
+ data.addColumn({type: "date", id: "Start"});
1009
+ data.addColumn({type: "date", id: "End"});
1010
+ data.addRows(chart.data);
1117
1011
 
1118
- callbacks.push({pack: pack, callback: callback});
1012
+ chart.element.style.lineHeight = "normal";
1013
+ chart.chart = new google.visualization.Timeline(chart.element);
1119
1014
 
1120
- if (loaded[pack]) {
1121
- runCallbacks();
1122
- } else {
1123
- loaded[pack] = true;
1015
+ resize(function () {
1016
+ chart.chart.draw(data, options);
1017
+ });
1018
+ });
1019
+ };
1020
+ };
1124
1021
 
1125
- // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
1126
- var loadOptions = {
1127
- packages: [pack],
1128
- callback: runCallbacks
1129
- };
1130
- if (config.language) {
1131
- loadOptions.language = config.language;
1132
- }
1133
- if (pack === "corechart" && config.mapsApiKey) {
1134
- loadOptions.mapsApiKey = config.mapsApiKey;
1135
- }
1022
+ adapters.push(GoogleChartsAdapter);
1023
+ }
1024
+ if (!ChartjsAdapter && "Chart" in window) {
1025
+ ChartjsAdapter = new function () {
1026
+ var Chart = window.Chart;
1136
1027
 
1137
- if (window.google.setOnLoadCallback) {
1138
- google.load("visualization", "1", loadOptions);
1139
- } else {
1140
- google.charts.load("current", loadOptions);
1141
- }
1142
- }
1143
- };
1028
+ this.name = "chartjs";
1144
1029
 
1145
- // Set chart options
1146
- var defaultOptions = {
1147
- chartArea: {},
1148
- fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
1149
- pointSize: 6,
1150
- legend: {
1151
- textStyle: {
1152
- fontSize: 12,
1153
- color: "#444"
1154
- },
1155
- alignment: "center",
1156
- position: "right"
1157
- },
1158
- curveType: "function",
1159
- hAxis: {
1160
- textStyle: {
1161
- color: "#666",
1162
- fontSize: 12
1163
- },
1164
- titleTextStyle: {},
1165
- gridlines: {
1166
- color: "transparent"
1167
- },
1168
- baselineColor: "#ccc",
1169
- viewWindow: {}
1170
- },
1171
- vAxis: {
1172
- textStyle: {
1173
- color: "#666",
1174
- fontSize: 12
1175
- },
1176
- titleTextStyle: {},
1177
- baselineColor: "#ccc",
1178
- viewWindow: {}
1179
- },
1180
- tooltip: {
1181
- textStyle: {
1182
- color: "#666",
1183
- fontSize: 12
1184
- }
1030
+ var baseOptions = {
1031
+ maintainAspectRatio: false,
1032
+ animation: false,
1033
+ tooltips: {
1034
+ displayColors: false
1035
+ },
1036
+ legend: {},
1037
+ title: {fontSize: 20, fontColor: "#333"}
1038
+ };
1039
+
1040
+ var defaultOptions = {
1041
+ scales: {
1042
+ yAxes: [
1043
+ {
1044
+ ticks: {
1045
+ maxTicksLimit: 4
1046
+ },
1047
+ scaleLabel: {
1048
+ fontSize: 16,
1049
+ // fontStyle: "bold",
1050
+ fontColor: "#333"
1051
+ }
1052
+ }
1053
+ ],
1054
+ xAxes: [
1055
+ {
1056
+ gridLines: {
1057
+ drawOnChartArea: false
1058
+ },
1059
+ scaleLabel: {
1060
+ fontSize: 16,
1061
+ // fontStyle: "bold",
1062
+ fontColor: "#333"
1063
+ },
1064
+ time: {},
1065
+ ticks: {}
1066
+ }
1067
+ ]
1185
1068
  }
1186
1069
  };
1187
1070
 
1071
+ // http://there4.io/2012/05/02/google-chart-color-list/
1072
+ var defaultColors = [
1073
+ "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
1074
+ "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
1075
+ "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
1076
+ ];
1077
+
1188
1078
  var hideLegend = function (options, legend, hideLegend) {
1189
1079
  if (legend !== undefined) {
1190
- var position;
1191
- if (!legend) {
1192
- position = "none";
1193
- } else if (legend === true) {
1194
- position = "right";
1195
- } else {
1196
- position = legend;
1080
+ options.legend.display = !!legend;
1081
+ if (legend && legend !== true) {
1082
+ options.legend.position = legend;
1197
1083
  }
1198
- options.legend.position = position;
1199
1084
  } else if (hideLegend) {
1200
- options.legend.position = "none";
1085
+ options.legend.display = false;
1201
1086
  }
1202
1087
  };
1203
1088
 
1204
1089
  var setTitle = function (options, title) {
1205
- options.title = title;
1206
- options.titleTextStyle = {color: "#333", fontSize: "20px"};
1090
+ options.title.display = true;
1091
+ options.title.text = title;
1207
1092
  };
1208
1093
 
1209
1094
  var setMin = function (options, min) {
1210
- options.vAxis.viewWindow.min = min;
1095
+ if (min !== null) {
1096
+ options.scales.yAxes[0].ticks.min = toFloat(min);
1097
+ }
1211
1098
  };
1212
1099
 
1213
1100
  var setMax = function (options, max) {
1214
- options.vAxis.viewWindow.max = max;
1101
+ options.scales.yAxes[0].ticks.max = toFloat(max);
1215
1102
  };
1216
1103
 
1217
1104
  var setBarMin = function (options, min) {
1218
- options.hAxis.viewWindow.min = min;
1105
+ if (min !== null) {
1106
+ options.scales.xAxes[0].ticks.min = toFloat(min);
1107
+ }
1219
1108
  };
1220
1109
 
1221
1110
  var setBarMax = function (options, max) {
1222
- options.hAxis.viewWindow.max = max;
1111
+ options.scales.xAxes[0].ticks.max = toFloat(max);
1223
1112
  };
1224
1113
 
1225
1114
  var setStacked = function (options, stacked) {
1226
- options.isStacked = !!stacked;
1115
+ options.scales.xAxes[0].stacked = !!stacked;
1116
+ options.scales.yAxes[0].stacked = !!stacked;
1227
1117
  };
1228
1118
 
1229
1119
  var setXtitle = function (options, title) {
1230
- options.hAxis.title = title;
1231
- options.hAxis.titleTextStyle.italic = false;
1120
+ options.scales.xAxes[0].scaleLabel.display = true;
1121
+ options.scales.xAxes[0].scaleLabel.labelString = title;
1232
1122
  };
1233
1123
 
1234
1124
  var setYtitle = function (options, title) {
1235
- options.vAxis.title = title;
1236
- options.vAxis.titleTextStyle.italic = false;
1125
+ options.scales.yAxes[0].scaleLabel.display = true;
1126
+ options.scales.yAxes[0].scaleLabel.labelString = title;
1237
1127
  };
1238
1128
 
1239
- var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
1129
+ var drawChart = function(chart, type, data, options) {
1130
+ if (chart.chart) {
1131
+ chart.chart.destroy();
1132
+ } else {
1133
+ chart.element.innerHTML = "<canvas></canvas>";
1134
+ }
1240
1135
 
1241
- // cant use object as key
1242
- var createDataTable = function (series, columnType, xtype) {
1243
- var i, j, s, d, key, rows = [], sortedLabels = [];
1136
+ var ctx = chart.element.getElementsByTagName("CANVAS")[0];
1137
+ chart.chart = new Chart(ctx, {
1138
+ type: type,
1139
+ data: data,
1140
+ options: options
1141
+ });
1142
+ };
1143
+
1144
+ // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
1145
+ var addOpacity = function(hex, opacity) {
1146
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1147
+ return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
1148
+ };
1149
+
1150
+ var setLabelSize = function (chart, data, options) {
1151
+ var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
1152
+ if (maxLabelSize > 25) {
1153
+ maxLabelSize = 25;
1154
+ }
1155
+ options.scales.xAxes[0].ticks.callback = function (value) {
1156
+ value = toStr(value);
1157
+ if (value.length > maxLabelSize) {
1158
+ return value.substring(0, maxLabelSize - 2) + "...";
1159
+ } else {
1160
+ return value;
1161
+ }
1162
+ };
1163
+ };
1164
+
1165
+ var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
1166
+
1167
+ var createDataTable = function (chart, options, chartType) {
1168
+ var datasets = [];
1169
+ var labels = [];
1170
+
1171
+ var colors = chart.options.colors || defaultColors;
1172
+
1173
+ var day = true;
1174
+ var week = true;
1175
+ var dayOfWeek;
1176
+ var month = true;
1177
+ var year = true;
1178
+ var hour = true;
1179
+ var minute = true;
1180
+ var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
1181
+
1182
+ var series = chart.data;
1183
+
1184
+ var sortedLabels = [];
1185
+
1186
+ var i, j, s, d, key, rows = [];
1244
1187
  for (i = 0; i < series.length; i++) {
1245
1188
  s = series[i];
1246
1189
 
1247
1190
  for (j = 0; j < s.data.length; j++) {
1248
1191
  d = s.data[j];
1249
- key = (columnType === "datetime") ? d[0].getTime() : d[0];
1192
+ key = detectType ? d[0].getTime() : d[0];
1250
1193
  if (!rows[key]) {
1251
1194
  rows[key] = new Array(series.length);
1252
- sortedLabels.push(key);
1253
1195
  }
1254
1196
  rows[key][i] = toFloat(d[1]);
1197
+ if (sortedLabels.indexOf(key) === -1) {
1198
+ sortedLabels.push(key);
1199
+ }
1255
1200
  }
1256
1201
  }
1257
1202
 
1203
+ if (detectType || chart.options.xtype === "number") {
1204
+ sortedLabels.sort(sortByNumber);
1205
+ }
1206
+
1258
1207
  var rows2 = [];
1259
- var day = true;
1208
+ for (j = 0; j < series.length; j++) {
1209
+ rows2.push([]);
1210
+ }
1211
+
1260
1212
  var value;
1261
- for (j = 0; j < sortedLabels.length; j++) {
1262
- i = sortedLabels[j];
1263
- if (columnType === "datetime") {
1213
+ var k;
1214
+ for (k = 0; k < sortedLabels.length; k++) {
1215
+ i = sortedLabels[k];
1216
+ if (detectType) {
1264
1217
  value = new Date(toFloat(i));
1218
+ // TODO make this efficient
1265
1219
  day = day && isDay(value);
1266
- } else if (columnType === "number") {
1267
- value = toFloat(i);
1220
+ if (!dayOfWeek) {
1221
+ dayOfWeek = value.getDay();
1222
+ }
1223
+ week = week && isWeek(value, dayOfWeek);
1224
+ month = month && isMonth(value);
1225
+ year = year && isYear(value);
1226
+ hour = hour && isHour(value);
1227
+ minute = minute && isMinute(value);
1268
1228
  } else {
1269
1229
  value = i;
1270
1230
  }
1271
- rows2.push([value].concat(rows[i]));
1231
+ labels.push(value);
1232
+ for (j = 0; j < series.length; j++) {
1233
+ // Chart.js doesn't like undefined
1234
+ rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
1235
+ }
1272
1236
  }
1273
- if (columnType === "datetime") {
1274
- rows2.sort(sortByTime);
1275
- } else if (columnType === "number") {
1276
- rows2.sort(sortByNumberSeries);
1237
+
1238
+ for (i = 0; i < series.length; i++) {
1239
+ s = series[i];
1240
+
1241
+ var color = s.color || colors[i];
1242
+ var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
1243
+
1244
+ var dataset = {
1245
+ label: s.name,
1246
+ data: rows2[i],
1247
+ fill: chartType === "area",
1248
+ borderColor: color,
1249
+ backgroundColor: backgroundColor,
1250
+ pointBackgroundColor: color,
1251
+ borderWidth: 2
1252
+ };
1253
+
1254
+ if (s.stack) {
1255
+ dataset.stack = s.stack;
1256
+ }
1257
+
1258
+ // PATCH_BEGIN
1259
+ if (chart.options.y2 === true) {
1260
+ dataset.yAxisID = (s.y2 === true) ? 'y-axis-right' : 'y-axis-left';
1261
+ options.scales.yAxes = [
1262
+ { id: 'y-axis-left', position: 'left' },
1263
+ { id: 'y-axis-right', position: 'right' }
1264
+ ];
1265
+ }
1266
+ // PATCH_END
1267
+
1268
+ if (chart.options.curve === false) {
1269
+ dataset.lineTension = 0;
1270
+ }
1271
+
1272
+ if (chart.options.points === false) {
1273
+ dataset.pointRadius = 0;
1274
+ dataset.pointHitRadius = 5;
1275
+ }
1276
+
1277
+ datasets.push(merge(dataset, s.library || {}));
1277
1278
  }
1278
1279
 
1279
- if (xtype === "number") {
1280
- rows2.sort(sortByNumberSeries);
1280
+ if (detectType && labels.length > 0) {
1281
+ var minTime = labels[0].getTime();
1282
+ var maxTime = labels[0].getTime();
1283
+ for (i = 1; i < labels.length; i++) {
1284
+ value = labels[i].getTime();
1285
+ if (value < minTime) {
1286
+ minTime = value;
1287
+ }
1288
+ if (value > maxTime) {
1289
+ maxTime = value;
1290
+ }
1291
+ }
1292
+
1293
+ var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
1294
+
1295
+ if (!options.scales.xAxes[0].time.unit) {
1296
+ var step;
1297
+ if (year || timeDiff > 365 * 10) {
1298
+ options.scales.xAxes[0].time.unit = "year";
1299
+ step = 365;
1300
+ } else if (month || timeDiff > 30 * 10) {
1301
+ options.scales.xAxes[0].time.unit = "month";
1302
+ step = 30;
1303
+ } else if (day || timeDiff > 10) {
1304
+ options.scales.xAxes[0].time.unit = "day";
1305
+ step = 1;
1306
+ } else if (hour || timeDiff > 0.5) {
1307
+ options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
1308
+ options.scales.xAxes[0].time.unit = "hour";
1309
+ step = 1 / 24.0;
1310
+ } else if (minute) {
1311
+ options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
1312
+ options.scales.xAxes[0].time.unit = "minute";
1313
+ step = 1 / 24.0 / 60.0;
1314
+ }
1315
+
1316
+ if (step && timeDiff > 0) {
1317
+ var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
1318
+ if (week && step === 1) {
1319
+ unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
1320
+ }
1321
+ options.scales.xAxes[0].time.unitStepSize = unitStepSize;
1322
+ }
1323
+ }
1281
1324
 
1282
- for (i = 0; i < rows2.length; i++) {
1283
- rows2[i][0] = toStr(rows2[i][0]);
1325
+ if (!options.scales.xAxes[0].time.tooltipFormat) {
1326
+ if (day) {
1327
+ options.scales.xAxes[0].time.tooltipFormat = "ll";
1328
+ } else if (hour) {
1329
+ options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
1330
+ } else if (minute) {
1331
+ options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
1332
+ }
1284
1333
  }
1285
1334
  }
1286
1335
 
1287
- // create datatable
1288
- var data = new google.visualization.DataTable();
1289
- columnType = columnType === "datetime" && day ? "date" : columnType;
1290
- data.addColumn(columnType, "");
1291
- for (i = 0; i < series.length; i++) {
1292
- data.addColumn("number", series[i].name);
1293
- }
1294
- data.addRows(rows2);
1336
+ var data = {
1337
+ labels: labels,
1338
+ datasets: datasets
1339
+ };
1295
1340
 
1296
1341
  return data;
1297
1342
  };
1298
1343
 
1299
- var resize = function (callback) {
1300
- if (window.attachEvent) {
1301
- window.attachEvent("onresize", callback);
1302
- } else if (window.addEventListener) {
1303
- window.addEventListener("resize", callback, true);
1344
+ this.renderLineChart = function (chart, chartType) {
1345
+ if (chart.options.xtype === "number") {
1346
+ return self.renderScatterChart(chart, chartType, true);
1304
1347
  }
1305
- callback();
1306
- };
1307
1348
 
1308
- var drawChart = function(chart, type, data, options) {
1309
- if (chart.chart) {
1310
- chart.chart.clearChart();
1349
+ var chartOptions = {};
1350
+ if (chartType === "area") {
1351
+ // TODO fix area stacked
1352
+ // chartOptions.stacked = true;
1353
+ }
1354
+ // fix for https://github.com/chartjs/Chart.js/issues/2441
1355
+ if (!chart.options.max && allZeros(chart.data)) {
1356
+ chartOptions.max = 1;
1311
1357
  }
1312
1358
 
1313
- chart.chart = new type(chart.element);
1314
- resize(function () {
1315
- chart.chart.draw(data, options);
1316
- });
1317
- };
1318
-
1319
- var renderLineChart = function (chart) {
1320
- waitForLoaded(function () {
1321
- var chartOptions = {};
1322
-
1323
- if (chart.options.curve === false) {
1324
- chartOptions.curveType = "none";
1325
- }
1359
+ var options = jsOptions(chart, merge(chartOptions, chart.options));
1326
1360
 
1327
- if (chart.options.points === false) {
1328
- chartOptions.pointSize = 0;
1329
- }
1361
+ var data = createDataTable(chart, options, chartType || "line");
1330
1362
 
1331
- var options = jsOptions(chart, chart.options, chartOptions);
1332
- var columnType = chart.discrete ? "string" : "datetime";
1333
- if (chart.options.xtype === "number") {
1334
- columnType = "number";
1335
- }
1336
- var data = createDataTable(chart.data, columnType);
1363
+ options.scales.xAxes[0].type = chart.discrete ? "category" : "time";
1337
1364
 
1338
- drawChart(chart, google.visualization.LineChart, data, options);
1339
- });
1365
+ drawChart(chart, "line", data, options);
1340
1366
  };
1341
1367
 
1342
- var renderPieChart = function (chart) {
1343
- waitForLoaded(function () {
1344
- var chartOptions = {
1345
- chartArea: {
1346
- top: "10%",
1347
- height: "80%"
1348
- },
1349
- legend: {}
1350
- };
1351
- if (chart.options.colors) {
1352
- chartOptions.colors = chart.options.colors;
1353
- }
1354
- if (chart.options.donut) {
1355
- chartOptions.pieHole = 0.5;
1356
- }
1357
- if ("legend" in chart.options) {
1358
- hideLegend(chartOptions, chart.options.legend);
1359
- }
1360
- if (chart.options.title) {
1361
- setTitle(chartOptions, chart.options.title);
1362
- }
1363
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1368
+ this.renderPieChart = function (chart) {
1369
+ var options = merge({}, baseOptions);
1370
+ if (chart.options.donut) {
1371
+ options.cutoutPercentage = 50;
1372
+ }
1364
1373
 
1365
- var data = new google.visualization.DataTable();
1366
- data.addColumn("string", "");
1367
- data.addColumn("number", "Value");
1368
- data.addRows(chart.data);
1374
+ if ("legend" in chart.options) {
1375
+ hideLegend(options, chart.options.legend);
1376
+ }
1369
1377
 
1370
- drawChart(chart, google.visualization.PieChart, data, options);
1371
- });
1372
- };
1378
+ if (chart.options.title) {
1379
+ setTitle(options, chart.options.title);
1380
+ }
1373
1381
 
1374
- var renderColumnChart = function (chart) {
1375
- waitForLoaded(function () {
1376
- var options = jsOptions(chart, chart.options);
1377
- var data = createDataTable(chart.data, "string", chart.options.xtype);
1382
+ options = merge(options, chart.options.library || {});
1378
1383
 
1379
- drawChart(chart, google.visualization.ColumnChart, data, options);
1380
- });
1381
- };
1384
+ var labels = [];
1385
+ var values = [];
1386
+ for (var i = 0; i < chart.data.length; i++) {
1387
+ var point = chart.data[i];
1388
+ labels.push(point[0]);
1389
+ values.push(point[1]);
1390
+ }
1382
1391
 
1383
- var renderBarChart = function (chart) {
1384
- waitForLoaded(function () {
1385
- var chartOptions = {
1386
- hAxis: {
1387
- gridlines: {
1388
- color: "#ccc"
1389
- }
1392
+ var data = {
1393
+ labels: labels,
1394
+ datasets: [
1395
+ {
1396
+ data: values,
1397
+ backgroundColor: chart.options.colors || defaultColors
1390
1398
  }
1391
- };
1392
- var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
1393
- var data = createDataTable(chart.data, "string", chart.options.xtype);
1399
+ ]
1400
+ };
1394
1401
 
1395
- drawChart(chart, google.visualization.BarChart, data, options);
1396
- });
1402
+ drawChart(chart, "pie", data, options);
1397
1403
  };
1398
1404
 
1399
- var renderAreaChart = function (chart) {
1400
- waitForLoaded(function () {
1401
- var chartOptions = {
1402
- isStacked: true,
1403
- pointSize: 0,
1404
- areaOpacity: 0.5
1405
- };
1405
+ this.renderColumnChart = function (chart, chartType) {
1406
+ var options;
1407
+ if (chartType === "bar") {
1408
+ options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
1409
+ } else {
1410
+ options = jsOptions(chart, chart.options);
1411
+ }
1412
+ var data = createDataTable(chart, options, "column");
1413
+ setLabelSize(chart, data, options);
1414
+ drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
1415
+ };
1406
1416
 
1407
- var options = jsOptions(chart, chart.options, chartOptions);
1408
- var columnType = chart.discrete ? "string" : "datetime";
1409
- if (chart.options.xtype === "number") {
1410
- columnType = "number";
1411
- }
1412
- var data = createDataTable(chart.data, columnType);
1417
+ var self = this;
1413
1418
 
1414
- drawChart(chart, google.visualization.AreaChart, data, options);
1415
- });
1419
+ this.renderAreaChart = function (chart) {
1420
+ self.renderLineChart(chart, "area");
1416
1421
  };
1417
1422
 
1418
- var renderGeoChart = function (chart) {
1419
- waitForLoaded(function () {
1420
- var chartOptions = {
1421
- legend: "none",
1422
- colorAxis: {
1423
- colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
1424
- }
1425
- };
1426
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1423
+ this.renderBarChart = function (chart) {
1424
+ self.renderColumnChart(chart, "bar");
1425
+ };
1427
1426
 
1428
- var data = new google.visualization.DataTable();
1429
- data.addColumn("string", "");
1430
- data.addColumn("number", chart.options.label || "Value");
1431
- data.addRows(chart.data);
1427
+ this.renderScatterChart = function (chart, chartType, lineChart) {
1428
+ chartType = chartType || "line";
1432
1429
 
1433
- drawChart(chart, google.visualization.GeoChart, data, options);
1434
- });
1435
- };
1430
+ var options = jsOptions(chart, chart.options);
1436
1431
 
1437
- var renderScatterChart = function (chart) {
1438
- waitForLoaded(function () {
1439
- var chartOptions = {};
1440
- var options = jsOptions(chart, chart.options, chartOptions);
1432
+ var colors = chart.options.colors || defaultColors;
1441
1433
 
1442
- var series = chart.data, rows2 = [], i, j, data, d;
1443
- for (i = 0; i < series.length; i++) {
1444
- d = series[i].data;
1445
- for (j = 0; j < d.length; j++) {
1446
- var row = new Array(series.length + 1);
1447
- row[0] = d[j][0];
1448
- row[i + 1] = d[j][1];
1449
- rows2.push(row);
1434
+ var datasets = [];
1435
+ var series = chart.data;
1436
+ for (var i = 0; i < series.length; i++) {
1437
+ var s = series[i];
1438
+ var d = [];
1439
+ for (var j = 0; j < s.data.length; j++) {
1440
+ var point = {
1441
+ x: toFloat(s.data[j][0]),
1442
+ y: toFloat(s.data[j][1])
1443
+ };
1444
+ if (chartType === "bubble") {
1445
+ point.r = toFloat(s.data[j][2]);
1450
1446
  }
1447
+ d.push(point);
1451
1448
  }
1452
1449
 
1453
- data = new google.visualization.DataTable();
1454
- data.addColumn("number", "");
1455
- for (i = 0; i < series.length; i++) {
1456
- data.addColumn("number", series[i].name);
1457
- }
1458
- data.addRows(rows2);
1459
-
1460
- drawChart(chart, google.visualization.ScatterChart, data, options);
1461
- });
1462
- };
1450
+ var color = s.color || colors[i];
1451
+ var backgroundColor = chartType === "area" ? addOpacity(color, 0.5) : color;
1463
1452
 
1464
- var renderTimeline = function (chart) {
1465
- waitForLoaded("timeline", function () {
1466
- var chartOptions = {
1467
- legend: "none"
1468
- };
1453
+ datasets.push({
1454
+ label: s.name,
1455
+ showLine: lineChart || false,
1456
+ data: d,
1457
+ borderColor: color,
1458
+ backgroundColor: backgroundColor,
1459
+ pointBackgroundColor: color,
1460
+ fill: chartType === "area"
1461
+ })
1462
+ }
1469
1463
 
1470
- if (chart.options.colors) {
1471
- chartOptions.colors = chart.options.colors;
1472
- }
1473
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1464
+ if (chartType === "area") {
1465
+ chartType = "line";
1466
+ }
1474
1467
 
1475
- var data = new google.visualization.DataTable();
1476
- data.addColumn({type: "string", id: "Name"});
1477
- data.addColumn({type: "date", id: "Start"});
1478
- data.addColumn({type: "date", id: "End"});
1479
- data.addRows(chart.data);
1468
+ var data = {datasets: datasets};
1480
1469
 
1481
- chart.element.style.lineHeight = "normal";
1470
+ options.scales.xAxes[0].type = "linear";
1471
+ options.scales.xAxes[0].position = "bottom";
1482
1472
 
1483
- drawChart(chart, google.visualization.Timeline, data, options);
1484
- });
1473
+ drawChart(chart, chartType, data, options);
1485
1474
  };
1486
1475
 
1487
- return {
1488
- name: "google",
1489
- renderLineChart: renderLineChart,
1490
- renderPieChart: renderPieChart,
1491
- renderColumnChart: renderColumnChart,
1492
- renderBarChart: renderBarChart,
1493
- renderAreaChart: renderAreaChart,
1494
- renderScatterChart: renderScatterChart,
1495
- renderGeoChart: renderGeoChart,
1496
- renderTimeline: renderTimeline
1476
+ this.renderBubbleChart = function (chart) {
1477
+ this.renderScatterChart(chart, "bubble");
1497
1478
  };
1498
- })();
1479
+ };
1499
1480
 
1500
- adapters.push(GoogleChartsAdapter);
1481
+ adapters.unshift(ChartjsAdapter);
1501
1482
  }
1502
1483
  }
1503
1484
 
@@ -1634,13 +1615,13 @@
1634
1615
  function copySeries(series) {
1635
1616
  var newSeries = [], i, j;
1636
1617
  for (i = 0; i < series.length; i++) {
1637
- var copy = {};
1618
+ var copy = {}
1638
1619
  for (j in series[i]) {
1639
1620
  if (series[i].hasOwnProperty(j)) {
1640
1621
  copy[j] = series[i][j];
1641
1622
  }
1642
1623
  }
1643
- newSeries.push(copy);
1624
+ newSeries.push(copy)
1644
1625
  }
1645
1626
  return newSeries;
1646
1627
  }
@@ -1739,7 +1720,7 @@
1739
1720
  if (!processData) {
1740
1721
  processData = function (chart) {
1741
1722
  return chart.rawData;
1742
- };
1723
+ }
1743
1724
  }
1744
1725
 
1745
1726
  // getters
@@ -1801,7 +1782,7 @@
1801
1782
  } else {
1802
1783
  return null;
1803
1784
  }
1804
- };
1785
+ }
1805
1786
 
1806
1787
  Chartkick.charts[element.id] = chart;
1807
1788