swagchart 1.0.0

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.
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
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,19 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ swagchart (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.3.2)
10
+ rake (10.2.2)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ bundler (~> 1.3)
17
+ minitest
18
+ rake
19
+ swagchart!
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
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task :default => :test
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.pattern = "test/**/*_test.rb"
8
+ end
data/lib/swagchart.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "swagchart/version"
2
+ require "swagchart/helper"
3
+ require "swagchart/rails" if defined?(Rails)
4
+ require "swagchart/sinatra" if defined?(Sinatra)
5
+
6
+ module Swagchart
7
+ class << self
8
+ attr_accessor :content_for
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Swagchart
2
+ class Engine < ::Rails::Engine
3
+
4
+ initializer "helper" do |app|
5
+ ActiveSupport.on_load(:action_view) do
6
+ include Helper
7
+ end
8
+ end
9
+
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ if Rails.version >= "3.1"
2
+ require "swagchart/engine"
3
+ else
4
+ ActionView::Base.send :include, Swagchart::Helper
5
+ end
@@ -0,0 +1,3 @@
1
+ class Sinatra::Base
2
+ helpers Swagchart::Helper
3
+ end
@@ -0,0 +1,3 @@
1
+ module Swagchart
2
+ VERSION = "1.0.0"
3
+ 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
@@ -0,0 +1,4 @@
1
+ require "bundler/setup"
2
+ Bundler.require(:default)
3
+ require "minitest/autorun"
4
+ require "minitest/pride"
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