Google maps and previous maps answers

More
3 years 2 months ago - 3 years 2 months ago #110337 by BCorfman
BCorfman created the topic: Google maps and previous maps answers
Hello,

I'm trying to implement a survey where someone picks a location on one map, and then picks a location on another map, and it calculates the distance between those two points.

To do this I'm attempting to implement a modified version of tpartner's code from this page: www.limesurvey.org/en/community-services...on?start=10&start=20


But no matter what I try, I can't get this to work. I have absolutely no experience with Javascript so I've been trying to stumble my way through it, but can't figure it out. Here is the code I modified and attached to question 2:
<script type="text/javascript" charset="utf-8">	
 
	$(document).ready(function(){
 
		// Identify the map
		var map2SGQA = '{SGQ}';
		var map1SGQA = '774328X12X32';
		var currentMap = gmaps[''+map2SGQA+'_c'];
 
 
		// Wait for the map to load
		google.maps.event.addListenerOnce(currentMap, 'idle', function(){ 
 
			// Some variable definitions
			var currentMarker = gmaps['marker__'+map2SGQA+'_c'];
			var answerInput = $('#answer'+map2SGQA+'_c');
			var defaultPosition = $(answerInput).val();
			var startLat = $('{INSERTANS:'+map1SGQA+'}').val().split(';')[0];
			var startLng = $('{INSERTANS:'+map1SGQA+'}').val().split(';')[1];
			var startLatLng = new google.maps.LatLng(startLat, startLng);
			var originIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=O|FFFF00|000000';
 
 
			// Listener on the map events
			google.maps.event.addListener(currentMap, 'click', function() {
				calculateDistances(startLatLng, currentMarker.getPosition());
			});
			google.maps.event.addListener(currentMarker, 'dragend', function() {
				calculateDistances(startLatLng, currentMarker.getPosition());
			});
			google.maps.event.addListener(currentMap, 'rightclick', function() {
				calculateDistances(startLatLng, currentMarker.getPosition());
			});
 
			// Insert the results element
			$(answerInput).after('<div class="distanceResults" />');
 
		});
	});
 
	function calculateDistances(origin, destination) {
		var service = new google.maps.DistanceMatrixService();
		service.getDistanceMatrix({
			origins: [origin],
			destinations: [destination],
			travelMode: google.maps.TravelMode.DRIVING,
			unitSystem: google.maps.UnitSystem.METRIC,
			avoidHighways: false,
			avoidTolls: false
		}, callback);
	}
 
	function callback(response, status) {
		if (status != google.maps.DistanceMatrixStatus.OK) {
			alert('Error was: ' + status);
		} else {
			var origins = response.originAddresses;
			var destinations = response.destinationAddresses;
 
			var outputDiv = $('.questiontext');
			outputDiv.innerHTML = '';
 
			for (var i = 0; i < origins.length; i++) {
				var results = response.rows[i].elements;
				for (var j = 0; j < results.length; j++) {
					$('.distanceResults').html('Start address: '+origins[i]+'<br />\
												End address: '+destinations[j]+'<br />\
												Distance: '+results[j].distance.text+'<br />\
												Time: '+results[j].duration.text+'');
				}
			}
		}
	}
</script>


I could also see doing this by setting the start point of the second map to the answer of the first map, but because of how map questions output answers I can't figure out how to get that to work either.


Edit:

