Using onpopstate in an Chrome Extension for Facebook - javascript

I'm trying to create a Chrome plugin for facebook and I'm using onpopstate event to check when the user goes to another page. The only problem is that the onpopstate doesn't fire.
This is the (simple) code I'm using:
window.onpopstate = function() { console.log('pop'); };
this is a screen of the problem:
As you can see the pushState code is called, but the onpopstate listener is not.
Do you know what's happening here?

#enhzflep's answer is in the comments above and not immediately obvious. From MDN:
Calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript), when navigating between two history entries for the same document.
In other words, the onpopstate event shouldn't be firing in this case.

Related

Popstate not triggering on Chrome for Android when clicking the back button

Upon clicking the back button in the browser, I would like to prevent the default behaviour of going one page back and instead do an action. I'm using the "popstate" event listener. The following function (I'm using Vue 2) works in all major browsers and even in Firefox for Android, but when I test it in Chrome for Android, it simply goes back one page without popstate being triggered at all.
mounted() {
history.pushState(null, null, <current-url>);
window.addEventListener("popstate", () => { alert(1) });
}
I tried wrapping the popstate event inside the load event and giving it a timeOut of 0, but it still didn't work specifically in Chrome for Android. The version I'm testing on is 93.
I did some more research and it seems that Chrome won't let you use popstate if there is no user interaction first. As long as you click on something or scroll down on mobile, popsate will work, otherwise it won't. I tried to simulate user interaction with click(), but that didn't work either. It seems Chrome wants genuine user interaction. I also realized this is sort of a duplicate of: Chrome popstate not firing on Back Button if no user interaction

PopState not firing after coming back from another site

My popstate event handler is defined thusly:
window.addEventListener('popstate', function (ev) {
alert('popstate');
/* recompose dom */
});
It works fine while I am within my site as I use back and forward, however when I navigate to another site and then come back my event does not fire.
I assume this is by design based on the following comment on Mozilla Developer:
Browsers tend to handle the popstate event differently on page load.
Chrome (prior to v34) and Safari (prior to 10.0) always emit a
popstate event on page load, but Firefox doesn't.
If this is the case, how do I get the most recent pushed state when coming back to my page from another site.
I figured it out; pull the current page state from history.state on document ready and apply it.

How can I ignore window.onpopstate on page load?

