Using a file to hold array items for Google Maps - javascript

I have create a Google Map using however, it has a lot of markers and it has become unwieldy to have them in the the same html file. To use the markers I first create a array as follows;
var markers = [
['Balham Leisure Centre',51.441234,-0.152297,'leisure_center.png'],
['Putney Leisure Centre',51.463955,-0.228771,'leisure_center.png'],
['Latchmere Leisure Centre',51.470967,-0.163805,'leisure_center.png']
]
then utilise them as follows;
for( i = 0; i < markers.length; i++ ) {
var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0],
icon: iconBase + markers[i][3],
});
}
I would like to store the markers array in a separate text file like;
['Balham Leisure Centre',51.441234,-0.152297,'leisure_center.png'],
['Putney Leisure Centre',51.463955,-0.228771,'leisure_center.png'],
['Latchmere Leisure Centre',51.470967,-0.163805,'leisure_center.png']
then have the main page read that file and put it into the markers array so that everything still works the same.

Since you don't use any frameworks, in native JS you want to use XMLHttpRequest object. Save your data in a separate file (you might want to use JSON for example) and then follow the code below.
Basic usage:
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == XMLHttpRequest.DONE) {
console.log(req.responseText);
}
}
req.open('GET', url);
req.send();
Readmore: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

Related

Calling a .php document in JavaScript using Django Framework

I'm wondering if this is Django URLs issue. I am following [a Google Tutorial][1] to pop down markers showing addresses on a Google Map pulled from a database using php and xml. I have wired up a .php to my PostgreSQL db okay and seem to be able to run the script and show all the addresses and details in the console (I believe this means the XML file is working too).
The Problem
The trouble I am having is on the JavaScript side: I am using downloadURL() function in my .js static file. And pointing the URL parameter to my .php file which is stored in my local directory:
var markerurl = 'testingland/www/xmlpgd.php'
downloadUrl(markerurl, function(data)
However when I test the script on my local development server (http://127.0.0.1:8000/cafe_list) it returns the following error:
http://127.0.0.1:8000/cafe_list/testingland/www/xmlpgd.php 404 (Not Found)
What I have tried
I have tried moving the xmlpgd.php file to different locations including templates, static and elsewhere. I have tried hosting it on Google Cloud (which returns a CORS error). I am at a loss and thinking maybe I need to wire it up to my urls.py file? I am just not sure whether this is the case or how to do this properly.
My Code
Here is my urls.py file:
urlpatterns = [
path('cafe_list/', views.cafes_home, name='cafes_home'),
url('electra/cafe_list/', views.cafe_list.as_view(), name='cafe_list'),
]
Here is my JS Code:
//loads map markers from database
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, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
//get the markers from php file and adds them to map
var markerurl = 'testingland/www/xmlpgd.php';
downloadUrl(markerurl, function(data) {
var xml = parseXml(data);
var markers = xml.documentElement.getElementsByTagName('marker');
Array.prototype.forEach.call(markers, function(markerElem) {
var id = markerElem.getAttribute('id');
var name = markerElem.getAttribute('name');
var address = markerElem.getAttribute('address');
var type = markerElem.getAttribute('location');
var point = new google.maps.LatLng(
parseFloat(markerElem.getAttribute('lat')),
parseFloat(markerElem.getAttribute('lng')));
var infowincontent = document.createElement('div');
var strong = document.createElement('strong');
strong.textContent = name
infowincontent.appendChild(strong);
infowincontent.appendChild(document.createElement('br'));
var text = document.createElement('text');
text.textContent = address
infowincontent.appendChild(text);
var icon = customLabel[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point
[1]: https://developers.google.com/maps/documentation/javascript/mysql-to-maps

Google Maps API - heatmap not defined (map displaying but cannot alter)

On 2nd version of a heatmapping system I am making using google maps api.
Initial version works fine but uses PHP and MySQL to write the points into the map, this displays fine and can then alter map (e.g. radius / opacity) using heatmap.set the only problem is you cant change heatmap displayed without reloading (points are effectively hard coded into script by PHP).
So I have altered original code to instead call a php script (using a serialized version of form) which returns query in JSON format, this works fine in as far as get a blank map to begin with, can choose some settings and it will load heatmap fine, can change these and it will do a new heatmap (which it layers on top of old one) so have gone through how to remove previous heatmap and hit a brick wall...
If I try any function calling heatmap. I get "heatmap not defined" this includes all the previous functions that worked fine in old map.
Full code is quite large so will hopefully cover everything in these snippets...
Initial map load...
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: {lat: 51.514898, lng: -0.144432},
mapTypeId: 'roadmap'
});
}
Make a heatmap...
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var heatmapData = [];
myObj = JSON.parse(this.responseText);
for (var i = 0; i < myObj.points.length; i++) {
var latLng = new google.maps.LatLng(myObj.points[i].lat,myObj.points[i].lng);
var pushData = {
location: latLng,
weight: myObj.points[i].weight
}
heatmapData.push(pushData);
}
var heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
maxIntensity: 10,
radius:30,
opacity: 0.4,
map: map
})
}
};
Which is called by form submit...
$( "form" ).on( "submit", function( event ) {
event.preventDefault();
url = "query.php?" + $( this ).serialize();
xmlhttp.open("GET", url, true);
xmlhttp.send();
});
and an example function which don't work (value set by a slider with an onchange event)...
function changeOp(val) {
heatmap.set('opacity', val);
}
The heatmap is currently local to the xmlhttp.onreadystatechange function, you can't access it outside of there. You need to declare it outside of that function (the global scope works, like the map variable), then you can access it to modify it later (or in the next call to the AJAX request).
var heatmap;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var heatmapData = [];
myObj = JSON.parse(this.responseText);
for (var i = 0; i < myObj.points.length; i++) {
var latLng = new google.maps.LatLng(myObj.points[i].lat, myObj.points[i].lng);
var pushData = {
location: latLng,
weight: myObj.points[i].weight
}
heatmapData.push(pushData);
}
heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
maxIntensity: 10,
radius: 30,
opacity: 0.4,
map: map
})
}
};

