google_visualr_rails5 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +159 -0
  4. data/Rakefile +9 -0
  5. data/lib/google_visualr.rb +53 -0
  6. data/lib/google_visualr/app/helpers/view_helper.rb +26 -0
  7. data/lib/google_visualr/app/railtie.rb +19 -0
  8. data/lib/google_visualr/base_chart.rb +100 -0
  9. data/lib/google_visualr/data_table.rb +294 -0
  10. data/lib/google_visualr/formatters.rb +78 -0
  11. data/lib/google_visualr/image/bar_chart.rb +47 -0
  12. data/lib/google_visualr/image/line_chart.rb +47 -0
  13. data/lib/google_visualr/image/pie_chart.rb +47 -0
  14. data/lib/google_visualr/image/spark_line.rb +34 -0
  15. data/lib/google_visualr/interactive/annotated_time_line.rb +11 -0
  16. data/lib/google_visualr/interactive/annotation_chart.rb +11 -0
  17. data/lib/google_visualr/interactive/area_chart.rb +13 -0
  18. data/lib/google_visualr/interactive/bar_chart.rb +29 -0
  19. data/lib/google_visualr/interactive/bubble_chart.rb +13 -0
  20. data/lib/google_visualr/interactive/calendar.rb +11 -0
  21. data/lib/google_visualr/interactive/candlestick_chart.rb +13 -0
  22. data/lib/google_visualr/interactive/column_chart.rb +29 -0
  23. data/lib/google_visualr/interactive/combo_chart.rb +13 -0
  24. data/lib/google_visualr/interactive/gantt_chart.rb +16 -0
  25. data/lib/google_visualr/interactive/gauge.rb +11 -0
  26. data/lib/google_visualr/interactive/geo_chart.rb +11 -0
  27. data/lib/google_visualr/interactive/geo_map.rb +11 -0
  28. data/lib/google_visualr/interactive/histogram.rb +14 -0
  29. data/lib/google_visualr/interactive/intensity_map.rb +11 -0
  30. data/lib/google_visualr/interactive/line_chart.rb +21 -0
  31. data/lib/google_visualr/interactive/map.rb +11 -0
  32. data/lib/google_visualr/interactive/motion_chart.rb +11 -0
  33. data/lib/google_visualr/interactive/org_chart.rb +11 -0
  34. data/lib/google_visualr/interactive/pie_chart.rb +13 -0
  35. data/lib/google_visualr/interactive/sankey.rb +11 -0
  36. data/lib/google_visualr/interactive/scatter_chart.rb +21 -0
  37. data/lib/google_visualr/interactive/stepped_area_chart.rb +13 -0
  38. data/lib/google_visualr/interactive/table.rb +11 -0
  39. data/lib/google_visualr/interactive/timeline.rb +11 -0
  40. data/lib/google_visualr/interactive/tree_map.rb +11 -0
  41. data/lib/google_visualr/interactive/word_tree.rb +11 -0
  42. data/lib/google_visualr/packages.rb +98 -0
  43. data/lib/google_visualr/param_helpers.rb +57 -0
  44. data/lib/google_visualr/version.rb +3 -0
  45. data/spec/dummy/Gemfile +0 -0
  46. data/spec/dummy/Gemfile.lock +7 -0
  47. data/spec/dummy/Rakefile +7 -0
  48. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  49. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  50. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  51. data/spec/dummy/config.ru +4 -0
  52. data/spec/dummy/config/application.rb +38 -0
  53. data/spec/dummy/config/boot.rb +6 -0
  54. data/spec/dummy/config/database.yml +22 -0
  55. data/spec/dummy/config/environment.rb +5 -0
  56. data/spec/dummy/config/environments/development.rb +30 -0
  57. data/spec/dummy/config/environments/production.rb +84 -0
  58. data/spec/dummy/config/environments/test.rb +41 -0
  59. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  60. data/spec/dummy/config/initializers/inflections.rb +10 -0
  61. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  62. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  63. data/spec/dummy/config/initializers/session_store.rb +8 -0
  64. data/spec/dummy/config/locales/en.yml +5 -0
  65. data/spec/dummy/config/routes.rb +58 -0
  66. data/spec/dummy/db/seeds.rb +7 -0
  67. data/spec/dummy/doc/README_FOR_APP +2 -0
  68. data/spec/dummy/log/development.log +0 -0
  69. data/spec/dummy/log/production.log +0 -0
  70. data/spec/dummy/log/server.log +0 -0
  71. data/spec/dummy/log/test.log +0 -0
  72. data/spec/dummy/public/404.html +26 -0
  73. data/spec/dummy/public/422.html +26 -0
  74. data/spec/dummy/public/500.html +26 -0
  75. data/spec/dummy/public/favicon.ico +0 -0
  76. data/spec/dummy/public/images/rails.png +0 -0
  77. data/spec/dummy/public/index.html +239 -0
  78. data/spec/dummy/public/javascripts/application.js +2 -0
  79. data/spec/dummy/public/javascripts/controls.js +965 -0
  80. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  81. data/spec/dummy/public/javascripts/effects.js +1123 -0
  82. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  83. data/spec/dummy/public/javascripts/rails.js +191 -0
  84. data/spec/dummy/public/robots.txt +5 -0
  85. data/spec/dummy/script/rails +6 -0
  86. data/spec/dummy/test/performance/browsing_test.rb +9 -0
  87. data/spec/dummy/test/test_helper.rb +13 -0
  88. data/spec/google_visualr/app/helpers/view_helper_spec.rb +25 -0
  89. data/spec/google_visualr/base_chart_spec.rb +129 -0
  90. data/spec/google_visualr/data_table_spec.rb +331 -0
  91. data/spec/google_visualr/formatters_spec.rb +105 -0
  92. data/spec/google_visualr/image_charts_spec.rb +127 -0
  93. data/spec/google_visualr/param_helpers_spec.rb +91 -0
  94. data/spec/spec_helper.rb +25 -0
  95. data/spec/support/common.rb +55 -0
  96. data/spec/turbolinks_tests/broken.html +19 -0
  97. data/spec/turbolinks_tests/fixed.html +18 -0
  98. data/spec/turbolinks_tests/index.html +15 -0
  99. data/spec/turbolinks_tests/old.html +17 -0
  100. data/spec/turbolinks_tests/turbolinks.js +455 -0
  101. metadata +204 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 336730e9cc3b35d547dc615631210d2afc4de27559278a3f90198babaebc4e40
