Creating an interactive InfoWindow Google Maps API - javascript

I'm trying to essentially allow the user to click options in the Google Map infowindow which would alter the content of that infowindow, i.e a page a,b,c inside the infowindow which when initially opened starts on a.
I've tried using jQuery at the top of the page (outside of the infowindow)
of the form
$(document).ready(function(){
$("#other1").click(function(){
$("#thingy").slideToggle("slow");
$("#squirry").slideToggle("slow");
});
});
and giving them id="something" inside the contentvar but to no avail
I've also tried having javascript of the form
function removeDummy() {
var elem = document.getElementById('dummy');
elem.parentNode.removeChild(elem);
return false;
}
inside the infowindow but I just get a whitescreen of death. Is there anyway you can put javascript within the html within the javascript? or anyway to allow the content of an infowindow to be changed from within the window once its already loaded.
Here is the code i'm looking at
its javascript/html nested inside some php
echo "
var myLatLng$i = {lat: $lat[$i], lng: $lng[$i]};
var image = 'nuticon.png';
var address$i = new google.maps.Marker({
position: myLatLng$i,
icon: image,
map: map});
address$i.addListener('click', function() {
document.getElementById('right-panel').innerHTML = '';
var contentString$i =
'<div id=\"content\">'+
'<div id=\"siteNotice\">'+
'</div>'+
'<h1 id=\"firstHeading\" align=\"center\" class=\"h3\">$titles[$i] </h1>'+
'<table border=\"1\" align=\"center\"><tr><p><td><b>Info</b></td><td> <b>Menu </b></td><td><b>Pictures</b></td></p></tr></table>'+
'<div id=\"bodyContent\" align=\"center\">'+
'<p></p>'+
'<iframe id=\"iframe\" src=\"http://voting.first-jump.com/init.php?a=g&g=1000000000004$i&m=0&n=5&s=25&nosound=1&f=3.png&f_a=&f_b=&f_c=\" allowtransparency=\"true\" hspace=\"0\" vspace=\"0\" marginheight=\"0\" marginwidth=\"0\" frameborder=\"0\" height=\"38\" scrolling=\"no\" width=\"128\"></iframe>'+
'</div>'+
'<p align=\"center\" id=\"logo\" ><img src=\"$i.png\" width=\"120\" onclick=\"window()\"></p>'+
'<p align=\"center\" id=\"weblink\">Website Link: <a href=\"$websites[$i]\">'+
'$titles[$i]</a> '
'</div>';
var infoWindow$i = new google.maps.InfoWindow({
map: map,
content: contentString$i,
maxWidth: 200
});
infoWindow$i.open(map, address$i);
var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer({
draggable: false,
map: map,
panel: document.getElementById('right-panel')
});
directionsDisplay.setOptions( { suppressMarkers: true } );
directionsDisplay.addListener('directions_changed', function() {
computeTotalDistance(directionsDisplay.getDirections());
});
displayRoute(pos, '$lat[$i],$lng[$i]', directionsService,
directionsDisplay);
});
";
}}}
?>

for those people trying to add tabs to your infowindow, try the infobubble library provided by Google
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobubble/examples/example.html/
provides as good a working example as I myself would post.

Related

How to display multiple colour pins on Google Maps

