Is there a way to delay a popstate event? - javascript

I've tried a few methods to see if I can create a cross browser solution for delaying a popstate event but have not had any luck.
Anyone have any ideas or thoughts?
Below obviously does not work, but something to the effect of:
$(window).on('popstate', function(e) {
// something here to delay the history pageload
console.log('a wild console has appeared!');
});
So the flow would follow this sequence:
Browser "back" or "forward" button clicked
run initial code
A delay before the page changes
page change

According to the Documentation the popstate event is
only triggered by doing a browser action such as a click on the back button
So I do not believe it will get triggered when user clicks 'forward' (and it varies in some browsers)
For reference, here's the full text:
The popstate event is fired when 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.
Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by doing a browser action such as a click on the back button (or calling history.back() in JavaScript).
Browsers tend to handle the popstate event differently on page load. Chrome (prior to v34) and Safari always emit a popstate event on page load, but Firefox doesn't.
UPDATED ANSWER ABOVE
Your code works. (see below) - I added an element to trigger the event (you can see the results in the console)
Make sure you include the jQuery library on your HTML prior to using it though.
$(window).on('popstate', function(e) {
console.log('fired instantly!');
var timer = setTimeout(function() {
console.log('delayed popstate!');
clearTimeout(timer);
}, 1000);
});
$(window).trigger( 'popstate') ;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Call history.back() without triggering 'popstate'

Is there a way to call window.history.back(); without triggering this.getWindow().on('popstate', this.handleBrowserButtons.bind(this));?
No, window.history.back and window.history.go would always trigger the popstate event.
In fact, that's the only time the event is actually triggering so you could probably remove the popstate event handler altogether and use something else if you don't want this happening on back/forward navigation.
As history.back and history.go always call a registered onpopstate event you could make the onpopstate event the main way of closing the modal. I did this when I was doing something similar and it worked well.
To keep this backward compatible with browsers that don't support pushstate you can check for support and call closeModal directly when there is no support.
So the close modal button code would be like this:
if (history.pushState) {
// Your popstate event handler will be called, which calls closeModal()
history.back();
}
else {
// No popstate event handler registered, so call closeModal() directly
closeModal();
}

How to "browser back" when using pushState?

I have this code:
window.history.pushState(newUrl, "", newUrl);
My question is, how to make sure that when doing pushState the browser back button will function as normal or in other words should go "back"?
(without using jQUery)
The normal behaviour for the back button is for the browser to go back to the previous document, but when you use pushState, there isn't a previous document.
The point of pushState is to keep the browser on the same document while updating the URL. This is accompanied by DOM changes applied with JavaScript.
It is a simulation of going to a new page.
To make the back button appear to work, you need to write a matching simulation of going to the previous page.
You can do this by listening for a popstate event.
Page <span id="p">1</span>
<button>Next</button>
<script>
document.querySelector("button").addEventListener("click", function () {
document.getElementById('p').textContent++;
history.pushState({}, "", "/" + document.getElementById('p').textContent);
});
addEventListener("popstate", function (e) {
document.getElementById('p').textContent--;
e.preventDefault();
});
</script>
push is for pushing... adding
you should go for history.back()
If you want to popState - emit popstate event on window or do history.replaceState()
If you want to cancell commented event:
My answer will do the trick
https://stackoverflow.com/a/44553087/5694206

Firefox firing onchange events after tab restore

