Having problems with infowindow.setContent and OverlappingMarkerSpiderfier - javascript

I have been palying around with OVerlappingMArkerSpiderfier
https://github.com/jawj/OverlappingMarkerSpiderfier
I have a loop that adds markers, but each marker needs an infoWindow to have some unique text as its content.
If I do the following:
content = '<div id="info">' +
'<p><b><?php echo $row->Event ?></b></p>' +
'<p><?php echo $row->Date ?></br>' +
'<?php echo $row->City . ", " . $row->Country ?></p>' +
'</div>';
oms.addListener('click', function(myMarker) {
if(!iw){
iw = new google.maps.InfoWindow();
};
iw.setContent(content);
// iw.setContent(myMarker.title);
iw.open(map, myMarker);
});
This only puts the last event in the infowindow.
If I try to do this:
(function(content, myMarker){
oms.addListener('click', function(myMarker) {
if(!iw){
iw = new google.maps.InfoWindow();
};
iw.setContent(content);
// iw.setContent(myMarker.title);
iw.open(map, myMarker);
});
})();
...doesn't work at all
Can anyone shed some light.
I failed to mention: I'm relatively new to javascript.

First, I would set iw = new google.maps.InfoWindow(); outside of the function to avoid your if(!iw) check.
Second, oms.addListener applies to all markers, not just one so this should not be within your loop of results (I'm assuming this is withing a while $row=$results type loop).
To make the correct content appear, you'll want to do something like marker.desc = content inside your loop, then inside the addListener do iw.setContent(myMarker.desc);
So something like this:
iw = new google.maps.InfoWindow();
oms.addListener('click', function(myMarker) {
iw.setContent(myMarker.desc);
iw.open(map, myMarker);
});
<?php while... { ?>
...
content = '<div id="info">' +
'<p><b><?php echo $row->Event ?></b></p>' +
'<p><?php echo $row->Date ?></br>' +
'<?php echo $row->City . ", " . $row->Country ?></p>' +
'</div>';
...
marker = new google.maps.Marker({
...
...
});
marker.desc = content;
oms.addMarker(marker);
<?php } ?>

Related

Getting error "Cannot read property 'documentElement' of null" in PHP/XML/JavaScript communication

So I am trying to follow the tutorial found here: https://developers.google.com/maps/articles/phpsqlajax_v3
Currently I have the database communication properly set and an XML with the desired results is produced by another file, phpsqlajax_genxml2.php.
However when this is integrated with the Google Map API the console logs the error "Cannot read property 'documentElement' of null" at the line which reads "var markers = xml.documentElement.getElementsByTagName("marker");", which is under the downloadUrl function call.
Here is a snippet from index.html's JS section:
var customIcons = {
restaurant: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png'
},
bar: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png'
}
};
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(47.6145, -122.3418),
zoom: 13,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("phpsqlajax_genxml2.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b> <br/>" + address;
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
In case it is helpful, here is the phpsqlajax_genxml2.php file:
<?php
require("phpsqlajax_dbinfo.php");
function parseToXML($htmlStr)
{
$xmlStr=str_replace('<','<',$htmlStr);
$xmlStr=str_replace('>','>',$xmlStr);
$xmlStr=str_replace('"','"',$xmlStr);
$xmlStr=str_replace("'",''',$xmlStr);
$xmlStr=str_replace("&",'&',$xmlStr);
return $xmlStr;
}
// Opens a connection to a MySQL server
$connection=mysql_connect ('creeptrekcom.domaincommysql.com', $username, $password);
if (!$connection) {
die('Not connected : ' . mysql_error());
}
// Set the active MySQL database
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
die ('Can\'t use db : ' . mysql_error());
}
// Select all the rows in the markers table
$query = "SELECT * FROM markers WHERE 1";
$result = mysql_query($query);
if (!$result) {
die('Invalid query: ' . mysql_error());
}
header("Content-type: text/xml");
// Start XML file, echo parent node
echo '<markers>';
// Iterate through the rows, printing XML nodes for each
while ($row = #mysql_fetch_assoc($result)){
// ADD TO XML DOCUMENT NODE
echo '<marker ';
echo 'name="' . parseToXML($row['name']) . '" ';
echo 'address="' . parseToXML($row['address']) . '" ';
echo 'lat="' . $row['lat'] . '" ';
echo 'lng="' . $row['lng'] . '" ';
echo 'type="' . $row['type'] . '" ';
echo '/>';
}
// End XML file
echo '</markers>';
?>
Which has in its source when inspected:
<markers>
<marker name="Pan Africa Market" address="1521 1st Ave, Seattle, WA" lat="47.608940" lng="-122.340141" type="restaurant"/>
<marker name="Buddha Thai & Bar" address="2222 2nd Ave, Seattle, WA" lat="47.613590" lng="-122.344391" type="bar"/>
<marker name="The Melting Pot" address="14 Mercer St, Seattle, WA" lat="47.624561" lng="-122.356445" type="restaurant"/>
...
</markers>
You need to allow cross-domain access. You do so by sending the correct header on top of your php script:
<?php
header("Access-Control-Allow-Origin: *");
But be careful, because you allow access for everyone, not just you, to this resource!
On your php script at $result = mysql_query($query); add your connection variable before query parametter.
Something like this: $result = mysqli_query($conn, $query);
Make sure the variable name is $conn in your database connection file.
exemple: $conn = mysqli_connect("HOST", "USERNAME", "PASSWORD", "DATABASE");

Add marker listener to all markers in a loop

I have made a website with a map using the Google Maps Javascript API. Im using PHP to call $rows from a Google BigQuery database. I want to add a listener to all markers on the map. Currently any marker clicked jumps to the final marker as if its looping through all remaining markers to the final marker.
foreach ($rows as $row) {
?>
var contentString = "<h1><?php echo str_replace('"', "'", $row['f'][2]['v']); ?></h1>";
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var geolocate = new google.maps.LatLng(<?php echo $row['f'][0]['v']; ?> , <?php echo $row['f'][1]['v']; ?>);
var marker = new google.maps.Marker({
map: map,
position: geolocate,
icon: '/img/Toilet.png',
title: "<?php echo str_replace('"', "'", $row['f'][2]['v']); ?>" //String Replace
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
I imaging that marker.addListener needs a pointer to the array index but i cant work it out, What do I do?
You can use an IIFE pattern. Please have a look at
https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
In this case your code will be something like:
<?php
foreach ($rows as $row) {
?>
(function() {
var contentString = "<h1><?php echo str_replace('"', "'", $row['f'][2]['v']); ?></h1>";
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var geolocate = new google.maps.LatLng(<?php echo $row['f'][0]['v']; ?> , <?php echo $row['f'][1]['v']; ?>);
var marker = new google.maps.Marker({
map: map,
position: geolocate,
icon: '/img/Toilet.png',
title: "<?php echo str_replace('"', "'", $row['f'][2]['v']); ?>" //String Replace
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
})();
<?php
}
?>

Javascript and PHP for each loop to output an array

I am trying to create a javascript array using content that is pulled from a php database.
<?php
//This creates an array from the database and allows us to use it later in the jquery
//CREATE SQL STATEMENT
$sql_locations = "SELECT * FROM tbllocations";
//CONNECT TO MYSQL SERVER
require('test-connection.php');
//EXECUTE SQL STATEMENT
$rs_locations = mysqli_query($vconnection, $sql_locations);
$rs_locations_rows = mysqli_fetch_assoc($rs_locations);
foreach( $rs_locations as $rs_location ) {
$markers[] = array(
"{$rs_location['place']}, {$rs_location['city']}",
$rs_location['long'],
$rs_location['lat']
);
}
?>
<div id="map_wrapper">
<div id="map_canvas" class="mapping"></div>
</div>
<style>
#map_wrapper {
height: 400px;
}
#map_canvas {
width: 100%;
height: 100vh;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script>
function initialize() {
var map;
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
mapTypeId: "roadmap",
center: new google.maps.LatLng(47.608941, -122.340145), // somewhere in the uk BEWARE center is required
zoom: 3,
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
map.setTilt(45);
// Multiple Markers
var markers = <?php echo json_encode( $markers ); ?>;
// Info Window Content
var infoWindowContent = [
<?php while($rs_location_rows = mysqli_fetch_assoc($rs_location)) { ?>
['<div class="info_content">' +
'<h3><?php echo $rs_locations_rows['branch']; ?></h3>' +
'<p><?php echo $rs_locations_rows['content']; ?></p>' +
'<p><?php echo $rs_locations_rows['phone']; ?></p>' +
'</div>']
<?php } ?>
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow();
var marker, i;
// Loop through our array of markers & place each one on the map
for (i = 0; i < markers.length; i++) {
var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0]
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infoWindow.setContent(infoWindowContent[i][0]);
infoWindow.open(map, marker);
}
})(marker, i));
// Automatically center the map fitting all markers on the screen
map.fitBounds(bounds);
}
//Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {
this.setZoom(10);
google.maps.event.removeListener(boundsListener);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I have updated the code to show my whole page. I have tried this while loop in the meantime and adding that in stops my page from generating and outputting my map, so my page will hang.
I am thinking to do a for each loop the same way that I have done for the markers, but I have not succeeded thus far
As you are basically trying to build a string containing some js code and then pass it directly to the browser, I would build a string in PHP and then echo the lot in one go. Its easier to see what you are doing.
<?php
$js = '<script type="text/javascript">';
$js .= 'var infoWindowContent = [';
while( $row = mysqli_fetch_assoc($rs_location)) {
$js .= "['" . '<div class="info_content">';
$js .= "<h3>{$row['branch']}</h3>";
$js .= "<p>{$row['content']}</p>";
$js .= "<p>{$row['phone']}</p>";
$js .= "</div>'],";
}
// trim off the js interpreter breaking trailing comma
$js = rtrim( $js, ',' );
// close the outer array
$js .= '];';
$js .= '</script>';
echo $js;
?>
You just need to change the do while structure to while:
As also mentioned by #RiggsFolly. (sorry I see now)
var infoWindowContent = [
<?php while($rs_location_rows = mysqli_fetch_assoc($rs_location)) { ?>
['<div class="info_content">' +
'<h3><?php echo $rs_locations_rows['branch']; ?></h3>' +
'<p><?php echo $rs_locations_rows['content']; ?></p>' +
'<p><?php echo $rs_locations_rows['phone']; ?></p>' +
'</div>'],
<?php } ?>
];
This is the approach i would use to do that:
var myArray = [
<?php while ($rs_location_rows = mysqli_fetch_assoc($rs_location)) : ?>
{
'branch' : '<?= $rs_locations_rows["branch"] ?>',
'content' : '<?= $rs_locations_rows["content"] ?>',
'phone' : '<?= $rs_locations_rows["phone"] ?>'
},
<?php endwhile; ?>
];
console.log(myArray);
Now you have the array in your js.

including a Google dynamic map

I need some help as I'm trying to call back a JavaScript function with PHP. I created 2 classes which work together perfectly. In the first one exploiting a Google API, I extract the latitude and longitude of a city chosen by a user on my form, and then I pass these values to the second class which exploits another API to show a weather forecast service for that city.
I'd like to add a Google map too, to create this way a more complete service showing a dynamic map with the chosen city.
I noticed with Firebug that the browser is not able to parse correctly the two mentioned properties of the object $map, as you can easily see by yourself.
I really don't know how to call back the js function inside the tag , I need for my purpose.
The simple echo I'm using here with PHP doesn't work here.
Hope someone can help me.
Here's my page
and here's the piece of my code that is not working:
/**
* Check for the real existence of the city, using the
* property $status of the instanced GeoLocalization class, here the object $map.
* This class exploits a Google API.
*/
if ( isset($missing) && empty($missing) && strlen($citta) > 1 && $map->status == 'OK' )
{
/**
* Use some properties of the object $map to show my user
* the chosen city and state in Italian.
* Show even the latitude and the longitudine.
* These values are those passed to the GeoWeather class.
*/
// show the location
echo '<ul id="display_location">' .
'<li class="rosso centra sottolineato grassetto">' . $map->formatted_address . '</li>' .
'<li>' . 'Latitudine: ' . $map->latitude . '</li>' .
'<li>' . 'Longitudine: ' . $map->longitude . '</li>' .
</ul>';
echo '<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>';
echo '<script type="text/javascript">
var map;
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(<?php echo $map->latitude . ", " . $map->longitude; ?>)
};
map = new google.maps.Map(document.getElementById("googleStaticMap"), mapOptions);
}
</script>';
echo '<script type="text/javascript">initialize();</script>';
echo '<div id="googleStaticMap"></div>';
}
</body>
You can't start a new PHP-block inside a PHP-block.
This:
echo '<script type="text/javascript">
var map;
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(<?php echo $map->latitude . ", " . $map->longitude; ?>)
};
map = new google.maps.Map(document.getElementById("googleStaticMap"), mapOptions);
}
</script>';
should be:
echo '<script type="text/javascript">
var map;
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng('. $map->latitude . ','
. $map->longitude .')
};
map = new google.maps.Map(document.getElementById("googleStaticMap"),
mapOptions);
}
</script>';
Other issues:
you must switch the order of these 2 lines(otherwise #googleStaticMap is unknown when you call the function):
echo '<script type="text/javascript">initialize();</script>';
echo '<div id="googleStaticMap"></div>';
Additionaly:
#googleStaticMap currently doesn't have a height. You've set a height of 100%, but as long as the parent element of #googleStaticMap doesn't have a height set via CSS this will not have any effect.

multiple google maps markers with PHP

I've had a look around SO and found some situations similar to mine but haven't found a solution.
I'm learning PHP, Javascript as I go along so the code may be a little off but here goes:
I have a Google map with a postcode search function working - The postcode and Lat/Long are stored in a Mysql DB. What I need now is a function to place any amount of markers on the map for specific postcodes - in time I hope to expand the function to allow something like postcode+10 miles, etc depending on the zoom level. The code below will bring back the lat/long for the markers but it sticks a "," at the end of each results and therefore when I pass it into the javascript, it's an invalid parameter - please be sure that I know that the way I'm doing all of this is in-efficient - I'm learning as I go along :)
PHP function:
// get markers Function
if(!function_exists("getMarkers"))
{
//Get Markers Function
function getMarkers()
{
//prep the query
include ('../../secure/db_conn.php');
$currentPcode = searchPostcode($_POST['postcode']);
$tsearch = $con->prepare("SELECT t.CompanyName, p.lat, p.lng FROM Traders t, cpo_data p WHERE t.Postcode LIKE p.Postcode");
$tsearch->bindParam(1,$currentPcode, PDO::PARAM_STR);
$tsearch->execute();
$tresults = $tsearch->fetchAll(PDO::FETCH_ASSOC);
foreach ($tresults as $row)
{
$Company = $row['CompanyName'];
$Tlat = (string)$row['p.lat'];
$Tlng = (string)$row['p.lng'];
}
echo $Tlat .", " .$Tlng;
}
}
Javascript:
<script src="http://maps.googleapis.com/maps/api/js?sensor=false">
</script>
<script>
//postcode function call
var myCenter=new google.maps.LatLng(<?php echo searchPostcode($_POST['postcode']); ?>);
//markers function call
var locations=new google.maps.LatLng(<?php echo getMarkers(); ?>);
function initialize()
{
var mapProp = {
center:myCenter,
zoom:14,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
var mymap=new google.maps.Map(document.getElementById("googleMap"),mapProp);
// To add the marker to the map, use the 'map' property
var marker, i;
for (i = 0; i < locations.length; i++)
{
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i]),
map: mymap
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations[i]);
infowindow.open(mymap, marker);
}
})(marker, i));
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
Any help or advice will be greatly appreciated - my current knowledge is only PHP and Javascript (and as mentioned previously, it's beginners knowledge).
Forgot to add, When I use google developer tools in Chrome to analyse the page, I can see the following which confirms it is picking up the lat/long, but with a comma at the end (I think it's to do with it being an array but not sure how I deal with it):
var locations=new google.maps.LatLng(53.51139969260000, -2.54091408438000, );
If you want to place the markers fetched from the database you have two problems:
PHP Code
You echo only the last pair of lat/lng fetched:
foreach ($tresults as $row)
{
$Company = $row['CompanyName'];
$Tlat = (string)$row['p.lat'];
$Tlng = (string)$row['p.lng'];
}
echo $Tlat .", " .$Tlng;
A solution would be:
$locations = array();
foreach ($tresults as $row)
{
$Company = $row['CompanyName'];
$Tlat = (string)$row['p.lat'];
$Tlng = (string)$row['p.lng'];
$locations[] = "[" . $Tlat .", " .$Tlng . "]";
}
echo srpintf("[%s]", implode(", ", $locations);
Then in your javascript code you store an array of coordinates in locations.
Javascript code
Now in your javascript code:
var locations = <?php getMarkers(); ?>
You have now in locations the array like this:
[[53.51139969260000, -2.54091408438000], [...], ...]
Then in the loop you should access to coordinates as an array:
var marker, i;
for (i = 0; i < locations.length; i++)
{
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: mymap
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations[i][0] + ", " + locations[i][1]);
infowindow.open(mymap, marker);
}
})(marker, i));
}
}

Categories