Disable button if geolocation is unavaliable - javascript

So i've got a main page where there's 3 buttons - login, register and recover account. I want to disable all those buttons and display a message when geolocation is unavaliable or the user has not allowed the browser to share it's location.
$scope.btnDisabled = false;
$scope.errorMsg = null;
$scope.checkBrowser = function () {
if (navigator.geolocation.getCurrentPosition) {
// let's find out where you are!
console.log("Got your location");
$scope.btnDisabled = false;
} else {
$scope.errorMsg = "Warning. Could not locate your position. Please enable your GPS device.";
//disable the buttons
$scope.btnDisabled = true;
//Show errorMessage
return true
}
//errorMessage visibility is set false
return false;
}
So far i haven't managed to disable the buttons or show errorMessage(except for an alert message).
This is how i got the alert message:
function getPosition() {
console.group("geoloc getPosition");
if (window.navigator) {
console.log("api supported");
navigator.geolocation.getCurrentPosition(success, error);
} else {
console.log("api fallback");
}
console.groupEnd();
}
function success(pos) {
console.log("geoloc pos ", pos);
}
function error(err) {
alert("Geolocation identification failed.");
$scope.btnDisabled = true;
}
Why doesn't the $scope.btnDisable work in error() function?

You should use
navigator.geolocation.getCurrentPosition(
function() {
$scope.btnDisabled=false;
$scope.$apply();
}, function() {
$scope.btnDisabled=true;
$scope.$apply();
}
});
It is verry important to know, that getCurrentPosition will call a callback instead of returning something! See https://developer.mozilla.org/en-US/docs/Web/API/Geolocation.getCurrentPosition
You've also to call $scope.$apply() as you'll disable any angular updates while processing non angular callbacks!
Do so in your 2nd example and the button state should get updated

Related

Notification.requestPermission does not fire when it is automatically blocked by Chrome

So basically I have button which when clicked will trigger a call to Notification.requestPermission and depending on the users response I do some action.
The issue is that Notification.requestPermission does not actually fire when it is automatically blocked by Chrome.
This is my code
function askNotificationPermission(handler) {
// checks to see if notification is actually supported
function checkNotificationPromise() {
try {
// checks if promise based notification is okay
Notification.requestPermission().then();
} catch(e) {
return false;
}
return true;
}
// Let's check if the browser supports notifications
if (!('Notification' in window)) {
console.log("This browser does not support notifications.");
} else {
if(checkNotificationPromise()) {
window.console.log("requesting permission...")
Notification.requestPermission()
.then((permission) => {
window.console.log("PERMISSION", permission)
handler(permission);
window.console.log("finished handler")
})
window.console.log("done", Notification.permission)
} else {
Notification.requestPermission(function(permission) {
handler(permission);
});
}
}
}
Is there anyway to catch when notifications are automatically blocked?

service-worker.js catch updatefound before running other custom functions

