Finish function executing before proceeding - javascript

I have a form that is validated upon submission, inside the form submit a function is called, the submit continues and doesn't wait for the function to finish. How do I fix this?
var clientaddress=false;
function checkaddress(callback){
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': address}, function(results, status) {
if (status != google.maps.GeocoderStatus.OK) {
clientaddress=false;
callback(false);
}
else if (status == google.maps.GeocoderStatus.OK) {
clientaddress=true;
callback(false);
}
}
jQuery(document).ready(function(){
jQuery("#submitOrder").submit(function(){
checkaddress(function(result) {
if (!result) {
jAlert("Please enter a valid address!");
jQuery("#address").focus();
isValidation = 0;
}
});
//other validation code that gets executed without waiting for checkaddress()
//submit page
})
I tried to make one function that calls both the address checker and a validation function, but still they do not wait for each other.
How can I solve this problem?

Because the geocode function is async! Use a callback:
function checkaddress(callback){
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status != google.maps.GeocoderStatus.OK) {
callback(false)
} else if (status == google.maps.GeocoderStatus.OK) {
callback(true)
}
});
}
Then use this like:
checkaddress(function(result) {
if (result) {
//result true!
} else {
//result false!
}
//REST OF YOUR CODE GOES HERE, IF PUT OUTSIDE IT WILL EXECUTE WHILE CHECKADDRESS IS IN PROGRESS
});
Your submit function is also most likely running the default behavior, use preventDefault
jQuery("#submitOrder").submit(function(e){
e.preventDefault();
//code
});

Related

Changing visibility of HTML elements based on geolocation permission [duplicate]

This question already has answers here:
check if location setting has been turned off in users browser
(2 answers)
Closed 3 years ago.
I'm trying to make an HTML element visible if the end user hasn't agreed to let the browser know their location. However, my current code isn't working (nor is the console log) when declining the browser's request. But when allowing the browser to access my location, the API call to Google Places works.
To summarise: If a user declines the browser's request, I want the visibility of geolocationunavail to be visible, rather than hidden.
HTML
<div id="geolocationunavail">
<p>Don't want to share your location?</p>
<p><span>That's cool.</span> Type a location below.</p>
</div>
CSS
#geolocationunavail {
visibility: hidden;
}
JS
function getUserLocation() {
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(function(position) {
document.querySelector("#longitude").value = position.coords.longitude;
document.querySelector("#latitude").value = position.coords.latitude;
var lng = position.coords.longitude;
var lat = position.coords.latitude;
var latlng = new google.maps.LatLng(lat, lng);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status !== google.maps.GeocoderStatus.OK) {
alert(status);
}
if (status == google.maps.GeocoderStatus.OK) {
console.log(results);
var address = (results[0].formatted_address);
document.querySelector("#citysearch").value = address;
}
});
});
} else {
console.log("Geolocation is not supported by this browser.");
document.getElementById("geolocationunavail").style.display = "visible";
}
}
It looks like you have 2 different problems, so I will address them both:
First, your geolocation function is not working as expected. This is happening because you are not using the function correctly. You would not want to use an else statement to say that geolocation is not working, because geolocation will always "work" since it is called successfully regardless of the user input. Even if the user selects "block" the function technically "worked" and therefore will not run the else statement.
Second, your visibility is not toggling correctly. There are 2 ways you can fix this. You can either make it a class and use classList.toggle("myClass"), or you can do document.getElementById('geolocationunavil').style.visibility = 'visible';
Both of these put together will result in:
function getUserLocation() {
navigator.geolocation.getCurrentPosition(
position => {
document.querySelector("#longitude").value = position.coords.longitude;
document.querySelector("#latitude").value = position.coords.latitude;
var lng = position.coords.longitude;
var lat = position.coords.latitude;
var latlng = new google.maps.LatLng(lat, lng);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status !== google.maps.GeocoderStatus.OK) {
alert(status);
}
if (status == google.maps.GeocoderStatus.OK) {
console.log(results);
var address = (results[0].formatted_address);
document.querySelector("#citysearch").value = address;
}
});
},
err => {
console.log("Geolocation is not supported by this browser.");
document.getElementById("geolocationunavail").style.visibility = "visible";
})
}

Trigger JavaScript error when geo location services disabled

