Welcome, Guest
Username: Password: Remember me

TOPIC: Google maps and previous maps answers

Google maps and previous maps answers 3 months 3 weeks ago #110337

  • BCorfman
  • BCorfman's Avatar
  • OFFLINE
  • Fresh Lemon
  • Posts: 2
  • Karma: 0
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 months 3 weeks ago by BCorfman.
The administrator has disabled public write access.

Google maps and previous maps answers 3 months 3 weeks ago #110377

  • tpartner
  • tpartner's Avatar
  • NOW ONLINE
  • LimeSurvey Team
  • Posts: 4266
  • Thank you received: 803
  • Karma: 368
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_survey_926833_2014-06-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.

LimeSurvey is open-source and run entirely by volunteers so please consider donating to support the project.
Last Edit: 3 months 3 weeks ago by tpartner.
The administrator has disabled public write access.
The following user(s) said Thank You: dglp

Google maps and previous maps answers 3 months 2 weeks ago #110563

  • BCorfman
  • BCorfman's Avatar
  • OFFLINE
  • Fresh Lemon
  • Posts: 2
  • Karma: 0
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 months 2 weeks ago by BCorfman.
The administrator has disabled public write access.

Google maps and previous maps answers 3 months 2 weeks ago #110619

  • tpartner
  • tpartner's Avatar
  • NOW ONLINE
  • LimeSurvey Team
  • Posts: 4266
  • Thank you received: 803
  • Karma: 368
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.

LimeSurvey is open-source and run entirely by volunteers so please consider donating to support the project.
The administrator has disabled public write access.
Moderators: ITEd
Time to create page: 0.165 seconds
Donation Image