Infowindow is not looping in google maps - javascript

In my project, am taking values from php database and showing as markers in google maps. I want to show service name, in each location as infowindow (Multiple service names are available for each location). I want that service name displayed in infowindow line by line in each marker location.
But when i tried to show only first service name
Following is my code, I am showing only essential codes
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var id = markerNodes[i].getAttribute("id");
var name = markerNodes[i].getAttribute("locationName");
// console.log(name);
var address = markerNodes[i].getAttribute("locationAddress1");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var servicename = markerNodes[i].getAttribute("serviceName");
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("locationLat")),
parseFloat(markerNodes[i].getAttribute("locationLong")));
//console.log (parseFloat(markerNodes[i].getAttribute("locationLong")));
createOption(name, distance, i);
createMarker(latlng, name, address,servicename);
bounds.extend(latlng);
From above code, i will get everything from php databse,from this servicename ,i want to show as infowindow.
Following is the code for adding infowindow
function createMarker(latlng, name, address,servicename ) {
var html = servicename;
var marker = new google.maps.Marker({
map: map,
draggable: true,
animation: google.maps.Animation.DROP,
position: latlng,
// label: "C",
icon: {
url: "{{ asset('img/new_map.png') }}"
}
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
What is wrong with this code, if i print address or name, it will works fine.
Below is the console data am getting,for reffrenceOutput

If you were to add a fourth named argument to the createMarker function you can then assign it as a property of the marker itself - which makes it quite simple to access when clicking the marker as you can use this
That said I do not see that you actually use the name nor the address arguments within the function itself so if again they are assigned as custom properties for the marker you can access them in the click event using this - ie: this.name etc
function createMarker( latlng, name, address, servicename ) {
var marker = new google.maps.Marker({
html:servicename,
map:map,
draggable:true,
animation:google.maps.Animation.DROP,
position:latlng,
name:name,
address:address,
icon: {
url:"{{ asset('img/new_map.png') }}"
}
});
google.maps.event.addListener(marker, 'click', function(e) {
infoWindow.setContent( this.html );
infoWindow.open( map, this );
}.bind( marker ));
markers.push( marker );
return marker;
}
After our brief discussion and thinking further about your requirements perhaps you might try like this. As you have ( as you stated ) already added the 4th argument we can add as a custom property to each marker. In the click handler we can iterate over the markers array and compare the current markers html attribute/property ( you originally refer to html hence continuing to do so here ) to the html property of whatever marker in the array and if they match add this to the output to be displayed in the infowindow
function createMarker( latlng, name, address, servicename ) {
var marker = new google.maps.Marker({
html:servicename,
map:map,
draggable:true,
animation:google.maps.Animation.DROP,
position:latlng,
name:name,
address:address,
icon: {
url:"{{ asset('img/new_map.png') }}"
}
});
google.maps.event.addListener( marker, 'click', function(e) {
let data=[];
markers.forEach( mkr=>{
if( mkr.html==this.html ){
data.push( mkr.html )
}
});
infoWindow.setContent( data.join( '<br />' ) );
infoWindow.open( map, this );
}.bind( marker ));
markers.push( marker );
return marker;
}
A fully working demo ( apikey redacted ) based upon the following XML file. The ajax function and it's callback are simply to emulate whatever mechanism used in your code to load markers onto the map, once loaded they do not get used again - the querying of markers is done solely based upon the markers array.
<?xml version="1.0"?>
<markers>
<marker servicename='a' name="Kinnettles" address="B9127, Angus DD8 1, UK" lat="56.61543329027024" lng="-2.9266123065796137"/>
<marker servicename='b' name="Nathro" address="1 Goynd Steading, Glenogil, Forfar, Angus DD8 3SW, UK" lat="56.793249595719956" lng="-2.8623101711273193"/>
<marker servicename='a' name="ArkHill" address="3 Dryburn Cottages, Glenogilvy, Forfar, Angus DD8 1UP, UK" lat="56.57065514278748" lng="-3.0511732892761074"/>
<marker servicename='b' name="DoddHill" address="4 Backmuir Rd, Duntrune, Tealing, Dundee, Angus DD4 0PT, UK" lat="56.54251020079966" lng="-2.9051538305053555"/>
<marker servicename='c' name="Govals" address="B9127, Forfar, Angus DD8, UK" lat="56.582320876071854" lng="-2.9509015874633633"/>
<marker servicename='d' name="Carsegownie" address="B9134, Forfar, Angus DD8, UK" lat="56.67951330362271" lng="-2.8062983350524746"/>
<marker servicename='a' name="Frawney" address="Kerton Farm, Forfar, Angus DD8, UK" lat="56.56806620951482" lng="-2.9501720266113125"/>
<marker servicename='a' name="NorthTarbrax" address="4 Nether Finlarg Farm Cottages, Forfar, Angus DD8 1XQ, UK" lat="56.57144715546598" lng="-2.92476614282225"/>
<marker servicename='e' name="TheCarrach" address="B951, Kirriemuir, Angus DD8, UK" lat="56.6938437674986" lng="-3.131382067657455"/>
<marker servicename='f' name="Glaxo" address="5 Meridian St, Montrose, Angus DD10 8DS, UK" lat="56.70431711148748" lng="-2.4660869436035"/>
</markers>
The html
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Collate attributes from multiple markers to display in single InfoWindow</title>
<style>
#map{width:800px;height:600px;}
</style>
<script>
var map;
var markers=[];
var infoWindow;
function ajax(callback){
let xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if( this.status==200 && this.readyState==4 )callback(this.response)
}
xhr.open( 'GET', 'maps.xml', true );
xhr.send( null );
};
function loadmarkers(r){
let oParser=new DOMParser();
let oXML=oParser.parseFromString( r, 'application/xml' );
let nodes=oXML.documentElement.getElementsByTagName('marker');
for( let i=0; i < nodes.length; i++ ){
let latlng=new google.maps.LatLng( nodes[i].getAttribute('lat'),nodes[i].getAttribute('lng') );
let name=nodes[i].getAttribute('name');
let address=nodes[i].getAttribute('address');
let servicename=nodes[i].getAttribute('servicename');
createMarker(latlng,name,address,servicename)
}
};
function createMarker( latlng, name, address, servicename ) {
var marker = new google.maps.Marker({
html:servicename,
map:map,
draggable:true,
animation:google.maps.Animation.DROP,
position:latlng,
name:name,
address:address
});
google.maps.event.addListener( marker, 'click', function(e) {
/* query XML to find ALL nodes that have the same location */
let data=[
this.name,
this.address
];
markers.forEach( mkr=>{
if( mkr.html==this.html ) data.push( mkr.html );
});
infoWindow.setContent( data.join( '<br />' ) );
infoWindow.open( map, this );
}.bind( marker ));
markers.push( marker );
return marker;
};
function initMap(){
let centre=new google.maps.LatLng( 56.7, -2.8 );
let options = {
zoom: 10,
center: centre,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
mapTypeControl: false,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
mapTypeIds: ['roadmap', 'terrain','satellite','hybrid']
}
};
map=new google.maps.Map( document.getElementById('map'), options );
infoWindow=new google.maps.InfoWindow();
ajax( loadmarkers );
}
</script>
<script async defer src='//maps.googleapis.com/maps/api/js?key=xxx&callback=initMap'></script>
</head>
<body>
<div id='map'></div>
</body>
</html>

Related

Google Maps API v3 I want to download marker data (lat lng) and save it to MySQL database

I have a map code like this:
function initMap() {
var map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 7,
center: new google.maps.LatLng(52.215594, 21.014130),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var myMarker = new google.maps.Marker({
position: new google.maps.LatLng(52.215594, 21.014130),
draggable: true
});
google.maps.event.addListener(myMarker, 'dragend', function(evt) {
document.getElementById('current').innerHTML = '<p>Marker dropped: Current Lat: ' +
evt.latLng.lat().toFixed(6) + ' Current Lng: ' + evt.latLng.lng().toFixed(6) + '</p>';
});
google.maps.event.addListener(myMarker, 'dragstart', function(evt) {
document.getElementById('current').innerHTML = '<p>Moving marker...</p>';
});
map.setCenter(myMarker.position);
myMarker.setMap(map);
}
I want to save the lat and lng values to the database but I don't know how to get them, I just know how to display lat and lng in js. The marker has draggable option. I can drag it to the desired location on the map and then show the dragged data of this marker (lat and lng) will be displayed by innerHTML.
But how now to get these values (lat and lng) after dragging them to desired position and save them to the database? My site is written in Smarty. Thank you in advance for your help.
It is easy enough to add your own ajax function within the dragend callback to fire-off a HTTPRequest that can be used to save the lat/lng of the current marker position.
The following uses fetch in conjunction with FormData to create and send the request. In this example the request is processed by the same page but you can simply change the javascript endpoint variable to point to a separate PHP script to save the lat/lng.
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' && isset(
$_POST['lat'],
$_POST['lng']
)){
/* save to db */
$sql='insert into `markers` (`lat`,`lng`) values (?,?)';
# $stmt=$db->prepare($sql);
# $stmt->bind_param('ss',$_POST['lat'],$_POST['lng']);
# $stmt->execute();
#etc
#prepare data to send back if appropriate
$data=array(
'status'=> 'success',
'lat' => $_POST['lat'],
'lng' => $_POST['lng'],
'sql' => $sql,
'date' => date( DATE_ATOM ),
'ip' => $_SERVER['REMOTE_ADDR']
);
# send data and exit
exit( json_encode( $data ) );
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<style>
body, body *{
box-sizing:border-box;
}
#map{
width:800px;
height:600px;
float:none;
margin:auto;
}
#current{
width:800px;
float:none;
margin:1rem auto;
}
</style>
<script>
function initMap() {
let lat=52.215594;
let lng=21.014130;
const current=document.getElementById('current');
const savelatlng=(e)=>{
let fd=new FormData();
fd.set('lat',e.latLng.lat());
fd.set('lng',e.latLng.lng());
let endpoint=location.href; // the php script that will save the latlng
fetch( endpoint, { method:'post', body:fd })
.then(r=>r.json())
.then(json=>{
console.log( 'Position saved: %o', json )
});
};
var map=new google.maps.Map(document.getElementById('map'), {
zoom:7,
center:new google.maps.LatLng( lat, lng ),
mapTypeId:google.maps.MapTypeId.ROADMAP
});
var myMarker=new google.maps.Marker({
draggable:true,
map:map
});
myMarker.setPosition( map.getCenter() );
google.maps.event.addListener( myMarker, 'dragend', function( evt ) {
current.innerHTML = `<p>Marker dropped: Current Lat: ${evt.latLng.lat().toFixed(6)} Current Lng: ${evt.latLng.lng().toFixed(6)}</p>`;
map.setCenter( evt.latLng );
savelatlng( evt );
});
google.maps.event.addListener( myMarker, 'dragstart', function( evt ) {
current.innerHTML = '<p>Moving marker...</p>';
});
}
</script>
<script async defer src='//maps.googleapis.com/maps/api/js?key=<APIKEY>&callback=initMap'></script>
</head>
<body>
<div id='map'></div>
<div id='current'></div>
</body>
</html>

