Firebase.auth.currentUser not available on load of page but available after a few seconds - javascript

My problem is that on load of my page, I need to access the information firebase.auth.currentUser, but this information is undefined if I call my function in the eventListener('load). But if I call it on click on a button, here the "add" button, (so a few seconds after page loaded), then it is working.
Here is what I tried in my code.
var FIREBASE_AUTH;
var FIREBASE_DATABASE;
const addButton = document.getElementById("add");
addButton.addEventListener("click", getEtablissemennts);
window.addEventListener('load', (event) => {
FIREBASE_AUTH = firebase.auth();
FIREBASE_DATABASE = firebase.database();
getEtablissemennts();
});
function getEtablissemennts(){
//works only if function is call on click on the button, doesn't work on load of the page
FIREBASE_DATABASE.ref('users').orderByChild('email').equalTo(FIREBASE_AUTH.currentUser.email).once("value", function(snapshot) {
...
}
}

You can't expect Firebase to authenticate the user and get their data on load. You should set up a listener:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is available now
} else {
// No user is signed in.
}
});
Source: https://firebase.google.com/docs/auth/web/manage-users#get_the_currently_signed-in_user

Related

document.getElementById returns a null value, but only when executed within a multiline script. Returns correct element when executed by itself

I am creating a script to automate a data entry process on a server monitoring website. The site does not have an API for this specific data entry type, so I am using JavaScript to automate the mouse clicking and data entry process.
The script returns the correct document.getElementById("") value for getElement statement. However, it only returns the correct value whenever I manually execute line of individually. If I run the entire script, then the code breaks on one single line.
`var namesAndAddresses = { 'DomainName': 'IP' };
//Function to press sidebar "add device button"
function MenuFunction() {
MenuId = document.getElementById("menurow_Add/Import Devices").firstChild.nextElementSibling;
MenuId.click()
}
//Function to press "add device manually button"
function AddDeviceFunction() {
AddDeviceButton = document.getElementById("addDeviceButtonId_label");
AddDeviceButton.click();
}
//Function to add device information and then press the save button
function AddDeviceInformationFunction(domain, address) {
FQDN = document.getElementById("deviceNameId").value =
domain; //FQDN;
deviceClass = document.getElementById("deviceClassId").value =
"Switch/Router";
OS = document.getElementById("deviceOsId").value =
"Other Operating System";
ipAddress = document.getElementById("customUriId").value =
address; //DictionaryID;
licenseMode = document.getElementById("licenseModeId").value =
"Professional Mode";
saveButton = document.getElementById("cancelButtonId"); //change to save button
saveButton.click();
}
//manually wait function
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
//For loop to add each domain and ip that is listed in the dictionary
for (var [domainName, IP] of Object.entries(namesAndAddresses)) {
window.self = document;
//Function to press sidebar "add device button"
MenuFunction();
//Insert wait for sub-page to load here
pause(3000);
//Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
AddDeviceFunction();
//Insert wait for objects to load here
pause(5000);
//Function to add device information and then press the save button
AddDeviceInformationFunction(domainName, IP);
//Insert wait for objects to load here
pause(5000);
};`
HTML code is below:
enter image description here
I have tried adding in a manual "wait" because window.onload does not work due to all the HTML being loaded already. I also tried adding a try/catch statement within a loop, so that it could make the attempt 10 times over a period of 10 seconds. That didn't work either.
Your code's pause function is blocking.
What this means is that since it "waits" using a while loop, it is not actually waiting but doing a lot of useless work, using up 100% of the CPU, and preventing anything else from actually loading.
Because of this, I can only presume the elements that are supposed to appear when loading do not get a chance to, meaning getElementById returns null (they do not exist yet)
Consider using something like setTimeout, which will properly wait, without preventing other work from being done.
Replace your for loop near the end with
var entries = Object.entries(namesAndAddresses)
window.self = document;
function processEntry(){
if(!entries.length){
// Done
return
}
// Get (and remove) the first element in the array
var [domainName, IP] = entries.shift()
//Function to press sidebar "add device button"
MenuFunction();
//Wait for sub-page to load using setTimeout, which will run this code after 3000ms
setTimeout(function(){
//Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
AddDeviceFunction();
//Wait for objects to load here
setTimeout(function(){
//Function to add device information and then press the save button
AddDeviceInformationFunction(domainName, IP);
//Insert wait for objects to load here
setTimeout(function(){
// Done, go to next entry
processEntry();
}, 5000);
}, 5000);
}, 3000);
};
processEntry()
I would also recommend looking into promises and async/await, which can make this code look much neater:
function pause(milliseconds) {
return new Promise(function(finish){
setTimeout(finish, milliseconds)
})
}
async function processAllEntries(){
//For loop to add each domain and ip that is listed in the dictionary
for (var [domainName, IP] of Object.entries(namesAndAddresses)) {
window.self = document;
//Function to press sidebar "add device button"
MenuFunction();
//Insert wait for sub-page to load here
await pause(3000);
//Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
AddDeviceFunction();
//Insert wait for objects to load here
await pause(5000);
//Function to add device information and then press the save button
AddDeviceInformationFunction(domainName, IP);
//Insert wait for objects to load here
await pause(5000);
}
}
Your pause causes the UI not to be able to render. You can make a function that uses await to look for an element. As soon as it is available it will update.
function addElem() {
const div = document.createElement('div');
div.className = 'foo';
div.textContent = 'hello';
document.body.append(div);
}
const waitForElem = (selector) => new Promise((resolve, reject) => {
const check = () => {
const elem = document.querySelector(selector);
if (elem) {
resolve(elem);
} else {
window.setTimeout(check, 1);
}
};
check();
});
window.setTimeout(addElem, 5000);
(async function() {
const el1 = await waitForElem('#bar');
el1.textContent = 'found 1';
const el2 = await waitForElem('.foo');
el2.textContent = 'found 2';
})();
<div id="bar">Test</div>