Is there a way to check if the service worker found an update before loading custom functions?
i have this function which is working, but it runs the custom functions twice, and seems very untidy..
I'm looking for a way to only run the custom functions once, and not when an update was found and installed. When an update is found, the user || the page will reload automatically and then the custom functions can run normally..
I added the reg.events in this function to determine where to place my custom functions. I hope this question is understandable..
function installApp(path, scope) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(path, {
scope: scope
}).then((reg) => {
// event listener to catch the prompt if any and store in
// an instance for later use with add to homescreen() function.
getPrompt();
// this is a custom alert type notification
makeProgress('System','is ok');
/* THIS IS THE UPDATE FOUND FUNCTION */
reg.onupdatefound = function() {
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
// the _clear() function removes items from the locaforage db to
// force the app to not auto login, but let the user
// login again to refresh any data when the page reloads
_clear('uuid');
_clear('user');
_clear('token');
makeProgress('new version','reload app');
} else {
// removes any custom notifications
clearProgress();
//just go into the app because everything is loaded.
//We dont need to reinstall the
//homescreen or listen for the homescreen because this
//is an update and the homescreen should already be installed?
enterApp();
}
break;
case 'redundant':
// removes any custom notifications cause
//the install is complete
clearProgress();
enterApp();
console.log('The installing service worker became redundant.');
break;
}
};
return;
};
/** Here is the events that fire during the install
// process and where i am currently stuck **/
if (reg.installing) {
makeProgress('updating','files');
/* THE SERVICE WORKER IS DOWNLOADING THE CACHE FROM THE SERVER */
} else if (reg.waiting) {
/* what message here ?*/
/* as far as i can tell, THE SERVICE WORKER IS WAITING FOR
*//*PREVIOUS SERVICE WORKER TO BEREFRESHED SO A RELOAD */
/*UI SHOULD COME HERE??*/
} else if (reg.active) {
/* what message here ?*/
/* IS THIS THE BEST PLACE TO RUN THE BELOW CUSTOM
*//*FUNCTIONS?? WILL //THEY ALWAYS FIRE */
}
/** AT WHICH OF THE EVENTS ABOVE WILL I ADD THE FUNCTIONS FROM HERE **/
requestWakeLock();
const browserFeatures = detectFeatures(reg);
setCompatibilityArray(browserFeatures);
localforage.ready().then(function() {
localforage.getItem('homescreen').then(function (value) {
if(value != 1){
if (platform == 'iPhone' || platform == 'iPad') {
installHome();
} else {
makeProgress('waiting', 'prompt');
waitPrompt();
}
return;
} else {
enterApp();
return;
}
}).catch(function (err) {
alertIt('something went wrong. Please refresh the page to try again. If the problem persists, try another browser.</br>', 'warning', 0);
return;
});
}).catch(function (err) {
alertIt('Something went wrong.<br>Please refresh the page to restart the installation process.<br>'+err, 'danger', 0);
return;
});
/** TO HERE, WITHOUT RUNNING THESE FUNCTION DURING*/
/*THE ONUPDATEFOUND EVENT AS THEN THEY WILL RUN TWICE**/
}, (err) => {
alertIt('Something went wrong.<br>Please refresh the page to restart the installation process.<br>', 'danger', 0);
})
} else {
alertIt('This browser is not compatible with this app.<br>Please try to use a different browser to install this application.<br>', 'danger', 0);
return;
}
}
I initialize this script like so:
window.addEventListener("load", () => {
makeProgress('Checking','system');
installApp(appsPath, appScope);
})
basically they must not be invoked if a new update is found..
I discovered that the onupdate function runs when old service worker is active..
If the onupdate function fires it changes a variable to a true value
I then used a time out function in the active event to see if a variable had changed... if it did change then i return false, and let the onupdate functions continue their course.. otherwise i continue to load my custom functions...Its working, but it doesn't seem like the best way.
Do you have a better method?
so like this:
function installApp(path, scope) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(path, {
scope: scope
}).then((reg) => {
getPrompt();
makeProgress('refreshing','files');
var entApp = true;
reg.onupdatefound = function() {
entApp = false;
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
_clear('uuid');
_clear('user');
_clear('token');
makeProgress('new version','reloading app');
setTimeout(function(){
location.reload();
}, 2500);
return;
} else {
/*NOT SURE WHAT IS SUPPOSED TO GO HERE, SO I JUST RELOADED THE PAGE*/
makeProgress('new version','reloading app');
setTimeout(function(){
location.reload();
}, 2500);
return;
}
break;
case 'redundant':
/*NOT SURE WHAT IS SUPPOSED TO GO HERE, SO I JUST RELOADED THE PAGE*/
makeProgress('new version','reloading app');
setTimeout(function(){
location.reload();
}, 2500);
return;
break;
}
};
return;
};
if (reg.active) {
/** RIGHT HERE IS WHERE THE ONUPDATE FIRES. I GAVE IT A
2.5 SECONDS TO DO ITS THING, THEN CHECKED TO SEE IF THERE WAS
AN UPDATE, IF NO UPDATE THEN I RUN MY CUSTOM FUNCTIONS, OTHERWISE
THE ONUPDATE FUNCTION RELOADS THE PAGE AND THE UPDATED SW.JS FILE
WILL THEN RUN THESE FUNCTIONS WHEN ITS ACTIVE.. IS THERE A BETTER
IN-BUILT METHOD TO DO THIS?**/
setTimeout(function(){
if(entApp === true){
requestWakeLock();
const browserFeatures = detectFeatures(reg);
setCompatibilityArray(browserFeatures);
localforage.ready().then(function() {
localforage.getItem('homescreen').then(function (value) {
if(value != 1){
if (platform == 'iPhone' || platform == 'iPad') {
installHome();
} else {
makeProgress('waiting', 'prompt');
waitPrompt();
}
return;
} else {
enterApp();
return;
}
}).catch(function (err) {
alertIt('something went wrong. Please refresh the page to try again. If the problem persists, try another browser.</br>', 'warning', 0);
return;
});
}).catch(function (err) {
alertIt('Something went wrong.<br>Please refresh the page to restart the installation process.<br>'+err, 'danger', 0);
return;
});
}
}, 2500);
}

