I am trying to update a store location by getting the lat/long of a marker on the google map.
However I get this error:
UpdateStoreDAO.js:7 Uncaught TypeError: Cannot read property 'getPosition' of undefined
at updateItemData (UpdateStoreDAO.js:7)
at UpdateStore.js:68
at IDBOpenDBRequest.request.onsuccess (indexedDB.js:38)
I'm not quite sure why it won't work as getPosition works for adding a store location to the map for a marker. It uses the same Google Maps API as my adding page does and the add page never threw me this error.
The code for the update function (DAO) is:
function updateItemData(marker) {
//User input of item name
var storeLocation = $('#txtStoreLocation').val();
//Get latitude and longitude of current marker position
var eventLat = marker.getPosition().lat();
var eventLng = marker.getPosition().lng();
//Create an item object combining name, desc and price attributes
data.storeLocation = storeLocation;
data.eventLat = eventLat;
data.eventLng = eventLng;
var data = {
'storeLocation' : storeLocation,
'eventLat' : eventLat,
'eventLng' : eventLng
}
//Insert data into indexedDB database
updateOne(data, function(lastID) {
event.preventDefault();
return false;
});
}
The code for the update store js file is (if it's any help):
//mapCenter
var mapCenter = new google.maps.LatLng(51.8979988098144,-2.0838599205017);
//geocoder will be used to convert geographic coordinates (current marker position)
// intop a human-readable address
var geocoder = new google.maps.Geocoder();
//An InfoWindow displays content (usually text or images)
//in a popup window above the map, at a given location.
var infowindow = new google.maps.InfoWindow();
function initialize(){
// Initial map properties
var mapOptions = {
zoom: 15,
center: mapCenter
};
//Create a map object passing the html div placeholder to hold google map
myMap = new google.maps.Map(document.getElementById("mapInput"), mapOptions);
//Create a draggable marker icon in the map
marker = new google.maps.Marker({
map: myMap,
position: mapCenter,
draggable: true
});
}
//Retrieve Item information saved in database
//show in the form
var urlParams = new URLSearchParams(window.location.search);
var itemID = urlParams.get('itemID');
$('#itemID').html("Item ID: " + itemID);
setDatabaseName('dbCatalogue', ['UsersObjectStore', 'ItemsObjectStore']);
setCurrObjectStoreName('ItemsObjectStore');
//Select One function to retrieve data of a specific item
var data;
startDB(function () {
selectOne(itemID, function(result) {
$('#txtStoreLocation').val(result.storeLocation);
$('#txtEventLat').val(result.eventLat);
$('#txtEventLng').val(result.eventLng);
data = result;
})
})
//The addDomListener will be triggered when the HTML page is loaded
//and will execture the initialize function above
google.maps.event.addDomListener(window, 'load', initialize);
//Event handler for form submit button
$('#formUpdateStore').submit(function(event){
// cancels the deafult form submission and handle the event from javascript
event.preventDefault();
//Create an idexedDB database (the name of the database is dbFlogger)
// with two object stores - UsersObjectStore to store user data
// and ItemsObjectStore to store item data
setDatabaseName('dbEvent', ['EventObjStore']);
// For this example, we will store data in ItemsObjectStore
setCurrObjectStoreName('EventObjStore');
//startDB will create a connection with the database and
//execute operations such as save item
startDB(function () {
updateItemData(data);
alert("Store has been updated successfully!");
});
});
I understand it's probably a lot to ask but any help would be appreciated!
(note = comments are a bit off since code has been reused from other pages)
===UPDATE===
I fixed the error by changing updateItemData(data) to updateItemData(marker) in the regular js file.
However, I am now getting a new error:
Uncaught TypeError: Cannot set property 'storeLocation' of undefined
at updateItemData (UpdateStoreDAO.js:11)
at UpdateStore.js:68
at IDBOpenDBRequest.request.onsuccess (indexedDB.js:38)
I'm not quite sure why I'm getting this as storeLocation is defined and there's a property set via user input?
Related
I am trying to make a web map in which I can add a marker on map and at the same time get the lat lon coordinates of all markers to be saved on my database later on. I came up with this function to do that:
function newMarker(e) {
var new_mark = L.marker()
.setLatLng(e.latlng)
.addTo(map_4562f93a48a3459d95c4d292f52b5adc);
new_mark.dragging.enable();
new_mark.on("dblclick", function(e) {
map_4562f93a48a3459d95c4d292f52b5adc.removeLayer(e.target);
});
var latlngs = [];
var lat = e.latlng.lat.toFixed(4),
lng = e.latlng.lng.toFixed(4),
mark_latlon = new_mark.getLatLng();
map_4562f93a48a3459d95c4d292f52b5adc.eachLayer(function(layer) {
latlngs.push(mark_latlon);
console.log(latlngs);
});
new_mark.bindPopup("Waypoint");
}
map_4562f93a48a3459d95c4d292f52b5adc.on("click", newMarker);
The problem with this code is that it just adds the coordinates of the last marker every time a marker is created by clicking. I want all the coordinates to be appended to latlongs Array. And if possible I want to it to be updated when deleted or dragged. Can anyone help me on this?
As stated in the title, I have my lng and lat values in my DOM where I'm trying to display the map location based on that 2 values in my DOM however the map isn't display any location as it is in gray color, i suspect that the initMap function is executing before the content has been loaded. Is there a way to initialize the map after the content has been loaded? Here are some of my codes.
Controller
public function show($id)
{
$report = Report::find($id);
return view('report',compact('report'));
}
View
<p class="title" id="reportId" data-id="{{$report->id}}" data-lat="{{$report->latitude}}"
data-lng="{{$report->longitude}}">{{$report->title}}</p>
JavaScript
function initMap() {
const latData = parseFloat(document.getElementById('reportId').getAttribute('data-lat'));
const lngData = parseFloat(document.getElementById('reportId').getAttribute('data-lng'));
console.log(typeof latData);
var options = {
zoom: 15,
center: {
lat : latData,
lng : lngData
}
};
var map = new google.maps.Map(
document.getElementById("map"),
options
);
var marker = new google.maps.Marker({
position: {
lat : 3.119822,
lng : 101.594800
},
map: map
});
}
This is how the map looks
EDIT
I did not include this in the beginning because I assumed it was just an issue with JavaScript however, for more information I'm using Laravel 6.5.2 in this project which is the reason why my lat and lng data are inside an element's dataset.
There are nothing special in my laravel codes just getting the data from database through controller methods and display onto my view at the same time setting a data-lat and data-lng so that in my script i can get the coordinates and populate to a google map view.
I have tried one Laravel Google Map library called Googlmapper but unfortunately I'm getting some error from that library too. It is out of topic but you can check it out here.
I would make use of Document.readyState.
The Document.readyState property describes the loading state of the document.
The readyState of a document can be one of following:
loading
The document is still loading.
interactive
The document has finished loading and the document has been parsed but sub-resources such as images, stylesheets and frames are still loading.
complete
The document and all sub-resources have finished loading. The state indicates that the load event is about to fire.
so in your case:
document.addEventListener('readystatechange', event => {
if (event.target.readyState === 'interactive') {
//
}
else if (event.target.readyState === 'complete') {
initMap();
}
});
Source Mozilla
2nd solution:
If you will load content via ajax after the dom is already loaded and maybe this take some time, you could set up a time out function, but you will never know when the object is loaded.
Then you can track the existence of a dom object and if it is part of the dom content, then read the value and execute your function:
function waitForElement(callback){
if(window.someVariable){
callback();
} else{
setTimeout(waitForElement(callback), 250);
}
}
// execute on load:
waitForElement(initMap);
edit: (based on your comment)
seems to me that the map is initialised but without coords.
I have only rewritten the coords and created a fiddle.
If you have a valid GoogleApiKey, then enter it and the map will be created successfully.
JsFiddle GoogleMaps-example
function initMap() {
const latData = parseFloat(document.getElementById('reportId').getAttribute('data-lat'));
const lngData = parseFloat(document.getElementById('reportId').getAttribute('data-lng'));
var uluru = {lat: latData, lng: lngData};
console.log(typeof latData);
var options = {
zoom: 15,
center: uluru
};
var map = new google.maps.Map(
document.getElementById("map"),
options
);
var marker = new google.maps.Marker({
position: uluru,
map: map
});
}
Solved
Apparently... It was a very careless mistake made by me.
which was flipping the values between lat and lng value which results into a undefined location which is why the map did not display location even thought it has been initialized.
You can change your body tag to be the following:
<body onload="initMap()">
so that once the dom loads, the map will be initialized.
I'm trying to send a few longitude and latitude variables to a function that will then generate a Google Map.
Starting with a datatable that retrieves various information stored in a database, I'm using data-attributes to store the lng and lat for each record. When a record is selected, a modal opens and the map is displayed.
I was able to get the map to display with default lng and lat points. But now I need to create a new map every time a record is selected.
Starting with the onclick event that triggers the modal to open (shortened as much as possible):
$('#example1').on('click', 'tr > td > a.actionMatch', function(e)
{
e.preventDefault();
var actimpbill = $(this).attr('data-actimpbill'); // random record info
var actramplat = parseFloat($(this).attr('data-actramplat')); // first lat
var actramplng = parseFloat($(this).attr('data-actramplng')); // first lng
var actdellat = parseFloat($(this).attr('data-actdellat')); // second lat
var actdellng = parseFloat($(this).attr('data-actdellng')); // second lng
// my map was opening in a grey box. this next piece of code fixed that
$("#actionMatchbackModal").on("shown.bs.modal", function () {
google.maps.event.trigger(map, "resize");
});
initMap(actramplat, actramplng, actdellat, actdellng); // my attempt to call a function and the variables to it
$('#actionMatchbackModal').modal('show'); // show the modal
});
Here is the function that sets the map. This is located outside of the initial onclick event that opens the modal (I'm not sure if that's a problem). This is where I'm trying to pass the variables that I created inside the onclick event:
function initMap(actramplat, actramplng, actdellat, actdellng)
{
// map options
var options = {
zoom: 8,
center: {actramplat, actramplng}
}
// new map
var map = new google.maps.Map(document.getElementById('map'), options);
// add marker
var marker = new google.maps.Marker({
position:{actdellat, actdellng},
map: map
});
}
I am probably butchering the function call. The function once housed the default lat and lng numbers and I was able to properly generate a map.
Edit
I just checked the console, and I am getting these errors:
InvalidValueError: setCenter: not a LatLng or LatLngLiteral: in property lat: not a number
InvalidValueError: setPosition: not a LatLng or LatLngLiteral: in property lat: not a number
Edit
I just added parseFloat to the variables to ensure they are not strings, but still no success.
Edit
Here is what the data-attributes look like:
<a href="#" class="actionMatch" id="actionMatch"
data-toggle="modal" data-actimpbill="xxxxxxxx"
data-actramplat="39.11" data-actramplng="-94.63"
data-actdellat="39.03" data-actdellng="-96.83"
data-actreclat="39.84" data-actreclng="-96.65"
rel="tooltip" data-placement="right" title="Action Matchback"></a>
You can see the actramplat, actramplng, actdellat, actdellng in the A tag above.
Looking at their API, they expect lat/long values to be provided as an object literal that looks like this: var myLatLng = {lat: -25.363, lng: 131.044};
So you need to call it like this:
// map options
var options = {
zoom: 8,
center: {lat: dellat, lng: dellng}
}
// new map
var map = new google.maps.Map(document.getElementById('map'), options);
// add marker
var marker = new google.maps.Marker({
position:{lat: reclat, lng: reclng},
map: map
});
I have a script that:
pulls results from a database in the form of an XML file
parses those results
creates a marker for each result and places it on a map (a single map for all markers)
at the same times, builds a clickable HTML list (sidebar) containing all those results.
When the user clicks on a place name in the sidebar, the info window from the corresponding marker on the map is automatically displayed. Of course the user can also click directly on a marker on the map, and the same info window is also displayed.
This code has been working fine for several years, but last week I noticed that its behavior was now bugged. When viewing some given results, the first click (either on the map or in the sidebar) works fine (the info window opens and displays the correct information), but the following clicks all show the same information from the first click, all in their respective info window. (To be clear: the information shown is the one from the very first click, not from the previous click.)
I've been trying to debug that for hours but I don't understand why it doesn't work anymore. As you can see in my code below, I tried adding a console.log in the google.maps.event.addListener function, to see what data is being worked with when the marker is clicked, but even there, I don't see anything wrong.
Here is my code (simplified to be more readable):
var side_bar_html = '\n';
var gmarkers = []; // array for created markers
var infoWindow;
var center_lat = <?php echo $position_lat; ?>;
var center_lng = <?php echo $position_lng; ?>;
function createMarker(point, name, html, place_id, map) {
var marker, markerOptions;
markerOptions = {
map: map,
position: point,
dataId: place_id,
icon : 'theme/marker.png',
shadow: 'theme/marker_shadow.png'
};
marker = new google.maps.Marker(markerOptions);
infoWindow = new google.maps.InfoWindow({content: html});
google.maps.event.addListener(marker, 'click', function() {
console.log(this, marker, html);
infoWindow.content = html;
infoWindow.open(map, this);
});
gmarkers.push(marker);
side_bar_html += '\n<li>' + name + '</li>';
return marker;
}
function showPlace(i) {
google.maps.event.trigger(gmarkers[i], 'click');
}
function loadEarth(opt, zoom) {
var map, point, mapCenter, mapOptions;
if (zoom === null) {zoom = 7;}
mapCenter = new google.maps.LatLng(center_lat, center_lng);
mapOptions = {
zoom: zoom,
center: mapCenter,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
point = new google.maps.LatLng(parseFloat(center_lat), parseFloat(center_lng));
if (opt != 0) {
map.setMap(new google.maps.Marker(point));
}
}
// receiving results via XML
function go() {
var map, bounds;
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
bounds = new google.maps.LatLngBounds();
$.ajax({
url : 'url/to/data.xml',
type : 'GET',
dataType : 'xml',
success : function(xml) {
var markers, lat, lng, place_id, point, label, html, marker;
markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// extract data for each marker
lat = parseFloat(markers[i].getAttribute("lat"));
lng = parseFloat(markers[i].getAttribute("lng"));
place_id = parseFloat(markers[i].getAttribute("place_id"));
point = new google.maps.LatLng(lat,lng);
label = $(markers[i]).find('label').eq(0).text();
html = $(markers[i]).find('infowindow').eq(0).text();
// marker creation
marker = createMarker(point, label, html, place_id, map);
// extend visible zone to newly added marker
bounds.extend(point);
}
map.setCenter(new google.maps.LatLng(center_lat, center_lng), 7);
bounds.extend(point);
if (markers.length>0) {
document.getElementById("side_results").innerHTML = side_bar_html;
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
} else {
loadEarth();
}
} // end AJAX success
}); // end AJAX
} // end go()
if ($('#places_page').is('.empty')) {
loadEarth(0,8);
} else go();
Any help would be greatly appreciated.
Edit:
As requested, here's a sample of the XML received. In this case, the PHP variables at the start of the script would receive the following values:
$position_lat: 46.9479222
$position_lng: 7.4446085
<?xml version="1.0" encoding="UTF-8"?><markers>
<marker place_id="955" lat="46.950218" lng="7.442429">
<label><![CDATA[<em>Place 955</em><strong>3011 Bern</strong>]]></label>
<infowindow>
<![CDATA[<p><em>Place 955</em><br />Speichergasse 35<br />3011 <ins>Bern</ins></p>]]>
</infowindow>
</marker>
<marker place_id="985" lat="46.942032" lng="7.389993">
<label><![CDATA[<em>Place 985</em><strong>3018 Bern</strong>]]></label>
<infowindow>
<![CDATA[<p><em>Place 985</em><br />BrĂ¼nnenstrasse 106A<br />3018 <ins>Bern</ins></p>]]>
</infowindow>
</marker>
</markers>
The Google Maps API is included via this line:
<script src="http://maps.google.com/maps/api/js?v=3&sensor=true&language=fr&key=..."></script>
Edit 2:
Changing the API call to force it to use version 3.18 does fix the problem:
<script src="http://maps.google.com/maps/api/js?v=3.18&sensor=true&language=fr&key=..."></script>
Obviously this is a temporary fix, since v. 3.18 won't always be available. Now I need to understand what change in the 3.19 version made this bug appear. Any suggestion is still appreciated. :)
This undocumented usage:
infoWindow.content = html;
May be the issue. Should be:
infoWindow.setContent(html);
The .content property went away or is no longer supported issue
I'm working with google maps api and javascript which I am not much familiar with. Here's the code I use to draw markers on my map. I get Latitudes and Longitudes from my database:
var geocoder;
var map;
var jsonStr = '<?php echo json_encode($arajka) ?>';
var LatLong = JSON.parse(jsonStr);
function initialize() {
geocoder = new google.maps.Geocoder();
var mapOptions = {
center: new google.maps.LatLng(50.000001, 20.000001),
zoom: 12
};
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
var marker = [];
for(var i=0;i<LatLong.length;i++){
var LatLong1 = new google.maps.LatLng(LatLong[i].lat, LatLong[i].lon);
marker.ajdi=LatLong[i].id; // storing additional data (I need to get it when user clicks on certain marker)
marker.push(new google.maps.Marker({position: LatLong1, map: map, title: LatLong[i].login}));
}
// trying to set some listener but it fails.
google.maps.event.addListener(marker, 'click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
alert("ASDASDASD" + marker.ajdi);
});
}
So, this listener doesn't work, I don't know why. Well, I expect that it doesn't exactly know what marker is it about. When I tried to do it with a single one, like in tutorial, it worked properly. I don't know what to do when I have this array. Any suggestions please?
You have several mistakes in your code:
As #Hollister mentions, marker is an array, so you need to put the addListener call inside the loop;
You have to store the additional marker data into the marker, not into the marker array;
you have to use this in the listener, not marker.
for(var i=0;i<LatLong.length;i++){
var LatLong1 = new google.maps.LatLng(LatLong[i].lat, LatLong[i].lon);
var this_marker = new google.maps.Marker({position: LatLong1, map: map, title: LatLong[i].login});
this_marker.ajdi=LatLong[i].id; // storing additional data (I need to get it when user clicks on certain marker)
marker.push(this_marker);
// trying to set some listener but it fails.
google.maps.event.addListener(this_marker, 'click', function() {
map.setZoom(8);
map.setCenter(this.getPosition());
alert("ASDASDASD" + this.ajdi);
});
}