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()"
Related
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!
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
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.
I want your guys' help on this. I wrote the code for allowing users to create markers(with infowindow) with a 'click' function that will save the lat/lan and other info to a MySQL database that will then be called to show the markers on the map. When you click on the map, it creates a marker but it will not save the info in the infowindow to the database. I followed the guide from the google maps developer's guide but I still can't get it to work. I even triple checked to make sure my MySQL login details work correct and still nothing.
Here is the code to the map itself:
<!DOCTYPE html >
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Map Simple</title>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js? sensor=false"></script>
<script type="text/javascript">
var marker;
var infowindow;
function initialize() {
var latlng = new google.maps.LatLng(37.4419, -122.1419);
var options = {
zoom: 13,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map-canvas"), options);
var html = "<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='bar' SELECTED>bar</option>" +
"<option value='restaurant'>restaurant</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, "click", function(event) {
marker = new google.maps.Marker({
position: event.latLng,
map: map
});
google.maps.event.addListener(marker, "click", function() {
infowindow.open(map, marker);
});
});
}
function saveData() {
var name = escape(document.getElementById("name").value);
var address = escape(document.getElementById("address").value);
var type = document.getElementById("type").value;
var latlng = marker.getPosition();
var url = "phpsqlinfo_addrow.php?name=" + name + "&address=" + address +
"&type=" + type + "&lat=" + latlng.lat() + "&lng=" + latlng.lng();
downloadUrl(url, function(data, responseCode) {
if (responseCode == 200 && data.length <= 1) {
infowindow.close();
document.getElementById("message").innerHTML = "Location added.";
}
});
}
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.responseText, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
</script>
</head>
<body style="margin:0px; padding:0px;" onload="initialize()">
<div id="map-canvas" style="width: 500px; height: 300px"></div>
<div id="message"></div>
</body>
</html>
This is what is supposed to save info to the database(phpsqlinfo_addrow.php):
<?php
require("phpsqlinfo_dbinfo.php");
// Gets data from URL parameters
$name = $_GET['name'];
$address = $_GET['address'];
$lat = $_GET['lat'];
$lng = $_GET['lng'];
$type = $_GET['type'];
// Opens a connection to a MySQL server
$connection=mysql_connect ("localhost", $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());
}
// Insert new row with user data
$query = sprintf("INSERT INTO markers " .
" (id, name, address, lat, lng, type ) " .
" VALUES (NULL, '%s', '%s', '%s', '%s', '%s');",
mysql_real_escape_string($name),
mysql_real_escape_string($address),
mysql_real_escape_string($lat),
mysql_real_escape_string($lng),
mysql_real_escape_string($type));
$result = mysql_query($query);
if (!$result) {
die('Invalid query: ' . mysql_error());
}
?>
hi i have same issue with my project to save customer location,
which they click on there browser,
what i did was i save location in latitude and longitude in two input box as{you may take it hidden so it will not seen} in and give submit button and submit form i have given code you can also change it to submit form on click on map by submitting form on click by this and you can also store latitude and longitude in same column if you want
and you will need to insert you key
document.getElementById("yourform").submit();
<html>
<head>
<style type="text/css">
#map_canvas {height:300px;width:500px}
</style>
<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&key=""""youerapikeyhere""""&language=mr"></script>
<script type="text/javascript">
var map;
var marker;
var markersArray = [];
function initialize()
{
var latlng = new google.maps.LatLng(18.5236, 73.8478);
var mapOptions = {
zoom: 13,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
google.maps.event.addListener(map, 'click', function(event) {
if (marker) {
marker.setMap(null); //code
}
//adding marker
document.getElementById('txtLat').value=event.latLng.lat();
document.getElementById('txtLng').value=event.latLng.lng();
marker= new google.maps.Marker({
position: event.latLng,
map: map,
title: 'pune'
});
//creting info window instance
var infowindow = new google.maps.InfoWindow({
content: 'selected location'
});
//adding pointer click event to open infowindow
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<table cellpadding="0" cellspacing="0">
<tr><td colspan=3><div id="map_canvas" style="background-color: #ffffff"></div></td></tr>
<tr><td><input type="text" id="txtLat" name="txtLat"style="width:150px"></td>
<td><input type="text" id="txtLng" name="txtLng"style="width:150px"></td></tr>
</table></form>
</html>`
Try to narrow down the possibilities, or at least find out "where" it went wrong; meaning, is the issue caused from the front end or in the backend!?
If you use Webkit UA (browser) or its variants, use its Developer tools; if using Firefox, install an AddOn called FireBug. In the marker's click handler, try to output the coordinates using alert() or console.log() and see if the results are accurately fetched. Next check whether the AJAX call is passed as it should be to the backend.
In your PHP, try to examine the incoming values (from request parameters). Also turn on the debug output in php.ini so you'll know if the DB connections are successfully made by checking stderr or system logs.
There's a lot of things that could go wrong. It's hard to tell given by the lack of details you provided, but I hope my reply helps you to get a good start.
Oh, BTW, I'd strongly suggest you switch to PDO over mysql_, the mysql_ are to be deprecated in the future.
I am trying to make the map load markers - pulled in from an xml file. It currently does this perfectly. However I also want the map to reload new markers based upon the month passed through from a hyperlink.
When the 'global_month' variable is changed via hyperlink the ajax request fires and the 'data_array' should be repopulated with the new data based upon the date passed to the 'if' statement later on. However it reuses the 'data_array' contents, and doesn't fill it with new data.
I have tried resetting the 'global_month' via 'global_month = []' in the 'change_date_range' function, however - the array doesn't seem to be refilled. I have spent 3 hours trying to work out where I am going wrong, but cannot. Can anyone help? Also is there a more efficient way of doing this?
Thank you very much for you time!
/////////////////////////////////////////////
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="jquery-1.7.1.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script>
$(document).ready(function()
{
$.ajax({
type: "GET",
url: "driving_test_centers.xml",
dataType: "xml",
success: parseXml
});
});
var global_month = 6;
function refetch()
{
$.ajax({
type: "GET",
url: "driving_test_centers.xml",
dataType: "xml",
success: parseXml
});
};
var data_array = [];
var empty_holder;
var empty_month;
var info_date;
var address1;
var address2;
var town;
var county;
var postcode;
var lat;
var lon;
var male_pass_percentage1;
var male_pass_percentage;
var female_pass_percentage1;
var female_pass_percentage;
var the_new_date;
var infowindow;
var xml_contents;
function parseXml(xml)
{
$(xml).find("test_center").each(function() // look for all of the test centers
{
center_name = $(this).attr('name');
address1 = $(this).find('address1').text();
address2 = $(this).find('address2').text();
town = $(this).find('town').text();
county = $(this).find('county').text();
postcode = $(this).find('postcode').text();
lat = $(this).find('lat').text();
lon = $(this).find('lon').text();
$(this).find("date_info").each(function()
{
info_date = $(this).attr('date');
empty_month = $(this).find('month').text();
male_pass_percentage = $(this).find('male');
male_pass_percentage = male_pass_percentage.find('pass_percentage').text();
female_pass_percentage = $(this).find('female');
female_pass_percentage = female_pass_percentage.find('pass_percentage').text();
if(empty_month == global_month){
data_array.push([lat,lon,center_name,info_date,male_pass_percentage,female_pass_percentage]);
}
});
});
}
function change_date_range(the_new_date){
global_month = the_new_date;
refetch();
init();
};
</script>
<script>
function init() {
var options = {
zoom: 5,
center: new google.maps.LatLng(55.3781, -3.4360),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var places;
places = null;
var map = new google.maps.Map(document.getElementById('map'), options);
var bounds = new google.maps.LatLngBounds();
var places = data_array;
var temp_location;
for (var i = 0; i < places.length; i++) {
temp_location = new google.maps.LatLng(places[i][0], places[i][1])
// Adding the markers
var marker = new google.maps.Marker({
position: temp_location,
map: map,
title: places[i][2]
});
// Wrapping the event listener inside an anonymous function
// that we immediately invoke and passes the variable i to.
(function(i, marker) {
// Creating the event listener. It now has access to the values of
// i and marker as they were during its creation
google.maps.event.addListener(marker, 'click', function() {
// Check to see if we already have an InfoWindow
if (!infowindow) {
infowindow = new google.maps.InfoWindow();
}
// Setting the content of the InfoWindow
infowindow.setContent(places[i][2] + "<br />" + global_month + "<br />" + places[i][3] + "<br /><br />Male: " + places[i][4] + "%<br />Female: " + places[i][5] + "%");
// Tying the InfoWindow to the marker
infowindow.open(map, marker);
});
})(i, marker);
// Extending the bounds object with each LatLng
bounds.extend(temp_location);
}
// Adjusting the map to new bounding box
map.fitBounds(bounds)
};
</script>
</head>
<body onload="init()">
<div id="map" style="width:800px;height:600px"></div>
click
</body>
</html>
/////////////////////////////////////////////////////////////
XML file (small part of):
http://tinypaste.com/198889bb
You're not clearing out the data_array array...you just continue to add to it. Why don't you add data_array = []; to the beginning of the parseXml function
edit: you should also clear the markers that are already placed...a good way to make that easy is that when you add markers, hold them in an array, then you can loop through it, setting the map attribute of each to null:
for (x=0;x<markers.length;x++) {markers[x].setMap(null);}