glennr-seer 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
data/CONTRIBUTORS ADDED
@@ -0,0 +1,6 @@
1
+ Thanks go to the following individuals for their contributions:
2
+
3
+ Alexey Kuleshov (http://github.com/kulesa)
4
+ Harold Giménez (http://github.com/hgimenez)
5
+ Henry Poydar (http://github.com/hpoydar)
6
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Corey Ehmke / SEO Logic
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,51 @@
1
+ =Seer
2
+
3
+ Seer is a lightweight, semantically rich wrapper for the Google Visualization API. It allows you to easily create a visualization of data in a variety of formats, including area charts, bar charts, column charts, gauges, line charts, and pie charts.
4
+
5
+ ==Usage
6
+
7
+ Add the following to the head of the page that will display a chart, or add it to your layout file:
8
+
9
+ <%= Seer::init_visualization -%>
10
+
11
+ Gather the data you want to visualize in an instance variable in your controller, then use the visualize method to insert the appropriate chart in your view.
12
+
13
+ == Example
14
+
15
+ In your controller:
16
+
17
+ # @data must be an array, and each object in the array must respond to the data method specified
18
+ # in the visualize call (in this example, 'quantity')
19
+ @data = Widget.all
20
+
21
+ In your view:
22
+
23
+ <div id="chart"></div>
24
+
25
+ <%= Seer::visualize(
26
+ @widgets,
27
+ :as => :bar_chart,
28
+ :in_element => 'chart',
29
+ :series => {:series_label => 'name', :data_method => 'quantity'},
30
+ :chart_options => {
31
+ :height => 300,
32
+ :width => 200 * @widgets.size,
33
+ :is_3_d => false,
34
+ :legend => 'none',
35
+ :colors => ["#990000"],
36
+ :title => "Widget Quantities",
37
+ :title_x => 'Quantity',
38
+ :title_y => 'Widgets'
39
+ }
40
+ )
41
+ -%>
42
+
43
+ == More information
44
+
45
+ For examples of additional chart types, refer to the documentation for each of the individual chart objects, or see the blog post announcing Seer: {Simple, Semantic Graphing for Ruby on Rails with Seer}[http://www.idolhands.com/ruby-on-rails/gems-plugins-and-engines/graphing-for-ruby-on-rails-with-seer]
46
+
47
+ A {sample project}[http://github.com/Bantik/seer_sample] that demonstrates each of the chart types is available on GitHub.
48
+
49
+ Seer is developed and maintained by {Corey Ehmke}[http://www.idolhands.com/] at {SEO Logic}[http://www.seologic.com/].
50
+
51
+ Copyright (c) 2010 Corey Ehmke / SEO Logic, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "glennr-seer"
8
+ gem.summary = %Q{Seer is a lightweight, semantically rich wrapper for the Google Visualization API.}
9
+ gem.description = %Q{ Seer is a lightweight, semantically rich wrapper for the Google Visualization API. It allows you to easily create a visualization of data in a variety of formats, including area charts, bar charts, column charts, gauges, line charts, and pie charts.}
10
+ gem.email = "glenn.roberts@siyelo.com"
11
+ gem.homepage = "http://github.com/glennr/seer"
12
+ gem.authors = ["Corey Ehmke / SEO Logic", "Glenn Roberts / Siyelo"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.files = [
15
+ "CONTRIBUTORS",
16
+ "init.rb",
17
+ "lib/seer.rb",
18
+ "lib/seer/area_chart.rb",
19
+ "lib/seer/bar_chart.rb",
20
+ "lib/seer/chart.rb",
21
+ "lib/seer/column_chart.rb",
22
+ "lib/seer/gauge.rb",
23
+ "lib/seer/geomap.rb",
24
+ "lib/seer/line_chart.rb",
25
+ "lib/seer/pie_chart.rb",
26
+ "lib/seer/visualization_helper.rb",
27
+ "LICENSE",
28
+ "Rakefile",
29
+ "README.rdoc",
30
+ "rails/init.rb",
31
+ "spec/spec.opts",
32
+ "spec/spec_helper.rb",
33
+ "spec/seer_spec.rb"
34
+ ]
35
+ end
36
+ Jeweler::GemcutterTasks.new
37
+ rescue LoadError
38
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
39
+ end
40
+
41
+ require 'spec/rake/spectask'
42
+ Spec::Rake::SpecTask.new(:spec) do |spec|
43
+ spec.libs << 'lib' << 'spec'
44
+ spec.spec_files = FileList['spec/**/*_spec.rb']
45
+ end
46
+
47
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
48
+ spec.libs << 'lib' << 'spec'
49
+ spec.pattern = 'spec/**/*_spec.rb'
50
+ spec.rcov = true
51
+ end
52
+
53
+ task :spec => :check_dependencies
54
+
55
+ task :default => :spec
56
+
57
+ require 'rake/rdoctask'
58
+ Rake::RDocTask.new do |rdoc|
59
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
60
+
61
+ rdoc.rdoc_dir = 'rdoc'
62
+ rdoc.title = "seer #{version}"
63
+ rdoc.rdoc_files.include('README*')
64
+ rdoc.rdoc_files.include('lib/**/*.rb')
65
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'seer'
data/lib/seer.rb ADDED
@@ -0,0 +1,73 @@
1
+ module Seer
2
+
3
+ require 'seer/chart'
4
+ require 'seer/area_chart'
5
+ require 'seer/bar_chart'
6
+ require 'seer/column_chart'
7
+ require 'seer/gauge'
8
+ require 'seer/geomap'
9
+ require 'seer/line_chart'
10
+ require 'seer/pie_chart'
11
+
12
+ VISUALIZERS = [:area_chart, :bar_chart, :column_chart, :gauge, :geomap, :line_chart, :pie_chart]
13
+
14
+ def self.valid_hex_number?(val) #:nodoc:
15
+ return false unless val.is_a?(String) && ! val.empty?
16
+ ! (val =~ /^\#([0-9]|[a-f]|[A-F])+$/).nil? && val.length == 7
17
+ end
18
+
19
+ def self.log(message) #:nodoc:
20
+ RAILS_DEFAULT_LOGGER.info(message)
21
+ end
22
+
23
+ # gifted from ActionView::Helpers::JavaScriptHelper
24
+ def self.options_for_javascript(options)
25
+ '{' + options.map {|k, v| "#{k}:\"#{v}\""}.sort.join(', ') + '}'
26
+ end
27
+
28
+ def self.init_visualization
29
+ %{
30
+ <script type="text/javascript">
31
+ var jsapi = (("https:" == document.location.protocol) ? "https://" : "http://");
32
+ document.write(unescape("%3Cscript src='" + jsapi + "www.google.com/jsapi' type='text/javascript'%3E%3C/script%3E"));
33
+ </script>
34
+ }
35
+ end
36
+
37
+ def self.visualize(data, args={})
38
+ raise ArgumentError, "Seer: Invalid visualizer: #{args[:as]}" unless args[:as] && VISUALIZERS.include?(args[:as])
39
+ raise ArgumentError, "Seer: No data provided!" unless data && ! data.empty?
40
+ self.send(args[:as], data, args)
41
+ end
42
+
43
+ private
44
+
45
+ def self.area_chart(data, args)
46
+ AreaChart.render(data, args)
47
+ end
48
+
49
+ def self.bar_chart(data, args)
50
+ BarChart.render(data, args)
51
+ end
52
+
53
+ def self.column_chart(data, args)
54
+ ColumnChart.render(data, args)
55
+ end
56
+
57
+ def self.gauge(data, args)
58
+ Gauge.render(data, args)
59
+ end
60
+
61
+ def self.geomap(data, args)
62
+ Geomap.render(data, args)
63
+ end
64
+
65
+ def self.line_chart(data, args)
66
+ LineChart.render(data, args)
67
+ end
68
+
69
+ def self.pie_chart(data, args)
70
+ PieChart.render(data, args)
71
+ end
72
+
73
+ end
@@ -0,0 +1,139 @@
1
+ module Seer
2
+
3
+ # =USAGE
4
+ #
5
+ # In your controller:
6
+ #
7
+ # @data = Widgets.all # Must be an array, and must respond
8
+ # # to the data method specified below (in this example, 'quantity')
9
+ #
10
+ # @series = @data.map{|w| w.widget_stats} # An array of arrays
11
+ #
12
+ # In your view:
13
+ #
14
+ # <div id="chart"></div>
15
+ #
16
+ # <%= Seer::visualize(
17
+ # @data,
18
+ # :as => :area_chart,
19
+ # :in_element => 'chart',
20
+ # :series => {
21
+ # :series_label => 'name',
22
+ # :data_label => 'date',
23
+ # :data_method => 'quantity',
24
+ # :data_series => @series
25
+ # },
26
+ # :chart_options => {
27
+ # :height => 300,
28
+ # :width => 300,
29
+ # :axis_font_size => 11,
30
+ # :colors => ['#7e7587','#990000','#009900'],
31
+ # :title => "Widget Quantities",
32
+ # :point_size => 5
33
+ # }
34
+ # )
35
+ # -%>
36
+ #
37
+ # For details on the chart options, see the Google API docs at
38
+ # http://code.google.com/apis/visualization/documentation/gallery/areachart.html
39
+ #
40
+ class AreaChart
41
+
42
+ include Seer::Chart
43
+
44
+ # Graph options
45
+ attr_accessor :axis_color, :axis_background_color, :axis_font_size, :background_color, :border_color, :data_table, :enable_tooltip, :focus_border_color, :height, :is_stacked, :legend, :legend_background_color, :legend_font_size, :legend_text_color, :line_size, :log_scale, :max, :min, :point_size, :reverse_axis, :show_categories, :title, :title_x, :title_y, :title_color, :title_font_size, :tooltip_font_size, :tooltip_height, :number, :tooltip_width, :width
46
+
47
+ # Graph data
48
+ attr_accessor :series_label, :data_label, :data, :data_method, :data_series
49
+
50
+ def initialize(args={}) #:nodoc:
51
+
52
+ # Standard options
53
+ args.each{ |method,arg| self.send("#{method}=",arg) if self.respond_to?(method) }
54
+
55
+ # Chart options
56
+ args[:chart_options].each{ |method, arg| self.send("#{method}=",arg) if self.respond_to?(method) }
57
+
58
+ # Handle defaults
59
+ @colors ||= args[:chart_options][:colors] || DEFAULT_COLORS
60
+ @legend ||= args[:chart_options][:legend] || DEFAULT_LEGEND_LOCATION
61
+ @height ||= args[:chart_options][:height] || DEFAULT_HEIGHT
62
+ @width ||= args[:chart_options][:width] || DEFAULT_WIDTH
63
+
64
+ @data_table = []
65
+
66
+ end
67
+
68
+ def data_columns #:nodoc:
69
+ _data_columns = " data.addRows(#{data_rows.size});\r"
70
+ _data_columns << " data.addColumn('string', 'Date');\r"
71
+ data.each do |datum|
72
+ _data_columns << " data.addColumn('number', '#{datum.send(series_label)}');\r"
73
+ end
74
+ _data_columns
75
+ end
76
+
77
+ def data_table #:nodoc:
78
+ _rows = data_rows
79
+ _rows.each_with_index do |r,i|
80
+ @data_table << " data.setCell(#{i}, 0,'#{r}');\r"
81
+ end
82
+ data_series.each_with_index do |column,i|
83
+ column.each_with_index do |c,j|
84
+ @data_table << " data.setCell(#{j},#{i+1},#{c.send(data_method)});\r"
85
+ end
86
+ end
87
+ @data_table
88
+ end
89
+
90
+ def data_rows
91
+ data_series.inject([]) do |rows, element|
92
+ rows |= element.map { |e| e.send(data_label) }
93
+ end
94
+ end
95
+
96
+ def nonstring_options #:nodoc:
97
+ [ :axis_font_size, :colors, :enable_tooltip, :height, :is_stacked, :legend_font_size, :line_size, :log_scale, :max, :min, :point_size, :reverse_axis, :show_categories, :title_font_size, :tooltip_font_size, :tooltip_height, :tooltip_width, :width]
98
+ end
99
+
100
+ def string_options #:nodoc:
101
+ [ :axis_color, :axis_background_color, :background_color, :border_color, :focus_border_color, :legend, :legend_background_color, :legend_text_color, :title, :title_x, :title_y, :title_color ]
102
+ end
103
+
104
+ def to_js #:nodoc:
105
+
106
+ %{
107
+ <script type="text/javascript">
108
+ google.load('visualization', '1', {'packages':['corechart']});
109
+ google.setOnLoadCallback(drawChart);
110
+ function drawChart() {
111
+ var data = new google.visualization.DataTable();
112
+ #{data_columns}
113
+ #{data_table.to_s}
114
+ var options = {};
115
+ #{options}
116
+ var container = document.getElementById('#{self.chart_element}');
117
+ var chart = new google.visualization.AreaChart(container);
118
+ chart.draw(data, options);
119
+ }
120
+ </script>
121
+ }
122
+ end
123
+
124
+ def self.render(data, args) #:nodoc:
125
+ graph = Seer::AreaChart.new(
126
+ :data => data,
127
+ :series_label => args[:series][:series_label],
128
+ :data_series => args[:series][:data_series],
129
+ :data_label => args[:series][:data_label],
130
+ :data_method => args[:series][:data_method],
131
+ :chart_options => args[:chart_options],
132
+ :chart_element => args[:in_element] || 'chart'
133
+ )
134
+ graph.to_js
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1,124 @@
1
+ module Seer
2
+
3
+ # =USAGE
4
+ #
5
+ # In your controller:
6
+ #
7
+ # @data = Widgets.all # Must be an array, and must respond
8
+ # # to the data method specified below (in this example, 'quantity')
9
+ #
10
+ # In your view:
11
+ #
12
+ # <div id="chart"></div>
13
+ #
14
+ # <%= Seer::visualize(
15
+ # @widgets,
16
+ # :as => :bar_chart,
17
+ # :in_element => 'chart',
18
+ # :series => {:series_label => 'name', :data_method => 'quantity'},
19
+ # :chart_options => {
20
+ # :height => 300,
21
+ # :width => 200 * @widgets.size,
22
+ # :is_3_d => false,
23
+ # :legend => 'none',
24
+ # :colors => ["#990000"],
25
+ # :title => "Widget Quantities",
26
+ # :title_x => 'Quantity',
27
+ # :title_y => 'Widgets'
28
+ # }
29
+ # )
30
+ # -%>
31
+ #
32
+ # Colors are treated differently for 2d and 3d graphs. If you set is_3_d to true, set the
33
+ # graph colors like this:
34
+ #
35
+ # :colors => "[{color:'#990000', darker:'#660000'}]",
36
+ #
37
+ # For details on the chart options, see the Google API docs at
38
+ # http://code.google.com/apis/visualization/documentation/gallery/barchart.html
39
+ #
40
+ class BarChart
41
+
42
+ include Seer::Chart
43
+
44
+ # Chart options accessors
45
+ attr_accessor :axis_color, :axis_background_color, :axis_font_size, :background_color, :border_color, :data_table, :enable_tooltip, :focus_border_color, :height, :is_3_d, :is_stacked, :legend, :legend_background_color, :legend_font_size, :legend_text_color, :log_scale, :max, :min, :reverse_axis, :show_categories, :title, :title_x, :title_y, :title_color, :title_font_size, :tooltip_font_size, :tooltip_height, :tooltip_width, :width
46
+
47
+ # Graph data
48
+ attr_accessor :data, :data_method, :label_method
49
+
50
+ def initialize(args={}) #:nodoc:
51
+
52
+ # Standard options
53
+ args.each{ |method,arg| self.send("#{method}=",arg) if self.respond_to?(method) }
54
+
55
+ # Chart options
56
+ args[:chart_options].each{ |method, arg| self.send("#{method}=",arg) if self.respond_to?(method) }
57
+
58
+ # Handle defaults
59
+ @colors ||= args[:chart_options][:colors] || DEFAULT_COLORS
60
+ @legend ||= args[:chart_options][:legend] || DEFAULT_LEGEND_LOCATION
61
+ @height ||= args[:chart_options][:height] || DEFAULT_HEIGHT
62
+ @width ||= args[:chart_options][:width] || DEFAULT_WIDTH
63
+ @is_3_d ||= args[:chart_options][:is_3_d]
64
+
65
+ @data_table = []
66
+
67
+ end
68
+
69
+ def data_table #:nodoc:
70
+ data.each_with_index do |datum, column|
71
+ @data_table << [
72
+ " data.setValue(#{column}, 0,'#{datum.send(label_method)}');\r",
73
+ " data.setValue(#{column}, 1, #{datum.send(data_method)});\r"
74
+ ]
75
+ end
76
+ @data_table
77
+ end
78
+
79
+ def is_3_d #:nodoc:
80
+ @is_3_d.blank? ? false : @is_3_d
81
+ end
82
+
83
+ def nonstring_options #:nodoc:
84
+ [:axis_font_size, :colors, :enable_tooltip, :is_3_d, :is_stacked, :legend_font_size, :log_scale, :max, :min, :reverse_axis, :show_categories, :title_font_size, :tooltip_font_size, :tooltip_width]
85
+ end
86
+
87
+ def string_options #:nodoc:
88
+ [:axis_color, :axis_background_color, :background_color, :border_color, :focus_border_color, :height, :legend, :legend_background_color, :legend_text_color, :title, :title_x, :title_y, :title_color, :width]
89
+ end
90
+
91
+ def to_js #:nodoc:
92
+
93
+ %{
94
+ <script type="text/javascript">
95
+ google.load('visualization', '1', {'packages':['corechart']});
96
+ google.setOnLoadCallback(drawChart);
97
+ function drawChart() {
98
+ var data = new google.visualization.DataTable();
99
+ #{data_columns}
100
+ #{data_table.to_s}
101
+ var options = {};
102
+ #{options}
103
+ var container = document.getElementById('#{self.chart_element}');
104
+ var chart = new google.visualization.BarChart(container);
105
+ chart.draw(data, options);
106
+ }
107
+ </script>
108
+ }
109
+ end
110
+
111
+ def self.render(data, args) #:nodoc:
112
+ graph = Seer::BarChart.new(
113
+ :label_method => args[:series][:series_label],
114
+ :data_method => args[:series][:data_method],
115
+ :chart_options => args[:chart_options],
116
+ :chart_element => args[:in_element] || 'chart',
117
+ :data => data
118
+ )
119
+ graph.to_js
120
+ end
121
+
122
+ end
123
+
124
+ end