ym4r_gm 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,118 @@
1
+ require 'open-uri'
2
+ require 'rexml/document'
3
+
4
+ module Ym4r
5
+ module GmPlugin
6
+ module Geocoding
7
+
8
+ GEO_SUCCESS = 200
9
+ GEO_MISSING_ADDRESS = 601
10
+ GEO_UNKNOWN_ADDRESS = 602
11
+ GEO_UNAVAILABLE_ADDRESS = 603
12
+ GEO_BAD_KEY = 610
13
+ GEO_TOO_MANY_QUERIES = 620
14
+ GEO_SERVER_ERROR = 500
15
+
16
+ #Gets placemarks by querying the Google Maps Geocoding service with the +request+ string. Options can either an explicity GMaps API key (<tt>:key</tt>) or a host, (<tt>:host</tt>).
17
+ def self.get(request,options = {})
18
+ api_key = ApiKey.get(options)
19
+ sensor = options[:sensor] || false
20
+ output = options[:output] || "kml"
21
+ output_encoding = options[:output_encoding] || "utf-8"
22
+ url = "http://maps.google.com/maps/geo?q=#{URI.encode(request)}&key=#{api_key}&sensor=#{sensor}&output=#{output}&oe=#{output_encoding}"
23
+
24
+ res = open(url).read
25
+
26
+ case output.to_sym
27
+ when :json
28
+ res = eval(res.gsub(":","=>")) #!!!EVAL EVAL EVAL EVAL!!! hopefully we can trust google...
29
+ placemarks = Placemarks.new(res['name'],res['Status']['code'])
30
+ if res['Placemark']
31
+ placemark = res['Placemark']
32
+
33
+ placemark.each do |data|
34
+
35
+ data_country = data['Country']['CountryNameCode'] rescue ""
36
+ data_administrative = data['Country']['AdministrativeArea']['AdministrativeAreaName'] rescue ""
37
+ data_sub_administrative = data['Country']['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName'] rescue ""
38
+ data_locality = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['LocalityName'] rescue ""
39
+ data_dependent_locality = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['DependentLocalityName'] rescue ""
40
+ data_thoroughfare = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['Thoroughfare']['ThoroughfareName'] rescue ""
41
+ data_postal_code = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['Thoroughfare']['PostalCode']['PostalCodeNumber'] rescue ""
42
+ lon, lat = data['Point']['coordinates'][0,2]
43
+ data_accuracy = data['Accuracy']
44
+ unless data_accuracy.nil?
45
+ data_accuracy = data_accuracy.to_i
46
+ end
47
+
48
+ placemarks << Geocoding::Placemark.new(data['address'],
49
+ data_country,
50
+ data_administrative,
51
+ data_sub_administrative,
52
+ data_locality,
53
+ data_dependent_locality,
54
+ data_thoroughfare,
55
+ data_postal_code,
56
+ lon, lat, data_accuracy)
57
+
58
+ end
59
+ end
60
+ when :kml, :xml
61
+
62
+ doc = REXML::Document.new(res)
63
+
64
+ response = doc.elements['//Response']
65
+ placemarks = Placemarks.new(response.elements['name'].text,response.elements['Status/code'].text.to_i)
66
+ response.elements.each(".//Placemark") do |placemark|
67
+ data = placemark.elements
68
+ data_country = data['.//CountryNameCode']
69
+ data_administrative = data['.//AdministrativeAreaName']
70
+ data_sub_administrative = data['.//SubAdministrativeAreaName']
71
+ data_locality = data['.//LocalityName']
72
+ data_dependent_locality = data['.//DependentLocalityName']
73
+ data_thoroughfare = data['.//ThoroughfareName']
74
+ data_postal_code = data['.//PostalCodeNumber']
75
+ lon, lat = data['.//coordinates'].text.split(",")[0..1].collect {|l| l.to_f }
76
+ data_accuracy = data['.//*[local-name()="AddressDetails"]'].attributes['Accuracy']
77
+ unless data_accuracy.nil?
78
+ data_accuracy = data_accuracy.to_i
79
+ end
80
+ placemarks << Geocoding::Placemark.new(data['address'].text,
81
+ data_country.nil? ? "" : data_country.text,
82
+ data_administrative.nil? ? "" : data_administrative.text,
83
+ data_sub_administrative.nil? ? "" : data_sub_administrative.text,
84
+ data_locality.nil? ? "" : data_locality.text,
85
+ data_dependent_locality.nil? ? "" : data_dependent_locality.text,
86
+ data_thoroughfare.nil? ? "" : data_thoroughfare.text,
87
+ data_postal_code.nil? ? "" : data_postal_code.text,
88
+ lon, lat, data_accuracy )
89
+ end
90
+ end
91
+
92
+ placemarks
93
+ end
94
+
95
+ #Group of placemarks returned by the Geocoding service. If the result is valid the +status+ attribute should be equal to <tt>Geocoding::GE0_SUCCESS</tt>
96
+ class Placemarks < Array
97
+ attr_accessor :name,:status
98
+
99
+ def initialize(name,status)
100
+ super(0)
101
+ @name = name
102
+ @status = status
103
+ end
104
+ end
105
+
106
+ #A result from the Geocoding service.
107
+ class Placemark < Struct.new(:address,:country_code,:administrative_area,:sub_administrative_area,:locality,:dependent_locality,:thoroughfare,:postal_code,:longitude,:latitude,:accuracy)
108
+ def lonlat
109
+ [longitude,latitude]
110
+ end
111
+
112
+ def latlon
113
+ [latitude,longitude]
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,72 @@
1
+
2
+ Ym4r::GmPlugin::GPolyline.class_eval do
3
+ #Creates a GPolyline object from a georuby line string. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
4
+ def self.from_georuby(line_string,color = nil,weight = nil,opacity = nil)
5
+ GPolyline.new(line_string.points.collect { |point| GLatLng.new([point.y,point.x])},color,weight,opacity)
6
+ end
7
+ end
8
+
9
+ Ym4r::GmPlugin::GMarker.class_eval do
10
+ #Creates a GMarker object from a georuby point. Accepts the same options as the GMarker constructor. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
11
+ def self.from_georuby(point,options = {})
12
+ GMarker.new([point.y,point.x],options)
13
+ end
14
+ end
15
+
16
+ Ym4r::GmPlugin::GLatLng.class_eval do
17
+ #Creates a GLatLng object from a georuby point. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
18
+ def self.from_georuby(point,unbounded = nil)
19
+ GLatLng.new([point.y,point.x],unbounded)
20
+ end
21
+ end
22
+
23
+ Ym4r::GmPlugin::GLatLngBounds.class_eval do
24
+ #Creates a GLatLng object from a georuby point. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
25
+ def self.from_georuby(envelope)
26
+ GLatLngBounds.new(GLatLng.from_georuby(envelope.lower_corner),
27
+ GLatLng.from_georuby(envelope.upper_corner))
28
+ end
29
+ end
30
+
31
+ Ym4r::GmPlugin::GPolygon.class_eval do
32
+ #Creates a GPolygon object from a georuby polygon or line string. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
33
+ def self.from_georuby(ls_or_p, stroke_color="#000000",stroke_weight=1,stroke_opacity=1.0,color="#ff0000",opacity=1.0)
34
+ if ls_or_p.is_a?(GeoRuby::SimpleFeatures::LineString)
35
+ GPolygon.new(ls_or_p.collect { |point| GLatLng.new([point.y,point.x])},stroke_color,stroke_weight,stroke_opacity,color,opacity)
36
+ else
37
+ GPolygon.new(ls_or_p[0].collect { |point| GLatLng.new([point.y,point.x])},stroke_color,stroke_weight,stroke_opacity,color,opacity)
38
+ end
39
+ end
40
+ end
41
+
42
+ Ym4r::GmPlugin::GPolylineEncoded.class_eval do
43
+ def self.from_georuby(line_string, color = nil, weight = nil, opacity = nil)
44
+ encoded_points = GMapPolylineEncoder.new.encode(
45
+ line_string.points.collect {|p| [p.y, p.x]})
46
+ GPolylineEncoded.new(
47
+ :points => encoded_points[:points],
48
+ :levels => encoded_points[:levels],
49
+ :num_levels => encoded_points[:numLevels],
50
+ :zoom_factor => encoded_points[:zoomFactor],
51
+ :color => color,
52
+ :weight => weight,
53
+ :opacity => opacity
54
+ )
55
+ end
56
+ end
57
+
58
+ Ym4r::GmPlugin::GPolygonEncoded.class_eval do
59
+ def self.from_georuby(ls_or_p, stroke_color="#000000",stroke_weight=1,stroke_opacity=1.0,color="#ff0000",opacity=1.0)
60
+ if ls_or_p.is_a?(GeoRuby::SimpleFeatures::LineString)
61
+ GPolygonEncoded.new(
62
+ GPolylineEncoded.from_georuby(ls_or_p, stroke_color, stroke_weight, stroke_opacity),
63
+ color.nil?, color, opacity, stroke_weight > 0)
64
+ else
65
+ polylines = ls_or_p.rings.collect do |line_string|
66
+ GPolylineEncoded.from_georuby(line_string, stroke_color,
67
+ stroke_weight, stroke_opacity)
68
+ end
69
+ GPolygonEncoded.new(polylines, true, color, opacity, true)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,37 @@
1
+ module Ym4r
2
+ module GmPlugin
3
+ class GMapsAPIKeyConfigFileNotFoundException < StandardError
4
+ end
5
+
6
+ class AmbiguousGMapsAPIKeyException < StandardError
7
+ end
8
+
9
+ #Class fo the manipulation of the API key
10
+ class ApiKey
11
+ #Read the API key config for the current ENV
12
+ unless File.exist?(Rails.root.join("config","gmaps_api_key.yml"))
13
+ raise GMapsAPIKeyConfigFileNotFoundException.new("File config/gmaps_api_key.yml not found")
14
+ else
15
+ env = ENV['RAILS_ENV'] || Rails.env
16
+ GMAPS_API_KEY = YAML.load_file(Rails.root.join("config","gmaps_api_key.yml"))[env]
17
+ end
18
+
19
+ def self.get(options = {})
20
+ if options.has_key?(:key)
21
+ options[:key]
22
+ elsif GMAPS_API_KEY.is_a?(Hash)
23
+ #For this environment, multiple hosts are possible.
24
+ #:host must have been passed as option
25
+ if options.has_key?(:host)
26
+ GMAPS_API_KEY[options[:host]]
27
+ else
28
+ raise AmbiguousGMapsAPIKeyException.new(GMAPS_API_KEY.keys.join(","))
29
+ end
30
+ else
31
+ #Only one possible key: take it and ignore the :host option if it is there
32
+ GMAPS_API_KEY
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,126 @@
1
+ module Ym4r
2
+ module GmPlugin
3
+ #Map types of the map
4
+ class GMapType
5
+ include MappingObject
6
+
7
+ G_NORMAL_MAP = Variable.new("G_NORMAL_MAP")
8
+ G_SATELLITE_MAP = Variable.new("G_SATELLITE_MAP")
9
+ G_HYBRID_MAP = Variable.new("G_HYBRID_MAP")
10
+ G_PHYSICAL_MAP = Variable.new("G_PHYSICAL_MAP")
11
+
12
+ attr_accessor :layers, :name, :projection, :options
13
+
14
+ #The options can be any of the GMapType options detailed in the documentation + a <tt>:projection</tt>.
15
+ def initialize(layers, name, options = {})
16
+ @layers = layers
17
+ @name = name
18
+ @projection = options.delete(:projection) || GMercatorProjection.new
19
+ @options = options
20
+ end
21
+
22
+ def create
23
+ "new GMapType(#{MappingObject.javascriptify_variable(Array(layers))}, #{MappingObject.javascriptify_variable(projection)}, #{MappingObject.javascriptify_variable(name)}, #{MappingObject.javascriptify_variable(options)})"
24
+ end
25
+ end
26
+
27
+ #Represents a mercator projection for zoom levels 0 to 17 (more than that by passing an argument to the constructor)
28
+ class GMercatorProjection
29
+ include MappingObject
30
+
31
+ attr_accessor :n
32
+
33
+ def initialize(n = nil)
34
+ @n = n
35
+ end
36
+
37
+ def create
38
+ if n.nil?
39
+ return "G_NORMAL_MAP.getProjection()"
40
+ else
41
+ "new GMercatorProjection(#{@n})"
42
+ end
43
+ end
44
+ end
45
+
46
+ #Abstract Tile layer. Subclasses must implement a get_tile_url method.
47
+ class GTileLayer
48
+ include MappingObject
49
+
50
+ attr_accessor :opacity, :zoom_range, :copyright, :format
51
+
52
+ #Options are the following, with default values:
53
+ #:zoom_range (0..17), :copyright ({'prefix' => '', 'copyright_texts' => [""]}), :opacity (1.0), :format ("png")
54
+ def initialize(options = {})
55
+ @opacity = options[:opacity] || 1.0
56
+ @zoom_range = options[:zoom_range] || (0..17)
57
+ @copyright = options[:copyright] || {'prefix' => '', 'copyright_texts' => [""]}
58
+ @format = (options[:format] || "png").to_s
59
+ end
60
+
61
+ def create
62
+ "addPropertiesToLayer(new GTileLayer(new GCopyrightCollection(\"\"),#{zoom_range.begin},#{zoom_range.end}),#{get_tile_url},function(a,b) {return #{MappingObject.javascriptify_variable(@copyright)};}\n,function() {return #{@opacity};},function(){return #{@format == "png"};})"
63
+ end
64
+
65
+ #for subclasses to implement
66
+ def get_tile_url
67
+ end
68
+ end
69
+
70
+ #Represents a pre tiled layer, taking images directly from a server, without using a server script.
71
+ class PreTiledLayer < GTileLayer
72
+ attr_accessor :base_url
73
+
74
+ #Possible options are the same as for the GTileLayer constructor
75
+ def initialize(base_url,options = {})
76
+ super(options)
77
+ @base_url = base_url
78
+ end
79
+
80
+ #Returns the code to determine the url to fetch the tile. Follows the convention adopted by the tiler: {base_url}/tile_{b}_{a.x}_{a.y}.{format}
81
+ def get_tile_url
82
+ "function(a,b) { return '#{@base_url}/tile_' + b + '_' + a.x + '_' + a.y + '.#{format}';}"
83
+ end
84
+ end
85
+
86
+ #Represents a pretiled layer (it actually does not really matter where the tiles come from). Calls an action on the server to get back the tiles. It passes the action arguments x, y (coordinates of the tile) and z (zoom level). It can be used, for example, to return default tiles when the requested tile is not present.
87
+ class PreTiledLayerFromAction < PreTiledLayer
88
+ def get_tile_url
89
+ "function(a,b) { return '#{base_url}?x=' + a.x + '&y=' + a.y + '&z=' + b ;}"
90
+ end
91
+ end
92
+
93
+ #Represents a TileLayer where the tiles are generated dynamically from a WMS server (MapServer, GeoServer,...)
94
+ #You need to include the JavaScript file wms-gs.js for this to work
95
+ #see http://docs.codehaus.org/display/GEOSDOC/Google+Maps
96
+ class WMSLayer < GTileLayer
97
+ attr_accessor :base_url, :layers, :styles, :merc_proj, :use_geographic
98
+
99
+ #Options are the same as with GTileLayer + :styles (""), :merc_proj (:mapserver), :use_geographic (false)
100
+ def initialize(base_url, layers, options = {})
101
+ super(options)
102
+ @base_url = base_url.gsub(/\?$/,"") #standardize the url
103
+ @layers = layers
104
+ @styles = options[:styles] || ""
105
+ merc_proj = options[:merc_proj] || :mapserver
106
+ @merc_proj = if merc_proj == :mapserver
107
+ "54004"
108
+ elsif merc_proj == :geoserver
109
+ "41001"
110
+ else
111
+ merc_proj.to_s
112
+ end
113
+ @use_geographic = options.has_key?(:use_geographic)? options[:use_geographic] : false
114
+ puts format
115
+ end
116
+
117
+ def get_tile_url
118
+ "getTileUrlForWMS"
119
+ end
120
+
121
+ def create
122
+ "addWMSPropertiesToLayer(#{super},#{MappingObject.javascriptify_variable(@base_url)},#{MappingObject.javascriptify_variable(@layers)},#{MappingObject.javascriptify_variable(@styles)},#{MappingObject.javascriptify_variable(format)},#{MappingObject.javascriptify_variable(@merc_proj)},#{MappingObject.javascriptify_variable(@use_geographic)})"
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,301 @@
1
+ module Ym4r
2
+ module GmPlugin
3
+ #Representing the Google Maps API class GMap2.
4
+ class GMap
5
+ include MappingObject
6
+
7
+ #A constant containing the declaration of the VML namespace, necessary to display polylines under IE.
8
+ VML_NAMESPACE = "xmlns:v=\"urn:schemas-microsoft-com:vml\""
9
+
10
+ #The id of the DIV that will contain the map in the HTML page.
11
+ attr_reader :container
12
+
13
+ #By default the map in the HTML page will be globally accessible with the name +map+.
14
+ def initialize(container, variable = "map")
15
+ @container = container
16
+ @variable = variable
17
+ @init = []
18
+ @init_end = [] #for stuff that must be initialized at the end (controls)
19
+ @init_begin = [] #for stuff that must be initialized at the beginning (center + zoom)
20
+ @global_init = []
21
+ end
22
+
23
+ #Deprecated. Use the static version instead.
24
+ def header(with_vml = true)
25
+ GMap.header(:with_vml => with_vml)
26
+ end
27
+
28
+ #Outputs the header necessary to use the Google Maps API, by including the JS files of the API, as well as a file containing YM4R/GM helper functions. By default, it also outputs a style declaration for VML elements. This default can be overriddent by passing <tt>:with_vml => false</tt> as option to the method. You can also pass a <tt>:host</tt> option in order to select the correct API key for the location where your app is currently running, in case the current environment has multiple possible keys. Usually, in this case, you should pass it <tt>@request.host</tt>. If you have defined only one API key for the current environment, the <tt>:host</tt> option is ignored. Finally you can override all the key settings in the configuration by passing a value to the <tt>:key</tt> key. You can pass a language for the map type buttons with the <tt>:hl</tt> option (possible values are: Japanese (ja), French (fr), German (de), Italian (it), Spanish (es), Catalan (ca), Basque (eu) and Galician (gl): no values means english). Finally, you can pass <tt>:local_search => true</tt> to get the header css and js information needed for the local search control. If you do want local search you must also add <tt>:local_search => true</tt> to the @map.control_init method.
29
+ def self.header(options = {})
30
+ options[:with_vml] = true unless options.has_key?(:with_vml)
31
+ options[:hl] ||= ''
32
+ options[:local_search] = false unless options.has_key?(:local_search)
33
+ options[:sensor] = false unless options.has_key?(:sensor)
34
+ options[:version] ||= "2.x"
35
+ api_key = ApiKey.get(options)
36
+ a = "<script src=\"http://maps.google.com/maps?file=api&amp;v=#{options[:version]}&amp;key=#{api_key}&amp;hl=#{options[:hl]}&amp;sensor=#{options[:sensor]}\" type=\"text/javascript\"></script>\n"
37
+ a << "<script src=\"/javascripts/ym4r-gm.js\" type=\"text/javascript\"></script>\n" unless options[:without_js]
38
+ a << "<!--[if IE]>\n<style type=\"text/css\">\n v\\:* { behavior:url(#default#VML);}\n</style>\n<![endif]-->\n" if options[:with_vml]
39
+ a << "<script src=\"http://www.google.com/uds/api?file=uds.js&amp;v=1.0\" type=\"text/javascript\"></script>" if options[:local_search]
40
+ a << "<script src=\"http://www.google.com/uds/solutions/localsearch/gmlocalsearch.js\" type=\"text/javascript\"></script>\n" if options[:local_search]
41
+ a << "<style type=\"text/css\">@import url(\"http://www.google.com/uds/css/gsearch.css\");@import url(\"http://www.google.com/uds/solutions/localsearch/gmlocalsearch.css\");}</style>" if options[:local_search]
42
+ a
43
+ end
44
+
45
+ #Outputs the <div id=...></div> which has been configured to contain the map. You can pass <tt>:width</tt> and <tt>:height</tt> as options to output this in the style attribute of the DIV element (you could also achieve the same effect by putting the dimension info into a CSS or using the instance method GMap#header_width_height). You can aslo pass <tt>:class</tt> to set the classname of the div.
46
+ # To include initial content in the div, such as a loading message, you
47
+ # may pass a <tt>:content</tt> option specifying a string, or other
48
+ # object, such as a REXML fragment, that responds to #to_s.
49
+ def div(options = {})
50
+ attributes = "id=\"#{@container}\" "
51
+ if options.has_key?(:height) && options.has_key?(:width)
52
+ width = options.delete(:width)
53
+ if width.is_a?(Integer) or width =~ /^[0-9]+$/
54
+ width = width.to_s + "px"
55
+ end
56
+ height = options.delete(:height)
57
+ if height.is_a?(Integer) or height =~ /^[0-9]+$/
58
+ height = height.to_s + "px"
59
+ end
60
+ attributes += "style=\"width:#{width};height:#{height}\" "
61
+ end
62
+ if options.has_key?(:class)
63
+ attributes += options.keys.map {|opt| "#{opt}=\"#{options[opt]}\"" }.join(" ")
64
+ end
65
+ "<div #{attributes}>#{options[:content].to_s}</div>"
66
+ end
67
+
68
+ #Outputs a style declaration setting the dimensions of the DIV container of the map. This info can also be set manually in a CSS.
69
+ def header_width_height(width,height)
70
+ "<style type=\"text/css\">\n##{@container} { height: #{height}px;\n width: #{width}px;\n}\n</style>"
71
+ end
72
+
73
+ #Records arbitrary JavaScript code and outputs it during initialization inside the +load+ function.
74
+ def record_init(code)
75
+ @init << code
76
+ end
77
+
78
+ #Initializes the controls: you can pass a hash with keys <tt>:small_map</tt>, <tt>:large_map</tt>, <tt>:small_zoom</tt>, <tt>:scale</tt>, <tt>:map_type</tt>, <tt>:overview_map</tt> and hash of options controlling its display (<tt>:hide</tt> and <tt>:size</tt>), <tt>:local_search</tt>, <tt>:local_search_options</tt>, and <tt>:show_on_focus</tt>
79
+ def control_init(controls = {})
80
+ @init_end << add_control(GSmallMapControl.new) if controls[:small_map]
81
+ @init_end << add_control(GLargeMapControl.new) if controls[:large_map]
82
+ @init_end << add_control(GSmallZoomControl.new) if controls[:small_zoom]
83
+ @init_end << add_control(GScaleControl.new) if controls[:scale]
84
+ @init_end << add_control(GMapTypeControl.new) if controls[:map_type]
85
+ @init_end << add_control(GHierarchicalMapTypeControl.new) if controls[:hierarchical_map_type]
86
+ if controls[:overview_map]
87
+ if controls[:overview_map].is_a?(Hash)
88
+ hide = controls[:overview_map][:hide]
89
+ size = controls[:overview_map][:size]
90
+ end
91
+ overview_control = GOverviewMapControl.new(size)
92
+ @global_init << overview_control.declare("#{@variable}_ovm") if hide
93
+ @init_end << add_control(overview_control)
94
+ @init_end << "#{overview_control.variable}.hide(true);" if hide
95
+ end
96
+ @init_end << add_control(GLocalSearchControl.new(controls[:anchor], controls[:offset_width], controls[:offset_height], controls[:local_search_options])) if controls[:local_search]
97
+ if controls[:show_on_focus] # Should be last
98
+ @init_end << "#{@variable}.hideControls();"
99
+ event_init(self, :mouseover, "function(){#{@variable}.showControls();}")
100
+ event_init(self, :mouseout, "function(){#{@variable}.hideControls();}")
101
+ end
102
+ end
103
+
104
+ #Initializes the interface configuration: double-click zoom, dragging, continuous zoom,... You can pass a hash with keys <tt>:dragging</tt>, <tt>:info_window</tt>, <tt>:double_click_zoom</tt>, <tt>:continuous_zoom</tt> and <tt>:scroll_wheel_zoom</tt>. The values should be true or false. Check the google maps API doc to know what the default values are.
105
+ def interface_init(interface = {})
106
+ if !interface[:dragging].nil?
107
+ if interface[:dragging]
108
+ @init << enableDragging()
109
+ else
110
+ @init << disableDragging()
111
+ end
112
+ end
113
+ if !interface[:info_window].nil?
114
+ if interface[:info_window]
115
+ @init << enableInfoWindow()
116
+ else
117
+ @init << disableInfoWindow()
118
+ end
119
+ end
120
+ if !interface[:double_click_zoom].nil?
121
+ if interface[:double_click_zoom]
122
+ @init << enableDoubleClickZoom()
123
+ else
124
+ @init << disableDoubleClickZoom()
125
+ end
126
+ end
127
+ if !interface[:continuous_zoom].nil?
128
+ if interface[:continuous_zoom]
129
+ @init << enableContinuousZoom()
130
+ else
131
+ @init << disableContinuousZoom()
132
+ end
133
+ end
134
+ if !interface[:scroll_wheel_zoom].nil?
135
+ if interface[:scroll_wheel_zoom]
136
+ @init << enableScrollWheelZoom()
137
+ else
138
+ @init << disableScrollWheelZoom()
139
+ end
140
+ end
141
+ end
142
+
143
+ #Initializes the initial center and zoom of the map. +center+ can be both a GLatLng object or a 2-float array.
144
+ def center_zoom_init(center, zoom)
145
+ if center.is_a?(GLatLng)
146
+ @init_begin << set_center(center,zoom)
147
+ else
148
+ @init_begin << set_center(GLatLng.new(center),zoom)
149
+ end
150
+ end
151
+
152
+ #Center and zoom based on the coordinates passed as argument (either 2D arrays or GLatLng objects)
153
+ def center_zoom_on_points_init(*points)
154
+ if(points.length > 0)
155
+ if(points[0].is_a?(Array))
156
+ points = points.collect { |point| GLatLng.new(point) }
157
+ end
158
+ @init_begin << center_and_zoom_on_points(points)
159
+ end
160
+ end
161
+
162
+ #Center and zoom based on the bbox corners. Pass a GLatLngBounds object, an array of 2D coordinates (sw and ne) or an array of GLatLng objects (sw and ne).
163
+ def center_zoom_on_bounds_init(latlngbounds)
164
+ if(latlngbounds.is_a?(Array))
165
+ if latlngbounds[0].is_a?(Array)
166
+ latlngbounds = GLatLngBounds.new(GLatLng.new(latlngbounds[0]),GLatLng.new(latlngbounds[1]))
167
+ elsif latlngbounds[0].is_a?(GLatLng)
168
+ latlngbounds = GLatLngBounds.new(*latlngbounds)
169
+ end
170
+ end
171
+ #else it is already a latlngbounds object
172
+
173
+ @init_begin << center_and_zoom_on_bounds(latlngbounds)
174
+ end
175
+
176
+ #Initializes the map by adding an overlay (marker or polyline).
177
+ def overlay_init(overlay)
178
+ @init << add_overlay(overlay)
179
+ end
180
+
181
+ #Sets up a new map type. If +add+ is false, all the other map types of the map are wiped out. If you want to access the map type in other methods, you should declare the map type first (with +declare_init+).
182
+ def add_map_type_init(map_type, add = true)
183
+ unless add
184
+ @init << get_map_types.set_property(:length,0)
185
+ end
186
+ @init << add_map_type(map_type)
187
+ end
188
+ #for legacy purpose
189
+ alias :map_type_init :add_map_type_init
190
+
191
+ #Sets the map type displayed by default after the map is loaded. It should be known from the map (ie either the default map types or a user-defined map type added with <tt>add_map_type_init</tt>). Use <tt>set_map_type_init(GMapType::G_SATELLITE_MAP)</tt> or <tt>set_map_type_init(GMapType::G_HYBRID_MAP)</tt> to initialize the map with repsecitvely the Satellite view and the hybrid view.
192
+ def set_map_type_init(map_type)
193
+ @init << set_map_type(map_type)
194
+ end
195
+
196
+ #Locally declare a MappingObject with variable name "name"
197
+ def declare_init(variable, name)
198
+ @init << variable.declare(name)
199
+ end
200
+
201
+ #Records arbitrary JavaScript code and outputs it during initialization outside the +load+ function (ie globally).
202
+ def record_global_init(code)
203
+ @global_init << code
204
+ end
205
+
206
+ #Deprecated. Use icon_global_init instead.
207
+ def icon_init(icon , name)
208
+ icon_global_init(icon , name)
209
+ end
210
+
211
+ #Initializes an icon and makes it globally accessible through the JavaScript variable of name +variable+.
212
+ def icon_global_init(icon , name, options = {})
213
+ declare_global_init(icon,name,options)
214
+ end
215
+
216
+ #Registers an event
217
+ def event_init(object,event,callback)
218
+ @init << "GEvent.addListener(#{object.to_javascript},\"#{MappingObject.javascriptify_method(event.to_s)}\",#{callback});"
219
+ end
220
+
221
+ #Registers an event globally
222
+ def event_global_init(object,event,callback)
223
+ @global_init << "GEvent.addListener(#{object.to_javascript},\"#{MappingObject.javascriptify_method(event.to_s)}\",#{callback});"
224
+ end
225
+
226
+ #Declares the overlay globally with name +name+
227
+ def overlay_global_init(overlay,name, options = {})
228
+ declare_global_init(overlay,name, options)
229
+ @init << add_overlay(overlay)
230
+ end
231
+
232
+ #Globally declare a MappingObject with variable name "name". Option <tt>:local_construction</tt> should be passed if the construction has to be done inside the onload callback method (for exsample if it depends on the GMap to be initialized)
233
+ def declare_global_init(variable,name, options = {})
234
+ unless options[:local_construction]
235
+ @global_init << "var #{variable.assign_to(name)}"
236
+ else
237
+ @global_init << "var #{name};"
238
+ @init << variable.assign_to(name)
239
+ end
240
+ end
241
+
242
+ #Outputs the initialization code for the map. By default, it outputs the script tags, performs the initialization in response to the onload event of the window and makes the map globally available. If you pass +true+ to the option key <tt>:full</tt>, the map will be setup in full screen, in which case it is not necessary (but not harmful) to set a size for the map div.
243
+ def to_html(options = {})
244
+ no_load = options[:no_load]
245
+ no_script_tag = options[:no_script_tag]
246
+ no_declare = options[:no_declare]
247
+ no_global = options[:no_global]
248
+ fullscreen = options[:full]
249
+ load_pr = options[:proto_load] #to prevent some problems when the onload event callback from Prototype is used
250
+
251
+ html = ""
252
+ html << "<script type=\"text/javascript\">\n" if !no_script_tag
253
+ #put the functions in a separate javascript file to be included in the page
254
+ html << @global_init * "\n"
255
+ html << "var #{@variable};\n" if !no_declare and !no_global
256
+ if !no_load
257
+ if load_pr
258
+ html << "Event.observe(window,'load',"
259
+ else
260
+ html << "window.onload = addCodeToFunction(window.onload,"
261
+ end
262
+ html << "function() {\n"
263
+ end
264
+
265
+ html << "if (GBrowserIsCompatible()) {\n"
266
+
267
+ if fullscreen
268
+ #Adding the initial resizing and setting up the event handler for
269
+ #future resizes
270
+ html << "setWindowDims(document.getElementById('#{@container}'));\n"
271
+ html << "if (window.attachEvent) { window.attachEvent(\"onresize\", function() {setWindowDims(document.getElementById('#{@container}'));})} else {window.addEventListener(\"resize\", function() {setWindowDims(document.getElementById('#{@container}')); } , false);}\n"
272
+ end
273
+
274
+ if !no_declare and no_global
275
+ html << "#{declare(@variable)}\n"
276
+ else
277
+ html << "#{assign_to(@variable)}\n"
278
+ end
279
+ html << @init_begin * "\n"
280
+ html << @init * "\n"
281
+ html << @init_end * "\n"
282
+ html << "\n}\n"
283
+ html << "});\n" if !no_load
284
+ html << "</script>" if !no_script_tag
285
+
286
+ if fullscreen
287
+ #setting up the style in case of full screen
288
+ html << "<style>html, body {width: 100%; height: 100%} body {margin-top: 0px; margin-right: 0px; margin-left: 0px; margin-bottom: 0px} ##{@container} {margin: 0px;} </style>"
289
+ end
290
+
291
+ html
292
+ end
293
+
294
+ #Outputs in JavaScript the creation of a GMap2 object
295
+ def create
296
+ "new GMap2(document.getElementById(\"#{@container}\"))"
297
+ end
298
+ end
299
+ end
300
+ end
301
+