seer 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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.
@@ -0,0 +1,49 @@
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" class="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
+ Seer is developed and maintained by {Corey Ehmke}[http://www.idolhands.com/] at {SEO Logic}[http://www.seologic.com/].
48
+
49
+ Copyright (c) 2010 Corey Ehmke / SEO Logic, released under the MIT license
@@ -0,0 +1,63 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "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 = "corey@seologic.com"
11
+ gem.homepage = "http://github.com/Bantik/seer"
12
+ gem.authors = ["Corey Ehmke / SEO Logic"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.files = [
15
+ "init.rb",
16
+ "lib/seer.rb",
17
+ "lib/seer/area_chart.rb",
18
+ "lib/seer/bar_chart.rb",
19
+ "lib/seer/chart.rb",
20
+ "lib/seer/column_chart.rb",
21
+ "lib/seer/gauge.rb",
22
+ "lib/seer/line_chart.rb",
23
+ "lib/seer/pie_chart.rb",
24
+ "lib/seer/visualization_helper.rb",
25
+ "LICENSE",
26
+ "Rakefile",
27
+ "README.rdoc",
28
+ "rails/init.rb",
29
+ "spec/spec.opts",
30
+ "spec/spec_helper.rb",
31
+ "spec/seer_spec.rb"
32
+ ]
33
+ end
34
+ Jeweler::GemcutterTasks.new
35
+ rescue LoadError
36
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
37
+ end
38
+
39
+ require 'spec/rake/spectask'
40
+ Spec::Rake::SpecTask.new(:spec) do |spec|
41
+ spec.libs << 'lib' << 'spec'
42
+ spec.spec_files = FileList['spec/**/*_spec.rb']
43
+ end
44
+
45
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
46
+ spec.libs << 'lib' << 'spec'
47
+ spec.pattern = 'spec/**/*_spec.rb'
48
+ spec.rcov = true
49
+ end
50
+
51
+ task :spec => :check_dependencies
52
+
53
+ task :default => :spec
54
+
55
+ require 'rake/rdoctask'
56
+ Rake::RDocTask.new do |rdoc|
57
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
58
+
59
+ rdoc.rdoc_dir = 'rdoc'
60
+ rdoc.title = "seer #{version}"
61
+ rdoc.rdoc_files.include('README*')
62
+ rdoc.rdoc_files.include('lib/**/*.rb')
63
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'seer'
@@ -0,0 +1,58 @@
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/line_chart'
9
+ require 'seer/pie_chart'
10
+
11
+ VISUALIZERS = [:area_chart, :bar_chart, :column_chart, :gauge, :line_chart, :pie_chart]
12
+
13
+ def self.valid_hex_number?(val) #:nodoc:
14
+ return false unless val.is_a?(String) && ! val.empty?
15
+ ! (val =~ /^\#([0-9]|[a-f]|[A-F])+$/).nil? && val.length == 7
16
+ end
17
+
18
+ def self.log(message) #:nodoc:
19
+ RAILS_DEFAULT_LOGGER.info(message)
20
+ end
21
+
22
+ def self.init_visualization
23
+ %{<script type="text/javascript" src="http://www.google.com/jsapi"></script> }
24
+ end
25
+
26
+ def self.visualize(data, args={})
27
+ raise ArgumentError, "Seer: Invalid visualizer: #{args[:as]}" unless args[:as] && VISUALIZERS.include?(args[:as])
28
+ raise ArgumentError, "Seer: No data provided!" unless data && ! data.empty?
29
+ self.send(args[:as], data, args)
30
+ end
31
+
32
+ private
33
+
34
+ def self.area_chart(data, args)
35
+ AreaChart.render(data, args)
36
+ end
37
+
38
+ def self.bar_chart(data, args)
39
+ BarChart.render(data, args)
40
+ end
41
+
42
+ def self.column_chart(data, args)
43
+ ColumnChart.render(data, args)
44
+ end
45
+
46
+ def self.gauge(data, args)
47
+ Gauge.render(data, args)
48
+ end
49
+
50
+ def self.line_chart(data, args)
51
+ LineChart.render(data, args)
52
+ end
53
+
54
+ def self.pie_chart(data, args)
55
+ PieChart.render(data, args)
56
+ end
57
+
58
+ end
@@ -0,0 +1,133 @@
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" class="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_series.first.map{|d| d.send(data_label)}.uniq.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_series.first.map{|d| d.send(data_label)}.uniq
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 nonstring_options #:nodoc:
91
+ [ :axis_font_size, :colors, :enable_tooltip, :height, :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]
92
+ end
93
+
94
+ def string_options #:nodoc:
95
+ [ :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 ]
96
+ end
97
+
98
+ def to_js #:nodoc:
99
+
100
+ %{
101
+ <script type="text/javascript">
102
+ google.load('visualization', '1', {'packages':['areachart']});
103
+ google.setOnLoadCallback(drawChart);
104
+ function drawChart() {
105
+ var data = new google.visualization.DataTable();
106
+ #{data_columns}
107
+ #{data_table.to_s}
108
+ var options = {};
109
+ #{options}
110
+ var container = document.getElementById('chart');
111
+ var chart = new google.visualization.AreaChart(container);
112
+ chart.draw(data, options);
113
+ }
114
+ </script>
115
+ }
116
+ end
117
+
118
+ def self.render(data, args) #:nodoc:
119
+ graph = Seer::AreaChart.new(
120
+ :data => data,
121
+ :series_label => args[:series][:series_label],
122
+ :data_series => args[:series][:data_series],
123
+ :data_label => args[:series][:data_label],
124
+ :data_method => args[:series][:data_method],
125
+ :chart_options => args[:chart_options],
126
+ :chart_element => args[:in_element] || 'chart'
127
+ )
128
+ graph.to_js
129
+ end
130
+
131
+ end
132
+
133
+ 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" class="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':['barchart']});
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('chart');
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