Ticket #11200: gmap.py.diff

File gmap.py.diff, 8.8 KB (added by ludifan, 15 years ago)
Line 
1from django.conf import settings
2from django.contrib.gis import geos
3from django.template.loader import render_to_string
4from django.utils.safestring import mark_safe
5
6class GoogleMapException(Exception): pass
7from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker, GIcon
8
9# The default Google Maps URL (for the API javascript)
10# TODO: Internationalize for Japan, UK, etc.
11GOOGLE_MAPS_URL='http://maps.google.com/maps?file=api&v=%s&key='
12
13class GoogleMap(object):
14 "A class for generating Google Maps JavaScript."
15
16 # String constants
17 onunload = mark_safe('onunload="GUnload()"') # Cleans up after Google Maps
18 vml_css = mark_safe('v\:* {behavior:url(#default#VML);}') # CSS for IE VML
19 xmlns = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML Namespace (for IE VML).
20
21 def __init__(self, key=None, api_url=None, version=None,
22 center=None, zoom=None, dom_id='map',
23 kml_urls=[], polylines=None, polygons=None, markers=None,
24 template='gis/google/google-single.js',
25 js_module='geodjango',
26 extra_context={}):
27
28 # The Google Maps API Key defined in the settings will be used
29 # if not passed in as a parameter. The use of an API key is
30 # _required_.
31 if not key:
32 try:
33 self.key = settings.GOOGLE_MAPS_API_KEY
34 except AttributeError:
35 raise GoogleMapException('Google Maps API Key not found (try adding GOOGLE_MAPS_API_KEY to your settings).')
36 else:
37 self.key = key
38
39 # Getting the Google Maps API version, defaults to using the latest ("2.x"),
40 # this is not necessarily the most stable.
41 if not version:
42 self.version = getattr(settings, 'GOOGLE_MAPS_API_VERSION', '2.x')
43 else:
44 self.version = version
45
46 # Can specify the API URL in the `api_url` keyword.
47 if not api_url:
48 self.api_url = mark_safe(getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % self.version)
49 else:
50 self.api_url = api_url
51
52 # Setting the DOM id of the map, the load function, the JavaScript
53 # template, and the KML URLs array.
54 self.dom_id = dom_id
55 self.extra_context = extra_context
56 self.js_module = js_module
57 self.template = template
58 self.kml_urls = kml_urls
59
60 # Does the user want any GMarker, GPolygon, and/or GPolyline overlays?
61 overlay_info = [[GMarker, markers, 'markers'],
62 [GPolygon, polygons, 'polygons'],
63 [GPolyline, polylines, 'polylines']]
64
65 for overlay_class, overlay_list, varname in overlay_info:
66 setattr(self, varname, [])
67 if overlay_list:
68 for overlay in overlay_list:
69 if isinstance(overlay, overlay_class):
70 getattr(self, varname).append(overlay)
71 else:
72 getattr(self, varname).append(overlay_class(overlay))
73
74 # If GMarker, GPolygons, and/or GPolylines are used the zoom will be
75 # automatically calculated via the Google Maps API. If both a zoom
76 # level and a center coordinate are provided with polygons/polylines,
77 # no automatic determination will occur.
78 self.calc_zoom = False
79 if self.polygons or self.polylines or self.markers:
80 if center is None or zoom is None:
81 self.calc_zoom = True
82
83 # Defaults for the zoom level and center coordinates if the zoom
84 # is not automatically calculated.
85 if zoom is None: zoom = 4
86 self.zoom = zoom
87 if center is None: center = (0, 0)
88 self.center = center
89
90 def render(self):
91 """
92 Generates the JavaScript necessary for displaying this Google Map.
93 """
94 params = {'calc_zoom' : self.calc_zoom,
95 'center' : self.center,
96 'dom_id' : self.dom_id,
97 'js_module' : self.js_module,
98 'kml_urls' : self.kml_urls,
99 'zoom' : self.zoom,
100 'polygons' : self.polygons,
101 'polylines' : self.polylines,
102 'icons': self.icons,
103 'markers' : self.markers,
104 }
105 params.update(self.extra_context)
106 return render_to_string(self.template, params)
107
108 @property
109 def body(self):
110 "Returns HTML body tag for loading and unloading Google Maps javascript."
111 return mark_safe('<body %s %s>' % (self.onload, self.onunload))
112
113 @property
114 def onload(self):
115 "Returns the `onload` HTML <body> attribute."
116 return mark_safe('onload="%s.%s_load()"' % (self.js_module, self.dom_id))
117
118 @property
119 def api_script(self):
120 "Returns the <script> tag for the Google Maps API javascript."
121 return mark_safe('<script src="%s%s" type="text/javascript"></script>' % (self.api_url, self.key))
122
123 @property
124 def js(self):
125 "Returns only the generated Google Maps JavaScript (no <script> tags)."
126 return self.render()
127
128 @property
129 def scripts(self):
130 "Returns all <script></script> tags required with Google Maps JavaScript."
131 return mark_safe('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>' % (self.api_script, self.js))
132
133 @property
134 def style(self):
135 "Returns additional CSS styling needed for Google Maps on IE."
136 return mark_safe('<style type="text/css">%s</style>' % self.vml_css)
137
138 @property
139 def xhtml(self):
140 "Returns XHTML information needed for IE VML overlays."
141 return mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" %s>' % self.xmlns)
142
143 @property
144 def icons(self):
145 "Returns a sequence of GIcon objects in this map."
146 return set([marker.icon for marker in self.markers if marker.icon])
147
148class GoogleMapSet(GoogleMap):
149
150 def __init__(self, *args, **kwargs):
151 """
152 A class for generating sets of Google Maps that will be shown on the
153 same page together.
154
155 Example:
156 gmapset = GoogleMapSet( GoogleMap( ... ), GoogleMap( ... ) )
157 gmapset = GoogleMapSet( [ gmap1, gmap2] )
158 """
159 # The `google-multi.js` template is used instead of `google-single.js`
160 # by default.
161 template = kwargs.pop('template', 'gis/google/google-multi.js')
162
163 # This is the template used to generate the GMap load JavaScript for
164 # each map in the set.
165 self.map_template = kwargs.pop('map_template', 'gis/google/google-map.js')
166
167 # Running GoogleMap.__init__(), and resetting the template
168 # value with default obtained above.
169 super(GoogleMapSet, self).__init__(**kwargs)
170 self.template = template
171
172 # If a tuple/list passed in as first element of args, then assume
173 if isinstance(args[0], (tuple, list)):
174 self.maps = args[0]
175 else:
176 self.maps = args
177
178 # Generating DOM ids for each of the maps in the set.
179 self.dom_ids = ['map%d' % i for i in xrange(len(self.maps))]
180
181 def load_map_js(self):
182 """
183 Returns JavaScript containing all of the loading routines for each
184 map in this set.
185 """
186 result = []
187 for dom_id, gmap in zip(self.dom_ids, self.maps):
188 # Backup copies the GoogleMap DOM id and template attributes.
189 # They are overridden on each GoogleMap instance in the set so
190 # that only the loading JavaScript (and not the header variables)
191 # is used with the generated DOM ids.
192 tmp = (gmap.template, gmap.dom_id)
193 gmap.template = self.map_template
194 gmap.dom_id = dom_id
195 result.append(gmap.js)
196 # Restoring the backup values.
197 gmap.template, gmap.dom_id = tmp
198 return mark_safe(''.join(result))
199
200 def render(self):
201 """
202 Generates the JavaScript for the collection of Google Maps in
203 this set.
204 """
205 params = {'js_module' : self.js_module,
206 'dom_ids' : self.dom_ids,
207 'load_map_js' : self.load_map_js(),
208 'icons' : self.icons,
209 }
210 params.update(self.extra_context)
211 return render_to_string(self.template, params)
212
213 @property
214 def onload(self):
215 "Returns the `onload` HTML <body> attribute."
216 # Overloaded to use the `load` function defined in the
217 # `google-multi.js`, which calls the load routines for
218 # each one of the individual maps in the set.
219 return mark_safe('onload="%s.load()"' % self.js_module)
220
221 @property
222 def icons(self):
223 "Returns a sequence of all icons in each map of the set."
224 icons = []
225 for map in self.maps: icons.extend(map.icons)
226 return icons
Back to Top