Passing php var to javascript in Laravel

I am trying to pass php $var to Javascript in google map script. I have address table in DB. And with controller I fetch it to view and now try to pass it in Javascript and iterate it.
But having some trouble I think my code a bit corrupted. By the way I dont have lat and lng, just addresses.
function initMap(){
var options = {
zoom:8,
center:
#foreach($address as $addr){
{!! $addr->address !!}
}
#endforeach
}
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position:
#foreach($address as $addr){
{!! $addr->address !!}
}
#endforeach
map:map
});
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
marker.addListener('click', function () {
infoWindow.open(map, marker);
})
}
And Map API calling
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=MY-KEY&callback=initMap"></script>
controller
public function index()
{
$address = DB::table("allestates")
->get();
return view("home", compact('address'));
}
Address column in DB:
I see a few things that could be causing the issue
Try this:
function initMap(){
var options = {
zoom:8,
center:
'{!! $address[0]->address !!}'
}
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position:
#foreach($address as $addr)
'{!! $addr->address !!}'
#endforeach
map:map
});
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
marker.addListener('click', function () {
infoWindow.open(map, marker);
})
}
So first of all the #foreach (...) does not use { or }
Second you want to output any information that is not only numeric inside of quotes
Hope this helps

Multiple markers in flask google map api

