glennr-seer 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,143 @@
1
+ module Seer
2
+
3
+ # =USAGE
4
+ #
5
+ # In your controller:
6
+ #
7
+ # @data = Widgets.all # Must be an array of objects that respond to the specidied data method
8
+ # # (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 => :line_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/linechart.html
39
+ #
40
+ class LineChart
41
+
42
+ include Seer::Chart
43
+
44
+ # Graph options
45
+ attr_accessor :axis_color, :axis_background_color, :axis_font_size, :background_color, :border_color, :enable_tooltip, :focus_border_color, :height, :legend, :legend_background_color, :legend_font_size, :legend_text_color, :line_size, :log_scale, :max, :min, :point_size, :reverse_axis, :show_categories, :smooth_line, :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 :data, :data_label, :data_method, :data_series, :data_table, :series_label
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
+ if data.first.respond_to?(series_label)
72
+ data.each{ |datum| _data_columns << " data.addColumn('number', '#{datum.send(series_label)}');\r" }
73
+ else
74
+ data.each{ |datum| _data_columns << " data.addColumn('number', '#{series_label}');\r" }
75
+ end
76
+ _data_columns
77
+ end
78
+
79
+ def data_table #:nodoc:
80
+ _rows = data_rows
81
+ _rows.each_with_index do |r,i|
82
+ @data_table << " data.setCell(#{i}, 0,'#{r}');\r"
83
+ end
84
+ data_series.each_with_index do |column,i|
85
+ column.each_with_index do |c,j|
86
+ @data_table << "data.setCell(#{j},#{i+1},#{c.send(data_method)});\r"
87
+ end
88
+ end
89
+ @data_table
90
+ end
91
+
92
+ def data_rows
93
+ data_series.inject([]) do |rows, element|
94
+ rows |= element.map { |e| e.send(data_label) }
95
+ end
96
+ end
97
+
98
+ def nonstring_options #:nodoc:
99
+ [ :axis_font_size, :colors, :enable_tooltip, :height, :legend_font_size, :line_size, :log_scale, :max, :min, :point_size, :reverse_axis, :show_categories, :smooth_line, :title_font_size, :tooltip_font_size, :tooltip_height, :tooltip_width, :width]
100
+ end
101
+
102
+ def string_options #:nodoc:
103
+ [ :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 ]
104
+ end
105
+
106
+ def to_js #:nodoc:
107
+
108
+ %{
109
+ <script type="text/javascript">
110
+ google.load('visualization', '1', {'packages':['corechart']});
111
+ google.setOnLoadCallback(drawChart);
112
+ function drawChart() {
113
+ var data = new google.visualization.DataTable();
114
+ #{data_columns}
115
+ #{data_table.to_s}
116
+ var options = {};
117
+ #{options}
118
+ var container = document.getElementById('#{self.chart_element}');
119
+ var chart = new google.visualization.LineChart(container);
120
+ chart.draw(data, options);
121
+ }
122
+ </script>
123
+ }
124
+ end
125
+
126
+ # ====================================== Class Methods =========================================
127
+
128
+ def self.render(data, args) #:nodoc:
129
+ graph = Seer::LineChart.new(
130
+ :data => data,
131
+ :series_label => args[:series][:series_label],
132
+ :data_series => args[:series][:data_series],
133
+ :data_label => args[:series][:data_label],
134
+ :data_method => args[:series][:data_method],
135
+ :chart_options => args[:chart_options],
136
+ :chart_element => args[:in_element] || 'chart'
137
+ )
138
+ graph.to_js
139
+ end
140
+
141
+ end
142
+
143
+ end
@@ -0,0 +1,128 @@
1
+ module Seer
2
+
3
+ # =USAGE
4
+ #
5
+ # In your controller:
6
+ #
7
+ # @data = Widgets.all # Must be an array of objects that respond to the specidied data method
8
+ # # (In this example, 'quantity'
9
+ #
10
+ # In your view:
11
+ #
12
+ # <div id="chart"></div>
13
+ #
14
+ # <%= Seer::visualize(
15
+ # @data,
16
+ # :as => :pie_chart,
17
+ # :series => {:series_label => 'name', :data_method => 'quantity'},
18
+ # :chart_options => {
19
+ # :height => 300,
20
+ # :width => 300,
21
+ # :axis_font_size => 11,
22
+ # :title => "Widget Quantities",
23
+ # :point_size => 5,
24
+ # :is_3_d => true
25
+ # }
26
+ # )
27
+ # -%>
28
+ #
29
+ # For details on the chart options, see the Google API docs at
30
+ # http://code.google.com/apis/visualization/documentation/gallery/piechart.html
31
+ #
32
+ class PieChart
33
+
34
+ include Seer::Chart
35
+
36
+ # Chart options accessors
37
+ attr_accessor :background_color, :border_color, :chart_area,
38
+ :enable_tooltip, :focus_border_color, :height, :is_3_d, :legend,
39
+ :legend_background_color, :legend_font_size, :legend_text_color,
40
+ :pie_join_angle, :pie_minimal_angle, :title, :title_x,
41
+ :title_y, :title_color, :title_font_size, :tooltip_font_size,
42
+ :tooltip_height, :tooltip_width, :width, :pie_slice_text
43
+
44
+ # Graph data
45
+ attr_accessor :data, :data_method, :data_table, :label_method
46
+
47
+ def initialize(args={}) #:nodoc:
48
+
49
+ # Standard options
50
+ args.each{ |method,arg| self.send("#{method}=",arg) if self.respond_to?(method) }
51
+
52
+ # Chart options
53
+ args[:chart_options].each{ |method, arg| self.send("#{method}=",arg) if self.respond_to?(method) }
54
+
55
+ # Handle defaults
56
+ @colors ||= args[:chart_options][:colors] || DEFAULT_COLORS
57
+ @legend ||= args[:chart_options][:legend] || DEFAULT_LEGEND_LOCATION
58
+ @height ||= args[:chart_options][:height] || DEFAULT_HEIGHT
59
+ @width ||= args[:chart_options][:width] || DEFAULT_WIDTH
60
+ @is_3_d ||= args[:chart_options][:is_3_d]
61
+
62
+ @data_table = []
63
+
64
+ end
65
+
66
+ def data_table #:nodoc:
67
+ data.each_with_index do |datum, column|
68
+ @data_table << [
69
+ " data.setValue(#{column}, 0,'#{datum.send(label_method)}');\r",
70
+ " data.setValue(#{column}, 1, #{datum.send(data_method)});\r"
71
+ ]
72
+ end
73
+ @data_table
74
+ end
75
+
76
+ def is_3_d #:nodoc:
77
+ @is_3_d.blank? ? false : @is_3_d
78
+ end
79
+
80
+ def nonstring_options #:nodoc:
81
+ [:colors, :enable_tooltip, :height, :is_3_d, :legend_font_size,
82
+ :pie_join_angle, :pie_minimal_angle, :title_font_size, :tooltip_font_size,
83
+ :tooltip_width, :width]
84
+ end
85
+
86
+ def string_options #:nodoc:
87
+ [:background_color, :border_color, :focus_border_color, :legend,
88
+ :legend_background_color, :legend_text_color, :title, :title_color,
89
+ :pie_slice_text]
90
+ end
91
+
92
+ def hash_options #:nodoc:
93
+ [:chart_area]
94
+ end
95
+
96
+ def to_js #:nodoc:
97
+ %{
98
+ <script type="text/javascript">
99
+ google.load('visualization', '1', {'packages':['corechart']});
100
+ google.setOnLoadCallback(drawChart);
101
+ function drawChart() {
102
+ var data = new google.visualization.DataTable();
103
+ #{data_columns}
104
+ #{data_table.to_s}
105
+ var options = {};
106
+ #{options}
107
+ var container = document.getElementById('#{self.chart_element}');
108
+ var chart = new google.visualization.PieChart(container);
109
+ chart.draw(data, options);
110
+ }
111
+ </script>
112
+ }
113
+ end
114
+
115
+ def self.render(data, args) #:nodoc:
116
+ graph = Seer::PieChart.new(
117
+ :data => data,
118
+ :label_method => args[:series][:series_label],
119
+ :data_method => args[:series][:data_method],
120
+ :chart_options => args[:chart_options],
121
+ :chart_element => args[:in_element] || 'chart'
122
+ )
123
+ graph.to_js
124
+ end
125
+
126
+ end
127
+
128
+ end
@@ -0,0 +1,108 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Seer::AreaChart" do
4
+
5
+ before :each do
6
+ @chart = Seer::AreaChart.new(
7
+ :data => [0,1,2,3],
8
+ :series_label => 'to_s',
9
+ :data_series => [[1,2,3],[3,4,5]],
10
+ :data_label => 'to_s',
11
+ :data_method => 'size',
12
+ :chart_options => {},
13
+ :chart_element => 'chart'
14
+ )
15
+ end
16
+
17
+ describe 'defaults' do
18
+ it_should_behave_like 'it sets default values'
19
+ end
20
+
21
+ describe 'graph options' do
22
+
23
+ [:axis_color, :axis_background_color, :axis_font_size, :background_color, :border_color, :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].each do |accessor|
24
+ it "sets its #{accessor} value" do
25
+ @chart.send("#{accessor}=", 'foo')
26
+ @chart.send(accessor).should == 'foo'
27
+ end
28
+ end
29
+
30
+ it_should_behave_like 'it has colors attribute'
31
+ end
32
+
33
+ it 'renders as JavaScript' do
34
+ (@chart.to_js =~ /javascript/).should be_true
35
+ (@chart.to_js =~ /areachart/).should be_true
36
+ end
37
+
38
+ it 'sets its data columns' do
39
+ @chart.data_columns.should =~ /addRows\(5\)/
40
+ @chart.data_columns.should add_column('string', 'Date')
41
+ @chart.data_columns.should add_column('number', '0')
42
+ @chart.data_columns.should add_column('number', '1')
43
+ @chart.data_columns.should add_column('number', '2')
44
+ @chart.data_columns.should add_column('number', '3')
45
+ end
46
+
47
+ it 'sets its data table' do
48
+ @chart.data_table.to_s.should set_cell(0, 0,'1')
49
+ @chart.data_table.to_s.should set_cell(1, 0,'2')
50
+ @chart.data_table.to_s.should set_cell(2, 0,'3')
51
+ @chart.data_table.to_s.should set_cell(3, 0,'4')
52
+ @chart.data_table.to_s.should set_cell(4, 0,'5')
53
+ @chart.data_table.to_s.should set_cell(0,1,8)
54
+ @chart.data_table.to_s.should set_cell(2,1,8)
55
+ @chart.data_table.to_s.should set_cell(0,2,8)
56
+ @chart.data_table.to_s.should set_cell(1,2,8)
57
+ @chart.data_table.to_s.should set_cell(2,2,8)
58
+ end
59
+
60
+ describe 'when data_series is an array of arrays of arrays/hashes' do
61
+ before(:each) do
62
+ data_series = Array.new(3) {|i| [[i, i+1], [i+1, i+2]]}
63
+ @chart = Seer::AreaChart.new(
64
+ :data => [0,1,2,3],
65
+ :series_label => 'to_s',
66
+ :data_series => data_series,
67
+ :data_label => 'first',
68
+ :data_method => 'size',
69
+ :chart_options => {},
70
+ :chart_element => 'chart'
71
+ )
72
+ end
73
+
74
+ it 'calculates number of rows' do
75
+ @chart.data_columns.should =~ /addRows\(4\)/
76
+ end
77
+
78
+ it 'sets its data table' do
79
+ @chart.data_table.to_s.should set_cell(0, 0,'0')
80
+ @chart.data_table.to_s.should set_cell(1, 0,'1')
81
+ @chart.data_table.to_s.should set_cell(2, 0,'2')
82
+ @chart.data_table.to_s.should set_cell(3, 0,'3')
83
+ end
84
+ end
85
+
86
+ describe 'should receive options' do
87
+ before(:each) do
88
+ data_series = Array.new(3) {|i| [[i, i+1], [i+1, i+2]]}
89
+ @options = {
90
+ :data => [0,1,2,3],
91
+ :series_label => 'to_s',
92
+ :data_series => data_series,
93
+ :data_label => 'first',
94
+ :data_method => 'size',
95
+ :chart_options => {},
96
+ :chart_element => 'chart'
97
+ }
98
+ end
99
+
100
+ it 'should receive :is_stacked option' do
101
+ create_chart_with_option(:is_stacked => true).to_js.should =~ /options\['isStacked'\] = true/
102
+ end
103
+ end
104
+ end
105
+
106
+ def create_chart_with_option(option)
107
+ Seer::AreaChart.new(@options.merge(option))
108
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Seer::BarChart" do
4
+
5
+ before :each do
6
+ @chart = Seer::BarChart.new(
7
+ :data => [0,1,2,3],
8
+ :label_method => 'to_s',
9
+ :data_method => 'size',
10
+ :chart_options => {},
11
+ :chart_element => 'chart'
12
+ )
13
+ end
14
+
15
+ describe 'defaults' do
16
+ it_should_behave_like 'it sets default values'
17
+ end
18
+
19
+ describe 'graph options' do
20
+
21
+ [:axis_color, :axis_background_color, :axis_font_size, :background_color, :border_color, :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].each do |accessor|
22
+ it "sets its #{accessor} value" do
23
+ @chart.send("#{accessor}=", 'foo')
24
+ @chart.send(accessor).should == 'foo'
25
+ end
26
+ end
27
+
28
+ it_should_behave_like 'it has colors attribute'
29
+ end
30
+
31
+ it 'renders as JavaScript' do
32
+ (@chart.to_js =~ /javascript/).should be_true
33
+ (@chart.to_js =~ /barchart/).should be_true
34
+ end
35
+
36
+ it 'sets its data columns' do
37
+ @chart.data_columns.should =~ /addRows\(4\)/
38
+ end
39
+
40
+ it 'sets its data table' do
41
+ @chart.data_table.to_s.should set_value(0, 0,'0')
42
+ @chart.data_table.to_s.should set_value(0, 1, 8)
43
+ @chart.data_table.to_s.should set_value(1, 0,'1')
44
+ @chart.data_table.to_s.should set_value(1, 1, 8)
45
+ @chart.data_table.to_s.should set_value(2, 0,'2')
46
+ @chart.data_table.to_s.should set_value(2, 1, 8)
47
+ @chart.data_table.to_s.should set_value(3, 0,'3')
48
+ @chart.data_table.to_s.should set_value(3, 1, 8)
49
+ end
50
+
51
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Seer::Chart" do
4
+
5
+ before :all do
6
+ @chart = Seer::AreaChart.new(
7
+ :data => [0,1,2,3],
8
+ :series_label => 'to_s',
9
+ :data_series => [[1,2,3],[3,4,5]],
10
+ :data_label => 'to_s',
11
+ :data_method => 'size',
12
+ :chart_options => {
13
+ :legend => 'right',
14
+ :title_x => 'Something'
15
+ },
16
+ :chart_element => 'chart'
17
+ )
18
+ end
19
+
20
+ it 'sets the chart element' do
21
+ @chart.in_element = 'foo'
22
+ @chart.chart_element.should == 'foo'
23
+ end
24
+
25
+ describe 'sets colors' do
26
+
27
+ it 'accepting valid values' do
28
+ @chart.colors = ["#ff0000", "#00ff00"]
29
+ @chart.colors.should == ["#ff0000", "#00ff00"]
30
+ end
31
+
32
+ it 'raising an error on invalid values' do
33
+ lambda do
34
+ @chart.colors = 'fred'
35
+ end.should raise_error(ArgumentError)
36
+ lambda do
37
+ @chart.colors = [0,1,2]
38
+ end.should raise_error(ArgumentError)
39
+ end
40
+
41
+ end
42
+
43
+ it 'formats colors' do
44
+ @chart.colors = ["#ff0000"]
45
+ @chart.formatted_colors.should == "['ff0000']"
46
+ end
47
+
48
+ it 'sets its data columns' do
49
+ @chart.data_columns.should =~ /addRows\(5\)/
50
+ @chart.data_columns.should =~ /addColumn\('string', 'Date'\)/
51
+ @chart.data_columns.should =~ /addColumn\('number', '0'\)/
52
+ @chart.data_columns.should =~ /addColumn\('number', '1'\)/
53
+ @chart.data_columns.should =~ /addColumn\('number', '2'\)/
54
+ @chart.data_columns.should =~ /addColumn\('number', '3'\)/
55
+ end
56
+
57
+ it 'sets its options' do
58
+ @chart.options.should =~ /options\['titleX'\] = 'Something'/
59
+ end
60
+
61
+
62
+ end