+4

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?

5/9/2019 1:41:40 PM

Paul K Sadler

23 Answers

New Answer

+7

HTML:- <button id="oneTime">Click</button> JS:- var btn = document.getElementById("oneTime"); btn.addEventListener("click", fn); function fn() { console.log("clicked"); // if you want to remove event listener btn.removeEventListener("click", fn); // if you don't want to remove it btn.disabled = true; // using css (this also don't removes listener) btn.style.pointerEvents = "none"; } If you use removeEventListener, it will just remove that corresponding event with that particular function whereas disable will also prevent the element to be listened to some other event.

+6

Have you tried using the line below? event.preventDefault(); Where event is provided as an argument in your click handler.

+6

const lis = document.querySelectorAll("li"); // while processing lis.forEach(li => li.style.pointerEvents = "none"; // after processing is done lis.forEach(li => li.style.pointerEvents = "all";

+6

You're welcome Paul K Sadler. I'll be waiting for your code.

+5

Hmm... Something isn't right about that. Can you share the code?

+5

In addEventListener, add an option, object 'once' set to true, would make the event only fire once. target.addEventListener('click', eventMethod, { once: true } );

+5

https://code.sololearn.com/W139LRjWs4gh/?ref=app

+4

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. 😉

+3

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

+3

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.

+3

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.

+3

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! 👍

+3

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.

+3

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

+2

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.

+2

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; }

+2

Thanks again everyone! 😁

+2

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.

+2

Calviղ that's cool, I am going to try that out.

+2

David Carroll I understand, thanks for following up.