I'm creating a flask app and try to fetch coordinates from mysql DB, the database has latitude and longitude infomation, I'd like to show all of markers on the page with the lat/lng and tend to using js to add markers, don't know why it doesn't work. Any helps appreciated.
using flask sqlalchemy to get lat/lng info
<script>
$(document).ready(function () {
function initMap() {
var latlng = {lat: -37.8253632, lng: 144.1404107}; // THIS IS CENTER OF THE MAP
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: latlng
});
google.maps.event.addListenerOnce(map, 'tilesloaded', addMarkers);
function addMarkers() {
{% for CarD in page_data %}
var point = {lat: {{ CarD.lat }}, lng: {{ CarD.lng }} };
var marker = new google.maps.Marker({
position: point,
map: map,
title: '!'
});
{% endfor %}
marker['infowindow'] = new google.maps.InfoWindow({
content: '<div id="content" style="text-align: center"></div>'
}); // info of the point
}
}
});
</script>
Your jinja templates are processed on the server side so putting the python variables in javascript only works if the js is in your template (as in you have the html and js in the same .html file). Additionally, i would discourage you from mixing the code. I would recommend you make an ajax call and receive a json response with your points. In flask you can do something like this
#app.route('/api/coordinates)
def coordinates():
addresses = session.query(Coordinates)#however you query your db
all_coods = [] # initialize a list to store your addresses
for add in addresses:
address_details = {
"lat": add.lat,
"lng": add.lng,
"title": add.title}
all_coods.append(address_details)
return jsonify({'cordinates': all_coods})
then in your javascript you can call this endpoint then process the json object (I like to use fetch for my ajax calls)
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: new google.maps.LatLng(-33.91722, 151.23064),
mapTypeId: 'roadmap'
});
//variable to hold your endpoint
var coodAddresses = 'https://yoursite.com/api/coordinates';
//an array to hold your cordinates
var locations = [];
//Using fetch to process the ajax call
// if you use fetch, besure to include the source below this line in your template
//<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.js"></script>
fetch(coodAddresses)
.then(function(response) {
return response.text();
}).then(function(body) {
var obj = JSON.parse(body);
var myAdd = {};
var addresses = obj.cordinates;
var l = addresses.length;
for (i = 0; i < l; i++) {
myAdd = {
position: {
lat: parseFloat(obj.cordinates[i].lat),
lng: parseFloat(obj.cordinates[i].lng)
},
title: obj.cordinates[i].title,
};
locations.push(myAdd);
}
locations.forEach(function(feature) {
var marker = new google.maps.Marker({
position: feature.position,
title: feature.title,
map: map
});
});
}).catch(function() {
// if the ajax call fails display an error in an info window
var pos = {
lat: lat,
lng: lng
};
infoWindow.setMap(map);
infoWindow.setPosition(pos);
infoWindow.setContent('An error occurred, we are unable to retreive cordinates.');
});
}
I hope you find this useful. If your points are not near each other, you may need to make sure the bounds include all of them

