chartkick 3.3.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -2
- data/LICENSE.txt +1 -1
- data/README.md +78 -39
- data/lib/chartkick.rb +2 -26
- data/lib/chartkick/enumerable.rb +25 -0
- data/lib/chartkick/helper.rb +43 -28
- data/lib/chartkick/version.rb +1 -1
- data/licenses/LICENSE-chart.js.txt +9 -0
- data/licenses/LICENSE-chartjs-adapter-date-fns.txt +9 -0
- data/licenses/LICENSE-chartkick.js.txt +22 -0
- data/licenses/LICENSE-date-fns.txt +20 -0
- data/vendor/assets/javascripts/Chart.bundle.js +2 -20755
- data/vendor/assets/javascripts/chart.js +12486 -0
- data/vendor/assets/javascripts/chartjs-adapter-date-fns.bundle.js +6313 -0
- data/vendor/assets/javascripts/chartkick.js +340 -257
- metadata +16 -52
- data/CONTRIBUTING.md +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9ca3fe125f71ef5a1a21a191a03244b9235396f4c72f4d8e742f7d1a3feaa98
|
4
|
+
data.tar.gz: d7da49117fa84b8525bf76acc421b22e71a0a38a2f2e798c182f96f0d6780a60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b00a3accac3e738dc1d0fa7480d162002f5302a8e725d28bfcd3c455514fa79080559b01cfc8a897c44a8d551fdfad3b80fb39a98a9b69671ec8dfa9c2d082e4
|
7
|
+
data.tar.gz: 5a1ccaf63c5bbd240e6ef7a14e240992387cc16c7ce43e6c1b3eab8cb1b632046adbea632db17a96194a21e6e7ce2427d1997ca5734541d51b3c6d2e506a3a8f
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,36 @@
|
|
1
|
+
## 4.0.0 (2021-04-04)
|
2
|
+
|
3
|
+
- Added support for Chart.js 3
|
4
|
+
- Added `loading` option
|
5
|
+
- Made charts deferrable by default
|
6
|
+
- Set `nonce` automatically when present
|
7
|
+
- Prefer `empty` over `messages: {empty: ...}`
|
8
|
+
- Removed support for Ruby < 2.6 and Rails < 5.2
|
9
|
+
|
10
|
+
Breaking changes
|
11
|
+
|
12
|
+
- Removed support for Chart.js 2
|
13
|
+
|
14
|
+
## 3.4.2 (2020-10-20)
|
15
|
+
|
16
|
+
- Updated Chart.js to 2.9.4
|
17
|
+
|
18
|
+
## 3.4.1 (2020-10-06)
|
19
|
+
|
20
|
+
- Relaxed validation for `width` and `height` options
|
21
|
+
|
22
|
+
## 3.4.0 (2020-08-04)
|
23
|
+
|
24
|
+
- Fixed CSS injection with `width` and `height` options - [more info](https://github.com/ankane/chartkick/issues/546)
|
25
|
+
|
26
|
+
## 3.3.2 (2020-07-23)
|
27
|
+
|
28
|
+
- Updated Chartkick.js to 3.2.1
|
29
|
+
|
1
30
|
## 3.3.1 (2019-12-26)
|
2
31
|
|
3
32
|
- Updated Chart.js to 2.9.3
|
4
|
-
- Fixed
|
33
|
+
- Fixed deprecation warnings in Ruby 2.7
|
5
34
|
|
6
35
|
## 3.3.0 (2019-11-09)
|
7
36
|
|
@@ -19,7 +48,7 @@
|
|
19
48
|
|
20
49
|
## 3.2.0 (2019-06-04)
|
21
50
|
|
22
|
-
- Fixed XSS vulnerability -
|
51
|
+
- Fixed XSS vulnerability - [more info](https://github.com/ankane/chartkick/issues/488)
|
23
52
|
|
24
53
|
## 3.1.0 (2019-05-26)
|
25
54
|
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -4,13 +4,17 @@ Create beautiful JavaScript charts with one line of Ruby. No more fighting with
|
|
4
4
|
|
5
5
|
[See it in action](https://chartkick.com)
|
6
6
|
|
7
|
-
|
7
|
+
**Chartkick 4.0 was recently released** - see [how to upgrade](#upgrading)
|
8
|
+
|
9
|
+
:fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/), and for advanced visualizations, check out [Vega](https://github.com/ankane/vega)
|
8
10
|
|
9
11
|
:two_hearts: A perfect companion to [Groupdate](https://github.com/ankane/groupdate), [Hightop](https://github.com/ankane/hightop), and [ActiveMedian](https://github.com/ankane/active_median)
|
10
12
|
|
13
|
+
[![Build Status](https://github.com/ankane/chartkick/workflows/build/badge.svg?branch=master)](https://github.com/ankane/chartkick/actions)
|
14
|
+
|
11
15
|
## Quick Start
|
12
16
|
|
13
|
-
Add this line to your application
|
17
|
+
Add this line to your application’s Gemfile:
|
14
18
|
|
15
19
|
```ruby
|
16
20
|
gem "chartkick"
|
@@ -19,14 +23,13 @@ gem "chartkick"
|
|
19
23
|
For Rails 6 / Webpacker, run:
|
20
24
|
|
21
25
|
```sh
|
22
|
-
yarn add chartkick
|
26
|
+
yarn add chartkick
|
23
27
|
```
|
24
28
|
|
25
29
|
And in `app/javascript/packs/application.js`, add:
|
26
30
|
|
27
31
|
```js
|
28
|
-
require("chartkick")
|
29
|
-
require("chart.js")
|
32
|
+
require("chartkick/chart.js")
|
30
33
|
```
|
31
34
|
|
32
35
|
For Rails 5 / Sprockets, in `app/assets/javascripts/application.js`, add:
|
@@ -36,7 +39,7 @@ For Rails 5 / Sprockets, in `app/assets/javascripts/application.js`, add:
|
|
36
39
|
//= require Chart.bundle
|
37
40
|
```
|
38
41
|
|
39
|
-
This sets up Chartkick with Chart.js. For other charting libraries, see [detailed instructions](#installation).
|
42
|
+
This sets up Chartkick with [Chart.js](https://www.chartjs.org/). For other charting libraries, see [detailed instructions](#installation).
|
40
43
|
|
41
44
|
## Charts
|
42
45
|
|
@@ -206,12 +209,6 @@ Specify legend position
|
|
206
209
|
<%= line_chart data, legend: "bottom" %>
|
207
210
|
```
|
208
211
|
|
209
|
-
Defer chart creation until after the page loads
|
210
|
-
|
211
|
-
```erb
|
212
|
-
<%= line_chart data, defer: true %>
|
213
|
-
```
|
214
|
-
|
215
212
|
Donut chart
|
216
213
|
|
217
214
|
```erb
|
@@ -260,16 +257,22 @@ Show insignificant zeros, useful for currency - *Chart.js, Highcharts*
|
|
260
257
|
<%= line_chart data, round: 2, zeros: true %>
|
261
258
|
```
|
262
259
|
|
263
|
-
Friendly byte sizes
|
260
|
+
Friendly byte sizes
|
264
261
|
|
265
262
|
```erb
|
266
263
|
<%= line_chart data, bytes: true %>
|
267
264
|
```
|
268
265
|
|
266
|
+
Show a message when data is loading
|
267
|
+
|
268
|
+
```erb
|
269
|
+
<%= line_chart data, loading: "Loading..." %>
|
270
|
+
```
|
271
|
+
|
269
272
|
Show a message when data is empty
|
270
273
|
|
271
274
|
```erb
|
272
|
-
<%= line_chart data,
|
275
|
+
<%= line_chart data, empty: "No data" %>
|
273
276
|
```
|
274
277
|
|
275
278
|
Refresh data from a remote source every `n` seconds
|
@@ -308,7 +311,7 @@ Chartkick.options = {
|
|
308
311
|
Customize the html
|
309
312
|
|
310
313
|
```ruby
|
311
|
-
Chartkick.options[:html] = '<div id="%{id}" style="height: %{height};"
|
314
|
+
Chartkick.options[:html] = '<div id="%{id}" style="height: %{height};">%{loading}</div>'
|
312
315
|
```
|
313
316
|
|
314
317
|
You capture the JavaScript in a content block with:
|
@@ -323,7 +326,7 @@ Then, in your layout, use:
|
|
323
326
|
<%= yield :charts_js %>
|
324
327
|
```
|
325
328
|
|
326
|
-
|
329
|
+
For Padrino, use `yield_content` instead of `yield`.
|
327
330
|
|
328
331
|
This is great for including all of your JavaScript at the bottom of the page.
|
329
332
|
|
@@ -370,9 +373,7 @@ If you want to use the charting library directly, get the code with:
|
|
370
373
|
<%= line_chart data, code: true %>
|
371
374
|
```
|
372
375
|
|
373
|
-
The code will be logged to the JavaScript console.
|
374
|
-
|
375
|
-
> JavaScript functions cannot be logged, so it may not be identical.
|
376
|
+
The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical.
|
376
377
|
|
377
378
|
### Download Charts
|
378
379
|
|
@@ -384,7 +385,7 @@ Give users the ability to download charts. It all happens in the browser - no se
|
|
384
385
|
<%= line_chart data, download: true %>
|
385
386
|
```
|
386
387
|
|
387
|
-
|
388
|
+
Safari will open the image in a new window instead of downloading.
|
388
389
|
|
389
390
|
Set the filename
|
390
391
|
|
@@ -418,21 +419,20 @@ Next, choose your charting library.
|
|
418
419
|
- [Google Charts](#google-charts)
|
419
420
|
- [Highcharts](#highcharts)
|
420
421
|
|
421
|
-
|
422
|
+
In the instructions below, `application.js` must be included **before** the charts in your views, unless using the `:content_for` option.
|
422
423
|
|
423
424
|
### Chart.js
|
424
425
|
|
425
426
|
For Rails 6 / Webpacker, run:
|
426
427
|
|
427
428
|
```sh
|
428
|
-
yarn add chartkick
|
429
|
+
yarn add chartkick
|
429
430
|
```
|
430
431
|
|
431
432
|
And in `app/javascript/packs/application.js`, add:
|
432
433
|
|
433
434
|
```js
|
434
|
-
require("chartkick")
|
435
|
-
require("chart.js")
|
435
|
+
require("chartkick/chart.js")
|
436
436
|
```
|
437
437
|
|
438
438
|
For Rails 5 / Sprockets, in `app/assets/javascripts/application.js`, add:
|
@@ -487,7 +487,7 @@ yarn add chartkick highcharts
|
|
487
487
|
And in `app/javascript/packs/application.js`, add:
|
488
488
|
|
489
489
|
```js
|
490
|
-
require("chartkick
|
490
|
+
require("chartkick/highcharts")
|
491
491
|
```
|
492
492
|
|
493
493
|
For Rails 5 / Sprockets, download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts` in Rails 5.1+), and in `app/assets/javascripts/application.js`, add:
|
@@ -505,6 +505,27 @@ Download [chartkick.js](https://raw.githubusercontent.com/ankane/chartkick/maste
|
|
505
505
|
<script src="chartkick.js"></script>
|
506
506
|
```
|
507
507
|
|
508
|
+
Then include the charting library.
|
509
|
+
|
510
|
+
Chart.js - download [Chart.js](https://unpkg.com/chart.js@3/dist/chart.js) and the [date-fns adapter bundle](https://unpkg.com/chartjs-adapter-date-fns@2.0.0/dist/chartjs-adapter-date-fns.bundle.js)
|
511
|
+
|
512
|
+
```html
|
513
|
+
<script src="chart.js"></script>
|
514
|
+
<script src="chartjs-adapter-date-fns.bundle.js"></script>
|
515
|
+
```
|
516
|
+
|
517
|
+
Google Charts
|
518
|
+
|
519
|
+
```html
|
520
|
+
<script src="https://www.gstatic.com/charts/loader.js"></script>
|
521
|
+
```
|
522
|
+
|
523
|
+
Highcharts - download [highcharts.js](https://code.highcharts.com/highcharts.js)
|
524
|
+
|
525
|
+
```html
|
526
|
+
<script src="highcharts.js"></script>
|
527
|
+
```
|
528
|
+
|
508
529
|
### Multiple Libraries
|
509
530
|
|
510
531
|
If more than one charting library is loaded, choose between them with:
|
@@ -562,6 +583,12 @@ Redraw the chart with:
|
|
562
583
|
chart.redraw()
|
563
584
|
```
|
564
585
|
|
586
|
+
Destroy the chart with:
|
587
|
+
|
588
|
+
```javascript
|
589
|
+
chart.destroy()
|
590
|
+
```
|
591
|
+
|
565
592
|
Loop over charts with:
|
566
593
|
|
567
594
|
```javascript
|
@@ -587,23 +614,28 @@ Check out [chartkick.js](https://github.com/ankane/chartkick.js)
|
|
587
614
|
|
588
615
|
## Upgrading
|
589
616
|
|
590
|
-
###
|
617
|
+
### 4.0
|
591
618
|
|
592
|
-
|
619
|
+
If you use Sprockets, update the gem and you’re good to go!
|
593
620
|
|
594
|
-
|
595
|
-
- Removed chartkick.js from asset precompile (no longer needed)
|
596
|
-
- Removed `xtype` option - numeric axes are automatically detected
|
597
|
-
- Removed `window.Chartkick = {...}` way to set config - use `Chartkick.configure` instead
|
598
|
-
- Removed support for the Google Charts jsapi loader - use loader.js instead
|
621
|
+
If you use Webpacker, run:
|
599
622
|
|
600
|
-
|
623
|
+
```sh
|
624
|
+
yarn upgrade chartkick --latest
|
625
|
+
```
|
601
626
|
|
602
|
-
|
627
|
+
If you use Chart.js with Webpacker, in `app/javascript/packs/application.js`, change:
|
603
628
|
|
604
|
-
|
605
|
-
|
606
|
-
|
629
|
+
```js
|
630
|
+
require("chartkick")
|
631
|
+
require("chart.js")
|
632
|
+
```
|
633
|
+
|
634
|
+
to:
|
635
|
+
|
636
|
+
```js
|
637
|
+
require("chartkick/chart.js")
|
638
|
+
```
|
607
639
|
|
608
640
|
## Credits
|
609
641
|
|
@@ -613,8 +645,6 @@ Chartkick uses [iso8601.js](https://github.com/Do/iso8601.js) to parse dates and
|
|
613
645
|
|
614
646
|
View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md)
|
615
647
|
|
616
|
-
Chartkick follows [Semantic Versioning](https://semver.org/)
|
617
|
-
|
618
648
|
## Contributing
|
619
649
|
|
620
650
|
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
@@ -623,3 +653,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
|
|
623
653
|
- Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls)
|
624
654
|
- Write, clarify, or fix documentation
|
625
655
|
- Suggest or add new features
|
656
|
+
|
657
|
+
To get started with development:
|
658
|
+
|
659
|
+
```sh
|
660
|
+
git clone https://github.com/ankane/chartkick.git
|
661
|
+
cd chartkick
|
662
|
+
bundle install
|
663
|
+
bundle exec rake test
|
664
|
+
```
|
data/lib/chartkick.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# modules
|
2
|
+
require "chartkick/enumerable"
|
1
3
|
require "chartkick/helper"
|
2
4
|
require "chartkick/version"
|
3
5
|
|
@@ -18,29 +20,3 @@ module Chartkick
|
|
18
20
|
end
|
19
21
|
self.options = {}
|
20
22
|
end
|
21
|
-
|
22
|
-
# for multiple series
|
23
|
-
# use Enumerable so it can be called on arrays
|
24
|
-
module Enumerable
|
25
|
-
def chart_json
|
26
|
-
if is_a?(Hash)
|
27
|
-
if (key = keys.first) && key.is_a?(Array) && key.size == 2
|
28
|
-
group_by { |k, _v| k[0] }.map do |name, data|
|
29
|
-
{name: name, data: data.map { |k, v| [k[1], v] }}
|
30
|
-
end
|
31
|
-
else
|
32
|
-
to_a
|
33
|
-
end
|
34
|
-
elsif is_a?(Array)
|
35
|
-
map do |v|
|
36
|
-
if v.is_a?(Hash) && v[:data].is_a?(Hash)
|
37
|
-
v = v.dup
|
38
|
-
v[:data] = v[:data].to_a
|
39
|
-
end
|
40
|
-
v
|
41
|
-
end
|
42
|
-
else
|
43
|
-
self
|
44
|
-
end.to_json
|
45
|
-
end
|
46
|
-
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# for both multiple series and
|
2
|
+
# making sure hash order is preserved in JavaScript
|
3
|
+
module Enumerable
|
4
|
+
def chart_json
|
5
|
+
if is_a?(Hash)
|
6
|
+
if (key = keys.first) && key.is_a?(Array) && key.size == 2
|
7
|
+
group_by { |k, _v| k[0] }.map do |name, data|
|
8
|
+
{name: name, data: data.map { |k, v| [k[1], v] }}
|
9
|
+
end
|
10
|
+
else
|
11
|
+
to_a
|
12
|
+
end
|
13
|
+
elsif is_a?(Array)
|
14
|
+
map do |v|
|
15
|
+
if v.is_a?(Hash) && v[:data].is_a?(Hash)
|
16
|
+
v = v.dup
|
17
|
+
v[:data] = v[:data].to_a
|
18
|
+
end
|
19
|
+
v
|
20
|
+
end
|
21
|
+
else
|
22
|
+
self
|
23
|
+
end.to_json
|
24
|
+
end
|
25
|
+
end
|
data/lib/chartkick/helper.rb
CHANGED
@@ -37,17 +37,16 @@ module Chartkick
|
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
-
def chartkick_chart(klass, data_source, **options)
|
40
|
+
def chartkick_chart(klass, data_source, nonce: true, **options)
|
41
41
|
@chartkick_chart_id ||= 0
|
42
42
|
options = chartkick_deep_merge(Chartkick.options, options)
|
43
43
|
element_id = options.delete(:id) || "chart-#{@chartkick_chart_id += 1}"
|
44
|
-
height = options.delete(:height) || "300px"
|
45
|
-
width = options.delete(:width) || "100%"
|
44
|
+
height = (options.delete(:height) || "300px").to_s
|
45
|
+
width = (options.delete(:width) || "100%").to_s
|
46
46
|
defer = !!options.delete(:defer)
|
47
47
|
# content_for: nil must override default
|
48
48
|
content_for = options.key?(:content_for) ? options.delete(:content_for) : Chartkick.content_for
|
49
49
|
|
50
|
-
nonce = options.delete(:nonce)
|
51
50
|
if nonce == true
|
52
51
|
# Secure Headers also defines content_security_policy_nonce but it takes an argument
|
53
52
|
# Rails 5.2 overrides this method, but earlier versions do not
|
@@ -57,6 +56,8 @@ module Chartkick
|
|
57
56
|
elsif respond_to?(:content_security_policy_script_nonce)
|
58
57
|
# Secure Headers
|
59
58
|
nonce = content_security_policy_script_nonce
|
59
|
+
else
|
60
|
+
nonce = nil
|
60
61
|
end
|
61
62
|
end
|
62
63
|
nonce_html = nonce ? " nonce=\"#{ERB::Util.html_escape(nonce)}\"" : nil
|
@@ -65,12 +66,26 @@ module Chartkick
|
|
65
66
|
html_vars = {
|
66
67
|
id: element_id,
|
67
68
|
height: height,
|
68
|
-
width: width
|
69
|
+
width: width,
|
70
|
+
# don't delete loading option since it needs to be passed to JS
|
71
|
+
loading: options[:loading] || "Loading..."
|
69
72
|
}
|
73
|
+
|
74
|
+
[:height, :width].each do |k|
|
75
|
+
# limit to alphanumeric and % for simplicity
|
76
|
+
# this prevents things like calc() but safety is the priority
|
77
|
+
# dot does not need escaped in square brackets
|
78
|
+
raise ArgumentError, "Invalid #{k}" unless html_vars[k] =~ /\A[a-zA-Z0-9%.]*\z/
|
79
|
+
end
|
80
|
+
|
70
81
|
html_vars.each_key do |k|
|
82
|
+
# escape all variables
|
83
|
+
# we already limit height and width above, but escape for safety as fail-safe
|
84
|
+
# to prevent XSS injection in worse-case scenario
|
71
85
|
html_vars[k] = ERB::Util.html_escape(html_vars[k])
|
72
86
|
end
|
73
|
-
|
87
|
+
|
88
|
+
html = (options.delete(:html) || %(<div id="%{id}" style="height: %{height}; width: %{width}; text-align: center; color: #999; line-height: %{height}; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;">%{loading}</div>)) % html_vars
|
74
89
|
|
75
90
|
# js vars
|
76
91
|
js_vars = {
|
@@ -84,28 +99,28 @@ module Chartkick
|
|
84
99
|
end
|
85
100
|
createjs = "new Chartkick[%{type}](%{id}, %{data}, %{options});" % js_vars
|
86
101
|
|
87
|
-
if defer
|
88
|
-
|
89
|
-
<
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
102
|
+
warn "[chartkick] The defer option is no longer needed and can be removed" if defer
|
103
|
+
|
104
|
+
# Turbolinks preview restores the DOM except for painted <canvas>
|
105
|
+
# since it uses cloneNode(true) - https://developer.mozilla.org/en-US/docs/Web/API/Node/
|
106
|
+
#
|
107
|
+
# don't rerun JS on preview to prevent
|
108
|
+
# 1. animation
|
109
|
+
# 2. loading data from URL
|
110
|
+
js = <<~JS
|
111
|
+
<script#{nonce_html}>
|
112
|
+
(function() {
|
113
|
+
if (document.documentElement.hasAttribute("data-turbolinks-preview")) return;
|
114
|
+
|
115
|
+
var createChart = function() { #{createjs} };
|
116
|
+
if ("Chartkick" in window) {
|
117
|
+
createChart();
|
118
|
+
} else {
|
119
|
+
window.addEventListener("chartkick:load", createChart, true);
|
120
|
+
}
|
121
|
+
})();
|
122
|
+
</script>
|
123
|
+
JS
|
109
124
|
|
110
125
|
if content_for
|
111
126
|
content_for(content_for) { js.respond_to?(:html_safe) ? js.html_safe : js }
|