execute js function after reloading page [duplicate]

I'm trying to refresh a page and then run a function once the refresh has been completed. However the code I have now, runs the function and then it only refreshes it, meaning I lose what the function did. Is there a way to solve this?
My code
function reloadP(){
document.location.reload();
myFunction();
}
<button onclick: "reloadP()">Click</button>
You need to call myFunction() when the page is loaded.
window.onload = myFunction;
If you only want to run it when the page is reloaded, not when it's loaded for the first time, you could use sessionStorage to pass this information.
window.onload = function() {
var reloading = sessionStorage.getItem("reloading");
if (reloading) {
sessionStorage.removeItem("reloading");
myFunction();
}
}
function reloadP() {
sessionStorage.setItem("reloading", "true");
document.location.reload();
}
DEMO
function myFunction() {
document.getElementById("welcome").textContent = "Welcome back!";
}
window.onload = function() {
var reloading = sessionStorage.getItem("reloading");
if (reloading) {
sessionStorage.removeItem("reloading");
myFunction();
}
}
function reloadP() {
sessionStorage.setItem("reloading", "true");
document.location.reload();
}
DEMO: https://jsfiddle.net/barmar/5sL3hd74/
Adding to #Barmar answer... In case you'd like to use session storage only when a button in the page is clicked and not when reloading with the browser button, you can use sessionStorage.clear() or sessionStorage.removeItem() once you've executed the function after loading the window.
So, let's say we have:
let restart = sessionStorage.getItem("restart")
Set restart boolean to true as a session storage and reload:
resetBtn.addEventListener("click", () => {
sessionStorage.setItem("restart", "true")
location.reload()
})
Once the window is reloaded we can execute the following function:
window.onload = () => {
if(restart){
// Do something
sessionStorage.clear() // This cleans all the session storage
// If you want to remove ONLY the item from the storage use:
// sessionStorage.removeItem("restart")
}
};
So, if now the user reloads the page with the browser button it will reload with the session storage cleaned. Meaning, no functions will be executed after window load.
In my case i used Barmar's solution. I have a modal popup form, i want to submit the form then automatically refresh the page and finally success message on reloaded page.
var form = document.getElementById('EditUserInfosForm')
form.addEventListener('submit', function () {
sessionStorage.setItem("reloading", "true");
document.location.reload();
})
window.onload = function () {
var reloading = sessionStorage.getItem("reloading");
if (reloading) {
sessionStorage.removeItem("reloading");
$('#success-message-modal').modal('show')
}
}
Probably simplest approach.
HTML Button
Reload button (credits):
<!-- index.html -->
<button onClick="window.location.reload();">Refresh Page</button>
JS Code
Run your code after reload:
// index.js
window.addEventListener("load", (event) => {
YourFunction(); // already declared somewhere else
});
You may not use event variable at all.
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event#examples

How can i execute a function after a form submission causes a page refresh?

