swagchart 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f50cb24ac13690119021c8ccf54150f0a899933a
4
- data.tar.gz: 224b0d54724f4150d6482ee47b50c710f7fe8e41
3
+ metadata.gz: 2c5d21471ee4516f2b8024db7323fc791add9ff4
4
+ data.tar.gz: 58ca0c97ccb96fcdcc96865a1263d24ef1d8009d
5
5
  SHA512:
6
- metadata.gz: 8aba1feb3a8ddf4f6a4b8f31baa2ea0c64233f3cda53f9e52fc0a986b6bc024dfc6b468e007ebc381120626a7b9eb2dae3b87bf134a40e7b2a4295d471c3b894
7
- data.tar.gz: 3f2f57951567c41f1d64b3060c1f5b4ce5ddda9e4a7528899be0790bbfbfd7f1f21119782f4db6632d252012232951c1bb0a678cc833bb456c3bbdb325fb930e
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!
@@ -2,6 +2,11 @@ module Swagchart
2
2
  class Engine < ::Rails::Engine
3
3
 
4
4
  initializer "helper" do |app|
5
+
6
+ ActiveSupport.on_load(:action_controller) do
7
+ include Helper
8
+ end
9
+
5
10
  ActiveSupport.on_load(:action_view) do
6
11
  include Helper
7
12
  end
@@ -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
- 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
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 << classic_template(id: chart_id, type: type, style: style, options: options, data: data)
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
- # 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)
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 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
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 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
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
- <<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
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
@@ -1,3 +1,3 @@
1
1
  module Swagchart
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
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.0.0
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: 2014-08-05 00:00:00.000000000 Z
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.2.2
98
+ rubygems_version: 2.4.8
98
99
  signing_key:
99
100
  specification_version: 4
100
101
  summary: Small Wrapper Around Google CHARTS