views:

950

answers:

5

I have the following code:

var selected = $('#hiddenField').val().split(",");
...
if (selected.indexOf(id) > 0) {
   ... set value ...
}

I'm dynamically creating a CheckBoxList, and trying to remember the state of the checkboxes by putting the selected IDs into the hidden field.

I get an error stating that "Object doesn't support this property or method". My assumption is that selected is an array, which should support indexOf. Is that incorrect?

+3  A: 

Based on your error message, I'm assuming this is coming from Internet Explorer.

Surprise! Internet Explorer (including version 8) does not support indexOf for arrays.

Here is Firefox's implementation you can use:

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
Matt
@Matt: Thank you. I thought they'd implemented it in IE8, so went and did a quick experiement, and was pleasantly surprised to see it in IE7 as well. As you can guess, the experiment was flawed (I forgot to remove the reference to Prototype, which conveniently adds it if it's missing). Thanks again.
T.J. Crowder
+1  A: 

indexOf is not a standard a method on the Array object; but it is on the String object.

You're fine without using split;

if ($('#hiddenField').val().indexOf(id) > -1) {
  // set it
}

Be very careful with indexOf; a return of zero means that the character exists, and it's first occurance is the first character. It returns -1 if the string wasn't found.

If you still fancy using your array, you'll have to iterate over selected using a good old fashioned for loop.

Matt
Does not work for if you search for `1` and the value is `11,12,13`
Felix Kling
This produces a *very* different result than the OPs code.
Nick Craver
*"indexOf is not a standard a method on the Array object; but it is on the String object"* Almost true. It wasn't, until the 5th Edition ECMAScript specification came out late last year. Now it is, but of course, it's only implemented in browsers that had already gone with the array additions proposed years ago as part of the failed 3.1/4th edition processes, and browsers that have added new stuff recently. So not IE (yet), but yes Chrome, Firefox, and Safari. And wow does that workaround look like a maintenance failure waiting to happen.
T.J. Crowder
A: 
[].indexOf || (Array.prototype.indexOf = function(v,n){
  n = (n==null)?0:n; var m = this.length;
  for(var i = n; i < m; i++)
    if(this[i] == v)
       return i;
  return -1;
});
Ivo Sabev
A: 

.indexOf() is a string method. There is no such method for arrays. However if the IDs are totally distinct and are all of the same length (e.g. 3 digits) you can just do:

if ($('#hiddenField').val().indexOf(id) > -1) {
   ... set value ...
}

Of course it does not work if you have IDs like 128 and 12.

Felix Kling
No, it's also an array method. It was proposed *years* ago and implemented by nearly everyone, but of course there is a browser with significant (even now!) market share that doesn't support it: IE. It's now in the ECMAScript 5th edition specification (the first new official, completed specification in 11 years) and will hopefully percolate out since Microsoft is being more aggressive with updates now.
T.J. Crowder
@TJCrowder: Yeah I didn't know. I deleted the part because I already read your comment on the other answer ;) Thank you.
Felix Kling
I should clarify that the "even now" part of my comment above dated from when I thought they'd added it in IE7 and so only IE6 was the problem. They didn't. In fact, they still haven't gotten around to it in IE8, but they were involved in the spec process and are being more aggressive with updates to IE, so hopefully before too long...
T.J. Crowder
+7  A: 

There's an jQuery method to overcome the lack of indexOf(), you can use .inArray() instead:

var selected = $('#hiddenField').val().split(",");
if ($.inArray(id, selected) > -1) {
   ... set value ...
}

jQuery.inArray() exists for just this reason...if you're including jQuery already, no need to write the function again. Note: This actually returns a number, like indexOf() would.

Nick Craver
+1 seems to be the most reasonable answer :)
Felix Kling
This seems like it should work, for some reason it's not:>? line.id101>? selected{...} [0]: "101" length: 1>? $.inArray(line.id, selected)-1>
chris