+ 8
Solved:Is there a way to disable click on an element with an event listener without removing the event listener or flags & if's?
I have a group of elements that can be clicked. But once clicked, I don't want them clicked again. I have a bunch of flags and if's but it seems an ugly solution. Removing and adding the event listeners is also ugly. Is there a better way?
20 Réponses
+ 7
Have you tried using the line below?
event.preventDefault();
Where event is provided as an argument in your click handler.
+ 6
Hmm... Something isn't right about that. Can you share the code?
+ 6
In addEventListener, add an option, object 'once' set to true, would make the event only fire once.
target.addEventListener('click', eventMethod, { once: true } );
+ 5
Paul K Sadler BTW... I just saw your followup question from earlier.
I'm responding to that now...
Without knowing more about the code and markup, it's hard for me to say what the issue is with e.preventDefault() in your code.
I can mess around with a version of what I believe you described and try to replicate the issue. However, I'd be guessing and I would likely implement my code much differently.
If you can publish what you have in Code Playground, that would be much easier to work with. Otherwise, no biggie. 😉
+ 4
In addition to Biraj's solution for removing named event listener with removeEventListener() method, here is how you can remove anonymous event listener:
https://code.sololearn.com/W6NpiFj2L4kt/?ref=app
However, an advanced solution will be to refrain from adding event listener to each element one by one. A simple solution is using event delegation, and dataset. Here is a small demo:
https://code.sololearn.com/WKip4OTCKHdd/?ref=app
+ 4
I have a memory card game. As you click pairs of cards I check to see if they match or not. The card deck is a <ul> and the cards are <li> I have moved the event lister up to the parent as it is a less ugly and I get the events when they bubble up.
deck.addEventListener('click', function(event) {
if(!gameTimerIntervalID) {
gameTimerIntervalID = window.setInterval(() => {
seconds += 1;
displayTimer(timer);
}, 1000);
}
if(event.target.nodeName === 'LI') {
// Let's flip the cards and have a look
if(event.target.classList.contains('match') ||
event.target.classList.contains('open') ||
event.target.classList.contains('show')) {
} else {
event.target.classList.add('open', 'show');
openCards.push(event.target);
if(openCards.length === 2) {
Basically here, after two cards are open, I don't want the cards in the deck clicked until they are processed.
+ 4
here your click do two things. you should separate them.
your trigger timer should be one single named function and be remove with Biraj's way.
for the rest, put it as one anonymous function, only the outmost if else is checking whether openCards length. Your classList statements should be in the code block when openCards has less than two elements.
you'll also need a setTimeout for your code block where openCards does have two elements.
+ 4
Paul K Sadler Sorry for going MIA on you. I got slammed with work.
I reviewed your followup and now have a better understanding of what you were asking.
It sounds like you've gotten several people to help... so I'm glad that worked out! 👍
+ 4
If it hasn't been suggested yet, maybe add the 'disabled' attribute after the event has fired.
Here's a quick example using jquery.
https://code.sololearn.com/Wl7eqc5ttR8t/?ref=app
The disabled attribute will suffice, but removing the click event as well just to show you what that looks like. Doing one or the other works.
+ 4
Paul K Sadler no prob... it'll work on other elements too. Just do the .off instead of disabling. Mind you, I really should stop using jQuery lol
+ 3
David Carroll Biraj Gordon Thank you for all the input, this is Awesome! I like @Biraj suggestion on the CSS. I am going to add a class to disallow the pointer on the deck using a class to set the pointer event to none. Reading about it on MDN. Thanks again guys this was very helpful. [EDIT] trying to type on the phone in that tiny box at the bottom is a challenge.
+ 3
Biraj That worked! After talking myself through how I wanted it to work once two cards were clicked I realized I could just set it on the deck.
The result was far more elegant than what I was doing.
if(openCards.length === 2) { deck.classList.add('no-click');
...
The CSS is
.no-click {
pointer-events: none;
}
+ 3
Thanks again everyone! 😁
+ 3
David Carroll I wonder if the issue with
event.preventDefault();
was being on the child rather than the parent?
What I read on MDN seemed to make me think it would stop the bubble up, but that didn't happen. I will read some more, because, like you, I thought that would work.
+ 3
Calviղ that's cool, I am going to try that out.
+ 3
David Carroll I understand, thanks for following up.
+ 3
Mike thanks for that and the demo. I'm using a ul/li in this case and not a button. But I will keep it in mind for future use. Thanks again!
+ 2
David Carroll I did, but that did not do the trick. Using flags and if's made it work and so did pulling the event listener. Just seemed convoluted.
+ 2
David Carroll Thanks, what you all came up with is working, so I would rather call on your time when I am stuck 🙃