I've done something (not sure what) to my map and now a function that was running is now throwing the following error:
Invalid value for property <travelMode>: undefined line 16 main.js
The last thing I did was add the line:
directionsDisplay.setPanel(document.getElementById("directions"));
So that I can display direction details in a div. Here's my code for reference:
// This function sets-up and initiates the Google maps interface
function load_map() {
startLatLng = new google.maps.LatLng(52.485809,-1.888783);
// create a new Google latLang marker object with co-ords for
//the start location
var config = {
zoom: 5,
center: startLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create a JASON object to store map configruation
map = new google.maps.Map(document.getElementById("map"), config);
// intilise the map passing the display divs id and the config
// object
var startMarker = new google.maps.Marker({
position: startLatLng,
map: map
})
startMarker.setIcon('/imgs/startMarker.png');
// create a new marker object for start (passing anonomus JASON
// config object)
startMarker.setMap(map);
// Add the marker to the map
geocodeAddress("ARM Ltd Rockingham Court 152 Rockingham Street Sheffield Great Britain");
geocodeAddress("Centrum House 36 Station Road Egham Surrey");
geocodeAddress("Pipers Way Swindon United Kingdom");
// call the geocoding function to add markers to the map
}
/*
* This function loads a marker overlay on to the location provided
* and calls the addInfoWindow function to add an info window to it
* #param a location: google location object representing the location at which
* the marker is to be placed
* #param a windowText: String variable representing the information to be attached
* to the window.
*/
function loadMarker(location,windowText,address) {
var tempMarker = new google.maps.Marker({
position: location,
map: map,
address:address,
selected:"false"
});
google.maps.event.addListener(tempMarker, 'click',function(){
selectLocation(tempMarker);
});
google.maps.event.addListener(tempMarker, 'dblclick',function(){
deselectLocation(tempMarker);
});
addInfoWindow(windowText,tempMarker,tempMarker.address);
// add an information window anchored on the marker
tempMarker.setIcon('/imgs/workofficeMarker.png');
markersArray.push(tempMarker);
tempMarker.setMap(map);
// add the marker to the map at this location
}
/*
* A function to geocode the string type address passed into usable
* lat lng type co-ords
* #param address: a String representing the address to be geocoded
*/
function geocodeAddress (address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode( {'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
loadMarker(results[0].geometry.location,"Info here",address);
latlngArray.push(results[0].geometry.location);
} else {
alert("Geocode was not successful for the following reason: " +" "+ status);
}
});
}
/*
* This function adds an info window to each marker and allows it
* to be activated on click.
* #Param infoText: a String representing the data to be included in the
* info window
* #Param marker: a Google Marker Object to attach the Text Window to.
*/
function addInfoWindow (infoText,marker) {
var contentString = '<div id = "windowContent">'+
'<h4> Details</h4>'+'</div>'+
'<div id ="windowContent">'
+'</br>'
+infoText
+ '</br>'
+ '<p><label for="mapsUkSaddr">Your address</label> <form action="http://maps.google.co.uk/maps" method="get" target="_blank">'
+ '<input type="text" name="saddr" id="mapsUkSaddr" value="" size="20"/>'
+ '<input type="submit" value="Get directions" />'
+'<input type="hidden" name="daddr" value=' + '\"'+ marker.address +'\"' + '/>'
+'<input type="hidden" name="hl" value="en" /> </p>'
+ '</form>'
+ '</div>';
var tempInfoWindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker,'rightclick', function() {
tempInfoWindow.open(map,marker);
});
}
/*
* A function to resize the bounds of the map to fit selected locations
*
*/
function getSelected () {
if (markersArray.length == 0) {
return -1;
}
else {
selectedMarkersAdds = new Array();
for (var i = 0; i < markersArrayAdds.length; i++) {
if ( markersArray[i].selected == "true") {
selectedMarkersAdds.push( markersArray[i].address)
}
}
return selectedMarkersAdds;
}
}
function sizeMap() {
var bounds = new google.maps.LatLngBounds();
for ( var i = 0; i < 1; i++) {
alert(latlngArray[i]);
var tempLatLng = new google.maps.LatLng(latlngArray[i]);
alert(tempLatLng);
bounds.extend(tempLatLng);
}
map.fitBounds(bounds);
}
/*
* This function allow a given location to be selected as a potential
* vist location. The location is added to the selected array to
* allow resizing and changes the icons colour to show selection
* #param a marker: Google maps Marker object representing the marker to be
* selected.
*/
function selectLocation (marker) {
var markerIndex = checkForMarker(marker);
if (markerIndex == -1) {
alert ("Marker specified in selection not found");
return;
}
else {
markersArray[markerIndex].selected = "true";
markersArray[markerIndex].setIcon('/imgs/workofficeRedMarker.png');
return;
}
}
/*
* Allows the specified marker to be deselected
* #param marker: a Google Maps marker object representing the marker
* to be deselected
*/
function deselectLocation (marker) {
var markerIndex = checkForMarker(marker);
if (markerIndex == -1) {
alert ("Marker specified in deselection not found");
return;
}
else {
markersArray[markerIndex].selected = "false";
markersArray[markerIndex].setIcon('/imgs/workofficeMarker.png');
return;
}
}
/*
* This function allows a route to be calculated to each location
* selected and displayed: Google maps LatLng object representing the start of the route
* #param a endLocation: Google maps LatLng object representing the end of the route
*/
function calculateRoot (startLocation,endLocation) {
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById("directions"));
var request = {
origin:startLocation,
destination:endLocation,
provideRouteAlternatives: true
};
directionsService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
}
});
}
/*
* This function shows the route from the chosen start location
* to all of the avaliable placement locations
*/
function showSpiderView(){
for (var i = 0; i<latlngArray.length; i++ ) {
calculateRoot(startLatLng,latlngArray[i]);
}
sizeMap();
}
/*
* This function allows the selectedLocations array to be checked
* to see if a fiven marker has already been selected
* #param marker: A Google maps marker type object to be searched for
* #return integer value of array postion if marker is found -1 otherwise
*/
function checkForMarker (marker) {
if (markersArray.length !=0){
for (var i = 0; i < markersArray.length; i++ ) {
if (marker.address == markersArray[i].address){
return i
}
}
}
else {
return -1;
}
}
/*
* Display only placement locations that have been selected by the
* user
*/
function showOnlySelected () {
clearMarkers();
if (markersArray.length != 0) {
for (var i = 0; i < markersArray.length; i ++ ) {
if (markersArray[i].selected == "true") {
markersArray[i].setMap(map);
}
}
}
else {
alert ("No locations are avaliable to show");
return;
}
}
/*
* A function to allow all placement locations to be displayed
*/
function showAll () {
clearMarkers();
if (markersArray != 0) {
for (var i = 0; i < markersArray.length; i ++) {
markersArray[i].setMap(map);
}
}
else {
alert ("No markers found to display")
return;
}
}
/*
* A function to allow all markers to be cleared from the screen
*/
function clearMarkers () {
if (markersArray.length != 0) {
for (var i = 0; i < markersArray.length; i ++) {
markersArray[i].setMap(null);
}
}
else {
alert ("No markers avaliable to clear");
}
}
// initilise all the page components by calling there load functions
function init () {
load_grid();
load_map();
}
Seemed to be working last night but I must have changed something before i stopped working. (which will teach me not to code tired at 2:00 am :-))
Can any of you good people shed some light?
As Requested line 16 reads:
J.toSpan=function(){return new P(this.$[Ta]()?0:this.$.d-this.$.b,ge(this.ba),i)};na(J,function(){return this.$[Ta]()||this.ba[Ta]()});function je(a,b){return function(c){if(!b)for(var d in c)a[d]||aa(ia("Unknown property <"+(d+">")));var e;for(d in a)try{var f=c[d];if(!a[d](f)){e="Invalid value for property <"+(d+(">: "+f));break}}catch(g){e="Error in property <"+(d+(">: ("+(g[dc]+")")));break}e&&aa(ia(e));return i}}function ke(a){return a==j}function le(a){try{return!!a.cloneNode}catch(b){return k}}function me(a,b){var c=Kd(b)?b:i;return function(b){return b==j&&c||b instanceof a}}
Been trying to work out what it means but cant make much of it, think it may have something to do with the JSON request object but I'm not sure
Your request
var request = {
origin:startLocation,
destination:endLocation,
provideRouteAlternatives: true
};
should also specify travelMode, eg
travelMode: google.maps.DirectionsTravelMode.DRIVING
http://code.google.com/apis/maps/documentation/javascript/reference.html#DirectionsRequest
Related
This is the updated final code that I got it to work. I use the get.zoom and center.change to ensure that no matter the view of the map, there will always be 10 markers on the map! (original question below
'''
// Declare map and markers array globally
var map, markers = [];
function initMap() {
var myLatLng = {
lat: 0,
lng: 0
};
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: myLatLng,
zoomControl: true
});
// Moved this out of the AJAX success and declared variable correctly
var infowindow = new google.maps.InfoWindow();
// Listen for zoom change event
// Handle markers display
google.maps.event.addListener(map, 'zoom_changed', handleMarkersDisplay);
$.ajax({
type: 'GET',
url: 'https://us-central1-cloud-calendar-project.cloudfunctions.net/InfoWindow',
success: function(data) {
data = JSON.parse(data);
for (var element in data) {
var marker = new google.maps.Marker({
position: {
lat: data[element].lat,
lng: data[element].lon
},
map: map,
title: element,
visible: false, // Default visibility is false
marker_celsius: data[element].celsius // Add celsius as marker property
});
console.log("marker#" + marker.getPosition().toUrlValue());
// Push this marker to the markers array
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker, element) {
return function() {
var content = 'Country: ' + data[element].country;
content += '<br>Temperature (°C): ' + data[element].celsius;
content += '<br>Day: ' + data[element].day;
content += '<br>Month: ' + data[element].month;
infowindow.setContent(content);
infowindow.open(map, marker);
}
})(marker, element));
}
// All markers have been added, sort the markers array by celsius value
markers.sort(function(a, b) {
return b.marker_celsius - a.marker_celsius;
});
map.addListener('center_changed', function() {
window.setTimeout(handleMarkersDisplay() , 3000);
});
// Handle markers display
handleMarkersDisplay();
}
});
}
function handleMarkersDisplay() {
console.log("handleMarkerDisplay zoom=" + map.getZoom());
// Check if map current zoom <= 2
if (map.getZoom() <= 2) {
hideAllMarkers();
displayMarkers();
} else if (map.getZoom() == 3) {
hideAllMarkers();
displayMarkers();
} else if (map.getZoom() == 4) {
hideAllMarkers();
displayMarkers();
} else if (map.getZoom() == 5) {
hideAllMarkers();
displayMarkers();
}
}
function hideAllMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setVisible(false);
}
}
function displayMarkers() {
// add new markers to map
var shownMarkers = 10;
for (var i = 0; i < markers.length; i++) {
// Only show the first 10 markers in the viewport
if (shownMarkers > 0) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
shownMarkers--;
}
} else {
markers[i].setVisible(false);
}
}
}
function displayAllMarkers() {
// Zoom is greater than 3, show all markers
for (var i = 0; i < markers.length; i++) {
markers[i].setVisible(true);
}
}
'''
I am working on a web application whereby I want to show markers on a map based on the highest temperature recorded (from a JSON file I parse through). Currently, I am able to get the 10 highest temperatures markers on the map but when I zoom in it does not get updated to add new markers. So when I zoom in one I go from 10 markers to 8 markers in view(you need to scroll to see the other two markers). I would like to add two new markers that correspond to the next highest markers for that view so that whatever view/zoom you have you always see 10 markers! (probably not possible at some level, eg only see one country). The picture below demonstrates that at zoom 3, two markers are left out of view.
I found this implementation (https://github.com/endiliey/cs50/blob/master/pset8/mashup/static/scripts.js) by endiliey. However the implementation is not working..
If you want to show the highest 10 markers in the viewport, you need to count those:
function displayMarkers() {
// add new markers to map
var shownMarkers = 10;
for (var i = 0; i < markers.length; i++) {
// Only show the first 10 markers in the viewport
if (shownMarkers > 0) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
shownMarkers--;
} else {
markers[i].setVisible(false);
}
} else {
markers[i].setVisible(false);
}
}
}
Then call that function, when you load new markers or update the zoom:
proof of concept fiddle
code snippet:
// Declare map and markers array globally
var map, markers = [];
function initMap() {
var myLatLng = {
lat: 0,
lng: 0
};
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: myLatLng,
zoomControl: true
});
// Moved this out of the AJAX success and declared variable correctly
var infowindow = new google.maps.InfoWindow();
// Listen for zoom change event
// Handle markers display
google.maps.event.addListener(map, 'zoom_changed', handleMarkersDisplay);
$.ajax({
type: 'GET',
url: 'https://us-central1-cloud-calendar-project.cloudfunctions.net/InfoWindow',
success: function(data) {
removeMarkers();
data = JSON.parse(data);
for (var element in data) {
var marker = new google.maps.Marker({
position: {
lat: data[element].lat,
lng: data[element].lon
},
map: map,
title: element,
visible: false, // Default visibility is false
marker_celsius: data[element].celsius // Add celsius as marker property
});
console.log("marker#" + marker.getPosition().toUrlValue());
// Push this marker to the markers array
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker, element) {
return function() {
var content = 'Country: ' + data[element].country;
content += '<br>Temperature (°C): ' + data[element].celsius;
content += '<br>Day: ' + data[element].day;
content += '<br>Month: ' + data[element].month;
infowindow.setContent(content);
infowindow.open(map, marker);
}
})(marker, element));
}
// All markers have been added, sort the markers array by celsius value
markers.sort(function(a, b) {
return b.marker_celsius - a.marker_celsius;
});
console.log("loaded "+markers.length+" markers");
// Handle markers display
handleMarkersDisplay();
}
});
}
function handleMarkersDisplay() {
console.log("handleMarkerDisplay zoom=" + map.getZoom());
// Check if map current zoom <= 2
if (map.getZoom() <= 5) {
displayMarkers();
} else {
displayAllMarkers();
}
}
function removeMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
}
function hideAllMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setVisible(false);
}
}
function displayMarkers() {
// add new markers to map
var shownMarkers = 10;
for (var i = 0; i < markers.length; i++) {
// Only show the first 10 markers in the viewport
if (shownMarkers > 0) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
shownMarkers--;
} else {
markers[i].setVisible(false);
}
} else {
markers[i].setVisible(false);
}
}
}
function displayAllMarkers() {
// Zoom is greater than 3, show all markers
for (var i = 0; i < markers.length; i++) {
markers[i].setVisible(true);
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap" async defer></script>
I am working on a website in which I want to make a circle on google map either around current location or some manual address.
Users will have option to decide whether they want to make circle around current location or some random address they will provide. (Users would have the option to put manual address inside current location as shown below in an image)
Now we also need to make sure that circle is of particular radius (0-20/70km from the current location) as well and user needs to decide that as well. (The line beneath the current location will decide the radius which users can move here and there 0-70km)
For example: user want to create a circle from current location till 30KM or user want to create a circle from some random address till 20KM.
The HTML code which I have used in order to make a search bar for search radius is:
<div class="input-searchradius">
<input class="form-control search_radius mb-4" type="text" placeholder="search radius">
</div>
Problem Statement:
(1) I am wondering what changes I need to make or code I need to add so that the items are being searched around a specific radius. I think, I need to integrate the code Google Maps circle but I am not sure how I can do that.
(2) On hit of search radius on the website the following options/screen will appear at the bottom:
Let's try to give you some first steps, I would no code the whole app, but rather give you some guide lines in to how to solve the small subproblems that you have:
Adding a circle in a map
Well, for this you have many different options for input, but the most important part is the addCircle function:
function addCircle(center){
circle = new google.maps.Circle({
map: map, //The existing map
center: center,
radius: 200, //This will be modified afterwards
zindex: 100
});
}
The center could come from a click for example:
// Area is wherever you want to attach the click, either a polygon, a map...
google.maps.event.addListener(area, "click", function(event) {
addCircle(event.latLng);
});
OR by getting the position of a certain address (This is documented as well), OR whatever method (drag and drop the circle, drag the marker blablabla)
Adding a dynamic radius
Well, if we know that the radius of the Circle is given in meters, then is very easy to give the addCircle function the correct radius. For example, 20km -> 20 000 meters. So you just have to be able to access radius when calling addCircle (it can be an argument, a global variable... your choice).
We are done with the drawing part, lets now search within that circle.
Getting only the markers inside the circle
There is a prerequisite here, to have all the markers of your map. You may have an array of places that you get from a database or maybe you get the markers from Google Maps API (Place search for example).
After that you will have to compute the distance between those markers and your given center, and check if the distance is smaller than your radius (with computeDistanceBetween is very easy), so you will know which markers are valid for you.
const markers = [//array of my valid markers with position];
markers.filter( (marker) =>
google.maps.geometry.spherical.computeDistanceBetween(marker.getPosition(), center.getPosition()) < radius; // Filter the markers which distance is bigger than radius;
The rest of the job should be as easy, place the markers in the map and do whatever you like with this information.
EXTRAS
As a further help there are a pair of examples/answers that may be useful for you:
Full Google Map API example, very easy step by step guide.
Radius search using places, a good answer in to how to do radius search.
Example of radius search, open F12 and debug the code if you like, but it is easy to follow.
EDIT**: I did not realize that 2 of these link where also pointed out in the comments.
I recommend using a worker thread to do the searching to free up the UI thread by doing the searching in the background. This is also useful if the user moves the circle or expands/contracts it as the previous search/render of matching markers can be abandoned,
importScripts("Tier3Toolbox.js");
var currVintage = 0;
var inBounds = false;
var facFilter = [];
var imageProlog = "<div style='height:5em; width:5em; display:inline-block;vertical-align:middle;'>" +
"<img style='height:100%; width: 100%; max-height:100%; max-width:100%' src='";
var imageEpilog = "' ></div>";
var facilityTable, lineBreak;
self.addEventListener('message', function(e)
{
var data = e.data;
switch (data.cmd) {
case 'init':
initThread(data.load);
break;
case 'initFilter':
for (var i=0; i<data.filterTable.length; i++) {
facFilter[data.filterTable[i].locTypeId] = {'icon':data.filterTable[i].icon};
}
break;
case 'filter':
facFilter = [];
for (var i=0; i<data.filterTable.length; i++) {
if (data.filterTable[i].facSelected)
facFilter[data.filterTable[i].locTypeId] = {'icon':data.filterTable[i].icon};
}
break;
case 'search':
var searchVintage = ++currVintage;
var tableSearch = new searcher(searchVintage, data);
break;
case 'reset':
reset();
self.postMessage({'reset': true});
break;
case 'stop':
self.postMessage({'success' : true});
self.close();
break;
default:
self.postMessage({'success' : false, 'msg' : data.msg});
};
}, false);
function initThread(msg)
{
facilityTable = JSON.parse(msg);
reset();
self.postMessage({'success' : true,
'cnt' : facilityTable.length
});
}
function reset()
{
for (var i=0; i<facilityTable.length; i++) {
facilityTable[i].visible=false
}
currVintage = 0;
}
function searcher(searchVintage, msg)
{
var myVintage = searchVintage;
var facIndex = -1;
var msg = msg;
var checkLoop = function()
{
if (myVintage != currVintage)
return;
if (++facIndex == facilityTable.length)
return;
inBounds = geoFencer.call(this, msg);
if (inBounds) {
var facMatch = 0;
var bubbleHTML = "";
for (var i=0; i<facilityTable[facIndex].facilities.length; i++){
var currFac = facilityTable[facIndex].facilities[i];
if (facFilter[currFac.locTypeId] != undefined) {
if (facMatch != 0) {
lineBreak = (facMatch / 3);
if (lineBreak == lineBreak.toFixed(0)) {
bubbleHTML += "<br />";
}
}
facMatch++;
bubbleHTML += imageProlog + facFilter[currFac.locTypeId].icon + imageEpilog;
}
}
if (facMatch == 0) {
inBounds = false;
}
}
if (inBounds != facilityTable[facIndex].visible) {
self.postMessage({'match' : inBounds,
'facIndex' : facIndex,
'scopeVintage': msg.scopeVintage,
'bubbleHTML' : bubbleHTML,
'success' : true
});
facilityTable[facIndex].visible = inBounds;
}
setTimeout(checkLoop,0);
}
var circleCheck = function(msg)
{
var diff = Tier3Toolbox.calculateDistance(
msg.centerLat,
msg.centerLng,
facilityTable[facIndex].searchLat,
facilityTable[facIndex].searchLng);
if (msg.radius > diff)
return true;
return false;
}
var rectangleCheck = function(msg)
{
if (facilityTable[facIndex].searchLat > msg.SWLat &&
facilityTable[facIndex].searchLat < msg.NELat &&
facilityTable[facIndex].searchLng > msg.SWLng &&
facilityTable[facIndex].searchLng < msg.NELng)
return true;
return false;
}
var GEOFENCER = [circleCheck,rectangleCheck];
var geoFencer = GEOFENCER[msg.checker];
setTimeout(checkLoop,0);
return this;
}
The "Toolbox" functions referred to are : -
function Tier3Toolbox()
{
return this;
}
Tier3Toolbox.EARTH_RADIUS = 6378137; /* Equitorial Radius instead of 6371000 */
Tier3Toolbox.toRad =
function (num) {
return num * Math.PI / 180;
};
Tier3Toolbox.calculateDistance =
function(lat1, lon1, lat2, lon2){
var dLat = this.toRad(lat2 - lat1);
var dLon = this.toRad(lon2 - lon1);
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.toRad(lat1)) *
Math.cos(this.toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
var distance = this.EARTH_RADIUS * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return distance;
}
Tier3Toolbox.prototype.callAJAX =
function(url, method, callback, serverArgs)
{
var callback = callback;
var xmlhttp;
var target = url;
var args = (serverArgs != undefined) ? serverArgs : "";
var postArgs = "";
var callbackArgs = new Array();
for (i = 4; i < arguments.length; i++) {
callbackArgs[i - 3] = arguments[i];
}
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
callbackArgs[0] = xmlhttp;
if (method.toUpperCase() == "GET") {
target = target + "?" + args;
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
callback.apply(this, callbackArgs)
} else {
throw new Error("Error making Ajax call to " + target + " Status = " + xmlhttp.status);
}
}
};
xmlhttp.open(method, url, true);
if (method.toUpperCase() == "POST") {
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
postArgs = args;
}
xmlhttp.send(postArgs);
}
Tier3Toolbox.reportError =
function(error)
{
var header = error.header || "Error";
var message = error.message || "";
var topWindow=window.top.document.open();
topWindow.write("<!DOCTYPE html><html><body style='height: 100%;'><hr><h1>" + header + "</h1><hr>");
topWindow.write("<h2>Please contact Server Support for assistance.</h2><br />");
topWindow.write('<p style="color:red">' + message + "</p></body></html>");
topWindow.close();
return;
}
In you mainline you need to add listeners like: -
google.maps.event.addDomListener(radarCircle, 'center_changed', reScope);
google.maps.event.addDomListener(radarCircle, 'radius_changed', reScope);
google.maps.event.addDomListener(radarRectangle, 'bounds_changed', reScope);
function createFacilityMarkers(xmlhttp){
facFinder = new Worker("facfinder.js");
facFinder.addEventListener('message', workerInit, false);
facFinder.postMessage({'cmd' : 'init', 'load' : xmlhttp.responseText});
}
function reScope() {
var searchReq = {'cmd':'search', 'scopeVintage':scopeVintage};
if (radarShape.getCenter) {
searchReq.checker = 0;
var currCenter = radarCircle.getCenter();
searchReq.centerLat = currCenter.lat();
searchReq.centerLng = currCenter.lng();
searchReq.radius = radarCircle.getRadius();
} else {
searchReq.checker = 1;
searchReq.SWLat = radarShape.getBounds().getSouthWest().lat();
searchReq.SWLng = radarShape.getBounds().getSouthWest().lng();
searchReq.NELat = radarShape.getBounds().getNorthEast().lat();
searchReq.NELng = radarShape.getBounds().getNorthEast().lng();
}
facFinder.postMessage(searchReq);
}
HTH
Cheers Richard
Following #SirPeople suggestions here is the complete code that addresses your core problem statement of getting location input from user, update map, and set dynamic radius around it.
here is JS Fiddle link https://jsfiddle.net/innamhunzai/63vcthp7/3/
JS:
var circle;
var map;
function initMap() {
var centerCoordinates = new google.maps.LatLng(37.6, -95.665);
map = new google.maps.Map(document.getElementById('map'), {
center: centerCoordinates,
zoom: 4
});
var card = document.getElementById('pac-card');
var input = document.getElementById('pac-input');
var infowindowContent = document.getElementById('infowindow-content');
var autocomplete = new google.maps.places.Autocomplete(input);
var infowindow = new google.maps.InfoWindow();
infowindow.setContent(infowindowContent);
var marker = new google.maps.Marker({
map: map
});
circle = new google.maps.Circle({
map: map,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
});
autocomplete.addListener('place_changed', function() {
document.getElementById("location-error").style.display = 'none';
infowindow.close();
marker.setVisible(false);
var place = autocomplete.getPlace();
if (!place.geometry) {
document.getElementById("location-error").style.display = 'inline-block';
document.getElementById("location-error").innerHTML = "Cannot Locate '" + input.value + "' on map";
return;
}
map.fitBounds(place.geometry.viewport);
marker.setPosition(place.geometry.location);
circle.setCenter(place.geometry.location);
marker.setVisible(true);
circle.setVisible(true);
infowindowContent.children['place-icon'].src = place.icon;
infowindowContent.children['place-name'].textContent = place.name;
infowindowContent.children['place-address'].textContent = input.value;
infowindow.open(map, marker);
});
}
function updateRadius() {
circle.setRadius(document.getElementById('radius').value * 1609.34);
map.fitBounds(circle.getBounds());
}
**CSS:**
#map {
height: 400px;
}
**HTML**
<html>
<link href="style.css" rel="stylesheet" type="text/css">
<body>
<div class="pac-card" id="pac-card">
<div>
<div id="label">
Location search
</div>
</div>
<div id="pac-container">
<input id="pac-input" type="text" placeholder="Enter a location">
<div id="location-error"></div>
</div>
<div>
<input type="range" id="radius" name="radius" min="0" max="100" onchange="updateRadius()">
</div>
</div>
<div id="map"></div>
<div id="infowindow-content">
<img src="" width="16" height="16" id="place-icon">
<span id="place-name" class="title"></span><br>
<span id="place-address"></span>
</div>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&callback=initMap"
async defer></script>
</body>
</html>
I already have a working map where it generates a valid xml and can generate a marker on my map. Now what I want to do is to upon generating of maps for each loop in the xml I can create asynchronously a check box for each name. here is the code that generates the xml
function searchNearLocations(radius){
clearLocations();
var searchUrl = './designIncludes/phpLogicIncludes/searchMarkers.php?lat=' + userLat +'&lng=' + userLng + '&radius=' + radius;
downloadUrl(searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var info = markerNodes[i].getAttribute("info");
var tts = markerNodes[i].getAttribute("tts");
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createMarker(latlng, name, address,info,tts);
createCheckboxes(name);
bounds.extend(latlng);
}
map.fitBounds(bounds);
});
}
My createMarker()
function createMarker(latlng, name, address,info,tts) {
var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts;
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
I'm not that good in javascript but I have a marker=[] array global variable. Can I use that variable to generate a checkbox with it?by the way I also have a pre made marker before invoking the searchNearLocations function and I want to add it on the latlng bounds. Is it possible to insert it on the loop?
Okay
Everything not having to do with the checkboxes, I ignored. You'll have to put it back in your code.
I wrote a functioning example, you can copy/paste this as is.
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript">
var markers = [];
var map;
/* I don't have that XML. I'll just insert a few locations hard coded. You can ignore this; it doesn't affect your question */
var markerNodes = [
{latlng: new google.maps.LatLng(50.896328544032805,4.4825010816688), name: 'Brussels Airport', address: 'A201, 1930 Zaventem', info: 'National airport of Brussels', tts: 'foo'},
{latlng: new google.maps.LatLng(50.8957080950929,4.334064952575659), name: 'Football stadion', address: 'Marathonlaan', info: 'Football stadion of the Red Devils', tts: 'foo'},
{latlng: new google.maps.LatLng(50.82302545625156,4.39255052014533), name: 'VUB campus', address: 'Pleinlaan 2', info: 'University of Brussels', tts: 'foo'}
];
function initialize() {
var position = new google.maps.LatLng(50.84499325563654,4.349978498661017);
var myOptions = {
zoom: 11,
center: position
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
searchNearLocations(null); // I ignore the radius part. I presume this searches for locations in a DB, or something...
}
/* never mind most of the changes I made here, it's just to ignore the xml part of the code */
function searchNearLocations(radius) {
clearLocations();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<markerNodes.length; i++) {
var latlng = markerNodes[i].latlng,
name = markerNodes[i].name,
address = markerNodes[i].address,
info = markerNodes[i].info,
tts = markerNodes[i].tts;
createMarker(latlng, name, address, info, tts);
createCheckbox(name, i); // the most important thing is to pass the i; then markers[i] corresponds with checkboxes[i]
bounds.extend(latlng);
}
map.fitBounds(bounds);
}
function createMarker(latlng, name, address, info, tts) {
// var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts;
var marker = new google.maps.Marker({
map: map,
title: name, // You should add this
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
/* I'll ignore the infoWindow */
});
markers.push(marker);
}
function clearLocations() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers=[];
}
function checkboxChanged(i, checked) {
if(checked) {
markers[i].setMap(map);
}
else {
markers[i].setMap(null);
}
}
function createCheckbox(name, i) {
document.getElementById('checkboxes').innerHTML +=
'<input type="checkbox" checked="checked" onclick="checkboxChanged(' + i + ', this.checked);"> ' + name + '<br>';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#map-canvas {
width: 500px;
height: 400px;
}
</style>
<div id="map-canvas"></div>
<div id="checkboxes"></div>
Can you manage to include this in your code?
EDIT:
Here is an example of locations in a DB; I bypass xml and communicate through JSON.
It gives you (kind of) a combination of your questions;
I have a different table on my DB, but that shouldn't be a problem.
I add jQuery, just for ajax.
CREATE TABLE IF NOT EXISTS stations (
id bigint(15) NOT NULL AUTO_INCREMENT,
lat decimal(12,10) DEFAULT NULL,
lng decimal(12,10) DEFAULT NULL,
name varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
INSERT INTO stations (id, lat, lng, name) VALUES
(1, '50.8456035000', '4.3568658000', 'Brussel-Centraal'),
(2, '50.8413140000', '4.3490830000', 'Brussel-Kapellekerk'),
(3, '50.8517507000', '4.3623635000', 'Brussel-Congres'),
(4, '50.8604931000', '4.3607035000', 'Brussel-Noord'),
(5, '50.8348278000', '4.3365303000', 'Brussel-Zuid');
index.php
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript">
var markers = [];
var map;
// settings, to pass to the DB
var lat = 50.84499325563654;
var lng = 4.349978498661017;
var radius = 1.5; /* set this to more than 1.5 to see more locations */
function initialize() {
var position = new google.maps.LatLng(50.84499325563654, 4.349978498661017);
var myOptions = {
zoom: 11,
center: position
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
searchNearLocations(lat, lng, radius);
}
function searchNearLocations(lat, lng, radius) {
document.getElementById('checkboxes').innerHTML = '';
// we start an Ajax call.
$.ajax({
url: 'ajax.php',
data: {lat: lat, lng: lng, radius: radius},
dataType: 'json',
success: function(data) {
// the request has returned data. Now we can proceed
clearLocations();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<data.length; i++) {
var latlng = new google.maps.LatLng(data[i].lat, data[i].lng),
name = data[i].name;
/* add what ever extra data you need */
createMarker(latlng, name, null, null, null);
createCheckbox(name, i); // the most important thing is to pass the i; then markers[i] corresponds with checkboxes[i]
bounds.extend(latlng);
}
map.fitBounds(bounds);
}
});
}
function createMarker(latlng, name, address, info, tts) {
/* var html = "<b>" + name + "</b></br><u>" + address + "</u></br>" + info + "</br>" + "Time allowance to spend: " + tts; */
var marker = new google.maps.Marker({
map: map,
title: name, // You should add this
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
/* I'll ignore the infoWindow */
});
markers.push(marker);
}
function clearLocations() {
for (var i=0; i<markers.length; i++) {
markers[i].setMap(null);
}
markers=[];
}
function checkboxChanged(i, checked) {
if(checked) {
markers[i].setMap(map);
}
else {
markers[i].setMap(null);
}
}
function createCheckbox(name, i) {
document.getElementById('checkboxes').innerHTML +=
'<input type="checkbox" checked="checked" onclick="checkboxChanged(' + i + ', this.checked);"> ' + name + '<br>';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#map-canvas {
width: 500px;
height: 400px;
}
</style>
<div id="map-canvas"></div>
<div id="checkboxes"></div>
ajax.php
<?php
$link = mysqli_connect('localhost', 'root', '', 'stackoverflow'); /* put your settings back */
if(!$link) {
die ('unable to connect to the database' . mysqli_connect_error());
}
//Get parameters from URL
$myLat = (isset ($_GET['lat']) ? $_GET['lat'] : 0.0); // give it some default
$myLng = (isset ($_GET['lng']) ? $_GET['lng'] : 0.0);
$calcDistance = (isset ($_GET['radius']) ? $_GET['radius'] : 1.0);
//Search the rows in the markers table
/* I have a slightly different table; I'll continue with mine; it's easy to put everything back */
// $query = sprintf("SELECT siteName,address,lat,lng,info,tts, (6371 * acos(cos(radians('%s')) * cos(radians(lat)) * cos(radians(lng) - radians ('%s')) + sin(radians('%s')) * sin(radians(lat))))AS distance FROM mapTable HAVING distance < '%s' ORDER BY distance LIMIT 0, 50",
$query = sprintf("SELECT id, lat, lng, name, (6371 * acos(cos(radians('%s')) * cos(radians(lat)) * cos(radians(lng) - radians ('%s')) + sin(radians('%s')) * sin(radians(lat)))) AS distance FROM stations HAVING distance < '%s' ORDER BY distance LIMIT 0, 50",
mysqli_real_escape_string($link, $myLat),
mysqli_real_escape_string($link, $myLng),
mysqli_real_escape_string($link,$myLat),
mysqli_real_escape_string($link, $calcDistance));
$result = mysqli_query($link, $query);
$row_cnt = mysqli_num_rows($result);
if(!$result) {
die("Invalid query: " . mysqli_error());
}
header("content-type: application/json; charset=utf-8");
$items = array();
//iterate through the rows,
while($row = mysqli_fetch_assoc($result)) {
$items[] = $row;
}
echo json_encode($items); // this can immediatly be read by javascript
exit;
?>
You can add links/buttons, whith something like
<div onclick="searchNearLocations(50.80, 4.35, 20)">click: 20 km radius from (50.80, 4.35)</div>
To add the position of the client, check out my answer here
google getLocation function not work in my script
In the example fiddle, how can I get the total number of markers displayed on the map? I'm pushing each of the markers into an array like this:
markers.push(marker)
And attempting to get the total number of markers like this:
$('.marker-count span').html(markers.length);
Unfortunately, "markers.length" is returning 0 when it should be returning at least 3.
I have example code here: http://jsfiddle.net/287C7/
How can I display the total number of markers? Is it not possible to add each marker to my array?
I need to know the amount of markers shown so that I can alert the user if there are none.
Thanks,
In case you don't want to view the code on jsfiddle.net, here it is:
var map, places, tmpLatLng, markers = [];
var pos = new google.maps.LatLng(51.5033630,-0.1276250);
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(51.5033630,-0.1276250)
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
// create the map and reference the div#map-canvas container
var markerBounds = new google.maps.LatLngBounds();
var service = new google.maps.places.PlacesService(map);
// fetch the existing places (ajax)
// and put them on the map
var request = {
location: pos,
radius: 48000, // Max radius
name: "mc donalds"
};
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
$('#map-canvas').attr("data-markers",results.length);
$('.marker-count span').html(markers.length);
} else {
console.log("Places request failed: "+status);
}
} // end callback
function createMarker(place) {
var prequest = {
reference: place.reference
};
var tmpLatLng = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
markers.push(marker);
markerBounds.extend( tmpLatLng );
} // end createMarker
service.nearbySearch(request, callback);
the placesSearch call is asynchronous, when you run your code:
$('.marker-count span').html(markers.length);
the result hasn't come back from the server yet. You need to do that in the call back after you update the markers array.
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
$('#map-canvas').attr("data-markers",results.length);
$('.marker-count span').html(markers.length);
} else {
console.log("Places request failed: "+status);
}
} // end callback
working fiddle
I've been working on this very simple Google Places search and I cannot get anything but a ZERO_RESULTS. It makes no sense to me at this point as my map is working and displays markers from my database within a separate AJAX function. I've logged my objects and variables and all seem to be just fine.
Why does the success callback go right to my else statement with ZERO_RESULTS?
$( "#submit3" ).click(function(e) {
e.preventDefault();
findPlaces();
$('#results').text("Triggah3!");
});
function findPlaces() {
var lat = document.getElementById("latitude").value;
var lng = document.getElementById("longitude").value;
var cur_location = new google.maps.LatLng(lat, lng);
// prepare request to Places
var request = {
location: cur_location,
radius: 50000,
types: 'bank'
};
// send request
service = new google.maps.places.PlacesService(map);
service.search(request, createMarkers);
}
// create markers (from 'findPlaces' function)
function createMarkers(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) { //ZERO_RESULTS
// if we have found something - clear map (overlays)
clearOverlays();
// and create new markers by search result
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
} else if (status == google.maps.places.PlacesServiceStatus.ZERO_RESULTS) {
alert('Sorry, nothing is found');
}
}
// create single marker function
function createMarker(obj) {
// prepare new Marker object
var mark = new google.maps.Marker({
position: obj.geometry.location,
map: map,
title: obj.name
});
markers.push(mark);
// prepare info window
var infowindow = new google.maps.InfoWindow({
content: '<img src="' + obj.icon + '" /><font style="color:#000;">' + obj.name +
'<br />Rating: ' + obj.rating + '<br />Vicinity: ' + obj.vicinity + '</font>'
});
// add event handler to current marker
google.maps.event.addListener(mark, 'click', function() {
clearInfos();
infowindow.open(map,mark);
});
infos.push(infowindow);
}
types is expected to be an array.
Use:
types: ['bank']