I am currently displaying markers on a Google Map successfully, but want to overlay a different set of markers in a different colour for something else but I'm a bit stuck on how to do it.
I am getting the data into the $markers array from a database as follows:
while($row = $result->fetch_row())
{
$rows[]=$row;
$markers[$key] = trim($row[12]).','.trim($row[13]).','.trim($row[10]).','.trim($row[9]).','.trim($row[8]).','.trim($row[4]).','.trim($row[6]).','.trim($row[3]);
$key = $key +1;
}
Where the $row[""] is the data from the database including lat and lon for the marker locations.
The magic then happens in here:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=<?=$api_key?>">
</script>
<script type="text/javascript">
var map;
var marker = {};
function initialize() {
var mapOptions = {
center: { lat: 20.1788823, lng: 13.8262155},
zoom: 2
};
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
var markers = [];
<?php
$counter = 0;
foreach ($markers as $index => $list){
$marker_details = explode(',',$list);
echo 'markers["m'.($index-1).'"] = {};'."\n";
echo "markers['m".($index-1)."'].lat = '".$marker_details[0]."';\n";
echo "markers['m".($index-1)."'].lon = '".$marker_details[1]."';\n";
$counter++;
}
?>
var totalMarkers = <?=$counter?>;
var i = 0;
var infowindow;
var contentString;
for (var i = 0; i<totalMarkers; i++){
contentString = '<div class="content">'+
'<h2 class="firstHeading">'+markers['m'+i].name+'</h2>'+
'<div class="bodyContent">'+
'<p>'+markers['m'+i].content+'</p>'+
'</div>'+
'</div>';
infowindow = new google.maps.InfoWindow({
content: contentString
});
marker['c'+i] = new google.maps.Marker({
position: new google.maps.LatLng(markers['m'+i].lat,markers['m'+i].lon),
icon: {
url: "https://maps.google.com/mapfiles/ms/icons/red.png"
},
map: map,
title: markers['m'+i].name,
infowindow: infowindow
});
//console.log(markers['m'+i].lat+','+markers['m'+i].lon);
google.maps.event.addListener(marker['c'+i], 'click', function() {
for (var key in marker){
marker[key].infowindow.close();
}
this.infowindow.open(map, this);
});
}
}
function panMap(la,lo){
map.panTo(new google.maps.LatLng(la,lo));
}
function openMarker(mName){
//console.log(marker);
for (var key in marker){
marker[key].infowindow.close();
}
for (var key in marker){
if (marker[key].title.search(mName) != -1){
marker[key].infowindow.open(map,marker[key]);
}
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
And finally it is rendered with this:
<div id="map-canvas"></div>
I have tried reading the second set of data from another data into $markers2[$key] but I'm then stuck at what to do next, I've tried quite a few different things (too many to list here!) but it either fails to render the new markers of fails to render anything at all on the map.
Any pointers in the right direction would be helpful. I'm not too familiar with javascript unfortunately.
Ok, I found the problem, the issue was that I was creating another "new" map each time and needed to remove the additional instances of :
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
Now the additional markers with the new data display correctly.
Thanks for all the downvotes, it really does concentrate the mind on finding the solution yourself!

Attempting to allow users to upload an image to an infowindow, google maps api

Just doing a bit of a university GIS project at the moment which allows users to take photos of birds they've seen and upload them with a marker on a google map in the place in which they found them.
I've managed to get the geolocation, add the marker and a clickable infoWindow but does anyone have any idea of how to allow a user to upload a photo within this infowindow?
Also how I should go about storing them so they stay on the map after the user has uploaded them?
I've included my code and an image of what I have so far!
Any help whatsoever would be hugely appreciated, I feel like i'm tearing my hair out with it.
Cheers,
Laura
<script>
//The user will be prompted to give consent to geolocation.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 6
});
var marker = new google.maps.Marker({map: map, draggable: true});
//HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
marker.setPosition(pos);
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, marker, map.getCenter());
}
// Create the info window content
var infoWindowContent = '<div class="info_content">' +
"<table>" +
"<tr><td>Name:</td> <td><input type='text' id='name'/> </td> </tr>" +
"<tr><td>Address:</td> <td><input type='text' id='address'/></td> </tr>" +
"<tr><td>Type:</td> <td><select id='type'>" +
"<option value='bird' SELECTED>bird</option>" +
"<option value='bird'>bird</option>" +
"</select> </td></tr>" +
"<tr><td><input type='button' value='Save & Close' onclick='saveData()'/></td></tr>" +
"<tr><td><input type='button' value='Add Image' onclick='saveData()'/></td></tr>"; +
'</div>';
// Display our info window when the marker is clicked
var infoWindow = new google.maps.InfoWindow({
content: infoWindowContent
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.open(map, marker);
});
}
function handleLocationError(browserHasGeolocation, marker, pos) {
marker.setPosition(pos);
marker.setContent(browserHasGeolocation ?
'Error: The Geolocation service failed.' :
'Error: Your browser doesn\'t support geolocation.');
}
</script>
https://i.stack.imgur.com/156UQ.png

Uncaught ReferenceError: saveData is not defined in Google Maps

