google_visualr 0.0.1 → 2.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.
Files changed (62) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +25 -0
  6. data/MIT-LICENSE +15 -14
  7. data/README.rdoc +59 -48
  8. data/Rakefile +9 -30
  9. data/google_visualr.gemspec +24 -0
  10. data/lib/google_visualr.rb +39 -0
  11. data/lib/google_visualr/base_chart.rb +40 -0
  12. data/lib/google_visualr/data_table.rb +277 -0
  13. data/lib/google_visualr/formatters.rb +78 -0
  14. data/lib/google_visualr/image/spark_line.rb +13 -0
  15. data/lib/google_visualr/interactive/annotated_time_line.rb +11 -0
  16. data/lib/google_visualr/interactive/area_chart.rb +13 -0
  17. data/lib/google_visualr/interactive/bar_chart.rb +13 -0
  18. data/lib/google_visualr/interactive/candlestick_chart.rb +13 -0
  19. data/lib/google_visualr/interactive/column_chart.rb +13 -0
  20. data/lib/google_visualr/interactive/combo_chart.rb +13 -0
  21. data/lib/google_visualr/interactive/gauge.rb +11 -0
  22. data/lib/google_visualr/interactive/geo_chart.rb +11 -0
  23. data/lib/google_visualr/interactive/intensity_map.rb +11 -0
  24. data/lib/google_visualr/interactive/line_chart.rb +13 -0
  25. data/lib/google_visualr/interactive/map.rb +11 -0
  26. data/lib/google_visualr/interactive/motion_chart.rb +11 -0
  27. data/lib/google_visualr/interactive/org_chart.rb +11 -0
  28. data/lib/google_visualr/interactive/pie_chart.rb +13 -0
  29. data/lib/google_visualr/interactive/scatter_chart.rb +13 -0
  30. data/lib/google_visualr/interactive/table.rb +11 -0
  31. data/lib/google_visualr/interactive/treemap.rb +11 -0
  32. data/lib/google_visualr/packages.rb +30 -0
  33. data/lib/google_visualr/param_helpers.rb +50 -0
  34. data/lib/google_visualr/version.rb +3 -0
  35. data/spec/google_visualr/base_chart_spec.rb +55 -0
  36. data/spec/google_visualr/data_table_spec.rb +251 -0
  37. data/spec/google_visualr/formatters_spec.rb +104 -0
  38. data/spec/spec_helper.rb +8 -0
  39. data/test/google_visualr_spec.rb +7 -0
  40. data/test/helper.rb +18 -0
  41. metadata +73 -36
  42. data/VERSION +0 -1
  43. data/init.rb +0 -17
  44. data/install.rb +0 -1
  45. data/lib/annotated_time_line.rb +0 -50
  46. data/lib/area_chart.rb +0 -54
  47. data/lib/bar_chart.rb +0 -53
  48. data/lib/base_chart.rb +0 -285
  49. data/lib/column_chart.rb +0 -53
  50. data/lib/formatters.rb +0 -184
  51. data/lib/gauge.rb +0 -36
  52. data/lib/geo_map.rb +0 -32
  53. data/lib/image_spark_line.rb +0 -36
  54. data/lib/intensity_map.rb +0 -29
  55. data/lib/line_chart.rb +0 -54
  56. data/lib/map.rb +0 -31
  57. data/lib/motion_chart.rb +0 -36
  58. data/lib/org_chart.rb +0 -29
  59. data/lib/pie_chart.rb +0 -44
  60. data/lib/scatter_chart.rb +0 -52
  61. data/lib/table.rb +0 -39
  62. data/uninstall.rb +0 -1
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format nested
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.2-p180@google_visualr --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in gv.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ google_visualr (2.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.2)
10
+ rspec (2.6.0)
11
+ rspec-core (~> 2.6.0)
12
+ rspec-expectations (~> 2.6.0)
13
+ rspec-mocks (~> 2.6.0)
14
+ rspec-core (2.6.4)
15
+ rspec-expectations (2.6.0)
16
+ diff-lcs (~> 1.1.2)
17
+ rspec-mocks (2.6.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ bundler (>= 1.0.15)
24
+ google_visualr!
25
+ rspec (>= 2.6.0)
data/MIT-LICENSE CHANGED
@@ -1,21 +1,22 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2010 Winston Teo Yong Wei
3
+ Copyright (c) 2011 Winston Teo Yong Wei
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
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
11
 
12
12
  The above copyright notice and this permission notice shall be included in
13
13
  all copies or substantial portions of the Software.
14
14
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
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.
data/README.rdoc CHANGED
@@ -1,92 +1,103 @@
1
1
  = Overview
2
2
 
3
- This Ruby library, GoogleVisualr, is a wrapper around the {Google Visualization API}[http://code.google.com/apis/visualization/documentation/] and allows you to create the same visualizations with just pure Ruby;
4
- you don't have to write any JavaScript at all.
3
+ This Ruby gem, GoogleVisualr, is a wrapper around the {Google Chart Tools}[http://code.google.com/apis/chart/interactive/docs/index.html] that allows anyone to create the same beautiful charts with just plain Ruby.
4
+
5
+ You don't have to write any JavaScript at all!
5
6
 
6
7
  Good for any Ruby on Rails setup whereby you prefer to work your logic in models or controllers.
7
8
 
8
- Please refer to the {GoogleVisualr reference site}[http://googlevisualr.heroku.com/] for a complete list of visualizations that you can create with GoogleVisualr.
9
+ Please refer to the {GoogleVisualr API Reference site}[http://googlevisualr.heroku.com/] for a complete list of Google charts that you can create with GoogleVisualr.
10
+
11
+ == Differences Between Gem and Plugin
12
+
13
+ Gem
14
+ * is Rails 3 compatible.
15
+ * implements many of the newer versions of Google Charts E.g. Core Charts.
16
+ * enjoyed a major refactoring, and also now has Tests!
17
+
18
+ Plugin
19
+ * has not been tested for Rails 3 compatibility
20
+ * implements the older versions of Google Charts.
21
+ * has deprecated methods.
22
+
23
+ This gem, however, is not a drop-in replacement for the plugin, as there are numerous changes in its usage.
24
+
25
+ Notably, you will have to interact mostly with GoogleVisualr::DataTable which was absent in the plugin.
9
26
 
10
27
  == The Gist
11
28
 
12
- * In your model or controller, write Ruby code to create your visualization (e.g. Area Chart, Bar Chart, even Spark Lines etc).
13
- * Configure your visualization with all the options as listed in Google Visualization API Docs. E.g. {Area Chart's configuration options}[http://code.google.com/apis/visualization/documentation/gallery/areachart.html#Configuration_Options].
14
- * In your view, just call a <em>visualization.render(div_id)</em> method that will magically generate and insert JavaScript into the final HTML output.
15
- * You get your visualization, and you didn't write any JavaScript!
29
+ * In your model or controller, write Ruby code to create your chart (e.g. Area Chart, Bar Chart, even Spark Lines etc).
30
+ * Configure your chart with any of the options as listed in Google Chart Tools' API Docs. E.g. {Area Chart's Configuration Options}[http://code.google.com/apis/chart/interactive/docs/gallery/areachart.html#Configuration_Options].
31
+ * In your view, invoke a <em>chart.to_js(div_id)</em> method and that will magically generate and insert JavaScript into the final HTML output.
32
+ * You get your awesome Google chart, and you didn't write any JavaScript!
16
33
 
17
34
  == Limitations
18
35
 
19
- Do note that GoogleVisualr is not a 100% complete wrapper for the Google Visualization API. These are not implemented for sake of simplicity:
20
- * JavaScript Methods for use after a visualization has been rendered in a view. E.g. {Area Chart's methods}[http://code.google.com/apis/visualization/documentation/gallery/areachart.html#Methods].
21
- * JavaScript Events for use after a visualization has been rendered in a view. E.g. {Area Chart's events}[http://code.google.com/apis/visualization/documentation/gallery/areachart.html#Events].
22
- * Visualizations not created by Google, and a few image-only charts.
36
+ GoogleVisualr is created solely for the aim of simplifying the display of a chart, and not the interactions.
37
+
38
+ Hence, do note that GoogleVisualr is not a 100% complete wrapper for Google Chart Tools.
39
+
40
+ For example, Methods and Events as described in Google Chart Tools' API Docs, for use after a chart has been rendered, are not implemented because they felt more native being written as JavaScript functions, within views or .js files.
23
41
 
24
42
  = Install
25
43
 
26
- Just install the GitHub repository into your app/vendor/plugin folder.
44
+ Assuming you are on Rails 3, include the gem in your Gemfile.
27
45
 
28
- > rails my_app; cd my_app;
29
- > script/plugin install git://github.com/winston/google_visualr.git
46
+ gem "google_visualr", ">= 2.0"
30
47
 
31
48
  = Basics
32
49
 
33
- This section describes a basic implementation of the GoogleVisualr::AreaChart class.
50
+ This section describes a basic implementation of the GoogleVisualr::DataTable and GoogleVisualr::AreaChart classes.
51
+
52
+ For detailed documentation and advanced implementations, please refer to the {GoogleVisualr API Reference site}[http://googlevisualr.heroku.com/] or read the source.
34
53
 
35
- Please review the {Docs}[http://googlevisualr.heroku.com/docs] for detailed documentation and advanced implementation of constructors and methods.
36
54
  ---
37
55
 
38
56
  In your Rails layout, load Google Ajax API in the head tag, at the very top.
39
57
 
40
58
  <script src='http://www.google.com/jsapi'></script>
41
59
 
42
- In your Rails controller, initialize a visualization (area chart) with an empty constructor.
60
+ In your Rails controller, initialize a GoogleVisualr::DataTable object with an empty constructor.
43
61
 
44
- @chart = GoogleVisualr::AreaChart.new
62
+ data_table = GoogleVisualr::DataTable.new
45
63
 
46
- Populate visualization with column headers, and row values.
64
+ Populate data_table with column headers, and row values.
47
65
 
48
66
  # Add Column Headers
49
- @chart.add_column('string', 'Year' )
50
- @chart.add_column('number', 'Sales')
51
- @chart.add_column('number', 'Expenses')
67
+ data_table.new_column('string', 'Year' )
68
+ data_table.new_column('number', 'Sales')
69
+ data_table.new_column('number', 'Expenses')
52
70
 
53
71
  # Add Rows and Values
54
- @chart.add_rows(4)
55
- @chart.set_value(0, 0, '2004')
56
- @chart.set_value(0, 1, 1000)
57
- @chart.set_value(0, 2, 400)
58
- @chart.set_value(1, 0, '2005')
59
- @chart.set_value(1, 1, 1170)
60
- @chart.set_value(1, 2, 460)
61
- @chart.set_value(2, 0, '2006')
62
- @chart.set_value(2, 1, 1500)
63
- @chart.set_value(2, 2, 660)
64
- @chart.set_value(3, 0, '2007')
65
- @chart.set_value(3, 1, 1030)
66
- @chart.set_value(3, 2, 540)
67
-
68
- Configure visualization with options.
69
-
70
- @chart.width = 400
71
- @chart.height = 240
72
-
73
- In your Rails view, render visualization.
72
+ data_table.add_rows([
73
+ ['2004', 1000, 400],
74
+ ['2005', 1170, 460],
75
+ ['2006', 660, 1120],
76
+ ['2007', 1030, 540]
77
+ ])
78
+
79
+ Create a GoogleVisualr::AreaChart with data_table and configuration options.
80
+
81
+ option = { width: 400, height: 240, title: 'Company Performance' }
82
+ @chart = GoogleVisualr::Interactive::AreaChart.new(data_table, option)
83
+
84
+ In your Rails view, render the Google chart.
74
85
 
75
86
  <div id='chart'></div>
76
- <%= @chart.render('chart') %>
87
+ <%= raw @chart.to_js('chart') %>
77
88
 
78
89
  = Support
79
90
 
80
- Please submit all feedback, bugs and feature-requests to {GitHub Issues Tracker}[http://github.com/winston/google_visualr/issues].
91
+ Please feel free to fork the project, make improvements or bug fixes and submit pull requests. Ideally, all pull requests should also come with tests!
81
92
 
82
- Please also feel free to clone/fork the project, and improve it further!
93
+ Please submit all feedback, bugs and feature-requests to {GitHub Issues Tracker}[http://github.com/winston/google_visualr/issues].
83
94
 
84
95
  = Author
85
96
 
86
- GoogleVisualr is maintained by {Winston Teo}[mailto:winstonyw+googlevisualr@gmail.com], and his Ninja Penguin.
97
+ GoogleVisualr is maintained by {Winston Teo}[mailto:winstonyw+googlevisualr@gmail.com].
87
98
 
88
- Who is Winston Teo? Find out more on {WinstonYW}[http://www.winstonyw.com], {LinkedIn}[http://sg.linkedin.com/in/winstonyw], or {follow Winston on Twitter}[http://www.twitter.com/winstonyw].
99
+ 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] and {LinkedIn}[http://sg.linkedin.com/in/winstonyw].
89
100
 
90
101
  = License
91
102
 
92
- Copyright © 2010 Winston Teo Yong Wei. Free software, released under the MIT license.
103
+ Copyright © 2011 Winston Teo Yong Wei. Free software, released under the MIT license.
data/Rakefile CHANGED
@@ -1,33 +1,12 @@
1
- # Rake Hook
1
+ # Bundler Gem Tasks
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
2
4
 
3
- require 'rubygems'
4
- #Gem::manage_gems
5
- require 'rake/gempackagetask'
5
+ # RSpec Tasks
6
+ require 'rspec/core/rake_task'
6
7
 
7
- PKG_FILES = FileList[
8
- '[a-zA-Z]*',
9
- 'generators/**/*',
10
- 'lib/**/*',
11
- 'rails/**/*',
12
- 'tasks/**/*',
13
- 'test/**/*'
14
- ]
15
-
16
- spec = Gem::Specification.new do |s|
17
- s.name = "google_visualr"
18
- s.version = "0.0.1"
19
- s.author = "Winston Teo"
20
- s.email = "winston.yongwei+spam at gmail.com"
21
- s.homepage = "https://github.com/winston/google_visualr"
22
- s.platform = Gem::Platform::RUBY
23
- s.summary = "Wrapper around the Google Visualization API."
24
- s.files = PKG_FILES.to_a
25
- s.require_path = "lib"
26
- s.has_rdoc = false
27
- s.extra_rdoc_files = ["README.rdoc"]
28
- end
29
-
30
- desc 'Turn this plugin into a gem.'
31
- Rake::GemPackageTask.new(spec) do |pkg|
32
- pkg.gem_spec = spec
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.rspec_opts = ['--options', '.rspec']
33
10
  end
11
+
12
+ task :default => :spec
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/google_visualr/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "google_visualr"
6
+ s.version = GoogleVisualr::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Winston Teo"]
9
+ s.email = ["winston.yongwei+google_visualr@gmail.com"]
10
+ s.homepage = "https://github.com/winston/google_visualr"
11
+ s.summary = "A Ruby wrapper around the Google Chart Tools that allows anyone to create the same beautiful charts with just plain Ruby."
12
+ s.description = "This Ruby gem, GoogleVisualr, is a wrapper around the Google Chart Tools that allows anyone to create the same beautiful charts with just Ruby; you don't have to write any JavaScript at all."
13
+ s.extra_rdoc_files = ["README.rdoc"]
14
+
15
+ s.required_rubygems_version = ">= 1.3.6"
16
+ s.rubyforge_project = "google_visualr"
17
+
18
+ s.add_development_dependency "bundler", ">= 1.0.15"
19
+ s.add_development_dependency "rspec" , ">= 2.6.0"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
23
+ s.require_path = 'lib'
24
+ end
@@ -0,0 +1,39 @@
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/area_chart"
18
+ require "#{lib_path}/google_visualr/interactive/bar_chart"
19
+ require "#{lib_path}/google_visualr/interactive/candlestick_chart"
20
+ require "#{lib_path}/google_visualr/interactive/column_chart"
21
+ require "#{lib_path}/google_visualr/interactive/combo_chart"
22
+ require "#{lib_path}/google_visualr/interactive/gauge"
23
+ require "#{lib_path}/google_visualr/interactive/geo_chart"
24
+ require "#{lib_path}/google_visualr/interactive/line_chart"
25
+ require "#{lib_path}/google_visualr/interactive/pie_chart"
26
+ require "#{lib_path}/google_visualr/interactive/scatter_chart"
27
+ require "#{lib_path}/google_visualr/interactive/table"
28
+ require "#{lib_path}/google_visualr/interactive/treemap"
29
+
30
+ ## Additional
31
+ require "#{lib_path}/google_visualr/interactive/annotated_time_line"
32
+ require "#{lib_path}/google_visualr/interactive/intensity_map"
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
+
37
+ # Image Charts
38
+ require "#{lib_path}/google_visualr/image/spark_line"
39
+
@@ -0,0 +1,40 @@
1
+ module GoogleVisualr
2
+
3
+ class BaseChart
4
+ include GoogleVisualr::Packages
5
+ include GoogleVisualr::ParamHelpers
6
+
7
+ attr_accessor :data_table
8
+
9
+ def initialize(data_table, options={})
10
+ @data_table = data_table
11
+ send(:options=, options)
12
+ end
13
+
14
+ def options
15
+ @options
16
+ end
17
+
18
+ def options=(options)
19
+ @options = stringify_keys!(options)
20
+ end
21
+
22
+ # Generates JavaScript and renders the Google Chart in the final HTML output.
23
+ #
24
+ # Parameters:
25
+ # *div_id [Required] The ID of the DIV element that the Google Chart should be rendered in.
26
+ def to_js(element_id)
27
+ js = "\n<script type='text/javascript'>"
28
+ js << "\n google.load('visualization','1', {packages: ['#{package_name}'], callback: function() {"
29
+ js << "\n #{@data_table.to_js}"
30
+ js << "\n var chart = new google.visualization.#{class_name}(document.getElementById('#{element_id}'));"
31
+ js << "\n chart.draw(data_table, #{js_parameters(@options)});"
32
+ js << "\n }});"
33
+ js << "\n</script>"
34
+
35
+ js
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,277 @@
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
+ #
47
+ # Cells in the row array should be in the same order as their column descriptions in cols.
48
+ #
49
+ # 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.
50
+ # So, to indicate a row with null for the first two cells, you could specify [ '', '', {cell_val}] or [null, null, {cell_val}].
51
+ def initialize(options = {})
52
+ @cols = Array.new
53
+ @rows = Array.new
54
+
55
+ unless options.empty?
56
+ cols = options[:cols]
57
+ new_columns(cols)
58
+
59
+ rows = options[:rows]
60
+ rows.each do |row|
61
+ add_row(row[:c])
62
+ end
63
+ end
64
+ end
65
+
66
+ # Adds a new column to the data_table.
67
+ #
68
+ # Parameters:
69
+ # * type [Required] The data type of the data in the column. Supports the following string values:
70
+ # - 'string' : String value. Example values: v:'hello'
71
+ # - 'number' : Number value. Example values: v:7 , v:3.14, v:-55
72
+ # - 'date' : Date object, with the time truncated. Example values: v:Date.parse('2010-01-01')
73
+ # - 'datetime' : Date object including the time. Example values: v:Date.parse('2010-01-01 14:20:25')
74
+ # - 'boolean' : Boolean value ('true' or 'false'). Example values: v: true
75
+ # * label [Optional] A string value that some visualizations display for this column. Example: label:'Height'
76
+ # * id [Optional] A unique (basic alphanumeric) string ID of the column. Be careful not to choose a JavaScript keyword. Example: id:'col_1'
77
+ def new_column(type, label="", id ="")
78
+ @cols << { :type => type, :label => label, :id => id }
79
+ end
80
+
81
+ # Adds multiple columns to the data_table.
82
+ #
83
+ # Parameters:
84
+ # * columns [Required] An array of column objects {:type, :label, :id}. Calls new_column for each column object.
85
+ def new_columns(columns)
86
+ columns.each do |column|
87
+ new_column(column[:type], column[:label], column[:id])
88
+ end
89
+ end
90
+
91
+ # Sets a column in data_table, specified by column_index with an array of column_values. column_index starts from 0.
92
+ #
93
+ # Parameters
94
+ # * column_index [Required] The column to assign column_values. column_index starts from 0.
95
+ # * column_values [Required] An array of cell values.
96
+ def set_column(column_index, column_values)
97
+ if @rows.size < column_values.size
98
+ 1.upto(column_values.size - @rows.size) { @rows << Array.new }
99
+ end
100
+
101
+ column_values.each_with_index do |column_value, row_index|
102
+ set_cell(row_index, column_index, column_value)
103
+ end
104
+ end
105
+
106
+ # Gets a column of cell values from the data_table, at column_index. column_index starts from 0.
107
+ #
108
+ # Parameters
109
+ # * column_index [Required] The column to retrieve column values. column_index starts from 0.
110
+ def get_column(column_index)
111
+ @rows.transpose[column_index].collect(&:v)
112
+ end
113
+
114
+ # Adds a new row to the data_table.
115
+ # Call method without any parameters to add an empty row, otherwise, call method with a row object.
116
+ #
117
+ # Parameters:
118
+ # * row [Optional] An array of cell values specifying the data for the new row.
119
+ # - 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.
120
+ # - You can mix simple values and cell objects in the same method call.
121
+ # - To create an empty cell, use nil or empty string.
122
+ def add_row(row_values=[])
123
+ @rows << Array.new
124
+ row_index = @rows.size-1
125
+
126
+ row_values.each_with_index do |row_value, column_index|
127
+ set_cell(row_index, column_index, row_value)
128
+ end
129
+ end
130
+
131
+ # 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.
132
+ #
133
+ # Parameters:
134
+ # * array_or_num [Required] Either an array or a number.
135
+ # - Array: An array of row objects used to populate a set of new rows. Each row is an object as described in add_row().
136
+ # - Number: A number specifying the number of new empty rows to create.
137
+ def add_rows(array_or_num)
138
+ if array_or_num.is_a?(Array)
139
+ array_or_num.each do |row|
140
+ add_row(row)
141
+ end
142
+ else
143
+ array_or_num.times do
144
+ add_row
145
+ end
146
+ end
147
+ end
148
+
149
+ # Gets a row of cell values from the data_table, at row_index. row_index starts from 0.
150
+ #
151
+ # Parameters
152
+ # * row_index [Required] The row to retrieve row values. row_index starts from 0.
153
+ def get_row(row_index)
154
+ @rows[row_index].collect(&:v)
155
+ end
156
+
157
+ # Sets the value (and formatted value) of a cell.
158
+ #
159
+ # Parameters:
160
+ # * row_index [Required] A number greater than or equal to zero, but smaller than the total number of rows.
161
+ # * column_index [Required] A number greater than or equal to zero, but smaller than the total number of columns.
162
+ # * value [Required] The cell value.
163
+ # The data type should match the column data type.
164
+ # You can specify a value for a cell (e.g. 'hi').
165
+ # Or specify a formatted value using cell objects (e.g. {v:55, f:'Fifty-five'}).
166
+ def set_cell(row_index, column_index, value)
167
+ if within_range?(row_index, column_index)
168
+ verify_against_column_type( @cols[column_index][:type], value )
169
+ @rows[row_index][column_index] = GoogleVisualr::DataTable::Cell.new(value)
170
+ else
171
+ raise RangeError, "row_index and column_index MUST be < @rows.size and @cols.size", caller
172
+ end
173
+ end
174
+
175
+ # Gets a cell value from the visualization, at row_index, column_index. row_index and column_index start from 0.
176
+ #
177
+ # Parameters:
178
+ # * row_index [Required] row_index starts from 0.
179
+ # * column_index [Required] column_index starts from 0.
180
+ def get_cell(row_index, column_index)
181
+ if within_range?(row_index, column_index)
182
+ @rows[row_index][column_index].v
183
+ else
184
+ raise RangeError, "row_index and column_index MUST be < @rows.size and @cols.size", caller
185
+ end
186
+ end
187
+
188
+ # Applies one or more formatters to the data_table to format the columns as specified by the formatter/s.
189
+ #
190
+ # Parameters:
191
+ # * formatter/s [Required] One, or an array of formatters.
192
+ def format(*formatters)
193
+ @formatters ||= Array.new
194
+ @formatters += formatters
195
+ end
196
+
197
+ # Returns the JavaScript equivalent for this data_table instance.
198
+ def to_js
199
+ js = "var data_table = new google.visualization.DataTable();"
200
+
201
+ @cols.each do |column|
202
+ js << "data_table.addColumn('#{column[:type]}', '#{column[:label]}', '#{column[:id]}');"
203
+ end
204
+
205
+ @rows.each do |row|
206
+ js << "data_table.addRow("
207
+ js << "[ #{row.collect { |cell| cell.to_js }.join(", ")} ]" unless row.empty?
208
+ js << ");"
209
+ end
210
+
211
+ if @formatters
212
+ @formatters.each do |formatter|
213
+ js << formatter.to_js
214
+ end
215
+ end
216
+
217
+ js
218
+ end
219
+
220
+ private
221
+
222
+ def within_range?(row_index, column_index)
223
+ row_index < @rows.size && column_index < @cols.size
224
+ end
225
+
226
+ def verify_against_column_type(type, value)
227
+ v = value.is_a?(Hash) ? value[:v] : value
228
+
229
+ case
230
+ when type == "string"
231
+ raise ArgumentError, "cell value '#{v}' is not a String", caller unless v.is_a?(String)
232
+ when type == "number"
233
+ raise ArgumentError, "cell value '#{v}' is not an Integer or a Float", caller unless v.is_a?(Integer) || v.is_a?(Float)
234
+ when type == "date"
235
+ raise ArgumentError, "cell value '#{v}' is not a Date", caller unless v.is_a?(Date)
236
+ when type == 'datetime'
237
+ raise ArgumentError, "cell value '#{v}' is not a DateTime", caller unless v.is_a?(DateTime)
238
+ when type == "boolean"
239
+ raise ArgumentError, "cell value '#{v}' is not a Boolean", caller unless v.is_a?(TrueClass) || v.is_a?(FalseClass)
240
+ end
241
+ end
242
+
243
+
244
+ class Cell
245
+ include GoogleVisualr::ParamHelpers
246
+
247
+ attr_accessor :v # value
248
+ attr_accessor :f # formatted
249
+ attr_accessor :p # properties
250
+
251
+ def initialize(*args)
252
+ options = args.pop
253
+
254
+ if options.is_a?(Hash)
255
+ @v = options[:v]
256
+ @f = options[:f]
257
+ @p = options[:p]
258
+ else
259
+ @v = options
260
+ end
261
+ end
262
+
263
+ def to_js
264
+ js = "{"
265
+ js << "v: #{typecast(@v)}"
266
+ js << ", f: '#{@f}'" unless @f.nil?
267
+ js << ", p: #{@p}" unless @p.nil?
268
+ js << "}"
269
+
270
+ js
271
+ end
272
+
273
+ end
274
+
275
+ end
276
+
277
+ end