I'm playing with window.onpopstate, and there is a thing that annoys me:
Browsers tend to handle the popstate event differently on page load.
Chrome and Safari always emit a popstate event on page load, but
Firefox doesn't.
source
I tested it, and yeah, in Chrome and Safari 5.1+ the popstate event is fired on page load, but not in Firefox or IE10.
The problem is, that I want to listen only to popstate events where user clicked the back or forward button (or the history was changed via javascript), but don't want to do anything on pageload.
In other words, I want to differentiate the popstate event from page load from the other popstate events.
This is what I tried so far (I'm using jQuery):
$(function() {
console.log('document ready');
setTimeout(function() {
window.onpopstate = function(event) {
// Do something here
}, 10);
});
Basically I'm try to bind my listener function to popstate late enough to be not bound on page load, only later.
This seems to work; however, I don't like this solution. How can I be sure that the timeout chosen for setTimeout is big enough, but not too big (because I don't want it to wait too much).
I hope for a smarter solution!
Check for boolean truth of event.state in popstate event handler:
window.addEventListener('popstate', function(event) {
if (event.state) {
alert('!');
}
}, false);
To ensure this will work, always specify a non-null state argument when calling history.pushState() or history.replaceState(). Also, consider using a wrapper library like History.js that provides consistent behavior across browsers.
I had a similar problem and i had to validate to make sure if page was loaded completely.
I used something like this :
var page_loaded = false;
window.onpopstate = function(event){
if(!page_loaded){
page_loaded = true;
return false;
}
//Continue With Your Code
}
To react on popstate event, you need to push some state onto the session history.
For example add this line to the document ready section:
history.pushState(null, null, window.location.pathname);
Not ideal, but it works in Chrome, Firefox and other browsers as well.
Then the event is fired correctly when user clicks on Back or Forward button, also when history.back(), history.forward(), history.go() methods are called manually. Each time when popstate has been invoked, you have to push another state again to make it working.
See also:
Single-Page Apps and HTML5 pushState
How to Detect Browser Back Button event - Cross Browser
It seems none of the browsers are emitting the event on page load any more as of today:
Browsers used to handle the popstate event differently on page load, but now they behave the same. Firefox never emitted a popstate event on page load. Chrome did until version 34, while Safari did until version 10.0.
Source: https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent

When does popstate fire?

I put all of my code in $(document).ready as per norm, but should I put my 'popstate' listener at the very end of this code too? Or does it matter?
This doesn't really matter, and since it's an event, can even be done before your ready method. The only thing needing to be placed inside document ready is code interacting with the DOM. Everything else doesn't (and possibly shouldn't) be placed in document ready.
Example:
window.onpopstate = function() {
// binding this event can be done anywhere,
// but shouldn't be inside document ready
};
$(document).ready(function() {
// DOM manipulation and other stuff
});
Now when popstate actually is triggered is a lot different than when it is bound. According to the Mozilla doc:
A popstate event is dispatched to the window every time the active history entry changes. If the history entry being activated was created by a call to history.pushState() or was affected by a call to history.replaceState(), the popstate event's state property contains a copy of the history entry's state object.
I was confused, because popstate was firing on every page load (I use chrome).
From https://developer.mozilla.org/en-US/docs/DOM/window.onpopstate:
Browsers tend to handle the popstate event differently on page load.
Chrome and Safari always emit a popstate event on page load, but
Firefox doesn't.
So in chrome (and apparently safari), the jquery ready method will execute, followed by the popstate event.
i.e. it doesn't matter if you attach the event within ready (or body.onload for that matter), the popstate event will happen after your ready method is complete.
In firefox (16.0.1) the popstate event does not fire on page loads (I can't test IE 10).
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate
Calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript), when navigating between two history entries for the same document.
Just add a key to the state every time you push to history or replacing the state, and check for it on the popstate event, if you don't use the state at all you can simply push {} as state and quit the pop state in case the event.state is null.

JavaScript + onunload event

I want to fire onunload event to do some clean up operations, I have multiple tabs(Navbar) showing multiple links to different web pages,my problem is that even when I'm in some other page my unload function which is in tag of some other jsp is fired. Please help to resove this, I want unload function to be called when user closes browser in that page.
I'm not sure how you got the onunload event to work....The problem I've found with using the onunload event is that it is fired after the page has been unloaded. This means that no more JavaScript can be executed because the page has been unloaded.
You should be looking into using the onbeforeunload event.
This event is a little unique because if the function that handles this event returns anything a pop up is displayed asking the user if they would like to continue with the operation. So, in your case make sure that your function doesn't return anything. The other thing to note about the onbeforeunload event is that, at this time, Opera does not support it (Safari, FireFox, and Internet Explorer do though).
Both the onbeforeunload and onunload events are executed every time the page is unloaded. If a control on your page submits the page to the server code, the page is unloaded and the JavaScript is executed.
If you don't want the JavaScript to be executed when a control on your page is submitting it to the server you have to implement something that checks to see whether or not your code should be executed.
This is simple, add a JavaScript boolean to the page and a function that set's this boolean to true. Make sure that every element in your page that posts back to your server code sets this boolean to true before it submits the page. Check this boolean in your onbeforeunload event to see if your cleanup code should be executed.
Hope this helps,
-Frinny
It seems that the unload function has been created in a global scope. Try placing that function only on the page you want to act.
You have a frameset page? And you want to be notified when they navigate away from the frameset? Add an onbeforeunload on the frameset. I don't know what you mean by clean up, but you can't send XHRs during unload safely across browsers

Categories

Resources