I built a contact form in which a user can find his house via Google Maps and afterwards adjust the exact position via marker so that this information will be sent to my WPForms as static image together with pre-filled address details.
Everything works like expected, but there is this strange problem that the google map won't always load. It happens in every browser, beside Safari, sometimes it loads, sometimes it doesn't. I can refresh the page a few times and I'd say that it works 4 out of 5 times. When the map is not able to load, this is what the console is showing:
Uncaught (in promise) InvalidValueError: Map: Expected mapDiv of type HTMLElement but was passed null.
This is my script (I've randomized the api key)
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaS1234567890hIP123456789051hbRgLF0UM&libraries=places&callback=initMap"
async defer></script>
<script>
var map;
var autocomplete;
var marker;
var hintDiv;
function initMap() {
// Initialisiere die Karte
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 51.1657, lng: 10.4515},
zoom: 6,
mapTypeId: 'roadmap',
mapTypeControl: false,
streetViewControl: false,
tilt: 0
});
// Autocomplete-Feld
var input = document.getElementById('addressInput');
autocomplete = new google.maps.places.Autocomplete(input);
// Kein Browser-Autocomplete
input.setAttribute('autocomplete', 'off');
// Marker
marker = new google.maps.Marker({
position: {lat: 0, lng: 0},
map: map,
draggable: true
});
// Listener für Autocomplete-Auswahl
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (!place.geometry) {
console.error("Returned place contains no geometry");
return;
}
// Zentriere die Karte und setze den Marker an die ausgewählte Position
map.setCenter(place.geometry.location);
marker.setPosition(place.geometry.location);
// Ändere die Kartenansicht auf Sattelitenbild
map.setMapTypeId('satellite');
map.setZoom(19);
// WPForms Autofill
updateFormFields(place);
// Hinweis für Stecknadel
showHint();
// Image Export für Formular
showImageMap();
});
// Listener für Marker-Bewegung
marker.addListener('dragend', function(event) {
// Debug
console.log('Marker position:', event.latLng.lat(), event.latLng.lng());
// Geocode für Adresse des Markers
geocodeLatLng(event.latLng, function() {
// Update Image Export
showImageMap();
});
});
}
function updateFormFields(place) {
// WPForms Autofill
document.getElementById('wpforms-1307-field_10').value = getPostalCode(place);
document.getElementById('wpforms-1307-field_11').value = getCity(place);
document.getElementById('wpforms-1307-field_12').value = getStreet(place);
document.getElementById('wpforms-1307-field_13').value = getStreetNumber(place);
}
function getPostalCode(place) {
// Extrahiere PLZ
for (var i = 0; i < place.address_components.length; i++) {
for (var j = 0; j < place.address_components[i].types.length; j++) {
if (place.address_components[i].types[j] === 'postal_code') {
return place.address_components[i].long_name;
}
}
}
return '';
}
function getCity(place) {
// Extrahiere Stadt
for (var i = 0; i < place.address_components.length; i++) {
for (var j = 0; j < place.address_components[i].types.length; j++) {
if (place.address_components[i].types[j] === 'locality') {
return place.address_components[i].long_name;
}
}
}
return '';
}
function getStreet(place) {
// Extrahiere Straße
for (var i = 0; i < place.address_components.length; i++) {
for (var j = 0; j < place.address_components[i].types.length; j++) {
if (place.address_components[i].types[j] === 'route') {
return place.address_components[i].long_name;
}
}
}
return '';
}
function getStreetNumber(place) {
// Extrahiere Hausnummer
for (var i = 0; i < place.address_components.length; i++) {
for (var j = 0; j < place.address_components[i].types.length; j++) {
if (place.address_components[i].types[j] === 'street_number') {
return place.address_components[i].long_name;
}
}
}
return '';
}
function geocodeLatLng(latlng, callback) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
// ADresse formatiert
var address = results[0].formatted_address;
console.log('Address:', address);
// An WPForms via static Image senden
// Callback Bewegung Marker
if (callback && typeof callback === 'function') {
callback();
}
} else {
console.error('No results found');
}
} else {
console.error('Geocoder failed due to: ' + status);
}
});
}
// Hinweis für Stecknadel
function showHint() {
if (!hintDiv) {
hintDiv = document.createElement('div');
hintDiv.innerHTML = '<p>Bitte überprüfen Sie die Lage Ihres Hauses.<br>Sie können die rote Stecknadel verschieben, um Ihr Haus auszuwählen.</p>';
hintDiv.style.backgroundColor = 'white';
hintDiv.style.padding = '10px';
hintDiv.style.border = '1px solid #ccc';
hintDiv.style.borderRadius = '5px';
hintDiv.style.marginTop = '10px';
document.getElementById('hintContainer').appendChild(hintDiv);
}
}
// Image Export an WPForms
function showImageMap() {
// Erstelle ein neues Bild-Element
var imageMap = new Image();
// Aktualisierte Position des Markers
var markerPosition = marker.getPosition();
// URL für die statische Karte mit dem aktualisierten Marker
var imageUrl = "https://maps.googleapis.com/maps/api/staticmap?" +
"center=" + markerPosition.lat() + "," + markerPosition.lng() +
"&zoom=19" +
"&size=600x300" +
"&maptype=satellite" +
"&markers=color:yellow%7Clabel:Ihr%20Haus%7C" + markerPosition.lat() + "," + markerPosition.lng() +
"&key=AIz1234567890QmhIP123456789051hbRgLF0UM";
// URL für Bild
imageMap.src = imageUrl;
document.getElementById('wpforms-1307-field_15').value = imageUrl;
// HTML Export
document.getElementById('imageMapContainer').innerHTML = '';
document.getElementById('imageMapContainer').appendChild(imageMap);
}
</script>
These are my div containers:
<div>
<input type="text" id="addressInput" placeholder="Bitte geben Sie hier Ihre Adresse ein" autocomplete="off">
</div>
<div id="map"></div>
<div id="hintContainer"></div>
thanks in advance!
tried to run it on a different server (not wordpress), expected that is has something to do with the way my theme loads the function. Did not work.
tried to remove the callback function for the eventlistener when the marker has been moved, no difference.