chartkick 2.2.5 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of chartkick might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +42 -0
- data/ISSUE_TEMPLATE.md +7 -0
- data/README.md +38 -2
- data/chartkick.gemspec +2 -3
- data/lib/chartkick/helper.rb +1 -1
- data/lib/chartkick/version.rb +1 -1
- data/test/chartkick_test.rb +14 -0
- data/{app → vendor}/assets/javascripts/chartkick.js +1006 -853
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c58fc2c0725fcf5226fd394c02d7e7a08eed251
|
4
|
+
data.tar.gz: 4809227124c7b7fa8bb3e1907859e65d7476746c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5cfd768e87a01679cb843a18365f226a9e7014ee942606a8cdab144c51b05e315d9be2fab068668aad1a55022ce9d67bad30254dd9e7445da7e0f634a38fb0b
|
7
|
+
data.tar.gz: d7430b45f2d189d6e711cb9eefbf5e4edc4939200bcc0ba3a813aed1da0e24f47436a38c8c8fc64c8c86dc958be4a71c65e823c2a61dd8dc2d23dba7d58fd7c1
|
data/CHANGELOG.md
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
First, thanks for wanting to contribute. You’re awesome! :heart:
|
4
|
+
|
5
|
+
## Questions
|
6
|
+
|
7
|
+
Use [Stack Overflow](https://stackoverflow.com/) with the tag `chartkick`.
|
8
|
+
|
9
|
+
## Feature Requests
|
10
|
+
|
11
|
+
Create an issue. Start the title with `[Idea]`.
|
12
|
+
|
13
|
+
## Issues
|
14
|
+
|
15
|
+
Think you’ve discovered an issue?
|
16
|
+
|
17
|
+
1. Search existing issues to see if it’s been reported.
|
18
|
+
2. Try the `master` branch to make sure it hasn’t been fixed.
|
19
|
+
|
20
|
+
```rb
|
21
|
+
gem "chartkick", github: "ankane/chartkick"
|
22
|
+
```
|
23
|
+
|
24
|
+
If the above steps don’t help, create an issue.
|
25
|
+
|
26
|
+
- Include the JavaScript rendered by Chartkick.
|
27
|
+
- For exceptions, include the complete backtrace.
|
28
|
+
|
29
|
+
## Pull Requests
|
30
|
+
|
31
|
+
Fork the project and create a pull request. A few tips:
|
32
|
+
|
33
|
+
- Keep changes to a minimum. If you have multiple features or fixes, submit multiple pull requests.
|
34
|
+
- Follow the existing style. The code should read like it’s written by a single person.
|
35
|
+
|
36
|
+
Feel free to open an issue to get feedback on your idea before spending too much time on it.
|
37
|
+
|
38
|
+
Also, note that we aren’t currently accepting new chart types.
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
This contributing guide is released under [CCO](https://creativecommons.org/publicdomain/zero/1.0/) (public domain). Use it for your own project without attribution.
|
data/ISSUE_TEMPLATE.md
ADDED
data/README.md
CHANGED
@@ -170,12 +170,48 @@ Specify legend position
|
|
170
170
|
<%= line_chart data, legend: "bottom" %>
|
171
171
|
```
|
172
172
|
|
173
|
+
Defer chart creation until after the page loads
|
174
|
+
|
175
|
+
```erb
|
176
|
+
<%= line_chart data, defer: true %>
|
177
|
+
```
|
178
|
+
|
173
179
|
Donut chart
|
174
180
|
|
175
181
|
```erb
|
176
182
|
<%= pie_chart data, donut: true %>
|
177
183
|
```
|
178
184
|
|
185
|
+
Prefix, useful for currency - *Chart.js, Highcharts*
|
186
|
+
|
187
|
+
```erb
|
188
|
+
<%= line_chart data, prefix: "$" %>
|
189
|
+
```
|
190
|
+
|
191
|
+
Suffix, useful for percentages - *Chart.js, Highcharts*
|
192
|
+
|
193
|
+
```erb
|
194
|
+
<%= line_chart data, suffix: "%" %>
|
195
|
+
```
|
196
|
+
|
197
|
+
Set a thousands separator - *Chart.js, Highcharts*
|
198
|
+
|
199
|
+
```erb
|
200
|
+
<%= line_chart data, thousands: "," %>
|
201
|
+
```
|
202
|
+
|
203
|
+
Set a decimal separator - *Chart.js, Highcharts*
|
204
|
+
|
205
|
+
```erb
|
206
|
+
<%= line_chart data, decimal: "," %>
|
207
|
+
```
|
208
|
+
|
209
|
+
Show a message when data is empty
|
210
|
+
|
211
|
+
```erb
|
212
|
+
<%= line_chart data, messages: {empty: "No data"} %>
|
213
|
+
```
|
214
|
+
|
179
215
|
Refresh data from a remote source every `n` seconds
|
180
216
|
|
181
217
|
```erb
|
@@ -314,7 +350,7 @@ Works with Highcharts 2.1+
|
|
314
350
|
|
315
351
|
### Sinatra and Padrino
|
316
352
|
|
317
|
-
You must include `chartkick.js` manually. [Download it here](https://raw.
|
353
|
+
You must include `chartkick.js` manually. [Download it here](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js)
|
318
354
|
|
319
355
|
```html
|
320
356
|
<script src="chartkick.js"></script>
|
@@ -335,7 +371,7 @@ after the JavaScript files and before your charts.
|
|
335
371
|
If more than one charting library is loaded, choose between them with:
|
336
372
|
|
337
373
|
```erb
|
338
|
-
<%= line_chart data, adapter: "google" %> <!-- or highcharts -->
|
374
|
+
<%= line_chart data, adapter: "google" %> <!-- or highcharts or chartjs -->
|
339
375
|
```
|
340
376
|
|
341
377
|
## JavaScript API
|
data/chartkick.gemspec
CHANGED
@@ -8,9 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Chartkick::VERSION
|
9
9
|
spec.authors = ["Andrew Kane"]
|
10
10
|
spec.email = ["andrew@chartkick.com"]
|
11
|
-
spec.description = "Create beautiful JavaScript charts with one line of Ruby"
|
12
11
|
spec.summary = "Create beautiful JavaScript charts with one line of Ruby"
|
13
|
-
spec.homepage = "
|
12
|
+
spec.homepage = "https://www.chartkick.com"
|
14
13
|
spec.license = "MIT"
|
15
14
|
|
16
15
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
@@ -18,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ["lib"]
|
20
19
|
|
21
|
-
spec.add_development_dependency "bundler"
|
20
|
+
spec.add_development_dependency "bundler"
|
22
21
|
spec.add_development_dependency "rake"
|
23
22
|
spec.add_development_dependency "minitest"
|
24
23
|
end
|
data/lib/chartkick/helper.rb
CHANGED
data/lib/chartkick/version.rb
CHANGED
data/test/chartkick_test.rb
CHANGED
@@ -26,4 +26,18 @@ class TestChartkick < Minitest::Test
|
|
26
26
|
line_chart @data, options
|
27
27
|
assert_equal "boom", options[:id]
|
28
28
|
end
|
29
|
+
|
30
|
+
def test_chartkick_deep_merge_different_inner_key
|
31
|
+
global_option = {library: {backgroundColor: "#eee"}}
|
32
|
+
local_option = {library: {title: "test"}}
|
33
|
+
correct_merge = {library: {backgroundColor: "#eee", title: "test"}}
|
34
|
+
assert_equal chartkick_deep_merge(global_option, local_option), correct_merge
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_chartkick_deep_merge_same_inner_key
|
38
|
+
global_option = {library: {backgroundColor: "#eee"}}
|
39
|
+
local_option = {library: {backgroundColor: "#fff"}}
|
40
|
+
correct_merge = {library: {backgroundColor: "#fff"}}
|
41
|
+
assert_equal chartkick_deep_merge(global_option, local_option), correct_merge
|
42
|
+
end
|
29
43
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
* Chartkick.js
|
3
3
|
* Create beautiful charts with one line of JavaScript
|
4
4
|
* https://github.com/ankane/chartkick.js
|
5
|
-
* v2.
|
5
|
+
* v2.3.0
|
6
6
|
* MIT License
|
7
7
|
*/
|
8
8
|
|
@@ -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]);
|
@@ -319,16 +319,19 @@
|
|
319
319
|
if (typeof n !== "object") {
|
320
320
|
if (typeof n === "number") {
|
321
321
|
n = new Date(n * 1000); // ms
|
322
|
-
} else
|
322
|
+
} else {
|
323
|
+
n = toStr(n);
|
324
|
+
if ((matches = n.match(DATE_PATTERN))) {
|
323
325
|
year = parseInt(matches[1], 10);
|
324
326
|
month = parseInt(matches[3], 10) - 1;
|
325
327
|
day = parseInt(matches[5], 10);
|
326
328
|
return new Date(year, month, day);
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
329
|
+
} else { // str
|
330
|
+
// try our best to get the str into iso8601
|
331
|
+
// TODO be smarter about this
|
332
|
+
var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
|
333
|
+
n = parseISO8601(str) || new Date(n);
|
334
|
+
}
|
332
335
|
}
|
333
336
|
}
|
334
337
|
return n;
|
@@ -360,1113 +363,1238 @@
|
|
360
363
|
}
|
361
364
|
|
362
365
|
function loadAdapters() {
|
363
|
-
if (!
|
364
|
-
|
365
|
-
var
|
366
|
+
if (!ChartjsAdapter && "Chart" in window) {
|
367
|
+
ChartjsAdapter = (function () {
|
368
|
+
var Chart = window.Chart;
|
366
369
|
|
367
|
-
|
370
|
+
var baseOptions = {
|
371
|
+
maintainAspectRatio: false,
|
372
|
+
animation: false,
|
373
|
+
tooltips: {
|
374
|
+
displayColors: false,
|
375
|
+
callbacks: {}
|
376
|
+
},
|
377
|
+
legend: {},
|
378
|
+
title: {fontSize: 20, fontColor: "#333"}
|
379
|
+
};
|
368
380
|
|
369
381
|
var defaultOptions = {
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
382
|
+
scales: {
|
383
|
+
yAxes: [
|
384
|
+
{
|
385
|
+
ticks: {
|
386
|
+
maxTicksLimit: 4
|
387
|
+
},
|
388
|
+
scaleLabel: {
|
389
|
+
fontSize: 16,
|
390
|
+
// fontStyle: "bold",
|
391
|
+
fontColor: "#333"
|
392
|
+
}
|
378
393
|
}
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
394
|
+
],
|
395
|
+
xAxes: [
|
396
|
+
{
|
397
|
+
gridLines: {
|
398
|
+
drawOnChartArea: false
|
399
|
+
},
|
400
|
+
scaleLabel: {
|
401
|
+
fontSize: 16,
|
402
|
+
// fontStyle: "bold",
|
403
|
+
fontColor: "#333"
|
404
|
+
},
|
405
|
+
time: {},
|
406
|
+
ticks: {}
|
388
407
|
}
|
389
|
-
|
390
|
-
},
|
391
|
-
title: {
|
392
|
-
text: null
|
393
|
-
},
|
394
|
-
credits: {
|
395
|
-
enabled: false
|
396
|
-
},
|
397
|
-
legend: {
|
398
|
-
borderWidth: 0
|
399
|
-
},
|
400
|
-
tooltip: {
|
401
|
-
style: {
|
402
|
-
fontSize: "12px"
|
403
|
-
}
|
404
|
-
},
|
405
|
-
plotOptions: {
|
406
|
-
areaspline: {},
|
407
|
-
series: {
|
408
|
-
marker: {}
|
409
|
-
}
|
408
|
+
]
|
410
409
|
}
|
411
410
|
};
|
412
411
|
|
412
|
+
// http://there4.io/2012/05/02/google-chart-color-list/
|
413
|
+
var defaultColors = [
|
414
|
+
"#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
|
415
|
+
"#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
|
416
|
+
"#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
|
417
|
+
];
|
418
|
+
|
413
419
|
var hideLegend = function (options, legend, hideLegend) {
|
414
420
|
if (legend !== undefined) {
|
415
|
-
options.legend.
|
421
|
+
options.legend.display = !!legend;
|
416
422
|
if (legend && legend !== true) {
|
417
|
-
|
418
|
-
options.legend.verticalAlign = legend;
|
419
|
-
} else {
|
420
|
-
options.legend.layout = "vertical";
|
421
|
-
options.legend.verticalAlign = "middle";
|
422
|
-
options.legend.align = legend;
|
423
|
-
}
|
423
|
+
options.legend.position = legend;
|
424
424
|
}
|
425
425
|
} else if (hideLegend) {
|
426
|
-
options.legend.
|
426
|
+
options.legend.display = false;
|
427
427
|
}
|
428
428
|
};
|
429
429
|
|
430
430
|
var setTitle = function (options, title) {
|
431
|
+
options.title.display = true;
|
431
432
|
options.title.text = title;
|
432
433
|
};
|
433
434
|
|
434
435
|
var setMin = function (options, min) {
|
435
|
-
|
436
|
+
if (min !== null) {
|
437
|
+
options.scales.yAxes[0].ticks.min = toFloat(min);
|
438
|
+
}
|
436
439
|
};
|
437
440
|
|
438
441
|
var setMax = function (options, max) {
|
439
|
-
options.
|
442
|
+
options.scales.yAxes[0].ticks.max = toFloat(max);
|
443
|
+
};
|
444
|
+
|
445
|
+
var setBarMin = function (options, min) {
|
446
|
+
if (min !== null) {
|
447
|
+
options.scales.xAxes[0].ticks.min = toFloat(min);
|
448
|
+
}
|
449
|
+
};
|
450
|
+
|
451
|
+
var setBarMax = function (options, max) {
|
452
|
+
options.scales.xAxes[0].ticks.max = toFloat(max);
|
440
453
|
};
|
441
454
|
|
442
455
|
var setStacked = function (options, stacked) {
|
443
|
-
options.
|
456
|
+
options.scales.xAxes[0].stacked = !!stacked;
|
457
|
+
options.scales.yAxes[0].stacked = !!stacked;
|
444
458
|
};
|
445
459
|
|
446
460
|
var setXtitle = function (options, title) {
|
447
|
-
options.
|
461
|
+
options.scales.xAxes[0].scaleLabel.display = true;
|
462
|
+
options.scales.xAxes[0].scaleLabel.labelString = title;
|
448
463
|
};
|
449
464
|
|
450
465
|
var setYtitle = function (options, title) {
|
451
|
-
options.
|
466
|
+
options.scales.yAxes[0].scaleLabel.display = true;
|
467
|
+
options.scales.yAxes[0].scaleLabel.labelString = title;
|
452
468
|
};
|
453
469
|
|
454
|
-
var
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
if (chartType === "areaspline") {
|
460
|
-
chartOptions = {
|
461
|
-
plotOptions: {
|
462
|
-
areaspline: {
|
463
|
-
stacking: "normal"
|
464
|
-
},
|
465
|
-
area: {
|
466
|
-
stacking: "normal"
|
467
|
-
},
|
468
|
-
series: {
|
469
|
-
marker: {
|
470
|
-
enabled: false
|
471
|
-
}
|
472
|
-
}
|
473
|
-
}
|
474
|
-
};
|
470
|
+
var drawChart = function(chart, type, data, options) {
|
471
|
+
if (chart.chart) {
|
472
|
+
chart.chart.destroy();
|
473
|
+
} else {
|
474
|
+
chart.element.innerHTML = "<canvas></canvas>";
|
475
475
|
}
|
476
476
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
477
|
+
var ctx = chart.element.getElementsByTagName("CANVAS")[0];
|
478
|
+
chart.chart = new Chart(ctx, {
|
479
|
+
type: type,
|
480
|
+
data: data,
|
481
|
+
options: options
|
482
|
+
});
|
483
|
+
};
|
484
484
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
485
|
+
// http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
|
486
|
+
var addOpacity = function(hex, opacity) {
|
487
|
+
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
488
|
+
return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
|
489
|
+
};
|
490
|
+
|
491
|
+
var setLabelSize = function (chart, data, options) {
|
492
|
+
var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
|
493
|
+
if (maxLabelSize > 25) {
|
494
|
+
maxLabelSize = 25;
|
489
495
|
}
|
490
|
-
options.
|
496
|
+
options.scales.xAxes[0].ticks.callback = function (value) {
|
497
|
+
value = toStr(value);
|
498
|
+
if (value.length > maxLabelSize) {
|
499
|
+
return value.substring(0, maxLabelSize - 2) + "...";
|
500
|
+
} else {
|
501
|
+
return value;
|
502
|
+
}
|
503
|
+
};
|
504
|
+
};
|
491
505
|
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
506
|
+
var setFormatOptions = function(chart, options, chartType) {
|
507
|
+
var formatOptions = {
|
508
|
+
prefix: chart.options.prefix,
|
509
|
+
suffix: chart.options.suffix,
|
510
|
+
thousands: chart.options.thousands,
|
511
|
+
decimal: chart.options.decimal
|
512
|
+
};
|
513
|
+
|
514
|
+
if (formatOptions.prefix || formatOptions.suffix || formatOptions.thousands || formatOptions.decimal) {
|
515
|
+
if (chartType !== "pie") {
|
516
|
+
var myAxes = options.scales.yAxes;
|
517
|
+
if (chartType === "bar") {
|
518
|
+
myAxes = options.scales.xAxes;
|
519
|
+
}
|
520
|
+
|
521
|
+
if (!myAxes[0].ticks.callback) {
|
522
|
+
myAxes[0].ticks.callback = function (value, index, values) {
|
523
|
+
return formatValue("", value, formatOptions);
|
524
|
+
};
|
498
525
|
}
|
499
526
|
}
|
500
|
-
|
501
|
-
if (
|
502
|
-
|
527
|
+
|
528
|
+
if (!options.tooltips.callbacks.label) {
|
529
|
+
if (chartType !== "pie") {
|
530
|
+
var valueLabel = chartType === "bar" ? "xLabel" : "yLabel";
|
531
|
+
options.tooltips.callbacks.label = function (tooltipItem, data) {
|
532
|
+
var label = data.datasets[tooltipItem.datasetIndex].label || '';
|
533
|
+
if (label) {
|
534
|
+
label += ': ';
|
535
|
+
}
|
536
|
+
return formatValue(label, tooltipItem[valueLabel], formatOptions);
|
537
|
+
};
|
538
|
+
} else {
|
539
|
+
// need to use separate label for pie charts
|
540
|
+
options.tooltips.callbacks.label = function (tooltipItem, data) {
|
541
|
+
var dataLabel = data.labels[tooltipItem.index];
|
542
|
+
var value = ': ';
|
543
|
+
|
544
|
+
if (isArray(dataLabel)) {
|
545
|
+
// show value on first line of multiline label
|
546
|
+
// need to clone because we are changing the value
|
547
|
+
dataLabel = dataLabel.slice();
|
548
|
+
dataLabel[0] += value;
|
549
|
+
} else {
|
550
|
+
dataLabel += value;
|
551
|
+
}
|
552
|
+
|
553
|
+
return formatValue(dataLabel, data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index], formatOptions);
|
554
|
+
};
|
555
|
+
}
|
503
556
|
}
|
504
557
|
}
|
505
|
-
options.series = series;
|
506
|
-
chart.chart = new Highcharts.Chart(options);
|
507
|
-
};
|
508
|
-
|
509
|
-
this.renderScatterChart = function (chart) {
|
510
|
-
var chartOptions = {};
|
511
|
-
var options = jsOptions(chart, chart.options, chartOptions);
|
512
|
-
options.chart.type = "scatter";
|
513
|
-
options.chart.renderTo = chart.element.id;
|
514
|
-
options.series = chart.data;
|
515
|
-
chart.chart = new Highcharts.Chart(options);
|
516
558
|
};
|
517
559
|
|
518
|
-
|
519
|
-
var chartOptions = merge(defaultOptions, {});
|
520
|
-
|
521
|
-
if (chart.options.colors) {
|
522
|
-
chartOptions.colors = chart.options.colors;
|
523
|
-
}
|
524
|
-
if (chart.options.donut) {
|
525
|
-
chartOptions.plotOptions = {pie: {innerSize: "50%"}};
|
526
|
-
}
|
560
|
+
var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
527
561
|
|
528
|
-
|
529
|
-
|
530
|
-
|
562
|
+
var createDataTable = function (chart, options, chartType) {
|
563
|
+
var datasets = [];
|
564
|
+
var labels = [];
|
531
565
|
|
532
|
-
|
533
|
-
setTitle(chartOptions, chart.options.title);
|
534
|
-
}
|
566
|
+
var colors = chart.options.colors || defaultColors;
|
535
567
|
|
536
|
-
var
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
};
|
568
|
+
var day = true;
|
569
|
+
var week = true;
|
570
|
+
var dayOfWeek;
|
571
|
+
var month = true;
|
572
|
+
var year = true;
|
573
|
+
var hour = true;
|
574
|
+
var minute = true;
|
575
|
+
var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
|
545
576
|
|
546
|
-
this.renderColumnChart = function (chart, chartType) {
|
547
|
-
chartType = chartType || "column";
|
548
577
|
var series = chart.data;
|
549
|
-
var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
|
550
|
-
options.chart.type = chartType;
|
551
|
-
options.chart.renderTo = chart.element.id;
|
552
578
|
|
579
|
+
var sortedLabels = [];
|
580
|
+
|
581
|
+
var i, j, s, d, key, rows = [];
|
553
582
|
for (i = 0; i < series.length; i++) {
|
554
583
|
s = series[i];
|
555
584
|
|
556
585
|
for (j = 0; j < s.data.length; j++) {
|
557
586
|
d = s.data[j];
|
558
|
-
|
559
|
-
|
560
|
-
|
587
|
+
key = detectType ? d[0].getTime() : d[0];
|
588
|
+
if (!rows[key]) {
|
589
|
+
rows[key] = new Array(series.length);
|
590
|
+
}
|
591
|
+
rows[key][i] = toFloat(d[1]);
|
592
|
+
if (sortedLabels.indexOf(key) === -1) {
|
593
|
+
sortedLabels.push(key);
|
561
594
|
}
|
562
|
-
rows[d[0]][i] = d[1];
|
563
595
|
}
|
564
596
|
}
|
565
597
|
|
566
|
-
if (chart.options.xtype === "number") {
|
567
|
-
|
598
|
+
if (detectType || chart.options.xtype === "number") {
|
599
|
+
sortedLabels.sort(sortByNumber);
|
568
600
|
}
|
569
601
|
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
d = [];
|
575
|
-
for (j = 0; j < categories.length; j++) {
|
576
|
-
d.push(rows[categories[j]][i] || 0);
|
577
|
-
}
|
602
|
+
var rows2 = [];
|
603
|
+
for (j = 0; j < series.length; j++) {
|
604
|
+
rows2.push([]);
|
605
|
+
}
|
578
606
|
|
579
|
-
|
580
|
-
|
581
|
-
|
607
|
+
var value;
|
608
|
+
var k;
|
609
|
+
for (k = 0; k < sortedLabels.length; k++) {
|
610
|
+
i = sortedLabels[k];
|
611
|
+
if (detectType) {
|
612
|
+
value = new Date(toFloat(i));
|
613
|
+
// TODO make this efficient
|
614
|
+
day = day && isDay(value);
|
615
|
+
if (!dayOfWeek) {
|
616
|
+
dayOfWeek = value.getDay();
|
617
|
+
}
|
618
|
+
week = week && isWeek(value, dayOfWeek);
|
619
|
+
month = month && isMonth(value);
|
620
|
+
year = year && isYear(value);
|
621
|
+
hour = hour && isHour(value);
|
622
|
+
minute = minute && isMinute(value);
|
623
|
+
} else {
|
624
|
+
value = i;
|
582
625
|
}
|
583
|
-
|
584
|
-
|
626
|
+
labels.push(value);
|
627
|
+
for (j = 0; j < series.length; j++) {
|
628
|
+
// Chart.js doesn't like undefined
|
629
|
+
rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
|
585
630
|
}
|
586
|
-
|
587
|
-
newSeries.push(d2);
|
588
631
|
}
|
589
|
-
options.series = newSeries;
|
590
|
-
|
591
|
-
chart.chart = new Highcharts.Chart(options);
|
592
|
-
};
|
593
632
|
|
594
|
-
|
633
|
+
for (i = 0; i < series.length; i++) {
|
634
|
+
s = series[i];
|
595
635
|
|
596
|
-
|
597
|
-
|
598
|
-
};
|
636
|
+
var color = s.color || colors[i];
|
637
|
+
var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
|
599
638
|
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
639
|
+
var dataset = {
|
640
|
+
label: s.name,
|
641
|
+
data: rows2[i],
|
642
|
+
fill: chartType === "area",
|
643
|
+
borderColor: color,
|
644
|
+
backgroundColor: backgroundColor,
|
645
|
+
pointBackgroundColor: color,
|
646
|
+
borderWidth: 2
|
647
|
+
};
|
609
648
|
|
610
|
-
|
649
|
+
if (s.stack) {
|
650
|
+
dataset.stack = s.stack;
|
651
|
+
}
|
611
652
|
|
612
|
-
|
613
|
-
|
653
|
+
if (chart.options.curve === false) {
|
654
|
+
dataset.lineTension = 0;
|
655
|
+
}
|
614
656
|
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
cb = callbacks[i];
|
619
|
-
call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
|
620
|
-
if (call) {
|
621
|
-
cb.callback();
|
622
|
-
callbacks.splice(i, 1);
|
623
|
-
i--;
|
657
|
+
if (chart.options.points === false) {
|
658
|
+
dataset.pointRadius = 0;
|
659
|
+
dataset.pointHitRadius = 5;
|
624
660
|
}
|
625
|
-
}
|
626
|
-
};
|
627
661
|
|
628
|
-
|
629
|
-
if (!callback) {
|
630
|
-
callback = pack;
|
631
|
-
pack = "corechart";
|
662
|
+
datasets.push(merge(dataset, s.library || {}));
|
632
663
|
}
|
633
664
|
|
634
|
-
|
665
|
+
if (detectType && labels.length > 0) {
|
666
|
+
var minTime = labels[0].getTime();
|
667
|
+
var maxTime = labels[0].getTime();
|
668
|
+
for (i = 1; i < labels.length; i++) {
|
669
|
+
value = labels[i].getTime();
|
670
|
+
if (value < minTime) {
|
671
|
+
minTime = value;
|
672
|
+
}
|
673
|
+
if (value > maxTime) {
|
674
|
+
maxTime = value;
|
675
|
+
}
|
676
|
+
}
|
635
677
|
|
636
|
-
|
637
|
-
runCallbacks();
|
638
|
-
} else {
|
639
|
-
loaded[pack] = true;
|
678
|
+
var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
|
640
679
|
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
680
|
+
if (!options.scales.xAxes[0].time.unit) {
|
681
|
+
var step;
|
682
|
+
if (year || timeDiff > 365 * 10) {
|
683
|
+
options.scales.xAxes[0].time.unit = "year";
|
684
|
+
step = 365;
|
685
|
+
} else if (month || timeDiff > 30 * 10) {
|
686
|
+
options.scales.xAxes[0].time.unit = "month";
|
687
|
+
step = 30;
|
688
|
+
} else if (day || timeDiff > 10) {
|
689
|
+
options.scales.xAxes[0].time.unit = "day";
|
690
|
+
step = 1;
|
691
|
+
} else if (hour || timeDiff > 0.5) {
|
692
|
+
options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
|
693
|
+
options.scales.xAxes[0].time.unit = "hour";
|
694
|
+
step = 1 / 24.0;
|
695
|
+
} else if (minute) {
|
696
|
+
options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
|
697
|
+
options.scales.xAxes[0].time.unit = "minute";
|
698
|
+
step = 1 / 24.0 / 60.0;
|
699
|
+
}
|
700
|
+
|
701
|
+
if (step && timeDiff > 0) {
|
702
|
+
var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
|
703
|
+
if (week && step === 1) {
|
704
|
+
unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
|
705
|
+
}
|
706
|
+
options.scales.xAxes[0].time.unitStepSize = unitStepSize;
|
707
|
+
}
|
651
708
|
}
|
652
709
|
|
653
|
-
if (
|
654
|
-
|
655
|
-
|
656
|
-
|
710
|
+
if (!options.scales.xAxes[0].time.tooltipFormat) {
|
711
|
+
if (day) {
|
712
|
+
options.scales.xAxes[0].time.tooltipFormat = "ll";
|
713
|
+
} else if (hour) {
|
714
|
+
options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
|
715
|
+
} else if (minute) {
|
716
|
+
options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
|
717
|
+
}
|
657
718
|
}
|
658
719
|
}
|
720
|
+
|
721
|
+
var data = {
|
722
|
+
labels: labels,
|
723
|
+
datasets: datasets
|
724
|
+
};
|
725
|
+
|
726
|
+
return data;
|
659
727
|
};
|
660
728
|
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
|
665
|
-
pointSize: 6,
|
666
|
-
legend: {
|
667
|
-
textStyle: {
|
668
|
-
fontSize: 12,
|
669
|
-
color: "#444"
|
670
|
-
},
|
671
|
-
alignment: "center",
|
672
|
-
position: "right"
|
673
|
-
},
|
674
|
-
curveType: "function",
|
675
|
-
hAxis: {
|
676
|
-
textStyle: {
|
677
|
-
color: "#666",
|
678
|
-
fontSize: 12
|
679
|
-
},
|
680
|
-
titleTextStyle: {},
|
681
|
-
gridlines: {
|
682
|
-
color: "transparent"
|
683
|
-
},
|
684
|
-
baselineColor: "#ccc",
|
685
|
-
viewWindow: {}
|
686
|
-
},
|
687
|
-
vAxis: {
|
688
|
-
textStyle: {
|
689
|
-
color: "#666",
|
690
|
-
fontSize: 12
|
691
|
-
},
|
692
|
-
titleTextStyle: {},
|
693
|
-
baselineColor: "#ccc",
|
694
|
-
viewWindow: {}
|
695
|
-
},
|
696
|
-
tooltip: {
|
697
|
-
textStyle: {
|
698
|
-
color: "#666",
|
699
|
-
fontSize: 12
|
700
|
-
}
|
729
|
+
var renderLineChart = function (chart, chartType) {
|
730
|
+
if (chart.options.xtype === "number") {
|
731
|
+
return renderScatterChart(chart, chartType, true);
|
701
732
|
}
|
702
|
-
};
|
703
733
|
|
704
|
-
|
705
|
-
if (
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
position = legend;
|
713
|
-
}
|
714
|
-
options.legend.position = position;
|
715
|
-
} else if (hideLegend) {
|
716
|
-
options.legend.position = "none";
|
734
|
+
var chartOptions = {};
|
735
|
+
if (chartType === "area") {
|
736
|
+
// TODO fix area stacked
|
737
|
+
// chartOptions.stacked = true;
|
738
|
+
}
|
739
|
+
// fix for https://github.com/chartjs/Chart.js/issues/2441
|
740
|
+
if (!chart.options.max && allZeros(chart.data)) {
|
741
|
+
chartOptions.max = 1;
|
717
742
|
}
|
718
|
-
};
|
719
743
|
|
720
|
-
|
721
|
-
options
|
722
|
-
options.titleTextStyle = {color: "#333", fontSize: "20px"};
|
723
|
-
};
|
744
|
+
var options = jsOptions(chart, merge(chartOptions, chart.options));
|
745
|
+
setFormatOptions(chart, options, chartType);
|
724
746
|
|
725
|
-
|
726
|
-
options.vAxis.viewWindow.min = min;
|
727
|
-
};
|
747
|
+
var data = createDataTable(chart, options, chartType || "line");
|
728
748
|
|
729
|
-
|
730
|
-
|
749
|
+
options.scales.xAxes[0].type = chart.discrete ? "category" : "time";
|
750
|
+
|
751
|
+
drawChart(chart, "line", data, options);
|
731
752
|
};
|
732
753
|
|
733
|
-
var
|
734
|
-
options
|
735
|
-
|
754
|
+
var renderPieChart = function (chart) {
|
755
|
+
var options = merge({}, baseOptions);
|
756
|
+
if (chart.options.donut) {
|
757
|
+
options.cutoutPercentage = 50;
|
758
|
+
}
|
736
759
|
|
737
|
-
|
738
|
-
|
739
|
-
|
760
|
+
if ("legend" in chart.options) {
|
761
|
+
hideLegend(options, chart.options.legend);
|
762
|
+
}
|
740
763
|
|
741
|
-
|
742
|
-
|
764
|
+
if (chart.options.title) {
|
765
|
+
setTitle(options, chart.options.title);
|
766
|
+
}
|
767
|
+
|
768
|
+
options = merge(options, chart.options.library || {});
|
769
|
+
setFormatOptions(chart, options, "pie");
|
770
|
+
|
771
|
+
var labels = [];
|
772
|
+
var values = [];
|
773
|
+
for (var i = 0; i < chart.data.length; i++) {
|
774
|
+
var point = chart.data[i];
|
775
|
+
labels.push(point[0]);
|
776
|
+
values.push(point[1]);
|
777
|
+
}
|
778
|
+
|
779
|
+
var data = {
|
780
|
+
labels: labels,
|
781
|
+
datasets: [
|
782
|
+
{
|
783
|
+
data: values,
|
784
|
+
backgroundColor: chart.options.colors || defaultColors
|
785
|
+
}
|
786
|
+
]
|
787
|
+
};
|
788
|
+
|
789
|
+
drawChart(chart, "pie", data, options);
|
743
790
|
};
|
744
791
|
|
745
|
-
var
|
746
|
-
options
|
747
|
-
|
792
|
+
var renderColumnChart = function (chart, chartType) {
|
793
|
+
var options;
|
794
|
+
if (chartType === "bar") {
|
795
|
+
options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
|
796
|
+
} else {
|
797
|
+
options = jsOptions(chart, chart.options);
|
798
|
+
}
|
799
|
+
setFormatOptions(chart, options, chartType);
|
800
|
+
var data = createDataTable(chart, options, "column");
|
801
|
+
if (chartType !== "bar") {
|
802
|
+
setLabelSize(chart, data, options);
|
803
|
+
}
|
804
|
+
drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
|
748
805
|
};
|
749
806
|
|
750
|
-
var
|
751
|
-
|
752
|
-
options.vAxis.titleTextStyle.italic = false;
|
807
|
+
var renderAreaChart = function (chart) {
|
808
|
+
renderLineChart(chart, "area");
|
753
809
|
};
|
754
810
|
|
755
|
-
var
|
811
|
+
var renderBarChart = function (chart) {
|
812
|
+
renderColumnChart(chart, "bar");
|
813
|
+
};
|
756
814
|
|
757
|
-
|
758
|
-
|
759
|
-
var i, j, s, d, key, rows = [], sortedLabels = [];
|
760
|
-
for (i = 0; i < series.length; i++) {
|
761
|
-
s = series[i];
|
815
|
+
var renderScatterChart = function (chart, chartType, lineChart) {
|
816
|
+
chartType = chartType || "line";
|
762
817
|
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
if (!rows[key]) {
|
767
|
-
rows[key] = new Array(series.length);
|
768
|
-
sortedLabels.push(key);
|
769
|
-
}
|
770
|
-
rows[key][i] = toFloat(d[1]);
|
771
|
-
}
|
818
|
+
var options = jsOptions(chart, chart.options);
|
819
|
+
if (!lineChart) {
|
820
|
+
setFormatOptions(chart, options, chartType);
|
772
821
|
}
|
773
822
|
|
774
|
-
var
|
775
|
-
|
776
|
-
var
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
823
|
+
var colors = chart.options.colors || defaultColors;
|
824
|
+
|
825
|
+
var datasets = [];
|
826
|
+
var series = chart.data;
|
827
|
+
for (var i = 0; i < series.length; i++) {
|
828
|
+
var s = series[i];
|
829
|
+
var d = [];
|
830
|
+
for (var j = 0; j < s.data.length; j++) {
|
831
|
+
var point = {
|
832
|
+
x: toFloat(s.data[j][0]),
|
833
|
+
y: toFloat(s.data[j][1])
|
834
|
+
};
|
835
|
+
if (chartType === "bubble") {
|
836
|
+
point.r = toFloat(s.data[j][2]);
|
837
|
+
}
|
838
|
+
d.push(point);
|
786
839
|
}
|
787
|
-
rows2.push([value].concat(rows[i]));
|
788
|
-
}
|
789
|
-
if (columnType === "datetime") {
|
790
|
-
rows2.sort(sortByTime);
|
791
|
-
} else if (columnType === "number") {
|
792
|
-
rows2.sort(sortByNumberSeries);
|
793
|
-
}
|
794
840
|
|
795
|
-
|
796
|
-
|
841
|
+
var color = s.color || colors[i];
|
842
|
+
var backgroundColor = chartType === "area" ? addOpacity(color, 0.5) : color;
|
797
843
|
|
798
|
-
|
799
|
-
|
800
|
-
|
844
|
+
datasets.push({
|
845
|
+
label: s.name,
|
846
|
+
showLine: lineChart || false,
|
847
|
+
data: d,
|
848
|
+
borderColor: color,
|
849
|
+
backgroundColor: backgroundColor,
|
850
|
+
pointBackgroundColor: color,
|
851
|
+
fill: chartType === "area"
|
852
|
+
});
|
801
853
|
}
|
802
854
|
|
803
|
-
|
804
|
-
|
805
|
-
columnType = columnType === "datetime" && day ? "date" : columnType;
|
806
|
-
data.addColumn(columnType, "");
|
807
|
-
for (i = 0; i < series.length; i++) {
|
808
|
-
data.addColumn("number", series[i].name);
|
855
|
+
if (chartType === "area") {
|
856
|
+
chartType = "line";
|
809
857
|
}
|
810
|
-
data.addRows(rows2);
|
811
858
|
|
812
|
-
|
859
|
+
var data = {datasets: datasets};
|
860
|
+
|
861
|
+
options.scales.xAxes[0].type = "linear";
|
862
|
+
options.scales.xAxes[0].position = "bottom";
|
863
|
+
|
864
|
+
drawChart(chart, chartType, data, options);
|
813
865
|
};
|
814
866
|
|
815
|
-
var
|
816
|
-
|
817
|
-
window.attachEvent("onresize", callback);
|
818
|
-
} else if (window.addEventListener) {
|
819
|
-
window.addEventListener("resize", callback, true);
|
820
|
-
}
|
821
|
-
callback();
|
867
|
+
var renderBubbleChart = function (chart) {
|
868
|
+
renderScatterChart(chart, "bubble");
|
822
869
|
};
|
823
870
|
|
824
|
-
|
825
|
-
|
826
|
-
|
871
|
+
return {
|
872
|
+
name: "chartjs",
|
873
|
+
renderLineChart: renderLineChart,
|
874
|
+
renderPieChart: renderPieChart,
|
875
|
+
renderColumnChart: renderColumnChart,
|
876
|
+
renderBarChart: renderBarChart,
|
877
|
+
renderAreaChart: renderAreaChart,
|
878
|
+
renderScatterChart: renderScatterChart,
|
879
|
+
renderBubbleChart: renderBubbleChart
|
880
|
+
};
|
881
|
+
})();
|
827
882
|
|
828
|
-
|
829
|
-
|
830
|
-
}
|
883
|
+
adapters.push(ChartjsAdapter);
|
884
|
+
}
|
831
885
|
|
832
|
-
|
833
|
-
|
834
|
-
|
886
|
+
if (!HighchartsAdapter && "Highcharts" in window) {
|
887
|
+
HighchartsAdapter = (function () {
|
888
|
+
var Highcharts = window.Highcharts;
|
835
889
|
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
890
|
+
var defaultOptions = {
|
891
|
+
chart: {},
|
892
|
+
xAxis: {
|
893
|
+
title: {
|
894
|
+
text: null
|
895
|
+
},
|
896
|
+
labels: {
|
897
|
+
style: {
|
898
|
+
fontSize: "12px"
|
899
|
+
}
|
840
900
|
}
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
}
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
waitForLoaded(function () {
|
851
|
-
var chartOptions = {
|
852
|
-
chartArea: {
|
853
|
-
top: "10%",
|
854
|
-
height: "80%"
|
855
|
-
},
|
856
|
-
legend: {}
|
857
|
-
};
|
858
|
-
if (chart.options.colors) {
|
859
|
-
chartOptions.colors = chart.options.colors;
|
901
|
+
},
|
902
|
+
yAxis: {
|
903
|
+
title: {
|
904
|
+
text: null
|
905
|
+
},
|
906
|
+
labels: {
|
907
|
+
style: {
|
908
|
+
fontSize: "12px"
|
909
|
+
}
|
860
910
|
}
|
861
|
-
|
862
|
-
|
911
|
+
},
|
912
|
+
title: {
|
913
|
+
text: null
|
914
|
+
},
|
915
|
+
credits: {
|
916
|
+
enabled: false
|
917
|
+
},
|
918
|
+
legend: {
|
919
|
+
borderWidth: 0
|
920
|
+
},
|
921
|
+
tooltip: {
|
922
|
+
style: {
|
923
|
+
fontSize: "12px"
|
863
924
|
}
|
864
|
-
|
865
|
-
|
925
|
+
},
|
926
|
+
plotOptions: {
|
927
|
+
areaspline: {},
|
928
|
+
series: {
|
929
|
+
marker: {}
|
866
930
|
}
|
867
|
-
|
868
|
-
|
931
|
+
}
|
932
|
+
};
|
933
|
+
|
934
|
+
var hideLegend = function (options, legend, hideLegend) {
|
935
|
+
if (legend !== undefined) {
|
936
|
+
options.legend.enabled = !!legend;
|
937
|
+
if (legend && legend !== true) {
|
938
|
+
if (legend === "top" || legend === "bottom") {
|
939
|
+
options.legend.verticalAlign = legend;
|
940
|
+
} else {
|
941
|
+
options.legend.layout = "vertical";
|
942
|
+
options.legend.verticalAlign = "middle";
|
943
|
+
options.legend.align = legend;
|
944
|
+
}
|
869
945
|
}
|
870
|
-
|
946
|
+
} else if (hideLegend) {
|
947
|
+
options.legend.enabled = false;
|
948
|
+
}
|
949
|
+
};
|
871
950
|
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
data.addRows(chart.data);
|
951
|
+
var setTitle = function (options, title) {
|
952
|
+
options.title.text = title;
|
953
|
+
};
|
876
954
|
|
877
|
-
|
878
|
-
|
879
|
-
chart.chart.draw(data, options);
|
880
|
-
});
|
881
|
-
});
|
955
|
+
var setMin = function (options, min) {
|
956
|
+
options.yAxis.min = min;
|
882
957
|
};
|
883
958
|
|
884
|
-
|
885
|
-
|
886
|
-
var options = jsOptions(chart, chart.options);
|
887
|
-
var data = createDataTable(chart.data, "string", chart.options.xtype);
|
888
|
-
chart.chart = new google.visualization.ColumnChart(chart.element);
|
889
|
-
resize(function () {
|
890
|
-
chart.chart.draw(data, options);
|
891
|
-
});
|
892
|
-
});
|
959
|
+
var setMax = function (options, max) {
|
960
|
+
options.yAxis.max = max;
|
893
961
|
};
|
894
962
|
|
895
|
-
|
896
|
-
|
897
|
-
var chartOptions = {
|
898
|
-
hAxis: {
|
899
|
-
gridlines: {
|
900
|
-
color: "#ccc"
|
901
|
-
}
|
902
|
-
}
|
903
|
-
};
|
904
|
-
var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
|
905
|
-
var data = createDataTable(chart.data, "string", chart.options.xtype);
|
906
|
-
chart.chart = new google.visualization.BarChart(chart.element);
|
907
|
-
resize(function () {
|
908
|
-
chart.chart.draw(data, options);
|
909
|
-
});
|
910
|
-
});
|
963
|
+
var setStacked = function (options, stacked) {
|
964
|
+
options.plotOptions.series.stacking = stacked ? "normal" : null;
|
911
965
|
};
|
912
966
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
isStacked: true,
|
917
|
-
pointSize: 0,
|
918
|
-
areaOpacity: 0.5
|
919
|
-
};
|
967
|
+
var setXtitle = function (options, title) {
|
968
|
+
options.xAxis.title.text = title;
|
969
|
+
};
|
920
970
|
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
971
|
+
var setYtitle = function (options, title) {
|
972
|
+
options.yAxis.title.text = title;
|
973
|
+
};
|
974
|
+
|
975
|
+
var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
976
|
+
|
977
|
+
var drawChart = function(chart, data, options) {
|
978
|
+
if (chart.chart) {
|
979
|
+
chart.chart.destroy();
|
980
|
+
}
|
981
|
+
|
982
|
+
options.chart.renderTo = chart.element.id;
|
983
|
+
options.series = data;
|
984
|
+
chart.chart = new Highcharts.Chart(options);
|
985
|
+
};
|
986
|
+
|
987
|
+
var setFormatOptions = function(chart, options, chartType) {
|
988
|
+
var formatOptions = {
|
989
|
+
prefix: chart.options.prefix,
|
990
|
+
suffix: chart.options.suffix,
|
991
|
+
thousands: chart.options.thousands,
|
992
|
+
decimal: chart.options.decimal
|
993
|
+
};
|
994
|
+
|
995
|
+
if (formatOptions.prefix || formatOptions.suffix || formatOptions.thousands || formatOptions.decimal) {
|
996
|
+
if (chartType !== "pie" && !options.yAxis.labels.formatter) {
|
997
|
+
options.yAxis.labels.formatter = function () {
|
998
|
+
return formatValue("", this.value, formatOptions);
|
999
|
+
};
|
925
1000
|
}
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
1001
|
+
|
1002
|
+
if (!options.tooltip.pointFormatter) {
|
1003
|
+
options.tooltip.pointFormatter = function () {
|
1004
|
+
return '<span style="color:' + this.color + '>\u25CF</span> ' + formatValue(this.series.name + ': <b>', this.y, formatOptions) + '</b><br/>';
|
1005
|
+
};
|
1006
|
+
}
|
1007
|
+
}
|
932
1008
|
};
|
933
1009
|
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
1010
|
+
var renderLineChart = function (chart, chartType) {
|
1011
|
+
chartType = chartType || "spline";
|
1012
|
+
var chartOptions = {};
|
1013
|
+
if (chartType === "areaspline") {
|
1014
|
+
chartOptions = {
|
1015
|
+
plotOptions: {
|
1016
|
+
areaspline: {
|
1017
|
+
stacking: "normal"
|
1018
|
+
},
|
1019
|
+
area: {
|
1020
|
+
stacking: "normal"
|
1021
|
+
},
|
1022
|
+
series: {
|
1023
|
+
marker: {
|
1024
|
+
enabled: false
|
1025
|
+
}
|
1026
|
+
}
|
940
1027
|
}
|
941
1028
|
};
|
942
|
-
|
1029
|
+
}
|
943
1030
|
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
1031
|
+
if (chart.options.curve === false) {
|
1032
|
+
if (chartType === "areaspline") {
|
1033
|
+
chartType = "area";
|
1034
|
+
} else if (chartType === "spline") {
|
1035
|
+
chartType = "line";
|
1036
|
+
}
|
1037
|
+
}
|
948
1038
|
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
}
|
1039
|
+
var options = jsOptions(chart, chart.options, chartOptions), data, i, j;
|
1040
|
+
options.xAxis.type = chart.discrete ? "category" : "datetime";
|
1041
|
+
if (!options.chart.type) {
|
1042
|
+
options.chart.type = chartType;
|
1043
|
+
}
|
1044
|
+
setFormatOptions(chart, options, chartType);
|
1045
|
+
|
1046
|
+
var series = chart.data;
|
1047
|
+
for (i = 0; i < series.length; i++) {
|
1048
|
+
data = series[i].data;
|
1049
|
+
if (!chart.discrete) {
|
1050
|
+
for (j = 0; j < data.length; j++) {
|
1051
|
+
data[j][0] = data[j][0].getTime();
|
1052
|
+
}
|
1053
|
+
}
|
1054
|
+
series[i].marker = {symbol: "circle"};
|
1055
|
+
if (chart.options.points === false) {
|
1056
|
+
series[i].marker.enabled = false;
|
1057
|
+
}
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
drawChart(chart, series, options);
|
954
1061
|
};
|
955
1062
|
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
1063
|
+
var renderScatterChart = function (chart) {
|
1064
|
+
var options = jsOptions(chart, chart.options, {});
|
1065
|
+
options.chart.type = "scatter";
|
1066
|
+
drawChart(chart, chart.data, options);
|
1067
|
+
};
|
960
1068
|
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
1069
|
+
var renderPieChart = function (chart) {
|
1070
|
+
var chartOptions = merge(defaultOptions, {});
|
1071
|
+
|
1072
|
+
if (chart.options.colors) {
|
1073
|
+
chartOptions.colors = chart.options.colors;
|
1074
|
+
}
|
1075
|
+
if (chart.options.donut) {
|
1076
|
+
chartOptions.plotOptions = {pie: {innerSize: "50%"}};
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
if ("legend" in chart.options) {
|
1080
|
+
hideLegend(chartOptions, chart.options.legend);
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
if (chart.options.title) {
|
1084
|
+
setTitle(chartOptions, chart.options.title);
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
var options = merge(chartOptions, chart.options.library || {});
|
1088
|
+
setFormatOptions(chart, options, "pie");
|
1089
|
+
var series = [{
|
1090
|
+
type: "pie",
|
1091
|
+
name: chart.options.label || "Value",
|
1092
|
+
data: chart.data
|
1093
|
+
}];
|
1094
|
+
|
1095
|
+
drawChart(chart, series, options);
|
1096
|
+
};
|
1097
|
+
|
1098
|
+
var renderColumnChart = function (chart, chartType) {
|
1099
|
+
chartType = chartType || "column";
|
1100
|
+
var series = chart.data;
|
1101
|
+
var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
|
1102
|
+
options.chart.type = chartType;
|
1103
|
+
setFormatOptions(chart, options, chartType);
|
1104
|
+
|
1105
|
+
for (i = 0; i < series.length; i++) {
|
1106
|
+
s = series[i];
|
1107
|
+
|
1108
|
+
for (j = 0; j < s.data.length; j++) {
|
1109
|
+
d = s.data[j];
|
1110
|
+
if (!rows[d[0]]) {
|
1111
|
+
rows[d[0]] = new Array(series.length);
|
1112
|
+
categories.push(d[0]);
|
969
1113
|
}
|
1114
|
+
rows[d[0]][i] = d[1];
|
970
1115
|
}
|
1116
|
+
}
|
971
1117
|
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
data.addColumn("number", series[i].name);
|
976
|
-
}
|
977
|
-
data.addRows(rows2);
|
1118
|
+
if (chart.options.xtype === "number") {
|
1119
|
+
categories.sort(sortByNumber);
|
1120
|
+
}
|
978
1121
|
|
979
|
-
|
980
|
-
resize(function () {
|
981
|
-
chart.chart.draw(data, options);
|
982
|
-
});
|
983
|
-
});
|
984
|
-
};
|
1122
|
+
options.xAxis.categories = categories;
|
985
1123
|
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
1124
|
+
var newSeries = [], d2;
|
1125
|
+
for (i = 0; i < series.length; i++) {
|
1126
|
+
d = [];
|
1127
|
+
for (j = 0; j < categories.length; j++) {
|
1128
|
+
d.push(rows[categories[j]][i] || 0);
|
1129
|
+
}
|
991
1130
|
|
992
|
-
|
993
|
-
|
1131
|
+
d2 = {
|
1132
|
+
name: series[i].name,
|
1133
|
+
data: d
|
1134
|
+
};
|
1135
|
+
if (series[i].stack) {
|
1136
|
+
d2.stack = series[i].stack;
|
994
1137
|
}
|
995
|
-
var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
|
996
1138
|
|
997
|
-
|
998
|
-
|
999
|
-
data.addColumn({type: "date", id: "Start"});
|
1000
|
-
data.addColumn({type: "date", id: "End"});
|
1001
|
-
data.addRows(chart.data);
|
1139
|
+
newSeries.push(d2);
|
1140
|
+
}
|
1002
1141
|
|
1003
|
-
|
1004
|
-
|
1142
|
+
drawChart(chart, newSeries, options);
|
1143
|
+
};
|
1005
1144
|
|
1006
|
-
|
1007
|
-
|
1008
|
-
});
|
1009
|
-
});
|
1145
|
+
var renderBarChart = function (chart) {
|
1146
|
+
renderColumnChart(chart, "bar");
|
1010
1147
|
};
|
1011
|
-
};
|
1012
1148
|
|
1013
|
-
|
1149
|
+
var renderAreaChart = function (chart) {
|
1150
|
+
renderLineChart(chart, "areaspline");
|
1151
|
+
};
|
1152
|
+
|
1153
|
+
return {
|
1154
|
+
name: "highcharts",
|
1155
|
+
renderLineChart: renderLineChart,
|
1156
|
+
renderPieChart: renderPieChart,
|
1157
|
+
renderColumnChart: renderColumnChart,
|
1158
|
+
renderBarChart: renderBarChart,
|
1159
|
+
renderAreaChart: renderAreaChart,
|
1160
|
+
renderScatterChart: renderScatterChart
|
1161
|
+
};
|
1162
|
+
})();
|
1163
|
+
adapters.push(HighchartsAdapter);
|
1014
1164
|
}
|
1015
|
-
if (!
|
1016
|
-
|
1017
|
-
var
|
1165
|
+
if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
|
1166
|
+
GoogleChartsAdapter = (function () {
|
1167
|
+
var google = window.google;
|
1018
1168
|
|
1019
|
-
|
1169
|
+
var loaded = {};
|
1170
|
+
var callbacks = [];
|
1020
1171
|
|
1021
|
-
var
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1172
|
+
var runCallbacks = function () {
|
1173
|
+
var cb, call;
|
1174
|
+
for (var i = 0; i < callbacks.length; i++) {
|
1175
|
+
cb = callbacks[i];
|
1176
|
+
call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
|
1177
|
+
if (call) {
|
1178
|
+
cb.callback();
|
1179
|
+
callbacks.splice(i, 1);
|
1180
|
+
i--;
|
1181
|
+
}
|
1182
|
+
}
|
1029
1183
|
};
|
1030
1184
|
|
1185
|
+
var waitForLoaded = function (pack, callback) {
|
1186
|
+
if (!callback) {
|
1187
|
+
callback = pack;
|
1188
|
+
pack = "corechart";
|
1189
|
+
}
|
1190
|
+
|
1191
|
+
callbacks.push({pack: pack, callback: callback});
|
1192
|
+
|
1193
|
+
if (loaded[pack]) {
|
1194
|
+
runCallbacks();
|
1195
|
+
} else {
|
1196
|
+
loaded[pack] = true;
|
1197
|
+
|
1198
|
+
// https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
|
1199
|
+
var loadOptions = {
|
1200
|
+
packages: [pack],
|
1201
|
+
callback: runCallbacks
|
1202
|
+
};
|
1203
|
+
if (config.language) {
|
1204
|
+
loadOptions.language = config.language;
|
1205
|
+
}
|
1206
|
+
if (pack === "corechart" && config.mapsApiKey) {
|
1207
|
+
loadOptions.mapsApiKey = config.mapsApiKey;
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
if (window.google.setOnLoadCallback) {
|
1211
|
+
google.load("visualization", "1", loadOptions);
|
1212
|
+
} else {
|
1213
|
+
google.charts.load("current", loadOptions);
|
1214
|
+
}
|
1215
|
+
}
|
1216
|
+
};
|
1217
|
+
|
1218
|
+
// Set chart options
|
1031
1219
|
var defaultOptions = {
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1220
|
+
chartArea: {},
|
1221
|
+
fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
|
1222
|
+
pointSize: 6,
|
1223
|
+
legend: {
|
1224
|
+
textStyle: {
|
1225
|
+
fontSize: 12,
|
1226
|
+
color: "#444"
|
1227
|
+
},
|
1228
|
+
alignment: "center",
|
1229
|
+
position: "right"
|
1230
|
+
},
|
1231
|
+
curveType: "function",
|
1232
|
+
hAxis: {
|
1233
|
+
textStyle: {
|
1234
|
+
color: "#666",
|
1235
|
+
fontSize: 12
|
1236
|
+
},
|
1237
|
+
titleTextStyle: {},
|
1238
|
+
gridlines: {
|
1239
|
+
color: "transparent"
|
1240
|
+
},
|
1241
|
+
baselineColor: "#ccc",
|
1242
|
+
viewWindow: {}
|
1243
|
+
},
|
1244
|
+
vAxis: {
|
1245
|
+
textStyle: {
|
1246
|
+
color: "#666",
|
1247
|
+
fontSize: 12
|
1248
|
+
},
|
1249
|
+
titleTextStyle: {},
|
1250
|
+
baselineColor: "#ccc",
|
1251
|
+
viewWindow: {}
|
1252
|
+
},
|
1253
|
+
tooltip: {
|
1254
|
+
textStyle: {
|
1255
|
+
color: "#666",
|
1256
|
+
fontSize: 12
|
1257
|
+
}
|
1059
1258
|
}
|
1060
1259
|
};
|
1061
1260
|
|
1062
|
-
// http://there4.io/2012/05/02/google-chart-color-list/
|
1063
|
-
var defaultColors = [
|
1064
|
-
"#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
|
1065
|
-
"#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
|
1066
|
-
"#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
|
1067
|
-
];
|
1068
|
-
|
1069
1261
|
var hideLegend = function (options, legend, hideLegend) {
|
1070
1262
|
if (legend !== undefined) {
|
1071
|
-
|
1072
|
-
if (legend
|
1073
|
-
|
1263
|
+
var position;
|
1264
|
+
if (!legend) {
|
1265
|
+
position = "none";
|
1266
|
+
} else if (legend === true) {
|
1267
|
+
position = "right";
|
1268
|
+
} else {
|
1269
|
+
position = legend;
|
1074
1270
|
}
|
1271
|
+
options.legend.position = position;
|
1075
1272
|
} else if (hideLegend) {
|
1076
|
-
options.legend.
|
1273
|
+
options.legend.position = "none";
|
1077
1274
|
}
|
1078
1275
|
};
|
1079
1276
|
|
1080
1277
|
var setTitle = function (options, title) {
|
1081
|
-
options.title
|
1082
|
-
options.
|
1278
|
+
options.title = title;
|
1279
|
+
options.titleTextStyle = {color: "#333", fontSize: "20px"};
|
1083
1280
|
};
|
1084
1281
|
|
1085
1282
|
var setMin = function (options, min) {
|
1086
|
-
|
1087
|
-
options.scales.yAxes[0].ticks.min = toFloat(min);
|
1088
|
-
}
|
1283
|
+
options.vAxis.viewWindow.min = min;
|
1089
1284
|
};
|
1090
1285
|
|
1091
1286
|
var setMax = function (options, max) {
|
1092
|
-
options.
|
1287
|
+
options.vAxis.viewWindow.max = max;
|
1093
1288
|
};
|
1094
1289
|
|
1095
1290
|
var setBarMin = function (options, min) {
|
1096
|
-
|
1097
|
-
options.scales.xAxes[0].ticks.min = toFloat(min);
|
1098
|
-
}
|
1291
|
+
options.hAxis.viewWindow.min = min;
|
1099
1292
|
};
|
1100
1293
|
|
1101
1294
|
var setBarMax = function (options, max) {
|
1102
|
-
options.
|
1295
|
+
options.hAxis.viewWindow.max = max;
|
1103
1296
|
};
|
1104
1297
|
|
1105
1298
|
var setStacked = function (options, stacked) {
|
1106
|
-
options.
|
1107
|
-
options.scales.yAxes[0].stacked = !!stacked;
|
1299
|
+
options.isStacked = !!stacked;
|
1108
1300
|
};
|
1109
1301
|
|
1110
1302
|
var setXtitle = function (options, title) {
|
1111
|
-
options.
|
1112
|
-
options.
|
1303
|
+
options.hAxis.title = title;
|
1304
|
+
options.hAxis.titleTextStyle.italic = false;
|
1113
1305
|
};
|
1114
1306
|
|
1115
1307
|
var setYtitle = function (options, title) {
|
1116
|
-
options.
|
1117
|
-
options.
|
1118
|
-
};
|
1119
|
-
|
1120
|
-
var drawChart = function(chart, type, data, options) {
|
1121
|
-
if (chart.chart) {
|
1122
|
-
chart.chart.destroy();
|
1123
|
-
} else {
|
1124
|
-
chart.element.innerHTML = "<canvas></canvas>";
|
1125
|
-
}
|
1126
|
-
|
1127
|
-
var ctx = chart.element.getElementsByTagName("CANVAS")[0];
|
1128
|
-
chart.chart = new Chart(ctx, {
|
1129
|
-
type: type,
|
1130
|
-
data: data,
|
1131
|
-
options: options
|
1132
|
-
});
|
1133
|
-
};
|
1134
|
-
|
1135
|
-
// http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
|
1136
|
-
var addOpacity = function(hex, opacity) {
|
1137
|
-
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
1138
|
-
return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
|
1139
|
-
};
|
1140
|
-
|
1141
|
-
var setLabelSize = function (chart, data, options) {
|
1142
|
-
var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
|
1143
|
-
if (maxLabelSize > 25) {
|
1144
|
-
maxLabelSize = 25;
|
1145
|
-
}
|
1146
|
-
options.scales.xAxes[0].ticks.callback = function (value) {
|
1147
|
-
value = toStr(value);
|
1148
|
-
if (value.length > maxLabelSize) {
|
1149
|
-
return value.substring(0, maxLabelSize - 2) + "...";
|
1150
|
-
} else {
|
1151
|
-
return value;
|
1152
|
-
}
|
1153
|
-
};
|
1308
|
+
options.vAxis.title = title;
|
1309
|
+
options.vAxis.titleTextStyle.italic = false;
|
1154
1310
|
};
|
1155
1311
|
|
1156
|
-
var jsOptions = jsOptionsFunc(
|
1157
|
-
|
1158
|
-
var createDataTable = function (chart, options, chartType) {
|
1159
|
-
var datasets = [];
|
1160
|
-
var labels = [];
|
1161
|
-
|
1162
|
-
var colors = chart.options.colors || defaultColors;
|
1163
|
-
|
1164
|
-
var day = true;
|
1165
|
-
var week = true;
|
1166
|
-
var dayOfWeek;
|
1167
|
-
var month = true;
|
1168
|
-
var year = true;
|
1169
|
-
var hour = true;
|
1170
|
-
var minute = true;
|
1171
|
-
var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
|
1172
|
-
|
1173
|
-
var series = chart.data;
|
1174
|
-
|
1175
|
-
var sortedLabels = [];
|
1312
|
+
var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
1176
1313
|
|
1177
|
-
|
1314
|
+
// cant use object as key
|
1315
|
+
var createDataTable = function (series, columnType, xtype) {
|
1316
|
+
var i, j, s, d, key, rows = [], sortedLabels = [];
|
1178
1317
|
for (i = 0; i < series.length; i++) {
|
1179
1318
|
s = series[i];
|
1180
1319
|
|
1181
1320
|
for (j = 0; j < s.data.length; j++) {
|
1182
1321
|
d = s.data[j];
|
1183
|
-
key =
|
1322
|
+
key = (columnType === "datetime") ? d[0].getTime() : d[0];
|
1184
1323
|
if (!rows[key]) {
|
1185
1324
|
rows[key] = new Array(series.length);
|
1186
|
-
}
|
1187
|
-
rows[key][i] = toFloat(d[1]);
|
1188
|
-
if (sortedLabels.indexOf(key) === -1) {
|
1189
1325
|
sortedLabels.push(key);
|
1190
1326
|
}
|
1327
|
+
rows[key][i] = toFloat(d[1]);
|
1191
1328
|
}
|
1192
1329
|
}
|
1193
1330
|
|
1194
|
-
if (detectType || chart.options.xtype === "number") {
|
1195
|
-
sortedLabels.sort(sortByNumber);
|
1196
|
-
}
|
1197
|
-
|
1198
1331
|
var rows2 = [];
|
1199
|
-
|
1200
|
-
rows2.push([]);
|
1201
|
-
}
|
1202
|
-
|
1332
|
+
var day = true;
|
1203
1333
|
var value;
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
if (detectType) {
|
1334
|
+
for (j = 0; j < sortedLabels.length; j++) {
|
1335
|
+
i = sortedLabels[j];
|
1336
|
+
if (columnType === "datetime") {
|
1208
1337
|
value = new Date(toFloat(i));
|
1209
|
-
// TODO make this efficient
|
1210
1338
|
day = day && isDay(value);
|
1211
|
-
|
1212
|
-
|
1213
|
-
}
|
1214
|
-
week = week && isWeek(value, dayOfWeek);
|
1215
|
-
month = month && isMonth(value);
|
1216
|
-
year = year && isYear(value);
|
1217
|
-
hour = hour && isHour(value);
|
1218
|
-
minute = minute && isMinute(value);
|
1339
|
+
} else if (columnType === "number") {
|
1340
|
+
value = toFloat(i);
|
1219
1341
|
} else {
|
1220
1342
|
value = i;
|
1221
1343
|
}
|
1222
|
-
|
1223
|
-
for (j = 0; j < series.length; j++) {
|
1224
|
-
// Chart.js doesn't like undefined
|
1225
|
-
rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
|
1226
|
-
}
|
1344
|
+
rows2.push([value].concat(rows[i]));
|
1227
1345
|
}
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
var color = s.color || colors[i];
|
1233
|
-
var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
|
1234
|
-
|
1235
|
-
var dataset = {
|
1236
|
-
label: s.name,
|
1237
|
-
data: rows2[i],
|
1238
|
-
fill: chartType === "area",
|
1239
|
-
borderColor: color,
|
1240
|
-
backgroundColor: backgroundColor,
|
1241
|
-
pointBackgroundColor: color,
|
1242
|
-
borderWidth: 2
|
1243
|
-
};
|
1244
|
-
|
1245
|
-
if (s.stack) {
|
1246
|
-
dataset.stack = s.stack;
|
1247
|
-
}
|
1248
|
-
|
1249
|
-
if (chart.options.curve === false) {
|
1250
|
-
dataset.lineTension = 0;
|
1251
|
-
}
|
1252
|
-
|
1253
|
-
if (chart.options.points === false) {
|
1254
|
-
dataset.pointRadius = 0;
|
1255
|
-
dataset.pointHitRadius = 5;
|
1256
|
-
}
|
1257
|
-
|
1258
|
-
datasets.push(merge(dataset, s.library || {}));
|
1346
|
+
if (columnType === "datetime") {
|
1347
|
+
rows2.sort(sortByTime);
|
1348
|
+
} else if (columnType === "number") {
|
1349
|
+
rows2.sort(sortByNumberSeries);
|
1259
1350
|
}
|
1260
|
-
|
1261
|
-
if (
|
1262
|
-
|
1263
|
-
|
1264
|
-
for (i =
|
1265
|
-
|
1266
|
-
if (value < minTime) {
|
1267
|
-
minTime = value;
|
1268
|
-
}
|
1269
|
-
if (value > maxTime) {
|
1270
|
-
maxTime = value;
|
1271
|
-
}
|
1272
|
-
}
|
1273
|
-
|
1274
|
-
var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
|
1275
|
-
|
1276
|
-
if (!options.scales.xAxes[0].time.unit) {
|
1277
|
-
var step;
|
1278
|
-
if (year || timeDiff > 365 * 10) {
|
1279
|
-
options.scales.xAxes[0].time.unit = "year";
|
1280
|
-
step = 365;
|
1281
|
-
} else if (month || timeDiff > 30 * 10) {
|
1282
|
-
options.scales.xAxes[0].time.unit = "month";
|
1283
|
-
step = 30;
|
1284
|
-
} else if (day || timeDiff > 10) {
|
1285
|
-
options.scales.xAxes[0].time.unit = "day";
|
1286
|
-
step = 1;
|
1287
|
-
} else if (hour || timeDiff > 0.5) {
|
1288
|
-
options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
|
1289
|
-
options.scales.xAxes[0].time.unit = "hour";
|
1290
|
-
step = 1 / 24.0;
|
1291
|
-
} else if (minute) {
|
1292
|
-
options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
|
1293
|
-
options.scales.xAxes[0].time.unit = "minute";
|
1294
|
-
step = 1 / 24.0 / 60.0;
|
1295
|
-
}
|
1296
|
-
|
1297
|
-
if (step && timeDiff > 0) {
|
1298
|
-
var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
|
1299
|
-
if (week && step === 1) {
|
1300
|
-
unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
|
1301
|
-
}
|
1302
|
-
options.scales.xAxes[0].time.unitStepSize = unitStepSize;
|
1303
|
-
}
|
1304
|
-
}
|
1305
|
-
|
1306
|
-
if (!options.scales.xAxes[0].time.tooltipFormat) {
|
1307
|
-
if (day) {
|
1308
|
-
options.scales.xAxes[0].time.tooltipFormat = "ll";
|
1309
|
-
} else if (hour) {
|
1310
|
-
options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
|
1311
|
-
} else if (minute) {
|
1312
|
-
options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
|
1313
|
-
}
|
1351
|
+
|
1352
|
+
if (xtype === "number") {
|
1353
|
+
rows2.sort(sortByNumberSeries);
|
1354
|
+
|
1355
|
+
for (i = 0; i < rows2.length; i++) {
|
1356
|
+
rows2[i][0] = toStr(rows2[i][0]);
|
1314
1357
|
}
|
1315
1358
|
}
|
1316
1359
|
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1360
|
+
// create datatable
|
1361
|
+
var data = new google.visualization.DataTable();
|
1362
|
+
columnType = columnType === "datetime" && day ? "date" : columnType;
|
1363
|
+
data.addColumn(columnType, "");
|
1364
|
+
for (i = 0; i < series.length; i++) {
|
1365
|
+
data.addColumn("number", series[i].name);
|
1366
|
+
}
|
1367
|
+
data.addRows(rows2);
|
1321
1368
|
|
1322
1369
|
return data;
|
1323
1370
|
};
|
1324
1371
|
|
1325
|
-
|
1326
|
-
if (
|
1327
|
-
|
1372
|
+
var resize = function (callback) {
|
1373
|
+
if (window.attachEvent) {
|
1374
|
+
window.attachEvent("onresize", callback);
|
1375
|
+
} else if (window.addEventListener) {
|
1376
|
+
window.addEventListener("resize", callback, true);
|
1328
1377
|
}
|
1378
|
+
callback();
|
1379
|
+
};
|
1329
1380
|
|
1330
|
-
|
1331
|
-
if (
|
1332
|
-
|
1333
|
-
// chartOptions.stacked = true;
|
1334
|
-
}
|
1335
|
-
// fix for https://github.com/chartjs/Chart.js/issues/2441
|
1336
|
-
if (!chart.options.max && allZeros(chart.data)) {
|
1337
|
-
chartOptions.max = 1;
|
1381
|
+
var drawChart = function(chart, type, data, options) {
|
1382
|
+
if (chart.chart) {
|
1383
|
+
chart.chart.clearChart();
|
1338
1384
|
}
|
1339
1385
|
|
1340
|
-
|
1386
|
+
chart.chart = new type(chart.element);
|
1387
|
+
resize(function () {
|
1388
|
+
chart.chart.draw(data, options);
|
1389
|
+
});
|
1390
|
+
};
|
1341
1391
|
|
1342
|
-
|
1392
|
+
var renderLineChart = function (chart) {
|
1393
|
+
waitForLoaded(function () {
|
1394
|
+
var chartOptions = {};
|
1343
1395
|
|
1344
|
-
|
1396
|
+
if (chart.options.curve === false) {
|
1397
|
+
chartOptions.curveType = "none";
|
1398
|
+
}
|
1345
1399
|
|
1346
|
-
|
1400
|
+
if (chart.options.points === false) {
|
1401
|
+
chartOptions.pointSize = 0;
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
1405
|
+
var columnType = chart.discrete ? "string" : "datetime";
|
1406
|
+
if (chart.options.xtype === "number") {
|
1407
|
+
columnType = "number";
|
1408
|
+
}
|
1409
|
+
var data = createDataTable(chart.data, columnType);
|
1410
|
+
|
1411
|
+
drawChart(chart, google.visualization.LineChart, data, options);
|
1412
|
+
});
|
1347
1413
|
};
|
1348
1414
|
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1415
|
+
var renderPieChart = function (chart) {
|
1416
|
+
waitForLoaded(function () {
|
1417
|
+
var chartOptions = {
|
1418
|
+
chartArea: {
|
1419
|
+
top: "10%",
|
1420
|
+
height: "80%"
|
1421
|
+
},
|
1422
|
+
legend: {}
|
1423
|
+
};
|
1424
|
+
if (chart.options.colors) {
|
1425
|
+
chartOptions.colors = chart.options.colors;
|
1426
|
+
}
|
1427
|
+
if (chart.options.donut) {
|
1428
|
+
chartOptions.pieHole = 0.5;
|
1429
|
+
}
|
1430
|
+
if ("legend" in chart.options) {
|
1431
|
+
hideLegend(chartOptions, chart.options.legend);
|
1432
|
+
}
|
1433
|
+
if (chart.options.title) {
|
1434
|
+
setTitle(chartOptions, chart.options.title);
|
1435
|
+
}
|
1436
|
+
var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
|
1354
1437
|
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1438
|
+
var data = new google.visualization.DataTable();
|
1439
|
+
data.addColumn("string", "");
|
1440
|
+
data.addColumn("number", "Value");
|
1441
|
+
data.addRows(chart.data);
|
1358
1442
|
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1443
|
+
drawChart(chart, google.visualization.PieChart, data, options);
|
1444
|
+
});
|
1445
|
+
};
|
1362
1446
|
|
1363
|
-
|
1447
|
+
var renderColumnChart = function (chart) {
|
1448
|
+
waitForLoaded(function () {
|
1449
|
+
var options = jsOptions(chart, chart.options);
|
1450
|
+
var data = createDataTable(chart.data, "string", chart.options.xtype);
|
1364
1451
|
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
var point = chart.data[i];
|
1369
|
-
labels.push(point[0]);
|
1370
|
-
values.push(point[1]);
|
1371
|
-
}
|
1452
|
+
drawChart(chart, google.visualization.ColumnChart, data, options);
|
1453
|
+
});
|
1454
|
+
};
|
1372
1455
|
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
{
|
1377
|
-
|
1378
|
-
|
1456
|
+
var renderBarChart = function (chart) {
|
1457
|
+
waitForLoaded(function () {
|
1458
|
+
var chartOptions = {
|
1459
|
+
hAxis: {
|
1460
|
+
gridlines: {
|
1461
|
+
color: "#ccc"
|
1462
|
+
}
|
1379
1463
|
}
|
1380
|
-
|
1381
|
-
|
1464
|
+
};
|
1465
|
+
var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
|
1466
|
+
var data = createDataTable(chart.data, "string", chart.options.xtype);
|
1382
1467
|
|
1383
|
-
|
1468
|
+
drawChart(chart, google.visualization.BarChart, data, options);
|
1469
|
+
});
|
1384
1470
|
};
|
1385
1471
|
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
var data = createDataTable(chart, options, "column");
|
1394
|
-
setLabelSize(chart, data, options);
|
1395
|
-
drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
|
1396
|
-
};
|
1472
|
+
var renderAreaChart = function (chart) {
|
1473
|
+
waitForLoaded(function () {
|
1474
|
+
var chartOptions = {
|
1475
|
+
isStacked: true,
|
1476
|
+
pointSize: 0,
|
1477
|
+
areaOpacity: 0.5
|
1478
|
+
};
|
1397
1479
|
|
1398
|
-
|
1480
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
1481
|
+
var columnType = chart.discrete ? "string" : "datetime";
|
1482
|
+
if (chart.options.xtype === "number") {
|
1483
|
+
columnType = "number";
|
1484
|
+
}
|
1485
|
+
var data = createDataTable(chart.data, columnType);
|
1399
1486
|
|
1400
|
-
|
1401
|
-
|
1487
|
+
drawChart(chart, google.visualization.AreaChart, data, options);
|
1488
|
+
});
|
1402
1489
|
};
|
1403
1490
|
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1491
|
+
var renderGeoChart = function (chart) {
|
1492
|
+
waitForLoaded(function () {
|
1493
|
+
var chartOptions = {
|
1494
|
+
legend: "none",
|
1495
|
+
colorAxis: {
|
1496
|
+
colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
|
1497
|
+
}
|
1498
|
+
};
|
1499
|
+
var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
|
1407
1500
|
|
1408
|
-
|
1409
|
-
|
1501
|
+
var data = new google.visualization.DataTable();
|
1502
|
+
data.addColumn("string", "");
|
1503
|
+
data.addColumn("number", chart.options.label || "Value");
|
1504
|
+
data.addRows(chart.data);
|
1410
1505
|
|
1411
|
-
|
1506
|
+
drawChart(chart, google.visualization.GeoChart, data, options);
|
1507
|
+
});
|
1508
|
+
};
|
1412
1509
|
|
1413
|
-
|
1510
|
+
var renderScatterChart = function (chart) {
|
1511
|
+
waitForLoaded(function () {
|
1512
|
+
var chartOptions = {};
|
1513
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
1414
1514
|
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
y: toFloat(s.data[j][1])
|
1424
|
-
};
|
1425
|
-
if (chartType === "bubble") {
|
1426
|
-
point.r = toFloat(s.data[j][2]);
|
1515
|
+
var series = chart.data, rows2 = [], i, j, data, d;
|
1516
|
+
for (i = 0; i < series.length; i++) {
|
1517
|
+
d = series[i].data;
|
1518
|
+
for (j = 0; j < d.length; j++) {
|
1519
|
+
var row = new Array(series.length + 1);
|
1520
|
+
row[0] = d[j][0];
|
1521
|
+
row[i + 1] = d[j][1];
|
1522
|
+
rows2.push(row);
|
1427
1523
|
}
|
1428
|
-
d.push(point);
|
1429
1524
|
}
|
1430
1525
|
|
1431
|
-
|
1432
|
-
|
1526
|
+
data = new google.visualization.DataTable();
|
1527
|
+
data.addColumn("number", "");
|
1528
|
+
for (i = 0; i < series.length; i++) {
|
1529
|
+
data.addColumn("number", series[i].name);
|
1530
|
+
}
|
1531
|
+
data.addRows(rows2);
|
1433
1532
|
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
data: d,
|
1438
|
-
borderColor: color,
|
1439
|
-
backgroundColor: backgroundColor,
|
1440
|
-
pointBackgroundColor: color,
|
1441
|
-
fill: chartType === "area"
|
1442
|
-
})
|
1443
|
-
}
|
1533
|
+
drawChart(chart, google.visualization.ScatterChart, data, options);
|
1534
|
+
});
|
1535
|
+
};
|
1444
1536
|
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1537
|
+
var renderTimeline = function (chart) {
|
1538
|
+
waitForLoaded("timeline", function () {
|
1539
|
+
var chartOptions = {
|
1540
|
+
legend: "none"
|
1541
|
+
};
|
1448
1542
|
|
1449
|
-
|
1543
|
+
if (chart.options.colors) {
|
1544
|
+
chartOptions.colors = chart.options.colors;
|
1545
|
+
}
|
1546
|
+
var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
|
1450
1547
|
|
1451
|
-
|
1452
|
-
|
1548
|
+
var data = new google.visualization.DataTable();
|
1549
|
+
data.addColumn({type: "string", id: "Name"});
|
1550
|
+
data.addColumn({type: "date", id: "Start"});
|
1551
|
+
data.addColumn({type: "date", id: "End"});
|
1552
|
+
data.addRows(chart.data);
|
1453
1553
|
|
1454
|
-
|
1554
|
+
chart.element.style.lineHeight = "normal";
|
1555
|
+
|
1556
|
+
drawChart(chart, google.visualization.Timeline, data, options);
|
1557
|
+
});
|
1455
1558
|
};
|
1456
1559
|
|
1457
|
-
|
1458
|
-
|
1560
|
+
return {
|
1561
|
+
name: "google",
|
1562
|
+
renderLineChart: renderLineChart,
|
1563
|
+
renderPieChart: renderPieChart,
|
1564
|
+
renderColumnChart: renderColumnChart,
|
1565
|
+
renderBarChart: renderBarChart,
|
1566
|
+
renderAreaChart: renderAreaChart,
|
1567
|
+
renderScatterChart: renderScatterChart,
|
1568
|
+
renderGeoChart: renderGeoChart,
|
1569
|
+
renderTimeline: renderTimeline
|
1459
1570
|
};
|
1460
|
-
};
|
1571
|
+
})();
|
1572
|
+
|
1573
|
+
adapters.push(GoogleChartsAdapter);
|
1574
|
+
}
|
1575
|
+
}
|
1461
1576
|
|
1462
|
-
|
1577
|
+
function dataEmpty(data, chartType) {
|
1578
|
+
if (chartType === "PieChart" || chartType === "GeoChart" || chartType === "Timeline") {
|
1579
|
+
return data.length === 0;
|
1580
|
+
} else {
|
1581
|
+
for (var i = 0; i < data.length; i++) {
|
1582
|
+
if (data[i].data.length > 0) {
|
1583
|
+
return false;
|
1584
|
+
}
|
1585
|
+
}
|
1586
|
+
return true;
|
1463
1587
|
}
|
1464
1588
|
}
|
1465
1589
|
|
1466
1590
|
function renderChart(chartType, chart) {
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1591
|
+
if (chart.options.messages && chart.options.messages.empty && dataEmpty(chart.data, chartType)) {
|
1592
|
+
setText(chart.element, chart.options.messages.empty);
|
1593
|
+
} else {
|
1594
|
+
callAdapter(chartType, chart);
|
1595
|
+
if (chart.options.download && !chart.downloadAttached && chart.adapter === "chartjs") {
|
1596
|
+
addDownloadButton(chart);
|
1597
|
+
}
|
1470
1598
|
}
|
1471
1599
|
}
|
1472
1600
|
|
@@ -1574,18 +1702,43 @@
|
|
1574
1702
|
return false;
|
1575
1703
|
}
|
1576
1704
|
|
1705
|
+
function formatValue(pre, value, options) {
|
1706
|
+
if (options.thousands || options.decimal) {
|
1707
|
+
value = toStr(value);
|
1708
|
+
var parts = value.split(".")
|
1709
|
+
value = parts[0];
|
1710
|
+
if (options.thousands) {
|
1711
|
+
value = value.replace(/(\d)(?=(\d{3})+(?!\d))/g, options.thousands);
|
1712
|
+
}
|
1713
|
+
if (parts.length > 1) {
|
1714
|
+
value += (options.decimal || ".") + parts[1];
|
1715
|
+
}
|
1716
|
+
}
|
1717
|
+
|
1718
|
+
pre = pre || "";
|
1719
|
+
if (options.prefix) {
|
1720
|
+
if (value < 0) {
|
1721
|
+
value = value * -1;
|
1722
|
+
pre += "-";
|
1723
|
+
}
|
1724
|
+
pre += options.prefix;
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
return pre + value + (options.suffix || "");
|
1728
|
+
}
|
1729
|
+
|
1577
1730
|
// creates a shallow copy of each element of the array
|
1578
1731
|
// elements are expected to be objects
|
1579
1732
|
function copySeries(series) {
|
1580
1733
|
var newSeries = [], i, j;
|
1581
1734
|
for (i = 0; i < series.length; i++) {
|
1582
|
-
var copy = {}
|
1735
|
+
var copy = {};
|
1583
1736
|
for (j in series[i]) {
|
1584
1737
|
if (series[i].hasOwnProperty(j)) {
|
1585
1738
|
copy[j] = series[i][j];
|
1586
1739
|
}
|
1587
1740
|
}
|
1588
|
-
newSeries.push(copy)
|
1741
|
+
newSeries.push(copy);
|
1589
1742
|
}
|
1590
1743
|
return newSeries;
|
1591
1744
|
}
|
@@ -1684,7 +1837,7 @@
|
|
1684
1837
|
if (!processData) {
|
1685
1838
|
processData = function (chart) {
|
1686
1839
|
return chart.rawData;
|
1687
|
-
}
|
1840
|
+
};
|
1688
1841
|
}
|
1689
1842
|
|
1690
1843
|
// getters
|
@@ -1746,7 +1899,7 @@
|
|
1746
1899
|
} else {
|
1747
1900
|
return null;
|
1748
1901
|
}
|
1749
|
-
}
|
1902
|
+
};
|
1750
1903
|
|
1751
1904
|
Chartkick.charts[element.id] = chart;
|
1752
1905
|
|