I'm following this tutorial, using Ruby on Rails instead of PHP and MySQL (class requirements). I can right-click on the map to add a marker, left-click on the marker to make an infowindow popup, and I can fill out the infowindow, but when I click 'Save & Close' I get the error
Uncaught ReferenceError: saveData is not defined at HTMLInputElement.onclick (http://localhost:4000/#/user:1:1)onclick # VM83 user:1
Using debugger, I can confirm that saveData() never gets called.
What do I need to do to save the inputted info on the infowindow? Also, if you have input on my promise chain in mapController.js below (is it correct, etc).
Things I Have Tried
remove async defer from index.html script tag per stackOverflow suggestion.
re onclick='saveData()', I have removed the quotes and the parentheses in all permutations.
I manually typed out the line where onclick='saveData()' is found.
I moved the saveData function inside the initiliaze function per stackOverflow suggestion.
I renamed it to infowindow.saveData() per stackOverflow suggestion.
moved saveData() above initialize().
changed all lets to vars
added onload='initialize()' to div tag in _user.html, several permutations including nested divs, moving ng-controller, etc.
moved code from mapController.js to _user.html inside a script tag.
My Code
_user.html
<div ng-controller="mapController as map" id="map" style="width:100%; height:80vh;"></div>
mapController.js
angular.module('tour').controller('mapController', function() {
let self = this,
marker,
infowindow;
function initialize() {
var latlng = new google.maps.LatLng(37.0902, -95.7129);
var options = {
zoom: 4,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map"), options);
var html = "<table>" +
"<tr><td>Title:</td> <td><input type='text' id='title'/> </td> </tr>" +
"<tr><td>Description:</td> <td><input type='text' id='description'/></td> </tr>" +
"<tr><td>Audio URL:</td> <td><input type='url' id='audio'/></td> </tr>" +
"<tr><td>Category:</td> <td><select id='category'>" +
"<option value='art' SELECTED>art</option>" +
"<option value='history'>history</option>" +
"<option value='literature'>literature</option>" +
"<option value='music'>music</option>" +
"</select> </td></tr>" +
"<tr><td></td><td><input type='button' value='Save & Close' onclick='saveData()'/></td></tr>";
infowindow = new google.maps.InfoWindow({
content: html
});
google.maps.event.addListener(map, "rightclick", function(event) {
marker = new google.maps.Marker({
position: event.latLng,
map: map
});
google.maps.event.addListener(marker, "click", function() {
infowindow.open(map, marker);
}); // end addListener
}); // end addListener
} // end initialize function
function saveData() {
var marker = {
title: escape(document.getElementById("title").value),
description: escape(document.getElementById("description").value),
audio: document.getElementById("audio").value,
category: document.getElementById("category").value,
longitude: marker.lng(),
latitude: marker.lat()
}
return $http({
url: `${rootUrl}/users/:id/add_marker`,
method: 'POST',
data: {marker: marker},
headers: {
'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem('token'))
}
})
.then(function(res){
let markers = self.currentUser.markers;
let newMarker = res.config.data.marker;
markers.unshift(newMarker); // adds to beginning of array
})
.catch(function(error){
console.log('ERROR ~>', error);
});
}
initialize();
});
window.saveData = function(){ /* your code here */ }
onclick="window.saveData()"

Running a JavaScript Function From QWebView *Google Maps API, PyQT*

I'm trying to write a piece of code which reads the longitude and latitude from a database and passes that into a JavaScript function which then places a marker in correspondence to the longitude and latitude of the coordinates which have been read from the database.
After the HTML has been set to the QWebView I then use: evaluateJavaScript to attempt to run the function in the JavaScript MarkersFromDatabase.
As you can see I have modified the QWebPage class to display the console error message and when I run the program I get this error:
ReferenceError: Can't find variable: MarkersFromDatabase 0 undefined
I don't understand why it's trying to find a variable when I'm running a function.
I don't understand why this isn't running the function.
Any help would be appreciated. Sorry for the messy JavaScript formatting!
Full Code:
from PyQt4.QtWebKit import *
import sqlite3
from PyQt4.QtSql import *
class CustomQWebPage(QWebPage):
def __init__(self):
super().__init__()
def javaScriptConsoleMessage(self,message,lineNumber,sourceID):
print(message,lineNumber,sourceID)
print("javascript console message^")
class ViewOnlyMap(QWebView):
def __init__(self, parent=None):
super().__init__()
self.settings().setAttribute(QWebSettings.JavascriptEnabled, True)
self.settings().setAttribute(QWebSettings.JavascriptCanOpenWindows, True)
self.settings().setAttribute(QWebSettings.JavascriptCanAccessClipboard, True)
self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
self.CustomPage=CustomQWebPage()
self.Coordinates=None
self.set_code()
self.get_marker_coordinates()
def get_marker_coordinates(self):
with sqlite3.connect("skateboard_progress_tracker.db") as db:
cursor=db.cursor()
sql="select SkateparkLongitude, SkateparkLatitude from Skatepark"
cursor.execute(sql)
self.Coordinates=cursor.fetchall()
for coordinate in self.Coordinates:
self.CustomPage.mainFrame().evaluateJavaScript('MarkersFromDatabase({0},{1})'.format(coordinate[0],coordinate[1]))
print("Marker added")
print(coordinate[0])
print(coordinate[1])
def set_code(self):
self.html='''<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Simple markers</title>
<style>
html, body, #map-canvas {
height: 100%;
width: 100%
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
var map;
var markers = [];
var results = [];
var coords = [];
var highestLevel;
function initialize() {
var Centre = new google.maps.LatLng(52.20255705185695,0.1373291015625);
var mapOptions = {
zoom: 8,
minZoom: 3,
center: Centre,
}
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
google.maps.event.addListener(map, 'click', function(event) {
AddMarker(event.latLng);
});
}
function MarkersFromDatabase(SkateparkLat,SkateparkLng) {
var Skatepark = new google.maps.LatLng(SkateparkLat,SkateparkLng);
//return Skatepark;
AddMarker(Skatepark); }
function AddMarker(location) {
var marker = new google.maps.Marker({
title: 'Test',
position: location,
animation: google.maps.Animation.DROP,
map: map
});
//markers.push(marker);
var lat = marker.getPosition().lat();
var lng = marker.getPosition().lng();
markers.push({"Object":marker,"Lat":lat,"Lng":lng});
var contentString = '<div id="content">'+
'<div id="siteNotice">'+
'</div>'+
'<h1 id="firstHeading" class="firstHeading">Skatepark</h1>'+
'<div id="bodyContent">'+
'<p>A skatepark description </p>'+
'</div>'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker, 'rightclick', function(event) {
marker.setMap(null);
});
google.maps.event.addListener(marker, 'mouseover', function(event) {
infowindow.open(map,marker);
});
}
function GetMarkers(){
return markers;
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html> '''
self.setHtml(self.html)
You need to give the web-page a chance to load before attempting to call javascript functions. So add a handler for the loadFinished signal:
class ViewOnlyMap(QWebView):
def __init__(self, parent=None):
super().__init__()
...
self.setPage(self.CustomPage)
self.loadFinished.connect(self.handleLoadFinished)
self.set_code()
def handleLoadFinished(self, ok):
if ok:
print("Page loaded successfully")
self.get_marker_coordinates()
else:
print("Could not load page")

Integrating Google Maps w/ WordPress - Infowindow not opening

I am currently trying to incorporate a map on the homepage of my wordpress blog which will display a custom icon on a map based on a post content and customfield location. I am very close and got everything working except the infowindow. I get no errors and no window. Your help is much appreciated.
I looked at similar questions and tried a few things but nothing worked.
Here is my code:
<script type="text/javascript">
function initialize() {
// setup map
var latlng = new google.maps.LatLng(34.109739, -118.351936);
var myOptions = {
zoom: 10,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
var infowindow = new google.maps.InfoWindow();
// icons
var bootIcon = '/images/icons/bootIcon.png';
var hikingIcon = '/images/icons/hikingIconSm.png';
// Init post Data
var i = 0;
var hikingPositions = new Array();
var hikingMarkers = new Array();
var hikingBlurbs = new Array();
<?php $hiking_query = new WP_Query('category_name=hiking_ctg&posts_per_page=4');
while ($hiking_query->have_posts()) : $hiking_query->the_post();?>
<?php $geoLoc = get_post_meta($post->ID, 'longlat', true); ?>
// Set Post data
hikingPositions[i] = new google.maps.LatLng(<?php echo $geoLoc; ?>);
hikingMarkers[i] = new google.maps.Marker({
position: hikingPositions[i],
map: map,
icon: hikingIcon,
title:"<?php the_title(); ?>"
});
hikingBlurbs[i] = '<div id="content"><h1 id="firstHeading" class="firstHeading"><?php the_title(); ?></h1><div id="bodyContent"><p>.</p></div></div>';
i++;
<?php endwhile; ?>
// Assign data to map
for(var j=0, marker; j < hikingMarkers.length; j++)
{
// To add the marker to the map, call setMap();
hikingMarkers[j].setMap(map);
marker = hikingMarkers[j];
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(hikingBlurbs[j]);
infowindow.open(map,this);
});
}
}
$(document).ready(function() {
initialize();
});
</script>
I still have a long way to finish all the functionality I am looking for, but for this build, this is the only thing not working.
Thanks in advance.
Regards,
GeneralChaos
I am sure there are more elegant solutions to this, but this worked.
I noticed that the event handler I was using was receiving the index only when the loop was over so I changed the marker to 'this' and added an 'content' value to the marker object.
Define the content array before the marker:
hikingBlurbs[i] = '<div id="infowindowContent"><h1><?php the_title(); ?></h1><div id="bodyContent"><p>.</p></div></div>';
Define your marker with the new content variable:
// Set Post data
hikingPositions[i] = new google.maps.LatLng(<?php echo $geoLoc; ?>);
hikingMarkers[i] = new google.maps.Marker({
position: hikingPositions[i],
map: map,
icon: hikingIcon,
title:"<?php the_title(); ?>",
content: hikingBlurbs[i]
});
Now add the event listener with some simple changes:
// Assign data to map
for(marker in hikingMarkers)
{
google.maps.event.addListener(hikingMarkers[marker], 'mouseover', function() {
infowindow.setContent(this.content);
infowindow.open(map,this);
});
}
Let me know if you see a better way of doing this or you have any questions.
Best Regards,
GeneralChaos

Categories