views:

95

answers:

4

I'm trying to use a regular expression to capture the contents of all option values inside an HTML select element

For example, in:

<select name="test">
<option value="blah">one</option>
<option value="mehh">two</option>
<option value="rawr">three</option>
</select>

I'd like to capture one two and three into an array.

My current code is

var pages = responseDetails.responseText.match(/<select name="page" .+?>(?:\s*<option .+?>([^<]+)<\/option>)+\s*<\/select>/);

for (var c = 0; c<pages.length; c++) {
    alert(pages[c]);
}

But it only captures the last value, in this case, "three". How can I modify this to capture all of them?

Thanks!

+1  A: 

this is already done for you in the HTML DOM

var myselectoptions = document.getElementByName("test").options;

for (var i = 0; i <= myselectoptions.length; i ++) {
  alert(myselectoptions[i].text);
  alert(myselectoptions[i].value);
}

basically this code will capture the text and value in an array from the HTML Dom and alert each value out for you..

Here is a link for some documentation on select elements .options

John Hartsock
Unfortunately I cannot do that. The text I'm pulling from is results from a xmlhttprequest, not a dom object...
joey mueller
Actually you can stuff the results of your XHR into a div and get it parsed for you automatically. Sadly the code where I've done just this is not accessible to me right now so I can't C parsediv.innerHTML = XHRResult; var myOptions = parsediv.getElementByName("test").options;I'll try to find my working code in the morning and post it if it's still needed by then.
Hellion
couldnt you add it to the dom get what you need and then remove it. If you do this it will not render on the page
John Hartsock
Hellion, that sounds like a viable option. From your experience, was it performance intensive? I found a way to get this to work using two regular expressions, one non-global and one global, but yours idea sounds interesting too.
joey mueller
Well, my experience was not in a performance-critical area, so I can't really say for certain, but I don't believe it should be any worse than other DOM manipulations.
Hellion
`var container = document.createElement("div");container.innerHTML = xhr_response_text; div.style.display='hidden'; document.body.appendChild(div);` and then the above
Justin Johnson
+6  A: 

Even if you have only the HTML text, you can still use the DOM to parse it, for example, using a temporary element to inject the HTML, and traverse the options:

function extractOptions(html) {
  var el = document.createElement('div'), // temporary element
      result = [], select, option;

  el.innerHTML = html; // inject html
  select = el.getElementsByTagName('select')[0]; // get the first select element

  for (var i = 0, n = select.options.length; i < n; i++) { // loop options
    option = select.options[i];
    result.push({value: option.value, text: option.innerHTML});
  }
  return result;
}

// assuming that text contains the HTML string as in your example

var options = extractOptions(text);

// [{"value":"blah","text":"one"},
//  {"value":"mehh","text":"two"},
//  {"value":"rawr","text":"three"}]

Check the above example here.

CMS
+1 Nothing better than using the right tool for the job.
Anurag
+1  A: 

Afaik there's no cross-browser way to do this with just regular expressions. However, here's a kind of wacky approach (bear with me for a minute of explanation).

JavaScript's String.replace method can accept a function as the replacement, instead of a format string. The function is evaluated for each match of the full regex, so you could (ab)use this feature to repeatedly do something arbitrary with each match. Here's an example that would add each select to an array:

var matches = [];
var selectPattern = /<option .+?>([^<]+)<\/option>/;
body.replace(selectPattern, function(match) {
    matches.push(match);
});

I think using a hidden DOM node would be preferable for this (see also) but sometimes an "alternative" approach is fun too :)

David Winslow
A: 

This is all about the submatch in javascript. For your string, regexp is simple

/>(\w+)</

Now we push submatches into an array,

var matches = [];
var str = '<option value="blah">one</option><option value="mehh">two</option><option value="rawr">three</option>';

var tmp;

do { 
    tmp = str;
    str = str.replace(/>(\w+)</,function($0,$1){
        matches.push($1);           
        return $0.replace($1,"");
    });

 } while(tmp!=str);

alert(matches);
unigg