Showing multiple info boxes in Google Maps when pulling from MySQL - javascript

I have the following code and have been stuck on this issue for a very long time. I'm able to display the multiple markers but cannot get them to display the info details when clicked within a pop up info box. Right now I'm trying to get it to say "Hey!" as a test. Any suggestions is appreciated!
<script src="https://maps.googleapis.com/maps/api/js?signed_in=true&callback=initMap"
async defer>
</script>
<script type="text/javascript">
var map;
var image = 'images/marker_blast.png';
function initialize() {
// Set static latitude, longitude value
var latlng = new google.maps.LatLng(40.4313684, -79.9805005);
// Set map options
var myOptions = {
zoom: 11,
center: latlng,
panControl: true,
zoomControl: true,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
// Create map object with options
map = new google.maps.Map(document.getElementById("map"), myOptions);
//MARK MAP
<?php
$markers = $mysqli->query("SELECT * FROM reports");
while($row_marker = $markers->fetch_assoc()) {
// uncomment the 2 lines below to get real data from the db
// $result = mysql_query("SELECT * FROM parkings");
// while ($row = mysql_fetch_array($result))
echo "addMarker(new google.maps.LatLng(".$row_marker['lat'].", ".$row_marker['lng']."), map);\n";
}
?>
}
function addMarker(latLng, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: image,
size:30,
draggable: false, // enables drag & drop
animation: google.maps.Animation.DROP
});
}
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, 'mouseover', (function(marker) {
return function() {
var content = "Hey";
infowindow.setContent(content);
infowindow.open(map, marker);
}
})(marker));
</script>

You need to attach the InfoWindow to the marker in the addMarker function where the marker exists:
function addMarker(latLng, name, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: image,
size: 30,
draggable: false, // enables drag & drop
animation: google.maps.Animation.DROP
});
google.maps.event.addListener(marker, 'mouseover', (function (marker) {
return function () {
var content = "Hey "+name;
infowindow.setContent(content);
infowindow.open(map, marker);
}
})(marker));
}
proof of concept fiddle

I don't know if echoing the function inside the while loop will make it run like you want it to. Consider a method like this.
<?php while($row_marker = $markers->fetch_assoc()) {
$result = mysql_query("SELECT * FROM parkings");
while ($row = mysql_fetch_array($result)) { ?>
addMarker(new google.maps.LatLng(<?php echo $row_marker['lat']; ?>, <?php echo $row_marker['lng']; ?>), map);
<?php } ?>
<?php } ?>
Also, I'm not sure why you're running the second while loop but it doesn't look like you're using the result $row at all.

Related

Google Maps API: Mutiple Marker/Closures

Hey first time posting here. Trying to post multiple markers that I am pulling in from an API. I am a novice programmer, but I believe closures in the issue. I have tried many variations but I still can't get it to work. Can someone take a look?
$data = json_decode($json);
//var_dump($data);
foreach($data as $object):?>
<?php endforeach;
?>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCGLTlvxWSV6x4yH5XqqItlgHHIPt8GYp0" type="text/javascript"></script>
<script type="text/javascript">
var lat = '<?php echo $object->{'latitude'}?>';
var long = '<?php echo $object->{'longitude'}?>';
// check DOM Ready
$(document).ready(function() {
// execute
(function() {
// map options
var options = {
zoom: 5,
center: new google.maps.LatLng(39.909736, -98.522109), // centered US
mapTypeId: google.maps.MapTypeId.TERRAIN,
mapTypeControl: false
};
// init map
var map = new google.maps.Map(document.getElementById('map_canvas'), options);
// set multiple marker
for (var i = 0; i < 1000; i++) {
// init markers
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat,long),
map: map,
title: 'Check-In ' + i
});
// process multiple info windows
(function(marker, i) {
// add click event
google.maps.event.addListener(marker, 'click', function() {
var infowindow = new google.maps.InfoWindow({
content: '<?php echo $object->{'username'}?>'
});
infowindow.open(map, marker);
});
})(marker, i);
};
})();
});
</script>
</head>
<body>
<div id="map_canvas" style="width: 800px; height:500px;"></div>
</body>
You're in for a world of hurt if you intersperse PHP loops with JavaScript loops like this. What you should do instead is generate a JSON array or JavaScript object for your markers from PHP, and then loop through your array in JavaScript.
For example, you could generate this JavaScript array from PHP:
var places = [
{ lat:10, lng:20, username:"Weez" },
{ lat:30, lng:40, username:"Mike" }
];
You can see where you could use your foreach loop to generate this, or use PHP's json_encode function.
Then your JavaScript code might look something like this:
$(document).ready(function() {
var options = {
zoom: 5,
center: new google.maps.LatLng( 39.909736, -98.522109 ),
mapTypeId: google.maps.MapTypeId.TERRAIN,
mapTypeControl: false
};
var map = new google.maps.Map(
document.getElementById('map_canvas'),
options
);
places.forEach( function( place, index ) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng( place.lat, place.lng ),
map: map,
title: 'Check-In ' + index
});
google.maps.event.addListener( marker, 'click', function() {
var infowindow = new google.maps.InfoWindow({
content: place.username
});
infowindow.open( map, marker );
});
});
});
I took out a couple of nested inline functions that aren't necessary. You are right that you need a closure (or some other mechanism) to capture the username for each of your markers to use in the click event handler, but the the callback function used with the .forEach() loop provides that closure for you. place, index, and marker are unique variables for each iteration of the loop, because they are arguments or local variables in the callback. So when you use place.username inside the click handler it has the value you expect.

