Tuesday, December 21, 2010

Clear options in a MULTI-SELECT field without loops

If I've published anything that qualifies as a "tweet", this post does. Though I have been busy, it has been a while and I sorely miss blogging. With the holidays all around us, small posts make for published posts.

Perhaps I've never had to auto-select OPTION elements in a multi-SELECT field, but I discovered a simple method for doing so, that was worth noting.

I had a multi-select field and needed to select various options, based on the numeric indexes from another array. Before looping through the array of options (to select), I needed to ensure the form field had no previously selected options present.
Since the options property of a select field, is like an array, I first thought to iterate over them with a for-loop, but then I'd have two loops...

  // deselect all options
  for (var i = 0; select.options[i]; i++) {
    select.options[i].selected = 0;
  }
  // select the targeted options
  for (var i = 0, j = targets.length; i < j; i++) {
    select.options[targets[i]].selected = 1;
  }

I don't like looping through overlapping collections - such as select.options and then the list of target options... Maybe a nested loop? Well, that means even more wasted cycles, since the browser is processing the same array multiple times.

  // loop through all options
  for (var i = 0; select.options[i]; i++) {
    // deselect this option
    select.options[i].selected = 0;
    // loop through all targets
    for (var q = 0, z = targets.length; q < z; q++) {
      // if the option should be selected...
      if (i == targets[q]) {
        select.options[i].selected = 1;
        break; // exit this nested loop
      }
    }
  }

So that idea was out - if not, undesired. If your thinking cap is on, you've wondered aloud about the selectedIndex property of the select field. This index is mostly used with single-select fields (aka, the drop-down menu), to dynamically select an option. Happily, it works the same way for a multi-select field, with the added benefit of deselecting all other options.

  // select the first option
  select.selectedIndex = 0;
  // deselect the first option
  select.options[0].selected = 0;
  // select the targeted options
  for (var i = 0, j = targets.length; i < j; i++) {
    select.options[targets[i]].selected = 1;
  }

So we select the first option (doesn't matter which really), then immediately deselect it. Library authors would ensure there is a zero-indexed option to select-then-deselect, first. Also, I don't know if a repaint or redraw occurs when toggling active options - so you might hide it via css before doing all of this.Though we do loop through an array next (to select certain options), we avoid the initial/nested loop scenario. Pretty simple!

Yes, the solution takes less time than writing a blog post. I needed to get back in the swing of things (or I'd never blog again). If the new year is kind and time permits, I hope to blog about my next adventure into open-source this January!

Happy-everything all!

Share/Bookmark

No comments:

Post a Comment