Closed Bug 395107 Opened 17 years ago Closed 17 years ago

[FIX]Not updating UI after selection attribute removed from option inside SELECT element

Categories

(Core :: DOM: Core & HTML, defect, P3)

defect

Tracking

()

RESOLVED FIXED
mozilla1.9beta2

People

(Reporter: cmtalbert, Assigned: bzbarsky)

References

Details

(Keywords: regression)

Attachments

(2 files, 3 obsolete files)

Attached file Test case demonstrating the problem (obsolete) —
The UI is not being updated after the selected attribute is removed from the second option via javascript.  You can verify by DOM Inspector that the attribute is no longer on the option element. However, the browser still renders the second option as selected in addition to the slection on the first option. This is a regression from Firefox 2.0.0.6.

I have attached a sample test case that demonstrates the bug.

Testing in IE 7, I verify that without any javascript activity, the second element is selected.  If I only enable the javascript that resets the selection to the first element, then the selection UI appears on the first element, but not the second element.  So, in IE's case, the removeAttribute("selected") on the second element is unneeded.  They are probably behaving this way because the select element does not have the "multiple" attribute set.

I wonder if the real issue here is that Firefox is ignoring the fact that the "mupltiple" attribute is not set on the "select" element.
I think we should try to do what IE does here.... Jonas, what do you think?
Flags: blocking1.9?
Keywords: regression
Blocks: 391994
No, I don't think we should do exactly what IE does. Just like IE maps textField.value to textField.getAttribute("value") it maps option.selected to option.getAttribute("selected"). In other words, when the user, or javascript, selects an option, the selected attribute is removed from all other options.

We've never done that, but rather use the DOM attribute only to initiate javascript properties.


It does look like we get our knickers in a knot here though. Both options appear to be selected which clearly is wrong. I don't agree with the reference though as the disabled attribute has an effect. I think we should behave as if the DOM looked like the selected attribute was set on both options, and the first option was disabled. Attaching a testcase.
So basically it looks like we're just rendering the first option wrong by rendering it as selected.
The problem seems to be on the DOM side, both options have their .selected set to true, which is probably why layout gets all confused.
Component: Layout: Form Controls → DOM: HTML
QA Contact: layout.form-controls → general
> I think we should behave as if the DOM looked like the selected attribute was
> set on both options

That would be fine, yes.  I wonder why that's not happening...

Jonas, do you want to dig, or should I?
Not sure that this bug is super important, though it is always scary with regressions...

But if you feel you have the time to work on it feel free to.
Well.  I don't have the time, in fact, but I did cause the regression, so I feel obligated to fix it...
Bug 401554 might be the same issue as this, and appears on a real live site.
Blocks: 401554
Attached patch Proposed fixSplinter Review
OK, let's try this.

The basic issue was that toggling .defaultSelected could change the value of .selected but that the nsHTMLSelectElement was never notified of the change.  This patch notifies it.  With this patch, adding an option to a <select> and then setting defaultSelected is equivalent to setting defaultSelected and then adding the option, as far as I can see.  Neither quite matches what the <select> would have looked like when parsed from scratch, but I think that's sorta the behavior we want, given the IE compat needs here.

In brief, the patch does these:
* Do the notifying described above before setting or unsetting the "selected"
  attribute on options.
* Change OnOptionSelected to not effectively call SetSelected on when an option
  with the "selected" attribute set is added to the <select>.  This makes
  setting defaultSelected to false actually work to unselect options which have
  never had SetSelected called.
* Make nsGenericElement::UnsetAttr call Before/AfterSetAttr, and remove some
  code that's no longer needed if we do that.  Fix the one SVG consumer that
  assumed that aValue is never null in BeforeSetAttr.
* Add tests

This patch fixes bug 401554 as well.
Assignee: nobody → bzbarsky
Attachment #279820 - Attachment is obsolete: true
Attachment #279821 - Attachment is obsolete: true
Attachment #283799 - Attachment is obsolete: true
Status: NEW → ASSIGNED
Attachment #286646 - Flags: superreview?(jonas)
Attachment #286646 - Flags: review?(jonas)
Priority: -- → P1
Summary: Not updating UI after selection attribute removed from option inside SELECT element → [FIX]Not updating UI after selection attribute removed from option inside SELECT element
Target Milestone: --- → mozilla1.9 M10
Flags: blocking1.9? → blocking1.9+
Jonas, I think this is risky enough that we should land it ASAP...
Ugh, I hate the options code :(. Does this patch really need to be this big? Bz, would be great if you could give an overview of what's happening, either here on on irc.
> Ugh, I hate the options code 

Amen.

> Does this patch really need to be this big?

Not quite.  I could implement set/unset hooks in nsHTMLOptionElement instead of making nsGenericElement::UnsetAttr call BeforeSetAttr.  Doing it the way I did seems simpler, though...  If you prefer, I can revert this part of the patch (so nsGenericElement, nsGenericHTMLElement, and the SVG and XUL changes.  I do think we need the rest of it, though.

For the rest, like I said in comment 11, the basic problem is that the <select> needs to be told any time the .selected state of an option changes.  When it becomes true, the <select> (if it's a single select) goes through and unselects all other options.  Since we now map .selected to .defaultSelected unless .selected has been explicitly set, we need to notify the <select> if .defaultSelected changes and .selected hasn't been set.

That's what the patch does in nsHTMLOptionElement::BeforeSetAttr.  The nsHTMLSelectElement changes are to address the second bullet of comment 11.
Comment on attachment 286646 [details] [diff] [review]
Proposed fix

Why not let XUL::unsetattr also call before/aftersetattr? I'd prefer the consistency to the saved cycles I think
Comment on attachment 286646 [details] [diff] [review]
Proposed fix

r/sr = me either way.
Attachment #286646 - Flags: superreview?(jonas)
Attachment #286646 - Flags: superreview+
Attachment #286646 - Flags: review?(jonas)
Attachment #286646 - Flags: review+
> Why not let XUL::unsetattr also call before/aftersetattr?

Because the things nsXULElement::UnsetAttr and nsXULElement::AfterSetAttr do subtly different things to the same attributes.  So it was more a matter of complexity and regression risk than cycles...

Thanks for the review!
Checked in.
Status: ASSIGNED → RESOLVED
Closed: 17 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Component: DOM: HTML → DOM: Core & HTML
Depends on: 927796
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: