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 +1 -0
- data/lib/seer.rb +6 -1
- data/lib/seer/geomap.rb +166 -0
- data/spec/geomap_spec.rb +67 -0
- data/spec/spec_helper.rb +1 -1
- metadata +23 -4
data/Rakefile
CHANGED
data/lib/seer.rb
CHANGED
@@ -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
|
data/lib/seer/geomap.rb
ADDED
@@ -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
|
data/spec/geomap_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
-
|
8
|
+
- 9
|
8
9
|
- 0
|
9
|
-
version: 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-
|
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.
|
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
|