Why is trigger() triggering the select() handler 3 times?

$("#select-test").select(function(e){
    //console.log(e)
    console.log("selected")
})

$("#newTest").click(()=> {
    $("#select-test").trigger("select")
})
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>

<button id="newTest">TEST ME</button>
<input type="text", id="select-test" value="some">

This is in Chrome, in Firefox, it’s triggered twice.

I read this JQuery – Why does Trigger method call it three times? thread which talked about this issue, but honestly I couldn’t understand it.

Somebody said:

we have 1 isTrigger and 2 simple select events.

What is that mean? 2 simple select events? Where? We only have 1 select event, where’s the second one?

The best answer says that this happens because of bubbling, but… how? I mean, where’s the bubbling? I don’t see how this explain the event handler being triggered 3 times. Bubbling is when you target a child element, and the parent with the same handler is triggered too, but that’s not what we have here. We only have ONE select handler, so .. where’s the bubbling? And why is it triggered twice in Firefox?

Answer

A select needs a prevent default if you wish to stop it at some point. the select event isn’t the focus event, when a field becomes in focus. The select event gets fired when something is selected.

When you trigger the select event with the below code and have the browser tools open, you will see that the debugger shows the below code. When you select call stack -> dispatch, you can see what triggered the event and see that the third event is triggered by a native event.

call stack

var count = 0;
$("#select-test").select(function(e){
    if(count == 2) {
       debugger;
    }
    count++;
    console.log("selected")
})

$("#newTest").click(()=> {
    count = 0
    $("#select-test").trigger("select")
})
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>

<button id="newTest">TEST ME</button>
<input type="text", id="select-test" value="some">

If we look at the documentation for select we see this:

In addition, the default select action on the field will be fired, so the entire text field will be selected.

So what happens is:

  1. You trigger select -> jquery fires select to all event handlers
  2. jQuery focusses the field, which triggers an automatic browser select all text, which triggers the select event.
  3. Jquery selects all text in the field, native select is triggered, which is wrapped by jquery and then passed on to the handlers.

To stop any of these steps from happening you can use event.preventDefault() on the first time select is triggered, this will have the side event of not selecting the text.

Rather than using select I suggest you use focus() unless you really need to know what text is selected every time a select is triggered.