зеркало из https://github.com/mozilla/gecko-dev.git
Bug 885359 - Support :indeterminate pseudo-class for radio groups. r=smaug
This commit is contained in:
Родитель
17c45acab3
Коммит
1b328436b6
|
@ -3289,7 +3289,7 @@ HTMLInputElement::GetRadioGroupContainer() const
|
|||
}
|
||||
|
||||
already_AddRefed<nsIDOMHTMLInputElement>
|
||||
HTMLInputElement::GetSelectedRadioButton()
|
||||
HTMLInputElement::GetSelectedRadioButton() const
|
||||
{
|
||||
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||
if (!container) {
|
||||
|
@ -3360,6 +3360,13 @@ HTMLInputElement::SetCheckedInternal(bool aChecked, bool aNotify)
|
|||
// Notify the document that the CSS :checked pseudoclass for this element
|
||||
// has changed state.
|
||||
UpdateState(aNotify);
|
||||
|
||||
// Notify all radios in the group that value has changed, this is to let
|
||||
// radios to have the chance to update its states, e.g., :indeterminate.
|
||||
if (mType == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIRadioVisitor> visitor = new nsRadioUpdateStateVisitor(this);
|
||||
VisitGroup(visitor, aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -6420,6 +6427,15 @@ HTMLInputElement::IntrinsicState() const
|
|||
state |= NS_EVENT_STATE_INDETERMINATE;
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
|
||||
bool indeterminate = !selected && !mChecked;
|
||||
|
||||
if (indeterminate) {
|
||||
state |= NS_EVENT_STATE_INDETERMINATE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we are the default checked element (:default)
|
||||
if (DefaultChecked()) {
|
||||
state |= NS_EVENT_STATE_DEFAULT;
|
||||
|
@ -6643,6 +6659,9 @@ HTMLInputElement::WillRemoveFromRadioGroup()
|
|||
// longer a selected radio button
|
||||
if (mChecked) {
|
||||
container->SetCurrentRadioButton(name, nullptr);
|
||||
|
||||
nsCOMPtr<nsIRadioVisitor> visitor = new nsRadioUpdateStateVisitor(this);
|
||||
VisitGroup(visitor, true);
|
||||
}
|
||||
|
||||
// Remove this radio from its group in the container.
|
||||
|
|
|
@ -264,7 +264,7 @@ public:
|
|||
*
|
||||
* @return the selected button (or null).
|
||||
*/
|
||||
already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton();
|
||||
already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton() const;
|
||||
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||
|
||||
|
|
|
@ -55,3 +55,15 @@ nsRadioSetValueMissingState::Visit(nsIFormControl* aRadio)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsRadioUpdateStateVisitor::Visit(nsIFormControl* aRadio)
|
||||
{
|
||||
if (aRadio == mExcludeElement) {
|
||||
return true;
|
||||
}
|
||||
|
||||
HTMLInputElement* input = static_cast<HTMLInputElement*>(aRadio);
|
||||
input->UpdateState(true);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -94,5 +94,18 @@ protected:
|
|||
bool mNotify;
|
||||
};
|
||||
|
||||
class nsRadioUpdateStateVisitor : public nsRadioVisitor
|
||||
{
|
||||
public:
|
||||
explicit nsRadioUpdateStateVisitor(nsIFormControl* aExcludeElement)
|
||||
: mExcludeElement(aExcludeElement)
|
||||
{ }
|
||||
|
||||
virtual bool Visit(nsIFormControl* aRadio) override;
|
||||
|
||||
protected:
|
||||
nsIFormControl* mExcludeElement;
|
||||
};
|
||||
|
||||
#endif // _nsRadioVisitor_h__
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ support-files =
|
|||
[test_bug1286509.html]
|
||||
skip-if = os == "android" || appname == "b2g" # up/down arrow keys not supported on android/b2g
|
||||
[test_button_attributes_reflection.html]
|
||||
[test_input_radio_indeterminate.html]
|
||||
[test_input_radio_radiogroup.html]
|
||||
[test_input_radio_required.html]
|
||||
[test_change_event.html]
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=885359
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 885359</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885359">Mozilla Bug 343444</a>
|
||||
<p id="display"></p>
|
||||
<form>
|
||||
<input type="radio" id='radio1'/><br/>
|
||||
|
||||
<input type="radio" id="g1radio1" name="group1"/>
|
||||
<input type="radio" id="g1radio2" name="group1"/></br>
|
||||
<input type="radio" id="g1radio3" name="group1"/></br>
|
||||
|
||||
<input type="radio" id="g2radio1" name="group2"/>
|
||||
<input type="radio" id="g2radio2" name="group2" checked/></br>
|
||||
</form>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var radio1 = document.getElementById("radio1");
|
||||
var g1radio1 = document.getElementById("g1radio1");
|
||||
var g1radio2 = document.getElementById("g1radio2");
|
||||
var g1radio3 = document.getElementById("g1radio3");
|
||||
var g2radio1 = document.getElementById("g2radio1");
|
||||
var g2radio2 = document.getElementById("g2radio2");
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function verifyIndeterminateState(aElement, aIsIndeterminate, aMessage) {
|
||||
is(aElement.mozMatchesSelector(':indeterminate'), aIsIndeterminate, aMessage);
|
||||
}
|
||||
|
||||
function test() {
|
||||
// Initial State.
|
||||
verifyIndeterminateState(radio1, true,
|
||||
"Unchecked radio in its own group (no name attribute)");
|
||||
verifyIndeterminateState(g1radio1, true, "No selected radio in its group");
|
||||
verifyIndeterminateState(g1radio2, true, "No selected radio in its group");
|
||||
verifyIndeterminateState(g1radio3, true, "No selected radio in its group");
|
||||
verifyIndeterminateState(g2radio1, false, "Selected radio in its group");
|
||||
verifyIndeterminateState(g2radio2, false, "Selected radio in its group");
|
||||
|
||||
// Selecting radio buttion.
|
||||
g1radio1.checked = true;
|
||||
verifyIndeterminateState(g1radio1, false,
|
||||
"Selecting a radio should affect all radios in the group");
|
||||
verifyIndeterminateState(g1radio2, false,
|
||||
"Selecting a radio should affect all radios in the group");
|
||||
verifyIndeterminateState(g1radio3, false,
|
||||
"Selecting a radio should affect all radios in the group");
|
||||
|
||||
// Changing the selected radio button.
|
||||
g1radio3.checked = true;
|
||||
verifyIndeterminateState(g1radio1, false,
|
||||
"Selecting a radio should affect all radios in the group");
|
||||
verifyIndeterminateState(g1radio2, false,
|
||||
"Selecting a radio should affect all radios in the group");
|
||||
verifyIndeterminateState(g1radio3, false,
|
||||
"Selecting a radio should affect all radios in the group");
|
||||
|
||||
// Deselecting radio button.
|
||||
g2radio2.checked = false;
|
||||
verifyIndeterminateState(g2radio1, true,
|
||||
"Deselecting a radio should affect all radios in the group");
|
||||
verifyIndeterminateState(g2radio2, true,
|
||||
"Deselecting a radio should affect all radios in the group");
|
||||
|
||||
// Move a selected radio button to another group.
|
||||
g1radio3.name = "group2";
|
||||
|
||||
// The radios' state in the original group becomes indeterminated.
|
||||
verifyIndeterminateState(g1radio1, true,
|
||||
"Removing a radio from a group should affect all radios in the group");
|
||||
verifyIndeterminateState(g1radio2, true,
|
||||
"Removing a radio from a group should affect all radios in the group");
|
||||
|
||||
// The radios' state in the new group becomes determinated.
|
||||
verifyIndeterminateState(g1radio3, false,
|
||||
"Adding a radio from a group should affect all radios in the group");
|
||||
verifyIndeterminateState(g2radio1, false,
|
||||
"Adding a radio from a group should affect all radios in the group");
|
||||
verifyIndeterminateState(g2radio2, false,
|
||||
"Adding a radio from a group should affect all radios in the group");
|
||||
|
||||
// Change input type to 'text'.
|
||||
g1radio3.type = "text";
|
||||
verifyIndeterminateState(g1radio3, false,
|
||||
"Input type text does not have an indeterminate state");
|
||||
verifyIndeterminateState(g2radio1, true,
|
||||
"Changing input type should affect all radios in the group");
|
||||
verifyIndeterminateState(g2radio2, true,
|
||||
"Changing input type should affect all radios in the group");
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -43,8 +43,8 @@ is(document.defaultView.getComputedStyle($("s"), null).getPropertyValue("margin-
|
|||
$("s").setAttribute("type", "radio");
|
||||
|
||||
is(document.defaultView.getComputedStyle($("s"), null).getPropertyValue("margin-left"),
|
||||
"10px",
|
||||
"Only checkboxes should have indeterminate styles applied to them");
|
||||
"30px",
|
||||
"Setting an indeterminate element to type radio should give it indeterminate styles");
|
||||
|
||||
$("s").setAttribute("type", "checkbox");
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[indeterminate.html]
|
||||
type: testharness
|
||||
[':progress' matches <input>s radio buttons whose radio button group contains no checked input and <progress> elements without value attribute]
|
||||
expected: FAIL
|
||||
|
||||
[dynamically check a radio input in a radio button group]
|
||||
expected: FAIL
|
||||
|
||||
[click on radio4 which is in the indeterminate state]
|
||||
expected: FAIL
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
testSelectorIdsMatch(":indeterminate", ["radio4", "radio5", "progress1"], "dynamically check a radio input in a radio button group");
|
||||
|
||||
document.getElementById("radio4").click();
|
||||
testSelectorIdsMatch(":indeterminate", ["checkbox1", "progress2"], "click on radio4 which is in the indeterminate state");
|
||||
testSelectorIdsMatch(":indeterminate", ["progress1"], "click on radio4 which is in the indeterminate state");
|
||||
|
||||
document.getElementById("progress1").setAttribute("value", "20");
|
||||
testSelectorIdsMatch(":indeterminate", [], "adding a value to progress1 should put it in a determinate state");
|
||||
|
|
Загрузка…
Ссылка в новой задаче