1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.IOException;
18 import java.util.Map;
19
20 import org.htmlunit.Page;
21 import org.htmlunit.ScriptResult;
22 import org.htmlunit.SgmlPage;
23 import org.htmlunit.javascript.host.event.Event;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public class HtmlRadioButtonInput extends HtmlInput implements LabelableElement {
41
42
43
44
45 private static final String DEFAULT_VALUE = "on";
46
47 private boolean defaultCheckedState_;
48 private boolean checkedState_;
49
50
51
52
53
54
55
56
57
58
59
60 HtmlRadioButtonInput(final String qualifiedName, final SgmlPage page,
61 final Map<String, DomAttr> attributes) {
62 super(qualifiedName, page, attributes);
63
64 if (getAttributeDirect(VALUE_ATTRIBUTE) == ATTRIBUTE_NOT_DEFINED) {
65 setRawValue(DEFAULT_VALUE);
66 }
67
68 defaultCheckedState_ = hasAttribute(ATTRIBUTE_CHECKED);
69 checkedState_ = defaultCheckedState_;
70 }
71
72
73
74
75
76 @Override
77 public boolean isChecked() {
78 return checkedState_;
79 }
80
81
82
83
84
85 @Override
86 public void reset() {
87 setChecked(defaultCheckedState_);
88 }
89
90 void setCheckedInternal(final boolean isChecked) {
91 checkedState_ = isChecked;
92 }
93
94
95
96
97
98
99
100
101 @Override
102 public Page setChecked(final boolean isChecked) {
103 Page page = getPage();
104
105 final boolean changed = isChecked() != isChecked;
106 checkedState_ = isChecked;
107 if (isChecked) {
108 final HtmlForm form = getEnclosingForm();
109 if (form != null) {
110 form.setCheckedRadioButton(this);
111 }
112 else if (page != null && page.isHtmlPage()) {
113 setCheckedForPage((HtmlPage) page);
114 }
115 }
116
117 if (changed) {
118 final ScriptResult scriptResult = fireEvent(Event.TYPE_CHANGE);
119 if (scriptResult != null && page != null) {
120 page = page.getEnclosingWindow().getWebClient().getCurrentWindow().getEnclosedPage();
121 }
122 }
123 return page;
124 }
125
126
127
128
129
130
131
132
133 @Override
134 protected boolean doClickStateUpdate(final boolean shiftKey, final boolean ctrlKey) throws IOException {
135 final HtmlForm form = getEnclosingForm();
136 final boolean changed = !isChecked();
137
138 final Page page = getPage();
139 if (form != null) {
140 form.setCheckedRadioButton(this);
141 }
142 else if (page != null && page.isHtmlPage()) {
143 setCheckedForPage((HtmlPage) page);
144 }
145 super.doClickStateUpdate(shiftKey, ctrlKey);
146 return changed;
147 }
148
149
150
151
152 private void setCheckedForPage(final HtmlPage htmlPage) {
153 final String name = getNameAttribute();
154 for (final HtmlElement htmlElement : htmlPage.getHtmlElementDescendants()) {
155 if (htmlElement instanceof HtmlRadioButtonInput) {
156 final HtmlRadioButtonInput radioInput = (HtmlRadioButtonInput) htmlElement;
157 if (name.equals(radioInput.getAttribute(NAME_ATTRIBUTE))
158 && radioInput.getEnclosingForm() == null) {
159 if (radioInput == this) {
160 setCheckedInternal(true);
161 }
162 else {
163 radioInput.setCheckedInternal(false);
164 }
165 }
166 }
167 }
168 }
169
170
171
172
173 @Override
174 protected void doClickFireChangeEvent() {
175 executeOnChangeHandlerIfAppropriate(this);
176 }
177
178
179
180
181 @Override
182 protected void preventDefault() {
183 checkedState_ = !checkedState_;
184 }
185
186
187
188
189
190
191 @Override
192 public void setDefaultValue(final String defaultValue) {
193 super.setDefaultValue(defaultValue);
194 setValue(defaultValue);
195 }
196
197
198
199
200
201 @Override
202 public void setValue(final String newValue) {
203 super.setValue(newValue);
204 super.setDefaultValue(newValue);
205 }
206
207
208
209
210
211 @Override
212 public void setDefaultChecked(final boolean defaultChecked) {
213 defaultCheckedState_ = defaultChecked;
214 setChecked(isDefaultChecked());
215 }
216
217
218
219
220
221 @Override
222 public boolean isDefaultChecked() {
223 return defaultCheckedState_;
224 }
225
226
227
228
229 @Override
230 protected boolean isStateUpdateFirst() {
231 return true;
232 }
233
234
235
236
237 @Override
238 protected void onAddedToPage() {
239 super.onAddedToPage();
240 setChecked(isChecked());
241 }
242
243 @Override
244 protected Object getInternalValue() {
245 return isChecked();
246 }
247
248 @Override
249 void handleFocusLostValueChanged() {
250
251 }
252
253
254
255
256 @Override
257 protected void setAttributeNS(final String namespaceURI, final String qualifiedName, final String attributeValue,
258 final boolean notifyAttributeChangeListeners, final boolean notifyMutationObservers) {
259 final String qualifiedNameLC = org.htmlunit.util.StringUtils.toRootLowerCase(qualifiedName);
260
261 if (VALUE_ATTRIBUTE.equals(qualifiedNameLC)) {
262 super.setAttributeNS(namespaceURI, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
263 notifyMutationObservers);
264 setRawValue(attributeValue);
265 return;
266 }
267
268 if (ATTRIBUTE_CHECKED.equals(qualifiedNameLC)) {
269 checkedState_ = true;
270 }
271 super.setAttributeNS(namespaceURI, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
272 notifyMutationObservers);
273 }
274
275
276
277
278 @Override
279 protected boolean propagateClickStateUpdateToParent() {
280 return false;
281 }
282
283 @Override
284 public boolean isValueMissingValidityState() {
285 if (ATTRIBUTE_NOT_DEFINED == getAttributeDirect(ATTRIBUTE_REQUIRED)) {
286 return false;
287 }
288 if (ATTRIBUTE_NOT_DEFINED == getNameAttribute()) {
289 return false;
290 }
291
292 final String name = getNameAttribute();
293 for (final HtmlElement htmlElement : getPage().getHtmlElementDescendants()) {
294 if (htmlElement instanceof HtmlRadioButtonInput) {
295 final HtmlRadioButtonInput radioInput = (HtmlRadioButtonInput) htmlElement;
296 if (name.equals(radioInput.getAttribute(NAME_ATTRIBUTE))
297 && radioInput.isChecked()) {
298 return false;
299 }
300 }
301 }
302 return true;
303 }
304 }