So first I have a script that checks for the class .current and adds prevent default for all the links without that class, and then a callback that should re-check and restore click behavior for the link with the new .current class while applying prevent default to the other links.
Initial script that sets prevent default
var links = document.querySelectorAll('.link-slider');
var slidesv = document.querySelectorAll('.carousel-3d-slide');
for (var i = 0; i < slidesv.length; i++) {
var slidev = slidesv[i];
var link = links[i];
if (slidev.classList.contains('current')) {
// Class exists!
/*console.log("works");
link.addEventListener("click", function(e){ return true; });*/
} else {
// Class not found
console.log("nonworks");
link.addEventListener("click", function(e) {
e.preventDefault(); }, false);
}
}
callback
onAfterSlideChange() {
var linkscallback = document.querySelectorAll('.link-slider');
var slidescallback = document.querySelectorAll('.carousel-3d-slide');
for (var i = 0; i < slidescallback.length; i++) {
var slidecallback = slidescallback[i];
var linkcallback = linkscallback[i];
linkcallback.addEventListener("click", function(e){ return true; });
console.log("true");
if (slidecallback.classList.contains('current')) {
// Class exists!
} else {
linkcallback.addEventListener("click", function(e) {
e.preventDefault(); }, false);
}
}
},
Probably what you should do here is just have one event listener for all of those links and then put your logic in that event listener. This is referred to as event delegation.
Thank you. I’m not making sense though at the example in the link on the logic steps, but I’m on it. This example I mean:
let selectedTd;
table.onclick = function(event) {
let target = event.target; // where was the click?
if (target.tagName != 'TD') return; // not on TD? Then we're not interested
highlight(target); // highlight it
};
function highlight(td) {
if (selectedTd) { // remove the existing highlight if any
selectedTd.classList.remove('highlight');
}
selectedTd = td;
selectedTd.classList.add('highlight'); // highlight the new td
}
var linkscallback = document.querySelectorAll('.link-slider');
var slidescallback = document.querySelectorAll('.carousel-3d-slide');
linkscallback.addEventListener('click', function (event) {
for (var i = 0; i < slidescallback.length; i++) {
var slidecallback = slidescallback[i];
var linkcallback = linkscallback[i];
if (slidecallback.classList.contains('current')) {
linkcallback.classList.remove('preventcurrent');
} else {
linkcallback.classList.add('preventcurrent');
event.preventDefault();
}
if (linkcallback.classList.contains('preventcurrent'))
linkcallback.preventDefault();
}
}
Okey I did some progress, but I’m gertting the error “Uncaught TypeError: slidev.classLists is undefined”. Alright why I feel like I’m the only one checking this thread, won’t post again…
There’s a small typo - the method is .classList, you’ve written .classLists.
It’s very difficult to debug your code just from looking at it here, that’s probably why so few are answering. I also can’t copy/paste your code into my own editor to see what’s wrong with it, because I don’t have your HTML. Can you maybe put your code on an online sandbox like codepen.com?
Awesome, thanks. Now there’s not much happening yet, in fact I’m not sure what’s supposed to happen. Are the slider links actual links to an external resource, where the user should be able to click on (you have wikipedia for example), or should they allow the user to flip through a slideshow? When should the link be active (no preventDefault), and when should it be disabled?
I also don’t understand your click handler, because
the slides are the <div> elements with class .carousel-3d-slide
the e.currentTarget however is the <a> that received the click event
Which one should have the class “current”, the div or the link?
I tried to guess what’s supposed to happen and modified your code a little so that
when I click on a link, the corresponding slide-<div> gets the .current class, not the link
Sure! Thank you!! I explain in more detail: I’m trying to disable clicks on a slider for the not active slides. In other words the active slide contains a class named: “current” and only this slide, the active one, should have click behavior restored/not prevented.
The div, but perhaps it should be better to add the class to the link inside/contained in the div instead, that has the .current class, and then allow for click behavior to the link that has the class “current”.
Unfortunately removing the .current class for all slides and then adding it for the active slide is not an option since removing the .current class from the active slide causes it to disappear. Do note the codepen is a lot simplified, hence that won’t happen but it does in the local server installation, so I guess it would have to be used another approach.
I’m still not 100% sure how the user is supposed to flip through the slideshow, but maybe that’s not important.
You could give the current class to the links, and then first check if the link has current. If it doesn’t, then preventDefault, otherwise, the link will work:
Because you can either run that once (on page load), and then only one link would get an event listener. Or you can run it each time someone clicks on a link, and then you’d add more and more event listeners to the links (while at the same time not removing them where you don’t want a click event to have an effect).
The best solution is to give them all an event listener, and within the callback, first check if the link has a certain class or not, and then decide which code should run for an active/unactive link.
Okey something like this? it is preventing all clicks now though, so I’m doing something wrong here.
let links = Array.from(document.querySelectorAll('.link-slider'));
var linksv = document.querySelectorAll('.link-slider');
let slides = Array.from(document.querySelectorAll('.carousel-3d-slide'));
const handleClick = (e) => {
//e.preventDefault();
links.forEach(link => {
link.classList.remove('current');
});
slides.forEach(slide => {
if (slide.classList.contains('current')){
e.currentTarget.classList.add('current');
}
if (!e.target.classList.contains('current')) {
e.preventDefault()
}
});
}
links.forEach(link => {
link.addEventListener('click', handleClick)
});
Edit will fork the codepen: https://codepen.io/Snippet/pen/JjbJBYB
Edit 2 : improved the code more
I can see that even with the current class, the link click is prevented.
The preventDefault needs to happen at the very top of the function, because right now, you first loop over your links and remove the current class from all of them, and after that, you check for the current class. So you’d rather do something like this (I’ve added comments to explain):
const handleClick = (e) => {
if (!e.target.closest("a").classList.contains("current")) {
e.preventDefault();
}
/* remove current class from all links, and give it only to the one that was clicked */
links.forEach((link) => link.classList.remove("current"));
e.target.closest("a").classList.add("current");
/* remove current class from all slides, and give it only to the slide that was clicked*/
slides.forEach((slide) => slide.classList.remove("current"));
e.target.closest(".carousel-3d-slide").classList.add("current");
};