Closed Bug 108308 Opened 23 years ago Closed 23 years ago

Radio button initial value is not set when display: none

Categories

(Core :: Layout: Form Controls, defect)

x86
All
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla1.0

People

(Reporter: john, Assigned: john)

References

Details

Attachments

(1 file, 3 obsolete files)

<FORM NAME=mainform> <INPUT TYPE=radio NAME=btn VALUE="heck yeah" CHECKED STYLE="display: none"> <SCRIPT>alert(document.mainform.btn.checked)</SCRIPT> </FORM> should show true. Currently it shows false. This affects its ability to be properly submitted and manipulated with JavaScript.
Blocks: 109102
Note that the script below may also fail if you remove display: none, because the frame may not have been created. It will *definitely* fail if you create the radio button in a script and try to access its CHECKED state before you actually add it to the document with appendChild() or some such, because you're guaranteed the frame will not be created until it's inserted into the document. On top of this, I will probably make radio buttons happy whether or not they're in a form--I'll be changing those parts anyway, so it's not a big deal. Finally, this change will probably finally obsolete nsFormFrame.cpp and make it a simple block frame (yay!). If this turns out to be the case, I will remove the class and make any resultant changes elsewhere.
Blocks: 116872
Blocks: 112715
Status: NEW → ASSIGNED
Target Milestone: --- → mozilla0.9.9
Blocks: 92116
Blocks: 112489
Blocks: 121202
No longer blocks: 121202
Blocks: 122957
Blocks: 109914
Blocks: 44470
Blocks: 14445
Attached patch Patch (obsolete) (deleted) — Splinter Review
First version. We need to move the nsPLDStringSupportsHashTable out somewhere else, it doesn't really belong in nsHTMLFormElement. Things this patch does not address (for various reasons): - grouping radio buttons outside of forms - ensuring at least one radio button in every group is checked - removing nsFormFrame entirely (which may be imminently possible)
And by the way, this bug will likely *not* address those 3 problems. The patch is almost complete. I almost scaled the first two problems, and then realized that the best way to deal with them would require mess with parser. Specifically we would want to suppress adding radios to groups until the <input> tag is totally parsed. The problem with checking at least one in a group is, when <input name=a> is created, first the <input> is added to the form, at which point it is added to the blank group, which only has that input in it, so it is checked. Then name=a is parsed and the attribute is set, and the <input>, which is now checked, is added into the group. Adding a checked radio button into a group leaves the button checked (which is kinda what you'd expect with JS) and therefore deselects any other radios in the group. The proper solution is to consider <input name=a> as a piece and not add the control into the group until it is fully parsed. The problem with radios not in the document is similar. When we add a node to the document it is not yet added to the form. At that point we have to determine the "checked changed" property of the group. Finding a radio in the group to get "checked changed" from will be an expensive operation unless we add a hashtable to the group, and it's not even necessary. This one may be more easily surmountable, but we really shouldn't do anything with the non-form group for form controls inside a form. Again, we either have to predict whether the form will be set or we have to be told when that operation is complete (like when the <input> is completely parsed). nsFormFrame I'm not getting rid of right here because it can easily be dealt with separately and this patch is already big enough. No other reason. This patch adds the infrastructure necessary to support both of these, however, with the nsIRadioVisitor interface. On the plus side, this patch adds very little memory requirements, and subtracts a lot.
Marking nsbeta1+
Keywords: nsbeta1+
Blocks: 123435
Blocks: 125578
Depends on: 125849
Blocks: 125647
Attached patch Patch v2.0 (obsolete) (deleted) — Splinter Review
- uses nsDoubleHashtable (now in tree) - moved name change checking to nsHTMLInputElement.cpp, moved that code out so that SetAttr() and UnsetAttr() would have the same code paths - moved AddedToRadioGroup() and RemovedFromRadioGroup() (formerly CheckAddRadio and CheckRemoveRadio) from nsHTMLFormElement to nsHTMLInputElement to simplify slightly and to make it easier to make radio buttons outside of forms work
Attachment #69219 - Attachment is obsolete: true
Attached patch Patch v2.1 (obsolete) (deleted) — Splinter Review
As per JST's comments in IRC: - add Init() method to nsHTMLFormElement - make operators that split lines show up at the end of the previous line - there were some places we were grabbing radio.value when we didn't need to (printf remnants) Also: - removed the accidentally-pulled-in stuff from other work in layout/html/forms
Attachment #71002 - Attachment is obsolete: true
http://www.johnkeiser.com/mozilla/radio has extensive regression tests for radio button. Please note that when you add/remove radio buttons dynamically to/from the document, it's not repainting the test. This bug is unrelated to this patch, as it happens before applying as well. Just move a window over the affected area and you'll see what you're supposed to see. Here's a description of the radio button architecture and the patch for your reviewing pleasure: FUNCTIONALITY Radio Button Rules: - when a radio button is checked by JS or by a click, the checked radio button in the group will be unchecked. - when a *checked* radio button is added into a group, the checked radio button in the group will be unchecked. Grouping: - a radio button can be added to or removed from a group when it's type or name changes, or when it is added into the document underneath a form. - a radio button without a form is (currently) not in a group (bug 14445). Checked Changed: - "checked changed" is a bit that determines whether an element's checked property has been changed by JS or by a user click. When this has happened, setAttribute("checked") no longer affects the checkbox's value. (This is a compromise between the spec and real-world behavior, and is currently already done for checkbox and input type=text.) - "checked changed" applies to the entire group rather than to an individual button. If .checked is changed by JavaScript in one radio button, setAttribute("checked") will no longer work for any other radio button in the group. ARCHITECTURE HIGHLIGHTS Adding to/removing from a radio group: - nsHTMLInputElement::AddedToRadioGroup() and nsHTMLInputElement::RemovedFromRadioGroup() are called whenever an action occurs that changes an input element's being in a group. Generally nothing happens, unless the radio button in question is checked nsIRadioVisitor: - we use the visitor pattern to walk radio controls in a group. This is because: (a) there will be multiple walkers in the future--form controls not in a form vs. those in a form. (b) there are multiple operations that have to be performed on a group, and the walking code is non-trivial--a visitor is the easiest way to reuse this code. Though there are currently only two operations, a third will be necessary if/when we implement the rule that any radio group *must* have something checked, even if nothing is explicitly checked by the user. - nsIRadioVisitor is the interface implemented by visitors (called by form walkers). - nsHTMLFormElement::WalkRadioGroup() and nsHTMLInputElement::VisitGroup() currently handle this visitor pattern. Checked Changed: - To implement checked changed, when .checked is set using JS or the user clicks on a radio button, we iterate over all radio buttons to find the - To maintain data integrity, when a radio button is added to a radio group, its checked changed property is set to be the same as others in the same group.
John, do you have an estimate for the date this will land so that Brian can enable all the XBL Form Controls? Also, could you please add this to the mozilla landing plan page?
Comment on attachment 71020 [details] [diff] [review] Patch v2.1 Seems like you should check the return value of NS_GetRadioSetCheckedChangedVisitor and for some unknow reason it fails (although doubtful) you are not checking "visitor" and just passing it into VisitGroup VisitgGroup is defined as having a return code, and it appears to always returns NS_OK and doesn't appear to be in an interface, so just make it a void. There are some places where you are casting, you should probably use STATIC_CAST: + rv = ((nsHTMLInputElement*) + (nsIDOMHTMLInputElement*) + currentlySelected)->SetCheckedInternal(PR_FALSE); + rv = mForm->SetCurrentRadioButton(name, (nsIDOMHTMLInputElement*)this); Looks like you should have an assert here, since you removed the check on aType: nsHTMLInputElement::GetType(PRInt32* aType) Maybe comment about how you know it will always be loewer case: + checked ? NS_LITERAL_STRING("t") : Is NS_OK the right thing to return is mForm is NULL? +NS_IMETHODIMP +nsHTMLInputElement::AddedToRadioGroup() +{ + // + // Currently the only time radio groups really happen is in forms + // + if (!mForm) { + return NS_OK; + } Same for (is an assert a proper thing to do? Or is it just an no-op?): +nsHTMLInputElement::RemovedFromRadioGroup(nsIForm* aForm, nsAString* aName) +{ + // + // Currently radio groups only happen in forms + // + if (!aForm) { + return NS_OK; + } I see where WalkRadioGroup's return is not checked where it is used yet it can return alues other than NS_OK, should it be checked? In: + NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop) + { + nsCOMPtr<nsIRadioControlElement> radio(do_QueryInterface(aRadio)); + radio->SetCheckedChangedInternal(mCheckedChanged); + *aStop = PR_TRUE; + return NS_OK; + } We should have an NS_ENSURE_POINTER_ARG Seems like we make the assumption that aRadio will always QI to nsIRadioControlElement we should at least have an assert here. In: + NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop) + { + if (aRadio == mExcludeElement) { + return NS_OK; + } + nsCOMPtr<nsIRadioControlElement> radio(do_QueryInterface(aRadio)); + radio->GetCheckedChanged(mCheckedChanged); + *aStop = PR_TRUE; + return NS_OK; + } We should have an NS_ENSURE_POINTER_ARG Here: + static nsIRadioVisitor* visitorTrue = nsnull; + static nsIRadioVisitor* visitorFalse = nsnull; We need to have a BIG comment on why these are static and how holding onto their values are necessary. Also, I think maybe they need to be static class data members instead of being define static in the method. Overall the arch looks right, the above are just nits, but things that should be looked at. It's great to have this out of the frames. fix up the above r=rods
Attachment #71020 - Flags: review+
Fixed all except: 1. Should we return NS_OK when mForm is null in AddedToRadioGroup(), RemovedFromRadioGroup()? This can be called even if there is no form. It's a valid thing to do (we do it in SetAttr). In those cases the "radio group" is simply the button itself and there is nothing else to do. 2. In both Visit()s we should have an NS_ENSURE_POINTER_ARG and assert the result of QueryInterface. Both of these are really part of the contract; so I did an assertion instead and changed the documentation for the interface to explicitly reflect this..
Attached patch Patch v2.2 (deleted) — Splinter Review
rods changes above, one more change from his requests: - visitorTrue and visitorFalse remained static members in NS_GetRadioSetCheckedChangedVisitor, because to do otherwise required initializing the members outside of the class as well as making NS_NewSetCheckedChangedVisitor a friend of nsSetCheckedChangedVisitor. Comments added though.
Attachment #71020 - Attachment is obsolete: true
Not making it for 0.9.9, hopefully we'll land early in 1.0 cycle
Target Milestone: mozilla0.9.9 → mozilla1.0
Hopefully? Having all the form controls as soon as possible is critical for multiple projects. Is there anything we can do to help you land this sooner?
It's conditional on sr=, the patch is done and has r=. It *will* land in 1.0 and I hope it will land *early* in 1.0.
I hear you John, but one milestone granularity is not sufficient, even with hope. We have dependent features that require a landing *date* in the next 2 weeks. Could you use some help?
I'm working on sr'ing these changes, I won't be done today, but hopefully I'll get through this sometime tomorrow...
Comment on attachment 71705 [details] [diff] [review] Patch v2.2 - In nsFormControlFrame.cpp: @@ -897,7 +895,7 @@ nsIDOMHTMLInputElement* inputElement; if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) { inputElement->SetChecked(aState); - NS_RELEASE(inputElement); + NS_RELEASE(inputElement); nsCOMPtr! - In nsHTMLInputElement.cpp: + rv = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"), + checked ? NS_LITERAL_STRING("t") : + NS_LITERAL_STRING("f")); I believe this will get you into trouble on some compilers, I think it's safe to use two named literal strings and use those in the tri-statement, but the above is most likely not xp. - In nsRadioSetCheckedChangedVisitor, you don't need to declare any nsISupports stuff there since you're not directly inheriting any interfaces. Just let the base class deal with it. - In nsRadioGetCheckedChangedVisitor, same thing... Other than that, sr=jst
Attachment #71705 - Flags: superreview+
Comment on attachment 71705 [details] [diff] [review] Patch v2.2 a=asa (on behalf of drivers) for checkin to the 1.0 trunk
Attachment #71705 - Flags: approval+
Blocks: 127569
Fix checked in (with JST's changes).
Status: ASSIGNED → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
No longer blocks: 125647
QA Contact: madhur → tpreston
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: