J'ai donc ce code javascript. Dans les safari et chrome, si l'utilisateur refuse de partager l'emplacement, il échouera comme il se doit; Cependant, dans Firefox, ce n'est pas le cas.
Toute aide appréciée.
function initGeolocation()
{
if( navigator.geolocation )
{
// Call getCurrentPosition with success and failure callbacks
navigator.geolocation.getCurrentPosition( success, fail );
}
else
{
alert("Sorry, your browser does not support geolocation services.");
}
}
var map;
function success(position)
{
var longIDText = document.getElementById('longID');
var latIDText = document.getElementById('latID');
longIDText.value = position.coords.longitude;
latIDText.value = position.coords.latitude;
document.getElementById('coordSubmitID').click();
}
function fail(error)
{
alert("FAAAAAAAAAAIIIIIIIIIL")
var Zip_code ;
while (true){
// Could not obtain location
Zip_code = Prompt("Please enter your current address or Zip code","");
if ( Zip_code == "" ) {
alert(Zip_code +" is not a valid address. Please try again.");
}
else{
break;
}
}
var zipIDText = document.getElementById('zipID');
zipIDText.value = Zip_code;
document.getElementById('coordSubmitID').click();
}
Pour Firefox, il semble quePERMISSION_DENIED
est levé seulement si "Jamais partager" est sélectionné; si la boîte de dialogue est fermée ou si l'option "Pas maintenant" est sélectionnée, rien ne se passe effectivement, même sur démo de la géolocalisation de Mozilla si vous ignorez l'interface utilisateur des autorisations, rien ne se produit.
Cela signifie que getCurrentPosition
peut renvoyer, soit parce que l'utilisateur a fermé l'interface utilisateur de confirmation, soit parce qu'il a démarré la demande asynchrone avec succès - il ne semble pas y avoir de moyen de distinguer les deux.
C'est une vraie douleur, et une fonctionnalité certainement pas souhaitable.
La solution de contournement que j'utilise pour économiser l'utilisateur en attente consiste à définir un délai d'expiration pour vérifier si le compteur d'attente s'affiche au bout de 3 secondes et, le cas échéant, masquez-le et affichez une entrée manuelle du code postal:
var latlng;
var waitTime = 3000;
try {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
success(position);
}, showError);
} else {
showError("NOT-SUPPORTED");
}
var t = setTimeout(function () {
if ($("#getZip div.loading").css("display") != "none") {
$("#getZip div.loading").hide();
$("#errorZip").show();
}
}, waitTime);
} catch (evt) {
alert(evt);
}
Comme l'a souligné alexleonard, la seule solution fiable multi-navigateurs que j'ai trouvée consiste à avoir un setTimeout()
pour vérifier l'état de votre objet/variables latLng
, car l'option timeout
de getCurrentPosition()
ne semble pas fonctionner de manière fiable. L'exemple ci-dessous a été testé dans IE11, Chrome33 et Firefox28.
Pour une solution plus complète qui utilise une promesse jQuery, consultez mon résumé ici: https://Gist.github.com/GFoley83/10092929
Exemple - Appuyez sur F12, collez-le dans la console et exécutez
var latLng,
geoOptions = {
enableHighAccuracy: false,
timeout: 5000, // Wait 5 seconds
maximumAge: 300000 // Valid for 5 minutes
};
var userLocationFound = function(position){
latLng = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
window.console.log("User confirmed! Location found: " + latLng.lat + ", " + latLng .lng);
}
var userLocationNotFound = function(){
latLng = {
lat: -41.29247, // fallback lat
lng: 174.7732 // fallback lng
};
window.console.log("Fallback set: ", latLng);
}
window.navigator.geolocation.getCurrentPosition(userLocationFound, userLocationNotFound, geoOptions);
setTimeout(function () {
if(!latLng){
window.console.log("No confirmation from user, using fallback");
userLocationNotFound();
}else{
window.console.log("Location was set");
}
}, geoOptions.timeout + 1000); // Wait extra second
Notez que c'est également un problème dans Chrome.
Dans Chrome, un avis apparaît "Le site souhaite connaître votre position" - il propose ensuite les options "Autoriser" et "Refuser". Avec la conception de l'interface utilisateur, l'utilisateur est plus susceptible de choisir Autoriser ou Refuser, ce qui renverra ensuite une réponse à la fonction navigator.geolocation.getCurrentPosition. Toutefois, l'utilisateur peut également cliquer sur un "X" à l'extrême droite de la note d'information. Cela revient essentiellement à cliquer sur "Pas maintenant" dans Firefox.
Aucun résultat n'est renvoyé à la fonction.
Il semble qu'un minuteur doit être implémenté pour permettre ce résultat possible.
Ceci est conforme à la conception et n'est apparemment pas un problème. Voir https://bugzilla.mozilla.org/show_bug.cgi?id=675533
Il appartient aux développeurs utilisant cette fonctionnalité d’élaborer une solution de contournement spécifique à un navigateur pour Firefox.
Il est à noter que, d'après le commentaire du développeur FF sur l'utilisation réelle de la géolocalisation par les utilisateurs finaux, les développeurs de Firefox collectent apparemment des données détaillées sur les activités des utilisateurs finaux avec leurs produits.
Utilisez une promesse. J'utilise angularjs qui a sa propre version de $ q pour résoudre le même problème que nous avons tous.
$scope.ByUserPosition = function () {
//http://www.w3.org/TR/geolocation-API/
var deferred = $q.defer();
deferred.promise.then(findByPosition, function (data) {
console.log('error', data);
});
var resolveBy = 1000 * 30;
navigator.geolocation.getCurrentPosition(function (position) {
deferred.resolve({ latitude: position.coords.latitude, longitude: position.coords.longitude });
}, function (err) {
deferred.reject(err);
}, {
enableHighAccuracy: true,
timeout: resolveBy,
maximumAge: 0
});
$timeout(function() {
deferred.reject('timed out');
}, resolveBy)
};
La seule solution à ce problème est la suivante:
J'espère que ça aide :)
Modifier (après un vote négatif) 6-11-2013
Comme indiqué ci-dessous, cette réponse ne résout pas le problème lorsqu'un utilisateur refuse l'accès à la localisation. Pour le downvote est correct. Je garde la réponse ici, parce que le délai d'attente est très important, il faut l'utiliser de toute façon, et je ne le vois pas dans aucune réponse.
La fonction navigator.geolocation.getCurrentPosition () a la possibilité d’envoyer le timeout avec elle:
navigator.geolocation.getCurrentPosition(
function (position){
//do someting with position
},
function (error){
// do something with the error (like the code)
},
{timeout:10000}
);
et d'autres options, telles que l'âge de la position mise en cache (maximumAge) . le délai d'attente et la valeur maximale sont exprimés en millisecondes, donc 10000 = 10 secondes.
Soit dit en passant, le délai d’expiration par défaut est infini ... donc, si vous ne le définissez pas, il n’appellera jamais le rappel pour les erreurs ....
donc dans l'option comme Jamie a répondu, je dirais:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
success(position);
}, showError, {timeout:3000});
}
Voici une solution à mon problème avec Vanilla es6 Promises
. Inspiré par la réponse de @LeblancMeneses.
if(navigator.geolocation) {
let promise = new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(
(position) => {
resolve(position)
},
(error) => {
resolve(error)
}
)
window.setTimeout(() => {
resolve({})
}, 8000)
})
promise.then((result) => {
// do something with result
})
} else {
console.log('no geolocation available')
}