When putting both maps on the same page and using the following code, I have gotten this to work somewhat. Unfortunately it won't change the starting location after it has tried calculating everything once, so if anyone has any suggestions there I'd like to fix that.
<script type="text/javascript" charset="utf-8">	
 
	$(document).ready(function(){
 
		// Identify the map
		var map2SGQA = '{SGQ}';
		var map1SGQA = '774328X12X32';
		var currentMap = gmaps[''+map2SGQA+'_c'];
		var prevMap = gmaps[''+map1SGQA+'_c'];
 
 
		// Wait for the map to load
		google.maps.event.addListenerOnce(currentMap, 'idle', function(){ 
 
			// Some variable definitions
			var currentMarker = gmaps['marker__'+map2SGQA+'_c'];
			var prevMarker = gmaps['marker__'+map1SGQA+'_c'];
			var answerInput = $('#answer'+map2SGQA+'_c');
			var defaultPosition = $(answerInput).val();
			var startLat = $('#answer'+map1SGQA+'_c').val().split(' ')[0];
			var startLng = $('#answer'+map1SGQA+'_c').val().split(' ')[1];
			var startLatLng = new google.maps.LatLng(startLat, startLng);
			var originIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=O|FFFF00|000000';
 
 
			// Listener on the map events
			google.maps.event.addListener(prevMap, 'click', function() {
				startLatLng = prevMarker.getPosition();
			});
			google.maps.event.addListener(prevMarker, 'dragend', function() {
				startLatLng = prevMarker.getPosition();
			});
			google.maps.event.addListener(prevMap, 'rightclick', function() {
				startLatLng = prevMarker.getPosition();
			});
 
			google.maps.event.addListener(currentMap, 'click', function() {
				calculateDistances(startLatLng, currentMarker.getPosition());
			});
			google.maps.event.addListener(currentMarker, 'dragend', function() {
				calculateDistances(startLatLng, currentMarker.getPosition());
			});
			google.maps.event.addListener(currentMap, 'rightclick', function() {
				calculateDistances(startLatLng, currentMarker.getPosition());
			});
 
			// Insert the results element
			$(answerInput).after('<div class="distanceResults" />');
 
		});
	});
 
	function calculateDistances(origin, destination) {
		var service = new google.maps.DistanceMatrixService();
		service.getDistanceMatrix({
			origins: [origin],
			destinations: [destination],
			travelMode: google.maps.TravelMode.DRIVING,
			unitSystem: google.maps.UnitSystem.METRIC,
			avoidHighways: false,
			avoidTolls: false
		}, callback);
	}
 
	function callback(response, status) {
		if (status != google.maps.DistanceMatrixStatus.OK) {
			alert('Error was: ' + status);
		} else {
			var origins = response.originAddresses;
			var destinations = response.destinationAddresses;
 
			var outputDiv = $('.questiontext');
			outputDiv.innerHTML = '';
 
			for (var i = 0; i < origins.length; i++) {
				var results = response.rows[i].elements;
				for (var j = 0; j < results.length; j++) {
					$('.distanceResults').html('Start address: '+origins[i]+'<br />\
												End address: '+destinations[j]+'<br />\
												Distance: '+results[j].distance.text+'<br />\
												Time: '+results[j].duration.text+'');
				}
			}
		}
	}
</script>
Last Edit: 3 years 2 months ago by BCorfman.

Please Log in to join the conversation.

More
3 years 2 months ago - 3 years 2 months ago #110377 by tpartner
tpartner replied the topic: Google maps and previous maps answers
I would use something like the script below. This puts listeners on two maps on a page and when they are moved, calculates the addresses and distance and loads it into a long-text type question.

<script type="text/javascript" charset="utf-8">	
	$(document).ready(function() {
 
		// Identify the elements
		var map1Question = $('input.text.location:eq(0)').closest('.text-short');
		var map2Question = $('input.text.location:eq(1)').closest('.text-short');
		var map1SGQA = $('input.text.location', map1Question).attr('id').replace(/answer/, '').replace(/_c/, '');
		var map1 = gmaps[''+map1SGQA+'_c'];
		var marker1 = gmaps['marker__'+map1SGQA+'_c'];
		var map1Input = $('#answer'+map1SGQA+'_c');
		var map2SGQA = $('input.text.location', map2Question).attr('id').replace(/answer/, '').replace(/_c/, '');
		var map2 = gmaps[''+map2SGQA+'_c'];
		var marker2 = gmaps['marker__'+map2SGQA+'_c'];
		var map2Input = $('#answer'+map2SGQA+'_c');
		var resultsInput = $('.text-long:eq(0) .textarea');
 
		// Disable the results textarea
		$(resultsInput).attr('readonly', true);
 
		// Wait for the maps to load
		google.maps.event.addListenerOnce(map1, 'idle', function(){ 
			// Listeners on the map 1 events
			google.maps.event.addListener(map1, 'click', function() {
				updateDistance();
			});
			google.maps.event.addListener(marker1, 'dragend', function() {
				updateDistance();
			});
			google.maps.event.addListener(map1, 'rightclick', function() {
				updateDistance();
			});
		});
		google.maps.event.addListenerOnce(map2, 'idle', function(){ 
			// Listeners on the map 2 events
			google.maps.event.addListener(map2, 'click', function() {
				updateDistance();
			});
			google.maps.event.addListener(marker2, 'dragend', function() {
				updateDistance();
			});
			google.maps.event.addListener(map2, 'rightclick', function() {
				updateDistance();
			});
		});
 
		function updateDistance() {
			var startLat = $(map1Input).val().split(' ')[0];
			var startLng = $(map1Input).val().split(' ')[1];
			var startLatLng = new google.maps.LatLng(startLat, startLng);
			var endLat = $(map2Input).val().split(' ')[0];
			var endLng = $(map2Input).val().split(' ')[1];
			var endLatLng = new google.maps.LatLng(endLat, endLng);
 
			calculateDistances(startLatLng, endLatLng);
		}
 
		function calculateDistances(origin, destination) {
			var service = new google.maps.DistanceMatrixService();
			service.getDistanceMatrix({
				origins: [origin],
				destinations: [destination],
				travelMode: google.maps.TravelMode.DRIVING,
				unitSystem: google.maps.UnitSystem.METRIC,
				avoidHighways: false,
				avoidTolls: false
			}, callback);
		}
 
		function callback(response, status) {
			if (status != google.maps.DistanceMatrixStatus.OK) {
				alert('Error was: ' + status);
			} else {
				var origins = response.originAddresses;
				var destinations = response.destinationAddresses;
 
				for (var i = 0; i < origins.length; i++) {
					var results = response.rows[i].elements;
					for (var j = 0; j < results.length; j++) {
						$(resultsInput).val('Start address: '+origins[i]+'\n\nEnd address: '+destinations[j]+'\n\nDistance: '+results[j].distance.text+'\n\nTime: '+results[j].duration.text+'');
					}
				}
			}
		}
 
	});
