Hi I have a button which when it gets clicked triggers a function. The function does some stuff (reverse geocodes a latitude/longitude) and then fills a hidden form input with a value.
I need the input to have the correct value before the rest of the code I need gets executed, is there a way to do this? At the moment I have
$('.addButton').click(function() {
//first run the reverse geocode to update the hidden location input with the readable address
reversegeocode();
var location = $("#location").val();//the value I need
$.post("<?php echo $this->webroot;?>locations/add", {location:location})
.done(function (data) {
$("#locationsHolder").html(data);
});
});
So basically I don't want to get the value from the input and post it via AJAX until I know that the reversegeocode()
function has finished
Can anyone please explain how I can go about this. I've read some stuff about deferment but I'm absolutely useless at figuring out Javascript and I'm really struggling.
Thanks
EDIT:
Here's my reversegeocode funciton
function reversegeocode(){
var lat = $('#lattitude').val();
var lng = $('#longitude').val();
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {//http://stackoverflow.com/questions/8082405/parsing-address-components-in-google-maps-upon-autocomplete-select
var address_components = results[0].address_components;
var components={};
jQuery.each(address_components, function(k,v1) {jQuery.each(v1.types, function(k2, v2){components[v2]=v1.long_name});})
var output = '';
var needAcomma = false;
if(components.route != undefined) {
output += components.route;
needAcomma = true;
}
if(components.locality != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.locality;
needAcomma = true;
}
if(components.administrative_area_level_1 != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.administrative_area_level_1;
needAcomma = true;
}else if(components.administrative_area_level_2 != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.administrative_area_level_2;
needAcomma = true;
}else if(components.administrative_area_level_3 != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.administrative_area_level_3;
needAcomma = true;
}
$("#location").val(output);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
}
Since reversegeocode
is a asynchronous method, you need to use a callback based solution. reversegeocode
should receive a callback method as a argument and then invoke the callback once the geocoding is completed.
$('.addButton').click(function () {
//pass a callback to reversegeocode which will get called once the geocoding is completed
reversegeocode(function (location) {
//the callback receives the location as a parameter
$.post("<?php echo $this->webroot;?>locations/add", {
location: location
})
.done(function (data) {
$("#locationsHolder").html(data);
});
});
});
function reversegeocode(callback) {
var lat = $('#lattitude').val();
var lng = $('#longitude').val();
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({
'latLng': latlng
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) { //http://stackoverflow.com/questions/8082405/parsing-address-components-in-google-maps-upon-autocomplete-select
var address_components = results[0].address_components;
var components = {};
jQuery.each(address_components, function (k, v1) {
jQuery.each(v1.types, function (k2, v2) {
components[v2] = v1.long_name
});
})
var output = '';
var needAcomma = false;
if (components.route != undefined) {
output += components.route;
needAcomma = true;
}
if (components.locality != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.locality;
needAcomma = true;
}
if (components.administrative_area_level_1 != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.administrative_area_level_1;
needAcomma = true;
} else if (components.administrative_area_level_2 != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.administrative_area_level_2;
needAcomma = true;
} else if (components.administrative_area_level_3 != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.administrative_area_level_3;
needAcomma = true;
}
$("#location").val(output);
//call the callback
callback(output);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
}
Change reversegeocode
to take a callback
parameter (also known as a continuation
).
Encapsulate all the stuff that needs to wait for reversegeocode
to finish, putting it into an in-place, nameless function.
(Note the similarity to what you're already doing for the click
handler.)
With this approach you are also free to add parameters to the callback, which you can use to pass data directly through.
$('.addButton').click(function() {
reversegeocode(function(some_data) {
var location = $("#location").val();//the value I need
//...stuff...
});
});
function reversegeocode(callback){
//...stuff...
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//...stuff...
} else {
alert('Geocoder failed due to: ' + status);
}
callback(some_data);
});
}
您需要在reversegeocode
函数中使用回调函数。
The same exact way as you do ajax :)
$('.addButton').click(function() {
reversegeocode().done(function(location) {
$.post("<?php echo $this->webroot;?>locations/add", {location:location})
.done(function (data) {
$("#locationsHolder").html(data);
});
});
})
To do this you will have reversegeocode return a jquery deferred promise
function reversegeocode() {
return $.Deferred(function(d) {
//do stuff and when it succeeds
d.resolve(location);
//or if it fails
d.reject("something went wrong");
}).promise();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.