Skip to content

Commit

Permalink
As discussed, JS-style custom map layers.
Browse files Browse the repository at this point in the history
  • Loading branch information
philipn committed Sep 27, 2011
1 parent 5992ecb commit edeb0cc
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 74 deletions.
@@ -1,7 +1,7 @@
<div id="{{ id }}"></div>
{{ layer_html|join:"" }}
<script type="text/javascript">
olwidget.registerCustomBaseLayers({{ custom_base_layers|safe }});
{{ setup_custom_layer_types|safe }}
new olwidget.Map("{{ id }}", [
{{ layer_js|join:"," }}
],
Expand Down
4 changes: 2 additions & 2 deletions django-olwidget/olwidget/utils.py
Expand Up @@ -11,8 +11,8 @@ def get_options(o):
options.update(o or {})
return options

def get_custom_base_layers():
return getattr(settings, 'OLWIDGET_CUSTOM_BASE_LAYERS', {})
def get_custom_layer_types():
return getattr(settings, 'OLWIDGET_CUSTOM_LAYER_TYPES', {})

def url_join(*args):
return reduce(_reduce_url_parts, args)
Expand Down
11 changes: 9 additions & 2 deletions django-olwidget/olwidget/widgets.py
Expand Up @@ -59,7 +59,7 @@ def __init__(self, vector_layers=None, options=None, template=None,
# Though this layer is the olwidget.js default, it must be explicitly
# set so {{ form.media }} knows to include osm.
self.options['layers'] = self.options.get('layers', ['osm.mapnik'])
self.custom_base_layers = utils.get_custom_base_layers()
self.custom_layer_types = utils.get_custom_layer_types()
self.template = template or self.default_template
super(Map, self).__init__()

Expand Down Expand Up @@ -97,7 +97,7 @@ def render(self, name, value, attrs=None):
'layer_js': layer_js,
'layer_html': layer_html,
'map_opts': simplejson.dumps(utils.translate_options(self.options)),
'custom_base_layers': simplejson.dumps(utils.translate_options(self.custom_base_layers)),
'setup_custom_layer_types': self._custom_layer_types_js(),
'STATIC_URL': settings.STATIC_URL,
}
context.update(self.get_extra_context())
Expand All @@ -119,6 +119,13 @@ def value_from_datadict(self, data, files, name):
""" Return an array of all layers' values. """
return [vl.value_from_datadict(data, files, lyr_name) for vl, lyr_name in zip(self.vector_layers, self._get_layer_names(name))]

def _custom_layer_types_js(self):
layer_types_js = ""
for typename in self.custom_layer_types:
js_def = self.custom_layer_types[typename]
layer_types_js += "olwidget.%s = %s;" % (typename, js_def)
return layer_types_js

def _get_layer_names(self, name):
"""
If the user gave us a layer_names parameter, use that. Otherwise,
Expand Down
36 changes: 16 additions & 20 deletions doc-src/django-olwidget.rst
Expand Up @@ -550,28 +550,24 @@ General map display
``CLOUDMADE_API_KEY`` in your ``settings.py`` if you use any of those
layers.

Custom base layers from other providers can be used by choosing
``custom.<name>``, where ``<name>`` corresponds to a custom base
layer that's been listed in the ``OLWIDGET_CUSTOM_BASE_LAYERS`` setting
option. Here's an example::

OLWIDGET_CUSTOM_BASE_LAYERS = {
'opengeo_osm': # to use this, your olwidget layers would include ['custom.opengeo_osm']
{"class": "WMS", # The OpenLayers.Layer subclass to use.
"args": [ # These are passed as arguments to the constructor.
"OpenStreetMap (OpenGeo)",
"http://maps.opengeo.org/geowebcache/service/wms",
{"layers": "openstreetmap",
"format": "image/png",
"bgcolor": "#A1BDC4",
},
{"wrapDateLine": True
},
],
}
Custom layer types from other providers can be used by listing their
JavaScript construction string in the ``OLWIDGET_CUSTOM_LAYER_TYPES``
setting option. Here's an example::

OLWIDGET_CUSTOM_LAYER_TYPES = {
'opengeo_osm': """new OpenLayers.Layer.WMS(
'OpenStreetMap (OpenGeo)',
'http://maps.opengeo.org/geowebcache/service/wms',
{
layers: 'openstreetmap',
format: 'image/png',
bgColor: '#A1BDC4',
},
{wrapDateLine: true}
)"""
}

We can then access this base layer as ``custom.opengeo_osm``.
We can then access this layer type as ``opengeo_osm``.

``default_lat`` (float; default 0)
Latitude for the center point of the map.
Expand Down
38 changes: 16 additions & 22 deletions doc-src/olwidget.js.rst
Expand Up @@ -308,28 +308,22 @@ General map display
is the number for a cloudmade style). A blank map can be obtained using
``'wms.blank'``.
Other providers can be added by choosing ``custom.<name>`` where
``<name>`` corresponds to a property that has been registered with
``olwidget.registerCustomBaseLayers()``. The property must have a
``class`` property corresponding to an OpenLayers layer subclass
and an ``args`` property that is a list of arguments to pass to that
constructor. For example::
olwidget.registerCustomBaseLayers({
'opengeo_osm': // to use this, your olwidget layers would include ['custom.opengeo_osm']
{"class": "WMS", // The OpenLayers.Layer subclass to use.
"args": [ // These are passed as arguments to the constructor.
"OpenStreetMap (OpenGeo)",
"http://maps.opengeo.org/geowebcache/service/wms",
{"layers": "openstreetmap",
"format": "image/png",
"bgcolor": "#A1BDC4",
},
{"wrapDateLine": true
},
],
}
})
Other providers can be added by simply setting
``olwidget.layernamehere`` to an OpenLayers Layer object. For
example::
olwidget.opengeo_osm = new OpenLayers.Layer.WMS(
'OpenStreetMap (OpenGeo)',
'http://maps.opengeo.org/geowebcache/service/wms',
{
layers: 'openstreetmap',
format: 'image/png',
bgColor: '#A1BDC4',
},
{wrapDateLine: true}
);
The new base layer is now accessible as ``opengeo_osm``.
Additional options and layers can also be manually added
using the normal OpenLayers apis (see `this provider example
Expand Down
38 changes: 11 additions & 27 deletions js/olwidget.js
Expand Up @@ -144,32 +144,6 @@ var olwidget = {
});
}
},
custom: {
// Support for arbitrary OpenLayers base layers.
// To use this, ensure that customBaseLayers[type] exists, and
// has both a 'class' string (name of the OL constructor) and
// an 'args' array to pass to that constructor.
map: function(type) {
var classname = olwidget._customBaseLayers[type]['class'];
var class_ = OpenLayers.Layer[classname];
var args = olwidget._customBaseLayers[type].args;
// Can't use .apply() directly with an OL constructor,
// because we don't have a suitable `this` argument.
// Instead make a constructor function with a .prototype
// property the same as our class.prototype.
// The `new` keyword creates an instance from that prototype
// which will be used as `this` in the constructor call.
// `new` is also the only way to get the new instance to have
// the correct actual prototype, which is *not* the same as
// class.prototype. Thanks Tim Schaub for explaining this bit of
// javascript OOP to me.
var constructor = function() {
class_.prototype.initialize.apply(this, args);
};
constructor.prototype = class_.prototype;
return new constructor();
}
},
/*
* Utilities
*/
Expand Down Expand Up @@ -289,7 +263,17 @@ olwidget.Map = OpenLayers.Class(OpenLayers.Map, {
var layers = [];
for (var i = 0; i < opts.layers.length; i++) {
var parts = opts.layers[i].split(".");
layers.push(olwidget[parts[0]].map(parts[1]));
var map_service = olwidget[parts[0]];
var map_type = parts[1];

// If we have a .map dispatch method, use that.
if (map_service.map) {
layers.push(map_service.map(map_type));
}
// Otherwise, map_service is a layer object.
else {
layers.push(map_service);
}

// workaround for problems with Microsoft layers and vector layer
// drift (see http://openlayers.com/dev/examples/ve-novibrate.html)
Expand Down

0 comments on commit edeb0cc

Please sign in to comment.