Javascript and PHP for each loop to output an array - javascript

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.

Related

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
}
?>

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));
}
}

Google Maps // "Uncaught TypeError: Cannot read property 'icon' of undefined"

I'm implementing Google Maps onto a Wordpress website that will allow the user to add locations to the Map using Advanced Custom Fields. The map loads in great, but the icons/markers don't seem to be loading in right. I get an error that reads, "Uncaught TypeError: Cannot read property 'icon' of undefined" in the Chrome Developer Tool Inspector.
Do I need to add anything? I'm new to Google Maps and firing it off and what not. Here's what I'm using:
<?php // Index template
get_header(); ?>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<div class="twelve column">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="intro">
<?php the_excerpt(); ?>
<hr>
</div>
<?php the_content(); ?>
<header class="clearfix"></header>
<div id="mapcanvas"></div>
<?php
// For creating multiple, customized loops.
// http://codex.wordpress.org/Class_Reference/WP_Query
$custom_query = new WP_Query('post_type=locations'); // exclude category 9
while($custom_query->have_posts()) : $custom_query->the_post(); ?>
<?php if(get_field('link')): ?>
<div>
<?php while(has_sub_field('link')): ?>
<div>
<p><?php the_sub_field('url'); ?></p>
</div>
<?php endwhile; ?>
</div>
<?php endif; ?>
<?php endwhile; ?>
<?php wp_reset_postdata(); // reset the query ?>
<?php
function get_single_term($post_id, $taxonomy)
{
$terms = wp_get_object_terms($post_id, $taxonomy);
if(!is_wp_error($terms)) {
return ''.$terms[0]->name.'';
}
}
$i = 0;
// For creating multiple, customized loops.
// http://codex.wordpress.org/Class_Reference/WP_Query
$custom_query = new WP_Query('post_type=location&posts_per_page=-1');
while($custom_query->have_posts()) : $custom_query->the_post();
$title = get_the_title(); // Location title
$map = get_field('location'); // ACF location contains address and coordinates
$terms = strip_tags( get_the_term_list( $post->ID, 'distributors', '', ' & ' )); // Get distributor terms and rm links
$info = '<strong>' . $terms . '</strong><br>' . $title; // Info window content
$url = the_sub_field('url');
if(get_field('link')){
echo '<ul>';
while(has_sub_field('link')){
$info .= '<li>'.get_sub_field('url').'</li>';
}
echo '</ul>';
}
$location[$i][0] = $title; // Store the post title
$location[$i][1] = $map['coordinates']; // Store the ACF coordinates
$location[$i][2] = json_encode($info); // Store info window content
$location[$i][3] = strip_tags( get_single_term( $post->ID, 'distributor' )); // Get first term for marker icon
$i ++;
endwhile; ?>
<?php wp_reset_postdata(); // reset the query ?>
<script>
$(function initialize() {
// Center map on our main location
var myLatLng = new google.maps.LatLng(41.583013,-93.63701500000002);
var map;
var bounds = new google.maps.LatLngBounds();
// https://developers.google.com/maps/documentation/javascript/styling
// Create an array of styles.
var styles = [
{
stylers: [
{ saturation: -99.9 }
]
}
];
// Create a new StyledMapType object, passing it the array of styles,
// as well as the name to be displayed on the map type control.
var styledMap = new google.maps.StyledMapType(styles, {name: 'exile'});
// Create a map object, and include the MapTypeId to add
// to the map type control.
var mapOptions = {
mapTypeId: 'roadmap',
center: myLatLng,
zoom: 8,
disableDefaultUI: false,
scrollwheel: true,
draggable: true
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("mapcanvas"), mapOptions);
map.setTilt(45);
//Associate the styled map with the MapTypeId and set it to display.
map.mapTypes.set('exile', styledMap);
map.setMapTypeId('exile');
// Marker icons
typeObject = {
"Home" : {
"icon" : new google.maps.MarkerImage('img/target.png', new google.maps.Size(28,28), new google.maps.Point(0,0), new google.maps.Point(36,14)),
"shadow" : new google.maps.MarkerImage('http://maps.google.com/mapfiles/shadow50.png', new google.maps.Size(40,34))
},
"Others" : {
"icon" : new google.maps.MarkerImage('img/beer-mug.png', new google.maps.Size(18,26), new google.maps.Point(0,0), new google.maps.Point(9,26)),
"shadow" : new google.maps.MarkerImage('http://maps.google.com/mapfiles/shadow50.png', new google.maps.Size(40,34))
}
}
// http://wrightshq.com/playground/placing-multiple-markers-on-a-google-map-using-api-3/
// Multiple Markers
var markers = [
["Exile Brewing Co", 41.583013,-93.63701500000002,"Others"],
<?php
if (count($location)>0) {
foreach ($location as $key => $value){
if ($key < (count($location)-1)){
echo '["' . $location[$key][0] . '",' . $location[$key][1] . ',"' . $location[$key][3] . '"], ' . "\n";
} else {
echo '["' . $location[$key][0] . '",' . $location[$key][1] . ',"' . $location[$key][3] . '"]';
}
}
}
?>
];
// Info Window Content
var infoWindowContent = [
["<strong>Exile Brewing Co.</strong><br>1514 Walnut Street, Des Moines"],
<?php
if (count($location)>0) {
foreach ($location as $key => $value){
if ($key < (count($location)-1)) {
echo '[' . $location[$key][2] . '], ' . "\n";
} else {
echo '[' . $location[$key][2] . ']';
}
}
}
?>
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow(), 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]); // ACF coordinates
var icon = typeObject[markers[i][3]]['icon'];
var shadow = typeObject[markers[i][3]]['shadow'];
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0],
icon: icon,
shadow: shadow
});
// 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(15);
google.maps.event.removeListener(boundsListener);
});
});
</script>
<div id="panel">
Search within
<input id="address" type="textbox" value="10">
miles of zipcode
<input id="address" type="textbox" value="50266">
<input class = "button" type="button" value="Find it!" onclick="codeAddress()">
</div>
<footer class="clearfix"></footer>
<?php endwhile;?>
<?php endif; ?>
</div>
</div>
<?php get_footer(); ?>
Here's the link to the page I'm working on too:
http://exilebrewing.com/locations/
Any help is appreciated, thanks!
The typeObject contains 2 properties (Home and Others)
Your script will fail when the 4th item of a item in markers doesn't match 1 of these property-names.
This currently happens:
var markers = [
["Exile Brewing Co", 41.583013,-93.63701500000002,"Others"],
["Exile Brewing Co",41.583013,-93.63701500000002,""]
//this must be either Home or Others--------------^
];
You may either fix markers or use a fallback when the property can't be found:
for( i = 0; i < markers.length; i++ ) {
var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
//use typeObject.Others when property can't be found
var icon = (typeObject[markers[i][3]]||typeObject.Others).icon;
var shadow = (typeObject[markers[i][3]]||typeObject.Others).shadow;
//continue with your code
}

