seer 0.7.0 → 0.9.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.
data/Rakefile CHANGED
@@ -20,6 +20,7 @@ begin
20
20
  "lib/seer/chart.rb",
21
21
  "lib/seer/column_chart.rb",
22
22
  "lib/seer/gauge.rb",
23
+ "lib/seer/geomap.rb",
23
24
  "lib/seer/line_chart.rb",
24
25
  "lib/seer/pie_chart.rb",
25
26
  "lib/seer/visualization_helper.rb",
@@ -5,10 +5,11 @@ module Seer
5
5
  require 'seer/bar_chart'
6
6
  require 'seer/column_chart'
7
7
  require 'seer/gauge'
8
+ require 'seer/geomap'
8
9
  require 'seer/line_chart'
9
10
  require 'seer/pie_chart'
10
11
 
11
- VISUALIZERS = [:area_chart, :bar_chart, :column_chart, :gauge, :line_chart, :pie_chart]
12
+ VISUALIZERS = [:area_chart, :bar_chart, :column_chart, :gauge, :geomap, :line_chart, :pie_chart]
12
13
 
13
14
  def self.valid_hex_number?(val) #:nodoc:
14
15
  return false unless val.is_a?(String) && ! val.empty?
@@ -52,6 +53,10 @@ module Seer
52
53
  Gauge.render(data, args)
53
54
  end
54
55
 
56
+ def self.geomap(data, args)
57
+ Geomap.render(data, args)
58
+ end
59
+
55
60
  def self.line_chart(data, args)
56
61
  LineChart.render(data, args)
57
62
  end
