Ticket #14284: 14284_patch.2.diff

File 14284_patch.2.diff, 22.3 KB (added by Alan Justino da Silva, 14 years ago)

Improved patch, over 1.2.4

  • django/contrib/gis/maps/google/__init__.py

    diff -r e6fd4804cf6f django/contrib/gis/maps/google/__init__.py
    a b  
    5757      version.
    5858"""
    5959from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet
    60 from django.contrib.gis.maps.google.overlays import GEvent, GIcon, GMarker, GPolygon, GPolyline
     60from django.contrib.gis.maps.google.overlays import GEvent, GImage, GMarker, GPolygon, GPolyline
    6161from django.contrib.gis.maps.google.zoom import GoogleZoom
  • django/contrib/gis/maps/google/gmap.py

    diff -r e6fd4804cf6f django/contrib/gis/maps/google/gmap.py
    a b from django.template.loader import rende  
    44from django.utils.safestring import mark_safe
    55
    66class GoogleMapException(Exception): pass
    7 from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker, GIcon
     7from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker, GImage
    88
    99# The default Google Maps URL (for the API javascript)
    1010# TODO: Internationalize for Japan, UK, etc.
    11 GOOGLE_MAPS_URL='http://maps.google.com/maps?file=api&v=%s&key='
     11GOOGLE_MAPS_URL='http://maps.google.com/maps/api/js?sensor=%s'
    1212
    1313class GoogleMap(object):
    1414    "A class for generating Google Maps JavaScript."
    1515
    1616    # String constants
    17     onunload = mark_safe('onunload="GUnload()"') # Cleans up after Google Maps
     17    onunload = mark_safe('') # NOTE: Used to call GUnload, but google maps v3 doesn't need it so now blank
    1818    vml_css  = mark_safe('v\:* {behavior:url(#default#VML);}') # CSS for IE VML
    1919    xmlns    = mark_safe('xmlns:v="urn:schemas-microsoft-com:vml"') # XML Namespace (for IE VML).
    2020
    21     def __init__(self, key=None, api_url=None, version=None,
    22                  center=None, zoom=None, dom_id='map',
     21    def __init__(self, api_url=None, center=None, zoom=None, dom_id='map',
    2322                 kml_urls=[], polylines=None, polygons=None, markers=None,
     23                 using_sensor=False,
    2424                 template='gis/google/google-map.js',
    2525                 js_module='geodjango',
    2626                 extra_context={}):
    2727
    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 
    4628        # Can specify the API URL in the `api_url` keyword.
    4729        if not api_url:
    48             self.api_url = mark_safe(getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % self.version)
     30            sensor_value = 'false' # maps v3 needs to know if the device rendering the page has a gps sensor
     31            if using_sensor: sensor_value = 'true'
     32            self.api_url = mark_safe(getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % sensor_value)
    4933        else:
    5034            self.api_url = api_url
    5135
    class GoogleMap(object):  
    118102    @property
    119103    def api_script(self):
    120104        "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))
     105        return mark_safe('<script src="%s" type="text/javascript"></script>' % self.api_url)
    122106
    123107    @property
    124108    def js(self):
    class GoogleMap(object):  
    142126
    143127    @property
    144128    def icons(self):
    145         "Returns a sequence of GIcon objects in this map."
     129        "Returns a sequence of GImage objects in this map."
    146130        return set([marker.icon for marker in self.markers if marker.icon])
    147131
    148132class GoogleMapSet(GoogleMap):
  • django/contrib/gis/maps/google/overlays.py

    diff -r e6fd4804cf6f django/contrib/gis/maps/google/overlays.py
    a b from django.contrib.gis.geos import from  
    33
    44class GEvent(object):
    55    """
    6     A Python wrapper for the Google GEvent object.
     6    A Python wrapper for wiring map events using the
     7    google.maps.event.addListener() function.
    78
    89    Events can be attached to any object derived from GOverlayBase with the
    910    add_event() call.
    1011
    1112    For more information please see the Google Maps API Reference:
    12      http://code.google.com/apis/maps/documentation/reference.html#GEvent
     13     http://code.google.com/apis/maps/documentation/javascript/reference.html#event
    1314
    1415    Example:
    1516
    class GEvent(object):  
    5051        return mark_safe('"%s", %s' %(self.event, self.action))
    5152
    5253class GOverlayBase(object):
     54   
     55    JS_CLASSNAME = 'Overlay'
     56   
    5357    def __init__(self):
    5458        self.events = []
    5559
    5660    def latlng_from_coords(self, coords):
    57         "Generates a JavaScript array of GLatLng objects for the given coordinates."
    58         return '[%s]' % ','.join(['new GLatLng(%s,%s)' % (y, x) for x, y in coords])
     61        "Generates a JavaScript array of google.maps.LatLng objects for the given coordinates."
     62        return '[%s]' % ','.join(['new google.maps.LatLng(%s,%s)' % (y, x) for x, y in coords])
    5963
    6064    def add_event(self, event):
    61         "Attaches a GEvent to the overlay object."
     65        "Causes the event to be applied to the overlay object"
    6266        self.events.append(event)
    6367
    6468    def __unicode__(self):
    6569        "The string representation is the JavaScript API call."
    66         return mark_safe('%s(%s)' % (self.__class__.__name__, self.js_params))
     70        return mark_safe('google.maps.%s(%s)' % (self.JS_CLASSNAME, self.js_params))
    6771
    6872class GPolygon(GOverlayBase):
    6973    """
    70     A Python wrapper for the Google GPolygon object.  For more information
     74    A Python wrapper for the google.maps.Polygon object.  For more information
    7175    please see the Google Maps API Reference:
    72      http://code.google.com/apis/maps/documentation/reference.html#GPolygon
     76     http://code.google.com/apis/maps/documentation/javascript/reference.html#Polygon
    7377    """
     78   
     79    JS_CLASSNAME = 'Polygon'
     80   
    7481    def __init__(self, poly,
    7582                 stroke_color='#0000ff', stroke_weight=2, stroke_opacity=1,
    7683                 fill_color='#0000ff', fill_opacity=0.4):
    7784        """
    78         The GPolygon object initializes on a GEOS Polygon or a parameter that
    79         may be instantiated into GEOS Polygon.  Please note that this will not
    80         depict a Polygon's internal rings.
     85        The GPolygon object initializes on a GEOS Polygon or a
     86        parameter that may be instantiated into GEOS Polygon.  Please note
     87        that this will not depict a Polygon's internal rings.
    8188
    8289        Keyword Options:
    8390
    class GPolygon(GOverlayBase):  
    119126
    120127    @property
    121128    def js_params(self):
    122         return '%s, "%s", %s, %s, "%s", %s' % (self.points, self.stroke_color, self.stroke_weight, self.stroke_opacity,
    123                                                self.fill_color, self.fill_opacity)
     129        result = []
     130        result.append('paths: %s' % self.points)
     131        if self.stroke_color: result.append('strokeColor: "%s"' % self.stroke_color)
     132        if self.stroke_weight: result.append('strokeWeight: "%s"' % self.stroke_weight)
     133        if self.stroke_opacity: result.append('strokeOpacity: "%s"' % self.stroke_opacity)
     134        if self.fill_color: result.append('fillColor: "%s"' % self.fill_color)
     135        if self.fill_opacity: result.append('fillOpactiy: "%s"' % self.fill_opacity)
     136        return '{%s}' % ','.join(result)
    124137
    125138class GPolyline(GOverlayBase):
    126139    """
    127     A Python wrapper for the Google GPolyline object.  For more information
     140    A Python wrapper for the google.maps.Polyline object.  For more information
    128141    please see the Google Maps API Reference:
    129      http://code.google.com/apis/maps/documentation/reference.html#GPolyline
     142     http://code.google.com/apis/maps/documentation/javascript/reference.html#Polyline
    130143    """
     144   
     145    JS_CLASSNAME = 'Polyline'
     146   
    131147    def __init__(self, geom, color='#0000ff', weight=2, opacity=1):
    132148        """
    133149        The GPolyline object may be initialized on GEOS LineStirng, LinearRing,
    class GPolyline(GOverlayBase):  
    163179
    164180    @property
    165181    def js_params(self):
    166         return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity)
     182        result = []
     183        result.append('path: %s' % self.latlngs)
     184        if self.color: result.append('strokeColor: "%s"' % self.color)
     185        if self.weight: result.append('strokeWeight: "%s"' % self.weight)
     186        if self.opacity: result.append('strokeOpacity: "%s"' % self.opacity)
     187        return '{%s}' % ','.join(result)
    167188
    168189
    169 class GIcon(object):
     190class GImage(object):
    170191    """
    171     Creates a GIcon object to pass into a Gmarker object.
     192    Creates a GImage object to pass into a Gmarker object for the icon
     193    and shadow arguments.  The arguments are used to create a MarkerImage
     194    class in the javascript:
    172195
    173     The keyword arguments map to instance attributes of the same name. These,
    174     in turn, correspond to a subset of the attributes of the official GIcon
    175     javascript object:
    176 
    177     http://code.google.com/apis/maps/documentation/reference.html#GIcon
    178 
    179     Because a Google map often uses several different icons, a name field has
    180     been added to the required arguments.
     196    http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerImage
    181197
    182198    Required Arguments:
    183         varname:
    184             A string which will become the basis for the js variable name of
    185             the marker, for this reason, your code should assign a unique
    186             name for each GIcon you instantiate, otherwise there will be
    187             name space collisions in your javascript.
     199       
     200        url:
     201            The url of the image to be used as the icon on the map
    188202
    189203    Keyword Options:
    190         image:
    191             The url of the image to be used as the icon on the map defaults
    192             to 'G_DEFAULT_ICON'
    193204
    194         iconsize:
     205        size:
    195206            a tuple representing the pixel size of the foreground (not the
    196207            shadow) image of the icon, in the format: (width, height) ex.:
    197208
    198             GIcon('fast_food',
    199                   image="/media/icon/star.png",
     209            GImage("/media/icon/star.png",
    200210                  iconsize=(15,10))
    201211
    202212            Would indicate your custom icon was 15px wide and 10px height.
    203 
    204         shadow:
    205             the url of the image of the icon's shadow
    206 
    207         shadowsize:
    208             a tuple representing the pixel size of the shadow image, format is
    209             the same as ``iconsize``
    210 
    211         iconanchor:
     213           
     214        origin:
     215            a tuple representing the pixel coordinate of the upper left corner
     216            of the icon.  Used in conjuction with the size option to specify
     217            the sprite/subset of an image.  In the format: (x,y) ex.:
     218           
     219            3rd_marker = GImage("/media/icon/12_markers.png",
     220                               size=(15,10),
     221                               origin=(30,0))
     222                               
     223            Would indicate the image where it's upper left corner is at (30,0)
     224            and its lower right corner is (45,10).
     225           
     226        anchor:
    212227            a tuple representing the pixel coordinate relative to the top left
    213228            corner of the icon image at which this icon is anchored to the map.
    214229            In (x, y) format.  x increases to the right in the Google Maps
    215230            coordinate system and y increases downwards in the Google Maps
    216231            coordinate system.)
    217232
    218         infowindowanchor:
    219             The pixel coordinate relative to the top left corner of the icon
    220             image at which the info window is anchored to this icon.
     233    """
     234   
     235    def __init__(self, url, size=None, origin=None, anchor=None):
     236        self.url = url
     237        self.size = size
     238        self.origin = origin
     239        self.anchor = anchor
    221240
    222     """
    223     def __init__(self, varname, image=None, iconsize=None,
    224                  shadow=None, shadowsize=None, iconanchor=None,
    225                  infowindowanchor=None):
    226         self.varname = varname
    227         self.image = image
    228         self.iconsize = iconsize
    229         self.shadow = shadow
    230         self.shadowsize = shadowsize
    231         self.iconanchor = iconanchor
    232         self.infowindowanchor = infowindowanchor
    233 
    234     def __cmp__(self, other):
    235         return cmp(self.varname, other.varname)
    236    
    237     def __hash__(self):
    238         # XOR with hash of GIcon type so that hash('varname') won't
    239         # equal hash(GIcon('varname')).
    240         return hash(self.__class__) ^ hash(self.varname)
     241    def _to_param(self):
     242        args = "(%s" % self.url
     243        if self.size:
     244            args += ", new google.maps.Size(%s)" % self.size
     245            if self.origin:
     246                args += ", new google.maps.Point(%s)" % self.origin
     247                if self.anchor:
     248                    args += ", new google.maps.Point(%s)" % self.anchor
     249        args += ")"
     250        return "new google.maps.MarkerImage(%s)" % args
    241251
    242252class GMarker(GOverlayBase):
    243253    """
    244254    A Python wrapper for the Google GMarker object.  For more information
    245255    please see the Google Maps API Reference:
    246      http://code.google.com/apis/maps/documentation/reference.html#GMarker
     256     http://code.google.com/apis/maps/documentation/javascript/reference.html#Marker
    247257
    248258    Example:
    249259
    class GMarker(GOverlayBase):  
    258268          return render_to_response('mytemplate.html',
    259269                 {'google' : GoogleMap(markers=[marker])})
    260270    """
    261     def __init__(self, geom, title=None, draggable=False, icon=None):
     271   
     272    JS_CLASSNAME = 'Marker'
     273   
     274    def __init__(self, geom, title=None, draggable=False, icon=None, shadow=None):
    262275        """
    263276        The GMarker object may initialize on GEOS Points or a parameter
    264         that may be instantiated into a GEOS point.  Keyword options map to
    265         GMarkerOptions -- so far only the title option is supported.
     277        that may be instantiated into a GEOS point.
    266278
    267279        Keyword Options:
    268280         title:
    class GMarker(GOverlayBase):  
    270282
    271283         draggable:
    272284           Draggable option for GMarker, disabled by default.
     285           
     286         icon:
     287           Sets the GImage used to display the marker on the map.
     288           If not set google maps will use the default marker icon.
     289           
     290         shadow:
     291           Sets the GImage used to display the shadow of the marker on the map.
    273292        """
    274293        # If a GEOS geometry isn't passed in, try to construct one.
    275294        if isinstance(geom, basestring): geom = fromstr(geom)
    class GMarker(GOverlayBase):  
    284303        self.title = title
    285304        self.draggable = draggable
    286305        self.icon = icon
     306        self.shadow = shadow
    287307        super(GMarker, self).__init__()
    288308
    289309    def latlng_from_coords(self, coords):
    290         return 'new GLatLng(%s,%s)' %(coords[1], coords[0])
    291 
    292     def options(self):
    293         result = []
    294         if self.title: result.append('title: "%s"' % self.title)
    295         if self.icon: result.append('icon: %s' % self.icon.varname)
    296         if self.draggable: result.append('draggable: true')
    297         return '{%s}' % ','.join(result)
     310        return 'new google.maps.LatLng(%s,%s)' %(coords[1], coords[0])
    298311
    299312    @property
    300313    def js_params(self):
    301         return '%s, %s' % (self.latlng, self.options())
     314        result = []
     315        result.append('position: %s' % self.latlng)
     316        if self.title: result.append('title: "%s"' % self.title)
     317        if self.icon: result.append('icon: %s' % self.icon._to_param())
     318        if self.shadow: result.append('shadow: %s' % self.shadow_to_param())
     319        if self.draggable: result.append('draggable: true')
     320        return '{%s}' % ','.join(result)
  • django/contrib/gis/templates/gis/google/google-map.js

    diff -r e6fd4804cf6f django/contrib/gis/templates/gis/google/google-map.js
    a b  
    11{% autoescape off %}
    2 {% block vars %}var geodjango = {};{% for icon in icons %}
    3 var {{ icon.varname }} = new GIcon(G_DEFAULT_ICON);
    4 {% if icon.image %}{{ icon.varname }}.image = "{{ icon.image }}";{% endif %}
    5 {% if icon.shadow %}{{ icon.varname }}.shadow = "{{ icon.shadow }}";{% endif %} {% if icon.shadowsize %}{{ icon.varname }}.shadowSize = new GSize({{ icon.shadowsize.0 }}, {{ icon.shadowsize.1 }});{% endif %}
    6 {% if icon.iconanchor %}{{ icon.varname }}.iconAnchor = new GPoint({{ icon.iconanchor.0 }}, {{ icon.iconanchor.1 }});{% endif %} {% if icon.iconsize %}{{ icon.varname }}.iconSize = new GSize({{ icon.iconsize.0 }}, {{ icon.iconsize.1 }});{% endif %}
    7 {% if icon.infowindowanchor %}{{ icon.varname }}.infoWindowAnchor = new GPoint({{ icon.infowindowanchor.0 }}, {{ icon.infowindowanchor.1 }});{% endif %}{% endfor %}
     2{% block vars %}var geodjango = {};
    83{% endblock vars %}{% block functions %}
    94{% block load %}{{ js_module }}.{{ dom_id }}_load = function(){
    10   if (GBrowserIsCompatible()) {
    11     {{ js_module }}.{{ dom_id }} = new GMap2(document.getElementById("{{ dom_id }}"));
    12     {{ js_module }}.{{ dom_id }}.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});
    13     {% block controls %}{{ js_module }}.{{ dom_id }}.setUIToDefault();{% endblock %}
    14     {% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %}
    15     {% for kml_url in kml_urls %}{{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
    16     {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }});{% endfor %}
    17     {% for polygon in polygons %}{{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }} = new {{ polygon }};
    18     {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }});
    19     {% for event in polygon.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
    20     {% 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 %}
    21     {% for polyline in polylines %}{{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }} = new {{ polyline }};
    22     {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }});
    23     {% for event in polyline.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
    24     {% 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 %}
    25     {% for marker in markers %}{{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }} = new {{ marker }};
    26     {{ js_module }}.{{ dom_id }}.addOverlay({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }});
    27     {% for event in marker.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
    28     {% if calc_zoom %}bounds.extend({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
    29     {% if calc_zoom %}{{ js_module }}.{{ dom_id }}.setCenter(bounds.getCenter(), {{ js_module }}.{{ dom_id }}.getBoundsZoomLevel(bounds));{% endif %}
    30     {% block load_extra %}{% endblock %}
    31   }else {
    32     alert("Sorry, the Google Maps API is not compatible with this browser.");
     5  var map_options = {
     6    zoom: {{ zoom }},
     7    center: google.maps.LatLng({{ center.1 }}, {{ center.0 }}),
     8    mapTypeId: google.maps.MapTypeId.ROADMAP
    339  }
     10  {{ js_module }}.{{ dom_id }} = new google.maps.Map(document.getElementById("{{ dom_id }}"), map_options);
     11  {% block controls %}{% endblock %}
     12  {% if calc_zoom %}var bounds = new google.maps.LatLngBounds(); var i; var j;{% endif %}
     13  {% for kml_url in kml_urls %}{{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }} = new google.maps.KmlLayer("{{ kml_url }}");
     14  {{ js_module }}.{{ dom_id }}_kml{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }});{% endfor %}
     15  {% for polygon in polygons %}{{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }} = new {{ polygon }};
     16  {{ js_module }}.{{ dom_id }}_poly{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }});
     17  {% for event in polygon.events %}google.event.addListener({{ js_module }}.{{ dom_id }}_poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
     18  {% if calc_zoom %}paths={{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.getPaths(); for(i=0; i<paths.length(); i++){ for(j=0; j<paths[i].length(); j++){ bounds.extend(paths[i][j]); }}{% endif %}{% endfor %} 
     19  {% for polyline in polylines %}{{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }} = new {{ polyline }};
     20  {{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }});
     21  {% for event in polyline.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
     22  {% if calc_zoom %}path={{ js_module }}.{{ dom_id }}_polyline{{ forloop.counter }}.getPath(); for(i=0; i<path.length(); i++){ bounds.extend(path[i]); }{% endif %}{% endfor %}
     23  {% for marker in markers %}{{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }} = new {{ marker }};
     24  {{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.setMap({{ js_module }}.{{ dom_id }});
     25  {% for event in marker.events %}GEvent.addListener({{ js_module }}.{{ dom_id }}_marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
     26  {% if calc_zoom %}bounds.extend({{ js_module }}.{{ dom_id }}_marker{{ forloop.counter }}.getPosition());{% endif %}{% endfor %}
     27  {% if calc_zoom %}{{ js_module }}.{{ dom_id }}.fitBounds(bounds);{% endif %}
     28  {% block load_extra %}{% endblock %}
    3429}
    3530{% endblock load %}{% endblock functions %}{% endautoescape %}
Back to Top