2

If I have an event listener that listens for multiple events, is it possible to make it only trigger once per user action, even though the single user action spawns multiple events? Alternatively is there a way to determine if that handler has already been fired for the user action?

For example, in this jsfiddle (snippet below) the handler is called once each time I type in the text box (input) and once when I leave the text box (change).

When I click the checkbox, however, it is called twice (once for input and once for change). Although there are various ways I can mitigate this (for example by seeing what type of input the event came from and if it's a checkbox ignoring the 'input' event EDIT: or by changing the handler to only listen for the input event, which would mean the handler is called only once for this specific example, but doesn't answer my question), I'm wondering if there is a built in way to prevent multiple calls to the handler when it comes from a single user action.

$('input').on('input change', function(e) {
$('#events').append('triggered by '+$(e.target).attr('id')+'<br>');
});
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div>
Text input: <input type="text" id="text-input">
</div>

<div>
Checkbox: <input type="checkbox" id="checkbox-input">
</div>

<div>
  <input type="button" value="Clear" onclick="$('#events').html('');">
</div>
<div id="events">
</div>
Ben Holness
  • 2,457
  • 3
  • 28
  • 49
  • 1
    Just use the `input` event only. It covers everything that `change` does, and more. Also note that `$(e.target).attr('id')` can be changed to just `e.target.id` – Rory McCrossan Mar 20 '21 at 19:34
  • how about ``` $('input').change(function(e) { $('#events').append('triggered by '+$(e.target).attr('id')+'
    '); }); ```
    – Biki Maharjan Mar 20 '21 at 19:40
  • The post uses a specific example to illustrate my question. Another case is when the multiple events are `input click` and the input types are a button and a checkbox - then the `input` event is not fired on the click of the button. I am aware of various ways to mitigate the problem, as per my question, I'm wondering if there is a built in way to prevent the multiple calls. – Ben Holness Mar 20 '21 at 19:40
  • 1
    In which case you'd need to attach the events individually to each specific element which needs to listen for them. Unfortunately there's no built in method/syntax to avoid the event duplication issue in the question. – Rory McCrossan Mar 20 '21 at 19:53

1 Answers1

0

This is a conceptual solution only and I'm not sure of it's practicality in production.

With that disclaimer, you could store something in the element's data with a timer to reset it. For the case of a checkbox not triggering both chaange and input events this works fine. For a text input the scenario is different since the change event doesn't get triggered until the element is unfocused whereas the input event gets triggered for every key, paste or cut.

$('input').on('input change', (e) => {
   const $el = $(e.currentTarget),
         prevEvent = $el.data('prevEvent');
   if(prevEvent){
      e.stopPropagation();
      e.preventDefault();
   }else{
      $el.data('prevEvent', true);
      setTimeout(()=> $el.data('prevEvent', false), 200)
      $('#events').append(e.type + 'event triggered on '+e.currentTarget.id+'<br>');
   }
         

});
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div>
Text input: <input type="text" id="text-input">
</div>

<div>
Checkbox: <input type="checkbox" id="checkbox-input">
</div>

<div>
  <input type="button" value="Clear" onclick="$('#events').html('');">
</div>
<div id="events">
</div>
charlietfl
  • 170,828
  • 13
  • 121
  • 150