@@ -0,0 +1,166 @@
1
+ module Seer
2
+
3
+ # Geomap creates a map of a country, continent, or region, with colors and values assigned to
4
+ # specific regions. Values are displayed as a color scale, and you can specify optional hovertext
5
+ # for regions.
6
+ #
7
+ # =USAGE=
8
+ #
9
+ # In your view:
10
+ #
11
+ # <div id="my_geomap_container" class="chart"></div>
12
+ #
13
+ # <%= Seer::visualize(
14
+ # @widgets,
15
+ # :as => :geomap,
16
+ # :in_element => 'my_geomap_container',
17
+ # :series => {
18
+ # :series_label => 'name',
19
+ # :data_label => '# widgets',
20
+ # :data_method => 'quantity'
21
+ # },
22
+ # :chart_options => {
23
+ # :data_mode => 'regions',
24
+ # :region => 'US',
25
+ # }
26
+ # )
27
+ # -%>
28
+ #
29
+ # ==@widgets==
30
+ #
31
+ # A collection of objects (ActiveRecord or otherwise) that must respond to the
32
+ # following methods:
33
+ #
34
+ # latitude # => returns the latitude in decimal format
35
+ # longitude # => returns the longitude in decimal format
36
+ # geocoded? # => result of latitude && longitude
37
+ #
38
+ # For details on the chart options, see the Google API docs at
39
+ # http://code.google.com/apis/visualization/documentation/gallery/geomap.html
40
+ #
41
+ class Geomap
42
+
43
+ include Seer::Chart
44
+
45
+ COUNTRY_CODES = ['world', 'AX', 'AF', 'AL', 'DZ', 'AS', 'AD', 'AO', 'AI', 'AQ', 'AG', 'AR', 'AM', 'AW', 'AU', 'AT', 'AZ', 'BS', 'BH', 'BD', 'BB', 'BY', 'BE', 'BZ', 'BJ', 'BM', 'BT', 'BO', 'BA', 'BW', 'BV', 'BR', 'IO', 'BN', 'BG', 'BF', 'BI', 'KH', 'CM', 'CA', 'CV', 'KY', 'CF', 'TD', 'CL', 'CN', 'CX', 'CC', 'CO', 'KM', 'CD', 'CG', 'CK', 'CR', 'CI', 'HR', 'CU', 'CY', 'CZ', 'DK', 'DJ', 'DM', 'DO', 'EC', 'EG', 'SV', 'GQ', 'ER', 'EE', 'ET', 'FK', 'FO', 'FJ', 'FI', 'FR', 'GF', 'PF', 'TF', 'GA', 'GM', 'GE', 'DE', 'GH', 'GI', 'GR', 'GL', 'GD', 'GP', 'GU', 'GT', 'GN', 'GW', 'GY', 'HT', 'HM', 'HN', 'HK', 'HU', 'IS', 'IN', 'ID', 'IR', 'IQ', 'IE', 'IL', 'IT', 'JM', 'JP', 'JO', 'KZ', 'KE', 'KI', 'KP', 'KR', 'KW', 'KG', 'LA', 'LV', 'LB', 'LS', 'LR', 'LY', 'LI', 'LT', 'LU', 'MO', 'MK', 'MG', 'MW', 'MY', 'MV', 'ML', 'MT', 'MH', 'MQ', 'MR', 'MU', 'YT', 'MX', 'FM', 'MD', 'MC', 'MN', 'MS', 'MA', 'MZ', 'MM', 'NA', 'NR', 'NP', 'NL', 'AN', 'NC', 'NZ', 'NI', 'NE', 'NG', 'NU', 'NF', 'MP', 'NO', 'OM', 'PK', 'PW', 'PS', 'PA', 'PG', 'PY', 'PE', 'PH', 'PN', 'PL', 'PT', 'PR', 'QA', 'RE', 'RO', 'RU', 'RW', 'SH', 'KN', 'LC', 'PM', 'VC', 'WS', 'SM', 'ST', 'SA', 'SN', 'CS', 'SC', 'SL', 'SG', 'SK', 'SI', 'SB', 'SO', 'ZA', 'GS', 'ES', 'LK', 'SD', 'SR', 'SJ', 'SZ', 'SE', 'CH', 'SY', 'TW', 'TJ', 'TZ', 'TH', 'TL', 'TG', 'TK', 'TO', 'TT', 'TN', 'TR', 'TM', 'TC', 'TV', 'UG', 'UA', 'AE', 'GB', 'US', 'UM', 'UY', 'UZ', 'VU', 'VA', 'VE', 'VN', 'VG', 'VI', 'WF', 'EH', 'YE', 'ZM', 'ZW', '005', '013', '021', '002', '017', '015', '018', '030', '034', '035', '143', '145', '151', '154', '155', '039']
46
+
47
+ # Chart options accessors
48
+ attr_accessor :data_mode, :enable_tooltip, :height, :legend_background_color, :legend_font_size, :legend_text_color, :legend, :region, :show_legend, :show_zoom_out, :title_color, :title_font_size, :title_x, :title_y, :title, :tooltip_font_size, :tooltip_height, :tooltip_width, :width, :zoom_out_label
49
+
50
+ # Graph data
51
+ attr_accessor :data, :data_label, :data_method, :data_table, :label_method
52
+
53
+ def initialize(args={}) #:nodoc:
54
+
55
+ # Standard options
56
+ args.each{ |method,arg| self.send("#{method}=",arg) if self.respond_to?(method) }
57
+
58
+ # Chart options
59
+ args[:chart_options].each{ |method, arg| self.send("#{method}=",arg) if self.respond_to?(method) }
60
+
61
+ # Handle defaults
62
+ @colors ||= args[:chart_options][:colors] || DEFAULT_COLORS
63
+ @legend ||= args[:chart_options][:legend] || DEFAULT_LEGEND_LOCATION
64
+ @height ||= args[:chart_options][:height] || DEFAULT_HEIGHT
65
+ @width ||= args[:chart_options][:width] || DEFAULT_WIDTH
66
+
67
+ end
68
+
69
+ def data_columns #:nodoc:
70
+ _data_columns = "data.addRows(#{data_table.size});"
71
+ if self.data_mode == 'markers'
72
+ _data_columns << %{
73
+ data.addColumn('number', 'LATITUDE');
74
+ data.addColumn('number', 'LONGITUDE');
75
+ data.addColumn('number', '#{data_method}');
76
+ data.addColumn('string', '#{label_method}');
77
+ }
78
+ else
79
+ _data_columns << " data.addColumn('string', '#{label_method}');"
80
+ _data_columns << " data.addColumn('number', '#{data_method}');"
81
+ _data_columns
82
+ end
83
+ _data_columns
84
+ end
85
+
86
+ def data_mode=(mode) #:nodoc:
87
+ raise ArgumentError, "Invalid data mode option: #{mode}. Must be one of 'regions' or 'markers'." unless ['regions', 'markers'].include?(mode)
88
+ @data_mode = mode
89
+ end
90
+
91
+ def data_table #:nodoc:
92
+ @data_table = []
93
+ data.each_with_index do |datum, column|
94
+ next unless datum.geocoded?
95
+ if data_mode == "markers"
96
+ @data_table << [
97
+ " data.setValue(#{column}, 0, #{datum.latitude});\r",
98
+ " data.setValue(#{column}, 1, #{datum.longitude});\r",
99
+ " data.setValue(#{column}, 2, #{datum.send(data_method)});\r",
100
+ " data.setValue(#{column}, 3, '#{datum.send(label_method)}');\r"
101
+ ]
102
+ else # Regions
103
+ @data_table << [
104
+ " data.setValue(#{column}, 0, '#{datum.name}');\r",
105
+ " data.setValue(#{column}, 1, #{datum.send(data_method)});\r"
106
+ ]
107
+ end
108
+ end
109
+ @data_table
110
+ end
111
+
112
+ # Because Google is not consistent in their @#!$ API...
113
+ def formatted_colors
114
+ "[#{@colors.map{|color| "'#{color.gsub(/\#/,'0x')}'"} * ','}]"
115
+ end
116
+
117
+ def nonstring_options #:nodoc:
118
+ [:colors, :enable_tooltip, :height, :legend_font_size, :title_font_size, :tooltip_font_size, :tooltip_width, :width]
119
+ end
120
+
121
+ def string_options #:nodoc:
122
+ [:data_mode, :legend, :legend_background_color, :legend_text_color, :title, :title_x, :title_y, :title_color, :region]
123
+ end
124
+
125
+ def to_js
126
+ %{
127
+ <script type="text/javascript">
128
+ google.load('visualization', '1', {'packages':['geomap']});
129
+ google.setOnLoadCallback(drawChart);
130
+ function drawChart() {
131
+ var data = new google.visualization.DataTable();
132
+ #{data_columns}
133
+ #{data_table.to_s}
134
+ var options = {};
135
+ #{options}
136
+ var container = document.getElementById('#{self.chart_element}');
137
+ var geomap = new google.visualization.GeoMap(container);
138
+ geomap.draw(data, options);
139
+ }
140
+ </script>
141
+ }
142
+ end
143
+
144
+ def region=(desired_region)
145
+ raise ArgumentError, "Invalid region: #{desired_region}" unless COUNTRY_CODES.include?(desired_region)
146
+ @region = desired_region
147
+ end
148
+
149
+ # ====================================== Class Methods =========================================
150
+
151
+ def self.render(data, args)
152
+ map = Seer::Geomap.new(
153
+ :region => args[:chart_options][:region],
154
+ :data_mode => args[:chart_options][:data_mode],
155
+ :data => data,
156
+ :label_method => args[:series][:series_label],
157
+ :data_method => args[:series][:data_method],
158
+ :chart_options => args[:chart_options],
159
+ :chart_element => args[:in_element] || 'chart'
160
+ )
161
+ map.to_js
162
+ end
163
+
164
+ end
165
+
166
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Seer::Geomap" do
4
+
5
+ before :each do
6
+
7
+ class GeoThing
8
+ def initialize; end
9
+ def name; 'foo'; end
10
+ def latitude; -90; end
11
+ def longitude; -90; end
12
+ def count; 8; end
13
+ def geocoded?; true; end
14
+ end
15
+
16
+ @chart = Seer::Geomap.new(
17
+ :data => [GeoThing.new, GeoThing.new, GeoThing.new],
18
+ :label_method => 'name',
19
+ :data_method => 'count',
20
+ :chart_options => {},
21
+ :chart_element => 'geochart'
22
+ )
23
+ end
24
+
25
+ describe 'defaults' do
26
+
27
+ it 'height' do
28
+ @chart.height.should == Seer::Chart::DEFAULT_HEIGHT
29
+ end
30
+
31
+ it 'width' do
32
+ @chart.width.should == Seer::Chart::DEFAULT_WIDTH
33
+ end
34
+
35
+ end
36
+
37
+ describe 'graph options' do
38
+
39
+ [:show_zoom_out, :zoom_out_label].each do |accessor|
40
+ it "sets its #{accessor} value" do
41
+ @chart.send("#{accessor}=", 'foo')
42
+ @chart.send(accessor).should == 'foo'
43
+ end
44
+ end
45
+
46
+ it_should_behave_like 'it has colors attribute'
47
+ end
48
+
49
+ it 'renders as JavaScript' do
50
+ (@chart.to_js =~ /javascript/).should be_true
51
+ (@chart.to_js =~ /geomap/).should be_true
52
+ end
53
+
54
+ it 'sets its data columns' do
55
+ @chart.data_columns.should =~ /addRows\(3\)/
56
+ end
57
+
58
+ it 'sets its data table' do
59
+ @chart.data_table.to_s.should set_value(0, 0,'foo')
60
+ @chart.data_table.to_s.should set_value(0, 1, 8)
61
+ @chart.data_table.to_s.should set_value(1, 0,'foo')
62
+ @chart.data_table.to_s.should set_value(1, 1, 8)
63
+ @chart.data_table.to_s.should set_value(2, 0,'foo')
64
+ @chart.data_table.to_s.should set_value(2, 1, 8)
65
+ end
66
+
67
+ end
@@ -1,8 +1,8 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'rubygems'
4
- require 'active_support'
5
4
  require 'action_pack'
5
+ require 'active_support'
6
6
  require 'spec'
7
7
  require 'spec/autorun'
8
8
  require 'seer'
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seer
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 59
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 7
8
+ - 9
8
9
  - 0
9
- version: 0.7.0
10
+ version: 0.9.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Corey Ehmke / SEO Logic
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-11 00:00:00 -05:00
18
+ date: 2010-09-08 00:00:00 -05:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rspec
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 13
27
30
  segments:
28
31
  - 1
29
32
  - 2
@@ -52,11 +55,22 @@ files:
52
55
  - lib/seer/chart.rb
53
56
  - lib/seer/column_chart.rb
54
57
  - lib/seer/gauge.rb
58
+ - lib/seer/geomap.rb
55
59
  - lib/seer/line_chart.rb
56
60
  - lib/seer/pie_chart.rb
57
61
  - spec/seer_spec.rb
58
62
  - spec/spec.opts
59
63
  - spec/spec_helper.rb
64
+ - spec/area_chart_spec.rb
65
+ - spec/bar_chart_spec.rb
66
+ - spec/chart_spec.rb
67
+ - spec/column_chart_spec.rb
68
+ - spec/custom_matchers.rb
69
+ - spec/gauge_spec.rb
70
+ - spec/geomap_spec.rb
71
+ - spec/helpers.rb
72
+ - spec/line_chart_spec.rb
73
+ - spec/pie_chart_spec.rb
60
74
  has_rdoc: true
