swagchart 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +16 -8
- data/lib/swagchart/engine.rb +5 -0
- data/lib/swagchart/helper.rb +50 -60
- data/lib/swagchart/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c5d21471ee4516f2b8024db7323fc791add9ff4
|
4
|
+
data.tar.gz: 58ca0c97ccb96fcdcc96865a1263d24ef1d8009d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2cbe5e3eeb86fb57d1a72029c8825cc756e031cb239d0a54d2c75d78a1002a4516f1f5b2523e6ccfd3359b1b5228101bfa89af828aabf422d4fc1176cfda3da7
|
7
|
+
data.tar.gz: f1b066aa02bfd5999510573aba7beb2a67cc99c6a6f6c754b1883c1144c5ed84458adc26c6998ebe87164fe85e57c1940e84179859a138b16e17619187c9ad9a
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/*
|
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# Swagchart
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/swagchart.svg)](http://badge.fury.io/rb/swagchart) ![Installs](http://img.shields.io/gem/dt/swagchart.svg)
|
4
|
+
|
3
5
|
Get your swag on with this incredibly easy to use wrapper around [Googles Chart API](https://developers.google.com/chart/).
|
4
6
|
|
5
7
|
In case you haven't noticed, Swagchart is just an acronym for **S**.imple **W**.rapper **A**.round **G**.oogle **Chart**.
|
6
8
|
|
7
|
-
Swagchart is highly inspired by [Chartkick](https://github.com/ankane/chartkick) but making use of Googles new ChartWrapper class which allows a more flexible and direct interaction.
|
9
|
+
Swagchart is highly inspired by [Chartkick](https://github.com/ankane/chartkick) ~~but making use of Googles new ChartWrapper class which allows a more flexible and direct interaction.~~ (the code is still in there and you can enable it if you want to .. look at lib/swagchart/helper.rb .. but unfortunately ChartWrapper doesn't allow many charts so I switched back to the classic approach by default).
|
8
10
|
|
9
11
|
You can still create beautiful Javascript charts with one line of Ruby. In fact now you can pretty much use all the fancy chart types from [Googles Chart API](https://developers.google.com/chart/interactive/docs/gallery).
|
10
12
|
|
@@ -24,12 +26,6 @@ Pie chart
|
|
24
26
|
<%= chart 'PieChart', Goal.group(:name).count %>
|
25
27
|
```
|
26
28
|
|
27
|
-
~~Keep in mind that camelize is only available with activesupport. Use the camelized chart names ... i.e. "LineChart" instead of "line_chart"~~
|
28
|
-
|
29
|
-
:thought_balloon: ... Note to self: Include more examples ...
|
30
|
-
|
31
|
-
|
32
|
-
|
33
29
|
### Data
|
34
30
|
|
35
31
|
Pass data as a Array, Hash or "DataTable"
|
@@ -49,7 +45,19 @@ Pass data as a Array, Hash or "DataTable"
|
|
49
45
|
Multiple series just work automatically
|
50
46
|
|
51
47
|
```erb
|
52
|
-
<%= chart :line_chart [[1,2,4],[2,3,8],[3,4,16],[4,5,32]], columns: ['x', 'Series 1', 'Series 2'] %>
|
48
|
+
<%= chart :line_chart, [[1,2,4],[2,3,8],[3,4,16],[4,5,32]], columns: ['x', 'Series 1', 'Series 2'] %>
|
49
|
+
```
|
50
|
+
|
51
|
+
No need to define columns if you don't want to
|
52
|
+
|
53
|
+
```erb
|
54
|
+
<%= chart :line_chart, [[1,2,4],[2,3,8],[3,4,16],[4,5,32]] %>
|
55
|
+
```
|
56
|
+
|
57
|
+
:sparkles: Now brand new: Instead of actual data you can just provide an URL from where the data will be retrieved via an Ajax Get request
|
58
|
+
|
59
|
+
```erb
|
60
|
+
<%= chart :line_chart, '/api/line-chart-data' %>
|
53
61
|
```
|
54
62
|
|
55
63
|
If you want to use times or dates, do so. They have to be a time or date object!
|
data/lib/swagchart/engine.rb
CHANGED
data/lib/swagchart/helper.rb
CHANGED
@@ -5,7 +5,13 @@ require 'erb'
|
|
5
5
|
module Swagchart
|
6
6
|
module Helper
|
7
7
|
|
8
|
+
def default_chart_options(opts={})
|
9
|
+
@default_chart_options = opts
|
10
|
+
end
|
11
|
+
|
8
12
|
def chart(type, data, opts={}, &block)
|
13
|
+
opts[:options] ||= {}
|
14
|
+
opts[:options] = (@default_chart_options || {}).merge(opts[:options])
|
9
15
|
@google_visualization_included ||= false
|
10
16
|
@chart_counter ||= 0
|
11
17
|
type = camelize(type.to_s)
|
@@ -14,15 +20,8 @@ module Swagchart
|
|
14
20
|
if data.respond_to?(:first) && data.first.is_a?(Hash)
|
15
21
|
data = hash_array_to_data_table(data)
|
16
22
|
opts.delete(:columns)
|
17
|
-
elsif data.respond_to?(:unshift) && data.respond_to?(:first)
|
18
|
-
|
19
|
-
data.unshift opts.delete(:columns)
|
20
|
-
elsif !data.first.find{|e| !e.is_a?(String) && !e.is_a?(Symbol) }
|
21
|
-
# Do nothing! This should already be in a DataTable format.
|
22
|
-
# First row seems to only define column names.
|
23
|
-
else
|
24
|
-
data.unshift Array.new(data.first.size, '')
|
25
|
-
end
|
23
|
+
elsif data.respond_to?(:unshift) && data.respond_to?(:first) && opts[:columns]
|
24
|
+
data.unshift opts.delete(:columns)
|
26
25
|
end
|
27
26
|
chart_id = ERB::Util.html_escape(opts.delete(:chart_id) || "chart_#{@chart_counter += 1}")
|
28
27
|
style = 'height:320px;' #dirty hack right here .. you can override that with your style though
|
@@ -33,7 +32,7 @@ module Swagchart
|
|
33
32
|
@google_visualization_included = true
|
34
33
|
end
|
35
34
|
options = opts.delete(:options) || {}
|
36
|
-
html <<
|
35
|
+
html << chart_template(id: chart_id, type: type, style: style, options: options, data: data)
|
37
36
|
html.respond_to?(:html_safe) ? html.html_safe : html
|
38
37
|
end
|
39
38
|
|
@@ -49,63 +48,54 @@ module Swagchart
|
|
49
48
|
str.split('_').each(&:capitalize!).join('')
|
50
49
|
end
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
def ruby_to_js_conversions(str)
|
60
|
-
str.to_s.gsub(/["'](\d\d\d\d-\d\d-\d\d.*?)["']/){"new Date(Date.parse('#{$1}'))"}
|
61
|
-
.gsub(/\bnil\b/, 'null')
|
62
|
-
#drx = /#<Date: (\d\d\d\d)-(\d\d)-(\d\d).*?>/
|
63
|
-
#dtrx= /#<DateTime: (\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)\+\d\d:\d\d .*?>/
|
64
|
-
#trx = /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d) \+\d\d\d\d/
|
65
|
-
#blk = ->(s){v=$~.captures.map(&:to_i); v[1]-=1; "new Date(#{v.join(',')})"}
|
66
|
-
#str.to_s.gsub(dtrx, &blk).gsub(drx, &blk).gsub(trx, &blk)
|
51
|
+
def autocast_data_template
|
52
|
+
js = "for(var i=0;i<data.length;i++){for(var j=0;j<data[i].length;j++){if(typeof data[i][j] === 'string'){"
|
53
|
+
js << 'if(data[i][j].match(/\d\d\d\d-\d\d-\d\d.*?/)){data[i][j] = new Date(Date.parse(data[i][j]));}'
|
54
|
+
js << "else if(data[i][j] == 'nil'){data[i][j] = null;}"
|
55
|
+
js << "}}};"
|
56
|
+
js << "data.unshift(Array(data[0].length).join('.').split('.'));"
|
57
|
+
js
|
67
58
|
end
|
68
59
|
|
69
|
-
def
|
70
|
-
|
71
|
-
<
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
), #{opts[:options].to_json});
|
78
|
-
});
|
79
|
-
</script>
|
80
|
-
HTML
|
60
|
+
def chart_template(opts={})
|
61
|
+
html = "<div id='#{opts[:id]}' style='#{opts[:style]}'>Loading...</div>"
|
62
|
+
html << "<script type='text/javascript'>"
|
63
|
+
html << "google.setOnLoadCallback(function(){"
|
64
|
+
chart_js = chart_js_template(opts)
|
65
|
+
html << (opts[:data].is_a?(String) ? async_ajax_load_wrapper(opts[:data], chart_js) : chart_js)
|
66
|
+
html << "});</script>"
|
67
|
+
html
|
81
68
|
end
|
82
69
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
70
|
+
def chart_js_template(opts={})
|
71
|
+
js = ''
|
72
|
+
js << "var data = #{opts[:data]};" unless opts[:data].is_a?(String)
|
73
|
+
js << autocast_data_template
|
74
|
+
js << "var dt = google.visualization.arrayToDataTable(data);"
|
75
|
+
js << "new google.visualization.#{opts[:type]}(document.getElementById('#{opts[:id]}')).draw(dt, #{opts[:options].to_json});"
|
76
|
+
js
|
77
|
+
end
|
78
|
+
|
79
|
+
def async_ajax_load_wrapper(url, js_code)
|
80
|
+
js = "var xhr = new XMLHttpRequest();"
|
81
|
+
js << "xhr.onreadystatechange = function(){"
|
82
|
+
js << "if(xhr.readyState === 4) { if(xhr.status>=200 && xhr.status<400){"
|
83
|
+
js << "var data = JSON.parse(xhr.responseText);"
|
84
|
+
js << js_code
|
85
|
+
js << "}else{ console.log('Could not load data from #{url}. Status ' + xhr.status); }}};"
|
86
|
+
js << "xhr.open('GET', '#{url}'); xhr.send(null);"
|
87
|
+
js
|
97
88
|
end
|
98
89
|
|
99
90
|
def jsapi_includes_template
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
</script>
|
108
|
-
HTML
|
91
|
+
html = "<script type='text/javascript'>"
|
92
|
+
html << "google.load('visualization', '1');"
|
93
|
+
html << "google.load('visualization', '1', {packages: ["
|
94
|
+
html << "'corechart', 'geochart', 'map', 'treemap', 'annotatedtimeline','sankey', 'orgchart', 'calendar', 'gauge', 'timeline'"
|
95
|
+
html << "]});"
|
96
|
+
html << "</script>"
|
97
|
+
html
|
109
98
|
end
|
99
|
+
|
110
100
|
end
|
111
101
|
end
|
data/lib/swagchart/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swagchart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pachacamac
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-04-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -60,6 +60,7 @@ executables: []
|
|
60
60
|
extensions: []
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
|
+
- ".gitignore"
|
63
64
|
- Gemfile
|
64
65
|
- Gemfile.lock
|
65
66
|
- LICENSE.txt
|
@@ -94,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
95
|
version: '0'
|
95
96
|
requirements: []
|
96
97
|
rubyforge_project:
|
97
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.4.8
|
98
99
|
signing_key:
|
99
100
|
specification_version: 4
|
100
101
|
summary: Small Wrapper Around Google CHARTS
|