Google Map API use LatLng or Address

I'm using Javascript to render an embedded Google Map canvas on my website.
The inputs to the rendering are lat/lng coordinates that are retrieved from a database. However, if lat/lng returns null, the map will render based on the corresponding address string retrieved from the database. The following script always renders correctly for lat/lng coordinates inputs, but doesn't work for address input. Strangely, when I refresh the page multiple times, the address input would work randomly. I'm trying to cut out this randomness. Think I'm pretty close but I can't seem to find the missing link.
Note: if lat/lng is null, a default value is applied to $lat and $lng so it doesn't mess up the JS below.
I would appreciate if anyone could tell me what's wrong with the below code that's causing the random rendering of address strings.
var map;
var marker;
var geocoder;
function initialize() {
var mapCanvas = document.getElementById('map-canvas');
var estLatLng = new google.maps.LatLng( <? php echo $lat; ?> , <? php echo $lng; ?> );
var mapOptions = {
center: estLatLng,
zoom: 17,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: false,
streetViewControl: true,
scrollwheel: false
}
map = new google.maps.Map(mapCanvas, mapOptions);
marker = new google.maps.Marker({
position: estLatLng,
map: map,
draggable: false,
animation: google.maps.Animation.DROP,
title: "<?php echo $name;?>"
});
}
function toggleBounce() {
if (marker.getAnimation() != null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
}
google.maps.event.addDomListener(window, 'load', initialize);
<? php
} ?>
$(".navbar").load("navbar.html", function() {
$("#navbarrestaurants").addClass("active");
});
$(document).ready(function() { <? php
if ($calcAddress) { ?> // this chunk of code is not loaded if lat/lng is not null
geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': "<?php echo $address;?>",
'componentRestrictions': {
country: 'Singapore'
}
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
}); <? php
} ?>
});
I believe your problem is that the code in $(document).ready is being executed before that in your initialize function (listening for window load). The load event is called once the page is completely loaded, including images, etc, while everything in your document ready block is called slightly earlier when the DOM is ready.
Because it is executed sooner, and acting upon variables like map, that haven't been set up yet by the initialize function, the code in your geocoding callback is probably causing errors when it tries to alter the map center and set marker coords.
Try executing your geocoding code after the map is initialized. ie: wrap it in its own function and call it at the end of the initialization function.
function initialize() {
var mapCanvas = document.getElementById('map-canvas');
var estLatLng = new google.maps.LatLng( <? php echo $lat; ?> , <? php echo $lng; ?> );
var mapOptions = {
center: estLatLng,
zoom: 17,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: false,
streetViewControl: true,
scrollwheel: false
}
map = new google.maps.Map(mapCanvas, mapOptions);
marker = new google.maps.Marker({
position: estLatLng,
map: map,
draggable: false,
animation: google.maps.Animation.DROP,
title: "<?php echo $name;?>"
});
codeAddress();
}
ex: http://jsfiddle.net/j7pb7w3d/2/
This isn't great however, as the map starts with its default center, then visibly jerks a second later to the new address.
Instead you could determine whether or not geocoding is necessary first, and do this before the map is loaded, then use the result to set the map center and marker when the map is first created. Ex: http://jsfiddle.net/qsefxu5q/2/
Note these examples are hardly perfect and will need to be changed for your purposes. Hopefully they give you some ideas.

Google Maps v3 infoWindow addDomListener for HTML Button

