textpattern.changeType = function(elem, type)
{
    if (elem.prop('type') === type) {
        // Already the correct type.
        return elem;
    }

    try {
        // May fail if browser prevents it.
        return elem.prop('type', type);
    } catch(e) {
        // Create the element by hand.
        // Clone it via a div (jQuery has no html() method for an element).
        var html = $("<div>").append(elem.clone()).html();

        // Match existing attributes of type=text or type="text".
        var regex = /type=(\")?([^\"\s]+)(\")?/;

        // If no match, add the type attribute to the end; otherwise, replace it.
        var tmp = $(html.match(regex) == null ?
            html.replace(">", ' type="' + type + '">') :
            html.replace(regex, 'type="' + type + '"'));

        // Copy data from old element.
        tmp.data('type', elem.data('type'));
        var events = elem.data('events');
        var cb = function(events) {
            return function() {
                // Re-bind all prior events.
                for(var idx in events) {
                    var ydx = events[idx];

                    for(var jdx in ydx) {
                        tmp.bind(idx, ydx[jdx].handler);
                    }
                }
            }
        }(events);

        elem.replaceWith(tmp);

        // Wait a smidge before firing callback.
        setTimeout(cb, 10);

        return tmp;
    }
}
The product does not require that users should have strong passwords, which makes it easier for attackers to compromise user accounts.