4

I am seeing a weird behavior that when I use addEventListener, change event handler doesn't get fired on the select with display: none;. On the other hand, when I use jQuery, it does fire. What's the trick that allows jQuery to do that and how do I make it work in plain JavaScript?

Here is code that shows the example.

// This doesn't work
document.getElementById("notDisplayedSelect").addEventListener("change", function(e) {
  $("#output").text("When select is hidden events still fire: new value = " + $(this).val());
});

/*
// This works
$("#notDisplayedSelect").change(function (e) {
    $("#output").text("When select is hidden events still fire: new value = "+ $( this ).val());
}); 
*/

$("#setValue").click(function() {
  $("#notDisplayedSelect").val("3").trigger("change");
});
#notDisplayedSelect {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<select id="notDisplayedSelect">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>
<span id="output">I show selected value</span>
<button id="setValue">Select third option in the hidden select</button>
Shalom Aleichem
  • 2,987
  • 2
  • 22
  • 34
  • 1
    How can you change something that isn't visible? – Barmar May 22 '15 at 22:53
  • You can if you use `select` under the hood, while displaying a more complicated custom control. A good example is here: https://jqueryui.com/autocomplete/#combobox – Shalom Aleichem May 22 '15 at 22:54
  • 3
    It actually has nothing to do with the select element being hidden. If you remove the "display: none" from your jsFiddle, you'll notice no difference. The issue is with how you are firing the event, as others have mentioned below. Check here for how to fire the event properly: http://stackoverflow.com/questions/2490825/how-to-trigger-event-in-javascript – Vince May 22 '15 at 23:03
  • @VCode, I was able to make it work, thanks for suggestion. I'll accept your answer with `dispatchEvent` if you add it, since it was your idea. – Shalom Aleichem May 22 '15 at 23:18
  • @ShalomAleichem, by all means, if VCode puts an answer you should accept it. Otherwise,if there is an answer that helped you should accept it to guide future readers of this post – AmmarCSE May 22 '15 at 23:58
  • In fairness to @AmmarCSE, please accept his answer. It has the complete explanation of the problem and the correct solution already. No point in duplicating the work he's already done. Cheers! – Vince May 23 '15 at 00:23

2 Answers2

2

From jQuery trigger() docs

Any event handlers attached with .on() or one of its shortcut methods are triggered when the corresponding event occurs.

When you do

 $("#notDisplayedSelect").val("3").trigger("change");

only handlers attached with on() or change() will be triggered.

Apparently, this does not include handlers attached with the native

addEventListener("change", function (e) {...});

If you want to trigger the handler attached by native javascript, you can do

var event = new CustomEvent("change");
document.getElementById("notDisplayedSelect").dispatchEvent(event);

Update Workaround for above in IE

var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
document.getElementById("notDisplayedSelect").dispatchEvent(event);

DEMO

See How to trigger event in JavaScript?

Community
  • 1
  • 1
AmmarCSE
  • 30,079
  • 5
  • 45
  • 53
0

When you add a handler using jQuery, jQuery keeps information about this handler in its internal memory, in addition to adding it as a browser event listener. Then when you call trigger("change"), it just calls these handlers itself, rather than going through the browser.

In the browser, it makes no sense to change an invisible element, because the change event is associated with user interaction.

Barmar
  • 741,623
  • 53
  • 500
  • 612