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 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