61
75
  homepage: http://github.com/Bantik/seer
62
76
  licenses: []
@@ -67,23 +81,27 @@ rdoc_options:
67
81
  require_paths:
68
82
  - lib
69
83
  required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
70
85
  requirements:
71
86
  - - ">="
72
87
  - !ruby/object:Gem::Version
88
+ hash: 3
73
89
  segments:
74
90
  - 0
75
91
  version: "0"
76
92
  required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
77
94
  requirements:
78
95
  - - ">="
79
96
  - !ruby/object:Gem::Version
97
+ hash: 3
80
98
  segments:
81
99
  - 0
82
100
  version: "0"
83
101
  requirements: []
84
102
 
85
103
  rubyforge_project:
86
- rubygems_version: 1.3.6
104
+ rubygems_version: 1.3.7
87
105
  signing_key:
88
106
  specification_version: 3
89
107
  summary: Seer is a lightweight, semantically rich wrapper for the Google Visualization API.
@@ -94,6 +112,7 @@ test_files:
94
112
  - spec/column_chart_spec.rb
95
113
  - spec/custom_matchers.rb
96
114
  - spec/gauge_spec.rb
115
+ - spec/geomap_spec.rb
97
116
  - spec/helpers.rb
98
117
  - spec/line_chart_spec.rb
99
118
  - spec/pie_chart_spec.rb