Matt said:
Detecting the problem would surely be less efficient than simply
accessing a property, when the latter works just fine.
It works, but should it?
You noticed the problem in a page that was not completed (your linked
example). The OPTION's selected property was false before onload and
true after that. So if the OPTION's selected value were related to the
loaded state of the page, then it would make sense to check the state of
the page in the loop. However your observation was limited. The problem
is not related to the page state, but to whether the option is rendered.
You probably tried reading the selectedIndex, and then found that
worked, then tried to read the option.selected, and then found that
worked, and then figured that by simply accessing selectedIndex, the
selected property was achieved. Did I get that right?
Then you went to propose the workaround as a solution. That's a hack.
The problem was identified as: The default OPTION in a non-rendered
SELECT is false, when the option will be selected by default.
That is not a bug.
It would be a bug if, say, the option had the selected property set
before being rendered. For example, given a SELECT that is not yet part
of the dom, adding a selected OPTION to the SELECT should result in the
OPTION selected property being true.
var s = document.createElement("select");
s.options[0] = new Option("a", "a");
s.options[1] = new Option("a", "a", true, true); // Should be selected.
alert(s.options[1].selected); // Should be true.
Safari correctly elerts "true".
OTOH, if the browser is to make the determination of which option to set
the selected property on, you should not expect that information to be
available when the element is not in the DOM.
If we create two OPTIONs, set disabled=true on the first OPTION, the
second OPTION will be selected when the SELECT is rendered on the page.
There is no guarantee that the second OPTION will be selected before the
dom for that object is ready.
var s = document.createElement("select"),
o = new Option("a", "a"),
o2 = new Option("a", "a");
o.disabled = true;
s.add(o);
s.add(o2);
alert(o2.selected); // expect true or false.
To feature test the problem, create a SELECT, add an OPTION, and check
the OPTION's selected property. Save the result in a variable.
var s = document.createElement("select");
s.add(new Option("a"));
IS_NOT_DEFAULT_OPTION_IN_NONRENDRED_SELECTED = s.options[0].selected;
I suggest moving the workaround (and whatever comments may accompany)
with it and moved it out of the loop.
if(prop === "selected" && IS_NOTDEFAULT_OPTION_IN_NONRENDRED_NOTSELECTED) {
updateOptionSelected(elem);
}
function updateOptionSelected(elem) {
// If we're getting a false value, it may be that the option
// will be selected when fully rendered, but has not happened yet.
if(elem.selected === false) {
var selectedOption = elem.parentNode.options[s.selectedIndex];
selectedOption.selected = true;
}
}
Doesn't that make teh loop a lot clearer?
It will be a little slower in Safari but does not punish every browser
with that workaround.
It's not blind faith, it's tested and proven successful.
What does selectedIndex have to do with anything? It returns the
correct value. It's the <option> tag's 'selected' property that is
incorrect.
Accessign the selectedIndex is a hack. It "works" but by no guarantee of
any official or "de facto" standdard.
If you wait until the document is ready, then the problem goes away.
RIght, but your observation was limited. Based on what you observed,
checking isReady would seem like a sensible workaround. However, that
does not address the fact that the SELECT's DOM may not be ready.
It's a weird quirk, but it looks like you are just spewing "answers"
when you've never actually looked at the problem.
You provide a nonstandard workaround to get non-standard behavior
without looking closely enough at the problem. Your observations of the
problem are limited to "while the page is loading".
Your proposed workaround relies on an even bigger non-standard quirk. It
is possible that bigger quirk (your workaround) will not be present in
Safari 5 and the smaller quirk will remain. If and when that happens,
you're back to trying to figure out the problem.