chartkickm 3.0.4

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.
data/README.md ADDED
@@ -0,0 +1,582 @@
1
+ # Chartkick
2
+
3
+ Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries!
4
+
5
+ [See it in action](https://chartkick.com)
6
+
7
+ :fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/)
8
+
9
+ :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
+
11
+ ---
12
+
13
+ Have a minute? Take the [2019 Chartkick Survey](https://goo.gl/forms/x1Ic62QTKloUV95i1)
14
+
15
+ ---
16
+
17
+ ## Quick Start
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem "chartkick"
23
+ ```
24
+
25
+ In `application.js`, add:
26
+
27
+ ```js
28
+ //= require Chart.bundle
29
+ //= require chartkick
30
+ ```
31
+
32
+ This sets up Chartkick with Chart.js. For other charting libraries, see [detailed instructions](#installation).
33
+
34
+ ## Charts
35
+
36
+ Line chart
37
+
38
+ ```erb
39
+ <%= line_chart User.group_by_day(:created_at).count %>
40
+ ```
41
+
42
+ Pie chart
43
+
44
+ ```erb
45
+ <%= pie_chart Goal.group(:name).count %>
46
+ ```
47
+
48
+ Column chart
49
+
50
+ ```erb
51
+ <%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %>
52
+ ```
53
+
54
+ Bar chart
55
+
56
+ ```erb
57
+ <%= bar_chart Shirt.group(:size).sum(:price) %>
58
+ ```
59
+
60
+ Area chart
61
+
62
+ ```erb
63
+ <%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>
64
+ ```
65
+
66
+ Scatter chart
67
+
68
+ ```erb
69
+ <%= scatter_chart City.pluck(:size, :population) %>
70
+ ```
71
+
72
+ Geo chart - *Google Charts*
73
+
74
+ ```erb
75
+ <%= geo_chart Medal.group(:country).count %>
76
+ ```
77
+
78
+ Timeline - *Google Charts*
79
+
80
+ ```erb
81
+ <%= timeline [
82
+ ["Washington", "1789-04-29", "1797-03-03"],
83
+ ["Adams", "1797-03-03", "1801-03-03"],
84
+ ["Jefferson", "1801-03-03", "1809-03-03"]
85
+ ] %>
86
+ ```
87
+
88
+ Multiple series
89
+
90
+ ```erb
91
+ <%= line_chart @goals.map { |goal|
92
+ {name: goal.name, data: goal.feats.group_by_week(:created_at).count}
93
+ } %>
94
+ ```
95
+
96
+ or
97
+
98
+ ```erb
99
+ <%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %>
100
+ ```
101
+
102
+ ### Say Goodbye To Timeouts
103
+
104
+ Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.
105
+
106
+ ```erb
107
+ <%= line_chart completed_tasks_charts_path %>
108
+ ```
109
+
110
+ And in your controller, pass the data as JSON.
111
+
112
+ ```ruby
113
+ class ChartsController < ApplicationController
114
+ def completed_tasks
115
+ render json: Task.group_by_day(:completed_at).count
116
+ end
117
+ end
118
+ ```
119
+
120
+ For multiple series, add `chart_json` at the end.
121
+
122
+ ```ruby
123
+ render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json
124
+ ```
125
+
126
+ ### Options
127
+
128
+ Id, width, and height
129
+
130
+ ```erb
131
+ <%= line_chart data, id: "users-chart", width: "800px", height: "500px" %>
132
+ ```
133
+
134
+ Min and max values
135
+
136
+ ```erb
137
+ <%= line_chart data, min: 1000, max: 5000 %>
138
+ ```
139
+
140
+ `min` defaults to 0 for charts with non-negative values. Use `nil` to let the charting library decide.
141
+
142
+ Colors
143
+
144
+ ```erb
145
+ <%= line_chart data, colors: ["#b00", "#666"] %>
146
+ ```
147
+
148
+ Stacked columns or bars
149
+
150
+ ```erb
151
+ <%= column_chart data, stacked: true %>
152
+ ```
153
+
154
+ Discrete axis
155
+
156
+ ```erb
157
+ <%= line_chart data, discrete: true %>
158
+ ```
159
+
160
+ Label (for single series)
161
+
162
+ ```erb
163
+ <%= line_chart data, label: "Value" %>
164
+ ```
165
+
166
+ Axis titles
167
+
168
+ ```erb
169
+ <%= line_chart data, xtitle: "Time", ytitle: "Population" %>
170
+ ```
171
+
172
+ Straight lines between points instead of a curve
173
+
174
+ ```erb
175
+ <%= line_chart data, curve: false %>
176
+ ```
177
+
178
+ Hide points
179
+
180
+ ```erb
181
+ <%= line_chart data, points: false %>
182
+ ```
183
+
184
+ Show or hide legend
185
+
186
+ ```erb
187
+ <%= line_chart data, legend: false %>
188
+ ```
189
+
190
+ Specify legend position
191
+
192
+ ```erb
193
+ <%= line_chart data, legend: "bottom" %>
194
+ ```
195
+
196
+ Defer chart creation until after the page loads
197
+
198
+ ```erb
199
+ <%= line_chart data, defer: true %>
200
+ ```
201
+
202
+ Donut chart
203
+
204
+ ```erb
205
+ <%= pie_chart data, donut: true %>
206
+ ```
207
+
208
+ Prefix, useful for currency - *Chart.js, Highcharts*
209
+
210
+ ```erb
211
+ <%= line_chart data, prefix: "$" %>
212
+ ```
213
+
214
+ Suffix, useful for percentages - *Chart.js, Highcharts*
215
+
216
+ ```erb
217
+ <%= line_chart data, suffix: "%" %>
218
+ ```
219
+
220
+ Set a thousands separator - *Chart.js, Highcharts*
221
+
222
+ ```erb
223
+ <%= line_chart data, thousands: "," %>
224
+ ```
225
+
226
+ Set a decimal separator - *Chart.js, Highcharts*
227
+
228
+ ```erb
229
+ <%= line_chart data, decimal: "," %>
230
+ ```
231
+
232
+ Show a message when data is empty
233
+
234
+ ```erb
235
+ <%= line_chart data, messages: {empty: "No data"} %>
236
+ ```
237
+
238
+ Refresh data from a remote source every `n` seconds
239
+
240
+ ```erb
241
+ <%= line_chart url, refresh: 60 %>
242
+ ```
243
+
244
+ You can pass options directly to the charting library with:
245
+
246
+ ```erb
247
+ <%= line_chart data, library: {backgroundColor: "#eee"} %>
248
+ ```
249
+
250
+ See the documentation for [Chart.js](https://www.chartjs.org/docs/), [Google Charts](https://developers.google.com/chart/interactive/docs/gallery), and [Highcharts](https://api.highcharts.com/highcharts) for more info.
251
+
252
+ To customize datasets in Chart.js, use:
253
+
254
+ ```erb
255
+ <%= line_chart data, dataset: {borderWidth: 10} %>
256
+ ```
257
+
258
+ You can pass this option to individual series as well.
259
+
260
+ ### Global Options
261
+
262
+ To set options for all of your charts, create an initializer `config/initializers/chartkick.rb` with:
263
+
264
+ ```ruby
265
+ Chartkick.options = {
266
+ height: "400px",
267
+ colors: ["#b00", "#666"]
268
+ }
269
+ ```
270
+
271
+ Customize the html
272
+
273
+ ```ruby
274
+ Chartkick.options[:html] = '<div id="%{id}" style="height: %{height};">Loading...</div>'
275
+ ```
276
+
277
+ You capture the JavaScript in a content block with:
278
+
279
+ ```ruby
280
+ Chartkick.options[:content_for] = :charts_js
281
+ ```
282
+
283
+ Then, in your layout:
284
+
285
+ ```erb
286
+ <%= yield :charts_js %> <!-- Rails -->
287
+ <%= yield_content :charts_js %> <!-- Padrino -->
288
+ ```
289
+
290
+ This is great for including all of your JavaScript at the bottom of the page.
291
+
292
+ ### Data
293
+
294
+ Pass data as a Hash or Array
295
+
296
+ ```erb
297
+ <%= pie_chart({"Football" => 10, "Basketball" => 5}) %>
298
+ <%= pie_chart [["Football", 10], ["Basketball", 5]] %>
299
+ ```
300
+
301
+ For multiple series, use the format
302
+
303
+ ```erb
304
+ <%= line_chart [
305
+ {name: "Series A", data: series_a},
306
+ {name: "Series B", data: series_b}
307
+ ] %>
308
+ ```
309
+
310
+ Times can be a time or a string (strings are parsed)
311
+
312
+ ```erb
313
+ <%= line_chart({20.day.ago => 5, "2013-05-07 00:00:00 UTC" => 7}) %>
314
+ ```
315
+
316
+ ### Multiple Series
317
+
318
+ You can pass a few options with a series:
319
+
320
+ - `name`
321
+ - `data`
322
+ - `color`
323
+ - `dataset` - *Chart.js only*
324
+ - `points` - *Chart.js only*
325
+ - `curve` - *Chart.js only*
326
+
327
+ ### Code
328
+
329
+ If you want to use the charting library directly, get the code with:
330
+
331
+ ```erb
332
+ <%= line_chart data, code: true %>
333
+ ```
334
+
335
+ The code will be logged to the JavaScript console.
336
+
337
+ **Note:** JavaScript functions cannot be logged, so it may not be identical.
338
+
339
+ ### Download Charts
340
+
341
+ *Chart.js only*
342
+
343
+ Give users the ability to download charts. It all happens in the browser - no server-side code needed.
344
+
345
+ ```erb
346
+ <%= line_chart data, download: true %>
347
+ ```
348
+
349
+ **Note:** Safari will open the image in a new window instead of downloading.
350
+
351
+ Set the filename
352
+
353
+ ```erb
354
+ <%= line_chart data, download: {filename: "boom"} %>
355
+ ```
356
+
357
+ Set the background color
358
+
359
+ ```erb
360
+ <%= line_chart data, download: {background: "#ffffff"} %>
361
+ ```
362
+
363
+ Set title
364
+
365
+ ```erb
366
+ <%= line_chart data, title: "Awesome chart" %>
367
+ ```
368
+
369
+ ## Installation
370
+
371
+ Add this line to your application's Gemfile:
372
+
373
+ ```ruby
374
+ gem "chartkick"
375
+ ```
376
+
377
+ Next, choose your charting library.
378
+
379
+ ### Charting Libraries
380
+
381
+ **Note:** In the instructions below, `application.js` must be included **before** the charts in your views, unless using the `:content_for` option.
382
+
383
+ #### Chart.js
384
+
385
+ In `application.js`, add:
386
+
387
+ ```js
388
+ //= require Chart.bundle
389
+ //= require chartkick
390
+ ```
391
+
392
+ #### Google Charts
393
+
394
+ In `application.js`, add:
395
+
396
+ ```js
397
+ //= require chartkick
398
+ ```
399
+
400
+ In your views, before `application.js`, add:
401
+
402
+ ```erb
403
+ <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
404
+ ```
405
+
406
+ #### Highcharts
407
+
408
+ Download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts` in Rails 5.1+).
409
+
410
+ In `application.js`, add:
411
+
412
+ ```js
413
+ //= require highcharts
414
+ //= require chartkick
415
+ ```
416
+
417
+ Works with Highcharts 2.1+
418
+
419
+ ### Webpacker
420
+
421
+ For Webpacker, use Yarn to install the JavaScript libraries:
422
+
423
+ ```sh
424
+ yarn add chartkick chart.js # or highcharts
425
+ ```
426
+
427
+ Then include them in your pack.
428
+
429
+ ```es6
430
+ import Chartkick from "chartkick";
431
+ window.Chartkick = Chartkick;
432
+
433
+ // for Chart.js
434
+ import Chart from "chart.js";
435
+ Chartkick.addAdapter(Chart);
436
+
437
+ // for Highcharts
438
+ import Highcharts from "highcharts";
439
+ Chartkick.addAdapter(Highcharts);
440
+
441
+ // for Google Charts
442
+ // just include https://www.gstatic.com/charts/loader.js in your views
443
+ ```
444
+
445
+ You pack must be included **before** the charts in your views, unless using the `:content_for` option.
446
+
447
+ ### Sinatra and Padrino
448
+
449
+ You must include `chartkick.js` manually. [Download it here](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js)
450
+
451
+ ```html
452
+ <script src="chartkick.js"></script>
453
+ ```
454
+
455
+ ### Localization
456
+
457
+ To specify a language for Google Charts, add:
458
+
459
+ ```javascript
460
+ Chartkick.configure({language: "de"});
461
+ ```
462
+
463
+ after the JavaScript files and before your charts.
464
+
465
+ ### Multiple Libraries
466
+
467
+ If more than one charting library is loaded, choose between them with:
468
+
469
+ ```erb
470
+ <%= line_chart data, adapter: "google" %> <!-- or highcharts or chartjs -->
471
+ ```
472
+
473
+ ## JavaScript API
474
+
475
+ Access a chart with:
476
+
477
+ ```javascript
478
+ var chart = Chartkick.charts["chart-id"]
479
+ ```
480
+
481
+ Get the underlying chart object with:
482
+
483
+ ```javascript
484
+ chart.getChartObject()
485
+ ```
486
+
487
+ You can also use:
488
+
489
+ ```javascript
490
+ chart.getElement()
491
+ chart.getData()
492
+ chart.getOptions()
493
+ chart.getAdapter()
494
+ ```
495
+
496
+ Update the data with:
497
+
498
+ ```javascript
499
+ chart.updateData(newData)
500
+ ```
501
+
502
+ You can also specify new options:
503
+
504
+ ```javascript
505
+ chart.setOptions(newOptions)
506
+ // or
507
+ chart.updateData(newData, newOptions)
508
+ ```
509
+
510
+ Refresh the data from a remote source:
511
+
512
+ ```javascript
513
+ chart.refreshData()
514
+ ```
515
+
516
+ Redraw the chart with:
517
+
518
+ ```javascript
519
+ chart.redraw()
520
+ ```
521
+
522
+ Loop over charts with:
523
+
524
+ ```javascript
525
+ Chartkick.eachChart( function(chart) {
526
+ // do something
527
+ })
528
+ ```
529
+
530
+ ## Content Security Policy (CSP)
531
+
532
+ Check out [how to configure CSP](https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md)
533
+
534
+ ## No Ruby? No Problem
535
+
536
+ Check out [chartkick.js](https://github.com/ankane/chartkick.js)
537
+
538
+ ## Tutorials
539
+
540
+ - [Charts with Chartkick and Groupdate](https://gorails.com/episodes/charts-with-chartkick-and-groupdate)
541
+ - [Creando gráficos en Ruby on Rails con Chartkick y Chart.js](https://www.youtube.com/watch?v=W92AlkwQn3M)
542
+ - [Make Easy Graphs and Charts on Rails with Chartkick](https://www.sitepoint.com/make-easy-graphs-and-charts-on-rails-with-chartkick/)
543
+ - [Practical Graphs on Rails: Chartkick in Practice](https://www.sitepoint.com/graphs-on-rails-chartkick-in-practice/)
544
+
545
+ ## Upgrading
546
+
547
+ ### 3.0
548
+
549
+ Breaking changes
550
+
551
+ - Removed support for Rails < 4.2
552
+ - Removed chartkick.js from asset precompile (no longer needed)
553
+ - Removed `xtype` option - numeric axes are automatically detected
554
+ - Removed `window.Chartkick = {...}` way to set config - use `Chartkick.configure` instead
555
+ - Removed support for the Google Charts jsapi loader - use loader.js instead
556
+
557
+ ### 2.0
558
+
559
+ Breaking changes
560
+
561
+ - Chart.js is now the default adapter if multiple are loaded - yay open source!
562
+ - Axis types are automatically detected - no need for `discrete: true`
563
+ - Better date support - dates are no longer treated as UTC
564
+
565
+ ## Credits
566
+
567
+ Chartkick uses [iso8601.js](https://github.com/Do/iso8601.js) to parse dates and times.
568
+
569
+ ## History
570
+
571
+ View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md)
572
+
573
+ Chartkick follows [Semantic Versioning](https://semver.org/)
574
+
575
+ ## Contributing
576
+
577
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
578
+
579
+ - [Report bugs](https://github.com/ankane/chartkick/issues)
580
+ - Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls)
581
+ - Write, clarify, or fix documentation
582
+ - Suggest or add new features
@@ -0,0 +1,5 @@
1
+ module Chartkick
2
+ class Engine < ::Rails::Engine
3
+ # for assets
4
+ end
5
+ end
@@ -0,0 +1,109 @@
1
+ require "json"
2
+ require "erb"
3
+
4
+ module Chartkick
5
+ module Helper
6
+ def line_chart(data_source, **options)
7
+ chartkick_chart "LineChart", data_source, options
8
+ end
9
+
10
+ def pie_chart(data_source, **options)
11
+ chartkick_chart "PieChart", data_source, options
12
+ end
13
+
14
+ def column_chart(data_source, **options)
15
+ chartkick_chart "ColumnChart", data_source, options
16
+ end
17
+
18
+ def bar_chart(data_source, **options)
19
+ chartkick_chart "BarChart", data_source, options
20
+ end
21
+
22
+ def area_chart(data_source, **options)
23
+ chartkick_chart "AreaChart", data_source, options
24
+ end
25
+
26
+ def scatter_chart(data_source, **options)
27
+ chartkick_chart "ScatterChart", data_source, options
28
+ end
29
+
30
+ def geo_chart(data_source, **options)
31
+ chartkick_chart "GeoChart", data_source, options
32
+ end
33
+
34
+ def timeline(data_source, **options)
35
+ chartkick_chart "Timeline", data_source, options
36
+ end
37
+
38
+ private
39
+
40
+ def chartkick_chart(klass, data_source, **options)
41
+ @chartkick_chart_id ||= 0
42
+ options = chartkick_deep_merge(Chartkick.options, options)
43
+ element_id = options.delete(:id) || "chart-#{@chartkick_chart_id += 1}"
44
+ height = options.delete(:height) || "300px"
45
+ width = options.delete(:width) || "100%"
46
+ defer = !!options.delete(:defer)
47
+ # content_for: nil must override default
48
+ content_for = options.key?(:content_for) ? options.delete(:content_for) : Chartkick.content_for
49
+
50
+ nonce = options.delete(:nonce)
51
+ if nonce == true
52
+ # Secure Headers also defines content_security_policy_nonce but it takes an argument
53
+ # Rails 5.2 overrides this method, but earlier versions do not
54
+ if respond_to?(:content_security_policy_nonce) && (content_security_policy_nonce rescue nil)
55
+ # Rails 5.2
56
+ nonce = content_security_policy_nonce
57
+ elsif respond_to?(:content_security_policy_script_nonce)
58
+ # Secure Headers
59
+ nonce = content_security_policy_script_nonce
60
+ end
61
+ end
62
+ nonce_html = nonce ? " nonce=\"#{ERB::Util.html_escape(nonce)}\"" : nil
63
+
64
+ 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>)) % {id: ERB::Util.html_escape(element_id), height: ERB::Util.html_escape(height), width: ERB::Util.html_escape(width)}
65
+
66
+ createjs = "new Chartkick.#{klass}(#{element_id.to_json}, #{data_source.respond_to?(:chart_json) ? data_source.chart_json : data_source.to_json}, #{options.to_json});"
67
+ if defer
68
+ js = <<JS
69
+ <script type="text/javascript"#{nonce_html}>
70
+ (function() {
71
+ var createChart = function() { #{createjs} };
72
+ if (window.addEventListener) {
73
+ window.addEventListener("load", createChart, true);
74
+ } else if (window.attachEvent) {
75
+ window.attachEvent("onload", createChart);
76
+ } else {
77
+ createChart();
78
+ }
79
+ })();
80
+ </script>
81
+ JS
82
+ else
83
+ js = <<JS
84
+ <script type="text/javascript"#{nonce_html}>
85
+ #{createjs}
86
+ </script>
87
+ JS
88
+ end
89
+
90
+ if content_for
91
+ content_for(content_for) { js.respond_to?(:html_safe) ? js.html_safe : js }
92
+ else
93
+ html += js
94
+ end
95
+
96
+ html.respond_to?(:html_safe) ? html.html_safe : html
97
+ end
98
+
99
+ # https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
100
+ def chartkick_deep_merge(hash_a, hash_b)
101
+ hash_a = hash_a.dup
102
+ hash_b.each_pair do |k, v|
103
+ tv = hash_a[k]
104
+ hash_a[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? chartkick_deep_merge(tv, v) : v
105
+ end
106
+ hash_a
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,5 @@
1
+ require "sinatra/base"
2
+
3
+ class Sinatra::Base
4
+ helpers Chartkick::Helper
5
+ end
@@ -0,0 +1,3 @@
1
+ module Chartkick
2
+ VERSION = "3.0.4"
3
+ end