Trying to display Google Maps Directions with Geolocation, and user input, using meteor. Everything but the actual directions work

So I'm still relatively new to Meteor, and this will be my first Meteor project using an external API, and I'm running into a few issues. I've made web apps using the maps api before, and have had no problem displaying directions, but for some reason I'm having a lot of issue with Meteor. I have no problem getting the map to actually display a users current position, and map styling is the way I want it, but when it comes to the part where the user inputs directions, nothing happens. The map doesn't update, and I'm left just staring at the the current location. I'm using the packages jeremy:geocomplete dburles:google-maps and mdg:geolocation.
Here are the templates which create the map, and take user input for the destination:
<template name="map">
<div class="map-container">
{{#unless geolocationError}}
{{> googleMap name="map" options=mapOptions}}
{{else}}
Geolocation failed: {{geolocationError}}
{{/unless}}
</div>
</template>
<template name="greeting">
<div class="greet-overlay">
<div class="greet-window">
<div class="splash-window">
<p class="splash-text">Text</p>
<img class="splash" src="splash/PClogo.png" alt="Lorem Ipsum">
{{> addressForm}}
</div>
</div>
</div>
</template>
<template name="addressForm">
<div class="form-window">
<img src="game/directions.png" id="stuff">
<h1 class="address-title">Enter Destination</h1>
<input type="text" id="address" name="text" />
<button>Submit</button>
</div>
</template>
And here are the events and helpers for those templates (leaving out all the geocode stuff for now):
Template.map.helpers({
geolocationError: function() {
var error = Geolocation.error();
return error && error.message;
},
mapOptions: function() {
var latLng = Geolocation.latLng();
// Initialize the map once we have the latLng.
if (GoogleMaps.loaded() && latLng) {
return {
center: new google.maps.LatLng(LAT, LNG),
zoom: MAP_ZOOM
};
}
}
});
Template.map.onCreated(function() {
map = GoogleMaps.ready('map', function(map) {
var latLng = Geolocation.latLng();
var marker = new google.maps.Marker({
position: new google.maps.LatLng(LAT, LNG),
map: map.instance,
icon: '/game/loc_marker.png'
});
});
});
Template.addressForm.onRendered(function() {
this.autorun(function () {
if (GoogleMaps.loaded()) {
$("input").geocomplete()
.bind("geocode:result", function(event, result){
DESTLAT = result.geometry.location.lat();
DESTLNG = result.geometry.location.lng();
});
}
});
});
Template.addressForm.events({
'click button': function() {
directionsService = new google.maps.DirectionsService;
directionsDisplay = new google.maps.DirectionsRenderer;
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('panel'));
function calculateAndDisplayRoute(directionsService, directionsDisplay) {
directionsService.route({
origin: LAT + ',' + LNG,
destination: DESTLAT + ',' + DESTLNG,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
} else {
console.log('Directions request failed due to ' + status);
}
});
}
calculateAndDisplayRoute(directionsService, directionsDisplay);
$(".greet-overlay").toggle();
}
});
So yeah, basically everything works exactly the way I want it to, except for the directions. Not even the status responses are being logged to the console. I have no doubt I'm doing something so utterly foolish here that it's going to make me seriously question my career choices. Mistakes are probably being made, and I will learn from them.
Figured it out after some toying around! So essentially all I had to do was move some stuff around as I was initializing some things in the wrong order. I moved thecalculateAndDisplayRoute function out of the addressForm event template, and swapped the contents of map.onCreated with addressForm.onRendered. Now it is structured something like this:
function calculateAndDisplayRoute(service, display) {
directionsService.route({
origin: LAT + ',' + LNG,
destination: DESTLAT + ',' + DESTLNG,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
} else {
console.log('Directions request failed due to ' + status);
}
});
}
emplate.map.helpers({
geolocationError: function() {
var error = Geolocation.error();
return error && error.message;
},
mapOptions: function() {
var latLng = Geolocation.latLng();
// Initialize the map once we have the latLng.
if (GoogleMaps.loaded() && latLng) {
return {
center: new google.maps.LatLng(LAT, LNG),
zoom: MAP_ZOOM,
};
}
}
});
Template.map.onCreated(function() {
this.autorun(function () {
if (GoogleMaps.loaded()) {
$("input").geocomplete()
.bind("geocode:result", function(event, result){
DESTLAT = result.geometry.location.lat();
DESTLNG = result.geometry.location.lng();
directionsService = new google.maps.DirectionsService;
directionsDisplay = new google.maps.DirectionsRenderer;
});
}
});
});
Template.addressForm.onRendered(function() {
GoogleMaps.ready('map', function(map) {
var latLng = Geolocation.latLng();
var marker = new google.maps.Marker({
position: new google.maps.LatLng(LAT, LNG),
map: map.instance,
icon: '/game/loc_marker.png'
});
});
});
Template.addressForm.events({
'click button': function() {
var map = GoogleMaps.maps.map.instance;
calculateAndDisplayRoute(directionsService, directionsDisplay);
directionsDisplay.setMap(map);
$(".greet-overlay").toggle();
}
});

