I am writing a single page javascript application using the HTML5 History API. The application loads content via Ajax and internally maintains state information on the foreground screen using a screen stack.
I want to enable navigation with the back button, but I never want to the forward button to be enabled.
A couple quick bits of information:
When I load a new screen I run the following line:
history.pushState(screenData, window.document.title, "#");
I bind to the popstate event via jQuery:
$(window).bind("popstate", function(event) {
if (event.originalEvent.state != null) {
// Logic that loads the previous screen using my screen stack
}
});
My application's history management is working, however when I go back the forward button is enabled. I need to figure out how to remove data from history
on the popstate
event.
Can I do this with replaceState? I'm not sure how to go about doing this...
The forward button is used to go to the next page while the back button is used to go to the previous page.
Bad Part
To really disable the forward button, you would have to be able to delete browser history, which is not allowed by all javascript implementations because it would allow sites to delete the entire history, which would never be in the interest of the user.
Good Part
This is a bit tricky, but I guess it could work if you want to do custom history. You could just use pushState
in the popstate
event to make your actual page the topmost history entry. I assume the way you handle your history, your window will never unload. This allows you to keep track of the user history yourself:
var customHistory = [];
Push every page you load with history.pushState(screenData, window.document.title, "#");
, like you did before. Only you add the state to your custom history, too:
history.pushState(screenData, window.document.title, "#");
customHistory.push({data: screenData, title: window.document.title, location: '#'});
now if you have a popstate
event, you just pop you custom history and push it to the topmost entry:
window.onpopstate = function(e) {
var lastEntry = customHistory.pop();
history.pushState(lastEntry.data, lastEntry.title, lastEntry.location);
// load the last entry
}
Or in jQuery
$(window).on('popstate', function(e) {
var lastEntry = customHistory.pop();
history.pushState(lastEntry.data, lastEntry.title, lastEntry.location);
// load the last entry
});
The accepted answer solves the problem to disable the forward button, but creates a new annoying issue "the page navigated back to" is inserted in duplicate into the history (as indicated in the answers comments).
Here is how solve the question "diabled forward button" and to avoid the "duplicate" back-button-issue.
//setup the popstate EventListener that reacts to browser history events
window.addEventListener("popstate",function(event){
// In order to remove any "forward"-history (i.e. disable forward
// button), this popstate's event history state (having been navigated
// back to) must be insert _again_ as a new history state, thereby
// making it the new most forwad history state.
// This leaves the problem that to have this popstate event's history
// state to become the new top, it would now be multiple in the history
//
// Effectively history would be:
// * [states before..] ->
// * [popstate's event.state] ->
// * [*newly pushed _duplicate_ of popstate's event.state ]
//
// To remove the annoyance/confusion for the user to have duplicate
// history states, meaning it has to be clicked at least twice to go
// back, we pursue the strategy of marking the current history state
// as "obsolete", as it has been inserted _again_ as to be the most
// forward history entry.
//
// the popstate EventListener will hence have to distinguish 2 cases:
//
// case A) "popstate event is _not_ an obsolete duplicate"...
if( typeof event.state == "object"
&& event.state.obsolete !== true)
{
//...so we _firstly_ mark this state as to from now on "obsolete",
// which can be done using the history API's replaceState method
history.replaceState({"obsolete":true},"");
// and _secondly_ push this state _one_more_time_ to the history
// which will solve the OP's desired "disable forward button" issue
history.pushState(event.state,"");
}
// case B: there is the other case that the user clicked "back" and
// encounters one of the duplicate history event entries that are
// "obsolete" now.
if( typeof event.state == "object"
&& event.state.obsolete === true)
{
//...in which case we simply go "back" once more
history.back()
// by this resolving the issue/problem that the user would
// be counter-intuively needing to click back multiple times.
// > we skip over the obsolete duplicates, that have been the
// the result of necessarily pushing a history state to "disable
// forward navigation"
}
},false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With