IE, generated select boxes, change event and WTF?!

While I was writing a bigger JS project, I needed a generated select box that was filled with its options from somewhere. I tested it in Opera 11 and all was good. Then I opened Firefox and it worked, as it did in Chromium.

Did you notice something?

Yeah – IE is still missing. So fired up IE – 11 even – and, almost needless to say: It did not work 🙁

Normally the select box should fire a change event as soon as an option finally gets selected. While this works as intended in this example taken from MSDN:

<!DOCTYPE html> <html>  <head>   <title>onchange Event Sample</title> </head>  <body>   <h1>onchange Event Sample</h1>   <form>     <p>Select a different option in the drop-down listbox to trigger the <strong>onchange</strong> event.</p> 		<select name="selTest" onchange="alert('Index: ' + this.selectedIndex + '\nValue: ' + this.options[this.selectedIndex].value)">       <option value="Books">Books</option>       <option value="Clothing">Clothing</option>       <option value="Housewares">Housewares</option>     </select>   </form> </body>  </html> 

… it definitely does not work when the whole thing is set up a bit more complex like this (short excerpt, imagine the missing rest):

===================================================== menu.js =====================================================   function Menu() {         this.init(); }  Menu.prototype =  {     menucontainer: null,          foregroundColor: null,     backgroundColor: null,          selector: null,     save: null,     clear: null,     about: null,          init: function()     {         var option, space, separator, color_width = 15, color_height = 15;          this.menucontainer = document.createElement("div");         this.menucontainer.className = 'gui';         this.menucontainer.id = 'gui';         this.menucontainer.id = "menucontainer_menu";         this.menucontainer.style.position = 'absolute';         this.menucontainer.style.top = '0px';                  this.selector = document.createElement("select");          for (i = 0; i < BRUSHES.length; i++)         {             option = document.createElement("option");             option.id = i;             option.value = BRUSHES[i];             option.text = BRUSHES[i].toUpperCase();             this.selector.appendChild(option);         }         this.menucontainer.appendChild(this.selector);     } } ========================================== main.js  ========================================== var brush, BRUSHES = ["foo", "bar",  "", "baz", "bam"];  menu = new Menu(); menu.selector.onchange = onMenuSelectorChange;  /* ...  */ if (!brush)	{ 	brush = new window[BRUSHES[0]](context); }  /* ... */ function onMenuSelectorChange() {     if (BRUSHES[menu.selector.selectedIndex] == "")         return;      brush.destroy();     brush = new window[BRUSHES[menu.selector.selectedIndex]](context);      window.location.hash = BRUSHES[menu.selector.selectedIndex];     menu.selector.blur(); } 

So, what happens with IE here?

If the index was once set programatically, IE simply “forgets” to fire the change event, you can’t even select an option with the mouse. Opening the select box, moving to the option with the mouse and then pressing the [Enter] key surprisingly worked, so the select box was created and the event listener was attached to the select box. It seems that the select box only has a slight focus problem if you want to select something by using the mouse only. In the end it came down to a missing focus problem on the select element.

Solution

I added some extra code for IE – yes I used browser sniffing because I don’t know how to detect b0rked behavior of a browser.

menu = new Menu(); if(navigator.userAgent.indexOf(' MSIE ') > -1 || navigator.userAgent.indexOf(' Trident/') > -1){ menu.selector.onclick = (function() {     this.blur();     this.focus();   });  } menu.selector.onchange = onMenuSelectorChange; 

Not perfect, but it works – which is good enough for me now. If anyone has a better solution: I am willing to learn, please post it in the comments. Thank You!

PS: No, I don’t know what the MS devs were smoking when they implemented that behavior …