Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9503f105a3 | ||
|
|
427bdca611 | ||
|
|
cf9bd5bdf6 | ||
|
|
10316bd247 | ||
|
|
ea5d41a8ad | ||
|
|
cc8833037f |
@@ -4,6 +4,11 @@ Adds a fully-static location field (Leaflet) to manage location-based data witho
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Click on map or drag&drop pin to select location
|
||||||
|
- Reset button & use map-center button
|
||||||
|
- Display selected location or map center coordinates with zoom level
|
||||||
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -33,7 +38,6 @@ class Place(models.Model):
|
|||||||
# attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
# attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||||
# },
|
# },
|
||||||
# 'locate': {
|
# 'locate': {
|
||||||
# 'returnToPrevBounds': True,
|
|
||||||
# 'showPopup': False,
|
# 'showPopup': False,
|
||||||
# },
|
# },
|
||||||
})
|
})
|
||||||
@@ -48,7 +52,7 @@ class Place(models.Model):
|
|||||||
| markerZoom | Initial zoom scale (on load) – if a marker is set. (default: `18`)
|
| markerZoom | Initial zoom scale (on load) – if a marker is set. (default: `18`)
|
||||||
| tileLayer | [TileLayer](https://leafletjs.com/reference.html#tilelayer) urlTemplate (default: `"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"`)
|
| tileLayer | [TileLayer](https://leafletjs.com/reference.html#tilelayer) urlTemplate (default: `"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"`)
|
||||||
| tileOptions | [TileLayer Options](https://leafletjs.com/reference.html#tilelayer-option) (default: `{}`)
|
| tileOptions | [TileLayer Options](https://leafletjs.com/reference.html#tilelayer-option) (default: `{}`)
|
||||||
| locate | [Leaflet.Locate Options](https://github.com/domoritz/leaflet-locatecontrol#possible-options) (default: `{returnToPrevBounds: true, showPopup: false}`)
|
| locate | [Leaflet.Locate Options](https://github.com/domoritz/leaflet-locatecontrol#possible-options) (default: `{showPopup: false}`)
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class MapLocationWidget(Widget):
|
|||||||
|
|
||||||
def get_context(self, name, value, attrs):
|
def get_context(self, name, value, attrs):
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
|
context['id'] = context['widget']['attrs']['id']
|
||||||
context['map_options'] = json.dumps(
|
context['map_options'] = json.dumps(
|
||||||
context['widget']['attrs'].get('options'))
|
context['widget']['attrs'].get('options'))
|
||||||
return context
|
return context
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
function MapLocationInit(mapId, options = {}) {
|
function MapLocationInit(mapId, options = {}) {
|
||||||
const valField = document.getElementById(mapId + '_value');
|
const valField = document.getElementById(mapId + '_value');
|
||||||
const theMap = document.getElementById(mapId + '_map');
|
const theMap = document.getElementById(mapId + '_map');
|
||||||
const resetButton = document.getElementById(mapId + '_reset');
|
const btnAction = document.getElementById(mapId + '_btn');
|
||||||
|
const display = document.getElementById(mapId + '_disp');
|
||||||
|
|
||||||
function isZero(latlng) {
|
function isZero(latlng) {
|
||||||
return latlng.lat === 0 && latlng.lng === 0;
|
return latlng.lat === 0 && latlng.lng === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function asString(latlng) {
|
||||||
|
if (isZero(latlng)) { return ''; }
|
||||||
|
const pos = latlng.wrap();
|
||||||
|
return pos.lat.toFixed(6) + ',' + pos.lng.toFixed(6);
|
||||||
|
}
|
||||||
|
|
||||||
const osm = L.tileLayer(options.tileLayer || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', options.tileOptions);
|
const osm = L.tileLayer(options.tileLayer || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', options.tileOptions);
|
||||||
const map = L.map(mapId + '_map', {
|
const map = L.map(mapId + '_map', {
|
||||||
layers: [osm],
|
layers: [osm],
|
||||||
@@ -14,11 +21,7 @@ function MapLocationInit(mapId, options = {}) {
|
|||||||
zoom: 2,
|
zoom: 2,
|
||||||
...(options.map || {})
|
...(options.map || {})
|
||||||
});
|
});
|
||||||
L.control.locate({
|
L.control.locate({ showPopup: false, ...(options.locate || {}) }).addTo(map);
|
||||||
returnToPrevBounds: true,
|
|
||||||
showPopup: false,
|
|
||||||
...(options.locate || {})
|
|
||||||
}).addTo(map);
|
|
||||||
|
|
||||||
function loadPos() {
|
function loadPos() {
|
||||||
if (!valField.value) {
|
if (!valField.value) {
|
||||||
@@ -27,11 +30,10 @@ function MapLocationInit(mapId, options = {}) {
|
|||||||
return valField.value.split(',');
|
return valField.value.split(',');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const marker = L.marker(loadPos(), { draggable: true }).addTo(map);
|
const marker = L.marker(loadPos(), { draggable: true });
|
||||||
marker.on('move', function (e) {
|
marker.on('move', function (e) {
|
||||||
const pos = map.wrapLatLng(e.latlng);
|
valField.value = asString(e.latlng);
|
||||||
const flag = isZero(pos);
|
updatePrint();
|
||||||
valField.value = flag ? null : pos.lat.toFixed(6) + ',' + pos.lng.toFixed(6);
|
|
||||||
});
|
});
|
||||||
map.on('click', function (e) {
|
map.on('click', function (e) {
|
||||||
if (isZero(marker.getLatLng())) {
|
if (isZero(marker.getLatLng())) {
|
||||||
@@ -39,20 +41,33 @@ function MapLocationInit(mapId, options = {}) {
|
|||||||
setMapState(false);
|
setMapState(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
resetButton.onclick = function () {
|
btnAction.onclick = function () {
|
||||||
marker.setLatLng([0, 0]);
|
const isReset = !!btnAction.dataset.reset;
|
||||||
setMapState(true);
|
marker.setLatLng(isReset ? [0, 0] : map.getCenter());
|
||||||
|
setMapState(isReset ? true : false);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
function setMapState(initial) {
|
function setMapState(initial) {
|
||||||
theMap.style.cursor = initial ? 'crosshair' : null;
|
theMap.style.cursor = initial ? 'crosshair' : null;
|
||||||
marker.setOpacity(initial ? 0 : 1);
|
initial ? marker.remove() : marker.addTo(map);
|
||||||
|
btnAction.dataset.reset = initial ? '' : '1';
|
||||||
|
btnAction.innerText = initial ? 'Set center' : 'Reset';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isZero(marker.getLatLng())) {
|
function updatePrint() {
|
||||||
setMapState(true);
|
const prefix = valField.value
|
||||||
} else {
|
? ('pin: ' + valField.value)
|
||||||
|
: ('center: ' + asString(map.getCenter()));
|
||||||
|
display.innerText = prefix + ' zoom: ' + map.getZoom();
|
||||||
|
}
|
||||||
|
map.on('zoomend', updatePrint);
|
||||||
|
map.on('move', updatePrint);
|
||||||
|
|
||||||
|
setMapState(isZero(marker.getLatLng()));
|
||||||
|
updatePrint();
|
||||||
|
|
||||||
|
if (valField.value) {
|
||||||
map.setView(valField.value.split(','), options.markerZoom || 18);
|
map.setView(valField.value.split(','), options.markerZoom || 18);
|
||||||
}
|
}
|
||||||
// re-center map
|
// re-center map
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<div style="width: 100%">
|
<div style="width: 100%">
|
||||||
<input name="{{ widget.name }}" id="{{ widget.attrs.id }}_value" type="hidden" value="{{ widget.value|default:'' }}" />
|
<input name="{{ widget.name }}" id="{{id}}_value" type="hidden" value="{{ widget.value|default:'' }}" />
|
||||||
<div id="{{ widget.attrs.id }}_map" style="width: 100%; height: 400px"></div>
|
<div id="{{id}}_map" style="width: 100%; height: 400px"></div>
|
||||||
<a href="" id="{{ widget.attrs.id }}_reset">Remove</a>
|
<a href="" id="{{id}}_btn"></a>
|
||||||
|
<span id="{{id}}_disp" style="opacity: 0.5; margin-left: 1em"></span>
|
||||||
<script>
|
<script>
|
||||||
MapLocationInit("{{ widget.attrs.id }}", {{ map_options|safe }});
|
MapLocationInit("{{id}}", {{ map_options|safe }});
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
BIN
screenshot.jpg
BIN
screenshot.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 135 KiB |
2
setup.py
2
setup.py
@@ -6,7 +6,7 @@ with open('README.md', 'r') as f:
|
|||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name='django-map-location',
|
name='django-map-location',
|
||||||
description='Django Map-Location Field',
|
description='Django Map-Location Field',
|
||||||
version='0.9.1',
|
version='0.9.2',
|
||||||
author='relikd',
|
author='relikd',
|
||||||
license='MIT',
|
license='MIT',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
|||||||
Reference in New Issue
Block a user