Google Maps OverlappingMarkerSpiderfier instantiation problems

I've searhced the site for this error and, while there were several answers, none of them worked for me (or weren't applicable).
I am using google maps API v3 and am trying to implement OverlappingMarkerSpiderfier to solve my problem of overlapping markers. My problem is that I cannot create an instance of an OMS:
function getStateInfo(){
//do stuff
var lat = 42.5724;
var lon = -74.948052;
var map = new google.maps.Map(document.getElementById("map"),{draggableCursor:'pointer'});
var oms = new OverlappingMarkerSpiderfier(map,{markersWontMove: true, markersWontHide: true});
// do more stuff
var whiteicon = new GIcon();
whiteicon.image = "images/whiteCircle.png";
whiteicon.iconSize = new GSize(11, 11);
whiteicon.iconAnchor = new GPoint(6, 6);
whiteicon.infoWindowAnchor = new GPoint(6,6);
var marker = new GMarker(new GLatLng(lat,lon), {
draggable: false,
title: ($(this).find('COMPANY_NAME').text()),
icon: whiteicon,
map: map
});
oms.addMarker(marker);
}
I get the following error:
InvalidValueError: setMap: not an instance of Map; and not an instance of StreetViewPanorama
I have verified that the error occurs at the time of instantiation and not at marker creation/placement. For thoroughness, here is the code I am trying to use to place markers:
var marker = new GMarker(new GLatLng(lat,long), {
draggable: false,
title: ($(this).find('COMPANY_NAME').text()),
icon: whiteicon,
map: map});
...
oms.addMarker(marker);
I have also retrieved a different copy of OMS in the event that there was something wonky with the original (downloaded from github).
If you need to see more code, just let me know what you are looking for. I just posted the lines which are the problem. My map generates properly without OMS - it's just the oms instantiation that is the problem.
You are using a deprecated Google Maps JavaScript API v2 map with a Google Maps JavaScript API v3 spiderifier.
This is v2 code (GSize, GPoint, GLatLng):
whiteicon.iconSize = new GSize(11, 11);
whiteicon.iconAnchor = new GPoint(6, 6);
var marker = new GMarker(new GLatLng(lat,lon), {

Using a large data set of address to create a Google API heat map

I'm trying to create a heatmap using Google's API, but running into a few issues. The main issue I have run into so far is converting a large set of about ~25000 addresses into geocoordinates for use in the API. The two approaches I have used are Google's own API, which has heavy limitations, and Python's Geopy module, which also has limitations. Since I am trying to convert ~25000, Geopy's one second delay is a pretty steep issue.
The second issue I can see coming is a size limitation. Once I have a list of ~25000 geocoordinates, putting those into an array in Javascript seems ridiculous. Assuming a user would upload a text file in a format like this:
12.3456,-12.3456
23.4567,-23.4567
...
Would there be a way to process the file in blocks, or some other work around?
In case it helps, this is my current Javascript code for processing a file of addresses. I'm planning on changing the file reading format to find a better system.
var map, heatmap, geocoder;
var MVCarr;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 36.85, lng: -75.97},
zoom: 7
});
MVCarr = new google.maps.MVCArray();
heatmap = new google.maps.visualization.HeatmapLayer({
data: MVCarr,
map: map
})
}
window.onload = function() {
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
geocoder = new google.maps.Geocoder();
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function(e) {
var mySplit = (reader.result).split("\n");
for(var i = 0, len = mySplit.length; i < len; i++) {
//console.log(mySplit[i]);
geocodeAddress(geocoder, mySplit[i]);
}
}
reader.readAsText(file);
});
}
function geocodeAddress(geocoder, address) {
geocoder.geocode({'address': address}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
MVCarr.push(results[0].geometry.location);
console.log(MVCarr.length);
} else {
console.log('Failed: ' + status);
}
});
}

