0
votes

If you have a select:

<select id="sel">
  <option value="A">option A</option>
  <option value="B">option B</option>
  <option value="C">option C</option>
</select>

And you focus the select and then use the arrows to change the selected option, Firefox 30 will not trigger the "change" event on that select. This is how FF chose to implement the "change" event and they said it won't be fixed (it seems that this is what the standard says).

To try to get around this problem we can register the handler for both "change" and "keyup" events so we get the event even when the user uses the keyboard:

sel.addEventListener("change", handle_change); 
sel.addEventListener("keyup",  handle_change);

Except now we run into another bug http://jsfiddle.net/xLCNX/ that will appear when the user uses both the mouse and the keyboard to select options (use mouse to select option B, use keyboard to select option C, use again mouse to select option B - no change event will be triggered for this last action).

To solve this problem what you need to do is to put this in the event handler:

sel.value = sel.value;

Code from fiddle:

HTML:

<ol>
    <li>with the mouse(!) select option <b>B</b>. Event <b>change</b> is triggered.</li>
    <li>keyboard(!) press down arrow to select option <b>C</b>. Event <b>keyup</b> is triggered.</li>
    <li>with the mouse(!) select option <b>B</b> again. No event is triggered<br>
        Because we have selected the same option that was previously selected (<b>B</b>), there is no change so FF will not trigger a <b>change</b> event.<br>
        When we select option <b>C</b> with the keyboard, only the displayed option and the <b>select.value</b> changed to option <b>C</b>. Somehow, internally, FF kept the original value, option <b>B</b>. So when we selected back option <b>B</b> FF decides that nothing changed. The problem is the inconsistency between what FF knows is the current value and the other two values: the displayed value and the <b>select.value</b> value.
    </li>
</ol>
<select id="sel">
  <option value="A">option A</option>
  <option value="B">option B</option>
  <option value="C">option C</option>
</select>
<ol id="log"></ol>

JS:

var handle_change = function() {
  log.innerHTML += "<li>option " + sel.value + "</li>";
  //uncomment this to fix the bug
  //sel.value = sel.value;
};

var sel = document.getElementById("sel");
var log = document.getElementById("log");

sel.addEventListener("change", handle_change); 
sel.addEventListener("keyup",  handle_change); 
1
It works just fine for me in Firefox without that supposed fix. - Pointy
version? make sure you do it carefully as presented in the fiddle because if you click around the webpage the select will lose focus and then FF will correctly update the .value of the select. - GoTo
Firefox 30. I tab into the <select> element and then hit the up and down arrows, and the events are logged. - Pointy
as I said, read the text of the fiddle and do it exactlly as it is presented there . You must use mouse, arrow and mouse again. - GoTo
Oh I see - I still had the "keyup" handler enabled. The "change" event won't fire from keyboard interaction until the <select> element loses focus. I think that's actually a good, or at least arguably good, behavior. Using the keyboard to interact with a select would otherwise cause lots of unnecessary "change" events, because unlike with the mouse the only way to get to a selection is to keystroke through all intervening options. - Pointy

1 Answers

-1
votes

To solve this problem what you need to do is to put this in the event handler:

sel.value = sel.value;

This will set the internal value of the select kept by FF to the same value that is displayed in the select and which is also accessible on sel.value.