In my AngularJS project I am using the following code to get a device's GPS co-ordinates:
// when user clicks on geo button
$scope.getGeoLocation = function() {
var geocoder = new google.maps.Geocoder();
window.navigator.geolocation.getCurrentPosition(function(position) {
$scope.$apply(function() {
$scope.position = position;
var latlng = new google.maps.LatLng($scope.position.coords.latitude, $scope.position.coords.longitude);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
$scope.searchstring = results[2].formatted_address;
$location.search('s', $scope.searchstring);
$location.search('p', 1);
$location.search('geo', true);
$route.reload();
}
});
});
}, function(error) {
$scope.error = error;;
});
};
The problem is when location services is turned off on an iPhone 6, there is a no error created to inform the user that they need to turn on location services.
Does any one know how I can amend the code above to trigger an error in this scenario? Any help would be much appreciated.
As pointed out in this post Is there a way to check if geolocation has been DECLINED with Javascript?, you can pass a second callback to getCurrentPosition which will get called if the permission is declined.
Thanks for pointing me in the right direction unobf. Please find attached the code (with updated error handling) in case any one stumbles across this.
// when user clicks on geo button
$scope.getGeoLocation = function() {
var geocoder = new google.maps.Geocoder();
window.navigator.geolocation.getCurrentPosition(function(position) {
$scope.$apply(function() {
$scope.position = position;
var latlng = new google.maps.LatLng($scope.position.coords.latitude, $scope.position.coords.longitude);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
$scope.searchstring = results[2].formatted_address;
$location.search('s', $scope.searchstring);
$location.search('p', 1);
$location.search('geo', true);
$route.reload();
}
});
});
}, function(error) {
$scope.error = "";
// Check for known errors
switch (error.code) {
case error.PERMISSION_DENIED:
$scope.error = "This website does not have permission to use " +
"the Geolocation API.";
alert("Geo location services appears to be disabled on your device.");
break;
case error.POSITION_UNAVAILABLE:
$scope.error = "The current position could not be determined.";
break;
case error.PERMISSION_DENIED_TIMEOUT:
$scope.error = "The current position could not be determined " +
"within the specified timeout period.";
break;
}
// If it's an unknown error, build a $scope.error that includes
// information that helps identify the situation, so that
// the error handler can be updated.
if ($scope.error == "")
{
var strErrorCode = error.code.toString();
$scope.error = "The position could not be determined due to " +
"an unknown error (Code: " + strErrorCode + ").";
}
});
};

running a function after a google map call has finished