Catch html5 geolocation events

Is there a way to catch the html5 geolocation events?
Right now im using geolocator.js
and my problem is:
When the message pops up if i want to allow html5 locations if i accept it takes html5 location if I get ipLocation.
But I want to listen for these clicks so I can set a timeout if the user doesn't click for 10 seconds it automatically takes ip location.
Is there any way to get the event for "accept" and "decline"? Here is my code snippet for it
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, html5Options);
} else { // not supported
fallback(new Error('geolocation is not supported.'));
}
EDIT: Im using Chrome on iMac
EDIT 2:
var html5Options = { enableHighAccuracy: true,timeout: 10000, maximumAge: 0 };
EDIT 3: using the solution by kravitz
if (navigator.geolocation) {
waitTooLong=setTimeout(geoError, 15000);
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, html5Options);
} else { // not supported
fallback(new Error('geolocation is not supported.'));
}
function geoSuccess(position) {
clearTimeout(waitTooLong);
//doing my locationstuff
}
function geoError(error) {
//doing my locationstuff
clearTimeout(waitTooLong);
fallback(error);
}
var geoError = function(){
//get location failed so get manually by IP here
};
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, html5Options);
} else { // not supported
fallback(new Error('geolocation is not supported.'));
}
Above should work but if you want to be really sure:
var timeOut = setTimeout(geoError, 10000);
var geoSuccess = function(){
clearTimeout(timeOut);
};

Angular: When does app.config get called?

I am creating a chrome extension UI using angular. I want to make it so when the user clicks the icon in the upper right the correct screen appears. If the user is not logged in they should go to the login page. If the user is logged in and in drawing mode then they should go to the drawing screen, if they are logged in and not drawing then they should go to the main menu.
My main problem is checking whether or not they are already in drawing mode. I am sending a message to my content scripts to check whether or not I am in drawing mode, but for some reason this callback is never getting called! Very disappointing. I'm not sure when code in app.config gets called; when does it?
app.js
app.config(function($stateProvider, $urlRouterProvider) {
var rootRef = new Firebase(mysterious_url);
var user = rootRef.getAuth();
chrome.tabs.sendMessage('isInDrawingMode', {action: 'isInDrawingMode'}, function(response) {
if (!user) {
$urlRouterProvider.otherwise('/login');
} else if (response.inDrawingMode) {
$urlRouterProvider.otherwise('/draw');
} else {
$urlRouterProvider.otherwise('/main');
}
});
contentscripts.js
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse){
// Toggle User Canvas Messages
if ( request.toggle === 'off' ){
// toggleUserCanvasOff();
disableDrawingMode();
sendResponse({confirm:'canvas turned off'});
} else if ( request.toggle === 'on' ){
enableDrawingMode();
// toggleUserCanvasOn();
sendResponse({confirm:'canvas turned on'});
// Initialize toggle status for popup button
} else if ( request.getStatus === true ){
sendResponse({status:toggle});
} else if (request.canvasData) { // new Canvas data
onCanvasData(request.site, request.user, request.data);
} else if (request.erase){
eraseUserCanvas();
} else if (request.changeColor){
lineColor = request.changeColor;
} else if (request.image){
getCurrentUser(function(user){
var userCanvas = $('.'+ user);
addOneTimeClickEvent(userCanvas, addImage, request.image);
});
} else if (request.action) {
sendResponse({inDrawingMode: "true"});
}
}
);

perform default action of a link inside of callback

I have a link to login with facebook on my page and I want to manipulate the way the onclick works. Currently I have changed it so that it does not do the default action by adding return false to the end:
$('#login').on('click', function(e) {
FB.login(function(response) {
//window.easyUserData.login = response;
if (response.authResponse) {
console.log('authorised');
return true;
} else {
// cancelled
}
});
return false;
});
What was happening was that right after it called FB.login to open the dialog it would redirect the page, not what I wanted. What i am looking for is for it to do the default action of the link where i put return true. The return true bit doesn't work because by the time it gets there, return false has already been processed. Any tips on how to do this?
The link has href="#/home" and I am using backbone.js to handle routing.
Due to asynchronous nature of your login function you would have to use a javscript redirect:
$('#login').on('click', function(e) {
var href=this.href;
FB.login(function(response) {
//window.easyUserData.login = response;
if (response.authResponse) {
console.log('authorised');
/* redirect here*/
window.location=href;
} else {
// cancelled
}
});
return false;
});

Categories