jQuery and the Select Element Change Event

This is one of those "Gaaah, arrrg" types of things, mainly because I didn't that I didn't know what I was looking for.

I had a multi-select box on a page whose contents were being added and removed by clicking on other things on the page. The client then came back and asked for an auto-preview function for the data that the form would return when submitted. Easy enough, I thought. There were several reasons why I could not simply use jQuery's serialize() method, so I had to go about constructing the URL string on my own, and started using the change() method on all of the elements I could. Then I got to the multi-select box. Selects don't respond to the change event the same way other elements do (for good reasons), but in order to construct my URL string, I needed the current values of the box, whether they were selected or not.

After much head banging and just a few swear words trying to think up how I should Google this particular problem, it occurred to me that I was programmatically adding DOM elements, and that I needed to be paying attention to DOM changes below the select element, not the element or it's children themselves.

So, in brief (more for my use, I imagine, than anyone else's), here's how I addressed the problem:

  // Pay attention to addition of options to select
  jQuery(document).delegate('.multiselect_sel', 'DOMNodeInserted', function(){
    setTimeout("autoupdate()", 100);
  });

  // Pay attention to removal of options from select
  jQuery(document).delegate('.multiselect_sel', 'DOMNodeRemoved', function(){
    setTimeout("autoupdate()", 100);
  });

Note that you'll need to utilize the appropriate selector for your SELECT element as the first argument to the delegate method; I've found myself using the Drupal Multiselect plugin often recently and am leaving what's there for my notes. ;) Also, please note that this does not work for IE 7, 8. DOM Mutexes and Mutex events aren't registered in MSHTML in those versions of the browser. The timeout is necessary, at least for Chrome and Firefox, as the event is fired as the DOM Node is being inserted or removed. This can cause over-zealous javascript engines to still catch the "previous" value. 100ms should be enough to allow the event to finalize and not be a distraction (i.e. "hang") to the user.

javascript
jQuery