Delay form submission until location is retrieved
Asked Answered
B

4

8

I have an application that attempts to get locations settings from the browser, this tends to take a little while so I want it to run when the page loads. However, if you click the submit button before the location callback has run, you have no location data. My question is simple, how do I wait for my location success callback to finish before submitting my form? (without something silly like a sleep statement).
Ideally I'd like to flash a busy indicator and wait for the data. Is this possible? I have the code to make a busy indicator visible, but am not sure how I can elegantly wait for the data to be available.

$(document).ready(function(){
    var lat = "";
    var lng = "";
    var accuracy = "";
    var locationFound = false;

    if(navigator.geolocation){
        navigator.geolocation.getCurrentPosition(function positionSuccess(loc){
            lat = loc.coords.latitude;
            lng = loc.coords.longitude;
            accuracy = loc.coords.accuracy;
            locationFound = true;               
        });
    }else{
        alert("I'm sorry, your jerk browser doesn't support geolocation");
        locationFound = true;
    }

$('#locForm').submit(function(e){  

        $('#lat').val(lat);
        $('#lng').val(lng);
        $('#boundary').val($('#boundary-select').val());
}
Bashemeth answered 2/5, 2012 at 1:41 Comment(0)
B
1

Disable the submit button until the location data has been passed.

$('input[type="submit"]').attr('disabled','disabled');

Then enable the submit button

$('input[type="submit"]').removeAttr('disabled');
Bertrand answered 2/5, 2012 at 1:50 Comment(1)
I think this is a good fallback, but I'd much rather have the button enabled and introduce a delay after clicking the button rather than having having the button disabled for a while on page load.Bashemeth
H
1

If the location plugin you're using doesn't have a callback function available, then you would need to bind the results to the page somehow and check against it before the user submits.

One way is binding the results of the location to the form, then only allow the form to submit when there is a location there. Here is an example of using .data() to accomplish this.

    $(document).ready(function(){
        var lat = "";
        var lng = "";
        var accuracy = "";
        var locationFound = false;

        if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(function positionSuccess(loc){
                lat = loc.coords.latitude;
                lng = loc.coords.longitude;
                accuracy = loc.coords.accuracy;
                locationFound = true;  

                //bind the results to the form object using data()
                $("#locForm").data('lat' , lat)
                $("#locForm").data('lng' , lng)
                $("#locForm").data('accuracy' , accuracy)
                $("#locForm").data('locationFound' , locationFound)

            });
        }else{
            alert("I'm sorry, your jerk browser doesn't support geolocation");
            locationFound = true;
        }

    $('#locForm').submit(function(e){  

            e.preventDefault(); //prevents the normal submit

            if ( $("#locForm").data('lat') == "" || 
                 $("#locForm").data('lng') == "" || 
                 $("#locForm").data('accuracy') == "" || 
                 $("#locForm").data('locationFound') == ""
                ) {
             alert("Please wait for the browser to detect your location.");   
             return false;
                }
            else {       
              $.post( $(this).attr('action'),  $(this).serialize(), function(data){ 
                       // your callback data from the submit here
               } ); 
            }



    }

Added this code which checks every second for a value in from your location plugin:

  function wait4location() {

            if ( $("#locForm").data('lat') == "" || 
                 $("#locForm").data('lng') == "" || 
                 $("#locForm").data('accuracy') == "" || 
                 $("#locForm").data('locationFound') == ""
                ) {
                   x = setTimeout('wait4location()',1000) //every second
              } else { 
                  $("#loading").hide();
                  return false; 
                }
  }

  $("#loading").show();
  wait4location();
Heterosexuality answered 2/5, 2012 at 1:51 Comment(5)
The problem here is you are relying on telling the user "please try again" I'd much rather flash a busy indicator and wait for the data. Is this possible? I have the code to make a busy indicator visible, but am not sure how I can elegantly wait for the data to be available.Bashemeth
You can set a timer on this, otherwise, again if your plugin that retrieves the location doesn't have a CALLBACK function (which probably does, look at the documentation).Heterosexuality
I added a code that does what you said and will check every second until all the fields are populated.Heterosexuality
You can also use input [type=hidden] fields too instead of .data(), in case you were submitting this data in the form.Heterosexuality
I appreciate the help and this is for sure the route I want to go down, but I just can't make this work correctly =/Bashemeth
V
0

Use two semaphores:

var geoLoaded = false,
    submittingForm = false;

function LoadGeoData() {
    // .. your load code
    geoLoaded = true;
    ReallySubmitForm();
}

$('form').submit(function(e) {
    // .. your code
    submittingForm = true;
    ReallySubmitForm();
})

function ReallySubmitForm() {
    if (submittingForm && geoLoaded) {
        // .. your submit code
    } else {
        // .. trigger loading code
    }
}

This way, the user will see the loading image only if the Geo Data has not fully loaded by the time they submit the form. You will notice that it doesn't matter which event gets triggered first, it will only go through when both are done.

Verein answered 2/5, 2012 at 5:44 Comment(0)
L
0

You can add a submit function to the form after the location is returned.

Here is a snippet of code that worked for me.

HTML

<form id="form" action="" method="POST">

JavaScript

function getLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(showPosition);
    } else { 
        x.innerHTML = "Geolocation is not supported by this browser.";
    }
}
function showPosition(position) {
    x.innerHTML = "<input type=hidden name=lat id=lat value=" + 
        position.coords.latitude + "><input type=hidden name=lng id=lng value=" 
        + position.coords.longitude + ">";
    document.getElementById("form").submit();
}
Lapillus answered 20/2, 2018 at 2:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.