I need help figuring out whether a popstate event was triggered by clicking the browser’s back button or forward button. Right now I’m storing timestamps in the history state when pages get pushed, and this works fine most of the time. But there’s a problem when someone navigates back a few pages and then refreshes the current page. The timestamp gets updated on refresh, so when they go forward again, my animation logic gets confused because it thinks they’re going backwards.
var NavigationHandler = function (container) {
var self = this;
self.push = function (path, content, pageTitle) {
var timestamp = Date.now();
clearPrevious();
content.setAttribute('data-timestamp', timestamp);
container.appendChild(content);
executePageScripts(content);
if (pageTitle) {
document.title = pageTitle;
}
history.pushState({
html: content.innerHTML,
timestamp: timestamp,
title: pageTitle
}, null, '?page=' + timestamp);
};
function executePageScripts(element) {
var scriptTags = element.querySelectorAll('script');
for (var j = 0; j < scriptTags.length; j++) {
var func = new Function(scriptTags[j].innerHTML);
func.call(window);
}
}
function setupCurrentPage() {
var currentTimestamp = Date.now();
if (history.state && history.state.timestamp) {
currentTimestamp = history.state.timestamp;
}
var activePage = container.children[container.children.length - 1];
activePage.setAttribute('data-timestamp', currentTimestamp);
var pageContent = activePage ? activePage.innerHTML : '';
history.replaceState({
html: pageContent,
timestamp: currentTimestamp
}, null, location.href);
}
function clearPrevious(isBackward) {
if (container.children.length < 1) return;
var activePage = container.children[container.children.length - 1];
if (!activePage) return;
activePage.addEventListener("animationend", function() {
if (activePage.parentElement) {
activePage.parentElement.removeChild(activePage);
}
});
if (isBackward === true) {
activePage.classList.add('backward');
} else {
activePage.classList.remove('backward');
}
activePage.classList.add('exit');
}
window.addEventListener('popstate', function(event) {
if (!event.state) return;
var activePage = container.children[container.children.length - 1];
var activeTimestamp = activePage.attributes['data-timestamp'].value;
var newPage = document.createElement('div');
newPage.innerHTML = event.state.html;
newPage.setAttribute('data-timestamp', event.state.timestamp);
newPage.className = 'history-page';
var isGoingBack = activeTimestamp > event.state.timestamp;
if (isGoingBack) {
newPage.classList.add('backward');
}
if (event.state.title) {
document.title = event.state.title;
}
clearPrevious(isGoingBack);
container.appendChild(newPage);
executePageScripts(newPage);
});
setupCurrentPage();
};
function createPage() {
var pageElement = document.createElement('div');
var currentTime = new Date().toLocaleTimeString();
pageElement.innerHTML = '<div><h2>' + currentTime + '</h2></div>';
navHandler.push('?page=' + Date.now(), pageElement, 'New Page');
}
var navHandler = new NavigationHandler(document.getElementById('content'));
Has anyone found a reliable way to detect navigation direction without running into this refresh issue?