I'm currently making a gallery with JavaScript. I want to create a custom history entry, so that the enduser can click the history back for closing a big-picture overlay.
My window.onpopstate looks like this:
function stateChange(event){
let state = event.state;
console.log(state);
if(state !== null){
if(state.show){
showOverlay(state.obj);
}else{
hideOverlay();
}
}else{
hideOverlay();
}
}
And my eventListener for the pictures:
let state = {show: true, obj: itemLinks[i].dataset.file};
history.pushState(state, '');
The Problem is, that my console fires one null following after one click on a picture. But, when I then go back in the history it shows the state object. If I go back another time, I get the null, where I had started.
-- EDIT --
More of my code:
for (let i = 0, len = itemLinks.length; i < len; i++) {
itemLinks[i].addEventListener('click', function(){
let state = {show: true, obj: itemLinks[i].dataset.file};
history.pushState(state, '');
});
}
overlay.addEventListener('click', clickOverlay)
window.onpopstate = stateChange;
And:
let itemLinks = document.getElementsByClassName('item-link');
let overlay = document.getElementById('gallery-overlay');
let overlayImg = document.getElementById('gallery-overlay-img');
function showOverlay(src){
overlayImg.src = src;
overlay.classList.add('gallery-overlay__show');
}
function hideOverlay(){
overlay.classList.remove('gallery-overlay__show');
}
function clickOverlay(){
history.back();
}
The issue was that the elements being clicked to trigger the navigation were <a>
tags, which will trigger a navigation event if they are clicked and their href
attribute is set.
To avoid this you can change the element from an <a>
tag to something else like <span>
or an inline <div>
, but this can bring usability concerns if your page ever needs to be navigable without a mouse. A more robust solution is to prevent the click event from causing navigation, using event.preventDefault()
:
let itemLinks = document.getElementsByClassName('item-link');
for (let link of itemLinks) {
link.addEventListener('click', function(event){
// Keep the <a> tag from triggering the default navigation
event.preventDefault();
// Push our own state navigation
let state = {show: true, obj: link.dataset.file};
history.pushState(state, '');
});
}
This way you still keep all of the beneficial behavior of <a>
tags without the pesky extra navigation event.