swagchart 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +8 -0
- data/lib/swagchart.rb +10 -0
- data/lib/swagchart/engine.rb +11 -0
- data/lib/swagchart/helper.rb +111 -0
- data/lib/swagchart/rails.rb +5 -0
- data/lib/swagchart/sinatra.rb +3 -0
- data/lib/swagchart/version.rb +3 -0
- data/swagchart.gemspec +24 -0
- data/test/swagchart_test.rb +39 -0
- data/test/test_helper.rb +4 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f50cb24ac13690119021c8ccf54150f0a899933a
|
4
|
+
data.tar.gz: 224b0d54724f4150d6482ee47b50c710f7fe8e41
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8aba1feb3a8ddf4f6a4b8f31baa2ea0c64233f3cda53f9e52fc0a986b6bc024dfc6b468e007ebc381120626a7b9eb2dae3b87bf134a40e7b2a4295d471c3b894
|
7
|
+
data.tar.gz: 3f2f57951567c41f1d64b3060c1f5b4ce5ddda9e4a7528899be0790bbfbfd7f1f21119782f4db6632d252012232951c1bb0a678cc833bb456c3bbdb325fb930e
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Swagchart
|
2
|
+
|
3
|
+
Get your swag on with this incredibly easy to use wrapper around [Googles Chart API](https://developers.google.com/chart/).
|
4
|
+
|
5
|
+
In case you haven't noticed, Swagchart is just an acronym for **S**.imple **W**.rapper **A**.round **G**.oogle **Chart**.
|
6
|
+
|
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.
|
8
|
+
|
9
|
+
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
|
+
|
11
|
+
Works with Rails, Sinatra and most browsers (including IE 6).
|
12
|
+
|
13
|
+
## Usage examples
|
14
|
+
|
15
|
+
Line chart
|
16
|
+
|
17
|
+
```erb
|
18
|
+
<%= chart :line_chart, User.group_by_day(:created_at).count %>
|
19
|
+
```
|
20
|
+
|
21
|
+
Pie chart
|
22
|
+
|
23
|
+
```erb
|
24
|
+
<%= chart 'PieChart', Goal.group(:name).count %>
|
25
|
+
```
|
26
|
+
|
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
|
+
### Data
|
34
|
+
|
35
|
+
Pass data as a Array, Hash or "DataTable"
|
36
|
+
|
37
|
+
```erb
|
38
|
+
<%= chart :pie_chart, [["Football", 10], ["Basketball", 5]] %>
|
39
|
+
```
|
40
|
+
|
41
|
+
```erb
|
42
|
+
<%= chart :pie_chart, {"Football" => 10, "Basketball" => 5} %>
|
43
|
+
```
|
44
|
+
|
45
|
+
```erb
|
46
|
+
<%= chart :pie_chart, [["Sport", "Popularity"], ["Football", 10], ["Basketball", 5]] %>
|
47
|
+
```
|
48
|
+
|
49
|
+
Multiple series just work automatically
|
50
|
+
|
51
|
+
```erb
|
52
|
+
<%= chart :line_chart [[1,2,4],[2,3,8],[3,4,16],[4,5,32]], columns: ['x', 'Series 1', 'Series 2'] %>
|
53
|
+
```
|
54
|
+
|
55
|
+
If you want to use times or dates, do so. They have to be a time or date object!
|
56
|
+
|
57
|
+
|
58
|
+
```erb
|
59
|
+
<%= line_chart({20.day.ago => 5, Time.at(1368174456) => 4, Time.parse("2013-05-07 00:00:00 UTC") => 7, Date.new(1999,12,24) => 9}) %>
|
60
|
+
|
61
|
+
```
|
62
|
+
|
63
|
+
|
64
|
+
## Installation
|
65
|
+
|
66
|
+
Add this line to your application's Gemfile:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
gem "swagchart"
|
70
|
+
```
|
71
|
+
|
72
|
+
And add the javascript files to your views. These files must be included **before** the helper methods.
|
73
|
+
|
74
|
+
|
75
|
+
```erb
|
76
|
+
<script type="text/javascript" src="//www.google.com/jsapi"></script>
|
77
|
+
```
|
78
|
+
|
79
|
+
|
80
|
+
## Contributing
|
81
|
+
|
82
|
+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
83
|
+
|
84
|
+
- Report bugs
|
85
|
+
- Fix bugs and submit pull requests
|
86
|
+
- Write, clarify, or fix documentation
|
87
|
+
- Suggest or add new features
|
data/Rakefile
ADDED
data/lib/swagchart.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'time'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Swagchart
|
6
|
+
module Helper
|
7
|
+
|
8
|
+
def chart(type, data, opts={}, &block)
|
9
|
+
@google_visualization_included ||= false
|
10
|
+
@chart_counter ||= 0
|
11
|
+
type = camelize(type.to_s)
|
12
|
+
opts[:columns] = opts[:columns].split(',').map(&:strip) if opts[:columns].is_a?(String)
|
13
|
+
data = data.to_a if data.is_a?(Hash)
|
14
|
+
if data.respond_to?(:first) && data.first.is_a?(Hash)
|
15
|
+
data = hash_array_to_data_table(data)
|
16
|
+
opts.delete(:columns)
|
17
|
+
elsif data.respond_to?(:unshift) && data.respond_to?(:first)
|
18
|
+
if opts[:columns]
|
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
|
26
|
+
end
|
27
|
+
chart_id = ERB::Util.html_escape(opts.delete(:chart_id) || "chart_#{@chart_counter += 1}")
|
28
|
+
style = 'height:320px;' #dirty hack right here .. you can override that with your style though
|
29
|
+
style << ERB::Util.html_escape(opts.delete(:style)) if opts[:style]
|
30
|
+
html = ''
|
31
|
+
unless @google_visualization_included #we only need to include this once
|
32
|
+
html << jsapi_includes_template
|
33
|
+
@google_visualization_included = true
|
34
|
+
end
|
35
|
+
options = opts.delete(:options) || {}
|
36
|
+
html << classic_template(id: chart_id, type: type, style: style, options: options, data: data)
|
37
|
+
html.respond_to?(:html_safe) ? html.html_safe : html
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def hash_array_to_data_table(ha)
|
43
|
+
cols = ha.first.keys
|
44
|
+
rows = ha.map{|r| cols.reduce([]){|s,e| s<<r[e]} }
|
45
|
+
[cols, *rows]
|
46
|
+
end
|
47
|
+
|
48
|
+
def camelize(str)
|
49
|
+
str.split('_').each(&:capitalize!).join('')
|
50
|
+
end
|
51
|
+
|
52
|
+
# This finds and replaces some string representations of
|
53
|
+
# Ruby objects to their JavaScript equivalents.
|
54
|
+
# Yes it's dirty and using Ruby 2.x refinements to replace the
|
55
|
+
# to_s methods of those objects only in this module would
|
56
|
+
# be simply awesome, but refinements dont work in Ruby 1.x.
|
57
|
+
# TODO: Check if refinements are available and do either the
|
58
|
+
# right or the dirty thing.
|
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)
|
67
|
+
end
|
68
|
+
|
69
|
+
def classic_template(opts={})
|
70
|
+
<<HTML
|
71
|
+
<div id='#{opts[:id]}' style='#{opts[:style]}'>Loading...</div>
|
72
|
+
<script type='text/javascript'>
|
73
|
+
google.setOnLoadCallback(function(){
|
74
|
+
new google.visualization.#{opts[:type]}(document.getElementById('#{opts[:id]}')).draw(
|
75
|
+
google.visualization.arrayToDataTable(
|
76
|
+
#{ruby_to_js_conversions(opts[:data])}
|
77
|
+
), #{opts[:options].to_json});
|
78
|
+
});
|
79
|
+
</script>
|
80
|
+
HTML
|
81
|
+
end
|
82
|
+
|
83
|
+
def chartwrapper_template(opts={})
|
84
|
+
<<HTML
|
85
|
+
<div id='#{opts[:id]}' style='#{opts[:style]}'>Loading...</div>
|
86
|
+
<script type='text/javascript'>
|
87
|
+
google.setOnLoadCallback(function(){
|
88
|
+
new google.visualization.ChartWrapper({
|
89
|
+
chartType: '#{opts[:type]}',
|
90
|
+
containerId: '#{opts[:id]}',
|
91
|
+
options: #{opts[:options].to_json},
|
92
|
+
dataTable: #{ruby_to_js_conversions(opts[:data])}
|
93
|
+
}).draw();
|
94
|
+
});
|
95
|
+
</script>
|
96
|
+
HTML
|
97
|
+
end
|
98
|
+
|
99
|
+
def jsapi_includes_template
|
100
|
+
<<HTML
|
101
|
+
<script type='text/javascript'>
|
102
|
+
google.load('visualization','1');
|
103
|
+
google.load('visualization', '1', {packages: [
|
104
|
+
'corechart', 'geochart', 'map', 'treemap', 'annotatedtimeline',
|
105
|
+
'sankey', 'orgchart', 'calendar', 'gauge'
|
106
|
+
]});
|
107
|
+
</script>
|
108
|
+
HTML
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/swagchart.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'swagchart/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "swagchart"
|
8
|
+
spec.version = Swagchart::VERSION
|
9
|
+
spec.authors = ["pachacamac", "naema"]
|
10
|
+
spec.email = []
|
11
|
+
spec.description = %q{Use Google Charts easily within your Rails or Sinatra project or anywhere really}
|
12
|
+
spec.summary = %q{Small Wrapper Around Google CHARTS}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "minitest"
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
class TestSwagchart < Minitest::Test
|
5
|
+
include Swagchart::Helper
|
6
|
+
|
7
|
+
def test_no_random_exceptions
|
8
|
+
assert chart(:line_chart, [[23, 42], [666, 999]], columns: ['x', 'y'])
|
9
|
+
assert chart(:line_chart, [[23, 42], [666, 999]], columns: ['x', 'y'], style: 'width:100%;')
|
10
|
+
assert chart(:bar_chart, [['x', 'y'],[23, 42], [666, 999]])
|
11
|
+
assert chart('GeoMap', [{'Country'=>'Germany', 'Population'=>8600000}, {'Country'=>'France', 'Population'=>6500000}])
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_time_object_literals
|
15
|
+
t = Time.parse('2014-12-24 13:37:04')
|
16
|
+
raw_chart = chart(:line_chart, [[t, 42], [t+3600, 999]], columns: ['x', 'y'])
|
17
|
+
assert raw_chart.include?('new Date(2014,11,24,13,37,4)') #month starts at 0 in js
|
18
|
+
assert raw_chart.include?('new Date(2014,11,24,14,37,4)')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_date_object_literals
|
22
|
+
d1, d2 = Date.new(2014, 12, 24), Date.new(2014, 12, 31)
|
23
|
+
raw_chart = chart(:line_chart, [[d1, 42], [d2, 999]], columns: ['x', 'y'])
|
24
|
+
assert raw_chart.include?('new Date(2014,11,24)')
|
25
|
+
assert raw_chart.include?('new Date(2014,11,31)')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_datetime_object_literals
|
29
|
+
dt = Time.parse('2014-12-24 13:37:04').to_datetime
|
30
|
+
raw_chart = chart(:line_chart, [[dt, 42]], columns: ['x', 'y'])
|
31
|
+
assert raw_chart.include?('new Date(2014,11,24,13,37,4)')
|
32
|
+
end
|
33
|
+
|
34
|
+
# def test_chart_output
|
35
|
+
# puts chart('GeoMap', [{'Country'=>'Germany', 'Population'=>8600000}, {'Country'=>'France', 'Population'=>6500000}], columns: ['x', 'y'], :hAxis => {title: 'Year'}, style:'width:100%;')
|
36
|
+
# puts chart(:line_chart, [[23, 42], [666, 999]], columns: ['x', 'y'])
|
37
|
+
# end
|
38
|
+
|
39
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: swagchart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- pachacamac
|
8
|
+
- naema
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-08-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.3'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.3'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: minitest
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: Use Google Charts easily within your Rails or Sinatra project or anywhere
|
57
|
+
really
|
58
|
+
email: []
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/swagchart.rb
|
69
|
+
- lib/swagchart/engine.rb
|
70
|
+
- lib/swagchart/helper.rb
|
71
|
+
- lib/swagchart/rails.rb
|
72
|
+
- lib/swagchart/sinatra.rb
|
73
|
+
- lib/swagchart/version.rb
|
74
|
+
- swagchart.gemspec
|
75
|
+
- test/swagchart_test.rb
|
76
|
+
- test/test_helper.rb
|
77
|
+
homepage: ''
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.2.2
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Small Wrapper Around Google CHARTS
|
101
|
+
test_files:
|
102
|
+
- test/swagchart_test.rb
|
103
|
+
- test/test_helper.rb
|