React app detect if user refresh window or navigated away - javascript

I need to be able to detect if the user refreshed the window or navigated away (say google.com) and then return to the page so I can trigger an event.
I tried different onbeforeunload but it wasnt detecting it.
I tried, this and it wasnt working or triggering the console.log.
componentDidUpdate()
{
window.addEventListener("onbeforeunload",function (){
console.log('Page Refreshed')
})
}
However, that doesnt even trigger the console.log message. I have also tried beforeunload and same results
any ideas why?

The best way to detect a page reload is to use window.performance.navigation which returns an object for the page containing two key-value pairs { redirectCount: 0 , type: 0 } shown below:
console.log(window.performance.navigation)
When the key type is equal to a value which is non-zero for example - type: 1 it depicts a page reload.
Note: Most probably the snippet won't work as expected. In that case you can switch to browser console and check it out yourself and don't forget to check the Preserve log checkbox under network tab of browser console.
To check if page is navigating away. Try unload event instead of onbeforeunload.
window.addEventListener("unload", function (e) {
console.log('going away', e)
})
Lastly, in case of page load you can use lifecycle hooks. You can run some code as soon as the page loads in useEffect() of react-hooks in react or componentDidMount() if you're using class based syntax.
useEffect()
useEffect(() => {
// Run as soon as page loads
console.log('page loaded');
});
componentDidMount()
componentDidMount() {
// Run as soon as page loads
console.log('page loaded');
}

The event name is not recognized, in addEventListener the event name should be "beforeunload".
"onbeforeonload" is window property, use it like "window.onbeforeunload = funcName".
If your console log didnt show, it might be cleared by browser, try persist the log, then see it console.log shows up

Try this
window.onbeforeunload = function(event) {
console.log('Page Refreshed');
};
If you don't see the console you have to preserve the logs in the console.

Related

In Vue, how to make browser to go back to previous page using window.history.go(-1)

Hi I'm making a webpage based on Vue, but I'm in trouble now.
I initially used router.go(-1) to prevent access through the address
(ex : ../client/mypage -> ../admin/mypage ) and to redirect to the previous page,
but it didn't work because the page itself was refreshed. (In my opinion,router history stack was empty)
So, what I found is window.history.go(-1), but it didn't work either even though its length was greater than 1.
What's the problem and how should I solve it?
mounted(){
if (this.auth) { // when you access through address, check the authority
this.$router.go(-1); //doesn't work
window.history.go(-1); //doesn't work either
}
}
pic: console.log(window.history)
Try with this.
mounted(){
if (!this.auth) { //If not authenticated
window.history.back();
}
}

Why does my history.pushState call result in a null state?

I'm following some tutorials to learn how to use the history events in JS to deal with what is essentially paging on one of my forms. I have added the following code to an onClick event that changes the page:
state = {'actionCode': 'pageChange', 'pageNum': pageNum};
window.history.pushState(state, 'Page ' + pageNum, '/subF/fileName.cfm#page' + pageNum);
console.log(state);
I tried a number of other variations originally, including blank or null title and url arguments.
I then added this to the bottom of my JS file to see what I have to work with:
function checkState(e) {
console.log(e);
console.log(history.state);
}
$(function() {
window.onpopstate = checkState;
});
What I expected to see after changing 'pages' (running the first snippet of code) and then clicking the back button was a e.state object containing actionCode and pageNum variables. Instead, I see the state appear as null even though the object itself appears to hold the data immediately after passing said object to pushState:
I get the same null value when dumping history.state, so I assume the problem is with the push and not the get, or that I'm completely misunderstanding how these functions work.
What I expected to be able to do was add code to checkState that looks at the 'actionCode' and takes appropriate action based on that, reference the variables I know will exist in the state object for that particular actionCode.
In order for the onpopstate event to get triggered, you have to perform an actual "change history" action, i.e. clicking the browser BACK/FORWARD button or manually calling history.back() / history.forward() / history.go(). Simply pushing/replacing a state won't trigger an event.
You can try this:
<script>
window.onpopstate = function(event) {
console.log(event);
};
const state1 = {'actionCode': 'pageChange', 'pageNum': 1};
const state2 = {'actionCode': 'pageChange', 'pageNum': 2};
history.pushState(state1, 'Page ' + state1.pageNum, '/subF/fileName.cfm#page' + state1.pageNum);
history.pushState(state2, 'Page ' + state2.pageNum, '/subF/fileName.cfm#page' + state2.pageNum);
history.go(-1);
</script>
Here, the invocation of history.go(-1) will load the previous page from the session history thus firing an onpopstate event and you will see the state is there.
You can learn more about the peculiarities here: MDN page.
If you're trying to simulate handling of location/state change for new entries, you'll have to manually fire a PopStateEvent(or any custom one with a respective handler).
const event = new PopStateEvent('popstate', { state: state });
window.dispatchEvent(event);
or simply:
window.dispatchEvent(new Event('popstate'));

How to make automated test scripts in protractor wait, until the page is loaded fully