I'm trying to collect location data from my users as they're entering other details in a form. So I have a google map which users can move a marker about on but I also have an input which they can type a location into.
When they click to submit the form, I want to first geocode the location they have typed and update the hidden lat lng inputs in my form before the submit actually takes place.
I know there's lots of info online but I've read loads of tutorials but I'm struggling to understand or at least to apply the tutorials to my situation.
So when a user clicks submit I want to run geocode and only submit the form when geocode is definitely finished.
$('.submitButton').click(function () {
geocode();
$("#searchForm").submit();//Then submit when geocode finishes
});
And the geocode function
function geocode(){
geocoder.geocode({
address: $('#address').val()
}, function(results, status){
if(status == google.maps.GeocoderStatus.OK){
var geoPoint = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());
map.setCenter(geoPoint);
circle.setCenter(geoPoint);
marker.setPosition(geoPoint);
$('#lat').val(geoPoint.lat());
$('#lng').val(geoPoint.lng());
} else{
alert("Can not geolocate this address.");
}
});
}
Can someone explain to me what I need to do in simple javascript dummy language? THanks
Because Geocoding service is asynchronous, geocode() will return almost immediately and $("#searchForm").submit() will submit what is available and that will be wrong (old or undefined data).
You have to move form submit call to geocode() function just after settings of lat/lng values:
...
marker.setPosition(geoPoint);
$('#lat').val(geoPoint.lat());
$('#lng').val(geoPoint.lng());
$("#searchForm").submit();
} else{
...
If, as you said in comment, geocode() function is also used somewhere else then you will have to write another function with similar functionality or prepare two different callback function.
You may pass an optional argument to geocode, e.g. a function that will be executed on success:
$('.submitButton').click(function (e) {
e.preventDefault();
//call geocode and pass the desired function as argument
geocode(function(){$("#searchForm").submit();});
return false;
});
function geocode(fnc){
geocoder.geocode({
address: $('#address').val()
}, function(results, status){
if(status == google.maps.GeocoderStatus.OK){
var geoPoint = new google.maps.LatLng(results[0].geometry.location.lat(),
results[0].geometry.location.lng());
map.setCenter(geoPoint);
circle.setCenter(geoPoint);
marker.setPosition(geoPoint);
$('#lat').val(geoPoint.lat());
$('#lng').val(geoPoint.lng());
//check if the fnc-argument is a function,
//when it does, execute the function
if($.type(fnc)==='function'){
fnc();
}
} else{
alert("Can not geolocate this address.");
}
});
}

Jquery with autocomplete trigger after selecting an element

I am trying to use the autocomplete jquery API. The issue is I want to trigger a function or a set of code once I selected an item but i keep getting undefined items.
Here my code:
function init()
{
var input = document.getElementById('event_address');
var options =
{
types: ['geocode']
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
// event triggered when drop-down option selected
select: function(event, ui) {
var address = document.getElementById(event_address).value;
geocoder.geocode( { 'address': address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
alert(results[0].geometry.locations);
}
});
}
}
Here my errors:
Uncaught SyntaxError: Unexpected token (
Thanks
First, I believe what you are referring to is jqueryUI's autocomplete widget. The select method fires when an autocomplete selection has been made. I'm assuming what you're trying to do would be to display the coordinates of a geographical region chosen from the auto complete list.
you would need to do something like this:
$('#inputbox').autocomplete({
select: function(event, ui){
// code to get selection
var address = $('#inputbox').text();
//assuming your geocode is correct
geocoder.geocode( { 'address': address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
alert(results[0].geometry.locations);
}
});
}
});
For more info, see the autocomplete documentation: http://api.jqueryui.com/autocomplete/#event-select

Javascript function on submit button - Wait for it to complete

I want to trigger a function when the submit button is pressed on the form and wait for the javascript function to complete, then continue the form submission. I dont want the form to submit before the javascript function has completed.**
This is what I have at the moment:
http://jsfiddle.net/njDvn/68/
function autosuggest() {
var input = document.getElementById('location');
var options = {
types: [],
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
}
<!-- Get lat / long -->
function getLatLng() {
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('location').value;
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latLng = results[0].geometry.location;
$('#lat').val(results[0].geometry.location.lat());
$('#lng').val(results[0].geometry.location.lng());
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
<!-- Load it -->
window.onload = autosuggest;
You can intercept the form submission, abort it and send the geocoding request to Google.
When the server responds, you can re-submit the form from the callback (or display an error in case of failure).
Store the state of the request somewhere (for the sake of simplicity, I'm using a global variable in my example). In this case, it's just a flag that indicates whether or not the geocoding request was completed successfully (so that now, when the form is submitted and the listener is re-triggered, it will know not to re-send the geocoding request).
http://jsfiddle.net/njDvn/75/
Feel free to remove the console logging.
You may also want to make the lat/long fields hidden.
var GeoCoded = {done: false}; // this holds the status of the geo-coding request
$(document).ready(function(){
autosuggest(); // place your auto-suggest (now called autocomplete) box
$('#myform').on('submit',function(e){
if(GeoCoded.done)
return true;
e.preventDefault();
console.log('submit stopped');
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('location').value;
// disable the submit button
$('#myform input[type="submit"]').attr('disabled',true);
// send the request
geocoder.geocode({
'address': address
},
function (results, status) {
// update the status on success
if (status == google.maps.GeocoderStatus.OK) {
var latLng = results[0].geometry.location;
$('#lat').val(results[0].geometry.location.lat());
$('#lng').val(results[0].geometry.location.lng());
// if you only want to submit in the event of successful
// geocoding, you can only trigger submission here.
GeoCoded.done = true; // this will prevent an infinite loop
$('#myform').submit();
} else { // failure
console.log("Geocode was not successful for the following reason: " + status);
//enable the submit button
$('#myform input[type="submit"]').attr('disabled',false);
}
});
});
});
First you need to prevent the form to be submitted, add a return false at the end of getLatLng() function.
Then when the geocoding is done, submit the form manually with document.getElementsByTagName('form')[0].submit()
Here's an updated jsfiddle: http://jsfiddle.net/njDvn/70/
myFunction = new function(callback) {
$.ajax({...}).done(callback());
}
myFunction(new function() {
getLatLng();
});
Here you need to call myFunction onSubmit event.
As MasterAM has stated, all you need do is the following:
/// I've included the following function to allow you to bind events in a
/// better way than using the .onevent = function(){} method.
var addEvent = (function(){
if ( window.addEventListener ) {
return function(elm, eventName, listener, useCapture){
return elm.addEventListener(eventName,listener,useCapture||false);
};
}
else if ( window.attachEvent ) {
return function(elm, eventName, listener){
return elm.attachEvent('on'+eventName,listener);
};
}
})();
/// add another window.onload listener
addEvent(window,'load',function(){
/// find the form, obviously should use whatever id you have on your form
var form = document.getElementById('my_form');
form.preventSubmit = true;
/// add our onsubmit handler
addEvent(form,'submit',function(e){
/// only stop the form if we haven't already
if ( form.preventSubmit ) {
/// place/call whatever code you need to fire before submit here.
alert('submit was blocked!');
/// after that code is complete you can use the following
form.preventSubmit = false;
form.submit();
/// return false prevents the submit from happening
return false;
}
});
});

Categories