I am using shopify's built in customer create, login, reset form submissions which on submit, forces the page to refresh. My intention is to show a message that shows after the page has been refreshed via a button click function. This is what i have so far; The message shows until that page refreshes and then the active class is removed as you would expect.
$(document).ready(function () {
class Alert {
constructor() {
this.customerAlert = document.createElement('div');
}
init(){
this.customerAlert.classList.add('customer-alert');
document.querySelector('body').append(this.customerAlert);
}
show(message){
this.customerAlert.textContent = message;
this.customerAlert.classList.add('active');
setTimeout(() => {
this.customerAlert.classList.remove('active');
}, 8000);
}
}
//create snackbar and initiate
const alertMessage = new Alert();
alertMessage.init();
const createAccountButton = document.querySelector('input.account-trigger');
createAccountButton.addEventListener('click', () => {
alertMessage.show('Your account in now under review');
});
});
Set a boolean variable in session storage just prior to the submit to represent the two states, and then read it in after the refresh.
Something like this:
function HandleFlag(){
var F=sessionStorage.getItem('Flag');
if(F=='1'){
// display your message box here
sessionStorage.setItem('Flag','0');
} else {
// the state is "0" so toggle it just before submitting
sessionStorage.setItem('Flag','1');
}
}
I hope you get my drift.

beforeinstallprompt triggers on every load

Beforeinstallprompt triggers on every load.
I have used the code here: https://developers.google.com/web/fundamentals/app-install-banners/
I am not using the The mini-info bar which i have dissabled by calling e.preventDefault();
The problem is that the showAddToHomeScreen(); is called on every load if the user does not click addToHomeScreen.
I want the showAddToHomeScreen(); function to be called only every month or so by storing information about the last "canceled" click in sessions or something similar. Isn't google suppose to do this on it's own?
This i found on the following link:
https://developers.google.com/web/updates/2018/06/a2hs-updates
You can only call prompt() on the deferred event once, if the user clicks cancel on the dialog, you'll need to wait until the beforeinstallprompt event is fired on the next page navigation. Unlike traditional permission requests, clicking cancel will not block future calls to prompt() because it call must be called within a user gesture.
window.addEventListener('beforeinstallprompt', function (e) {
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
showAddToHomeScreen();
});
function showAddToHomeScreen() {
var prompt = document.querySelector(".a2hs-prompt");
prompt.style.display = "flex";
var open = document.querySelector(".a2hsBtn");
open.addEventListener("click", addToHomeScreen);
var close = document.querySelector(".a2hsBtn-close");
close.addEventListener("click", function() {
prompt.style.display = "none";
});
}
function addToHomeScreen() {
var prompt = document.querySelector(".a2hs-prompt");
// hide our user interface that shows our A2HS button
prompt.style.display = 'none';
if (deferredPrompt) {
// Show the prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then(
function (choiceResult) {
if (choiceResult.outcome === 'accepted') {
show_ad2hs_success_message();
}
deferredPrompt = null;
});
}
}
You have to define your own session and add expire date. This is simple with ajax. This is how i did:
Javascript:
$(document).ready(function() {
$.ajax({
url: '/update_session_addtohomescreen',
success: function (session_expired) {
if(session_expired=='True'){
showAddToHomeScreen();
}
},
error: function () {
alert("it didn't work");
}
});
});
This is wrapping the showAddToHomeScreen(); function
View
#csrf_exempt
def update_session_addtohomescreen(request):
if request.is_ajax():
number_of_days_till_expire = 1
now_in_secs = time.time()
if not 'last_session_coockie' in request.session or now_in_secs > request.session['last_session_coockie']+60:#number_of_days_till_expire*86400:
session_expired = True
request.session['last_session_coockie'] = now_in_secs
else:
session_expired = False
return HttpResponse(session_expired)
return None
You should though include csrf token in your request and also add the url to urls.py

Firebase - Web. Can not display logged user's picture

I'm not able to display the picture of a logged user with email/password inside an <img> tag. I could display correctly the email,uid and all the details but the picture. This is the code:
HTML:
<img id="user-image">
Js:
firebase.auth().onAuthStateChanged(function(user) {
var userId = firebase.auth().currentUser;
var picture;
if (userId) {
picture = userId.photoURL;
document.getElementById("user-image").src = picture;
} else {
//Nothing;
}
});
When I go to the console I get error 404/null. Yes, the user Do have a picture ,I tried already with the exact path of the image file and it works.
Thanks.
Why do you call firebase.auth().currentUser; when you already have the user as a parameter of the function that is triggered on change?
What do you get if you do as follows:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
var picture = user.photoURL;
console.log(picture). // <- check in you console that you get the correct url
document.getElementById("user-image").src = picture;
} else {
//Nothing;
}
});

Categories

Resources