views:

304

answers:

1

Background: Our web app uses the jquery.constrain.js plugin to handle data entry in some text boxes, to only allow valid characters to be added. This plugin allows various constraints upon the data, using regular expressions, whitelist/blacklist characters, etc. Until today, we were running the 1.0 release of this plugin, unmodified.

I noticed a few days ago that some of the text boxes still allowed invalid data entry. For example, a numeric-only textbox allowed alpha characters, etc. It also displayed a javascript error "Object doesn't support this property or method". I tracked it down to the following function in the jquery.constrain plugin.

    function match(item, input, e) {
        var arr = item.chars.split("");
        for (var i in arr) {
            var token = arr[i];
            if (token.charCodeAt(0) == e.which) {
                return true;
            }
        }
        if (item.regex) {
            var re = new RegExp(item.regex);
            if (re.test(String.fromCharCode(e.which))) {
                return true;
            }
        }

        return false;
    };

Debugging through this block of code, I determined the following:

  • item is an object with two string properties: chars and regex
  • item.chars is an empty string ("") at the time of failure.
  • arr, the result of item.chars.split("") is, as expected, an empty array.

Here's where it's weird. Even though arr is an empty array, the for loop assigns a valid value to i. The value is "remove". So we drop into the loop. token is obviously null, because arr["remove"] is null. So token.charCodeAt(0) throws.

I corrected the error by adding an if statement around the for loop, as follows:

        if (arr.length > 0) {
            for (var i in arr) {
                var token = arr[i];
                if (token.charCodeAt(0) == e.which) {
                    return true;
                }
            }
        }

However, I'm completely baffled as to why this was even necessary - is this an IE bug, a bug in the plugin, or am I just holding my breath wrong when I compile the app?

+1  A: 

You should never use for(i in arr) to loop over Arrays. If scripts add methods to the Array prototype these too will be iterated using the for(i in arr) loop. This is probably what is causing your errors. You probably have added a script that modifies the Array.prototype chain.

Also read here under "Why you should stop using for…in to iterate (or never take it up)"
http://www.prototypejs.org/api/array

Pim Jager
Yep, that was it. JQuery modifies the Array.prototype, and then we added some more to it. I'll let the plugin author know, and fix our local version as well.
GalacticCowboy