6

I want to compare a variable with a select -> option -> text selected in order to change the "selected" attrib, here is my code, it works but I think is not the best way to write it, excuse my English, I used google translate for help hehehehe :

var lista = 'example 1'; 
$("#id option").each(function(){
  if($(this).text() == lista){
    $(this).attr('selected','selected');
  }
});

here's the html:

<select id="id" >
  <option value="0" >example 1</option>
  <option value="1" >example 2</option>
</select>

here's a few attempts

$('#id option:eq("'+lista+'")').attr('selected','selected')

$("#id option[text='"+lista+"']").attr('selected','selected')
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
kakomerengue
  • 63
  • 1
  • 3

5 Answers5

7

Instead of looping through each, you can try this:

var lista = 'example 1'; 
$('#id option:contains(' + lista + ')').attr('selected', true);

or

$('#id option:[text="' + lista + '"]').attr('selected', true);

Works just as well. It just depends if your variable lista will need to be an exact match or just a partial one.

Victor
  • 4,721
  • 1
  • 26
  • 31
  • Second option is perfect, i will need to be exactly match, i think that I was pretty close hehehee – kakomerengue Feb 15 '11 at 20:55
  • @Victor Are you sure? :) I don't know why, but the code works only if the colon is present ... See here: http://jsfiddle.net/YbfqZ/1/ – Šime Vidas Feb 15 '11 at 21:01
  • @Victor Are you saying that you accidentally placed the colon at that position, only to find out that it only works that way? That is hilarious `:)` – Šime Vidas Feb 15 '11 at 21:09
  • The reason for that behavior is that your colon breaks the selector for `querySelectorAll` because it isn't valid. As such, it defaults to Sizzle, which will tolerate the colon, even though it technically isn't supported (which means it could break in the future). I'm guessing Sizzle will check for both *attributes* and *properties*. As such, it won't find a `text` attribute, but it will find the `text` property (as the one used in my answer). – user113716 Feb 15 '11 at 21:12
  • ...borrowing the fiddle from @Šime Vidas, [here's an example](http://jsfiddle.net/YbfqZ/3/) that demonstrates that Sizzle will match a property instead of just an attribute with its `attribute-equals` selector. – user113716 Feb 15 '11 at 21:16
  • @Andy Question is here: http://stackoverflow.com/questions/5009572/jquery-selector – Šime Vidas Feb 15 '11 at 21:28
  • This helped me as well. Why such complicated code for such a simple thing ('init) – Robert Johnstone Apr 19 '11 at 12:23
  • Can i get the option that begins with something? – Piyush Mattoo Mar 07 '12 at 01:05
2

There's nothing wrong with what you have, jQuery will be doing more-or-less the same under the hood.

You could use filter() if you want to chain it all together:

var lista = 'example 1'; 
$('#id option').filter(function () { 
    return $(this).text() == lista; 
})[0].selected = true;

:contains might work for you but it works like a wildcard match, e.g. cat would match category:

var lista = 'example 1'; 
$('#id option:contains(' + lista + ')')[0].selected = true;
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • I need a case insensitive contains. Is this possible? – Kees C. Bakker May 04 '11 at 10:34
  • @Kees: you would have to go the `filter()` route and use a regular expression [`test()`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp/test) with the `i` modifier. If you get stuck, ask a question; that sort of thing will get you an answer in a matter of minutes. – Andy E May 04 '11 at 11:19
  • Yeah, I used the filter. Thanks for the suggestion! – Kees C. Bakker May 04 '11 at 11:51
2

Your way is pretty efficient, but could be made a little more so like this:

var lista = 'example 1'; 
$("#id option").each(function(){
    if( this.text == lista ){
      this.selected = true;
      return false;
    }
});

This uses native properties so it will be faster.

  • .text property gives the text content of the <option> element

  • .selected sets the selected property

  • return false; will break the loop once one is selected, so it doesn't needlessly continue

user113716
  • 318,772
  • 63
  • 451
  • 440
1

This should work:

$("#id option").attr('selected', function() {
    return this.innerHTML === lista;
});
Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
0

I'm probably too late.

var lista = 'example 1';
$('#id option[text="' + lista + '"]').attr('selected', true);

This is about 97% faster then

var lista = 'example 1';
$('#id option:contains("' + lista + '")').attr('selected', true);

check performance log at http://jsperf.com/selector-performance-00000

Hussein
  • 42,480
  • 25
  • 113
  • 143
  • While you're right that the first selector will generally perform better, part of the reason for the performance difference is likely that the `[text=...]` version isn't matching any elements if your browser supports `querySelectorAll`. This is because `querySelectorAll` will look for a `text` *attribute*, which the `option` elements don't have. – user113716 Feb 15 '11 at 21:50