OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2011 Apple Inc. All rights reserved. |
3 * Copyright (C) 2010 Google Inc. All rights reserved. | 3 * Copyright (C) 2010 Google Inc. All rights reserved. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "core/events/MouseEvent.h" | 30 #include "core/events/MouseEvent.h" |
31 #include "core/html/HTMLInputElement.h" | 31 #include "core/html/HTMLInputElement.h" |
32 #include "core/page/SpatialNavigation.h" | 32 #include "core/page/SpatialNavigation.h" |
33 #include "platform/text/PlatformLocale.h" | 33 #include "platform/text/PlatformLocale.h" |
34 #include "wtf/PassOwnPtr.h" | 34 #include "wtf/PassOwnPtr.h" |
35 | 35 |
36 namespace blink { | 36 namespace blink { |
37 | 37 |
38 namespace { | 38 namespace { |
39 | 39 |
40 HTMLElement* nextElement(const HTMLElement& element, bool forward) | 40 HTMLElement* nextElement(const HTMLElement& element, HTMLFormElement* stayWithin
, bool forward) |
41 { | 41 { |
42 return forward ? Traversal<HTMLElement>::next(element) : Traversal<HTMLEleme
nt>::previous(element); | 42 return forward ? Traversal<HTMLElement>::next(element, (Node* )stayWithin) :
Traversal<HTMLElement>::previous(element, (Node* )stayWithin); |
43 } | 43 } |
44 | 44 |
45 } // namespace | 45 } // namespace |
46 | 46 |
47 using namespace HTMLNames; | 47 using namespace HTMLNames; |
48 | 48 |
49 PassRefPtrWillBeRawPtr<InputType> RadioInputType::create(HTMLInputElement& eleme
nt) | 49 PassRefPtrWillBeRawPtr<InputType> RadioInputType::create(HTMLInputElement& eleme
nt) |
50 { | 50 { |
51 return adoptRefWillBeNoop(new RadioInputType(element)); | 51 return adoptRefWillBeNoop(new RadioInputType(element)); |
52 } | 52 } |
(...skipping 11 matching lines...) Expand all Loading... |
64 String RadioInputType::valueMissingText() const | 64 String RadioInputType::valueMissingText() const |
65 { | 65 { |
66 return locale().queryString(blink::WebLocalizedString::ValidationValueMissin
gForRadio); | 66 return locale().queryString(blink::WebLocalizedString::ValidationValueMissin
gForRadio); |
67 } | 67 } |
68 | 68 |
69 void RadioInputType::handleClickEvent(MouseEvent* event) | 69 void RadioInputType::handleClickEvent(MouseEvent* event) |
70 { | 70 { |
71 event->setDefaultHandled(); | 71 event->setDefaultHandled(); |
72 } | 72 } |
73 | 73 |
| 74 HTMLInputElement* RadioInputType::findNextFocusableRadioButtonInGroup(HTMLInputE
lement* currentElement, bool forward) |
| 75 { |
| 76 HTMLElement* htmlElement; |
| 77 for (htmlElement = nextElement(*currentElement, element().form(), forward);
htmlElement; htmlElement = nextElement(*htmlElement, element().form(), forward))
{ |
| 78 if (!isHTMLInputElement(*htmlElement)) |
| 79 continue; |
| 80 HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); |
| 81 if (element().form() == inputElement->form() && inputElement->type() ==
InputTypeNames::radio && inputElement->name() == element().name() && inputElemen
t->isFocusable()) |
| 82 return inputElement; |
| 83 } |
| 84 return nullptr; |
| 85 } |
| 86 |
74 void RadioInputType::handleKeydownEvent(KeyboardEvent* event) | 87 void RadioInputType::handleKeydownEvent(KeyboardEvent* event) |
75 { | 88 { |
76 BaseCheckableInputType::handleKeydownEvent(event); | 89 BaseCheckableInputType::handleKeydownEvent(event); |
77 if (event->defaultHandled()) | 90 if (event->defaultHandled()) |
78 return; | 91 return; |
79 const String& key = event->keyIdentifier(); | 92 const String& key = event->keyIdentifier(); |
80 if (key != "Up" && key != "Down" && key != "Left" && key != "Right") | 93 if (key != "Up" && key != "Down" && key != "Left" && key != "Right") |
81 return; | 94 return; |
82 | 95 |
83 // Left and up mean "previous radio button". | 96 // Left and up mean "previous radio button". |
84 // Right and down mean "next radio button". | 97 // Right and down mean "next radio button". |
85 // Tested in WinIE, and even for RTL, left still means previous radio button | 98 // Tested in WinIE, and even for RTL, left still means previous radio button |
86 // (and so moves to the right). Seems strange, but we'll match it. However, | 99 // (and so moves to the right). Seems strange, but we'll match it. However, |
87 // when using Spatial Navigation, we need to be able to navigate without | 100 // when using Spatial Navigation, we need to be able to navigate without |
88 // changing the selection. | 101 // changing the selection. |
89 Document& document = element().document(); | 102 Document& document = element().document(); |
90 if (isSpatialNavigationEnabled(document.frame())) | 103 if (isSpatialNavigationEnabled(document.frame())) |
91 return; | 104 return; |
92 bool forward = (key == "Down" || key == "Right"); | 105 bool forward = (key == "Down" || key == "Right"); |
93 | 106 |
94 // We can only stay within the form's children if the form hasn't been demot
ed to a leaf because | 107 // We can only stay within the form's children if the form hasn't been demot
ed to a leaf because |
95 // of malformed HTML. | 108 // of malformed HTML. |
96 for (HTMLElement* htmlElement = nextElement(element(), forward); htmlElement
; htmlElement = nextElement(*htmlElement, forward)) { | 109 HTMLInputElement* inputElement = findNextFocusableRadioButtonInGroup(toHTMLI
nputElement(&element()), forward); |
97 // Once we encounter a form element, we know we're through. | 110 if (!inputElement) { |
98 if (isHTMLFormElement(*htmlElement)) | 111 // Traverse in reverse direction till last or first radio button |
99 break; | 112 forward = !(forward); |
100 // Look for more radio buttons. | 113 HTMLInputElement* nextInputElement = findNextFocusableRadioButtonInGroup
(toHTMLInputElement(&element()), forward); |
101 if (!isHTMLInputElement(*htmlElement)) | 114 while (nextInputElement) { |
102 continue; | 115 inputElement = nextInputElement; |
103 HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); | 116 nextInputElement = findNextFocusableRadioButtonInGroup(nextInputElem
ent, forward); |
104 if (inputElement->form() != element().form()) | |
105 break; | |
106 if (inputElement->type() == InputTypeNames::radio && inputElement->name(
) == element().name() && inputElement->isFocusable()) { | |
107 RefPtrWillBeRawPtr<HTMLInputElement> protector(inputElement); | |
108 document.setFocusedElement(inputElement); | |
109 inputElement->dispatchSimulatedClick(event, SendNoEvents); | |
110 event->setDefaultHandled(); | |
111 return; | |
112 } | 117 } |
113 } | 118 } |
| 119 if (inputElement) { |
| 120 RefPtrWillBeRawPtr<HTMLInputElement> protector(inputElement); |
| 121 document.setFocusedElement(inputElement); |
| 122 inputElement->dispatchSimulatedClick(event, SendNoEvents); |
| 123 event->setDefaultHandled(); |
| 124 return; |
| 125 } |
114 } | 126 } |
115 | 127 |
116 void RadioInputType::handleKeyupEvent(KeyboardEvent* event) | 128 void RadioInputType::handleKeyupEvent(KeyboardEvent* event) |
117 { | 129 { |
118 const String& key = event->keyIdentifier(); | 130 const String& key = event->keyIdentifier(); |
119 if (key != "U+0020") | 131 if (key != "U+0020") |
120 return; | 132 return; |
121 // If an unselected radio is tabbed into (because the entire group has nothi
ng | 133 // If an unselected radio is tabbed into (because the entire group has nothi
ng |
122 // checked, or because of some explicit .focus() call), then allow space to
check it. | 134 // checked, or because of some explicit .focus() call), then allow space to
check it. |
123 if (element().checked()) | 135 if (element().checked()) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 // The work we did in willDispatchClick was default handling. | 201 // The work we did in willDispatchClick was default handling. |
190 event->setDefaultHandled(); | 202 event->setDefaultHandled(); |
191 } | 203 } |
192 | 204 |
193 bool RadioInputType::shouldAppearIndeterminate() const | 205 bool RadioInputType::shouldAppearIndeterminate() const |
194 { | 206 { |
195 return !element().checkedRadioButtonForGroup(); | 207 return !element().checkedRadioButtonForGroup(); |
196 } | 208 } |
197 | 209 |
198 } // namespace blink | 210 } // namespace blink |
OLD | NEW |