Add Google Map of voters
[selectricity-live] / vendor / plugins / ym4r_gm / lib / gm_plugin / overlay.rb
1 module Ym4r\r
2   module GmPlugin\r
3     #A graphical marker positionned through geographic coordinates (in the WGS84 datum). An HTML info window can be set to be displayed when the marker is clicked on.\r
4     class GMarker\r
5       include MappingObject\r
6       attr_accessor :point, :options, :info_window, :info_window_tabs, :address\r
7       #The +points+ argument can be either a GLatLng object or an array of 2 floats. The +options+ keys can be: <tt>:icon</tt>, <tt>:clickable</tt>, <tt>:title</tt>, <tt>:info_window</tt> and <tt>:info_window_tabs</tt>, as well as <tt>:max_width</tt>. The value of the +info_window+ key is a string of HTML code that will be displayed when the markers is clicked on. The value of the +info_window_tabs+ key is an array of GInfoWindowTab objects or a hash directly, in which case it will be transformed to an array of GInfoWindowTabs, with the keys as the tab headers and the values as the content.\r
8       def initialize(position, options = {})\r
9         if position.is_a?(Array)\r
10           @point = GLatLng.new(position)\r
11         elsif position.is_a?(String)\r
12           @point = Variable.new("INVISIBLE") #default coordinates: won't appear anyway\r
13           @address = position\r
14         else\r
15           @point = position\r
16         end\r
17         @info_window = options.delete(:info_window)\r
18         @info_window_tabs = options.delete(:info_window_tabs)\r
19         if options.has_key?(:max_url)\r
20           @info_window_options = {:max_url => options.delete(:max_url) } \r
21         else\r
22           @info_window_options = {}\r
23         end\r
24         @options = options\r
25       end\r
26       #Creates a marker: If an info_window or info_window_tabs is present, the response to the click action from the user is setup here.\r
27       def create\r
28         if @options.empty?\r
29           creation = "new GMarker(#{MappingObject.javascriptify_variable(@point)})"\r
30         else\r
31           creation = "new GMarker(#{MappingObject.javascriptify_variable(@point)},#{MappingObject.javascriptify_variable(@options)})"\r
32         end\r
33         if @info_window && @info_window.is_a?(String)\r
34           creation = "addInfoWindowToMarker(#{creation},#{MappingObject.javascriptify_variable(@info_window)},#{MappingObject.javascriptify_variable(@info_window_options)})"\r
35         elsif @info_window_tabs && @info_window_tabs.is_a?(Hash)\r
36           creation = "addInfoWindowTabsToMarker(#{creation},#{MappingObject.javascriptify_variable(@info_window_tabs.to_a.collect{|kv| GInfoWindowTab.new(kv[0],kv[1] ) })},#{MappingObject.javascriptify_variable(@info_window_options)})"\r
37         elsif @info_window_tabs \r
38           creation = "addInfoWindowTabsToMarker(#{creation},#{MappingObject.javascriptify_variable(Array(@info_window_tabs))},#{MappingObject.javascriptify_variable(@info_window_options)})"\r
39         end\r
40         if @address.nil?\r
41           creation\r
42         else\r
43           "addGeocodingToMarker(#{creation},#{MappingObject.javascriptify_variable(@address)})"\r
44         end\r
45       end\r
46     end\r
47     \r
48     #Represents a tab to be displayed in a bubble when a marker is clicked on.\r
49     class GInfoWindowTab < Struct.new(:tab,:content)\r
50       include MappingObject\r
51       def create\r
52         "new GInfoWindowTab(#{MappingObject.javascriptify_variable(tab)},#{MappingObject.javascriptify_variable(content)})"\r
53       end\r
54     end\r
55         \r
56     #Represents a definition of an icon. You can pass rubyfied versions of the attributes detailed in the Google Maps API documentation. You can initialize global icons to be used in the application by passing a icon object, along with a variable name, to GMap#icon_init. If you want to declare an icon outside this, you will need to declare it first, since the JavaScript constructor does not accept any argument.\r
57     class GIcon\r
58       include MappingObject\r
59       DEFAULT = Variable.new("G_DEFAULT_ICON")\r
60       attr_accessor :options, :copy_base\r
61 \r
62       #Options can contain all the attributes (in rubyfied format) of a GIcon object (see Google's doc), as well as <tt>:copy_base</tt>, which indicates if the icon is copied from another one.\r
63       def initialize(options = {})\r
64         @copy_base = options.delete(:copy_base)\r
65         @options = options\r
66       end\r
67       #Creates a GIcon.\r
68       def create\r
69         if @copy_base\r
70           c = "new GIcon(#{MappingObject.javascriptify_variable(@copy_base)})"\r
71         else\r
72           c = "new GIcon()"\r
73         end\r
74         if !options.empty?\r
75           "addOptionsToIcon(#{c},#{MappingObject.javascriptify_variable(@options)})"\r
76         else\r
77           c\r
78         end\r
79       end\r
80     end\r
81      \r
82     #A polyline.\r
83     class GPolyline\r
84       include MappingObject\r
85       attr_accessor :points,:color,:weight,:opacity\r
86       #Can take an array of +GLatLng+ or an array of 2D arrays. A method to directly build a polyline from a GeoRuby linestring is provided in the helper.rb file.\r
87       def initialize(points,color = nil,weight = nil,opacity = nil)\r
88         if !points.empty? and points[0].is_a?(Array)\r
89           @points = points.collect { |pt| GLatLng.new(pt) }\r
90         else\r
91           @points = points\r
92         end\r
93         @color = color\r
94         @weight = weight\r
95         @opacity = opacity\r
96       end\r
97       #Creates a new polyline.\r
98       def create\r
99         a = "new GPolyline(#{MappingObject.javascriptify_variable(points)}"\r
100         a << ",#{MappingObject.javascriptify_variable(@color)}" if @color\r
101         a << ",#{MappingObject.javascriptify_variable(@weight)}" if @weight\r
102         a << ",#{MappingObject.javascriptify_variable(@opacity)}" if @opacity\r
103         a << ")"\r
104       end\r
105     end\r
106 \r
107     #Encoded GPolyline class\r
108     class GPolylineEncoded \r
109       include MappingObject\r
110       attr_accessor :points,:color,:weight,:opacity,:levels,:zoom_factor,:num_levels\r
111 \r
112       def initialize(options={})\r
113         #points = options[:points]\r
114         #if !points.empty? and points[0].is_a?(Array)\r
115         #  @points = points.collect { |pt| GLatLng.new(pt) }\r
116         #else\r
117         #@points = points\r
118           #end\r
119         @points = options[:points]\r
120         @color = options[:color]\r
121         @weight = options[:weight]\r
122         @opacity = options[:opacity]\r
123         @levels = options[:levels] || "BBBBBBBBBBBB"\r
124         @zoom_factor = options[:zoom_factor] || 32\r
125         @num_levels = options[:num_levels] || 4\r
126       end\r
127       def create\r
128         a = "new GPolyline.fromEncoded({points: #{MappingObject.javascriptify_variable(points)},\n" \r
129         a << "levels: #{MappingObject.javascriptify_variable(@levels)},"\r
130         a << "zoomFactor: #{MappingObject.javascriptify_variable(@zoom_factor)},"\r
131         a << "numLevels: #{MappingObject.javascriptify_variable(@num_levels)}"\r
132         a << ",color: #{MappingObject.javascriptify_variable(@color)}" if @color\r
133         a << ",weight: #{MappingObject.javascriptify_variable(@weight)}" if @weight\r
134         a << ",opacity: #{MappingObject.javascriptify_variable(@opacity)}" if @opacity\r
135         a << "})"\r
136       end\r
137     end\r
138 \r
139     #A basic Latitude/longitude point.\r
140     class GLatLng \r
141       include MappingObject\r
142       attr_accessor :lat,:lng,:unbounded\r
143       \r
144       def initialize(latlng,unbounded = nil)\r
145         @lat = latlng[0]\r
146         @lng = latlng[1]\r
147         @unbounded = unbounded\r
148       end\r
149       def create\r
150         unless @unbounded\r
151           "new GLatLng(#{MappingObject.javascriptify_variable(@lat)},#{MappingObject.javascriptify_variable(@lng)})"\r
152         else\r
153           "new GLatLng(#{MappingObject.javascriptify_variable(@lat)},#{MappingObject.javascriptify_variable(@lng)},#{MappingObject.javascriptify_variable(@unbounded)})"\r
154         end\r
155       end\r
156     end\r
157     \r
158     #A rectangular bounding box, defined by its south-western and north-eastern corners.\r
159     class GLatLngBounds < Struct.new(:sw,:ne)\r
160       include MappingObject\r
161       def create\r
162         "new GLatLngBounds(#{MappingObject.javascriptify_variable(sw)},#{MappingObject.javascriptify_variable(ne)})"\r
163       end\r
164     end\r
165 \r
166     #Polygon. Not documented yet in the Google Maps API\r
167     class GPolygon\r
168       include MappingObject\r
169       \r
170       attr_accessor :points,:stroke_color,:stroke_weight,:stroke_opacity,:color,:opacity\r
171       \r
172       #Can take an array of +GLatLng+ or an array of 2D arrays. A method to directly build a polygon from a GeoRuby polygon is provided in the helper.rb file.\r
173       def initialize(points,stroke_color="#000000",stroke_weight=1,stroke_opacity=1.0,color="#ff0000",opacity=1.0,encoded=false)\r
174         if !points.empty? and points[0].is_a?(Array)\r
175           @points = points.collect { |pt| GLatLng.new(pt) }\r
176         else\r
177           @points = points\r
178         end\r
179         @stroke_color = stroke_color\r
180         @stroke_weight = stroke_weight\r
181         @stroke_opacity = stroke_opacity\r
182         @color = color\r
183         @opacity = opacity\r
184       end\r
185       \r
186       #Creates a new polygon\r
187       def create\r
188         a = "new GPolygon(#{MappingObject.javascriptify_variable(points)}"\r
189         a << ",#{MappingObject.javascriptify_variable(@stroke_color)}"\r
190         a << ",#{MappingObject.javascriptify_variable(@stroke_weight)}"\r
191         a << ",#{MappingObject.javascriptify_variable(@stroke_opacity)}"\r
192         a << ",#{MappingObject.javascriptify_variable(@color)}"\r
193         a << ",#{MappingObject.javascriptify_variable(@opacity)}"\r
194         a << ")"\r
195       end\r
196     end\r
197 \r
198     class GPolygonEncoded \r
199       include MappingObject\r
200       \r
201       attr_accessor :polyline, :color, :opacity, :outline, :fill\r
202       \r
203       def initialize(polylines,fill=true,color="#000000",opacity=0.5,outline=false)\r
204         #force polylines to be an array\r
205         if polylines.is_a? Array\r
206           @polylines = polylines\r
207         else\r
208           @polylines = [polylines]\r
209         end\r
210         @color = color\r
211         @fill = fill \r
212         @opacity = opacity\r
213         @outline = outline\r
214       end\r
215       \r
216       #Creates a new polygon.\r
217       def create\r
218         polylines_for_polygon= []\r
219         @polylines.each do |p|\r
220           x = "{points: #{MappingObject.javascriptify_variable(p.points)}," \r
221           x << "levels: #{MappingObject.javascriptify_variable(p.levels)},"\r
222           x << "zoomFactor: #{MappingObject.javascriptify_variable(p.zoom_factor)},"\r
223           x << "numLevels: #{MappingObject.javascriptify_variable(p.num_levels)} "\r
224           x << "}"\r
225           polylines_for_polygon << x\r
226         end\r
227 \r
228         polylines_for_polygon = "[" + polylines_for_polygon.join(",") + "]"\r
229 \r
230         a = "new GPolygon.fromEncoded({polylines: #{polylines_for_polygon},"\r
231         a << "fill: #{MappingObject.javascriptify_variable(@fill)},"\r
232         a << "color: #{MappingObject.javascriptify_variable(@color)},"\r
233         a << "opacity: #{MappingObject.javascriptify_variable(@opacity)},"\r
234         a << "outline: #{MappingObject.javascriptify_variable(@outline)}"\r
235         a << "})"\r
236       end\r
237     end\r
238 \r
239     class ELabel\r
240       attr_accessor :point, :text, :style\r
241       include MappingObject\r
242 \r
243       def initialize(point, text=nil, style=nil)\r
244         @point = point\r
245         @text = text\r
246         @style = style\r
247       end\r
248 \r
249       def create\r
250           a = "new ELabel(#{MappingObject.javascriptify_variable(@point)}"\r
251           a << ",#{MappingObject.javascriptify_variable(@text)}" if @text\r
252           a << ",#{MappingObject.javascriptify_variable(@style)}" if @style\r
253           a << ")"\r
254       end\r
255     end\r
256 \r
257 \r
258     #A GGeoXml object gets data from a GeoRSS or KML feed and displays it. Use <tt>overlay_init</tt> to add it to a map at initialization time.\r
259     class GGeoXml\r
260       include MappingObject\r
261       \r
262       attr_accessor :url\r
263 \r
264       def initialize(url)\r
265         @url = url\r
266       end\r
267 \r
268       def create\r
269         "new GGeoXml(#{MappingObject.javascriptify_variable(@url)})"\r
270       end\r
271 \r
272     end\r
273     \r
274     #A GOverlay representing a group of GMarkers. The GMarkers can be identified with an id, which can be used to show the info window of a specific marker, in reponse, for example, to a click on a link. The whole group can be shown on and off at once. It should be declared global at initialization time to be useful.\r
275     class GMarkerGroup\r
276       include MappingObject\r
277       attr_accessor :active, :markers, :markers_by_id\r
278 \r
279       def initialize(active = true , markers = nil)\r
280         @active = active\r
281         @markers = []\r
282         @markers_by_id = {}\r
283         if markers.is_a?(Array)\r
284           @markers = markers\r
285         elsif markers.is_a?(Hash)\r
286           @markers_by_id = markers\r
287         end\r
288       end\r
289       \r
290       def create\r
291         "new GMarkerGroup(#{MappingObject.javascriptify_variable(@active)},#{MappingObject.javascriptify_variable(@markers)},#{MappingObject.javascriptify_variable(@markers_by_id)})"\r
292       end\r
293     end\r
294 \r
295     #Can be used to implement a clusterer, similar to the clusterer below, except that there is more stuff to manage explicitly byt the programmer (but this is also more flexible). See the README for usage esamples.\r
296     class GMarkerManager\r
297       include MappingObject\r
298       \r
299       attr_accessor :map,:options,:managed_markers\r
300             \r
301       #options can be <tt>:border_padding</tt>, <tt>:max_zoom</tt>, <tt>:track_markers</tt> and <tt>:managed_markers</tt>: managed_markers must be an array of ManagedMarker objects\r
302       def initialize(map, options = {})\r
303         @map = map\r
304         @managed_markers = Array(options.delete(:managed_markers)) #[] if nil\r
305         @options = options\r
306       end\r
307 \r
308       def create\r
309         puts @options.inspect\r
310         "addMarkersToManager(new GMarkerManager(#{MappingObject.javascriptify_variable(@map)},#{MappingObject.javascriptify_variable(@options)}),#{MappingObject.javascriptify_variable(@managed_markers)})"\r
311       end\r
312 \r
313     end\r
314 \r
315     #A set of similarly managed markers: They share the same minZoom and maxZoom.\r
316     class ManagedMarker\r
317       include MappingObject\r
318       \r
319       attr_accessor :markers,:min_zoom, :max_zoom\r
320       \r
321       def initialize(markers,min_zoom,max_zoom = nil)\r
322         @markers = markers\r
323         @min_zoom = min_zoom\r
324         @max_zoom = max_zoom\r
325       end\r
326 \r
327       def create\r
328         "new ManagedMarker(#{MappingObject.javascriptify_variable(@markers)},#{MappingObject.javascriptify_variable(@min_zoom)},#{MappingObject.javascriptify_variable(@max_zoom)})"\r
329       end\r
330       \r
331     end\r
332 \r
333     #Makes the link with the Clusterer2 library by Jef Poskanzer (slightly modified though). Is a GOverlay making clusters out of its GMarkers, so that GMarkers very close to each other appear as one when the zoom is low. When the zoom gets higher, the individual markers are drawn.\r
334     class Clusterer\r
335       include MappingObject\r
336       attr_accessor :markers,:icon, :max_visible_markers, :grid_size, :min_markers_per_cluster , :max_lines_per_info_box\r
337 \r
338       def initialize(markers = [], options = {})\r
339         @markers = markers\r
340         @icon = options[:icon] || GIcon::DEFAULT\r
341         @max_visible_markers = options[:max_visible_markers] || 150\r
342         @grid_size = options[:grid_size] || 5\r
343         @min_markers_per_cluster = options[:min_markers_per_cluster] || 5\r
344         @max_lines_per_info_box = options[:max_lines_per_info_box] || 10\r
345       end\r
346 \r
347       def create \r
348         js_marker = '[' + @markers.collect do |marker|\r
349           add_description(marker)\r
350         end.join(",") + ']'\r
351 \r
352         "new Clusterer(#{js_marker},#{MappingObject.javascriptify_variable(@icon)},#{MappingObject.javascriptify_variable(@max_visible_markers)},#{MappingObject.javascriptify_variable(@grid_size)},#{MappingObject.javascriptify_variable(@min_markers_per_cluster)},#{MappingObject.javascriptify_variable(@max_lines_per_info_box)})"\r
353       end\r
354             \r
355       private\r
356       def add_description(marker)\r
357         "addDescriptionToMarker(#{MappingObject.javascriptify_variable(marker)},#{MappingObject.javascriptify_variable(marker.options[:description] || marker.options[:title] || '')})"\r
358       end\r
359     end\r
360     \r
361     #Makes the link with the MGeoRSS extension by Mikel Maron (a bit modified though). It lets you overlay on top of Google Maps the items present in a RSS feed that has GeoRss data. This data can be either in W3C Geo vocabulary or in the GeoRss Simple format. See http://georss.org to know more about GeoRss.\r
362     class GeoRssOverlay\r
363       include MappingObject\r
364       attr_accessor :url, :proxy, :icon, :options\r
365       \r
366       #You can pass the following options:\r
367       #- <tt>:icon</tt>: An icon for the items of the feed. Defaults to the classic red balloon icon.\r
368       #- <tt>:proxy</tt>: An URL on your server where fetching the RSS feed will be taken care of.\r
369       #- <tt>:list_div</tt>: In case you want a list of all the markers, with a link on which you can click in order to display the info on the marker, use this option to indicate the ID of the div (that you must place yourself).\r
370       #- <tt>:list_item_class</tt>: class of the DIV containing each item of the list. Ignored if option <tt>:list_div</tt> is not set.\r
371       #- <tt>:limit</tt>: Maximum number of items to display on the map.\r
372       #- <tt>:content_div</tt>: Instead of having an info window appear, indicates the ID of the DIV where this info should be displayed.\r
373       def initialize(url, options = {})\r
374         @url = url\r
375         @icon = options.delete(:icon) || GIcon::DEFAULT\r
376         @proxy = options.delete(:proxy) || Variable::UNDEFINED\r
377         @options = options \r
378       end\r
379 \r
380       def create \r
381         "new GeoRssOverlay(#{MappingObject.javascriptify_variable(@url)},#{MappingObject.javascriptify_variable(@icon)},#{MappingObject.javascriptify_variable(@proxy)},#{MappingObject.javascriptify_variable(@options)})"\r
382       end\r
383     end\r
384 \r
385   end\r
386 end\r

Benjamin Mako Hill || Want to submit a patch?