views:

668

answers:

8

I have a <select>. Using JavaScript, I need to get a specific <option> from the list of options, and all I know is the value of the option. The option may or may not be selected.

Here's the catch: there are thousands of options and I need to do this a few hundred times in a loop. Right now I loop through the "options" array and look for the option I want. This is too slow (in the sense that on my very fast machine the browser locked up until I killed it after a few minutes).

Is there any faster way to do this? I'll take browser-specific ways, but of course a DOM-standard way would be nice.

A: 

With jQuery something like this could be faster:

$("#idselect option[value='yourval']")

http://docs.jquery.com/Selectors/attributeEquals#attributevalue

Davide Gualano
this is actually not faster at all it is just more compact. because you have just replaced a "for" loop for jQuery doing a "for" loop because it still has to go through each option of a select element and look for a specific value.
Nick Berardi
This makes sense, thanks for pointing it out.
Davide Gualano
A: 

no there isn't, you are doing it really the best way possible. The only other thing you can try for maybe a quicker look up is to give each of the options an ID tag so that you can look them up as a DOM object instead of looping through children of a DOM object.

Nick Berardi
A: 

You could loop through all the options once and put all items into an associative array. Then you can just look for myOptions[valueImLookingFor].

I haven't tested this and can't guarantee it will be faster/better. But it should get rid of all those loops.

Depending on your setup and needs you could also generate a javascript array on the client side and put it in the markup instead of (or in addition to) the select.

_Lasar
+2  A: 

I would suggest not having thousands of options in your select.

Perhaps you could structure your data differently a select with thousands of entries to me seems wrong.

Perhaps your app requires this but it would not be typical usage of this element.

Paul Whelan
Administrators control how many options there are in the <select>, not me. I'm just trying extreme cases to make sure that they are still performant, because some of our users are crazy. :-)
Max
Cool :) Best of luck
Paul Whelan
A: 

My suggestion would be to look at a framework/toolkit like Dojo and its way of selecting DOM nodes.

The toolkit irons out alot of browser inconsistencies and allows you select and manipulate DOM nodes quickly and easily.

philistyne
Yes but with this you have just traded parsing the DOM by your self in for an framework that parses the DOM in a more generalized way. If the original posters code is tight and not wasting any unnecessary operations it will beat the frameworks every time.
Nick Berardi
+5  A: 

I'd do it like this:

// first, build a reverse lookup
var optCount      = mySelect.options.length;
var reverseLookup = {};
for (var i = 0; i < optCount; i++)
{
  var option = mySelect.options[i];
  if (!reverseLookup[option.value])
  {
    // use an array to account for multiple options with the same value
    reverseLookup[option.value] = [];
  }
  // store a reference to the DOM element
  reverseLookup[option.value].push(option);
}

// then, use it to find the option
var foundOptions = reverseLookup["Value that you are looking for"];
if (foundOptions && foundOptions.length)
{
  alert(foundOptions[0].id);
}
Tomalak
wouldn't you need to make a small framework to just handle the hundreds of reverse lookups all on the page?
Nick Berardi
I'm going to do it by having a named array that stores the reverse lookups by the id of the field being looked up on, because all my fields have ids (which are unique by definition).
Max
I don't think you understood the code. Or I don't understand your objection. Can you clarify?
Tomalak
For those interested, you just helped me solve this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=463598 (with the solving code attached to it). Thanks! :-)
Max
Well, thank you for the flowers, as the German saying goes. ;-) Am I missing something essential in Nick Berardi's comment? Do you know what he means?
Tomalak
I think he means either that I need to do something to make it handle various different selects, or that I (fairly obviously) need to wrap the code in a function so that it becomes usable.
Max
Good. I took that for granted, and you did the same, obviously.
Tomalak
A: 

I would think that it may be an indicator that "thousands" of items in a select probably isn't the best user experience. Maybe you should consider trying to limit your dropdowns to several that narrow the results as a user selects them.

duckworth
A: 

This is Tomalak's answer with a minor speed tweak. You see a while loop that iterates down is faster than a for loop that iterates up. (I'm lazy so I won't provide the link.)

var i = mySelect.options.length - 1;
var reverseLookup = {};
while ( i >= 0 )
{
  var option = mySelect.options[i];
  if (!reverseLookup[option.value])
  {
    // use an array to account for multiple options with the same value
    reverseLookup[option.value] = [];
  }
  // store a reference to the DOM element
  reverseLookup[option.value].push(option);
  i--;
}

// then, use it to find the option
var foundOptions = reverseLookup["Value that you are looking for"];
if (foundOptions && foundOptions.length)
{
  alert(foundOptions[0].id);
}
Mr. Muskrat