1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.html;
16
17 import static org.htmlunit.BrowserVersionFeatures.JS_INPUT_NUMBER_DOT_AT_END_IS_DOUBLE;
18 import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
19 import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
20
21 import java.io.IOException;
22
23 import org.htmlunit.html.DomElement;
24 import org.htmlunit.html.DomNode;
25 import org.htmlunit.html.HtmlCheckBoxInput;
26 import org.htmlunit.html.HtmlFileInput;
27 import org.htmlunit.html.HtmlInput;
28 import org.htmlunit.html.HtmlNumberInput;
29 import org.htmlunit.html.HtmlRadioButtonInput;
30 import org.htmlunit.html.HtmlTextInput;
31 import org.htmlunit.html.impl.SelectableTextInput;
32 import org.htmlunit.javascript.JavaScriptEngine;
33 import org.htmlunit.javascript.configuration.JsxClass;
34 import org.htmlunit.javascript.configuration.JsxConstructor;
35 import org.htmlunit.javascript.configuration.JsxFunction;
36 import org.htmlunit.javascript.configuration.JsxGetter;
37 import org.htmlunit.javascript.configuration.JsxSetter;
38 import org.htmlunit.javascript.host.DOMRectList;
39 import org.htmlunit.javascript.host.Window;
40 import org.htmlunit.javascript.host.dom.DOMException;
41 import org.htmlunit.javascript.host.dom.NodeList;
42 import org.htmlunit.javascript.host.event.Event;
43 import org.htmlunit.javascript.host.file.FileList;
44 import org.htmlunit.util.StringUtils;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 @JsxClass(domClass = HtmlInput.class)
60 public class HTMLInputElement extends HTMLElement {
61
62
63 private NodeList labels_;
64
65
66
67
68 @Override
69 @JsxConstructor
70 public void jsConstructor() {
71 super.jsConstructor();
72 }
73
74
75
76
77
78 @JsxGetter
79 public String getType() {
80 return getDomNodeOrDie().getType();
81 }
82
83
84
85
86
87
88 @JsxSetter
89 public void setType(final String newType) {
90 getDomNodeOrDie().changeType(newType, false);
91 }
92
93
94
95
96
97
98 @JsxSetter
99 @Override
100 public void setValue(final Object newValue) {
101 if (null == newValue) {
102 getDomNodeOrDie().setValue("");
103 getDomNodeOrDie().valueModifiedByJavascript();
104 return;
105 }
106
107 final String val = JavaScriptEngine.toString(newValue);
108 if ("file".equals(getType())) {
109 if (!StringUtils.isEmptyOrNull(val)) {
110 throw JavaScriptEngine.asJavaScriptException(
111 getWindow(),
112 "Failed to set the 'value' property on 'HTMLInputElement'.",
113 DOMException.INVALID_STATE_ERR);
114 }
115 return;
116 }
117
118 getDomNodeOrDie().setValue(val);
119 getDomNodeOrDie().valueModifiedByJavascript();
120 }
121
122
123
124
125
126
127
128
129
130 @JsxSetter
131 public void setChecked(final boolean checked) {
132 getDomNodeOrDie().setChecked(checked);
133 }
134
135
136
137
138 @Override
139 public HtmlInput getDomNodeOrDie() {
140 return (HtmlInput) super.getDomNodeOrDie();
141 }
142
143
144
145
146
147
148
149
150
151 @JsxGetter
152 public boolean isChecked() {
153 return getDomNodeOrDie().isChecked();
154 }
155
156
157
158
159 @JsxFunction
160 public void select() {
161 final HtmlInput input = getDomNodeOrDie();
162 if (input instanceof HtmlTextInput) {
163 ((HtmlTextInput) input).select();
164 }
165
166 }
167
168
169
170
171
172
173 @JsxGetter
174 public String getDefaultValue() {
175 return getDomNodeOrDie().getDefaultValue();
176 }
177
178
179
180
181
182
183 @JsxSetter
184 public void setDefaultValue(final String defaultValue) {
185 getDomNodeOrDie().setDefaultValue(defaultValue);
186 }
187
188
189
190
191
192
193 @JsxGetter
194 public boolean isDefaultChecked() {
195 return getDomNodeOrDie().isDefaultChecked();
196 }
197
198
199
200
201
202
203 @JsxSetter
204 public void setDefaultChecked(final boolean defaultChecked) {
205 getDomNodeOrDie().setDefaultChecked(defaultChecked);
206 }
207
208
209
210
211
212 @JsxGetter({FF, FF_ESR})
213 public int getTextLength() {
214 return getValue().length();
215 }
216
217
218
219
220
221 @JsxGetter
222 public Integer getSelectionStart() {
223 final DomNode dom = getDomNodeOrDie();
224 if (dom instanceof SelectableTextInput) {
225 if ("number".equals(getType())) {
226 return null;
227 }
228
229 return ((SelectableTextInput) dom).getSelectionStart();
230 }
231
232 return null;
233 }
234
235
236
237
238
239 @JsxSetter
240 public void setSelectionStart(final int start) {
241 final DomNode dom = getDomNodeOrDie();
242 if (dom instanceof SelectableTextInput) {
243 if ("number".equals(getType())) {
244 throw JavaScriptEngine.asJavaScriptException(
245 getWindow(),
246 "Failed to set the 'selectionStart' property"
247 + "from 'HTMLInputElement': "
248 + "The input element's type ('number') does not support selection.",
249 DOMException.INVALID_STATE_ERR);
250 }
251
252 ((SelectableTextInput) dom).setSelectionStart(start);
253 return;
254 }
255
256 throw JavaScriptEngine.asJavaScriptException(
257 getWindow(),
258 "Failed to set the 'selectionStart' property from 'HTMLInputElement': "
259 + "The input element's type (" + getType() + ") does not support selection.",
260 DOMException.INVALID_STATE_ERR);
261 }
262
263
264
265
266
267 @JsxGetter
268 public Integer getSelectionEnd() {
269 final DomNode dom = getDomNodeOrDie();
270 if (dom instanceof SelectableTextInput) {
271 if ("number".equals(getType())) {
272 return null;
273 }
274
275 return ((SelectableTextInput) dom).getSelectionEnd();
276 }
277
278 return null;
279 }
280
281
282
283
284
285 @JsxSetter
286 public void setSelectionEnd(final int end) {
287 final DomNode dom = getDomNodeOrDie();
288 if (dom instanceof SelectableTextInput) {
289 if ("number".equals(getType())) {
290 throw JavaScriptEngine.asJavaScriptException(
291 getWindow(),
292 "Failed to set the 'selectionEnd' property"
293 + "from 'HTMLInputElement': "
294 + "The input element's type ('number') does not support selection.",
295 DOMException.INVALID_STATE_ERR);
296 }
297
298 ((SelectableTextInput) dom).setSelectionEnd(end);
299 return;
300 }
301
302 throw JavaScriptEngine.asJavaScriptException(
303 getWindow(),
304 "Failed to set the 'selectionEnd' property from 'HTMLInputElement': "
305 + "The input element's type (" + getType() + ") does not support selection.",
306 DOMException.INVALID_STATE_ERR);
307 }
308
309
310
311
312
313 @JsxGetter
314 public int getMaxLength() {
315 final String attrValue = getDomNodeOrDie().getAttribute("maxLength");
316 return StringUtils.toInt(attrValue, -1);
317 }
318
319
320
321
322
323 @JsxSetter
324 public void setMaxLength(final int length) {
325 getDomNodeOrDie().setMaxLength(length);
326 }
327
328
329
330
331
332 @JsxGetter
333 public int getMinLength() {
334 final String attrValue = getDomNodeOrDie().getAttribute("minLength");
335 return StringUtils.toInt(attrValue, -1);
336 }
337
338
339
340
341
342 @JsxSetter
343 public void setMinLength(final int length) {
344 getDomNodeOrDie().setMinLength(length);
345 }
346
347
348
349
350
351 @JsxGetter
352 public String getMin() {
353 return getDomNodeOrDie().getAttributeDirect("min");
354 }
355
356
357
358
359
360 @JsxSetter
361 public void setMin(final String min) {
362 getDomNodeOrDie().setAttribute("min", min);
363 }
364
365
366
367
368
369 @JsxGetter
370 public String getMax() {
371 return getDomNodeOrDie().getAttributeDirect("max");
372 }
373
374
375
376
377
378 @JsxSetter
379 public void setMax(final String max) {
380 getDomNodeOrDie().setAttribute("max", max);
381 }
382
383
384
385
386
387 @JsxGetter
388 public String getStep() {
389 return getDomNodeOrDie().getAttributeDirect("step");
390 }
391
392
393
394
395
396 @JsxSetter
397 public void setStep(final String step) {
398 getDomNodeOrDie().setAttribute("step", step);
399 }
400
401
402
403
404
405 @JsxGetter
406 public boolean isReadOnly() {
407 return getDomNodeOrDie().isReadOnly();
408 }
409
410
411
412
413
414 @JsxSetter
415 public void setReadOnly(final boolean readOnly) {
416 getDomNodeOrDie().setReadOnly(readOnly);
417 }
418
419
420
421
422
423
424 @JsxFunction
425 public void setSelectionRange(final int start, final int end) {
426 setSelectionStart(start);
427 setSelectionEnd(end);
428 }
429
430
431
432
433
434 @JsxGetter
435 public String getAlt() {
436 return getDomNodeOrDie().getAttributeDirect("alt");
437 }
438
439
440
441
442
443 @JsxSetter
444 public void setAlt(final String alt) {
445 getDomNodeOrDie().setAttribute("alt", alt);
446 }
447
448
449
450
451
452 @JsxGetter
453 public String getAlign() {
454 return getAlign(true);
455 }
456
457
458
459
460
461 @JsxSetter
462 public void setAlign(final String align) {
463 setAlign(align, false);
464 }
465
466
467
468
469
470 @JsxGetter
471 public String getSrc() {
472 return getDomNodeOrDie().getSrc();
473 }
474
475
476
477
478
479 @JsxSetter
480 public void setSrc(final String src) {
481 getDomNodeOrDie().setSrcAttribute(src);
482 }
483
484
485
486
487
488
489 @JsxGetter
490 @Override
491 public String getValue() {
492 final HtmlInput htmlInput = getDomNodeOrDie();
493
494 if (htmlInput instanceof HtmlNumberInput) {
495 final String valueAttr = htmlInput.getValue();
496 if (!valueAttr.isEmpty()) {
497 if (org.htmlunit.util.StringUtils.equalsChar('-', valueAttr)
498 || org.htmlunit.util.StringUtils.equalsChar('+', valueAttr)) {
499 return "";
500 }
501
502 final int lastPos = valueAttr.length() - 1;
503 if (lastPos >= 0 && valueAttr.charAt(lastPos) == '.') {
504 if (htmlInput.hasFeature(JS_INPUT_NUMBER_DOT_AT_END_IS_DOUBLE)) {
505 return "";
506 }
507 }
508 try {
509 Double.parseDouble(valueAttr);
510 }
511 catch (final NumberFormatException e) {
512 return "";
513 }
514 }
515 }
516
517 return htmlInput.getValue();
518 }
519
520
521
522
523 @Override
524 public String getAttribute(final String attributeName) {
525 final String superAttribute = super.getAttribute(attributeName);
526 if (DomElement.VALUE_ATTRIBUTE.equalsIgnoreCase(attributeName)) {
527 if ((superAttribute == null || !superAttribute.isEmpty())
528 && getDefaultValue().isEmpty()) {
529 return null;
530 }
531 if (!"file".equals(getType())) {
532 return getDefaultValue();
533 }
534 }
535 return superAttribute;
536 }
537
538
539
540
541 @Override
542 public void click() throws IOException {
543 final HtmlInput domNode = getDomNodeOrDie();
544 final boolean originalState = domNode.isChecked();
545
546 domNode.click(false, false, false, false, false, true, false);
547
548 final boolean newState = domNode.isChecked();
549
550 if (originalState != newState
551 && (domNode instanceof HtmlRadioButtonInput || domNode instanceof HtmlCheckBoxInput)) {
552 domNode.fireEvent(Event.TYPE_CHANGE);
553 }
554 }
555
556
557
558
559 @Override
560 protected boolean isEndTagForbidden() {
561 return true;
562 }
563
564
565
566
567
568 @JsxGetter
569 public boolean isRequired() {
570 return getDomNodeOrDie().isRequired();
571 }
572
573
574
575
576
577 @JsxSetter
578 public void setRequired(final boolean required) {
579 getDomNodeOrDie().setRequired(required);
580 }
581
582
583
584
585
586 @JsxGetter
587 public String getSize() {
588 return getDomNodeOrDie().getSize();
589 }
590
591
592
593
594
595 @JsxSetter
596 public void setSize(final String size) {
597 getDomNodeOrDie().setSize(size);
598 }
599
600
601
602
603
604 @JsxGetter
605 public String getAccept() {
606 return getDomNodeOrDie().getAccept();
607 }
608
609
610
611
612
613 @JsxSetter
614 public void setAccept(final String accept) {
615 getDomNodeOrDie().setAccept(accept);
616 }
617
618
619
620
621
622 @JsxGetter
623 public String getAutocomplete() {
624 return getDomNodeOrDie().getAutocomplete();
625 }
626
627
628
629
630
631 @JsxSetter
632 public void setAutocomplete(final String autocomplete) {
633 getDomNodeOrDie().setAutocomplete(autocomplete);
634 }
635
636
637
638
639
640 @JsxGetter
641 public FileList getFiles() {
642 final HtmlInput htmlInput = getDomNodeOrDie();
643 if (htmlInput instanceof HtmlFileInput) {
644 final FileList list = new FileList(((HtmlFileInput) htmlInput).getFiles());
645 list.setParentScope(getParentScope());
646 list.setPrototype(getPrototype(list.getClass()));
647 return list;
648 }
649 return null;
650 }
651
652
653
654
655
656 @JsxGetter
657 public String getPlaceholder() {
658 return getDomNodeOrDie().getPlaceholder();
659 }
660
661
662
663
664
665 @JsxSetter
666 public void setPlaceholder(final String placeholder) {
667 getDomNodeOrDie().setPlaceholder(placeholder);
668 }
669
670
671
672
673
674 @JsxGetter
675 public int getWidth() {
676 final String value = getDomNodeOrDie().getAttributeDirect("width");
677 final Integer intValue = HTMLCanvasElement.getValue(value);
678 if (intValue != null) {
679 return intValue;
680 }
681 return 0;
682 }
683
684
685
686
687
688 @JsxSetter
689 public void setWidth(final int width) {
690 getDomNodeOrDie().setAttribute("width", Integer.toString(width));
691 }
692
693
694
695
696
697 @JsxGetter
698 public int getHeight() {
699 final String value = getDomNodeOrDie().getAttributeDirect("height");
700 final Integer intValue = HTMLCanvasElement.getValue(value);
701 if (intValue != null) {
702 return intValue;
703 }
704 return 0;
705 }
706
707
708
709
710
711 @JsxSetter
712 public void setHeight(final int height) {
713 getDomNodeOrDie().setAttribute("height", Integer.toString(height));
714 }
715
716
717
718
719
720 @JsxGetter
721 public NodeList getLabels() {
722 if (labels_ == null) {
723 labels_ = new LabelsNodeList(getDomNodeOrDie());
724 }
725 return labels_;
726 }
727
728
729
730
731
732 @JsxFunction
733 public boolean checkValidity() {
734 return getDomNodeOrDie().isValid();
735 }
736
737
738
739
740 @JsxGetter
741 @Override
742 public String getName() {
743 return super.getName();
744 }
745
746
747
748
749 @JsxSetter
750 @Override
751 public void setName(final String newName) {
752 super.setName(newName);
753 }
754
755
756
757
758 @Override
759 @JsxGetter
760 public boolean isDisabled() {
761 return super.isDisabled();
762 }
763
764
765
766
767 @Override
768 @JsxSetter
769 public void setDisabled(final boolean disabled) {
770 super.setDisabled(disabled);
771 }
772
773
774
775
776 @JsxGetter
777 @Override
778 public HTMLFormElement getForm() {
779 return super.getForm();
780 }
781
782
783
784
785 @JsxGetter
786 public ValidityState getValidity() {
787 final ValidityState validityState = new ValidityState();
788 validityState.setPrototype(getPrototype(validityState.getClass()));
789 validityState.setParentScope(getParentScope());
790 validityState.setDomNode(getDomNodeOrDie());
791 return validityState;
792 }
793
794
795
796
797 @JsxGetter
798 public boolean isWillValidate() {
799 return getDomNodeOrDie().willValidate();
800 }
801
802
803
804
805
806 @JsxFunction
807 public void setCustomValidity(final String message) {
808 getDomNodeOrDie().setCustomValidity(message);
809 }
810
811
812
813
814
815 @JsxGetter
816 public boolean isFormNoValidate() {
817 return getDomNodeOrDie().isFormNoValidate();
818 }
819
820
821
822
823
824 @JsxSetter
825 public void setFormNoValidate(final boolean value) {
826 getDomNodeOrDie().setFormNoValidate(value);
827 }
828
829
830
831
832 @Override
833 public DOMRectList getClientRects() {
834 if ("hidden".equals(getType())) {
835 final Window w = getWindow();
836 final DOMRectList rectList = new DOMRectList();
837 rectList.setParentScope(w);
838 rectList.setPrototype(getPrototype(rectList.getClass()));
839
840 return rectList;
841 }
842
843 return super.getClientRects();
844 }
845 }