1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import static org.htmlunit.BrowserVersionFeatures.HTMLBUTTON_WILL_VALIDATE_IGNORES_READONLY;
18 import static org.htmlunit.html.HtmlForm.ATTRIBUTE_FORMNOVALIDATE;
19
20 import java.io.IOException;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Map;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.htmlunit.SgmlPage;
30 import org.htmlunit.javascript.host.event.Event;
31 import org.htmlunit.javascript.host.event.MouseEvent;
32 import org.htmlunit.util.NameValuePair;
33 import org.w3c.dom.Node;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class HtmlButton extends HtmlElement implements DisabledElement, SubmittableElement,
50 LabelableElement, FormFieldWithNameHistory, ValidatableElement {
51
52 private static final Log LOG = LogFactory.getLog(HtmlButton.class);
53
54
55 public static final String TAG_NAME = "button";
56
57 private static final String TYPE_SUBMIT = "submit";
58 private static final String TYPE_RESET = "reset";
59 private static final String TYPE_BUTTON = "button";
60
61 private final String originalName_;
62 private Collection<String> newNames_ = Collections.emptySet();
63 private String customValidity_;
64
65
66
67
68
69
70
71
72 HtmlButton(final String qualifiedName, final SgmlPage page,
73 final Map<String, DomAttr> attributes) {
74 super(qualifiedName, page, attributes);
75 originalName_ = getNameAttribute();
76 }
77
78
79
80
81
82
83 public void setValueAttribute(final String newValue) {
84 setAttribute(VALUE_ATTRIBUTE, newValue);
85 }
86
87
88
89
90 @Override
91 protected boolean doClickStateUpdate(final boolean shiftKey, final boolean ctrlKey) throws IOException {
92 if (!isDisabled()) {
93 final HtmlForm form = getEnclosingForm();
94 if (form != null) {
95 final String type = getType();
96 if (TYPE_BUTTON.equals(type)) {
97 return false;
98 }
99
100 if (TYPE_RESET.equals(type)) {
101 form.reset();
102 return false;
103 }
104
105 form.submit(this);
106 return false;
107 }
108 }
109
110 super.doClickStateUpdate(shiftKey, ctrlKey);
111 return false;
112 }
113
114
115
116
117 @Override
118 public final boolean isDisabled() {
119 if (hasAttribute(ATTRIBUTE_DISABLED)) {
120 return true;
121 }
122
123 Node node = getParentNode();
124 while (node != null) {
125 if (node instanceof DisabledElement
126 && ((DisabledElement) node).isDisabled()) {
127 return true;
128 }
129 node = node.getParentNode();
130 }
131
132 return false;
133 }
134
135
136
137
138
139 public boolean isReadOnly() {
140 return hasAttribute("readOnly");
141 }
142
143
144
145
146 @Override
147 public NameValuePair[] getSubmitNameValuePairs() {
148 return new NameValuePair[]{new NameValuePair(getNameAttribute(), getValueAttribute())};
149 }
150
151
152
153
154
155
156 @Override
157 public void reset() {
158 LOG.debug("reset() not implemented for this element");
159 }
160
161
162
163
164
165
166 @Override
167 public void setDefaultValue(final String defaultValue) {
168 LOG.debug("setDefaultValue() not implemented for this element");
169 }
170
171
172
173
174
175
176 @Override
177 public String getDefaultValue() {
178 LOG.debug("getDefaultValue() not implemented for this element");
179 return "";
180 }
181
182
183
184
185
186
187
188
189
190
191
192 @Override
193 public void setDefaultChecked(final boolean defaultChecked) {
194
195 }
196
197
198
199
200
201
202
203
204
205
206
207 @Override
208 public boolean isDefaultChecked() {
209 return false;
210 }
211
212
213
214
215 @Override
216 public boolean handles(final Event event) {
217 if (event instanceof MouseEvent) {
218 return true;
219 }
220
221 return super.handles(event);
222 }
223
224
225
226
227
228
229
230
231 public final String getNameAttribute() {
232 return getAttributeDirect(NAME_ATTRIBUTE);
233 }
234
235
236
237
238
239
240
241
242 public final String getValueAttribute() {
243 return getAttributeDirect(VALUE_ATTRIBUTE);
244 }
245
246
247
248
249
250
251
252
253 public final String getTypeAttribute() {
254 return getAttribute(TYPE_ATTRIBUTE);
255 }
256
257
258
259
260 public String getType() {
261 final String type = getTypeAttribute();
262 if (TYPE_RESET.equalsIgnoreCase(type)) {
263 return TYPE_RESET;
264 }
265 if (TYPE_BUTTON.equalsIgnoreCase(type)) {
266 return TYPE_BUTTON;
267 }
268 return TYPE_SUBMIT;
269 }
270
271
272
273
274
275
276
277
278 @Override
279 public final String getDisabledAttribute() {
280 return getAttributeDirect(ATTRIBUTE_DISABLED);
281 }
282
283
284
285
286
287
288
289
290 public final String getTabIndexAttribute() {
291 return getAttributeDirect("tabindex");
292 }
293
294
295
296
297
298
299
300
301 public final String getAccessKeyAttribute() {
302 return getAttributeDirect("accesskey");
303 }
304
305
306
307
308
309
310
311
312 public final String getOnFocusAttribute() {
313 return getAttributeDirect("onfocus");
314 }
315
316
317
318
319
320
321
322
323 public final String getOnBlurAttribute() {
324 return getAttributeDirect("onblur");
325 }
326
327
328
329
330 @Override
331 protected void setAttributeNS(final String namespaceURI, final String qualifiedName, final String attributeValue,
332 final boolean notifyAttributeChangeListeners, final boolean notifyMutationObservers) {
333 final String qualifiedNameLC = org.htmlunit.util.StringUtils.toRootLowerCase(qualifiedName);
334 if (NAME_ATTRIBUTE.equals(qualifiedNameLC)) {
335 if (newNames_.isEmpty()) {
336 newNames_ = new HashSet<>();
337 }
338 newNames_.add(attributeValue);
339 }
340 super.setAttributeNS(namespaceURI, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
341 notifyMutationObservers);
342 }
343
344
345
346
347 @Override
348 public String getOriginalName() {
349 return originalName_;
350 }
351
352
353
354
355 @Override
356 public Collection<String> getNewNames() {
357 return newNames_;
358 }
359
360
361
362
363 @Override
364 public DisplayStyle getDefaultStyleDisplay() {
365 return DisplayStyle.INLINE_BLOCK;
366 }
367
368
369
370
371
372 @Override
373 protected boolean isEmptyXmlTagExpanded() {
374 return true;
375 }
376
377
378
379
380 @Override
381 public boolean isValid() {
382 if (TYPE_RESET.equals(getType())) {
383 return true;
384 }
385
386 return super.isValid() && !isCustomErrorValidityState();
387 }
388
389
390
391
392 @Override
393 public boolean willValidate() {
394 if (TYPE_RESET.equals(getType()) || TYPE_BUTTON.equals(getType())) {
395 return false;
396 }
397
398 return !isDisabled()
399 && (hasFeature(HTMLBUTTON_WILL_VALIDATE_IGNORES_READONLY) || !isReadOnly());
400 }
401
402
403
404
405 @Override
406 public void setCustomValidity(final String message) {
407 customValidity_ = message;
408 }
409
410
411
412
413 @Override
414 public boolean isCustomErrorValidityState() {
415 return !StringUtils.isEmpty(customValidity_);
416 }
417
418 @Override
419 public boolean isValidValidityState() {
420 return !isCustomErrorValidityState();
421 }
422
423
424
425
426 public final boolean isFormNoValidate() {
427 return hasAttribute(ATTRIBUTE_FORMNOVALIDATE);
428 }
429
430
431
432
433
434
435 public final void setFormNoValidate(final boolean noValidate) {
436 if (noValidate) {
437 setAttribute(ATTRIBUTE_FORMNOVALIDATE, ATTRIBUTE_FORMNOVALIDATE);
438 }
439 else {
440 removeAttribute(ATTRIBUTE_FORMNOVALIDATE);
441 }
442 }
443 }