Fixed #9955 -- Added `GoogleMapSet`, which enables multiple `GoogleMap` objects to placed on the same page; moved all templates to `google` parent dir, and added 'google-map.html' for an included example. Thanks to mandric for the ticket and aromano for initial patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10011 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a7ff8b79ff
commit
d45e24a1f8
|
@ -56,6 +56,6 @@
|
||||||
* GOOGLE_MAPS_URL (optional): Must have a substitution ('%s') for the API
|
* GOOGLE_MAPS_URL (optional): Must have a substitution ('%s') for the API
|
||||||
version.
|
version.
|
||||||
"""
|
"""
|
||||||
from django.contrib.gis.maps.google.gmap import GoogleMap
|
from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet
|
||||||
from django.contrib.gis.maps.google.overlays import GEvent, GMarker, GPolygon, GPolyline
|
from django.contrib.gis.maps.google.overlays import GEvent, GMarker, GPolygon, GPolyline
|
||||||
from django.contrib.gis.maps.google.zoom import GoogleZoom
|
from django.contrib.gis.maps.google.zoom import GoogleZoom
|
||||||
|
|
|
@ -19,14 +19,14 @@ class GoogleMap(object):
|
||||||
xmlns = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML Namespace (for IE VML).
|
xmlns = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML Namespace (for IE VML).
|
||||||
|
|
||||||
def __init__(self, key=None, api_url=None, version=None,
|
def __init__(self, key=None, api_url=None, version=None,
|
||||||
center=None, zoom=None, dom_id='map', load_func='gmap_load',
|
center=None, zoom=None, dom_id='map',
|
||||||
kml_urls=[], polygons=[], polylines=[], markers=[],
|
kml_urls=[], polygons=[], polylines=[], markers=[],
|
||||||
template='gis/google/js/google-map.js',
|
template='gis/google/google-single.js',
|
||||||
extra_context={}):
|
js_module='geodjango',extra_context={}):
|
||||||
|
|
||||||
# The Google Maps API Key defined in the settings will be used
|
# The Google Maps API Key defined in the settings will be used
|
||||||
# if not passed in as a parameter. The use of an API key is
|
# if not passed in as a parameter. The use of an API key is
|
||||||
# _required_.
|
# _required_.
|
||||||
if not key:
|
if not key:
|
||||||
try:
|
try:
|
||||||
self.key = settings.GOOGLE_MAPS_API_KEY
|
self.key = settings.GOOGLE_MAPS_API_KEY
|
||||||
|
@ -36,7 +36,7 @@ class GoogleMap(object):
|
||||||
self.key = key
|
self.key = key
|
||||||
|
|
||||||
# Getting the Google Maps API version, defaults to using the latest ("2.x"),
|
# Getting the Google Maps API version, defaults to using the latest ("2.x"),
|
||||||
# this is not necessarily the most stable.
|
# this is not necessarily the most stable.
|
||||||
if not version:
|
if not version:
|
||||||
self.version = getattr(settings, 'GOOGLE_MAPS_API_VERSION', '2.x')
|
self.version = getattr(settings, 'GOOGLE_MAPS_API_VERSION', '2.x')
|
||||||
else:
|
else:
|
||||||
|
@ -51,7 +51,8 @@ class GoogleMap(object):
|
||||||
# Setting the DOM id of the map, the load function, the JavaScript
|
# Setting the DOM id of the map, the load function, the JavaScript
|
||||||
# template, and the KML URLs array.
|
# template, and the KML URLs array.
|
||||||
self.dom_id = dom_id
|
self.dom_id = dom_id
|
||||||
self.load_func = load_func
|
self.extra_context = extra_context
|
||||||
|
self.js_module = js_module
|
||||||
self.template = template
|
self.template = template
|
||||||
self.kml_urls = kml_urls
|
self.kml_urls = kml_urls
|
||||||
|
|
||||||
|
@ -76,11 +77,10 @@ class GoogleMap(object):
|
||||||
else:
|
else:
|
||||||
self.polylines.append(GPolyline(pline))
|
self.polylines.append(GPolyline(pline))
|
||||||
|
|
||||||
# If GMarker, GPolygons, and/or GPolylines
|
# If GMarker, GPolygons, and/or GPolylines are used the zoom will be
|
||||||
# are used the zoom will be automatically
|
# automatically calculated via the Google Maps API. If both a zoom
|
||||||
# calculated via the Google Maps API. If both a zoom level and a
|
# level and a center coordinate are provided with polygons/polylines,
|
||||||
# center coordinate are provided with polygons/polylines, no automatic
|
# no automatic determination will occur.
|
||||||
# determination will occur.
|
|
||||||
self.calc_zoom = False
|
self.calc_zoom = False
|
||||||
if self.polygons or self.polylines or self.markers:
|
if self.polygons or self.polylines or self.markers:
|
||||||
if center is None or zoom is None:
|
if center is None or zoom is None:
|
||||||
|
@ -93,19 +93,22 @@ class GoogleMap(object):
|
||||||
if center is None: center = (0, 0)
|
if center is None: center = (0, 0)
|
||||||
self.center = center
|
self.center = center
|
||||||
|
|
||||||
# Setting the parameters for the javascript template.
|
def render(self):
|
||||||
|
"""
|
||||||
|
Generates the JavaScript necessary for displaying this Google Map.
|
||||||
|
"""
|
||||||
params = {'calc_zoom' : self.calc_zoom,
|
params = {'calc_zoom' : self.calc_zoom,
|
||||||
'center' : self.center,
|
'center' : self.center,
|
||||||
'dom_id' : self.dom_id,
|
'dom_id' : self.dom_id,
|
||||||
|
'js_module' : self.js_module,
|
||||||
'kml_urls' : self.kml_urls,
|
'kml_urls' : self.kml_urls,
|
||||||
'load_func' : self.load_func,
|
|
||||||
'zoom' : self.zoom,
|
'zoom' : self.zoom,
|
||||||
'polygons' : self.polygons,
|
'polygons' : self.polygons,
|
||||||
'polylines' : self.polylines,
|
'polylines' : self.polylines,
|
||||||
'markers' : self.markers,
|
'markers' : self.markers,
|
||||||
}
|
}
|
||||||
params.update(extra_context)
|
params.update(self.extra_context)
|
||||||
self.js = render_to_string(self.template, params)
|
return render_to_string(self.template, params)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def body(self):
|
def body(self):
|
||||||
|
@ -115,16 +118,21 @@ class GoogleMap(object):
|
||||||
@property
|
@property
|
||||||
def onload(self):
|
def onload(self):
|
||||||
"Returns the `onload` HTML <body> attribute."
|
"Returns the `onload` HTML <body> attribute."
|
||||||
return mark_safe('onload="%s()"' % self.load_func)
|
return mark_safe('onload="%s.%s_load()"' % (self.js_module, self.dom_id))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_script(self):
|
def api_script(self):
|
||||||
"Returns the <script> tag for the Google Maps API javascript."
|
"Returns the <script> tag for the Google Maps API javascript."
|
||||||
return mark_safe('<script src="%s%s" type="text/javascript"></script>' % (self.api_url, self.key))
|
return mark_safe('<script src="%s%s" type="text/javascript"></script>' % (self.api_url, self.key))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def js(self):
|
||||||
|
"Returns only the generated Google Maps JavaScript (no <script> tags)."
|
||||||
|
return self.render()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def scripts(self):
|
def scripts(self):
|
||||||
"Returns all <script></script> tags required for Google Maps JavaScript."
|
"Returns all <script></script> tags required with Google Maps JavaScript."
|
||||||
return mark_safe('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>' % (self.api_script, self.js))
|
return mark_safe('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>' % (self.api_script, self.js))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -136,3 +144,75 @@ class GoogleMap(object):
|
||||||
def xhtml(self):
|
def xhtml(self):
|
||||||
"Returns XHTML information needed for IE VML overlays."
|
"Returns XHTML information needed for IE VML overlays."
|
||||||
return mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" %s>' % self.xmlns)
|
return mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" %s>' % self.xmlns)
|
||||||
|
|
||||||
|
class GoogleMapSet(GoogleMap):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
A class for generating sets of Google Maps that will be shown on the
|
||||||
|
same page together.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
gmapset = GoogleMapSet( GoogleMap( ... ), GoogleMap( ... ) )
|
||||||
|
gmapset = GoogleMapSet( [ gmap1, gmap2] )
|
||||||
|
"""
|
||||||
|
# The `google-multi.js` template is used instead of `google-single.js`
|
||||||
|
# by default.
|
||||||
|
template = kwargs.pop('template', 'gis/google/google-multi.js')
|
||||||
|
|
||||||
|
# This is the template used to generate the GMap load JavaScript for
|
||||||
|
# each map in the set.
|
||||||
|
self.map_template = kwargs.pop('map_template', 'gis/google/google-map.js')
|
||||||
|
|
||||||
|
# Running GoogleMap.__init__(), and resetting the template
|
||||||
|
# value with default obtained above.
|
||||||
|
super(GoogleMapSet, self).__init__(**kwargs)
|
||||||
|
self.template = template
|
||||||
|
|
||||||
|
# If a tuple/list passed in as first element of args, then assume
|
||||||
|
if isinstance(args[0], (tuple, list)):
|
||||||
|
self.maps = args[0]
|
||||||
|
else:
|
||||||
|
self.maps = args
|
||||||
|
|
||||||
|
# Generating DOM ids for each of the maps in the set.
|
||||||
|
self.dom_ids = ['map%d' % i for i in xrange(len(self.maps))]
|
||||||
|
|
||||||
|
def load_map_js(self):
|
||||||
|
"""
|
||||||
|
Returns JavaScript containing all of the loading routines for each
|
||||||
|
map in this set.
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
for dom_id, gmap in zip(self.dom_ids, self.maps):
|
||||||
|
# Backup copies the GoogleMap DOM id and template attributes.
|
||||||
|
# They are overridden on each GoogleMap instance in the set so
|
||||||
|
# that only the loading JavaScript (and not the header variables)
|
||||||
|
# is used with the generated DOM ids.
|
||||||
|
tmp = (gmap.template, gmap.dom_id)
|
||||||
|
gmap.template = self.map_template
|
||||||
|
gmap.dom_id = dom_id
|
||||||
|
result.append(gmap.js)
|
||||||
|
# Restoring the backup values.
|
||||||
|
gmap.template, gmap.dom_id = tmp
|
||||||
|
return mark_safe(''.join(result))
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
"""
|
||||||
|
Generates the JavaScript for the collection of Google Maps in
|
||||||
|
this set.
|
||||||
|
"""
|
||||||
|
params = {'js_module' : self.js_module,
|
||||||
|
'dom_ids' : self.dom_ids,
|
||||||
|
'load_map_js' : self.load_map_js(),
|
||||||
|
}
|
||||||
|
params.update(self.extra_context)
|
||||||
|
return render_to_string(self.template, params)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def onload(self):
|
||||||
|
"Returns the `onload` HTML <body> attribute."
|
||||||
|
# Overloaded to use the `load` function defined in the
|
||||||
|
# `google-multi.js`, which calls the load routines for
|
||||||
|
# each one of the individual maps in the set.
|
||||||
|
return mark_safe('onload="%s.load()"' % self.js_module)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
{% block vars %}var geodjango = {};{% endblock %}
|
||||||
|
{% block functions %}{% endblock %}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" {{ gmap.xmlns }}>
|
||||||
|
<head>
|
||||||
|
<title>{% block title %}Google Maps via GeoDjango{% endblock %}</title>
|
||||||
|
{{ gmap.style }}
|
||||||
|
{{ gmap.scripts }}
|
||||||
|
</head>
|
||||||
|
<body {{ gmap.onload }} {{ gmap.onunload }}>
|
||||||
|
{% if gmap.dom_ids %}{% for dom_id in gmap.dom_ids %}<div id="{{ dom_id }}" style="width:600px;height:400px;"></div>{% endfor %}
|
||||||
|
{% else %}<div id="{{ gmap.dom_id }}" style="width:600px;height:400px;"></div>{% endif %}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% autoescape off %}
|
||||||
|
{% block load %}{{ js_module }}.{{ dom_id }}_load = function(){
|
||||||
|
if (GBrowserIsCompatible()) {
|
||||||
|
{{ js_module }}.{{ dom_id }} = new GMap2(document.getElementById("{{ dom_id }}"));
|
||||||
|
{{ js_module }}.{{ dom_id }}.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});
|
||||||
|
{% block controls %}{{ js_module }}.{{ dom_id }}.addControl(new GSmallMapControl());
|
||||||
|
{{ js_module }}.{{ dom_id }}.addControl(new GMapTypeControl());{% endblock %}
|
||||||
|
{% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %}
|
||||||
|
{% for kml_url in kml_urls %}{{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
|
||||||
|
{{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }});{% endfor %}
|
||||||
|
{% for polygon in polygons %}{{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }} = new {{ polygon }};
|
||||||
|
{{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }});
|
||||||
|
{% for event in polygon.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
|
||||||
|
{% if calc_zoom %}tmp_bounds = {{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
||||||
|
{% for polyline in polylines %}{{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }} = new {{ polyline }};
|
||||||
|
{{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }});
|
||||||
|
{% for event in polyline.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
|
||||||
|
{% if calc_zoom %}tmp_bounds = {{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
||||||
|
{% for marker in markers %}{{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }} = new {{ marker }};
|
||||||
|
{{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }});
|
||||||
|
{% for event in marker.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
|
||||||
|
{% if calc_zoom %}bounds.extend({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
|
||||||
|
{% if calc_zoom %}{{ js_module }}.{{ dom_id }}.setCenter(bounds.getCenter(), {{ js_module }}.{{ dom_id }}.getBoundsZoomLevel(bounds));{% endif %}
|
||||||
|
{% block load_extra %}{% endblock %}
|
||||||
|
}else {
|
||||||
|
alert("Sorry, the Google Maps API is not compatible with this browser.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% endblock %}{% endautoescape %}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends "gis/google/google-base.js" %}
|
||||||
|
{% block functions %}
|
||||||
|
{{ load_map_js }}
|
||||||
|
{{ js_module }}.load = function(){
|
||||||
|
{% for dom_id in dom_ids %}{{ js_module }}.{{ dom_id }}_load();
|
||||||
|
{% endfor %}
|
||||||
|
}
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{% extends "gis/google/google-base.js" %}
|
||||||
|
{% block functions %}{% include "gis/google/google-map.js" %}{% endblock %}
|
|
@ -1,34 +0,0 @@
|
||||||
{% autoescape off %}{% block vars %}var map;{% endblock %}
|
|
||||||
{% block functions %}{% endblock %}
|
|
||||||
{% block load %}function {{ load_func }}(){
|
|
||||||
if (GBrowserIsCompatible()) {
|
|
||||||
map = new GMap2(document.getElementById("{{ dom_id }}"));
|
|
||||||
map.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});
|
|
||||||
{% block controls %}map.addControl(new GSmallMapControl());
|
|
||||||
map.addControl(new GMapTypeControl());{% endblock %}
|
|
||||||
{% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %}
|
|
||||||
{% for kml_url in kml_urls %}var kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
|
|
||||||
map.addOverlay(kml{{ forloop.counter }});{% endfor %}
|
|
||||||
|
|
||||||
{% for polygon in polygons %}var poly{{ forloop.counter }} = new {{ polygon }};
|
|
||||||
map.addOverlay(poly{{ forloop.counter }});
|
|
||||||
{% for event in polygon.events %}GEvent.addListener(poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
|
|
||||||
{% if calc_zoom %}tmp_bounds = poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
|
||||||
|
|
||||||
{% for polyline in polylines %}var polyline{{ forloop.counter }} = new {{ polyline }};
|
|
||||||
map.addOverlay(polyline{{ forloop.counter }});
|
|
||||||
{% for event in polyline.events %}GEvent.addListener(polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
|
|
||||||
{% if calc_zoom %}tmp_bounds = polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
|
||||||
|
|
||||||
{% for marker in markers %}var marker{{ forloop.counter }} = new {{ marker }};
|
|
||||||
map.addOverlay(marker{{ forloop.counter }});
|
|
||||||
{% for event in marker.events %}GEvent.addListener(marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
|
|
||||||
{% if calc_zoom %}bounds.extend(marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
|
|
||||||
|
|
||||||
{% if calc_zoom %}map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));{% endif %}
|
|
||||||
{% block load_extra %}{% endblock %}
|
|
||||||
}else {
|
|
||||||
alert("Sorry, the Google Maps API is not compatible with this browser.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{% endblock %}{% endautoescape %}
|
|
Loading…
Reference in New Issue