I have read many similar topics, but none of the answers seems to work for my case. I am working with Google Maps API to implement show/hide markers function using knockout data-binding. With show markers, there are no problems. But since I have to pass markers variable into hideMarkers function, I can't get this going.
Here is the html:
<div class="col-sm-6">
<input id="hide-listings" type="button" value="Hide Listings" class="btn1 btn-primary text-center" data-bind="click: hideMarkers">
</div>
Here is my ViewModel:
function viewModel() {
var self = this;
self.places = ko.observableArray(locations);
self.address = ko.observable();
self.city = ko.observable();
self.title = ko.observable();
self.id = ko.observable();
this.markers = ko.observable();
this.zaddress = ko.observable();
this.taddress = ko.observable();
this.paddress = ko.observable();
this.filter = ko.observable();
this.visiblePlaces = ko.computed(function() {
return this.places().filter(function(place) {
if (!self.filter() || place.title.toLowerCase().indexOf(self.filter().toLowerCase()) !== -1)
return place;
});
}, this);
//Zooms to a selected marker, open infowindow and displays current weather
self.zoomToPlace = function() {
// Initialize the geocoder.
var geocoder = new google.maps.Geocoder();
// Get the place.
var address = this.address;
var id = this.id;
var city = this.city;
var weatherAPIXU = "http://api.apixu.com/v1/current.json?key=453477e8eec14cbc805210143171706&q=" + city;
$.getJSON(weatherAPIXU, function(data) {
var forecast = data.current.temp_c;
$(".weather").html(forecast + '° C');
});
// Geocode the address/area entered to get the center. Then, center the map on it and zoom in
geocoder.geocode({
address: address,
}, function(results, status) {
map.setCenter(results[0].geometry.location);
map.setZoom(15);
google.maps.event.trigger(markers[id], 'click');
});
};
self.showListings = function() {
var bounds = new google.maps.LatLngBounds();
// Extend the boundaries of the map for each marker and display the marker
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
bounds.extend(markers[i].position);
}
map.fitBounds(bounds);
};
// This function takes the input value in the find nearby area text input
// locates it, and then zooms into that area. This is so that the user can
// show all listings, then decide to focus on one area of the map.
self.zoomToArea = function() {
// Initialize the geocoder.
var geocoder = new google.maps.Geocoder();
// Get the address or place that the user entered.
var zaddress = this.zaddress();
// Make sure the address isn't blank.
if (zaddress === '') {
window.alert('You must enter an area, or address.');
} else {
// Geocode the address/area entered to get the center. Then, center the map on it and zoom in
geocoder.geocode({
address: zaddress,
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
map.setZoom(15);
} else {
window.alert(
'We could not find that location - try entering a more' +
' specific place.');
}
});
}
};
// This function allows the user to input a desired travel time, in
// minutes, and a travel mode, and a location - and only show the listings
// that are within that travel time (via that travel mode) of the location
self.searchWithinTime = function() {
// Initialize the distance matrix service.
var distanceMatrixService = new google.maps.DistanceMatrixService();
var taddress = this.taddress();
// Check to make sure the place entered isn't blank.
if (taddress === '') {
window.alert('You must enter an address.');
} else {
hideMarkers(markers);
// Use the distance matrix service to calculate the duration of the
// routes between all our markers, and the destination address entered
// by the user. Then put all the origins into an origin matrix.
var origins = [];
for (var i = 0; i < markers.length; i++) {
origins[i] = markers[i].position;
}
var destination = taddress;
var mode = document.getElementById('mode').value;
// Now that both the origins and destination are defined, get all the
// info for the distances between them.
distanceMatrixService.getDistanceMatrix({
origins: origins,
destinations: [destination],
travelMode: google.maps.TravelMode[mode],
unitSystem: google.maps.UnitSystem.IMPERIAL,
}, function(response, status) {
if (status !== google.maps.DistanceMatrixStatus
.OK) {
window.alert('Error was: ' + status);
} else {
displayMarkersWithinTime(response);
}
});
}
};
// This function fires when the user select "go" on the places search.
// It will do a nearby search using the entered query string or place.
self.textSearchPlaces = function() {
var bounds = map.getBounds();
var place = this.paddress();
hideMarkers(placeMarkers);
var placesService = new google.maps.places.PlacesService(map);
placesService.textSearch({
query: place,
bounds: bounds
}, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus
.OK) {
createMarkersForPlaces(results);
}
});
};
// This function will loop through the listings and hide them all.
this.hideMarkers = function(markers) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
};
}
ko.applyBindings(new viewModel());
Please, advice me on how to best approach this issue, thank you!
If markers is this.markers then you dont need to pass the markers to the function as its available:
this.hideMarkers = function(markers) {
var m = markers == null ? this.markers : markers;
for (var i = 0; i < m.length; i++) {
m[i].setMap(null);
}
};
This means you can pass markers also to this function and if you dont it will default to your this.markers.
You can pass extra parameters in knockout like this also, if that is all your looking:
<input data-bind="click: hideMarkers.bind($data, markersYouWishtoHide)">
http://knockoutjs.com/documentation/click-binding.html
I have figured it out! The problem was that I was passing the value into the function inside the viewModel, but not in my click data-binding! The correct html:
<div class="col-sm-6">
<input id="hide-listings" type="button" value="Hide Listings" class="btn1 btn-primary text-center" data-bind="click: function() {hideMarkers(markers)}">
</div>
And the ViewModel function is simply:
self.hideMarkers = function() {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
};
Related
I am building an widget where user can upload an excel file and the places are get marked in the google map.
The following code works, but issue comes when i am reading an large excel file with 10k amount of data, the browser gets stuck. I am using a for loop and adding some timeout to get the data from the google api.
I pass the city name and get the latitude and longitude and mark it on the map.
Is there a better way i can implement?
Here is the code:
function googleMapsInit(widId, $scope, $http, $rootScope, $mdDialog) {
$scope.finish = function() {
var objIndex = getRootObjectById(widId, $rootScope.dashboard.widgets);
$mdDialog.hide();
document.getElementById('map').innerHTML = "";
//excel data
var array = JSON.parse($rootScope.json_string);
$scope.locationData = [];
//dividing it to chunks
var k,j,temparray,chunk = 8;
for (k=0,j=array.length; k<j; k+=chunk) {
temparray = array.slice(k,k+chunk);
var i;
//getting the longitude and latitude from the google geo api
for(i=0;i < temparray.length ; i++){
Geocode(temparray[i].PLACE_OF_ACCIDENT);
}
}
//sometimes data gets delayed
setTimeout(function(){ googleMap(); }, 5000);
};
function Geocode(address) {
var obj = {};
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': address}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
obj = {
lat : results[0].geometry.location.G,
lng : results[0].geometry.location.K
};
setTimeout(function(){ $scope.locationData.push(obj); }, 100);
}
else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function() {
Geocode(address);
}, 100);
}
else if (status === google.maps.GeocoderStatus.ZERO_LIMIT) {
setTimeout(function() {
Geocode(address);
}, 100);
}
else {
}
});
}
function googleMap() {
var dataStore = $scope.locationData;
var array = JSON.parse($rootScope.json_string);
var map = new google.maps.Map(document.getElementById('map'),{
center: {lat: 7.85, lng: 80.65},
zoom: 6 });
var pinImageGreen = new google.maps.MarkerImage("http://maps.google.com/mapfiles/ms/icons/green-dot.png");
var pinImageBlue = new google.maps.MarkerImage("http://maps.google.com/mapfiles/ms/icons/blue-dot.png");
var marker = [];
var k;
for(k=0; k < array.length; k++){
marker[k] = new google.maps.Marker({
position: {lat: $scope.locationData[k].lat, lng: $scope.locationData[k].lng},
map: map,
title: array[k].PLACE_OF_ACCIDENT,
icon: pinImageGreen,
VEHICLE_TYPE: array[k].VEHICLE_TYPE,
VEHICLE_USAGE: array[k].VEHICLE_USAGE,
VEHICLE_CLASS: array[k].VEHICLE_CLASS
});
marker[k].addListener('click', function(data) {
var j;
for(j=0;j<array.length;j++){
if(($scope.locationData[j].lat == data.latLng.G) && ($scope.locationData[j].lng == data.latLng.K )){
document.getElementById("details").innerHTML =
array[j].PLACE_OF_ACCIDENT + "</br>" +
array[j].VEHICLE_TYPE + "</br>" +
array[j].VEHICLE_USAGE + "</br>" +
array[j].VEHICLE_CLASS + "</br>" ;
}
}
});
}
}
$scope.cancel = function() {
$mdDialog.hide();
};
}
One way to slightly improve performance is this: Instead of adding markers to the map one at a time, just create the markers array separately and then add them all at once to the map. Here is a sample code:
var markersData = [];
for (var i = 0; i < myArray.length; i++) {
var item = scope.myArray[i];
if (item.lat != undefined && item.lon != undefined) {
var icon = 'icon.png';
markersData.push({
lat: item.lat,
lng: item.lon,
title: 'xyz'
});
}
}
map.addMarkers(markersData);
By the way I have used "gmaps.js" for this which simplifies coding google maps, but you don't necessarily need it. The general idea is to avoid adding markers to the map inside the loop, one by one.
EDIT: It seems that I'm hitting the query limit, but I'm not being returned a full 200 results. So upon further research it looks like the Google API will let me query 10 boxes, return those results, and then smacks me with an OVER_QUERY_LIMIT status for the rest. So I figure I now have two options: slow my queries, or broaden my distance to create fewer boxes along the route.
I'm currently fooling around building a little web app that provides a details about places along a route (like gas stations and coffee on a road trip). I'm using the Google Maps API with the Places Library and RouteBoxer. I'm generating all the appropriate boxes with RouteBoxer, but when the boxes are passed to the Places Library I'm only getting back some of the places. Usually I'll get the first half of the route (on shorter routes) or a few random chunks (for longer routes). San Francisco to Seattle returns me gas stations around Seattle and around Medford, OR only.
Initially I thought maybe I was hitting the results cap of 200, but it's making a separate request for each box, and my total results often aren't hitting 200. Results returned are generally pretty consistent from what I can see. When looking at the details of my network requests and responses, it seems that the script is moving through the boxes making requests with the Places library, and suddenly it stops part way through.
The live app where you can see results and boxes is on Heroku.
My JavaScript isn't the strongest by any means. That's part of why I wanted to work with this API, so please pardon my ignorance if I'm making a trivial mistake. The full script is below. Any direction is tremendously appreciated!
var infowindow = new google.maps.InfoWindow();
var map;
var routeBoxer;
var service;
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(39, -98),
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
service = new google.maps.places.PlacesService(map);
routeBoxer = new RouteBoxer();
directionService = new google.maps.DirectionsService();
directionsRenderer = new google.maps.DirectionsRenderer({ map: map })
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directions-panel'));
}
function calcRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var waypt1 = document.getElementById('waypoint1').value;
var waypt2 = document.getElementById('waypoint2').value;
var waypts = []
if (waypt1) {
waypts.push({
location:waypt1,
stopover:true});
}
if (waypt2) {
waypts.push({
location:waypt2,
stopover:true});
}
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
};
directionService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
// Build boxes around route
var path = response.routes[0].overview_path;
var boxes = routeBoxer.box(path, 2); // distance in km from route
drawBoxes(boxes);
for (var i=0; i < boxes.length; i++) {
var bounds = boxes[i];
findPlaces(bounds);
findPlacesByText(bounds);
}
} else {
alert("Directions query failed: " + status);
}
});
}
function findPlaces(bounds) {
var selectedTypes = [];
var inputElements = document.getElementsByClassName('placeOption');
for (var i=0; inputElements[i]; i++) {
if (inputElements[i].checked) {
selectedTypes.push(inputElements[i].value)
}
}
var request = {
bounds: bounds,
types: selectedTypes
};
if (selectedTypes.length > 0) {
service.radarSearch(request, callback);
}
}
function findPlacesByText(bounds) {
var selectedTypes = '';
var inputElements = document.getElementsByClassName('textOption');
for (var i=0; inputElements[i]; i++) {
if (inputElements[i].checked) {
selectedTypes += inputElements[i].value + ', '
}
}
var request = {
bounds: bounds,
query: selectedTypes
};
if (selectedTypes.length > 0) {
service.textSearch(request, callback);
}
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
var request = {
reference: place.reference
};
google.maps.event.addListener(marker,'click',function(){
service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var contentStr = '<h5>' + place.name + '</h5><p>' + place.formatted_address;
if (!!place.formatted_phone_number) contentStr += '<br />' + place.formatted_phone_number;
if (!!place.website) contentStr += '<br /><a target="_blank" href="' + place.website + '">' + place.website + '</a>';
contentStr += '<br />' + place.types + '</p>';
infowindow.setContent(contentStr);
infowindow.open(map,marker);
} else {
var contentStr = "<h5>No Result, status=" + status + "</h5>";
infowindow.setContent(contentStr);
infowindow.open(map,marker);
}
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
After much experimentation and further research, I decided to try to slow my queries. The way I handled that was to write a new function that calls my query function, and then recursively calls itself with a delay for the next route box. If an OVER_QUERY_LIMIT status is returned, it recalls that box with an increased delay. So far it seems to be working great, but it quickly increases the delay to nearly a half second (or more) between calls, which can take a while if you have a long route with many boxes. My new function that seems to have solves the problem is below. It'll take some more fine-tuning to really get it right, but it's close!
var delay = 100;
...
function queryPlaces(boxes, searchIndex) {
// delay calls to Places API to prevent going over query limit (10/sec)
var bounds = boxes[searchIndex];
findPlaces(bounds);
findPlacesByText(bounds);
if (searchIndex > 0) {
searchIndex--;
setTimeout(queryPlaces, delay, boxes, searchIndex);
}
}
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 don't know how to search for this in SO, so I'm asking a new question. What could cause or what is the concrete problem of my code: HTML generated by Javascript (createElement() and appendChild) is not being shown in Opera and Firefox, but it works in Chromium.
The HTML generating code:
function typesOfPlaces(map, bounds) {
var allowedTypes = [
"amusement_park",
"aquarium",
"art_gallery",
"cemetery",
"church",
"city_hall",
"hindu_temple",
"mosque",
"museum",
"night_club",
"park",
"place_of_worship",
"rv_park",
"spa",
"synagogue",
"travel_agency",
"zoo"
];
var typesToDisplay = new Array();
var request = {
bounds: bounds,
types: allowedTypes
};
var service = new google.maps.places.PlacesService(map);
service.nearbySearch(request, function(results, status) {
if(status == google.maps.places.PlacesServiceStatus.OK) {
for(var i = 0; i < results.length; i++) {
for(var j = 0; j < results[i].types.length; j++) {
for(var k = 0; k < allowedTypes.length; k++) {
if(results[i].types[j] == allowedTypes[k]) {
var allowed = true;
for(var x = 0; x < typesToDisplay.length; x++) {
if(allowedTypes[k]==typesToDisplay[x]) {
allowed = false;
}
}
if(allowed) {
typesToDisplay.push(allowedTypes[k]);
}
}
}
}
}
var parent = document.getElementById("types");
for(var i = 0; i < typesToDisplay.length; i++) {
var typeBox = document.createElement("div");
var checkBox = document.createElement("input");
var checkID = randomString(10);
var label = document.createElement("label");
checkBox.setAttribute("type", "checkbox");
checkBox.setAttribute("id", checkID);
label.setAttribute("for", checkID);
label.innerHTML = typesToDisplay[i];
typeBox.appendChild(checkBox);
typeBox.appendChild(label);
parent.appendChild(typeBox);
}
}
});
}//END OF Function
UPDATE TO COMMENTS
The randomString is just SO'ed code for generating random string:
function randomString(L) {
var s= '';
var randomchar=function() {
var n= Math.floor(Math.random()*62);
if(n<10) return n; //1-10
if(n<36) return String.fromCharCode(n+55); //A-Z
return String.fromCharCode(n+61); //a-z
}
while(s.length< L) s+= randomchar();
return s;
}
div #types really exists, it look like this:
<html>
<head>
...
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=MyKey&sensor=false&libraries=places&language=lt"></script>
</head>
<body>
<div>
<div>
<div id="types"></div>
</div>
</div>
</body>
</html>
You can see the import of google.maps.places.PlacesService by looking at the <head> section of the <script> tag, where you can see "&libraries=places".
SECOND UPDATE AFTER SOME TESTING
ok. I've figured out that if I deny location sharing in opera it works (it works in chromium because by default it does not even ask user if he is kind to share his geolocation with website)
The code for geolocation:
function initGeo()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}
else
{
errorFunction();
}
}
so, the function that does not work is successFunction (which is being launched if user kindly shares his geolocation)
function successFunction(position)
{
var geocoder = new google.maps.Geocoder();
var abstract_location;
var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
geocoder.geocode({'latLng': latlng}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
abstract_location = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast());
}
else
{
alert("NOT SUCCESS 1");
}
showGMap(latlng, abstract_location);
});
}
And the errorFunction, which successfully works on chromium by default and on Opera if you deny access to your geolocation:
function errorFunction(error)
{
var geocoder = new google.maps.Geocoder();
if(google.loader.ClientLocation)
{
var latlng = new google.maps.LatLng(google.loader.ClientLocation.latitude, google.loader.ClientLocation.longitude);
geocoder.geocode({'latLng': latlng}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var abstract_location = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast());
}
else
{
alert("NOT SUCCESS 2");
}
showGMap(latlng, abstract_location);
});
}
else
{
geocoder.geocode( {'address': 'Vilnius Region, Lithuania'}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var latlng = results[0].geometry.location;
var abstract_location = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast());
showGMap(latlng, abstract_location);
}
else
{
alert("NOT SUCCESS 3");
}
});
}
}
Nor Chromium nor Opera does not give me ANY errors, nor javascript exceptionaly, nor in general.
So the problem is in success function. Because it even does not give me alert(typesToDisplay.length) [as suggested by Stuart in the comments] - it means that there is no alert at all - in case of error function I get the aswer 4 and thus i can see my generated HTML.
In case of success function there is just empty (without any appended childs) #types .
I do not see what could be causing success function to be NOTSUCCESS (:))
Ok, so i have figured it out - it was pretty simple though...
The Geolocation data which you get is an address, so bounds are very small, you have to extract city with reverse geocoding (results[6].formatted_address) and then you geocode that reverse geocode (so confused though Geocoding -> reverse -> again geocode) and then it works!
So the problem was at geocoding (haven't thought that bounds of address is not the whole city (that should have been obvious in the first place, but was not).
HTML5 geocoding could have the info about the city (not only lan and lng, firefox has something, but that's only firefox, not the whole HTML5), but i do not know if it would be good or not (lack of my personal knowlede at the moment in this specific field)
So if anyone does get to something similar -> check the bounds ;)
Thank you for your comments and for your view's.
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