Jesse C Jesse C - 6 months ago 36
Javascript Question

Jquery only click once

I'm trying to disable a li click event after it has clicked the first time. Essentially to stop the array data being doubled. The click is working fine for each time. My current method doesn't appear to be working. I also need to disable the other li's from being clicked once the first one has :)

Thanks

JS code is:

$('#eventType ul li').click(function(e) {
e.preventDefault();
var value = $(this).attr('value');
answers.push(value);
// Below isn't working
$(this).click(function() {
return false;
});
console.log(answers);
});

Answer

jQuery is just JavaScript so you can easily add behaviors that you want

// basic jQuery plugin boilerplate
$.fn.once = function once(eventType, f) {
  // this = the selected elements
  return this.each(idx, elem) {
    // create reference to jQuery-wrapped elem
    var $elem = $(elem);
    // add event listener for eventType
    $elem.on(eventType, function(event) {
      // call the event handler
      return f(event);
      // remove the event handler
      $elem.off(eventType, f);
    });
  });
};

Usage would look like this

$('#eventType ul li').once('click', function(event) {
  console.log("you will only see this once");
});

However, this is obviously a common need so it exists in jQuery already. It's called $.one. As APIs grow, you may not know about the existence of such procedures. This answer exists to show you that you can use your brain to program the things that you want or that might be missing from a particular library. This lessens your dependence on the creator's of the lib to introduce the functionality you need.


EDIT

In a comment, you ask if the event handler can be disabled for all other LI elements after the first LI is clicked. The trouble here is that jQuery uses implicit iteration, which means that when you call $('li').on('click', ...), jQuery will bind an onclick event handler for each LI.

A better solution to this problem would be to use jQuery's event delegation

// only fire event handler for the first LI clicked
$('ul').one('click', 'li', function(event) {
  console.log($(this).text());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>one</li>
  <li>two</li>
  <li>three</li>
</ul>

This will delegate the event listener to the children LI, but once one of the LI is clicked, the event handler will be removed (because we delegated using the $.one procedure).

Try clicking one LI, you will see a message in the console. When you click the second LI, nothing will happen because the event handler was removed.

Comments