I'm trying to monitor the position of my vehicle in real time.
I'm using the googlemaps API to do this.
My objective is to constantly update the marker (position of my car) every three seconds without having to reload the entire map.
The vehicle's current location is saved in 'vehicle_location.txt'.
<!DOCTYPE html>
<html>
<head>
<title>Car Location</title>
<style>
/* 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;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
var markers = [];
var timerId;
var contents;
function initMap() {
``var initial_location = {lat: 15.3647, lng: 75.1240};
//timerId = setInterval(update_map,3000);
update_map();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: initial_location,
});
addMarker(initial_location);
}
// Adds a marker to the map and push to the array.
function addMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map
});
markers.push(marker);
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
}
// Shows any markers currently in the array.
function showMarkers() {
setMapOnAll(map);
}
// Deletes all markers in the array by removing references to them.
function deleteMarkers() {
clearMarkers();
markers = [];
}
//Updates map every 3 seconds
function update_map(){
//read_file();
var req = new XMLHttpRequest();
req.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
alert(this.responseText);
timerId = setTimeout('update_map()', 3000);
}
};
//req.addEventListener("load", reqListener);
req.open("GET", "./vehicle_location.txt", true);
req.send(null);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js? key=YOUR_APIKEY_HERE&callback=initMap">
</script>
The problem is, 'this.responseText' has same value on every call to
req.open("GET", "./vehicle_location.txt", true)
inspite of the text file constantly changing.
I am new to js. Any help is much appreciated!
If the software is constantly updating vehicle_location.txt with no issues. Then, it could be browser cache. To override this, the simplest method is adding a random query to target URL, so browser identifies it as a new URL; thus, ignoring cache. The most commonly used is a timestamp.
var ts = new Date().getTime(); // output a unix timestamp reflecting the current date and time.
req.open("GET", "./vehicle_location.txt?t="+ts, true);
The above will generate a new URL with every new XHR request issued like:
./vehicle_location.txt?t=1483349217755
./vehicle_location.txt?t=1483349217757
./vehicle_location.txt?t=1483349217759
./vehicle_location.txt?t=1483349217760
Related
I've searched the web but can't seem to locate an answer for my issue. I believe I'm close but just can't get this to work as intended.
I'd like to plot an array of locations on a google map and start with the DROP animation, then when a user clicks a point, I'd like it to bounce.
My current code does 1/2 the job, however, when you click it's targeting the last value in my array. The BOUNCE animation works but it doesn't seem to be applied to all values in my array. Can you point at what I'm missing in the code?
Thanks for all the help!
<html>
<head>
<!-- styles put here, but you can include a CSS file and reference it instead! -->
<style type="text/css">
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">
// Create a map variable
var map;
var markers = [];
// Function to initialize the map within the map div
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.74135, lng: -73.99802},
zoom: 10
});
// Create a single latLng literal object.
var locations = [
{title: 'Beer', location: new google.maps.LatLng(47.666633, -122.371453)},
{title: 'Home', location: new google.maps.LatLng(47.613141, -122.320587)},
{title: 'Work', location: new google.maps.LatLng(47.624812, -122.315134)}
];
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < locations.length; i++) {
var position = locations[i].location;
var title = locations[i].title;
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
id: i
});
bounds.extend(marker.position);
google.maps.event.addListener(marker, 'click', function(){
if (marker.getAnimation() !== null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
});
// markers.push(marker);
}
map.fitBounds(bounds);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=&v=3&callback=initMap">
</script>
</body>
</html>
One option would be to use this inside the click event listener function to reference the clicked marker.
google.maps.event.addListener(marker, 'click', function(){
if (this.getAnimation() !== null) {
this.setAnimation(null);
} else {
this.setAnimation(google.maps.Animation.BOUNCE);
}
});
(you can also use function closure)
I'm very new to using Google Maps and very new to intricate javascript. Bearing this in mind, I'm trying to create a web map, with a feed from USGS. This feed is updated every 5 minutes. I'd like to have my map refresh every 5 minutes using this same feed (which is a geojson file).
My end goal is to have this and at least one other feed displayed/updated on my map. Over the past four days, I've gone through dozens of posts, and am at the point of being overloaded and confused. Will someone please clear my fog?
The code I'm posting is 99% not my code, mostly I've added comments so I can figure out what's going on in the code.
<HTML>
<HEAD>
<TITLE>TEST OF MAP</TITLE>
<STYLE>
/* --------------------------------------------------- */
/* Set the map height explicitly to define the size of */
/* the DIV * element that contains the map. */
/* ----------------------------------------------------*/
#map {
height: 75%;
border: 5px solid green;
}
</STYLE>
</HEAD>
<SCRIPT type="text/javascript">
// --------------------------------------
// Set a refresh interval in milliseconds
// --------------------------------------
setInterval(page_refresh, 1*60000);
google.maps.event.addDomListener(window, 'load', initialize);
</SCRIPT>
<BODY>
<H1><CENTER>MAP Demo</CENTER></H1>
<DIV id="map"></DIV>
<SCRIPT>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: new google.maps.LatLng(35.4437,139.6380),
mapTypeId: 'terrain'
});
// ---------------------------------------------------------
// Create a <SCRIPT> tag and set the USGS URL as the source.
// ---------------------------------------------------------
var script = document.createElement('script');
// -----------------------------------------------------------------------
// Using a local copy of the GeoJSON stored on the USGS server
//
http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.geojsonp
// -----------------------------------------------------------------------
script.src =
'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.geojson
p';
document.getElementsByTagName('head')[0].appendChild(script);
}
// ------------------------------------------------------------------
// Loop through the results array and place a marker for each set of
// coordinates.
// ------------------------------------------------------------------
window.eqfeed_callback = function(results) {
for (var i = 0; i < results.features.length; i++) {
var coords = results.features[i].geometry.coordinates;
var latLng = new google.maps.LatLng(coords[1],coords[0]);
var marker = new google.maps.Marker({
position: latLng,
map: map
});
}
}
</SCRIPT>
<SCRIPT async defer src="https://maps.googleapis.com/maps/api/js?
key=MY_MAP_KEY&callback=initMap">
</SCRIPT>
</BODY>
</HTML>
Though not very elegant, I used the following for the refresh. Since I'm only building a "proof of concept", refreshing the entire page is not a problem.
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
window.onload = timedRefresh(60*5000);
So I have a search page with a location input. If a user comes from another page with a search query, I want to programmatically input this query into the input and trigger a place changed.
Here's what I have so far:
var searchBox = new google.maps.places.SearchBox(input);
$('input#location').val(searchQuery);
google.maps.event.trigger(searchBox, 'places_changed');
However, this gives me the error Cannot read property 'length' of undefined for this line of my places_changed function:
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
So clearly searchBox returns undefined for getPlaces() when the input has been filled programmatically. How can I get around this?
UPDATE: Here is a JSFiddle to exemplify what I mean.
Let's take a look what at the workflow of a SearchBox:
The user types a string
The API provides a list with predictions
The user selects a prediction
The API performs a Textsearch based on the selected prediction and returns a list of places
conclusion:
When you know the searchTerm and you don't need to select a prediction, simply skip the steps 1-3 and directly run the TextSearch. Assign the returned array with places to the places-property of the SearchBox (the places_changed-event will be triggered automatically, because the SearchBox is a MVCObject, where changes of properties will be observed and the related events will be triggered automatically)
function initialize() {
var goo = google.maps,
map = new goo.Map(document.getElementById('map_canvas'), {
zoom: 1,
center: new goo.LatLng(0, 0),
noClear: true
}),
input = map.getDiv().querySelector('input'),
ac = new goo.places.SearchBox(input),
service = new goo.places.PlacesService(map),
win = new goo.InfoWindow,
markers = [],
request;
map.controls[goo.ControlPosition.TOP_CENTER].push(input);
if (input.value.match(/\S/)) {
request = {
query: input.value
};
if (ac.getBounds()) {
request.bounds = ac.getBounds();
}
service.textSearch(request, function(places) {
//set the places-property of the SearchBox
//places_changed will be triggered automatically
ac.set('places', places || [])
});
}
goo.event.addListener(ac, 'places_changed', function() {
win.close();
//remove previous markers
while (markers.length) {
markers.pop().setMap(null);
}
//add new markers
(function(places) {
var bounds = new goo.LatLngBounds();
for (var p = 0; p < places.length; ++p) {
markers.push((function(place) {
bounds.extend(place.geometry.location);
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
}),
content = document.createElement('div');
content.appendChild(document.createElement('strong'));
content.lastChild.appendChild(document.createTextNode(place.name));
content.appendChild(document.createElement('div'));
content.lastChild.appendChild(document.createTextNode(place.formatted_address));
goo.event.addListener(marker, 'click', function() {
win.setContent(content);
win.open(map, this);
});
return marker;
})(places[p]));
};
if (markers.length) {
if (markers.length === 1) {
map.setCenter(bounds.getCenter());
} else {
map.fitBounds(bounds);
}
}
})(this.getPlaces());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map_canvas {
height: 100%;
margin: 0;
padding: 0
}
strong{
font-weight:bold;
}
<div id="map_canvas">
<input value="berlin">
</div>
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=places"></script>
I'm making a webapp that allows people to see the location of buses on Google maps. I'm having some problems with global variables in JavaScript. window.variable doesn't work for me. Neither does defining the variable outside the all the functions works. Here is my complete client side code:
<!DOCTYPE html>
<html>
<head>
<title>Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
// Note: This example requires that you consent to location sharing when
// prompted by your browser. If you see a blank space instead of the map, this
// is probably because you have denied permission for location sharing.
var old = [];
function getLocation()
{
$.get( "http://54.86.161.214/EC_bus_app/get_location.php", function( data ) {
old=[];
var buses = data;
var number_of_buses = buses.slice(0,1);
buses = buses.slice(2);
buses = buses.slice(0,-1);
var bus_coordinates_and_numbers = buses.split(/[ ]+/);
var length_of_array = bus_coordinates_and_numbers.length;
// Turn a single dimensional array into a multi-dimensional array
for (var index = 0; index < bus_coordinates_and_numbers.length; index+= 3)
old.push( bus_coordinates_and_numbers.slice(index, index + 3) );
console.log(old);
//initialize(old);
});
}
setInterval(getLocation, 10000);
var map;
function initialize() {
var mapOptions = {
zoom: 18
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var image = "icon_97.png";
for (i=0;i<old.length; i = i + 1){
var x = old[i][0];
var y = old[i][1];
var myLatlng = new google.maps.LatLng(x,y);
var busMarker = new google.maps.Marker({
position: myLatlng,
map: map,
icon: image,
title: old[i][2]
});
}
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Your location'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
The variable in question is old. I can pass it to the initialize function from within the get location function using initialize(old);. However, as you can see, I'm using a timer, and initialize(old); causes the entire map to reload again and again, whereas I only want the location markers to load again and again.
Solved the problem by moving getLocation() inside initialize(). But what #geocodezip said in the comments also answers my question completely.
Your problem is not with global variables. It is with asynchronous functions. You need to initialize the map, then request data (asynchronous request), make markers on the map, then periodically update them.
So I have 3 Divs with hidden Lat Lng inputs, and some ajax pagination to change them out. On the initial load, I have a script that turns each one of the three pairs of Lat Lng inputs into a marker and pushes them into an array. All of this works good.
Now, when I update the 3 divs with my script file, and then try to use the provided v3 API method to clear and redraw the markers, I get the same spots on the map. And then, if I tell it to go back to page one results, it does delete the page 1 markers and I get the markers from page 2 on my map.
Here is the javascript:
var map;
var markers = [];
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(37.09024, -96.712891),
zoom: 3
};
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
setRGBmarkers();
}
function setRGBmarkers() {
markers.push(new google.maps.Marker({
position: new google.maps.LatLng(
Number(document.getElementById("address-0-Lat").value),
Number(document.getElementById("address-0-Lng").value)
),
map: map
}));
//removed other markers for brevity
}
function setAllMap(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
function clearMarkers() {
setAllMap(null);
}
function deleteMarkers() {
clearMarkers();
markers = [];
}
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
type: "get"
};
$.ajax(options).done(function (data) {
var target = $a.parents("div.pagedList").attr("data-nerd-target");
$(target).replaceWith(data);
});
deleteMarkers();
setRGBmarkers();
alert('done');
return false;
}
$(".body-content").on("click", ".pagedList a", getPage);
So it successfully goes out and gets the results. I'm guessing it somehow is running delete and set before its actually done replacing the markers so its setting the 'unreplaced data' again, hence why going back to page one results finally in page 2's markers showing up? Here's a snippet of what the div looks like if needed:
<div class="panel-body">
Event Description
<input id="address-0-Lat" type="hidden" value="34.0519079">
<input id="address-0-Lng" type="hidden" value="-118.24389300000001">
</div>
Well, Anto is correct, and upon investigating the jQuery documentation for the ajax() function, I see the correct place to put the code would be like so:
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
type: "get"
};
$.ajax(options).done(function (data) {
var target = $a.parents("div.pagedList").attr("data-nerd-target");
$(target).replaceWith(data);
deleteMarkers();
setRGBmarkers();
alert('done');
});
return false;
}
$(".body-content").on("click", ".pagedList a", getPage);
Where the 'done' function is executed once the response comes back. Documenation and examples can be found here: http://api.jquery.com/jquery.ajax/