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.HTMLINPUT_TYPE_IMAGE_IGNORES_CUSTOM_VALIDITY;
18 import static org.htmlunit.BrowserVersionFeatures.HTMLINPUT_TYPE_MONTH_SUPPORTED;
19 import static org.htmlunit.BrowserVersionFeatures.HTMLINPUT_TYPE_WEEK_SUPPORTED;
20 import static org.htmlunit.html.HtmlForm.ATTRIBUTE_FORMNOVALIDATE;
21
22 import java.net.MalformedURLException;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.Locale;
27 import java.util.Map;
28
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.htmlunit.BrowserVersion;
33 import org.htmlunit.HttpHeader;
34 import org.htmlunit.Page;
35 import org.htmlunit.ScriptResult;
36 import org.htmlunit.SgmlPage;
37 import org.htmlunit.WebClient;
38 import org.htmlunit.corejs.javascript.Context;
39 import org.htmlunit.corejs.javascript.regexp.RegExpEngineAccess;
40 import org.htmlunit.javascript.AbstractJavaScriptEngine;
41 import org.htmlunit.javascript.HtmlUnitContextFactory;
42 import org.htmlunit.javascript.host.event.Event;
43 import org.htmlunit.javascript.host.event.MouseEvent;
44 import org.htmlunit.javascript.host.html.HTMLInputElement;
45 import org.htmlunit.util.NameValuePair;
46 import org.xml.sax.helpers.AttributesImpl;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public abstract class HtmlInput extends HtmlElement implements DisabledElement, SubmittableElement,
64 FormFieldWithNameHistory, ValidatableElement {
65
66 private static final Log LOG = LogFactory.getLog(HtmlInput.class);
67
68
69 public static final String TAG_NAME = "input";
70
71 private String rawValue_;
72 private boolean isValueDirty_;
73 private final String originalName_;
74 private Collection<String> newNames_ = Collections.emptySet();
75 private boolean valueModifiedByJavascript_;
76 private Object valueAtFocus_;
77 private String customValidity_;
78
79
80
81
82
83
84
85 public HtmlInput(final SgmlPage page, final Map<String, DomAttr> attributes) {
86 this(TAG_NAME, page, attributes);
87 }
88
89
90
91
92
93
94
95
96 public HtmlInput(final String qualifiedName, final SgmlPage page,
97 final Map<String, DomAttr> attributes) {
98 super(qualifiedName, page, attributes);
99 rawValue_ = getValueAttribute();
100 originalName_ = getNameAttribute();
101 }
102
103
104
105
106
107
108 public void setValueAttribute(final String newValue) {
109 super.setAttribute(VALUE_ATTRIBUTE, newValue);
110 }
111
112
113
114
115 @Override
116 public NameValuePair[] getSubmitNameValuePairs() {
117 return new NameValuePair[]{new NameValuePair(getNameAttribute(), getValue())};
118 }
119
120
121
122
123
124
125
126
127 public final String getTypeAttribute() {
128 final String type = getAttributeDirect(TYPE_ATTRIBUTE);
129 if (ATTRIBUTE_NOT_DEFINED == type) {
130 return "text";
131 }
132 return type;
133 }
134
135
136
137
138
139
140
141
142 public final String getNameAttribute() {
143 return getAttributeDirect(NAME_ATTRIBUTE);
144 }
145
146
147
148
149
150
151
152
153 public final String getValueAttribute() {
154 return getAttributeDirect(VALUE_ATTRIBUTE);
155 }
156
157
158
159
160 public String getValue() {
161 return getRawValue();
162 }
163
164
165
166
167
168
169 public void setValue(final String newValue) {
170 setRawValue(newValue);
171 isValueDirty_ = true;
172 }
173
174 protected void valueAttributeChanged(final String attributeValue, final boolean isValueDirty) {
175 if (!isValueDirty_) {
176 setRawValue(attributeValue);
177 }
178 }
179
180
181
182
183
184
185
186
187 public final String getCheckedAttribute() {
188 return getAttributeDirect(ATTRIBUTE_CHECKED);
189 }
190
191
192
193
194 @Override
195 public final String getDisabledAttribute() {
196 return getAttributeDirect(ATTRIBUTE_DISABLED);
197 }
198
199
200
201
202 @Override
203 public final boolean isDisabled() {
204 if (hasAttribute(ATTRIBUTE_DISABLED)) {
205 return true;
206 }
207
208 DomNode node = getParentNode();
209 while (node != null) {
210 if (node instanceof DisabledElement
211 && ((DisabledElement) node).isDisabled()) {
212 return true;
213 }
214 node = node.getParentNode();
215 }
216
217 return false;
218 }
219
220
221
222
223
224
225
226
227
228 public final String getReadOnlyAttribute() {
229 return getAttributeDirect("readonly");
230 }
231
232
233
234
235
236
237
238
239
240 public final String getSizeAttribute() {
241 return getAttributeDirect("size");
242 }
243
244
245
246
247
248
249
250
251
252 public final String getMaxLengthAttribute() {
253 return getAttribute("maxLength");
254 }
255
256
257
258
259
260 protected int getMaxLength() {
261 final String maxLength = getMaxLengthAttribute();
262 if (maxLength.isEmpty()) {
263 return Integer.MAX_VALUE;
264 }
265
266 try {
267 return Integer.parseInt(maxLength.trim());
268 }
269 catch (final NumberFormatException e) {
270 return Integer.MAX_VALUE;
271 }
272 }
273
274
275
276
277
278
279
280
281
282 public final String getMinLengthAttribute() {
283 return getAttribute("minLength");
284 }
285
286
287
288
289
290 protected int getMinLength() {
291 final String minLength = getMinLengthAttribute();
292 if (minLength.isEmpty()) {
293 return Integer.MIN_VALUE;
294 }
295
296 try {
297 return Integer.parseInt(minLength.trim());
298 }
299 catch (final NumberFormatException e) {
300 return Integer.MIN_VALUE;
301 }
302 }
303
304
305
306
307
308
309
310
311
312 public String getSrcAttribute() {
313 return getSrcAttributeNormalized();
314 }
315
316
317
318
319
320 public String getSrc() {
321 final String src = getSrcAttributeNormalized();
322 if (ATTRIBUTE_NOT_DEFINED == src) {
323 return src;
324 }
325
326 final HtmlPage page = getHtmlPageOrNull();
327 if (page != null) {
328 try {
329 return page.getFullyQualifiedUrl(src).toExternalForm();
330 }
331 catch (final MalformedURLException e) {
332
333 if (LOG.isWarnEnabled()) {
334 LOG.warn(e.getMessage(), e);
335 }
336 }
337 }
338 return src;
339 }
340
341
342
343
344
345
346 public void setSrcAttribute(final String src) {
347 setAttribute(SRC_ATTRIBUTE, src);
348 }
349
350
351
352
353
354
355
356
357
358 public final String getAltAttribute() {
359 return getAttributeDirect("alt");
360 }
361
362
363
364
365
366
367
368
369
370 public final String getUseMapAttribute() {
371 return getAttributeDirect("usemap");
372 }
373
374
375
376
377
378
379
380
381
382 public final String getTabIndexAttribute() {
383 return getAttributeDirect("tabindex");
384 }
385
386
387
388
389
390
391
392
393
394 public final String getAccessKeyAttribute() {
395 return getAttributeDirect("accesskey");
396 }
397
398
399
400
401
402
403
404
405
406 public final String getOnFocusAttribute() {
407 return getAttributeDirect("onfocus");
408 }
409
410
411
412
413
414
415
416
417
418 public final String getOnBlurAttribute() {
419 return getAttributeDirect("onblur");
420 }
421
422
423
424
425
426
427
428
429
430 public final String getOnSelectAttribute() {
431 return getAttributeDirect("onselect");
432 }
433
434
435
436
437
438
439
440
441
442 public final String getOnChangeAttribute() {
443 return getAttributeDirect("onchange");
444 }
445
446
447
448
449
450
451
452
453
454 public final String getAcceptAttribute() {
455 return getAttribute(HttpHeader.ACCEPT_LC);
456 }
457
458
459
460
461
462
463
464
465
466 public final String getAlignAttribute() {
467 return getAttributeDirect("align");
468 }
469
470
471
472
473
474 @Override
475 public void reset() {
476 setValue(getDefaultValue());
477 isValueDirty_ = true;
478 }
479
480
481
482
483
484
485 @Override
486 public void setDefaultValue(final String defaultValue) {
487 setValueAttribute(defaultValue);
488 }
489
490
491
492
493
494 @Override
495 public String getDefaultValue() {
496 return getValueAttribute();
497 }
498
499
500
501
502
503
504 public String getRawValue() {
505 return rawValue_;
506 }
507
508
509
510
511
512
513
514 public void setRawValue(final String rawValue) {
515 rawValue_ = rawValue;
516 }
517
518
519
520
521
522
523
524
525 @Override
526 public boolean isDefaultChecked() {
527 return false;
528 }
529
530
531
532
533
534
535
536
537
538 public Page setChecked(final boolean isChecked) {
539
540 return getPage();
541 }
542
543
544
545
546
547
548 public void setReadOnly(final boolean isReadOnly) {
549 if (isReadOnly) {
550 setAttribute("readOnly", "readOnly");
551 }
552 else {
553 removeAttribute("readOnly");
554 }
555 }
556
557
558
559
560
561 public boolean isChecked() {
562 return hasAttribute(ATTRIBUTE_CHECKED);
563 }
564
565
566
567
568
569 public boolean isReadOnly() {
570 return hasAttribute("readOnly");
571 }
572
573
574
575
576 @Override
577 protected boolean propagateClickStateUpdateToParent() {
578 return true;
579 }
580
581
582
583
584 @Override
585 public boolean handles(final Event event) {
586 if (event instanceof MouseEvent) {
587 return true;
588 }
589
590 return super.handles(event);
591 }
592
593
594
595
596
597
598
599
600
601
602 static Page executeOnChangeHandlerIfAppropriate(final HtmlElement htmlElement) {
603 final SgmlPage page = htmlElement.getPage();
604 final WebClient webClient = page.getWebClient();
605
606 if (!webClient.isJavaScriptEngineEnabled()) {
607 return page;
608 }
609
610 final AbstractJavaScriptEngine<?> engine = webClient.getJavaScriptEngine();
611 if (engine.isScriptRunning()) {
612 return page;
613 }
614 final ScriptResult scriptResult = htmlElement.fireEvent(Event.TYPE_CHANGE);
615
616 if (webClient.containsWebWindow(page.getEnclosingWindow())) {
617
618 return page.getEnclosingWindow().getEnclosedPage();
619 }
620
621 if (scriptResult != null) {
622
623 return webClient.getCurrentWindow().getEnclosedPage();
624 }
625
626 return page;
627 }
628
629
630
631
632 @Override
633 protected void setAttributeNS(final String namespaceURI, final String qualifiedName, final String attributeValue,
634 final boolean notifyAttributeChangeListeners, final boolean notifyMutationObservers) {
635 final String qualifiedNameLC = org.htmlunit.util.StringUtils.toRootLowerCase(qualifiedName);
636 if (NAME_ATTRIBUTE.equals(qualifiedNameLC)) {
637 if (newNames_.isEmpty()) {
638 newNames_ = new HashSet<>();
639 }
640 newNames_.add(attributeValue);
641 }
642
643 if (TYPE_ATTRIBUTE.equals(qualifiedNameLC)) {
644 changeType(attributeValue, true);
645 return;
646 }
647
648 if (VALUE_ATTRIBUTE.equals(qualifiedNameLC)) {
649 super.setAttributeNS(namespaceURI, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
650 notifyMutationObservers);
651
652 valueAttributeChanged(attributeValue, isValueDirty_);
653 return;
654 }
655
656 super.setAttributeNS(namespaceURI, qualifiedNameLC, attributeValue, notifyAttributeChangeListeners,
657 notifyMutationObservers);
658 }
659
660
661
662
663 @Override
664 public String getOriginalName() {
665 return originalName_;
666 }
667
668
669
670
671 @Override
672 public Collection<String> getNewNames() {
673 return newNames_;
674 }
675
676
677
678
679
680
681
682 public void valueModifiedByJavascript() {
683 valueModifiedByJavascript_ = true;
684 }
685
686
687
688
689 @Override
690 public final void focus() {
691 super.focus();
692
693 valueAtFocus_ = getInternalValue();
694 }
695
696
697
698
699 @Override
700 public final void removeFocus() {
701 super.removeFocus();
702
703 if (valueAtFocus_ != null && !valueAtFocus_.equals(getInternalValue())) {
704 handleFocusLostValueChanged();
705 }
706 valueAtFocus_ = null;
707 }
708
709 void handleFocusLostValueChanged() {
710 executeOnChangeHandlerIfAppropriate(this);
711 }
712
713
714
715
716 protected Object getInternalValue() {
717 return getRawValue();
718 }
719
720
721
722
723 @Override
724 public DisplayStyle getDefaultStyleDisplay() {
725 return DisplayStyle.INLINE_BLOCK;
726 }
727
728
729
730
731
732
733 public String getSize() {
734 return getAttributeDirect("size");
735 }
736
737
738
739
740
741
742 public void setSize(final String size) {
743 setAttribute("size", size);
744 }
745
746
747
748
749
750
751 public void setMaxLength(final int maxLength) {
752 setAttribute("maxLength", String.valueOf(maxLength));
753 }
754
755
756
757
758
759
760 public void setMinLength(final int minLength) {
761 setAttribute("minLength", String.valueOf(minLength));
762 }
763
764
765
766
767
768
769 public String getAccept() {
770 return getAttribute(HttpHeader.ACCEPT_LC);
771 }
772
773
774
775
776
777
778 public void setAccept(final String accept) {
779 setAttribute(HttpHeader.ACCEPT_LC, accept);
780 }
781
782
783
784
785
786
787 public String getAutocomplete() {
788 return getAttributeDirect("autocomplete");
789 }
790
791
792
793
794
795
796 public void setAutocomplete(final String autocomplete) {
797 setAttribute("autocomplete", autocomplete);
798 }
799
800
801
802
803
804
805 public String getPlaceholder() {
806 return getAttributeDirect("placeholder");
807 }
808
809
810
811
812
813
814 public void setPlaceholder(final String placeholder) {
815 setAttribute("placeholder", placeholder);
816 }
817
818
819
820
821
822
823 public String getPattern() {
824 return getAttributeDirect("pattern");
825 }
826
827
828
829
830
831
832 public void setPattern(final String pattern) {
833 setAttribute("pattern", pattern);
834 }
835
836
837
838
839
840
841 public String getMin() {
842 return getAttributeDirect("min");
843 }
844
845
846
847
848
849
850 public void setMin(final String min) {
851 setAttribute("min", min);
852 }
853
854
855
856
857
858
859 public String getMax() {
860 return getAttributeDirect("max");
861 }
862
863
864
865
866
867
868 public void setMax(final String max) {
869 setAttribute("max", max);
870 }
871
872
873
874
875
876
877 public String getStep() {
878 return getAttributeDirect("step");
879 }
880
881
882
883
884
885
886 public void setStep(final String step) {
887 setAttribute("step", step);
888 }
889
890 @Override
891 public boolean isValid() {
892 return !isValueMissingValidityState()
893 && isCustomValidityValid()
894 && isMaxLengthValid() && isMinLengthValid()
895 && !hasPatternMismatchValidityState();
896 }
897
898 protected boolean isCustomValidityValid() {
899 if (isCustomErrorValidityState()) {
900 final String type = getAttributeDirect(TYPE_ATTRIBUTE).toLowerCase(Locale.ROOT);
901 if (!"button".equals(type)
902 && !"hidden".equals(type)
903 && !"reset".equals(type)
904 && !("image".equals(type) && hasFeature(HTMLINPUT_TYPE_IMAGE_IGNORES_CUSTOM_VALIDITY))) {
905 return false;
906 }
907 }
908 return true;
909 }
910
911 @Override
912 protected boolean isRequiredSupported() {
913 return true;
914 }
915
916
917
918
919
920
921
922 protected boolean isPatternSupported() {
923 return false;
924 }
925
926
927
928
929 protected boolean isBlankPatternValidated() {
930 return true;
931 }
932
933
934
935
936
937
938
939 protected boolean isMinMaxLengthSupported() {
940 return false;
941 }
942
943
944
945
946 @Override
947 public DomNode cloneNode(final boolean deep) {
948 final HtmlInput newnode = (HtmlInput) super.cloneNode(deep);
949 newnode.newNames_ = new HashSet<>(newNames_);
950
951 return newnode;
952 }
953
954
955
956
957
958
959
960
961 private boolean isMaxLengthValid() {
962 if (!isMinMaxLengthSupported()
963 || valueModifiedByJavascript_
964 || getMaxLength() == Integer.MAX_VALUE
965 || getDefaultValue().equals(getValue())) {
966 return true;
967 }
968
969 return getValue().length() <= getMaxLength();
970 }
971
972
973
974
975
976
977
978
979 private boolean isMinLengthValid() {
980 if (!isMinMaxLengthSupported()
981 || valueModifiedByJavascript_
982 || getMinLength() == Integer.MIN_VALUE
983 || getDefaultValue().equals(getValue())) {
984 return true;
985 }
986
987 return getValue().length() >= getMinLength();
988 }
989
990
991
992
993
994
995
996
997 private boolean isPatternValid() {
998 if (!isPatternSupported()) {
999 return true;
1000 }
1001
1002 final String pattern = getPattern();
1003 if (StringUtils.isEmpty(pattern)) {
1004 return true;
1005 }
1006
1007 final String value = getValue();
1008 if (StringUtils.isEmpty(value)) {
1009 return true;
1010 }
1011 if (!isBlankPatternValidated() && StringUtils.isBlank(value)) {
1012 return true;
1013 }
1014
1015 try (Context cx = HtmlUnitContextFactory.getGlobal().enterContext()) {
1016 RegExpEngineAccess.compile(cx, pattern, "");
1017 final RegExpEngineAccess.CompiledRegExp compiled
1018 = RegExpEngineAccess.compile(cx, "^(?:" + pattern + ")$", "");
1019
1020 return RegExpEngineAccess.matches(cx, value, compiled);
1021 }
1022 catch (final Exception ignored) {
1023
1024 }
1025 return true;
1026 }
1027
1028
1029
1030
1031 @Override
1032 public boolean willValidate() {
1033 return !isDisabled() && !isReadOnly();
1034 }
1035
1036
1037
1038
1039 @Override
1040 public void setCustomValidity(final String message) {
1041 customValidity_ = message;
1042 }
1043
1044
1045
1046
1047 public boolean isCheckable() {
1048 final String type = getAttributeDirect(TYPE_ATTRIBUTE).toLowerCase(Locale.ROOT);
1049 return "radio".equals(type) || "checkbox".equals(type);
1050 }
1051
1052
1053
1054
1055 public boolean isSubmitable() {
1056 final String type = getAttributeDirect(TYPE_ATTRIBUTE);
1057 return !"submit".equalsIgnoreCase(type)
1058 && !"image".equalsIgnoreCase(type)
1059 && !"reset".equalsIgnoreCase(type)
1060 && !"button".equalsIgnoreCase(type);
1061 }
1062
1063 @Override
1064 public boolean isCustomErrorValidityState() {
1065 return !StringUtils.isEmpty(customValidity_);
1066 }
1067
1068 @Override
1069 public boolean hasPatternMismatchValidityState() {
1070 return !isPatternValid();
1071 }
1072
1073 @Override
1074 public boolean isTooShortValidityState() {
1075 if (!isMinMaxLengthSupported()
1076 || valueModifiedByJavascript_
1077 || getMinLength() == Integer.MIN_VALUE
1078 || getDefaultValue().equals(getValue())) {
1079 return false;
1080 }
1081
1082 return getValue().length() < getMinLength();
1083 }
1084
1085 @Override
1086 public boolean isValidValidityState() {
1087 return !isCustomErrorValidityState()
1088 && !isValueMissingValidityState()
1089 && !isTooLongValidityState()
1090 && !isTooShortValidityState()
1091 && !hasPatternMismatchValidityState();
1092 }
1093
1094 @Override
1095 public boolean isValueMissingValidityState() {
1096 return isRequiredSupported()
1097 && ATTRIBUTE_NOT_DEFINED != getAttributeDirect(ATTRIBUTE_REQUIRED)
1098 && getValue().isEmpty();
1099 }
1100
1101
1102
1103
1104 public final boolean isFormNoValidate() {
1105 return hasAttribute(ATTRIBUTE_FORMNOVALIDATE);
1106 }
1107
1108
1109
1110
1111
1112
1113 public final void setFormNoValidate(final boolean noValidate) {
1114 if (noValidate) {
1115 setAttribute(ATTRIBUTE_FORMNOVALIDATE, ATTRIBUTE_FORMNOVALIDATE);
1116 }
1117 else {
1118 removeAttribute(ATTRIBUTE_FORMNOVALIDATE);
1119 }
1120 }
1121
1122
1123
1124
1125 public final String getType() {
1126 final BrowserVersion browserVersion = getPage().getWebClient().getBrowserVersion();
1127 String type = getTypeAttribute();
1128 type = org.htmlunit.util.StringUtils.toRootLowerCase(type);
1129 return isSupported(type, browserVersion) ? type : "text";
1130 }
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 public HtmlInput changeType(String newType, final boolean setThroughAttribute) {
1145 final String currentType = getAttributeDirect(TYPE_ATTRIBUTE);
1146
1147 final SgmlPage page = getPage();
1148 final WebClient webClient = page.getWebClient();
1149 final BrowserVersion browser = webClient.getBrowserVersion();
1150 if (!currentType.equalsIgnoreCase(newType)) {
1151 if (!isSupported(org.htmlunit.util.StringUtils
1152 .toRootLowerCase(newType), browser)) {
1153 if (setThroughAttribute) {
1154 newType = "text";
1155 }
1156 }
1157
1158 final AttributesImpl attributes = new AttributesImpl();
1159 boolean typeFound = false;
1160 for (final DomAttr entry : getAttributesMap().values()) {
1161 final String name = entry.getName();
1162 final String value = entry.getValue();
1163
1164 if (TYPE_ATTRIBUTE.equals(name)) {
1165 attributes.addAttribute(null, name, name, null, newType);
1166 typeFound = true;
1167 }
1168 else {
1169 attributes.addAttribute(null, name, name, null, value);
1170 }
1171 }
1172
1173 if (!typeFound) {
1174 attributes.addAttribute(null, TYPE_ATTRIBUTE, TYPE_ATTRIBUTE, null, newType);
1175 }
1176
1177
1178 if (ATTRIBUTE_NOT_DEFINED != currentType || !"text".equalsIgnoreCase(newType)) {
1179 final HtmlInput newInput = (HtmlInput) webClient.getPageCreator().getHtmlParser()
1180 .getFactory(TAG_NAME)
1181 .createElement(page, TAG_NAME, attributes);
1182
1183 newInput.adjustValueAfterTypeChange(this, browser);
1184
1185
1186
1187
1188 if (getParentNode() != null) {
1189 getParentNode().replaceChild(newInput, this);
1190 }
1191
1192 final WebClient client = page.getWebClient();
1193 if (client.isJavaScriptEngineEnabled()) {
1194 final HTMLInputElement scriptable = getScriptableObject();
1195 setScriptableObject(null);
1196 scriptable.setDomNode(newInput, true);
1197 }
1198
1199 return newInput;
1200 }
1201 super.setAttributeNS(null, TYPE_ATTRIBUTE, newType, true, true);
1202 }
1203 return this;
1204 }
1205
1206 protected void adjustValueAfterTypeChange(final HtmlInput oldInput, final BrowserVersion browserVersion) {
1207 final String originalValue = oldInput.getValue();
1208 if (ATTRIBUTE_NOT_DEFINED != originalValue) {
1209 setValue(originalValue);
1210 }
1211 }
1212
1213
1214
1215
1216
1217
1218
1219 private static boolean isSupported(final String type, final BrowserVersion browserVersion) {
1220 boolean supported = false;
1221 switch (type) {
1222 case "month":
1223 supported = browserVersion.hasFeature(HTMLINPUT_TYPE_MONTH_SUPPORTED);
1224 break;
1225 case "week":
1226 supported = browserVersion.hasFeature(HTMLINPUT_TYPE_WEEK_SUPPORTED);
1227 break;
1228 case "color":
1229 case "date":
1230 case "datetime-local":
1231 case "time":
1232 case "email":
1233 case "text":
1234 case "submit":
1235 case "checkbox":
1236 case "radio":
1237 case "hidden":
1238 case "password":
1239 case "image":
1240 case "reset":
1241 case "button":
1242 case "file":
1243 case "number":
1244 case "range":
1245 case "search":
1246 case "tel":
1247 case "url":
1248 supported = true;
1249 break;
1250
1251 default:
1252 }
1253 return supported;
1254 }
1255
1256 protected void unmarkValueDirty() {
1257 isValueDirty_ = false;
1258 }
1259
1260 protected void markValueDirty() {
1261 isValueDirty_ = true;
1262 }
1263 }