Hello everyone…
I just want to inform you that I managed to achieve everything I mentioned above by using an HTML field and creating the map just like in the Geolocation field but without all the controls except the locate and refresh buttons…
And instead of using the marker control, I implemented a map click event handler to remove previous marker if any exist and create a new marker using the new coordinates…
I also managed to make the marker draggable which makes it easier to change the location just by repositioning the marker…
This is my modified map code…
// Geolocation field
let map_field = frm.get_field('location'),
// HTML field
html_field = frm.get_field('location_html'),
map_id = frappe.dom.get_unique_id();
// Setup the HTML field, just like the Geolocation field
html_field.$wrapper.removeClass('form-group').append('\
<div class="form-group">\
<div class="clearfix">\
<label class="control-label" style="padding-right: 0px;">\
' + __(map_field.df.label) + '\
</label>\
</div>\
<div class="control-input-wrapper">\
<p class="help-box small text-muted text-center">\
' + __('(Click on the map to mark a location)') + '\
</p>\
<div class="map-wrapper border">\
<div id="' + map_id + '" style="min-height: 400px; z-index: 1; max-width:100%"></div>\
</div>\
<p class="help-box small text-muted">\
' + (map_field.df.description ? __(map_field.df.description) : '') + '\
</p>\
</div>\
</div>\
');
// Initiate map and attach it to form variable for reference
frm._map = L.map(map_id);
// Add tile layer to map
L.tileLayer(
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
{
maxZoom: 19,
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}
).addTo(frm._map);
// Use the Geolocation API to set the map view to the user location
// If failed, then set the map view to Frappe's default location
window.navigator.geolocation.getCurrentPosition(
function(ret) {
ret = ret.coords;
frm._map.setView(
[ret.latitude, ret.longitude],
frappe.utils.map_defaults.zoom
);
},
function() {
frm._map.setView(
frappe.utils.map_defaults.center,
frappe.utils.map_defaults.zoom
);
},
{
maximumAge: 0,
timeout: Infinity,
enableHighAccuracy: true
}
);
// Add the locate control to the map
let locate_control = L.control.locate({position:'topright'});
locate_control.addTo(frm._map);
// Add the refresh control to the map
L.easyButton({
id: 'refresh-map-' + map_field.df.fieldname,
position: 'topright',
type: 'replace',
leafletClasses: true,
states:[{
stateName: 'refresh-map',
onClick: function(button, map) { map._onResize(); },
title: 'Refresh map',
icon: 'fa fa-refresh'
}]
}).addTo(frm._map);
// Create a marker remover control and add it to the map
frm._marker_remove_control = L.easyButton({
id: 'remove-marker-' + map_field.df.fieldname,
position: 'topleft',
type: 'replace',
leafletClasses: true,
states:[{
stateName: 'remove-marker',
onClick: function(button, map) {
removeMarker();
},
title: __('Remove Marker'),
icon: 'fa-trash'
}]
}).addTo(frm._map);
// Disable the marker remover control
frm._marker_remove_control.disable();
// Register the map click event handler
function mapClick(e) {
e = e.latlng;
if (!frm._marker) addMarker(e.lng, e.lat);
else {
frm._marker.setLatLng(new L.LatLng(e.lat, e.lng));
updateLocation(e.lng, e.lat);
}
}
frm._map.on('click', mapClick);
// Show the HTML field
frm.toggle_display('location_html', 1);
// Add marker function
function addMarker(lng, lat, old) {
frm._marker = new L.marker([lat, lng], {draggable: true});
frm._marker.addTo(frm._map);
frm._marker.on('dragend', markerDrag);
frm._marker_remove_control.enable();
if (!old) updateLocation(lng, lat);
}
// Update the Geolocation field value
function updateLocation(lng, lat) {
let value = {
type: 'FeatureCollection',
features: []
};
if (lng && lat)
value.features.push({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
});
frm.set_value('location', JSON.stringify(value));
}
// Remove marker function
function removeMarker() {
if (!frm._marker) return;
frm._marker_remove_control.disable();
frm._marker.off('dragend', markerDrag);
frm._map.removeLayer(frm._marker);
frm._marker = null;
updateLocation();
}
// Marker drag handler
function markerDrag(e) {
e = e.target.getLatLng();
updateLocation(e.lng, e.lat);
}
// Finally, if Geolocation field has an old value
// then add a marker and move the map to its location
if (!frm.is_new() && cstr(frm.doc.location).length) {
try {
let value = JSON.parse(cstr(frm.doc.location));
if (value.features && value.features.length) {
value = value.features[0].geometry.coordinates;
addMarker(value[0], value[1], 1);
frm._map.flyTo([value[1], value[0]], 16);
}
} catch(e) {}
}
Best regards…