No, but really! I know this generic question has been asked thousands of times, but there is something more specific that looks feasible to me and thus I want to know how to achieve it
The problem
I'm testing an angular app with protractor. Inside the app I want to verify that when I click a link I'm being redirected to the right page (non-angular). The problem is that until I reach the page I'm verifying, the url changes 3 times or so (there are multiple redirections happening), so I can't make a waiting function wait until the page is loaded completely
What I tried/what won't work for me
I'm against browser.sleep() for more than 1000 ms!
browser.waitForAngular() as this is not an angular page
ExpectedConditions.urlIs() the url is the variable I'm asserting
ExpectedConditions.presenseOf() the page maybe changing so I can't rely on elements inside
browser.executeScript("return window.document.readyState") returns compete immediately, though the page is still loading (I was certain this is what I need, but that didn't work either)
I tried even adding a functions that waits for innerHtml of the whole page not change for at least 3 sec, but it fails because at times there is a pause of more than 3 sec between redirects are happening. Everything above 3 sec isn't a reasonable timeout
The question
What I noticed is when the browser is loading the page, Reload this page button changes its state to Stop loading this page (X icon) until I'm redirected to the final page (screenshots below). So the question is is there a way to make protractor point to the same condition that chrome uses to choose which icon is displayed?
vs
And if not exactly the same, but how do I make protractor hang until the page is fully loaded
Important to consider
Obviously there are a lot of dirty solutions that I can do like explicit waits. But I'm coming back to this question every once in a while, so I'm not interested in these dirty solutions that work 70% of the time for a specific cause
P.S. I figured that the button changes the icon on document.load() event. But I can't figure out what should I write in the console in order for that script to log a message when I refresh they page
Have you tried
await browser.wait(async () =>
await browser.driver.executeScript('return document.readyState;') === 'loading', 2000)
.then(() => true, () => true);
await browser.wait(async () =>
await browser.driver.executeScript('return document.readyState;') === 'complete', 5000)
I have the following snippet for just the problem, I wait for an element to be displayed:
ElementFinder.prototype.secureIsDisplayed = function () {
return browser
.wait(EC.visibilityOf(this), actionTimeout)
.then(() => this.isDisplayed())
.catch(err => {
throw new Error(`Expected ElementFinder ${this.locator()} to be displayed. ${err.toString()}`);
});
};
where actionTimeout is a const int and EC = protractor.ExpectedConditions you will need to import the file and call it like so:
import './asd.ts'
element(by.css('.myClass')). secureIsDisplayed()
I if you can find the last element that loads, or just get an element of a redirect it can do wonders.
Cheers.
Have you tried...
browser.executeScript("return window.jQuery.active").equals(0)

How can I detect back button in the browser?

I have a function named back() which will be used for ajax calls. Actually I have an array stack contains last 5 search results and that back function will switch to the previous result set (according to that array stack) and it even changes the URL using window.history.pushState() when you click on the back button.
That back button I was talking about, is an element inside the browser which revokes back() function. Now I want to revoke back() function also when user click on the back button of the browser. Something like this:
window.onhashchange = function() {
back(); // this function also changes the url
}
But sadly window.onhashchange will be revokes twice when I click on the back of the browser. Because window.onhashchange will be revoked when you change the URL using window.history.pushState().
Anyway, how can I detect what things changes the URL? Either my JS code or the back button of the browser?
You can use performance.navigation.type
At any given point, for example on document.onload, you can read the value of type and, if it's:
0 The page was accessed by following a link, a bookmark, a form submission, a script, or typing the URL in the address bar.
1 The page was accessed by clicking the Reload button or via the Location.reload() method.
2 The page was accessed by navigating into the history.
255 any other way.
Just beware that support is limited according to the compatibilty table.
However, from the looks of it, it seems the table is outdated. It says it is not supported on chrome and I just tested it and works as expected on my chrome version (67.0)
One of solution is to implement onunload event with localstorage option.
This is from my head maybe you will need correction but this is base !
var history = [];
window.onload = function(){
var handler;
if ( localStorage.getItem('history') == null ) {
// FIRST TIME
history[0] = window.location.href;
localStorage.setItem("history", JSON.stringify(history));
}
else {
handler = localStorage.getItem('history');
handler = JSON.parse(handler);
history = handler;
// Just compare now
if (history[history.length-1] == window.location.href) {
// no change
} else {
history.push(window.location.href);
}
}
}
window.onunload = function(){
localStorage.setItem('history', JSON.stringify(history));
}
Note :
Since 25 May 2011, the HTML5 specification states that calls to
window.alert(), window.confirm(), and window.prompt() methods may be
ignored during this event. See the HTML5 specification for more
details.

Running some code when browser is closed

I have a website where each pages need to check if user close the browser, in this case I run some code (releaseLocking).
So on these pages I have implemented this code:
$(window).on('beforeunload', function () {
return "Are you sure you wanna quit ?";
});
$(window).unload(function () {
releaseLocking();
});
It works but I noticed that if I navigate to multiple pages where this code is implemented, when closing the browser, I'll have multiple call to releaseLocking (for each previously visited pages).
I would prefer only run this code for the last page really active. Do you see what I mean?
Do you have any idea how to proceed?
Thanks.
I suggest using localStorage for this. Since localStorage stores variables per domain, it will allow you to check if the code was already executed. Localstorage is also bound to the session, so after the browser is fully closed, your session is gone, causing the localStorage to be cleared so it wont interfere with the next session.
$(window).on('beforeunload', function () {
return "Are you sure you wanna quit ?";
});
$(window).unload(function () {
if ( !localStorage.getItem('lockReleased') ) {
releaseLocking();
localStorage.setItem('lockReleased', true)
}
});
The code above will set localStorage variable lockReleased to true for the first window that closes. The other windows will see the value, and won't call releaseLocking.
In my knowledge it is impossible to detect a browser close separately
from a browser navigation. the browser does not provide the
window with that information.
SEE HERE ALSO
I am not sure this is the only way to do it(neither the best), anyway you should be able to save a sort of session of the user and ask everytime to the server if the page is the last opened.
//the var declaration goes at the beginning of the script
var isLastPage = false;
$(window).on('beforeunload', function () {
//ajax request, the callback will set isLastPage to true if it is the last page opened by the user with that session.
});
$(window).unload(function () {
if(isLastPage) releaseLocking();
});
Server side you should create a session wich stores all the pages of the user(remember to update it via JS when the user closes a page or opens a new one). I think that only via JS is not possible to do it, you need to be helped by the server.

Categories