I have a simple google Maps example
JS File:
/*Standard Setup Google Map*/
var latlng = new google.maps.LatLng(-25.363882,131.044922);
var myOptions = {
zoom: 15,
center: latlng,
panControl: false,
mapTypeControl: true,
scaleControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// add Map
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// add Marker
var marker1 = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(-25.363882,131.044922)
});
// add Info Window
var infoWindow = new google.maps.InfoWindow();
Now i want to open the info Box when i click on a button in the my html template:
HTML File:
<body onload="initialize()">
...
<div id="map_canvas"></div>
...
<button id="test">Click</button>
...
</body>
adding these lines to my JS File:
var onMarkerHTMLClick = function() {
var marker = this;
var latLng = marker.getPosition();
var content = '<div style="text-align: center; font-size:14px;"><center><b>Company GmbH</b></center><div>Broadway Str.5</div><div>45132 Canvas</div></div>';
map.panTo(marker.getPosition());
map.setZoom(15);
infoWindow.setContent(content);
infoWindow.open(map, marker);
};
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
});
google.maps.event.addDomListener(document.getElementById("test"),'click', onMarkerHTMLClick);
error: marker.getPosition is not a function
why should this not work? If i do the same with a click function on the marker itself the window opens with no problems..
You need to trigger the event that opens the infoWindow. Probably the easiest thing to do is store your markers in a global array or if you dont have many just select them by ID.
Example
var myButton = document.getElementById('THE_ID');
google.maps.event.addDomListener(myButton, 'click', openInfoWindow);
openInfoWindow just being the callback function where you can trigger the event.

Display Multiple Markers in Array - Google Maps API

How can I clean this so that the code handles multiple listings better? I have seen some code examples that pull the marker info from an array, but I can't seem to get it to work.
The markers need to have "icon:", "url:" and "title:" attributes. The "icon:" so I can change each markers appearance, the "url:" to point through to the page dedicated to each marker and the "title" just to add the markers name on hover.
I also need the array in the script as I am not gathering it from a database or anything like that.
I am pretty green when it comes to javascript and google maps api, any help would be greatly appreciated.
function createMap(lat, lng, zoomVal) {
var mapOptions = { center: new google.maps.LatLng(lat, lng),
zoom: zoomVal,
scrollwheel: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var myLatlnglow = new google.maps.LatLng(23.654332,-79.387867);
var markerlow1 = new google.maps.Marker({
position: myLatlnglow,
icon: 'images/map-dot.png',
map: map,
url: '#',
title: 'Name'
});
google.maps.event.addListener(markerlow1, 'click', function() {
window.location.href = markerlow1.url;
});
var myLatlnglow = new google.maps.LatLng(23.688458,-79.300619);
var markerlow = new google.maps.Marker({
position: myLatlnglow,
icon: 'images/map-dot.png',
map: map,
url: '#',
title: 'Name'
});
google.maps.event.addListener(markerlow, 'click', function() {
window.location.href = markerlow.url;
});
}
var map;
function initialize() {
createMap(23.668493, -29.410812,12);
if(navigator.geolocation) {
success = function(position) {
createMap(position.coords.latitude, position.coords.longitude,13);
};
error = function() {
createMap(23.648493, -29.410812,12);
}
navigator.geolocation.getCurrentPosition(success, error);
}
}
If I were you I would make an object of objects for the sake of readability. If you must have efficiency, and want to save space and typing, replace the object with an array and address the data by index (0,1,2...)
Here's a demo
// inside function createMap(...)
...
markerData = {
bing: {
lat: 23.654332,
lng: -79.387867,
icon: "http://labs.google.com/ridefinder/images/mm_20_red.png",
url: "http://www.bing.com/",
title: "some search engine"
},
yahoo: {
lat: 23.688458,
lng: -79.300619,
icon: "http://labs.google.com/ridefinder/images/mm_20_blue.png",
url: "http://www.yahoo.com/",
title: "Great free games"
}
};
for (markerId in markerData) {
markers[markerId] = createMarker(markerData[markerId]);
}
markers['bing'].setTitle("new title");
}
function createMarker(data) {
var myLatLng = new google.maps.LatLng(data.lat, data.lng);
var marker = new google.maps.Marker({
position: myLatLng,
icon: data.icon,
map: map,
title: data.title
});
google.maps.event.addListener(marker, 'click', function() {
window.location.href = data.url;
});
return marker;
}
It should also help later to save the references to the created markers, I'm using the global object markers and the same IDs.
var map;
var markers = {};
If you later need to change a marker property it is accessible through markers.
markers['bing'].setTitle("new title");

Google Maps API (v3) adding/updating markers

