We use JS for opening and closing nav panels on our website. Each navbar choice is an href link for when someone without JS enabled visits our website. We are using JS to intercept the link and open the panels via CSS changes.
The function works well for the first few times it is called, then fails and the default link is followed. There doesn’t seem to be a set number of iterations before it fails, but nvbtn3 seems to be the one that it fails on the most.
Not sure how to sort out a cure. It is almost like it gets overloaded and quits. Any suggestions?
Event delegation portion that looks for clicks on the navbar
$('mstrwrap').addEventListener('click', function(e) {
// set eventlisteners for all A HREF links
if (e.target.nodeName === 'A') {
e.preventDefault();
// check if is navbar link
if ((e.target.id.includes('nvbtn'))) {
// determine matching nav panel
const nvpnl = e.target.id;
const lk = 'nav' + nvpnl.match(/d+/g);
// open nav panel
openNav(lk, nvpnl);
}
// end if navbar link
// lots more possible targets
}
}
JS function for opening navigation menus
function openNav(x, y) {
// if already open, close it
if ($(x).style.maxHeight === '100vh') {
// close
$(x).style.maxHeight = '0';
$(x).style.zIndex = '';
$(y).classList.remove('nvopen');
$('nvbar').classList.remove('nvopen2');
}
// close any that are open, then open target
else {
// close all pnl, open specified pnl
const targets = document.querySelectorAll('[id^="nav"]');
for (let i = targets.length; i--;) {
targets[i].style.maxHeight = '0';
targets[i].style.zIndex = '';
}
const nvbtns = document.querySelectorAll('[id^="nvbtn"]');
for (let i = nvbtns.length; i--;) {
nvbtns[i].classList.remove('nvopen');
}
$(x).style.maxHeight = '100vh';
$(x).style.zIndex = '5';
$(y).classList.add('nvopen');
$('nvbar').classList.add('nvopen2');
}
}
We use a pseudo jQuery style variable
var $ = function (selector) {
return document.getElementById(selector);
};
The navbar is simple href links
<a href="https://example.com/menu1.htm" id="nvbtn1">Menu 1</a>
<a href="https://example.com/menu2.htm" id="nvbtn2">Menu 2</a>
<a href="https://example.com/menu3.htm" id="nvbtn3">Menu 3</a>
2
Answers
Bergi was right in the comments, that’s why we ask to give the more details possible and ask for a reproducible example, because in simplifying the code for the question you got rid of the problem (trying to find the minimal example that cause your problem can help you solve it yourself, that’s a good thought process)
Your links are not simply text, they have elements in them:
So your bug happens when you click on the small icon between the text, because the test
if (e.target.nodeName === 'A') { }
failsEDIT (probably simpler):
There is another solution, using CSS
pointer-events: none;
on all elements inside your links, like the<span>
. The event then should not trigger on the span but on the parent link instead.ORIGINAL:
To solve this, you can use the following test, but be careful because changes in the structure of your
<a>
element can mess with it (a reliable solution would be to test the parent element recursively until you find you are in a link or not):You can add other tests, like the class of the
<span>
if it fits your use case.An alternative design proposal:
Put the javascript disabled menu inside a
<noscript>...</script>
opening and closing tag pair. Possibly omitid
attributes if they are only used for by JS, but not for styling.Put the JS enabled menu(s) inside
nav
element(s) which have their style attributes set tonone
.In JS startup code, after the body has been parsed, remove the
display:none
styling fromnav
elements:This design should work in browsers where the client has gone to some trouble to turn JS off. It won’t work in browsers that don’t support CSS and element
style
attributes.The major benefit would be that code to "intercept links" would no longer need to be written.