I want to fetch live gps location using javscript to store it in database. I already have implemented it. when user clicks on button. But it fetches location on second click.
Html code
<form action="user_location" method="post" id="form-{{$user->id}}">
#csrf
<input type="hidden" name="id" value="{{$user->id}}">
<input type="hidden" name="location" id="location-{{$user->id}}">
</form>
<a onclick="getLocation({{$user->id}})" class="btn">{{__('Get Location')}}</a>
Javscript code
function getLocation(user_id) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
geolocation = "Geolocation is not supported by this browser.";
}
if(setlocation){
form = document.getElementById("form-"+user_id);
var b = document.getElementById("location-"+user_id)
b.value = x.textContent;
form.submit();
}
}
function showPosition(position) {
x.innerText = position.coords.latitude + "-" + position.coords.longitude;
setlocation = true;
}
The getCurrentPosition function is asynchronous. That means that when it is called, it will allow the code after it to run before finishing. So that means that setLocation will not be true whenever your code reaches the following if statement:
if(setlocation){ // setlocation is still false
Handle your results of getting the position inside the success callback of getCurrentPosition.
function getLocation(user_id) {
if (!navigator.geolocation) {
return;
}
const form = document.getElementById("form-" + user_id);
const location = document.getElementById("location-" + user_id);
navigator.geolocation.getCurrentPosition(function(position) {
const { coords } = position;
location.value = coords.latitude + "-" + coords.longitude;
form.submit();
});
}
Related
I have a button that users can click to use their location to find places nearby. How can I write the if/else statements to prompt the user to allow access to their location, wait for a response, then either submit the form or cancel out if they deny it?
<button id="submit_latlng" class="btn btn-secondary my-2 my-sm-0" type="submit">Use Current Location</button>
$('#submit_latlng').click(function() {
getLocation(),
$('#geo-loc-form').submit()
})
function getLocation(){
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
getPosition,
positionError
)
}
function getPosition(position) {
document.getElementById('user_lat').value = position.coords.latitude;
document.getElementById('user_lng').value = position.coords.longitude;
}
function positionError(error) {
if (error.PERMISSION_DENIED) alert('Location services are off. Please enable location services, or use zip code search.');
showError('Geolocation is not enabled.');
}
};
This is the code I use. The user will be prompted by its web browser like this:
The first block is what you do if the user grants permission, and the second block function(error) is what you do if the user denies permission.
function getCoordinates()
{
navigator.geolocation.getCurrentPosition(function(location) {
var lat = location.coords.latitude;
var lng = location.coords.longitude;
console.log("Location permission granted");
console.log("lat: " + lat + " - lng: " + lng);
},
function(error) {
console.log("Location permission denied");
});
}
I got it working with the following:
$('#submit_latlng').click(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
getPosition,
positionError
)
}
function getPosition(position) {
document.getElementById('user_lat').value = position.coords.latitude;
document.getElementById('user_lng').value = position.coords.longitude;
$('#geo-loc-form').submit();
}
function positionError(error) {
if (error.PERMISSION_DENIED) alert('Location services are off. Please enable location services, or use zip code search.');
showError('Geolocation is not enabled.');
}
});
For my onsubmit function, I have a function that requests for user's location and adds their location to the input values of my form.
However, when the user clicks on the submit button and a pop-up appears and asks the user to allow the browser to know their location, my form always submits before the user could answer the pop-up. This leaves the function incompleted and the input values become undefined.
I have tried adding a "return true;" statement until my onsubmit function ends, but the form still gets submitted prior. I have also tried adding "e.preventDefault();" before my function completes. None of the methods worked so far...
My form:
<form action="/login" onsubmit="getLocation()" method="POST">
<button type="submit" class="btn btn-dark">Login</button>
<input id="currentUserLattitude" type=hidden name="currentLocation" value="placeholder">
<input id="currentUserLongitude" type=hidden name="currentLocation" value="placeholder">
</form>
The onsubmit function:
function getLocation(e) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError);
return true;
} else {
alert("Geolocation is not supported by this browser.");
}
}
function onGeoSuccess(position) {
document.getElementById("currentUserLattitude").value = position.coords.latitude;
document.getElementById("currentUserLongitude").value = position.coords.longitude;
}
function onGeoError(err) {
alert("Error code " + err.code + ". " + err.message);
}
Use an id and event listener, prevent default on submit, wrap your function in a promise, and only submit if the result is true:
function getLocation(e) {
// Create new promise
return new Promise(resolve => {
if (navigator.geolocation) {
// Since getCurrentPosition is asynchronous, resolve in the onsuccess callback.
navigator.geolocation.getCurrentPosition(
position => {
onGeoSuccess(position);
// Resolving here will return back to the .then()
resolve();
},
error => {
onGeoError(error);
resolve();
}
);
} else {
alert("Geolocation is not supported by this browser.");
// Return to the .then()
resolve();
}
});
}
function onGeoSuccess(position) {
document.getElementById("currentUserLattitude").value =
position.coords.latitude;
document.getElementById("currentUserLongitude").value =
position.coords.longitude;
}
function onGeoError(err) {
alert("Error code " + err.code + ". " + err.message);
}
document.getElementById("form").addEventListener("submit", e => {
// Prevent submission
e.preventDefault();
// Call your function and wait for a response
getLocation().then(() => {
// Submit the form
return e.target.submit();
});
});
<form id="form" action="/login" onsubmit="getLocation()" method="POST">
<button type="submit" class="btn btn-dark">Login</button>
<input id="currentUserLattitude" type=hidden name="currentLocation" value="placeholder">
<input id="currentUserLongitude" type=hidden name="currentLocation" value="placeholder">
</form>
First, you should ask permission on page load:
<body onload="getLocation()">
Second, you should use a flag (variable) to track the status of the Geo location success. And finally if there was no error the form is ready for submit.
var anErrorOccured = true;
function getLocation ()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition (onGeoSuccess);
}
}
function onGeoSuccess(position)
{
document.getElementById("currentUserLattitude").value = position.coords.latitude;
document.getElementById("currentUserLongitude").value = position.coords.longitude;
anErrorOccured = false;
}
function submitData ()
{
if (anErrorOccured)
{
return false;
}
else
{
return true;
}
}
Basically the anErrorOccured variable is set to true and only if the position is set successfully you will mark it as false.
And don't forgot to use 'return' when attaching some function to onsubmit event:
<form action="/login" onsubmit="return submitData()" method="POST">
You can also disable your submit button based on this flag, to be more user friendly.
Change from using an onSubmit to onComplete
Have a small javascript piece of code which calls navigator.geolocation.
I have an if statement, which works, to show the latitude and longitude if the user the user allows the call. However, the else section is not running.
If I run the code below I get prompted by the browser to allow; if I allow it then coordinates are shown. However, if I hit block instead nothing happens even though there is an else section.
<body>
<br> <p id="ChangeSring">Test</p>
<script>
var x = document.getElementById("ChangeSring");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(SavePosition);
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
document.cookie = 'location=false;path=/form_handler';
}
function SavePosition(position) {
x.innerHTML = "Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
document.cookie = 'location=true;path=/form_handler';
document.cookie = 'latitude='+ position.coords.latitude +';path=/form_handler';
document.cookie = 'longitude='+ position.coords.longitude +';path=/form_handler';
}
</script>
<form action="/form_handler" _lpchecked="1">
Enter value:
<input type="text" name="SomeVar"><br>
<input type="submit" value="search">
</form>
</body>
You cannot use else to check for permissions.
The navigator method getCurrentPosition takes a success and error callbacks.
The error callback will be called if permission is denied.
if (navigator.geolocation) { // this checks if navigator is supported at all
navigator.geolocation.getCurrentPosition(console.log, () => {
console.log('Permission denied')
});
} else {
console.log('Geolocation is not supported by this browser.');
}
getCurrentPosition takes a success and an error function.
Ref: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition#Example
function errorGettingPosition(positionError) {
x.innerHTML = "Geolocation is not supported by this browser.";
document.cookie = 'location=false;path=/form_handler';
}
navigator.geolocation.getCurrentPosition(SavePosition, errorGettingPosition)
That if-else statement is checking if navigator.geolocation it's not undefined(and it's not even if you don't want the browser to know your location) follow the other answers to properly handle permission
I'm calling the HTML geolocation method to get latitude and longitude and then storing them into 2 separate HiddenFields. These values from the HiddenFields will then be used in the server side (code behind) which will be stored in a table in my database. I searched high and low over stackoverflow to get help for empty values in HiddenFields, saving latitude and longitude into database, client and server side button click, etc.
I'm actually firing this javascript method based on a button, or do you think it's better to be fired window.onload?
I suspect that the functions aren't fired as well.. I have little knowledge on javascript.. Appreciate any help..
Javascript codes and HiddenFields in my WebForm:
<asp:HiddenField runat="server" ClientIDMode="Static" ID="latitudeTB"/>
<asp:HiddenField runat="server" ClientIDMode="Static" ID="longitudeTB"/>
<script type="text/javascript">
function HideLabel() {
var seconds = 3;
setTimeout(function () {
document.getElementById("<%=ErrorPanel.ClientID %>").style.display = "none";
}, seconds * 1000);
};
//GeoLocation Retrieval
var latJS = 0;
var lngJS = 0;
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
}
function showPosition(position) {
//position.coords.latitude + "," + position.coords.longitude;
//var lat = document.getElementById("<%=latitudeTB.ClientID %>");
latJS = position.coords.latitude;
lngJS = position.coords.longitude;
document.getElementById("<%= latitudeTB.ClientID %>").value = latJS;
document.getElementById("<%= longitudeTB.ClientID %>").value = lngJS;
alert(document.getElementById("<%= latitudeTB.ClientID %>").value + " " + document.getElementById("<%= longitudeTB.ClientID %>").value);
/*if (lat) {
lat.value = position.coords.latitude;
}*/
//var long = document.getElementById("<%=longitudeTB.ClientID %>");
/*if (long) {
long.value = position.coords.longitude;
}*/
}
function call() {
getLocation();
showPosition(position);
}
</script>
FYI. The button is placed above the HiddenFields and Javascript..
Codes for asp:Button:
<asp:Button ID="BTN_Login" CssClass="btn btn-theme-dark" Text="Login" runat="server" OnClientClick="call();" OnClick="BTN_Login_Click" />
I did actually print out the values of the hiddenfields on server side but i'm getting no values at all..
Debug.WriteLine(latitudeTB.Value);
Debug.WriteLine(longitudeTB.Value);
I hope that the code i added is sufficient..
Setting this on button click event or on window load event boils down to what you what the user experience to be.
Most websites tend to show the geolocation prompt when the DOM is ready.
You need to tweak your getLocation function. getCurrentPosition takes success and error callbacks, both of which are not being passed.
function getLocation(opts) {
return new Promise(function(resolve, reject) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition( resolve,
reject,
opts
);
}
else {
reject(new ReferenceError('Browser does not support geolocation api'));
}
});
}
You can then use it this way:
function setLatLong(latId, longId) {
getLocation()
.then(function(pos) {
var coords = pos.coords;
document.getElementById(latId).value = coords.latitude;
document.getElementById(longId).value = coords.longitude;
})
.catch(function(err) {
// log or fall back to come other Location API?
})
}
function call() {
setLatLong(
"<%= latitudeTB.ClientID %>",
"<%= longitudeTB.ClientID %>");
}
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition
I have been fiddling with Leaflet and different maps lately. I am currently trying to have the markers that are created by onClick events to show the current address that is parsed from a JSON query supplied by an API.
I am successfully parsing the address from the JSON query (console log in onMapClick(e)'s getAddress). What I want to do however is to return this value from the callbacked(?) function and make it visible as the marker's content.
function getAddress(lat, lon, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.digitransit.fi/geocoding/v1/reverse?point.lat=' + lat + '&point.lon=' + lon + '&size=1', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (typeof callback == "function") {
callback.apply(xhr);
}
}
}
xhr.send();
}
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("Address is " +
getAddress(e.latlng.lat, e.latlng.lng, function() {
var resp = JSON.parse(this.responseText);
console.log(resp.features[0].properties.label); //This gives the correct current address in console
return resp.features[0].properties.label; //This SHOULD return the correct address, verified with the console log, and replace the function call in the marker's content window, however the address appears always as undefined.
}))
.openOn(map);
}
Change the order of execution, so that you only use the value when you actually have it returned asynchronously from the API:
function onMapClick(e) {
getAddress(e.latlng.lat, e.latlng.lng, function() {
var resp = JSON.parse(this.responseText);
popup
.setLatLng(e.latlng)
.setContent("Address is " + resp.features[0].properties.label)
.openOn(map);
});
}