EDIT: It now works, but does not load if the user does not allow or have location-based services. See accepted answer comment for jsfiddle example.
I've looked through a few tutorials and questions but I can't quiet understand what's happening (or in this case, not happening). I'm loading my map when the user clicks a link. This loads the map with the users current location in the center, and a marker at the users location. However, any markers outside of the if (navigation.location) don't seem to load. Below is my current code:
function initialize() {
// Check if user support geo-location
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var point = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var userLat = position.coords.latitude;
var userLong = position.coords.longitude;
var mapOptions = {
zoom: 8,
center: point,
mapTypeId: google.maps.MapTypeId.HYBRID
}
// Initialize the Google Maps API v3
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
// Place a marker
new google.maps.Marker({
position: point,
map: map,
title: 'Your GPS Location'
});
});
} else {
var userLat = 53;
var userLong = 0;
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(userLat, userLong),
mapTypeId: google.maps.MapTypeId.HYBRID
}
// Place a marker
new google.maps.Marker({
position: point,
map: map,
title: 'Default Location'
});
// Initialize the Google Maps API v3
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
}
<?
for ($i = 0; $i < sizeof($userLocations); $i++) {
?>
var userLatLong = new google.maps.LatLng(<? echo $userLocations[$i]['lat']; ?>, <? echo $userLocations[$i]['long']; ?>);
new google.maps.Marker({
position: userLatLong,
map: map,
title:"<? echo $userLocations[$i]['displayName'] . ', ' . $userLocations[$i]['usertype']; ?>"
});
<?
}
?>
}
function loadMapScript() {
if (typeof(loaded) == "undefined") {
$("#showMap").css("display", "none");
$("#showMapLink").removeAttr("href");
$("#map").css("height", "600px");
$("#map").css("width", "600px");
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=MY_API_KEY&sensor=true&callback=initialize";
document.body.appendChild(script);
loaded = true;
} else {
alert("Map already loaded!");
}
}
loadMapScript() is called when the user clicks a link. The php for loop loops through a pre-created array with all the information.
I'm guessing I don't fully understand it, as when if I put:
var userLatLong = new google.maps.LatLng(53, 0);
new google.maps.Marker({
position: userLatLong,
map: map,
title:"Title"
});
into the console (Google Chrome), I get the error:
Error: Invalid value for property <map>: [object HTMLDivElement]
I don't, however, get any errors otherwise. Any help would be much appreciated! :)
navigator.geolocation.getCurrentPosition() is asynchronous.
Reorganize your code like this:
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.HYBRID
}
function initialize() {
// Check if user support geo-location
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
makeMap(position.coords.latitude, position.coords.longitude, 'Your GPS Location');
});
} else {
makeMap(53, 0, 'DefaultLocation');
}
}
function makeMap(lat, lng, text) {
var point = new google.maps.LatLng(lat, lng);
mapOptions.center = point;
map = new google.maps.Map(document.getElementById("map"), mapOptions);
new google.maps.Marker({
position: point,
map: map,
title: text
});
<?php for ($i = 0; $i < sizeof($userLocations); $i++): ?>
var userLatLong = new google.maps.LatLng(<? echo $userLocations[$i]['lat']; ?>, <? echo $userLocations[$i]['long']; ?>);
new google.maps.Marker({
position: userLatLong,
map: map,
title:"<? echo $userLocations[$i]['displayName'] . ', ' . $userLocations[$i]['usertype']; ?>"
});
<?php endforeach ?>
}
Also, consider bootstraping the $userLocations into a JavaScript variable like this:
var userLocations = <?php print json_encode($userLocations) ?>;
Then execute your for loop in JavaScript, instead of mixing languages.
Have you tried:
var map = null;
function initialize() { ... }
and then changing the code inside:
map = new google.maps.Map( ... ); //make this the first line
if (navigator.geolocation) {
// Change the code from:
var map ...
// to:
map ...
You just reference the map directly (without the var) everywhere else, so that should work.
Change:
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
To:
map = new google.maps.Map(document.getElementById("map"), mapOptions);
Because of var, your map variable is tied the the scope of initialize(). Removing it will set it as the global map variable (or window.map), making it available outside of the initialize() function.
What's happening is you have an HTML element <div id="map">. In many browsers, global variables are created from html element ids, so map equals document.getElementById('map').
Edit: Actually, this only explains your problem in the Chrome console. You need to set map before trying to attach markers to it, as you do within if (navigator.geolocation) {}. This also explains why none of the user location markers are being placed. The code to place them runs before initialize(). Put this code either within initialize or within its own function, and call that function from initialize.
It looks like you're creating the marker, but not doing anything with it. Try changing your new Marker to look like this:
var marker = new google.maps.Marker({
position: point, // this won't actually work - point is out of scope
title: 'Your GPS Location'
});
marker.setMap(map);
Edit: Make sure the point is inside the map!
var bounds = new google.maps.LatLngBounds();
bounds.extend(point);
map.fitBounds(bounds);

Categories

Resources