Opened 15 years ago
Closed 9 years ago
#2252 closed bug (fixed)
Setting select value via val() shows error in IE6
Reported by: | zaadjis | Owned by: | flesler |
---|---|---|---|
Priority: | low | Milestone: | 1.11 |
Component: | attributes | Version: | 1.4.4 |
Keywords: | ie6, select, val | Cc: | |
Blocked by: | Blocking: |
Description
When a select element is filled (dynamicly) with options and then one tries to set a selected option an error is thrown in IE6: "Could not set the selected property. Unspecified error.".
This seems to be some timing issue, because inserting some delay (timeout, alert, etc.) before the val() call, the error doesn't occur.
Attachments (3)
Change History (20)
Changed 15 years ago by
comment:1 Changed 15 years ago by
I tried your patch, and while it works for me using your test case, it still core-dumps the browser on my app. I'll try to distill mine into a minimal test case at some point, but it'll be difficult. The function that's killing things looks like this:
// select is a DOM element, versions is an array of strings, selectedOption is a string function fillSelect(select, versions, selectedOption) { // Map each version string to a DOM element var newOptions = $.map(versions, function(version, i) { return $("<option></option>") .val(version) .text(version) .get(0); }); $(select).append($(newOptions)) .val(selectedOption); }
I'm not sure if it matters, but my page is in "quirks" mode.
comment:2 Changed 15 years ago by
Milestone: | 1.2.3 → 1.2.4 |
---|---|
Owner: | set to flesler |
Status: | new → assigned |
I really don't get this.
You do .val(2) and there's no option with value="2". Don't you mean $('select').attr('selectedIndex',2) ?
That will surely work with the modified recently .attr().
If that was the case, please close the ticket as invalid.
comment:3 Changed 15 years ago by
Milestone: | 1.2.4 → 1.3 |
---|---|
Resolution: | → invalid |
Status: | assigned → closed |
Ok, the previous comment was wrong. IMO, if a delay is need for a specific case, then you need to provide it yourself. There's no need to delay every call to value, and doing that, would partially ruin the behavior for the rest.
So.. if necessary, you'll need to add a delay yourself.
comment:4 Changed 15 years ago by
Resolution: | invalid |
---|---|
Status: | closed → reopened |
Here's a super-minimal repro (it doesn't even use jQuery, but explains where the bug in IE6 is):
http://brh.numbera.com/experiments/browserdemos/ie6-adding-options.html
This shows that accessing the .childNodes property of a select element after adding new options to it, then setting the .selected property of one of the added options, will cause an error in IE6. Since .val() loops through childNodes before it sets .selected on one of the elements, it will always trigger this bug when used to select newly-appended options. zaadjis was simply pointing out that if you put the .selected in a setTimeout, the error won't occur, probably because IE needs to have control handed back to the browser for it to do some internal re-balancing.
I'm not sure how this could be fixed in general, but it is the sort of browser bug that I like jQuery to isolate me from.
comment:5 Changed 15 years ago by
Hm, actually, I found that if you wrap setting selected
in a try/catch and then throw away the exception, the option gets selected just fine. Maybe that's something to try.
Also, I tried doing: $(select).setAttribute('selectedIndex', 2)
using jQuery 1.2.6, and all I got was "Error: Object doesn't support this property or method", which doesn't help.
comment:6 Changed 15 years ago by
OK, trying zaadjis' patch works too - if you never touch selected
and instead use option.setAttribute('selected', true)
, there's no error. Seems like his patch is the best bet.
I also realized I had made a mistake in my last post trying to use setAttribute
instead of attr
. However, that still fails due to a closely related IE6 bug that I noticed which prevents you from setting selectedIndex
to the index of any newly created option
. It doesn't throw an error, it just doesn't work.
comment:7 Changed 14 years ago by
I've tried the setAttribute
and try/catch
patches and there is a problem: If I query the value just after being set, it still shows the old value.
After an alert or timeout the value is correctly refreshed.
comment:9 Changed 13 years ago by
Resolution: | → worksforme |
---|---|
Status: | reopened → closed |
I added the following test and it does not fail in IE:
jQuery("#select1").append("<option value='4'>four</option>"); jQuery("#select1").val(valueObj( 4 )); equals( jQuery("#select1").val(), "4", "Should be possible to set the val() to a newly created option" );
I'm assuming this bug is resolved. If you can still reproduce, please open with more details.
comment:10 Changed 13 years ago by
Resolution: | worksforme |
---|---|
Status: | closed → reopened |
This bug only manifests in IE6, on combination with execution at the "ready" event.
Example code:
<html> <head>
<script type="text/javascript" src="jquery-1.3.2.js"></script> <script type="text/javascript">
$(document).ready(function(){
init(); (A)
});
function init() {
$("#select1").append("<option value='3'>three</option>"); $("#select1").append("<option value='4'>four</option>"); $("#select1").append("<option value='5'>five</option>"); $("#select1").val(4);
alert("Should be 4: "+$("#select1").val());
}
</script> </head> <body>
<select id="select1"></select> <script type="text/javascript">
init(); (B)
</script>
</body> </html>
In the situation above, an exception ("Invalid index") will occur in jQuery-1.3.2.js, line 471:
jQuery( "option", this ).each(function(){
this.selected = (jQuery.inArray( this.value, values ) >= 0 jQuery.inArray( this.text, values ) >= 0);
});
When commenting line (A), and uncommenting line (B) in the example above, the code works correctly in IE6. But the "ready"-event is kind of essential for other stuff...
comment:11 Changed 13 years ago by
Please see my proposed fix. It seems to work well for single-select boxes. You can see that if you remove the redefinition of val(), things don't work, but no errors occur with my definition.
It uses the following interesting behaviours:
1) Changing the selectedIndex property (almost) works. It gets changed, but it is not shown as changed in the UI. However, the correct value is returned.
2) Trying to read the val() directly after doing the selectedIndex trick doesn't work. However, it is possible to use the selectedIndex as an index into the children() collection.
3) When IE has had a chance to do some idle stuff, the UI will update correctly in response to a selectedIndex change. Hence the call to window.setTimeout() (which will be a no-op if the bug didn't happen).
comment:12 Changed 12 years ago by
Component: | core → attributes |
---|---|
Keywords: | val added; val() removed |
Milestone: | 1.3 |
Priority: | trivial → low |
Resolution: | → patchwelcome |
Status: | reopened → closed |
Version: | 1.2.2 → 1.4.4 |
If someone can come up with a good patch for this, then we’ll take a look at it. Otherwise, since it is fixed in IE7+ and only occurs at the start of a page in IE6, it seems to me like there are more important battles to fight.
comment:13 Changed 12 years ago by
This IE6 problem does not just occurr when the page loads. It occurs any time you dynamically add options then try to select one.
comment:15 Changed 11 years ago by
This error still occurs in 1.7.1 and it does not only occur in ready-event but always when the <selection> tag is created dynamically...
so please reopen (with low priority).
comment:17 Changed 9 years ago by
Resolution: | patchwelcome |
---|---|
Status: | closed → reopened |
comment:18 Changed 9 years ago by
Milestone: | → 1.11 |
---|---|
Resolution: | → fixed |
Status: | reopened → closed |
Better late than never, fixed via https://github.com/jquery/jquery/commit/9fe051d57ea1dbe3697be32a4f21b08cbeb7d31f
Test case