4
+ data.tar.gz: 93888bafbd52dcffa8dacdbf54c7c691029f9dfd018b2e09fad54e2929542b44
5
+ SHA512:
6
+ metadata.gz: a560535ccdc977233a1390db6a2c2e7adbeb031ba249fa29f9f0ae99027fc26c970b05e66760f803e5d68f657f7822a3962fe52e069892a22a998e60c701408f
7
+ data.tar.gz: d99d339f74bc54cbabb804a414c1716a642838ea753d283a067de916a05537ef9fd2154e72771fa0e082a96a6e896031c145b87d0a8ecad78c45c77685ff7383
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Winston Teo Yong Wei
4
+
5
+ Permission is hereby granted, free of charge, to any person
6
+ obtaining a copy of this software and associated documentation files (the "Software"),
7
+ to deal in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9
+ and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
19
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,159 @@
1
+ # GoogleVisualr
2
+
3
+ [![Gem Version](http://img.shields.io/gem/v/google_visualr.svg?style=flat-square)](https://rubygems.org/gems/google_visualr)
4
+ [![Build Status](http://img.shields.io/travis/Kenneth-KT/google_visualr.svg?style=flat-square)](https://travis-ci.org/winston/google_visualr)
5
+ [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://github.com/winston/google_visualr/blob/master/MIT-LICENSE)
6
+
7
+ GoogleVisualr, is a wrapper around the [Google Charts](https://developers.google.com/chart/) that allows anyone to create beautiful charts with just plain Ruby. You don't have to write any JavaScript at all.
8
+
9
+ It's good for any Ruby (Rails/Sinatra) setup, and you can handle the entire charting logic in Ruby.
10
+
11
+ Please refer to the [GoogleVisualr API Reference site](http://googlevisualr.herokuapp.com/) for a complete list of Google charts that you can create with GoogleVisualr.
12
+
13
+ ## tl:dr
14
+
15
+ * In your model or controller, write Ruby code to create your chart (e.g. Area Chart, Bar Chart etc).
16
+ * Configure your chart with any of the options as listed in Google's API Docs. E.g. [Area Chart](http://code.google.com/apis/chart/interactive/docs/gallery/areachart.html#Configuration_Options).
17
+ * In your view, call `chart.to_js(div_id)` and that renders JavaScript into the HTML output.
18
+ * You get your awesome Google chart, and you didn't write any JavaScript!
19
+
20
+ ## Limitations
21
+
22
+ GoogleVisualr is not a 100% complete wrapper for Google Chart Tools.
23
+
24
+ `Methods` and `Events` as described in Google's API Docs - for use after a chart has been rendered,
25
+ are not implemented because they feel more natural being written as JavaScript functions, within the views or .js files.
26
+
27
+ ## Install
28
+
29
+ Assuming you are on Rails 3/4, include the gem in your Gemfile.
30
+
31
+ gem "google_visualr", ">= 2.5"
32
+
33
+ ## Basics
34
+
35
+ This is a basic implementation of `GoogleVisualr::DataTable` and `GoogleVisualr::AreaChart`.
36
+
37
+ For detailed documentation, please refer to the [GoogleVisualr API Reference](http://googlevisualr.herokuapp.com/) or [read the source](https://github.com/winston/google_visualr_app).
38
+
39
+ ---
40
+
41
+ In your Rails layout, load Google Ajax API in the head tag, at the very top.
42
+
43
+ <script src='https://www.google.com/jsapi'></script>
44
+
45
+ In your Rails controller, initialize a GoogleVisualr::DataTable object with an empty constructor.
46
+
47
+ data_table = GoogleVisualr::DataTable.new
48
+
49
+ Populate data_table with column headers, and row values.
50
+
51
+ # Add Column Headers
52
+ data_table.new_column('string', 'Year' )
53
+ data_table.new_column('number', 'Sales')
54
+ data_table.new_column('number', 'Expenses')
55
+
56
+ # Add Rows and Values
57
+ data_table.add_rows([
58
+ ['2004', 1000, 400],
59
+ ['2005', 1170, 460],
60
+ ['2006', 660, 1120],
61
+ ['2007', 1030, 540]
62
+ ])
63
+
64
+ Create a GoogleVisualr::AreaChart with data_table and configuration options.
65
+
66
+ option = { width: 400, height: 240, title: 'Company Performance' }
67
+ @chart = GoogleVisualr::Interactive::AreaChart.new(data_table, option)
68
+
69
+ In your Rails view, render the Google chart.
70
+
71
+ <div id='chart'></div>
72
+ <%= render_chart(@chart, 'chart') %>
73
+
74
+ ## Chart Initializer
75
+
76
+ The initializer of `GoogleVisualr::<ChartName>` takes in two parameters: `data_table` and `options`.
77
+
78
+ ### `data_table`
79
+
80
+ `data_table` is an instance of `GoogleVisualr::DataTable` and contains headers and rows of data.
81
+
82
+ ### `options`
83
+
84
+ `options` is a hash of configuration options for the Google chart (e.g. width, height, colors etc).
85
+
86
+ The available configuration options are exactly the same as those specified in Google's API Docs.
87
+
88
+ For example:
89
+ - [Configuration options for AreaChart](https://developers.google.com/chart/interactive/docs/gallery/areachart#configuration-options)
90
+ - [Configuration options for BarChart](https://developers.google.com/chart/interactive/docs/gallery/barchart#configuration-options)
91
+
92
+ At the same time, you can also specify `version`, `language` and `material` as configuration options.
93
+
94
+ #### `version`
95
+
96
+ The default version of Google Charts library loaded is `1.0`.
97
+
98
+ However, some charts (e.g. Gantt Charts) require the latest version of the Google Charts library,
99
+ so you will have to specify `version` as `1.1` in the configuration options
100
+
101
+ ```
102
+ ....
103
+ @chart = GoogleVisualr::GanttChart.new(data_table, { version: '1.1' })
104
+ ```
105
+
106
+ [Read more about it on Google's API Docs](https://developers.google.com/chart/interactive/docs/basic_load_libs).
107
+
108
+ #### `language`
109
+
110
+ The default locale of all Google Charts is `en`.
111
+
112
+ You can override this default by specifying `language` in the configuration options.
113
+
114
+ ```
115
+ ....
116
+ @chart = GoogleVisualr::BarChart.new(data_table, { language: 'ja' })
117
+ ```
118
+
119
+ [Read more about it on Google's API Docs](https://developers.google.com/chart/interactive/docs/library_loading_enhancements#loadwithlocale).
120
+
121
+ #### `material`
122
+
123
+ Google has also enabled `Material` design for some charts:
124
+
125
+ > In 2014, Google announced guidelines intended to support a common look and feel across its properties and apps (such as Android apps) that run on Google platforms. We call this effort Material Design. We'll be providing "Material" versions of all our core charts; you're welcome to use them if you like how they look.
126
+
127
+ To use material design, you will have to specify `material` as `true`
128
+ in the configuration options.
129
+
130
+ ```
131
+ ....
132
+ @chart = GoogleVisualr::BarChart.new(data_table, { material: true })
133
+ ```
134
+
135
+ ## Listeners
136
+
137
+ For an example usage of `listeners`, please refer to [this comment](https://github.com/winston/google_visualr/issues/36#issuecomment-9880256).
138
+
139
+ Besides `listeners` you can now also redraw charts in your JavaScript maunally by calling `draw_<element id>()` function. See [this commit](https://github.com/winston/google_visualr/commit/e5554886bd83f56dd31bbc543fdcf1e24523776a) for more details.
140
+
141
+ ## Support
142
+
143
+ Please submit all feedback, bugs and feature-requests to [GitHub Issues Tracker](http://github.com/winston/google_visualr/issues).
144
+
145
+ Feel free to fork the project, make improvements or bug fixes and submit pull requests (with tests!).
146
+
147
+ ## Who's Using GoogleVisualr?
148
+
149
+ I would like to collect some data about who's using this Gem. [Please drop me a line](mailto:winstonyw+googlevisualr@gmail.com).
150
+
151
+ ## Author
152
+
153
+ GoogleVisualr is maintained by [Winston Teo](mailto:winstonyw+googlevisualr@gmail.com).
154
+
155
+ Who is Winston Teo? [You should follow Winston on Twitter](http://www.twitter.com/winstonyw), or find out more on [WinstonYW](http://www.winstonyw.com).
156
+
157
+ ## License
158
+
159
+ Copyright © 2015 Winston Teo Yong Wei. Free software, released under the MIT license.
@@ -0,0 +1,9 @@
1
+ # Bundler Gem Tasks
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task test: :spec
9
+ task default: :spec
@@ -0,0 +1,53 @@
1
+ lib_path = File.dirname(__FILE__)
2
+
3
+ # Common
4
+ require "#{lib_path}/google_visualr/param_helpers"
5
+
6
+ # Base Classes
7
+ require "#{lib_path}/google_visualr/data_table"
8
+
9
+ require "#{lib_path}/google_visualr/packages"
10
+ require "#{lib_path}/google_visualr/base_chart"
11
+
12
+ require "#{lib_path}/google_visualr/formatters"
13
+
14
+ # Interactive Charts
15
+
16
+ ## Main
17
+ require "#{lib_path}/google_visualr/interactive/annotated_time_line"
18
+ require "#{lib_path}/google_visualr/interactive/annotation_chart"
19
+ require "#{lib_path}/google_visualr/interactive/area_chart"
20
+ require "#{lib_path}/google_visualr/interactive/bar_chart"
21
+ require "#{lib_path}/google_visualr/interactive/bubble_chart"
22
+ require "#{lib_path}/google_visualr/interactive/calendar"
23
+ require "#{lib_path}/google_visualr/interactive/candlestick_chart"
24
+ require "#{lib_path}/google_visualr/interactive/column_chart"
25
+ require "#{lib_path}/google_visualr/interactive/combo_chart"
26
+ require "#{lib_path}/google_visualr/interactive/gantt_chart"
27
+ require "#{lib_path}/google_visualr/interactive/gauge"
28
+ require "#{lib_path}/google_visualr/interactive/geo_chart"
29
+ require "#{lib_path}/google_visualr/interactive/geo_map"
30
+ require "#{lib_path}/google_visualr/interactive/histogram"
31
+ require "#{lib_path}/google_visualr/interactive/intensity_map"
32
+ require "#{lib_path}/google_visualr/interactive/line_chart"
33
+ require "#{lib_path}/google_visualr/interactive/map"
34
+ require "#{lib_path}/google_visualr/interactive/motion_chart"
35
+ require "#{lib_path}/google_visualr/interactive/org_chart"
36
+ require "#{lib_path}/google_visualr/interactive/pie_chart"
37
+ require "#{lib_path}/google_visualr/interactive/sankey"
38
+ require "#{lib_path}/google_visualr/interactive/scatter_chart"
39
+ require "#{lib_path}/google_visualr/interactive/stepped_area_chart"
40
+ require "#{lib_path}/google_visualr/interactive/table"
41
+ require "#{lib_path}/google_visualr/interactive/timeline"
42
+ require "#{lib_path}/google_visualr/interactive/tree_map"
43
+ require "#{lib_path}/google_visualr/interactive/word_tree"
44
+
45
+ # Image Charts
46
+ require "#{lib_path}/google_visualr/image/spark_line"
47
+ require "#{lib_path}/google_visualr/image/bar_chart"
48
+ require "#{lib_path}/google_visualr/image/line_chart"
49
+ require "#{lib_path}/google_visualr/image/pie_chart"
50
+
51
+
52
+ # Rails Helper
53
+ require "#{lib_path}/google_visualr/app/railtie.rb" if defined?(Rails)
@@ -0,0 +1,26 @@
1
+ module GoogleVisualr
2
+ module Rails
3
+ module ViewHelper
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ # Rails 5 compatibility fix
8
+ if respond_to?(:helper_method)
9
+ helper_method "render_chart"
10
+ end
11
+ end
12
+
13
+ def render_chart(chart, dom, options={})
14
+ script_tag = options.fetch(:script_tag) { true }
15
+ if script_tag
16
+ chart.to_js(dom).html_safe
17
+ else
18
+ html = ""
19
+ html << chart.load_js(dom)
20
+ html << chart.draw_js(dom)
21
+ html.html_safe
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ require "#{File.dirname(__FILE__)}/helpers/view_helper"
2
+
3
+ module GoogleVisualr
4
+
5
+ module Rails
6
+
7
+ class Railtie < ::Rails::Railtie
8
+
9
+ initializer "google_visualr" do
10
+ ActiveSupport.on_load(:action_controller) do
11
+ include GoogleVisualr::Rails::ViewHelper
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,100 @@
1
+ module GoogleVisualr
2
+
3
+ class BaseChart
4
+ include GoogleVisualr::ParamHelpers
5
+
6
+ DEFAULT_VERSION = "1.0".freeze
7
+
8
+ attr_accessor :data_table, :listeners, :version, :language, :material
9
+
10
+ def initialize(data_table, options={})
11
+ @data_table = data_table
12
+ @listeners = []
13
+ @version = options.delete(:version) || DEFAULT_VERSION
14
+ @language = options.delete(:language)
15
+ @material = options.delete(:material) || false
16
+ send(:options=, options)
17
+ end
18
+
19
+ def package_name
20
+ self.class.to_s.split("::").last.downcase
21
+ end
22
+
23
+ def class_name
24
+ self.class.to_s.split("::").last
25
+ end
26
+
27
+ def chart_class
28
+ if material
29
+ "charts"
30
+ else
31
+ "visualization"
32
+ end
33
+ end
34
+
35
+ def chart_name
36
+ if material
37
+ class_name.gsub!("Chart", "")
38
+ else
39
+ class_name
40
+ end
41
+ end
42
+
43
+ def chart_function_name(element_id)
44
+ "draw_#{element_id.gsub('-', '_')}"
45
+ end
46
+
47
+ def options
48
+ @options
49
+ end
50
+
51
+ def options=(options)
52
+ @options = stringify_keys!(options)
53
+ end
54
+
55
+ def add_listener(event, callback)
56
+ @listeners << { :event => event.to_s, :callback => callback }
57
+ end
58
+
59
+ # Generates JavaScript and renders the Google Chart in the final HTML output.
60
+ #
61
+ # Parameters:
62
+ # *div_id [Required] The ID of the DIV element that the Google Chart should be rendered in.
63
+ def to_js(element_id)
64
+ js = ""
65
+ js << "\n<script type='text/javascript'>"
66
+ js << load_js(element_id)
67
+ js << draw_js(element_id)
68
+ js << "\n</script>"
69
+ js
70
+ end
71
+
72
+ # Generates JavaScript for loading the appropriate Google Visualization package, with callback to render chart.
73
+ #
74
+ # Parameters:
75
+ # *div_id [Required] The ID of the DIV element that the Google Chart should be rendered in.
76
+ def load_js(element_id)
77
+ language_opt = ", language: '#{language}'" if language
78
+
79
+ "\n google.load('visualization', '#{version}', {packages: ['#{package_name}']#{language_opt}, callback: #{chart_function_name(element_id)}});"
80
+ end
81
+
82
+ # Generates JavaScript function for rendering the chart.
83
+ #
84
+ # Parameters:
85
+ # *div_id [Required] The ID of the DIV element that the Google Chart should be rendered in.
86
+ def draw_js(element_id)
87
+ js = ""
88
+ js << "\n function #{chart_function_name(element_id)}() {"
89
+ js << "\n #{@data_table.to_js}"
90
+ js << "\n var chart = new google.#{chart_class}.#{chart_name}(document.getElementById('#{element_id}'));"
91
+ @listeners.each do |listener|
92
+ js << "\n google.visualization.events.addListener(chart, '#{listener[:event]}', #{listener[:callback]});"
93
+ end
94
+ js << "\n chart.draw(data_table, #{js_parameters(@options)});"
95
+ js << "\n };"
96
+ js
97
+ end
98
+ end
99
+
100
+ end
@@ -0,0 +1,294 @@
1
+ module GoogleVisualr
2
+
3
+ class DataTable
4
+
5
+ attr_accessor :cols
6
+ attr_accessor :rows
7
+
8
+ ##############################
9
+ # Constructors
10
+ ##############################
11
+ #
12
+ # GoogleVisualr::DataTable.new
13
+ # Creates an empty data_table instance. Use new_column/s, add_row/s and set_cell methods to populate the data_table.
14
+ #
15
+ # GoogleVisualr::DataTable.new(data_object)
16
+ # Creates a data_table by passing a JavaScript-string-literal like data object into the data parameter. This object can contain formatting options.
17
+ #
18
+ ##############################
19
+ # Syntax Description of a Data Object
20
+ ##############################
21
+ #
22
+ # The data object consists of two required top-level properties, cols and rows.
23
+ #
24
+ # * cols property
25
+ #
26
+ # cols is an array of objects describing the ID and type of each column. Each property is an object with the following properties (case-sensitive):
27
+ #
28
+ # * type [Required] The data type of the data in the column. Supports the following string values:
29
+ # - 'string' : String value. Example values: v:'foo', :v:'bar'
30
+ # - 'number' : Number value. Example values: v:7, v:3.14, v:-55
31
+ # - 'boolean' : Boolean value ('true' or 'false'). Example values: v:true, v:false
32
+ # - 'date' : Date object, with the time truncated. Example value: v:Date.parse('2010-01-01')
33
+ # - 'datetime' : DateTime/Time object, time inclusive. Example value: v:DateTime.parse('2010-01-01 14:20:25')
34
+ # - 'timeofday' : Array of 3 numbers or 4 numbers, [Hour,Minute,Second,(Optional) Milliseconds]. Example value: v:[8, 15, 0]
35
+ # * label [Optional] A string value that some visualizations display for this column. Example: label:'Height'
36
+ # * id [Optional] A unique (basic alphanumeric) string ID of the column. Be careful not to choose a JavaScript keyword. Example: id:'col_1'
37
+ #
38
+ # * rows property
39
+ #
40
+ # The rows property holds an array of row objects. Each row object has one required property called c, which is an array of cells in that row.
41
+ #
42
+ # Each cell in the table is described by an object with the following properties:
43
+ #
44
+ # * v [Optional] The cell value. The data type should match the column data type.
45
+ # * f [Optional] A string version of the v value, formatted strictly for display only. If omitted, a string version of v will be used.
46
+ # * p [Optional] An object that is a map of custom values applied to the cell. Example: :p => { :style => 'border: 1px solid green;' }.
47
+ #
48
+ # Cells in the row array should be in the same order as their column descriptions in cols.
49
+ #
50
+ # To indicate a null cell, you can either specify null, or set empty string for a cell in an array, or omit trailing array members.
51
+ # So, to indicate a row with null for the first two cells, you could specify [ '', '', {cell_val}] or [null, null, {cell_val}].
52
+ def initialize(options = {})
53
+ @cols = Array.new
54
+ @rows = Array.new
55
+
56
+ unless options.empty?
57
+ cols = options[:cols]
58
+ new_columns(cols)
59
+
60
+ rows = options[:rows]
61
+ rows.each do |row|
62
+ add_row(row[:c])
63
+ end
64
+ end
65
+ end
66
+
67
+ # Adds a new column to the data_table.
68
+ # Experimental support for role (and pattern): http://code.google.com/apis/chart/interactive/docs/roles.html.
69
+ #
70
+ # Parameters:
71
+ # * type [Required] The data type of the data in the column. Supports the following string values:
72
+ # - 'string' : String value. Example values: v:'hello'
73
+ # - 'number' : Number value. Example values: v:7 , v:3.14, v:-55
74
+ # - 'date' : Date object, with the time truncated. Example values: v:Date.parse('2010-01-01')
75
+ # - 'datetime' : Date object including the time. Example values: v:Date.parse('2010-01-01 14:20:25')
76
+ # - 'boolean' : Boolean value ('true' or 'false'). Example values: v: true
77
+ # * label [Optional] A string value that some visualizations display for this column. Example: label:'Height'
78
+ # * id [Optional] A unique (basic alphanumeric) string ID of the column. Be careful not to choose a JavaScript keyword. Example: id:'col_1'
79
+ # * role [Optional] A string value that describes the purpose of the data in that column. Example, a column might hold data describing tooltip text, data point annotations, or uncertainty indicators.
80
+ # * pattern [Optional] A number (or date) format string specifying how to display the column value; used in conjunction with role.
81
+ def new_column(type, label=nil, id =nil, role=nil, pattern=nil)
82
+ column = { :type => type, :label => label, :id => id, :role => role, :pattern => pattern }.reject { |key, value| value.nil? }
83
+ @cols << column
84
+ end
85
+
86
+ # Adds multiple columns to the data_table.
87
+ #
88
+ # Parameters:
89
+ # * columns [Required] An array of column objects {:type, :label, :id, :role, :pattern}. Calls new_column for each column object.
90
+ def new_columns(columns)
91
+ columns.each do |column|
92
+ new_column(column[:type], column[:label], column[:id], column[:role], column[:pattern])
93
+ end
94
+ end
95
+
96
+ # Sets a column in data_table, specified by column_index with an array of column_values. column_index starts from 0.
97
+ #
98
+ # Parameters
99
+ # * column_index [Required] The column to assign column_values. column_index starts from 0.
100
+ # * column_values [Required] An array of cell values.
101
+ def set_column(column_index, column_values)
102
+ if @rows.size < column_values.size
103
+ 1.upto(column_values.size - @rows.size) { @rows << Array.new }
104
+ end
105
+
106
+ column_values.each_with_index do |column_value, row_index|
107
+ set_cell(row_index, column_index, column_value)
108
+ end
109
+ end
110
+
111
+ # Gets a column of cell values from the data_table, at column_index. column_index starts from 0.
112
+ #
113
+ # Parameters
114
+ # * column_index [Required] The column to retrieve column values. column_index starts from 0.
115
+ def get_column(column_index)
116
+ @rows.transpose[column_index].collect(&:v)
117
+ end
118
+
119
+ # Adds a new row to the data_table.
120
+ # Call method without any parameters to add an empty row, otherwise, call method with a row object.
121
+ #
122
+ # Parameters:
123
+ # * row [Optional] An array of cell values specifying the data for the new row.
124
+ # - You can specify a value for a cell (e.g. 'hi') or specify a formatted value using cell objects (e.g. {v:55, f:'Fifty-five'}) as described in the constructor section.
125
+ # - You can mix simple values and cell objects in the same method call.
126
+ # - To create an empty cell, use nil or empty string.
127
+ def add_row(row_values=[])
128
+ @rows << Array.new
129
+ row_index = @rows.size-1
130
+
131
+ row_values.each_with_index do |row_value, column_index|
132
+ set_cell(row_index, column_index, row_value)
133
+ end
134
+ end
135
+
136
+ # Adds multiple rows to the data_table. You can call this method with data to populate a set of new rows or create new empty rows.
137
+ #
138
+ # Parameters:
139
+ # * array_or_num [Required] Either an array or a number.
140
+ # - Array: An array of row objects used to populate a set of new rows. Each row is an object as described in add_row().
141
+ # - Number: A number specifying the number of new empty rows to create.
142
+ def add_rows(array_or_num)
143
+ if array_or_num.is_a?(Array)
144
+ array_or_num.each do |row|
145
+ add_row(row)
146
+ end
147
+ else
148
+ array_or_num.times do
149
+ add_row
150
+ end
151
+ end
152
+ end
153
+
154
+ # Gets a row of cell values from the data_table, at row_index. row_index starts from 0.
155
+ #
156
+ # Parameters
157
+ # * row_index [Required] The row to retrieve row values. row_index starts from 0.
158
+ def get_row(row_index)
159
+ @rows[row_index].collect(&:v)
160
+ end
161
+
162
+ # Sets the value (and formatted value) of a cell.
163
+ #
164
+ # Parameters:
165
+ # * row_index [Required] A number greater than or equal to zero, but smaller than the total number of rows.
166
+ # * column_index [Required] A number greater than or equal to zero, but smaller than the total number of columns.
167
+ # * value [Required] The cell value.
168
+ # The data type should match the column data type.
169
+ # You can specify a value for a cell (e.g. 'hi').
170
+ # Or specify a formatted value using cell objects (e.g. {v:55, f:'Fifty-five'}).
171
+ def set_cell(row_index, column_index, value)
172
+ if within_range?(row_index, column_index)
173
+ verify_against_column_type( @cols[column_index][:type], value )
174
+ @rows[row_index][column_index] = GoogleVisualr::DataTable::Cell.new(value, @cols[column_index][:type])
175
+ else
176
+ raise RangeError, "row_index and column_index MUST be < @rows.size and @cols.size", caller
177
+ end
178
+ end
179
+
180
+ # Gets a cell value from the visualization, at row_index, column_index. row_index and column_index start from 0.
181
+ #
182
+ # Parameters:
183
+ # * row_index [Required] row_index starts from 0.
184
+ # * column_index [Required] column_index starts from 0.
185
+ def get_cell(row_index, column_index)
186
+ if within_range?(row_index, column_index)
187
+ @rows[row_index][column_index].v
188
+ else
189
+ raise RangeError, "row_index and column_index MUST be < @rows.size and @cols.size", caller
190
+ end
191
+ end
192
+
193
+ # Applies one or more formatters to the data_table to format the columns as specified by the formatter/s.
194
+ #
195
+ # Parameters:
196
+ # * formatter/s [Required] One, or an array of formatters.
197
+ def format(*formatters)
198
+ @formatters ||= Array.new
199
+ @formatters += formatters
200
+ end
201
+
202
+ # Returns the JavaScript equivalent for this data_table instance.
203
+ def to_js
204
+ js = "var data_table = new google.visualization.DataTable();"
205
+
206
+ @cols.each do |column|
207
+ js << "data_table.addColumn("
208
+ js << display(column)
209
+ js << ");"
210
+ end
211
+
212
+ @rows.each do |row|
213
+ js << "data_table.addRow("
214
+ js << "[#{row.map(&:to_js).join(", ")}]" unless row.empty?
215
+ js << ");"
216
+ end
217
+
218
+ if @formatters
219
+ @formatters.each do |formatter|
220
+ js << formatter.to_js
221
+ end
222
+ end
223
+
224
+ js
225
+ end
226
+
227
+ private
228
+
229
+ def display(column)
230
+ column[:type] = "datetime" if column[:type] == "time"
231
+ column.to_json
232
+ end
233
+
234
+ def within_range?(row_index, column_index)
235
+ row_index < @rows.size && column_index < @cols.size
236
+ end
237
+
238
+ def verify_against_column_type(type, value)
239
+ v = value.is_a?(Hash) ? value[:v] : value
240
+
241
+ case
242
+ when v.nil?
243
+ return
244
+ when type == "string"
245
+ raise ArgumentError, "cell value '#{v}' is not a String", caller unless v.is_a?(String)
246
+ when type == "number"
247
+ raise ArgumentError, "cell value '#{v}' is not an Integer, Float or BigDecimal", caller unless v.is_a?(Integer) || v.is_a?(Float) || v.is_a?(BigDecimal)
248
+ when type == "boolean"
249
+ raise ArgumentError, "cell value '#{v}' is not a Boolean", caller unless v.is_a?(TrueClass) || v.is_a?(FalseClass)
250
+ when type == 'datetime'
251
+ raise ArgumentError, "cell value '#{v}' is not a DateTime", caller unless v.is_a?(DateTime) || v.is_a?(Time)
252
+ when type == 'time'
253
+ raise ArgumentError, "cell value '#{v}' is not a DateTime", caller unless v.is_a?(DateTime) || v.is_a?(Time)
254
+ when type == "date"
255
+ raise ArgumentError, "cell value '#{v}' is not a Date", caller unless v.is_a?(Date)
256
+ end
257
+ end
258
+
259
+ class Cell
260
+ include GoogleVisualr::ParamHelpers
261
+
262
+ attr_accessor :v # value
263
+ attr_accessor :f # formatted
264
+ attr_accessor :p # properties
265
+
266
+ def initialize(options, type = nil)
267
+ if options.is_a?(Hash)
268
+ @v = options[:v]
269
+ @f = options[:f]
270
+ @p = options[:p]
271
+ @type = type
272
+ else # should be a string
273
+ @v = options
274
+ @type = type
275
+ end
276
+ end
277
+
278
+ def to_js
279
+ return "null" if @v.nil? && @f.nil? && @p.nil?
280
+
281
+ js = "{"
282
+ js << "v: #{typecast(@v, @type)}"
283
+ js << ", f: #{typecast(@f)}" unless @f.nil?
284
+ js << ", p: #{typecast(@p)}" unless @p.nil?
285
+ js << "}"
286
+
287
+ js
288
+ end
289
+
290
+ end
291
+
292
+ end
293
+
294
+ end