Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #9955 -- Added `GoogleMapSet`, which enables multiple `GoogleMa…

…p` 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
  • Loading branch information...
commit d45e24a1f849e1f244b58565223765c95156fef1 1 parent a7ff8b7
Justin Bronn authored
2  django/contrib/gis/maps/google/__init__.py
@@ -56,6 +56,6 @@
56 56
    * GOOGLE_MAPS_URL (optional): Must have a substitution ('%s') for the API
57 57
       version.
58 58
 """
59  
-from django.contrib.gis.maps.google.gmap import GoogleMap
  59
+from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet
60 60
 from django.contrib.gis.maps.google.overlays import GEvent, GMarker, GPolygon, GPolyline
61 61
 from django.contrib.gis.maps.google.zoom import GoogleZoom
116  django/contrib/gis/maps/google/gmap.py
@@ -19,14 +19,14 @@ class GoogleMap(object):
19 19
     xmlns    = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML Namespace (for IE VML).
20 20
 
21 21
     def __init__(self, key=None, api_url=None, version=None, 
22  
-                 center=None, zoom=None, dom_id='map', load_func='gmap_load', 
  22
+                 center=None, zoom=None, dom_id='map',
23 23
                  kml_urls=[], polygons=[], polylines=[], markers=[],
24  
-                 template='gis/google/js/google-map.js',
25  
-                 extra_context={}):
  24
+                 template='gis/google/google-single.js',
  25
+                 js_module='geodjango',extra_context={}):
26 26
 
27 27
         # The Google Maps API Key defined in the settings will be used
28  
-        #  if not passed in as a parameter.  The use of an API key is
29  
-        #  _required_.
  28
+        # if not passed in as a parameter.  The use of an API key is
  29
+        # _required_.
30 30
         if not key:
31 31
             try:
32 32
                 self.key = settings.GOOGLE_MAPS_API_KEY
@@ -36,7 +36,7 @@ def __init__(self, key=None, api_url=None, version=None,
36 36
             self.key = key
37 37
         
38 38
         # Getting the Google Maps API version, defaults to using the latest ("2.x"),
39  
-        #  this is not necessarily the most stable.
  39
+        # this is not necessarily the most stable.
40 40
         if not version:
41 41
             self.version = getattr(settings, 'GOOGLE_MAPS_API_VERSION', '2.x')
42 42
         else:
@@ -51,7 +51,8 @@ def __init__(self, key=None, api_url=None, version=None,
51 51
         # Setting the DOM id of the map, the load function, the JavaScript
52 52
         # template, and the KML URLs array.
53 53
         self.dom_id = dom_id
54  
-        self.load_func = load_func
  54
+        self.extra_context = extra_context
  55
+        self.js_module = js_module
55 56
         self.template = template
56 57
         self.kml_urls = kml_urls
57 58
         
@@ -76,11 +77,10 @@ def __init__(self, key=None, api_url=None, version=None,
76 77
                 else:
77 78
                     self.polylines.append(GPolyline(pline))
78 79
        
79  
-        # If GMarker, GPolygons, and/or GPolylines 
80  
-        # are used the zoom will be automatically
81  
-        # calculated via the Google Maps API.  If both a zoom level and a
82  
-        # center coordinate are provided with polygons/polylines, no automatic
83  
-        # determination will occur.
  80
+        # If GMarker, GPolygons, and/or GPolylines are used the zoom will be
  81
+        # automatically calculated via the Google Maps API.  If both a zoom
  82
+        # level and a center coordinate are provided with polygons/polylines,
  83
+        # no automatic determination will occur.
84 84
         self.calc_zoom = False
85 85
         if self.polygons or self.polylines  or self.markers:
86 86
             if center is None or zoom is None:
@@ -93,19 +93,22 @@ def __init__(self, key=None, api_url=None, version=None,
93 93
         if center is None: center = (0, 0)
94 94
         self.center = center
95 95
 
96  
-        # Setting the parameters for the javascript template.
  96
+    def render(self):
  97
+        """
  98
+        Generates the JavaScript necessary for displaying this Google Map.
  99
+        """
97 100
         params = {'calc_zoom' : self.calc_zoom,
98 101
                   'center' : self.center,
99 102
                   'dom_id' : self.dom_id,
  103
+                  'js_module' : self.js_module,
100 104
                   'kml_urls' : self.kml_urls,
101  
-                  'load_func' : self.load_func,
102 105
                   'zoom' : self.zoom,
103 106
                   'polygons' : self.polygons,
104 107
                   'polylines' : self.polylines,
105 108
                   'markers' : self.markers,
106 109
                   }
107  
-        params.update(extra_context)
108  
-        self.js = render_to_string(self.template, params)
  110
+        params.update(self.extra_context)
  111
+        return render_to_string(self.template, params)
109 112
 
110 113
     @property
111 114
     def body(self):
@@ -115,7 +118,7 @@ def body(self):
115 118
     @property
116 119
     def onload(self):
117 120
         "Returns the `onload` HTML <body> attribute."
118  
-        return mark_safe('onload="%s()"' % self.load_func)
  121
+        return mark_safe('onload="%s.%s_load()"' % (self.js_module, self.dom_id))
119 122
 
120 123
     @property
121 124
     def api_script(self):
@@ -123,8 +126,13 @@ def api_script(self):
123 126
         return mark_safe('<script src="%s%s" type="text/javascript"></script>' % (self.api_url, self.key))
124 127
 
125 128
     @property
  129
+    def js(self):
  130
+        "Returns only the generated Google Maps JavaScript (no <script> tags)."
  131
+        return self.render()
  132
+
  133
+    @property
126 134
     def scripts(self):
127  
-        "Returns all <script></script> tags required for Google Maps JavaScript."
  135
+        "Returns all <script></script> tags required with Google Maps JavaScript."
128 136
         return mark_safe('%s\n  <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n  </script>' % (self.api_script, self.js))
129 137
 
130 138
     @property
@@ -136,3 +144,75 @@ def style(self):
136 144
     def xhtml(self):
137 145
         "Returns XHTML information needed for IE VML overlays."
138 146
         return mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" %s>' % self.xmlns)
  147
+
  148
+class 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
+                  }
  209
+        params.update(self.extra_context)
  210
+        return render_to_string(self.template, params)
  211
+
  212
+    @property
  213
+    def onload(self):
  214
+        "Returns the `onload` HTML <body> attribute."
  215
+        # Overloaded to use the `load` function defined in the
  216
+        # `google-multi.js`, which calls the load routines for
  217
+        # each one of the individual maps in the set.
  218
+        return mark_safe('onload="%s.load()"' % self.js_module)
2  django/contrib/gis/templates/gis/google/google-base.js
... ...
@@ -0,0 +1,2 @@
  1
+{% block vars %}var geodjango = {};{% endblock %}
  2
+{% block functions %}{% endblock %}
12  django/contrib/gis/templates/gis/google/google-map.html
... ...
@@ -0,0 +1,12 @@
  1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2
+<html xmlns="http://www.w3.org/1999/xhtml" {{ gmap.xmlns }}>
  3
+<head>
  4
+  <title>{% block title %}Google Maps via GeoDjango{% endblock %}</title>
  5
+  {{ gmap.style }}
  6
+  {{ gmap.scripts }}
  7
+</head>
  8
+<body {{ gmap.onload }} {{ gmap.onunload }}>
  9
+{% if gmap.dom_ids %}{% for dom_id in gmap.dom_ids %}<div id="{{ dom_id }}" style="width:600px;height:400px;"></div>{% endfor %}
  10
+{% else %}<div id="{{ gmap.dom_id }}" style="width:600px;height:400px;"></div>{% endif %}
  11
+</body>
  12
+</html>
29  django/contrib/gis/templates/gis/google/google-map.js
... ...
@@ -0,0 +1,29 @@
  1
+{% autoescape off %}
  2
+{% block load %}{{ js_module }}.{{ dom_id }}_load = function(){
  3
+  if (GBrowserIsCompatible()) {
  4
+    {{ js_module }}.{{ dom_id }} = new GMap2(document.getElementById("{{ dom_id }}"));
  5
+    {{ js_module }}.{{ dom_id }}.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});
  6
+    {% block controls %}{{ js_module }}.{{ dom_id }}.addControl(new GSmallMapControl());
  7
+    {{ js_module }}.{{ dom_id }}.addControl(new GMapTypeControl());{% endblock %}
  8
+    {% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %}
  9
+    {% for kml_url in kml_urls %}{{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
  10
+    {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }});{% endfor %}
  11
+    {% for polygon in polygons %}{{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }} = new {{ polygon }};
  12
+    {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }});
  13
+    {% for event in polygon.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
  14
+    {% 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 %}
  15
+    {% for polyline in polylines %}{{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }} = new {{ polyline }};
  16
+    {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }});
  17
+    {% for event in polyline.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
  18
+    {% 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 %}
  19
+    {% for marker in markers %}{{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }} = new {{ marker }};
  20
+    {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }});
  21
+    {% for event in marker.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
  22
+    {% if calc_zoom %}bounds.extend({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
  23
+    {% if calc_zoom %}{{ js_module }}.{{ dom_id }}.setCenter(bounds.getCenter(), {{ js_module }}.{{ dom_id }}.getBoundsZoomLevel(bounds));{% endif %}
  24
+    {% block load_extra %}{% endblock %}
  25
+  }else {
  26
+    alert("Sorry, the Google Maps API is not compatible with this browser.");
  27
+  }
  28
+}
  29
+{% endblock %}{% endautoescape %}
8  django/contrib/gis/templates/gis/google/google-multi.js
... ...
@@ -0,0 +1,8 @@
  1
+{% extends "gis/google/google-base.js" %}
  2
+{% block functions %}
  3
+{{ load_map_js }}
  4
+{{ js_module }}.load = function(){
  5
+    {% for dom_id in dom_ids %}{{ js_module }}.{{ dom_id }}_load();
  6
+    {% endfor %}
  7
+}
  8
+{% endblock %}
2  django/contrib/gis/templates/gis/google/google-single.js
... ...
@@ -0,0 +1,2 @@
  1
+{% extends "gis/google/google-base.js" %}
  2
+{% block functions %}{% include "gis/google/google-map.js" %}{% endblock %}
34  django/contrib/gis/templates/gis/google/js/google-map.js
... ...
@@ -1,34 +0,0 @@
1  
-{% autoescape off %}{% block vars %}var map;{% endblock %}
2  
-{% block functions %}{% endblock %}
3  
-{% block load %}function {{ load_func }}(){
4  
-  if (GBrowserIsCompatible()) {
5  
-    map = new GMap2(document.getElementById("{{ dom_id }}"));
6  
-    map.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});
7  
-    {% block controls %}map.addControl(new GSmallMapControl());
8  
-    map.addControl(new GMapTypeControl());{% endblock %}
9  
-    {% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %}
10  
-    {% for kml_url in kml_urls %}var kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
11  
-    map.addOverlay(kml{{ forloop.counter }});{% endfor %}
12  
-
13  
-    {% for polygon in polygons %}var poly{{ forloop.counter }} = new {{ polygon }};
14  
-    map.addOverlay(poly{{ forloop.counter }});
15  
-    {% for event in polygon.events %}GEvent.addListener(poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
16  
-    {% if calc_zoom %}tmp_bounds = poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
17  
-
18  
-    {% for polyline in polylines %}var polyline{{ forloop.counter }} = new {{ polyline }};
19  
-    map.addOverlay(polyline{{ forloop.counter }});
20  
-    {% for event in polyline.events %}GEvent.addListener(polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
21  
-    {% if calc_zoom %}tmp_bounds = polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
22  
-    
23  
-    {% for marker in markers %}var marker{{ forloop.counter }} = new {{ marker }};
24  
-    map.addOverlay(marker{{ forloop.counter }});
25  
-    {% for event in marker.events %}GEvent.addListener(marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
26  
-    {% if calc_zoom %}bounds.extend(marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
27  
-
28  
-    {% if calc_zoom %}map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));{% endif %}
29  
-    {% block load_extra %}{% endblock %}
30  
-  }else {
31  
-    alert("Sorry, the Google Maps API is not compatible with this browser.");
32  
-  }
33  
-}
34  
-{% endblock %}{% endautoescape %}

0 notes on commit d45e24a

Please sign in to comment.
Something went wrong with that request. Please try again.