Array alerts 0 for .length not sure why

I'm pretty new to JQuery, I'm trying to make an event so when table row is clicked it does something, but it will have a for loop, but that wasn't working so I removed the loop and did an alert to see how many items were inside of the array, it alerts 0. I'm not sure why, on page load the script generates markers from my database and loads them onto the map (That works fine and as intended) on the left side of the screen a table is made that says what street each stop is on, and when you click on the table row it is supposed to center and zoom on the marker (I can figure that part out on my own) But right now it's telling me there is nothing in the array and I'm not sure why. Thanks.
<?php
require_once('config.inc.php');
require_once($rootdir . $dirsubfolder . 'navbar.php');
include($rootdir . $dirsubfolder . 'php/findmarkers.php');
?>
<script>
$(document).ready(function() {
var arrMarkers = [];
var zoom = 6;
var initialLocation;
var map;
var markersArray = new Array();
$("table#listOfStops").find('tr').each(function() {
$(this).on('click', function() {
alert(arrMarkers.length);
});
});
$(window).resize(function () {
var h = $(window).height(),
offsetTop = 230; // Calculate the top offset
$('#gmaps').css('height', (h - offsetTop));
}).resize();
loadScript();
});
function initialize() {
geocode = new google.maps.Geocoder();
var mapOptions = {
zoom: 10,
center: new google.maps.LatLng(56.7626362, -111.379652),
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: false,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.LARGE
}
};
map = new google.maps.Map(document.getElementById('gmaps'),
mapOptions);
google.maps.event.addListener(map, 'click', function(event) {
var latitude = event.latLng.lat();
var longitude = event.latLng.lng();
deleteOverlays();
addMarker(event.latLng);
updateTextFields(latitude, longitude);
});
<?php while($stmt -> fetch()) { ?>
var long = "<?php echo $gLongitude ?>";
var lati = "<?php echo $gLatitude; ?>";
var title = "<?php echo $gTitle; ?>"
setMarker(lati, long, title);
<? } $stmt -> close(); $mysqli -> close();?>
}
function setMarker(lat,lon, markerTitle) {
var latLonMarker = new google.maps.LatLng(lat,lon);
marker = new google.maps.Marker({
position: latLonMarker,
map: map,
icon: 'icon.png',
title: markerTitle
});
google.maps.event.addListener(marker, 'dragend', function() {
$('#inputLatitude').val(this.getPosition().lat());
$('#inputLongitude').val(this.getPosition().lng());
});
arrMarkers.push(marker);
}
function loadScript() {
var script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true&' +
'callback=initialize';
document.body.appendChild(script);
}
</script>
<?php include($rootdir . $dirsubfolder . 'php/findmarkers.php'); ?>
<div style="padding-top: 5%; padding-bottom: 5%;">
<div class="container-fluid">
<div class="row-fluid">
<div class="span3 container hero-unit">
<h2 style="text-align: center;">Route <?php echo $gRouteNumber ?></h2>
<h4 style="text-align: center;" class="alert-info">Begins <? echo $gArrivalTime; ?></h4>
<br />
<table id="listOfStops" class="table table-striped">
<thead>
<tr>
<th>Stop #</th>
<th>Street Name</th>
</tr>
</thead>
<tbody>
<?php
$i = 0;
while($stmt -> fetch()) {
echo '<tr id="' . $i . '">';
echo '<td>' . $gStopNumber . '</td>';
echo '<td>' . $gStreetName . '</td>';
echo '</tr>';
$i++;} $stmt -> close(); $mysqli -> close(); ?>
</tbody>
</table>
</div>
<div class="span9">
<div id="gmaps"></div>
</div>
</div>
</div>
</div>
<?php
require_once('footer.php');
?>
As I already stated in my comment, you are declaring arrMarkers as a local variable in your document ready function.
That means, it is undefined in the setMarker function.
Try making it a global variable and you should be good.

Having problems with infowindow.setContent and OverlappingMarkerSpiderfier

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 } ?>

Categories