Displaying multiple Google Map markers and directions on one map

I would like to output multiple Google Map routes on to a single Google Map. The data is taken from an XML file which feature multiple markers. Each marker has a start point and an end point (in the form of latitude and longitude values). These markers are then added to the map and a call to the Google Maps Directions Service is made to draw a route between the start and end points of each marker.
The issue I'm having is that only one route is drawn (if I refresh the page it seems to just pick one of the markers at random and draw the directions between those two markers). The other markers aren't displayed at all.
I've console.logged the for loop to check it is running for each marker in the XML (it is). I'm guessing it is something to do with these two lines here, but that is a guess...
directionsDisplay = new google.maps.DirectionsRenderer();
directionsService = new google.maps.DirectionsService();
I've read this question - Using Google Maps 3 API to get multiple routes on a Map, but don't really understand the answer/know how relevant it is to my situation. Thanks.
jQuery(document).ready(function($) {
var map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 13,
mapTypeId: 'roadmap'
});
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(pos);
map.setZoom(13);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
directionsDisplay = new google.maps.DirectionsRenderer();
directionsService = new google.maps.DirectionsService();
// Change this depending on the name of your PHP file
downloadUrl("xml.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var title = markers[i].getAttribute("title");
mode = markers[i].getAttribute("mode");
startpoint = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("startlat")),
parseFloat(markers[i].getAttribute("startlng")));
endpoint = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("endlat")),
parseFloat(markers[i].getAttribute("endlng")));
calcRoute();
console.log('marker');
}
});
directionsDisplay.setMap(map);
});
function calcRoute() {
var request = {
origin: startpoint,
destination: endpoint,
//waypoints: waypts,
travelMode: google.maps.DirectionsTravelMode[mode]
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
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, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
I think the key point in the answer you linked to is that each route needs its own DirectionsRenderer object. And it doesn't mention it, but it seems likely that each route should also have its own DirectionsService object. You're sharing a single one of each these objects among all your routes. I suspect that these shared objects are getting overwritten for each route.
Here's an update that should fix that by creating new objects for each route:
jQuery(document).ready(function($) {
var map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 13,
mapTypeId: 'roadmap'
});
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(pos);
map.setZoom(13);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
// Change this depending on the name of your PHP file
$.get("xml.php", function( xml ) {
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
addMarkerPair( markers[i] );
}
}, 'xml' );
});
function addMarkerPair( pair ) {
function get( name ) {
return pair.getAttribute( name );
}
var title = get("title");
var mode = get("mode");
var startpoint = new google.maps.LatLng(
+get("startlat"),
+get("startlng")
);
var endpoint = new google.maps.LatLng(
+get("endlat"),
+get("endlng")
);
calcRoute( mode, startpoint, endpoint );
console.log('marker');
}
function calcRoute( mode, startpoint, endpoint ) {
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
var request = {
origin: startpoint,
destination: endpoint,
//waypoints: waypts,
travelMode: google.maps.DirectionsTravelMode[mode]
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
I also took the liberty of fixing and simplifying a few things:
Moved the marker loop body out to a separate addMarkerPair function for better readability.
Added a get function inside addMarkerPair as a shorthand for pair.getAttribute.
Used + instead of parseInt. Either one will do the same thing; I like + for its brevity.
Add several missing var declarations.
Passed the necessary parameters to calcRoute as function parameters instead of global variables.
Used $.get instead of downloadUrl. No need for your own function when jQuery has it already.
Also, as another alternative to the XML parsing, you could use jQuery to access the XML elements. But I stuck with code closer to how you're already doing it.

Categories

Resources