ext_sprockets 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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