</script>

Here's a working 2.05 survey with the script in the source of the first map question.

File Attachment:

File Name: limesurvey...6-25.lss
File Size:22 KB




.

Cheers,
Tony Partner
Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
Attachments:
Last Edit: 3 years 2 months ago by tpartner.
The following user(s) said Thank You: dglp

Please Log in to join the conversation.

More
3 years 2 months ago - 3 years 2 months ago #110563 by BCorfman
BCorfman replied the topic: Google maps and previous maps answers
Thanks so much, this works pretty much perfectly.

Edit: The problems below are suddenly not happening anymore; go figure. I would like to know if there's a reason why the following listener inserted into the code you provided doesn't react to the map center changing when the geocoder changes the map center:

listener:
google.maps.event.addListener(map1, 'center_changed', function() {
	updateDistance();
});

Geocoding (there is a second one of these attached to the second map with all the 1s replaced with 2s):
<script>
    var geocoder1;
    var mapgeo1;
    var markergeo1;
    function initialize1() {
        geocoder1 = new google.maps.Geocoder();
        mapgeo1 = gmaps[''+'{SGQ}_c'];
        markergeo1 = gmaps['marker__{SGQ}_c'];
    }
    function codeAddress1() {
        var address1 = document.getElementById('address1').value;
        geocoder1.geocode( { 'address': address1}, function(results1, status1) {
            if (status1 == google.maps.GeocoderStatus.OK) {
                var coords1 = String(results1[0].geometry.location)
                coords1 = coords1.replace(/\(?\)?\,?/g, '')
                document.getElementById('answer{SGQ}_c').value = coords1;
                mapgeo1.setCenter(results1[0].geometry.location);
                markergeo1.setPosition(results1[0].geometry.location);
            } else {
                alert('Geocode was not successful for the following reason: ' + status1);
            }
        });
    }
 
google.maps.event.addDomListener(window, 'load', initialize1);
 
</script>

button (again, another one on the second map):
<div id="panel">
	<input id="address1" type="textbox" value="" /> <input onclick="codeAddress1()" type="button" value="Suche" /></div>




I am trying to get it to work with a geocoder, and both sets of js work fine individually, but for some reason whenever I try searching with the search box element that calls the geocoder it makes the distance calculation js stop working. Here's the code for the geocoding:

-removed-


And then, of course, I added lines like this into the distance js (though they have nothing to do with it not working)

-removed-

Any idea why these aren't interacting well? I tried to make them not have any overlapping variables or anything in case that was the problem but it hasn't helped.

Edit: Oh, and here's the button in case it matters:
-removed-
Last Edit: 3 years 2 months ago by BCorfman.

Please Log in to join the conversation.

More
3 years 2 months ago #110619 by tpartner
tpartner replied the topic: Google maps and previous maps answers
Can you attach a test survey with your code?

Cheers,
Tony Partner
Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.

Please Log in to join the conversation.

Start now!

Just create your account and start using Limesurvey today.

Register now