mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #25004 -- Updated OpenLayers-based widget to OpenLayers 3
Thanks Tim Graham for the review.
This commit is contained in:
parent
f996f73667
commit
2ebfda38e6
@ -80,13 +80,22 @@ class OpenLayersWidget(BaseGeometryWidget):
|
|||||||
template_name = 'gis/openlayers.html'
|
template_name = 'gis/openlayers.html'
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
|
css = {
|
||||||
|
'all': (
|
||||||
|
'https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.1/ol.css',
|
||||||
|
'gis/css/ol3.css',
|
||||||
|
)
|
||||||
|
}
|
||||||
js = (
|
js = (
|
||||||
'https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js',
|
'https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.1/ol.js',
|
||||||
'gis/js/OLMapWidget.js',
|
'gis/js/OLMapWidget.js',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def serialize(self, value):
|
||||||
|
return value.json if value else ''
|
||||||
|
|
||||||
class OSMWidget(BaseGeometryWidget):
|
|
||||||
|
class OSMWidget(OpenLayersWidget):
|
||||||
"""
|
"""
|
||||||
An OpenLayers/OpenStreetMap-based widget.
|
An OpenLayers/OpenStreetMap-based widget.
|
||||||
"""
|
"""
|
||||||
@ -95,12 +104,6 @@ class OSMWidget(BaseGeometryWidget):
|
|||||||
default_lat = 47
|
default_lat = 47
|
||||||
map_srid = 3857
|
map_srid = 3857
|
||||||
|
|
||||||
class Media:
|
|
||||||
js = (
|
|
||||||
'https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js',
|
|
||||||
'gis/js/OLMapWidget.js',
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
super(OSMWidget, self).__init__()
|
super(OSMWidget, self).__init__()
|
||||||
for key in ('default_lon', 'default_lat'):
|
for key in ('default_lon', 'default_lat'):
|
||||||
|
31
django/contrib/gis/static/gis/css/ol3.css
Normal file
31
django/contrib/gis/static/gis/css/ol3.css
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
.switch-type {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0.5em;
|
||||||
|
width: 22px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-Point {
|
||||||
|
background-image: url("../img/draw_point_off.png");
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
.type-Point.type-active {
|
||||||
|
background-image: url("../img/draw_point_on.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-LineString {
|
||||||
|
background-image: url("../img/draw_line_off.png");
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
|
.type-LineString.type-active {
|
||||||
|
background-image: url("../img/draw_line_on.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-Polygon {
|
||||||
|
background-image: url("../img/draw_polygon_off.png");
|
||||||
|
right: 55px;
|
||||||
|
}
|
||||||
|
.type-Polygon.type-active {
|
||||||
|
background-image: url("../img/draw_polygon_on.png");
|
||||||
|
}
|
BIN
django/contrib/gis/static/gis/img/draw_line_off.png
Normal file
BIN
django/contrib/gis/static/gis/img/draw_line_off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
django/contrib/gis/static/gis/img/draw_line_on.png
Normal file
BIN
django/contrib/gis/static/gis/img/draw_line_on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
django/contrib/gis/static/gis/img/draw_point_off.png
Normal file
BIN
django/contrib/gis/static/gis/img/draw_point_off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
django/contrib/gis/static/gis/img/draw_point_on.png
Normal file
BIN
django/contrib/gis/static/gis/img/draw_point_on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
django/contrib/gis/static/gis/img/draw_polygon_off.png
Normal file
BIN
django/contrib/gis/static/gis/img/draw_polygon_off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
django/contrib/gis/static/gis/img/draw_polygon_on.png
Normal file
BIN
django/contrib/gis/static/gis/img/draw_polygon_on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -1,199 +1,59 @@
|
|||||||
/*global OpenLayers*/
|
/* global ol */
|
||||||
(function() {
|
|
||||||
|
var GeometryTypeControl = function(opt_options) {
|
||||||
'use strict';
|
'use strict';
|
||||||
/**
|
// Map control to switch type when geometry type is unknown
|
||||||
* Transforms an array of features to a single feature with the merged
|
var options = opt_options || {};
|
||||||
* geometry of geom_type
|
|
||||||
*/
|
var element = document.createElement('div');
|
||||||
OpenLayers.Util.properFeatures = function(features, geom_type) {
|
element.className = 'switch-type type-' + options.type + ' ol-control ol-unselectable';
|
||||||
if (features.constructor === Array) {
|
if (options.active) {
|
||||||
var geoms = [];
|
element.className += " type-active";
|
||||||
for (var i = 0; i < features.length; i++) {
|
}
|
||||||
geoms.push(features[i].geometry);
|
|
||||||
}
|
var self = this;
|
||||||
var geom = new geom_type(geoms);
|
var switchType = function(e) {
|
||||||
features = new OpenLayers.Feature.Vector(geom);
|
e.preventDefault();
|
||||||
|
if (options.widget.currentGeometryType !== self) {
|
||||||
|
options.widget.map.removeInteraction(options.widget.interactions.draw);
|
||||||
|
options.widget.interactions.draw = new ol.interaction.Draw({
|
||||||
|
features: options.widget.featureCollection,
|
||||||
|
type: options.type
|
||||||
|
});
|
||||||
|
options.widget.map.addInteraction(options.widget.interactions.draw);
|
||||||
|
var className = options.widget.currentGeometryType.element.className.replace(/ type-active/g, '');
|
||||||
|
options.widget.currentGeometryType.element.className = className;
|
||||||
|
options.widget.currentGeometryType = self;
|
||||||
|
element.className += " type-active";
|
||||||
}
|
}
|
||||||
return features;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
element.addEventListener('click', switchType, false);
|
||||||
* @requires OpenLayers/Format/WKT.js
|
element.addEventListener('touchstart', switchType, false);
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
ol.control.Control.call(this, {
|
||||||
* Class: OpenLayers.Format.DjangoWKT
|
element: element
|
||||||
* Class for reading Well-Known Text, with workarounds to successfully parse
|
|
||||||
* geometries and collections as returned by django.contrib.gis.geos.
|
|
||||||
*
|
|
||||||
* Inherits from:
|
|
||||||
* - <OpenLayers.Format.WKT>
|
|
||||||
*/
|
|
||||||
|
|
||||||
OpenLayers.Format.DjangoWKT = OpenLayers.Class(OpenLayers.Format.WKT, {
|
|
||||||
initialize: function(options) {
|
|
||||||
OpenLayers.Format.WKT.prototype.initialize.apply(this, [options]);
|
|
||||||
this.regExes.justComma = /\s*,\s*/;
|
|
||||||
},
|
|
||||||
|
|
||||||
parse: {
|
|
||||||
'point': function(str) {
|
|
||||||
var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);
|
|
||||||
return new OpenLayers.Feature.Vector(
|
|
||||||
new OpenLayers.Geometry.Point(coords[0], coords[1])
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
'multipoint': function(str) {
|
|
||||||
var point;
|
|
||||||
var points = OpenLayers.String.trim(str).split(this.regExes.justComma);
|
|
||||||
var components = [];
|
|
||||||
for(var i = 0, len = points.length; i < len; ++i) {
|
|
||||||
point = points[i].replace(this.regExes.trimParens, '$1');
|
|
||||||
components.push(this.parse.point.apply(this, [point]).geometry);
|
|
||||||
}
|
|
||||||
return new OpenLayers.Feature.Vector(
|
|
||||||
new OpenLayers.Geometry.MultiPoint(components)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
'linestring': function(str) {
|
|
||||||
var points = OpenLayers.String.trim(str).split(',');
|
|
||||||
var components = [];
|
|
||||||
for(var i = 0, len = points.length; i < len; ++i) {
|
|
||||||
components.push(this.parse.point.apply(this, [points[i]]).geometry);
|
|
||||||
}
|
|
||||||
return new OpenLayers.Feature.Vector(
|
|
||||||
new OpenLayers.Geometry.LineString(components)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
'multilinestring': function(str) {
|
|
||||||
var line;
|
|
||||||
var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);
|
|
||||||
var components = [];
|
|
||||||
for(var i = 0, len = lines.length; i < len; ++i) {
|
|
||||||
line = lines[i].replace(this.regExes.trimParens, '$1');
|
|
||||||
components.push(this.parse.linestring.apply(this, [line]).geometry);
|
|
||||||
}
|
|
||||||
return new OpenLayers.Feature.Vector(
|
|
||||||
new OpenLayers.Geometry.MultiLineString(components)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
'polygon': function(str) {
|
|
||||||
var ring, linestring, linearring;
|
|
||||||
var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);
|
|
||||||
var components = [];
|
|
||||||
for(var i = 0, len = rings.length; i < len; ++i) {
|
|
||||||
ring = rings[i].replace(this.regExes.trimParens, '$1');
|
|
||||||
linestring = this.parse.linestring.apply(this, [ring]).geometry;
|
|
||||||
linearring = new OpenLayers.Geometry.LinearRing(linestring.components);
|
|
||||||
components.push(linearring);
|
|
||||||
}
|
|
||||||
return new OpenLayers.Feature.Vector(
|
|
||||||
new OpenLayers.Geometry.Polygon(components)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
'multipolygon': function(str) {
|
|
||||||
var polygon;
|
|
||||||
var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);
|
|
||||||
var components = [];
|
|
||||||
for(var i = 0, len = polygons.length; i < len; ++i) {
|
|
||||||
polygon = polygons[i].replace(this.regExes.trimParens, '$1');
|
|
||||||
components.push(this.parse.polygon.apply(this, [polygon]).geometry);
|
|
||||||
}
|
|
||||||
return new OpenLayers.Feature.Vector(
|
|
||||||
new OpenLayers.Geometry.MultiPolygon(components)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
'geometrycollection': function(str) {
|
|
||||||
// separate components of the collection with |
|
|
||||||
str = str.replace(/,\s*([A-Za-z])/g, '|$1');
|
|
||||||
var wktArray = OpenLayers.String.trim(str).split('|');
|
|
||||||
var components = [];
|
|
||||||
for(var i = 0, len = wktArray.length; i < len; ++i) {
|
|
||||||
components.push(OpenLayers.Format.WKT.prototype.read.apply(this, [wktArray[i]]));
|
|
||||||
}
|
|
||||||
return components;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
extractGeometry: function(geometry) {
|
|
||||||
var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
|
|
||||||
if (!this.extract[type]) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (this.internalProjection && this.externalProjection) {
|
|
||||||
geometry = geometry.clone();
|
|
||||||
geometry.transform(this.internalProjection, this.externalProjection);
|
|
||||||
}
|
|
||||||
var wktType = type === 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase();
|
|
||||||
var data = wktType + '(' + this.extract[type].apply(this, [geometry]) + ')';
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Patched write: successfully writes WKT for geometries and
|
|
||||||
* geometrycollections.
|
|
||||||
*/
|
|
||||||
write: function(features) {
|
|
||||||
var collection, isCollection;
|
|
||||||
isCollection = features.geometry.CLASS_NAME === "OpenLayers.Geometry.Collection";
|
|
||||||
var pieces = [];
|
|
||||||
if (isCollection) {
|
|
||||||
collection = features.geometry.components;
|
|
||||||
pieces.push('GEOMETRYCOLLECTION(');
|
|
||||||
for (var i = 0, len = collection.length; i < len; ++i) {
|
|
||||||
if (i > 0) {
|
|
||||||
pieces.push(',');
|
|
||||||
}
|
|
||||||
pieces.push(this.extractGeometry(collection[i]));
|
|
||||||
}
|
|
||||||
pieces.push(')');
|
|
||||||
} else {
|
|
||||||
pieces.push(this.extractGeometry(features.geometry));
|
|
||||||
}
|
|
||||||
return pieces.join('');
|
|
||||||
},
|
|
||||||
|
|
||||||
CLASS_NAME: "OpenLayers.Format.DjangoWKT"
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
ol.inherits(GeometryTypeControl, ol.control.Control);
|
||||||
|
|
||||||
|
// TODO: allow deleting individual features (#8972)
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var jsonFormat = new ol.format.GeoJSON();
|
||||||
|
|
||||||
function MapWidget(options) {
|
function MapWidget(options) {
|
||||||
this.map = null;
|
this.map = null;
|
||||||
this.controls = null;
|
this.interactions = {draw: null, modify: null};
|
||||||
this.panel = null;
|
this.typeChoices = false;
|
||||||
this.layers = {};
|
this.ready = false;
|
||||||
this.wkt_f = new OpenLayers.Format.DjangoWKT();
|
|
||||||
|
|
||||||
// Mapping from OGRGeomType name to OpenLayers.Geometry name
|
|
||||||
if (options.geom_name === 'Unknown') {
|
|
||||||
options.geom_type = OpenLayers.Geometry;
|
|
||||||
} else if (options.geom_name === 'GeometryCollection') {
|
|
||||||
options.geom_type = OpenLayers.Geometry.Collection;
|
|
||||||
} else {
|
|
||||||
options.geom_type = OpenLayers.Geometry[options.geom_name];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default options
|
// Default options
|
||||||
this.options = {
|
this.options = {
|
||||||
color: 'ee9900',
|
|
||||||
default_lat: 0,
|
default_lat: 0,
|
||||||
default_lon: 0,
|
default_lon: 0,
|
||||||
default_zoom: 4,
|
default_zoom: 12,
|
||||||
is_collection: options.geom_name.indexOf('Multi') > -1 || options.geom_name.indexOf('Collection') > -1,
|
is_collection: options.geom_name.indexOf('Multi') > -1 || options.geom_name.indexOf('Collection') > -1
|
||||||
layerswitcher: false,
|
|
||||||
map_options: {},
|
|
||||||
map_srid: 4326,
|
|
||||||
modifiable: true,
|
|
||||||
mouse_position: false,
|
|
||||||
opacity: 0.4,
|
|
||||||
point_zoom: 12,
|
|
||||||
scale_text: false,
|
|
||||||
scrollable: true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Altering using user-provided options
|
// Altering using user-provided options
|
||||||
@ -202,185 +62,170 @@
|
|||||||
this.options[property] = options[property];
|
this.options[property] = options[property];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!options.base_layer) {
|
||||||
this.map = this.create_map();
|
this.options.base_layer = new ol.layer.Tile({source: new ol.source.OSM()});
|
||||||
|
|
||||||
var defaults_style = {
|
|
||||||
'fillColor': '#' + this.options.color,
|
|
||||||
'fillOpacity': this.options.opacity,
|
|
||||||
'strokeColor': '#' + this.options.color
|
|
||||||
};
|
|
||||||
if (this.options.geom_name === 'LineString') {
|
|
||||||
defaults_style.strokeWidth = 3;
|
|
||||||
}
|
}
|
||||||
var styleMap = new OpenLayers.StyleMap({'default': OpenLayers.Util.applyDefaults(defaults_style, OpenLayers.Feature.Vector.style.default)});
|
|
||||||
this.layers.vector = new OpenLayers.Layer.Vector(" " + this.options.name, {styleMap: styleMap});
|
this.map = this.createMap();
|
||||||
this.map.addLayer(this.layers.vector);
|
this.featureCollection = new ol.Collection();
|
||||||
var wkt = document.getElementById(this.options.id).value;
|
this.featureOverlay = new ol.layer.Vector({
|
||||||
if (wkt) {
|
map: this.map,
|
||||||
var feat = OpenLayers.Util.properFeatures(this.read_wkt(wkt), this.options.geom_type);
|
source: new ol.source.Vector({
|
||||||
this.write_wkt(feat);
|
features: this.featureCollection,
|
||||||
if (this.options.is_collection) {
|
useSpatialIndex: false // improve performance
|
||||||
for (var i = 0; i < this.num_geom; i++) {
|
}),
|
||||||
this.layers.vector.addFeatures([new OpenLayers.Feature.Vector(feat.geometry.components[i].clone())]);
|
updateWhileAnimating: true, // optional, for instant visual feedback
|
||||||
|
updateWhileInteracting: true // optional, for instant visual feedback
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate and set handlers for the feature container
|
||||||
|
var self = this;
|
||||||
|
this.featureCollection.on('add', function(event) {
|
||||||
|
var feature = event.element;
|
||||||
|
feature.on('change', function() {
|
||||||
|
self.serializeFeatures();
|
||||||
|
});
|
||||||
|
if (self.ready) {
|
||||||
|
self.serializeFeatures();
|
||||||
|
if (!self.options.is_collection) {
|
||||||
|
self.disableDrawing(); // Only allow one feature at a time
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.layers.vector.addFeatures([feat]);
|
|
||||||
}
|
}
|
||||||
this.map.zoomToExtent(feat.geometry.getBounds());
|
});
|
||||||
if (this.options.geom_name === 'Point') {
|
|
||||||
this.map.zoomTo(this.options.point_zoom);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.map.setCenter(this.defaultCenter(), this.options.default_zoom);
|
|
||||||
}
|
|
||||||
this.layers.vector.events.on({'featuremodified': this.modify_wkt, scope: this});
|
|
||||||
this.layers.vector.events.on({'featureadded': this.add_wkt, scope: this});
|
|
||||||
|
|
||||||
this.getControls(this.layers.vector);
|
var initial_value = document.getElementById(this.options.id).value;
|
||||||
this.panel.addControls(this.controls);
|
if (initial_value) {
|
||||||
this.map.addControl(this.panel);
|
var features = jsonFormat.readFeatures('{"type": "Feature", "geometry": ' + initial_value + '}');
|
||||||
this.addSelectControl();
|
var extent = ol.extent.createEmpty();
|
||||||
|
features.forEach(function(feature) {
|
||||||
if (this.options.mouse_position) {
|
this.featureOverlay.getSource().addFeature(feature);
|
||||||
this.map.addControl(new OpenLayers.Control.MousePosition());
|
ol.extent.extend(extent, feature.getGeometry().getExtent());
|
||||||
}
|
}, this);
|
||||||
if (this.options.scale_text) {
|
// Center/zoom the map
|
||||||
this.map.addControl(new OpenLayers.Control.Scale());
|
this.map.getView().fit(extent, this.map.getSize(), {maxZoom: this.options.default_zoom});
|
||||||
}
|
|
||||||
if (this.options.layerswitcher) {
|
|
||||||
this.map.addControl(new OpenLayers.Control.LayerSwitcher());
|
|
||||||
}
|
|
||||||
if (!this.options.scrollable) {
|
|
||||||
this.map.getControlsByClass('OpenLayers.Control.Navigation')[0].disableZoomWheel();
|
|
||||||
}
|
|
||||||
if (wkt) {
|
|
||||||
if (this.options.modifiable) {
|
|
||||||
this.enableEditing();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.enableDrawing();
|
this.map.getView().setCenter(this.defaultCenter());
|
||||||
}
|
}
|
||||||
|
this.createInteractions();
|
||||||
|
if (initial_value && !this.options.is_collection) {
|
||||||
|
this.disableDrawing();
|
||||||
|
}
|
||||||
|
this.ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapWidget.prototype.create_map = function() {
|
MapWidget.prototype.createMap = function() {
|
||||||
var map = new OpenLayers.Map(this.options.map_id, this.options.map_options);
|
var map = new ol.Map({
|
||||||
if (this.options.base_layer) {
|
target: this.options.map_id,
|
||||||
this.layers.base = this.options.base_layer;
|
layers: [this.options.base_layer],
|
||||||
} else {
|
view: new ol.View({
|
||||||
this.layers.base = new OpenLayers.Layer.WMS('OpenLayers WMS', 'http://vmap0.tiles.osgeo.org/wms/vmap0', {layers: 'basic'});
|
zoom: this.options.default_zoom
|
||||||
}
|
})
|
||||||
map.addLayer(this.layers.base);
|
});
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
|
||||||
MapWidget.prototype.get_ewkt = function(feat) {
|
MapWidget.prototype.createInteractions = function() {
|
||||||
return "SRID=" + this.options.map_srid + ";" + this.wkt_f.write(feat);
|
// Initialize the modify interaction
|
||||||
};
|
this.interactions.modify = new ol.interaction.Modify({
|
||||||
|
features: this.featureCollection,
|
||||||
MapWidget.prototype.read_wkt = function(wkt) {
|
deleteCondition: function(event) {
|
||||||
var prefix = 'SRID=' + this.options.map_srid + ';';
|
return ol.events.condition.shiftKeyOnly(event) &&
|
||||||
if (wkt.indexOf(prefix) === 0) {
|
ol.events.condition.singleClick(event);
|
||||||
wkt = wkt.slice(prefix.length);
|
|
||||||
}
|
|
||||||
return this.wkt_f.read(wkt);
|
|
||||||
};
|
|
||||||
|
|
||||||
MapWidget.prototype.write_wkt = function(feat) {
|
|
||||||
feat = OpenLayers.Util.properFeatures(feat, this.options.geom_type);
|
|
||||||
if (this.options.is_collection) {
|
|
||||||
this.num_geom = feat.geometry.components.length;
|
|
||||||
} else {
|
|
||||||
this.num_geom = 1;
|
|
||||||
}
|
|
||||||
document.getElementById(this.options.id).value = this.get_ewkt(feat);
|
|
||||||
};
|
|
||||||
|
|
||||||
MapWidget.prototype.add_wkt = function(event) {
|
|
||||||
if (this.options.is_collection) {
|
|
||||||
var feat = new OpenLayers.Feature.Vector(new this.options.geom_type());
|
|
||||||
for (var i = 0; i < this.layers.vector.features.length; i++) {
|
|
||||||
feat.geometry.addComponents([this.layers.vector.features[i].geometry]);
|
|
||||||
}
|
}
|
||||||
this.write_wkt(feat);
|
});
|
||||||
} else {
|
|
||||||
if (this.layers.vector.features.length > 1) {
|
// Initialize the draw interaction
|
||||||
var old_feats = [this.layers.vector.features[0]];
|
var geomType = this.options.geom_name;
|
||||||
this.layers.vector.removeFeatures(old_feats);
|
if (geomType === "Unknown" || geomType === "GeometryCollection") {
|
||||||
this.layers.vector.destroyFeatures(old_feats);
|
// Default to Point, but create icons to switch type
|
||||||
}
|
geomType = "Point";
|
||||||
this.write_wkt(event.feature);
|
this.currentGeometryType = new GeometryTypeControl({widget: this, type: "Point", active: true});
|
||||||
|
this.map.addControl(this.currentGeometryType);
|
||||||
|
this.map.addControl(new GeometryTypeControl({widget: this, type: "LineString", active: false}));
|
||||||
|
this.map.addControl(new GeometryTypeControl({widget: this, type: "Polygon", active: false}));
|
||||||
|
this.typeChoices = true;
|
||||||
}
|
}
|
||||||
};
|
this.interactions.draw = new ol.interaction.Draw({
|
||||||
|
features: this.featureCollection,
|
||||||
|
type: geomType
|
||||||
|
});
|
||||||
|
|
||||||
MapWidget.prototype.modify_wkt = function(event) {
|
this.map.addInteraction(this.interactions.draw);
|
||||||
if (this.options.is_collection) {
|
this.map.addInteraction(this.interactions.modify);
|
||||||
if (this.options.geom_name === 'MultiPoint') {
|
|
||||||
this.add_wkt(event);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
var feat = new OpenLayers.Feature.Vector(new this.options.geom_type());
|
|
||||||
for (var i = 0; i < this.num_geom; i++) {
|
|
||||||
feat.geometry.addComponents([this.layers.vector.features[i].geometry]);
|
|
||||||
}
|
|
||||||
this.write_wkt(feat);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.write_wkt(event.feature);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MapWidget.prototype.deleteFeatures = function() {
|
|
||||||
this.layers.vector.removeFeatures(this.layers.vector.features);
|
|
||||||
this.layers.vector.destroyFeatures();
|
|
||||||
};
|
|
||||||
|
|
||||||
MapWidget.prototype.clearFeatures = function() {
|
|
||||||
this.deleteFeatures();
|
|
||||||
document.getElementById(this.options.id).value = '';
|
|
||||||
this.map.setCenter(this.defaultCenter(), this.options.default_zoom);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MapWidget.prototype.defaultCenter = function() {
|
MapWidget.prototype.defaultCenter = function() {
|
||||||
var center = new OpenLayers.LonLat(this.options.default_lon, this.options.default_lat);
|
var center = [this.options.default_lon, this.options.default_lat];
|
||||||
if (this.options.map_srid) {
|
if (this.options.map_srid) {
|
||||||
return center.transform(new OpenLayers.Projection("EPSG:4326"), this.map.getProjectionObject());
|
return ol.proj.transform(center, 'EPSG:4326', this.map.getView().getProjection());
|
||||||
}
|
}
|
||||||
return center;
|
return center;
|
||||||
};
|
};
|
||||||
|
|
||||||
MapWidget.prototype.addSelectControl = function() {
|
|
||||||
var select = new OpenLayers.Control.SelectFeature(this.layers.vector, {'toggle': true, 'clickout': true});
|
|
||||||
this.map.addControl(select);
|
|
||||||
select.activate();
|
|
||||||
};
|
|
||||||
|
|
||||||
MapWidget.prototype.enableDrawing = function() {
|
MapWidget.prototype.enableDrawing = function() {
|
||||||
this.map.getControlsByClass('OpenLayers.Control.DrawFeature')[0].activate();
|
this.interactions.draw.setActive(true);
|
||||||
|
if (this.typeChoices) {
|
||||||
|
// Show geometry type icons
|
||||||
|
var divs = document.getElementsByClassName("switch-type");
|
||||||
|
for (var i = 0; i !== divs.length; i++) {
|
||||||
|
divs[i].style.visibility = "visible";
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MapWidget.prototype.enableEditing = function() {
|
MapWidget.prototype.disableDrawing = function() {
|
||||||
this.map.getControlsByClass('OpenLayers.Control.ModifyFeature')[0].activate();
|
if (this.interactions.draw) {
|
||||||
|
this.interactions.draw.setActive(false);
|
||||||
|
if (this.typeChoices) {
|
||||||
|
// Hide geometry type icons
|
||||||
|
var divs = document.getElementsByClassName("switch-type");
|
||||||
|
for (var i = 0; i !== divs.length; i++) {
|
||||||
|
divs[i].style.visibility = "hidden";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MapWidget.prototype.getControls = function(layer) {
|
MapWidget.prototype.clearFeatures = function() {
|
||||||
this.panel = new OpenLayers.Control.Panel({'displayClass': 'olControlEditingToolbar'});
|
this.featureCollection.clear();
|
||||||
this.controls = [new OpenLayers.Control.Navigation()];
|
// Empty textarea widget
|
||||||
if (!this.options.modifiable && layer.features.length) {
|
document.getElementById(this.options.id).value = '';
|
||||||
return;
|
this.enableDrawing();
|
||||||
}
|
|
||||||
if (this.options.geom_name.indexOf('LineString') >= 0 || this.options.geom_name === 'GeometryCollection' || this.options.geom_name === 'Unknown') {
|
|
||||||
this.controls.push(new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'}));
|
|
||||||
}
|
|
||||||
if (this.options.geom_name.indexOf('Polygon') >= 0 || this.options.geom_name === 'GeometryCollection' || this.options.geom_name === 'Unknown') {
|
|
||||||
this.controls.push(new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'}));
|
|
||||||
}
|
|
||||||
if (this.options.geom_name.indexOf('Point') >= 0 || this.options.geom_name === 'GeometryCollection' || this.options.geom_name === 'Unknown') {
|
|
||||||
this.controls.push(new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'}));
|
|
||||||
}
|
|
||||||
if (this.options.modifiable) {
|
|
||||||
this.controls.push(new OpenLayers.Control.ModifyFeature(layer, {'displayClass': 'olControlModifyFeature'}));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MapWidget.prototype.serializeFeatures = function() {
|
||||||
|
// Three use cases: GeometryCollection, multigeometries, and single geometry
|
||||||
|
var geometry = null;
|
||||||
|
var features = this.featureOverlay.getSource().getFeatures();
|
||||||
|
if (this.options.is_collection) {
|
||||||
|
if (this.options.geom_name === "GeometryCollection") {
|
||||||
|
var geometries = [];
|
||||||
|
for (var i = 0; i < features.length; i++) {
|
||||||
|
geometries.push(features[i].getGeometry());
|
||||||
|
}
|
||||||
|
geometry = new ol.geom.GeometryCollection(geometries);
|
||||||
|
} else {
|
||||||
|
geometry = features[0].getGeometry().clone();
|
||||||
|
for (var j = 1; j < features.length; j++) {
|
||||||
|
switch(geometry.getType()) {
|
||||||
|
case "MultiPoint":
|
||||||
|
geometry.appendPoint(features[j].getGeometry().getPoint(0));
|
||||||
|
break;
|
||||||
|
case "MultiLineString":
|
||||||
|
geometry.appendLineString(features[j].getGeometry().getLineString(0));
|
||||||
|
break;
|
||||||
|
case "MultiPolygon":
|
||||||
|
geometry.appendPolygon(features[j].getGeometry().getPolygon(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (features[0]) {
|
||||||
|
geometry = features[0].getGeometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById(this.options.id).value = jsonFormat.writeGeometry(geometry);
|
||||||
|
};
|
||||||
|
|
||||||
window.MapWidget = MapWidget;
|
window.MapWidget = MapWidget;
|
||||||
})();
|
})();
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
{% extends "gis/openlayers.html" %}
|
{% extends "gis/openlayers.html" %}
|
||||||
{% load l10n %}
|
{% load l10n %}
|
||||||
|
|
||||||
{% block map_options %}var map_options = {
|
|
||||||
maxExtend: new OpenLayers.Bounds(-20037508,-20037508,20037508,20037508),
|
|
||||||
maxResolution: 156543.0339,
|
|
||||||
numZoomLevels: 20,
|
|
||||||
units: 'm'
|
|
||||||
};{% endblock %}
|
|
||||||
|
|
||||||
{% block options %}{{ block.super }}
|
{% block options %}{{ block.super }}
|
||||||
options['scale_text'] = true;
|
|
||||||
options['mouse_position'] = true;
|
|
||||||
options['default_lon'] = {{ default_lon|unlocalize }};
|
options['default_lon'] = {{ default_lon|unlocalize }};
|
||||||
options['default_lat'] = {{ default_lat|unlocalize }};
|
options['default_lat'] = {{ default_lat|unlocalize }};
|
||||||
options['base_layer'] = new OpenLayers.Layer.OSM("OpenStreetMap (Mapnik)");
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block base_layer %}
|
||||||
|
var base_layer = new ol.layer.Tile({source: new ol.source.OSM()});
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,27 +1,32 @@
|
|||||||
{% load i18n l10n static %}
|
{% load i18n l10n %}
|
||||||
<style type="text/css">{% block map_css %}{% get_current_language_bidi as LANGUAGE_BIDI %}
|
<style type="text/css">{% block map_css %}{% get_current_language_bidi as LANGUAGE_BIDI %}
|
||||||
#{{ id }}_map { width: {{ map_width }}px; height: {{ map_height }}px; }
|
#{{ id }}_map { width: {{ map_width }}px; height: {{ map_height }}px; }
|
||||||
#{{ id }}_map .aligned label { float: inherit; }
|
#{{ id }}_map .aligned label { float: inherit; }
|
||||||
#{{ id }}_div_map { position: relative; vertical-align: top; float: {{ LANGUAGE_BIDI|yesno:"right,left" }}; }
|
#{{ id }}_div_map { position: relative; vertical-align: top; float: {{ LANGUAGE_BIDI|yesno:"right,left" }}; }
|
||||||
{% if not display_raw %}#{{ id }} { display: none; }{% endif %}
|
{% if not display_raw %}#{{ id }} { display: none; }{% endif %}
|
||||||
.olControlEditingToolbar .olControlModifyFeatureItemActive {
|
{% endblock %}
|
||||||
background-image: url("{% static "admin/img/gis/move_vertex_on.svg" %}");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.olControlEditingToolbar .olControlModifyFeatureItemInactive {
|
|
||||||
background-image: url("{% static "admin/img/gis/move_vertex_off.svg" %}");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}{% endblock %}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="{{ id }}_div_map">
|
<div id="{{ id }}_div_map">
|
||||||
<div id="{{ id }}_map"></div>
|
<div id="{{ id }}_map"></div>
|
||||||
<span class="clear_features"><a href="javascript:{{ module }}.clearFeatures()">{% trans "Delete all Features" %}</a></span>
|
{% if not disabled %}<span class="clear_features"><a href="javascript:{{ module }}.clearFeatures()">{% trans "Delete all Features" %}</a></span>{% endif %}
|
||||||
{% if display_raw %}<p>{% trans "Debugging window (serialized value)" %}</p>{% endif %}
|
{% if display_raw %}<p>{% trans "Debugging window (serialized value)" %}</p>{% endif %}
|
||||||
<textarea id="{{ id }}" class="vSerializedField required" cols="150" rows="10" name="{{ name }}">{{ serialized }}</textarea>
|
<textarea id="{{ id }}" class="vSerializedField required" cols="150" rows="10" name="{{ name }}">{{ serialized }}</textarea>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
{% block map_options %}var map_options = {};{% endblock %}
|
{% block map_options %}var map_options = {};{% endblock %}
|
||||||
|
{% block base_layer %}
|
||||||
|
var base_layer = new ol.layer.Tile({
|
||||||
|
source: new ol.source.XYZ({
|
||||||
|
attributions: "NASA Worldview",
|
||||||
|
maxZoom: 8,
|
||||||
|
url: "https://map1{a-c}.vis.earthdata.nasa.gov/wmts-webmerc/" +
|
||||||
|
"BlueMarble_ShadedRelief_Bathymetry/default/%7BTime%7D/" +
|
||||||
|
"GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpg"
|
||||||
|
})
|
||||||
|
});
|
||||||
|
{% endblock %}
|
||||||
{% block options %}var options = {
|
{% block options %}var options = {
|
||||||
|
base_layer: base_layer,
|
||||||
geom_name: '{{ geom_type }}',
|
geom_name: '{{ geom_type }}',
|
||||||
id: '{{ id }}',
|
id: '{{ id }}',
|
||||||
map_id: '{{ id }}_map',
|
map_id: '{{ id }}_map',
|
||||||
|
@ -164,18 +164,25 @@ Widget classes
|
|||||||
isn't suitable for production use since it offers no guaranteed uptime
|
isn't suitable for production use since it offers no guaranteed uptime
|
||||||
and runs on a slow server.
|
and runs on a slow server.
|
||||||
|
|
||||||
.. _tailored to your needs: http://docs.openlayers.org/library/deploying.html
|
Also, the widget nows uses OpenLayers 3 instead of OpenLayers 2.
|
||||||
|
|
||||||
|
.. _tailored to your needs: http://openlayers.org/en/latest/doc/tutorials/custom-builds.html
|
||||||
|
|
||||||
``OSMWidget``
|
``OSMWidget``
|
||||||
|
|
||||||
.. class:: OSMWidget
|
.. class:: OSMWidget
|
||||||
|
|
||||||
This widget uses an OpenStreetMap base layer (Mapnik) to display geographic
|
This widget uses an OpenStreetMap base layer to display geographic objects
|
||||||
objects on.
|
on. ``template_name`` is ``gis/openlayers-osm.html``.
|
||||||
``template_name`` is ``gis/openlayers-osm.html``.
|
|
||||||
|
|
||||||
The :class:`OpenLayersWidget` note about JavaScript file hosting above also
|
The :class:`OpenLayersWidget` note about JavaScript file hosting above also
|
||||||
applies here. See also this `FAQ answer`_ about ``https`` access to map
|
applies here. See also this `FAQ answer`_ about ``https`` access to map
|
||||||
tiles.
|
tiles.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.11
|
||||||
|
|
||||||
|
OpenLayers 2.x has been dropped in favor of OpenLayers 3. If you extend
|
||||||
|
the ``gis/openlayers-osm.html`` template, please review your custom
|
||||||
|
template.
|
||||||
|
|
||||||
.. _FAQ answer: https://help.openstreetmap.org/questions/10920/how-to-embed-a-map-in-my-https-site
|
.. _FAQ answer: https://help.openstreetmap.org/questions/10920/how-to-embed-a-map-in-my-https-site
|
||||||
|
@ -165,7 +165,8 @@ Minor features
|
|||||||
|
|
||||||
* The OpenLayers-based form widgets now use ``OpenLayers.js`` from
|
* The OpenLayers-based form widgets now use ``OpenLayers.js`` from
|
||||||
``https://cdnjs.cloudflare.com`` which is more suitable for production use
|
``https://cdnjs.cloudflare.com`` which is more suitable for production use
|
||||||
than the the old ``http://openlayers.org`` source.
|
than the the old ``http://openlayers.org`` source. They are also updated to
|
||||||
|
use OpenLayers 3.
|
||||||
|
|
||||||
* PostGIS migrations can now change field dimensions.
|
* PostGIS migrations can now change field dimensions.
|
||||||
|
|
||||||
@ -469,6 +470,11 @@ Backwards incompatible changes in 1.11
|
|||||||
|
|
||||||
* The ``GEOSGeometry`` equality operator now also compares SRID.
|
* The ``GEOSGeometry`` equality operator now also compares SRID.
|
||||||
|
|
||||||
|
* The OpenLayers-based form widgets now use OpenLayers 3, and the
|
||||||
|
``gis/openlayers.html`` and ``gis/openlayers-osm.html`` templates have been
|
||||||
|
updated. Check your project if you subclass these widgets or extend the
|
||||||
|
templates.
|
||||||
|
|
||||||
Database backend API
|
Database backend API
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -7,42 +7,58 @@ QUnit.module('gis.OLMapWidget');
|
|||||||
QUnit.test('MapWidget.featureAdded', function(assert) {
|
QUnit.test('MapWidget.featureAdded', function(assert) {
|
||||||
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
||||||
var widget = new MapWidget(options);
|
var widget = new MapWidget(options);
|
||||||
assert.equal(widget.layers.vector.features.length, 1);
|
assert.equal(widget.featureCollection.getLength(), 1);
|
||||||
|
widget.serializeFeatures();
|
||||||
assert.equal(
|
assert.equal(
|
||||||
widget.layers.vector.features[0].geometry.toString(),
|
document.getElementById('id_point').value,
|
||||||
'POINT(7.8177 47.397)',
|
'{"type":"Point","coordinates":[7.8177,47.397]}',
|
||||||
'Point addded to vector layer'
|
'Point added to vector layer'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('MapWidget.map_srid', function(assert) {
|
QUnit.test('MapWidget.map_srid', function(assert) {
|
||||||
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
||||||
var widget = new MapWidget(options);
|
var widget = new MapWidget(options);
|
||||||
assert.equal(widget.options.map_srid, 4326, 'SRID 4326');
|
assert.equal(widget.map.getView().getProjection().getCode(), 'EPSG:3857', 'SRID 3857');
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('MapWidget.defaultCenter', function(assert) {
|
QUnit.test('MapWidget.defaultCenter', function(assert) {
|
||||||
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
||||||
var widget = new MapWidget(options);
|
var widget = new MapWidget(options);
|
||||||
assert.equal(widget.defaultCenter().toString(), 'lon=0,lat=0', 'Default center at 0, 0');
|
assert.equal(widget.defaultCenter().toString(), '0,0', 'Default center at 0, 0');
|
||||||
options.default_lat = 47.08;
|
options.default_lat = 47.08;
|
||||||
options.default_lon = 6.81;
|
options.default_lon = 6.81;
|
||||||
widget = new MapWidget(options);
|
widget = new MapWidget(options);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
widget.defaultCenter().toString(),
|
widget.defaultCenter().toString(),
|
||||||
'lon=6.81,lat=47.08',
|
'6.81,47.08',
|
||||||
'Default center at 6.81, 47.08'
|
'Default center at 6.81, 47.08'
|
||||||
);
|
);
|
||||||
|
assert.equal(widget.map.getView().getZoom(), 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('MapWidget.getControls', function(assert) {
|
QUnit.test('MapWidget.interactions', function(assert) {
|
||||||
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
||||||
var widget = new MapWidget(options);
|
var widget = new MapWidget(options);
|
||||||
widget.getControls(widget.layers.vector);
|
assert.equal(Object.keys(widget.interactions).length, 2);
|
||||||
assert.equal(widget.controls.length, 3);
|
assert.equal(widget.interactions.draw.getActive(), false, "Draw is inactive with an existing point");
|
||||||
assert.equal(widget.controls[0].displayClass, 'olControlNavigation', 'Navigation control');
|
assert.equal(widget.interactions.modify.getActive(), true, "Modify is active with an existing point");
|
||||||
assert.equal(widget.controls[1].displayClass, 'olControlDrawFeaturePoint', 'Draw control');
|
});
|
||||||
assert.equal(widget.controls[2].displayClass, 'olControlModifyFeature', 'Modify control');
|
|
||||||
|
QUnit.test('MapWidget.clearFeatures', function(assert) {
|
||||||
|
var options = {id: 'id_point', map_id: 'id_point_map', geom_name: 'Point'};
|
||||||
|
var widget = new MapWidget(options);
|
||||||
|
var initial_value = document.getElementById('id_point').value;
|
||||||
|
widget.clearFeatures();
|
||||||
|
assert.equal(document.getElementById('id_point').value, "");
|
||||||
|
document.getElementById('id_point').value = initial_value;
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test('MapWidget.multipolygon', function(assert) {
|
||||||
|
var options = {id: 'id_multipolygon', map_id: 'id_multipolygon_map', geom_name: 'MultiPolygon'};
|
||||||
|
var widget = new MapWidget(options);
|
||||||
|
assert.ok(widget.options.is_collection);
|
||||||
|
assert.equal(widget.interactions.draw.getActive(), true, "Draw is active with no existing content");
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('MapWidget.IsCollection', function(assert) {
|
QUnit.test('MapWidget.IsCollection', function(assert) {
|
||||||
|
@ -77,12 +77,16 @@
|
|||||||
<script src='../django/contrib/admin/static/admin/js/prepopulate.js' data-cover></script>
|
<script src='../django/contrib/admin/static/admin/js/prepopulate.js' data-cover></script>
|
||||||
<script src='../django/contrib/admin/static/admin/js/urlify.js' data-cover></script>
|
<script src='../django/contrib/admin/static/admin/js/urlify.js' data-cover></script>
|
||||||
|
|
||||||
<div id="id_point_map">
|
<div id="id_point_map" style="display:none;">
|
||||||
<textarea id="id_point" name="point"
|
<textarea id="id_point" name="point" class="vSerializedField required"
|
||||||
class="vSerializedField required" style="display:none;"
|
style="display:none;" rows="10" cols="150"
|
||||||
rows="10" cols="150">POINT (7.8177 47.397)</textarea>
|
>{"type": "Point", "coordinates": [7.8177, 47.397]}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js'></script>
|
<div id="id_multipolygon_map" style="display:none;">
|
||||||
|
<textarea id="id_multipolygon" name="multipolygon" class="vSerializedField required"
|
||||||
|
style="display:none;" rows="10" cols="150"></textarea>
|
||||||
|
</div>
|
||||||
|
<script src='https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.0/ol.js'></script>
|
||||||
<script src='../django/contrib/gis/static/gis/js/OLMapWidget.js' data-cover></script>
|
<script src='../django/contrib/gis/static/gis/js/OLMapWidget.js' data-cover></script>
|
||||||
<script src='./gis/mapwidget.test.js'></script>
|
<script src='./gis/mapwidget.test.js'></script>
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ class SpecializedFieldTest(SimpleTestCase):
|
|||||||
|
|
||||||
self.assertIn('<textarea ', rendered)
|
self.assertIn('<textarea ', rendered)
|
||||||
self.assertIn('required', rendered)
|
self.assertIn('required', rendered)
|
||||||
self.assertIn(geom.wkt, rendered)
|
self.assertIn(escape(geom.json), rendered)
|
||||||
|
|
||||||
# map_srid in operlayers.html template must not be localized.
|
# map_srid in operlayers.html template must not be localized.
|
||||||
@override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True)
|
@override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True)
|
||||||
@ -318,7 +318,7 @@ class OSMWidgetTest(SimpleTestCase):
|
|||||||
form = PointForm(data={'p': geom})
|
form = PointForm(data={'p': geom})
|
||||||
rendered = form.as_p()
|
rendered = form.as_p()
|
||||||
|
|
||||||
self.assertIn("OpenStreetMap (Mapnik)", rendered)
|
self.assertIn("ol.source.OSM()", rendered)
|
||||||
self.assertIn("id: 'id_p',", rendered)
|
self.assertIn("id: 'id_p',", rendered)
|
||||||
|
|
||||||
def test_default_lat_lon(self):
|
def test_default_lat_lon(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user