.change() with checkboxes and select multiples
Fix for IE not firing the change event for certain inputs (namely, checkboxes and multiple select lists).
HTML
<form>
<h4>Checkboxes</h4>
<p>
<label class="checkbox"><input name="checkbox" type="checkbox" value="1" />1</label>
<label class="checkbox"><input name="checkbox" type="checkbox" value="2" />2</label>
<label class="checkbox"><input name="checkbox" type="checkbox" value="3" />3</label>
</p>
<input name="input" type="input"/>
<h4>Select Multiples</h4>
<p>
<select name="multi-select" multiple="multiple">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</p>
</form>
<ul id="changed"></ul>
CSS
#changed {
color: #ff0000;
}
JavaScript
// IE doesn't fire the change event for certain inputs (namely, checkboxes and multiple select lists).
// To get around this, you can use the "propertychange" event instead of "change":
/**
* Fixes binding the "change" event to checkboxes and select[type=multiple]
* for Internet Explorer. See: https://gist.github.com/770449
*
* @param {jQuery|Element|Element[]} elements
* The DOM Element we wish to bind the event to.
*
* @param {String} eventType
* The name of the event we want to bind to.
*
* @param {function} callback
* The function to execute when the event is triggered
*/
var bind = function(elements, eventType, callback) {
var $elements = $(elements),
rValidProps = /^(checked|selectedIndex)$/,
hasPropertyChange = ("onpropertychange" in document.body);
if (!$elements.length || typeof eventType !== "string") {
return $elements;
}
if (eventType !== "change") {
return $elements.bind(eventType, callback);
}
$elements.each(function() {
eventType = hasPropertyChange && (this.type === "checkbox" || this.tagName.toLowerCase() === "select" && this.multiple) ? "propertychange" : "change";
$(this).bind(eventType, function(e) {
if (e.type !== "propertychange" || rValidProps.test(window.event.propertyName)) {
callback.call(this, e);
}
});
});
};
var $li = $("<li>changed</li>");
bind($(":input"), "change", function() {
var $item = $li.clone();
$("#changed").append($item);
$item.fadeTo(1000, 0, function() {
$(this).remove();
});
});