Refresh PHP that grabs Co-Ords for google maps API

I am using the google maps API to show the last position a form was submitted to my site. So I am pulling the lon and lat values from a php file as variables but I need the script to refresh every 5 seconds so that the maps marker updates without page reload.
Here is the google api script:
<script>
function initialize() {
var myLatlng = new google.maps.LatLng<?php
require($DOCUMENT_ROOT . "php_includes/mobile_loc.php");
?>;
var mapOptions = {
zoom: 15,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Last Scan'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
And here is the php file:
<?php
include_once("php_includes/db_conx.php");
$sql = "SELECT * FROM patdub ORDER BY STR_TO_DATE(Timestamp, '%d/%m/%Y %H:%i:%s') DESC LIMIT 1";
$query = mysqli_query($db_conx, $sql);
$row = mysqli_fetch_array($query);
$lon = $row['Lon'];
$lat = $row['Lat'];
echo "($lat, $lon)";
?>
Any ideas? I've tried different AJAX methods but just can't seem to figure it out!
Edit: The line of code below is basically the bit I need to refresh every 5 seconds but without any div tags or anything because that interferes with the google api script..
<?php require($DOCUMENT_ROOT . "php_includes/mobile_loc.php"); ?>;
You want to call load the file your PHP script is in, assuming that it is in it's own file, you would do that like so and you can then update your DOM using the return from the AJAX call.
You would wrap the AJAX call in a javascript loop such as setInterval() like this:
setInterval(function() {
$.ajax({
url: "php_script.php"
}).done(function(return) {
console.log(return);
});
, 5000);
To call it every 5 seconds.
To incorportate it with your Google function (I have no knowledge of google maps so this may not be 100% accurate):
<script>
function initialize(myLatlng) {
myLatlng = myLatlng || new google.maps.LatLng<?php require($DOCUMENT_ROOT . "php_includes/mobile_loc.php");?>;
var mapOptions = {
zoom: 15,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Last Scan'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
setInterval(function() {
$.ajax(function() {
url: 'php_script.php'
}.done(function(response) {
var latlong = response;
initialize(latLong)
});
}, 5000)
</script>

Categories

Resources