Firefox is firing onchange events in my webapp after tab restore.
When reloading the same URL in Firefox there is no problem, no onchange events get fired on page load, all changed values since last visit are displayed correctly.
But when reopening the same page with the same URL, after closing Firefox and reopening the page with "restored tabs" (from the Firefox option "show my windows and tabs from last time") then it is firing onchange events for all values that have been changed since last visit.
Actual workflow ot reproduce the problem:
My update events are in background (JavaScript/AJAX) and are fired
with onchange events;
Firefox setting "show my windows and tabs from last time" enabled;
Change some values in my page (select fields);
Close Firefox;
Open the same URL on another browser or computer, and change some values;
Reopen Firefox, select the tab with the page on it, it reloads and fires onchange events again for all changed values since last visit.
Tried to reproduce this behaviour with completely different pages (not created by me and using other script libraries and stuff) and the result is the same, it is always firing the onchange events.
Chrome is not doing this with the "restore tabs" option.
Why is it firing onchange events? How can I prevent it?
A few suggestions on how to deal with this depending on the wanted result. Note that this is tested on my machine, behaviors may vary.
They way it seems to work is that Firefox tries to restore data that was entered by user. So it modifies the page, triggering the change event. This event is slighlty different than the one triggered by the user. It is a UIEvent while the user triggered one is a straight Event. And this Event is cancelable and triggered before the window load event. So this gives a couple of ways to deal with this. I'll take a select element for example.
If you want the select to keep value entered before window closing, but not trigger the onchange event, you can set the onchange call on the window.onload. Like this:
window.onload = function(){
element.onchange = function(){
Since the setting of the select occurs before onload, this specific change won't trigger your onchange function.
Other way would be to target behaviors you don't to trigger by putting a condition validating if the element is cancelable or not. If it's cancelable, it means it's called from a restore session and won't trigger what's inside. Like this:
element.onchange = function(e){
if(e.cancelable == true){
Other way, to clear out all data would be to set a document.onchange event and reload the page if the event is cancelable. Like this:
document.onchange = function(e){
if(e.cancelable == true){
window.location = window.location
}
}
Of course you need to make sure you don't have any other cancelable change event called in your page.
EDIT:
To clarify order of events fired, see this jsfiddle, not in iframes, iframes seems to behave differently, so if you have iframes, it may be a bit more complicated. But without iframe, you'll see how the different events are triggered depending on your interactions:
document.onchange = function (e) {
//this will be triggered on restore before the window load event
alert('restore onchange called, e.cancelable = ' + e.cancelable)
}
window.onload = function (e) {
//You'll see that on restore, this will be triggered but after page has been updated
alert('window load called')
document.onchange = function () {
//This onchange will be called normally, not on restore
alert('after onload change, e.cancelable = ' + e.cancelable)
}
}
http://fiddle.jshell.net/nozp9uhk/6/show/
Firefox is caching your files when you load the page, so when you restore the tab, the differences between your cached values and the new ones may be firing onchange events.
Try to clear the cache when restoring the tab. I see two ways to do this :
Call window.location.reload(true) to reload the current page
or
Change the name of the JavaScript file that initializes the onchange events for this :
<script language="JavaScript" type="text/javascript" src="yourscript.js?n=1"></script>
This (?n=1) will force Firefox to load a new copy of the file "yourscript.js"

popstate event on history api does not fire

I have a simple code to test the history api of html5
Just some buttons
<button name="hey1" onClick="historytestone();">history test one</button>
<button name="hey2" onClick="historytesttwo();">history test two</button>
<button name="hey3" onClick="historytestthree();">history test three</button>
<button name="hey4" onClick="historytestfour();">history test four</button>
<button name="hey5" onClick="historytestfive();">history test five</button>
and my js is like
function historytestone(){
history.pushState({page: "ross"}, "ross","ross.html");
}
function historytesttwo(){
history.pushState({page: "monica"}, "monica","monica.html");
}
function historytestthree(){
history.pushState({page: "chandler"}, "chandler","chandler.html");
}
function historytestfour(){
history.pushState({page: "joy"}, "joy","joy.html");
}
function historytestfive(){
history.pushState({page: "rachel"}, "rachel","rachel.html?a=1&b=2");
}
// this does not work
window.addEventListener("popstate", function(event) {
alert("hello");
});
//nor this works
window.onpopstate=function(event){
alert("hello");
}
When I try to listen for the popstate event, I get no alert and no errors on the console. No metter what syntax I use, I get nothing.
Sorry, but I cannot see what is wrong. Please explain.
EDIT
Here is my problem.
This is my code here and this is the demo I was based here.
Now, I believe that my code is a simplified version of the demo.
I have to click the "back" button of the browser in order to fire the popstate event (see the alerts). But the demo can fire the popstate event (change content) just by clicking the names.
Why this happens? Why I have to hit the back button and the demo does not, even tho is the same code? Thanks again
based on the definition here: https://developer.mozilla.org/en-US/docs/Web/Events/popstate
The popstate event is fired when 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.
Note that just calling history.pushState() or history.replaceState()
won't trigger a popstate event. The popstate event is only triggered
by doing a browser action such as a click on the back button (or
calling history.back() in JavaScript).
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.
if you see the source code of http://html5doctor.com/demos/history/ each time when you click a link it calls the updateContent function (which is also the event handler of popstate) then it calls pushState.

popstate event handler seems not to work

I'm having a problem with a 'popstate' event handler, this is my code:
window.addEventListener("popstate", function (event){
if (event.state) {
alert('abc')
}
});
// The data object is arbitrary and is passed with the popstate event.
var dataObject = {
createdAt: '2011-10-10',
author: 'donnamoss'
};
var url = '/posts/new-url';
history.pushState(dataObject, document.title, url);
I expected this code will pop up an alert box when it's executed but, nothing happens.
Is there anything wrong here?
Thank you.
pushState do not trigger the popstate event, only clicking back / forward button (or use backspace) or invoking history.back() / history.go(n) would trigger this event.
Also, in webkit browsers, a popstate event would be triggered after page's onload event, but Firefox and IE do not have this behavior.
No it will not,
As per MDN documentation
Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by doing a browser action such as a click on the back button (or calling history.back() in JavaScript).
Again as per this question the popstate event is not triggered in Chrome when you call pushState().
history.pushState() will not trigger the popstate event by definition.
The popstate event is fired in certain cases when navigating to a session history entry.
This event is intended to be only triggered when navigating to a history entry, either by pressing the back/forward button, or history.go/back.

Categories