.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();
    });
});