Fix to Handle downkey event on last and first radio button of a radio button list

After pressing last radio button in the list, on pressing downArrow it will select back first radio button, similarly after pressing last radio button in the list, on pressing upArrow it will select last radio button.

For this change I have added one test case : radio-checked-LastorFirst-then-DownorUp-keyDown.html. This HTML contains a list of radio buttons and after selecting last radio button downArrow keyDown event raised. Similarly done for first radio button also.


R=habib.virji@samsung.com
BUG=408512

Review URL: https://codereview.chromium.org/546753002

git-svn-id: svn://svn.chromium.org/blink/trunk@183661 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent c785dcd6
Tests after pressing last radio button in the list, on pressing downkey it selects back first radio button
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS document.getElementById("cherry").checked is true
PASS document.getElementById("apple").checked is true
PASS document.getElementById("cherry").checked is true
PASS document.getElementById("cucumber").checked is true
PASS document.getElementById("tomato").checked is true
PASS document.getElementById("cucumber").checked is true
PASS document.getElementById("pumpkin").checked is true
PASS document.getElementById("pumpkin").checked is true
PASS document.getElementById("pumpkin").checked is true
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<body>
<script src="../resources/common.js"></script>
<script src="../../../resources/js-test.js"></script>
<form name=alpha>
<input type="radio" name="fruit" id="apple"><br>
<input type="radio" name="fruit" id="banana"><br>
<input type="radio" name="fruit" id="cherry"><br>
<input type="radio" name="fruit" form=beta id="tomato"><br>
<input type="radio" name="fruit" form=beta id="delta"><br>
</form>
<form name=beta>
<input type="radio" name="fruit" id="pumpkin"><br>
</form>
<input type="radio" name="fruit" form=alpha id="cucumber"><br>
<script>
document.alpha.insertBefore(document.beta, document.alpha.fruit[2]);
description('Tests after pressing last radio button in the list, on pressing downkey it selects back first radio button');
clickElement(document.getElementById('cherry'));
shouldBeTrue('document.getElementById("cherry").checked');
eventSender.keyDown('downArrow');
shouldBeTrue('document.getElementById("apple").checked');
eventSender.keyDown('upArrow');
shouldBeTrue('document.getElementById("cherry").checked');
clickElement(document.getElementById('cucumber'));
shouldBeTrue('document.getElementById("cucumber").checked');
eventSender.keyDown('downArrow');
shouldBeTrue('document.getElementById("tomato").checked');
eventSender.keyDown('upArrow');
shouldBeTrue('document.getElementById("cucumber").checked');
clickElement(document.getElementById('pumpkin'));
shouldBeTrue('document.getElementById("pumpkin").checked');
eventSender.keyDown('downArrow');
shouldBeTrue('document.getElementById("pumpkin").checked');
eventSender.keyDown('upArrow');
shouldBeTrue('document.getElementById("pumpkin").checked');
</script>
</body>
</html>
......@@ -37,9 +37,9 @@ namespace blink {
namespace {
HTMLElement* nextElement(const HTMLElement& element, bool forward)
HTMLElement* nextElement(const HTMLElement& element, HTMLFormElement* stayWithin, bool forward)
{
return forward ? Traversal<HTMLElement>::next(element) : Traversal<HTMLElement>::previous(element);
return forward ? Traversal<HTMLElement>::next(element, (Node* )stayWithin) : Traversal<HTMLElement>::previous(element, (Node* )stayWithin);
}
} // namespace
......@@ -71,6 +71,19 @@ void RadioInputType::handleClickEvent(MouseEvent* event)
event->setDefaultHandled();
}
HTMLInputElement* RadioInputType::findNextFocusableRadioButtonInGroup(HTMLInputElement* currentElement, bool forward)
{
HTMLElement* htmlElement;
for (htmlElement = nextElement(*currentElement, element().form(), forward); htmlElement; htmlElement = nextElement(*htmlElement, element().form(), forward)) {
if (!isHTMLInputElement(*htmlElement))
continue;
HTMLInputElement* inputElement = toHTMLInputElement(htmlElement);
if (element().form() == inputElement->form() && inputElement->type() == InputTypeNames::radio && inputElement->name() == element().name() && inputElement->isFocusable())
return inputElement;
}
return nullptr;
}
void RadioInputType::handleKeydownEvent(KeyboardEvent* event)
{
BaseCheckableInputType::handleKeydownEvent(event);
......@@ -93,24 +106,23 @@ void RadioInputType::handleKeydownEvent(KeyboardEvent* event)
// We can only stay within the form's children if the form hasn't been demoted to a leaf because
// of malformed HTML.
for (HTMLElement* htmlElement = nextElement(element(), forward); htmlElement; htmlElement = nextElement(*htmlElement, forward)) {
// Once we encounter a form element, we know we're through.
if (isHTMLFormElement(*htmlElement))
break;
// Look for more radio buttons.
if (!isHTMLInputElement(*htmlElement))
continue;
HTMLInputElement* inputElement = toHTMLInputElement(htmlElement);
if (inputElement->form() != element().form())
break;
if (inputElement->type() == InputTypeNames::radio && inputElement->name() == element().name() && inputElement->isFocusable()) {
RefPtrWillBeRawPtr<HTMLInputElement> protector(inputElement);
document.setFocusedElement(inputElement);
inputElement->dispatchSimulatedClick(event, SendNoEvents);
event->setDefaultHandled();
return;
HTMLInputElement* inputElement = findNextFocusableRadioButtonInGroup(toHTMLInputElement(&element()), forward);
if (!inputElement) {
// Traverse in reverse direction till last or first radio button
forward = !(forward);
HTMLInputElement* nextInputElement = findNextFocusableRadioButtonInGroup(toHTMLInputElement(&element()), forward);
while (nextInputElement) {
inputElement = nextInputElement;
nextInputElement = findNextFocusableRadioButtonInGroup(nextInputElement, forward);
}
}
if (inputElement) {
RefPtrWillBeRawPtr<HTMLInputElement> protector(inputElement);
document.setFocusedElement(inputElement);
inputElement->dispatchSimulatedClick(event, SendNoEvents);
event->setDefaultHandled();
return;
}
}
void RadioInputType::handleKeyupEvent(KeyboardEvent* event)
......
......@@ -52,6 +52,7 @@ private:
virtual PassOwnPtrWillBeRawPtr<ClickHandlingState> willDispatchClick() override;
virtual void didDispatchClick(Event*, const ClickHandlingState&) override;
virtual bool shouldAppearIndeterminate() const override;
virtual HTMLInputElement* findNextFocusableRadioButtonInGroup(HTMLInputElement*, bool);
};
} // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment