Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is jQuery select event listener triggering multiple times?

Please run this sample in Google Chrome browser.

Stack Snippet

$(function() {
  $(":input").select(function() {
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $(":input").select();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text">
<div></div>

Here why jQuery select event listener is triggering multiple times? Does anyone know the reason behind this? And is there any workaround solution for this without using timeout?

like image 675
John R Avatar asked Mar 29 '16 12:03

John R


People also ask

Why is this jQuery Ajax click event firing multiple times?

They're attached to buttons for placing a bet, and it works fine for placing a bet on the first hand during a game (firing only once); but in betting for the second hand, it fires the click event twice each time a bet or place bet button is pressed (so twice the correct amount is bet for each press).

How do I get rid of addEventListener?

Event listeners can also be removed by passing an AbortSignal to an addEventListener() and then later calling abort() on the controller owning the signal.

What is unbind in jQuery?

jQuery unbind() Method The unbind() method removes event handlers from selected elements. This method can remove all or selected event handlers, or stop specified functions from running when the event occurs. This method can also unbind event handlers using an event object.

Can you have multiple event listeners?

We can add multiple event listeners for different events on the same element. One will not replace or overwrite another. In the example above we add two extra events to the 'button' element, mouseover and mouseout.


2 Answers

The $(":input") selector is selecting the button too, so it causes recursion. Either use just $("input"), or $(":input:not(button)").

I noticed when the three events are fired, the first doesn't have originalEvent property, so we definitely can dismiss it, and the second two has very similar (however not identical) timestamp. You can store the last timestamp in some variable and in event listener compare it with the event's timestamp. If the rounded values of these two are the same, you can dismiss this event.

$(function() {
  var lastTimeStamp;
  $("input").select(function(event) {
    if (!event.originalEvent ||
        lastTimeStamp === Math.round(event.timeStamp)) return;
    lastTimeStamp = Math.round(event.timeStamp);
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $("input").select();
  });
});

See updated JS Fiddle.

like image 190
Michał Perłakowski Avatar answered Sep 29 '22 20:09

Michał Perłakowski


It appears the issue is a combination of:

  • the :input selector gets the input and the button, hence multiple events triggered.
  • even when using just input as the selector there is some odd event propagation being triggered on related elements which is raising the select event handler multiple times.

To avoid both of the above, use input as the selector and also use preventDefault() in the event handler. stopPropagation() may also be required, depending on your HTML stucture.

$(function() {
    $('input').select(function(e) {
        // e.stopPropagation(); // optional
        e.preventDefault();
        $('#message').text("Something was selected").show().fadeOut(1000);
        console.log('Selected');
    });

    $('button').click(function() {
        $('input').select();
    });
});

Working example

like image 26
Rory McCrossan Avatar answered Sep 29 '22 20:09

Rory McCrossan