1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.html;
16
17 import java.util.Map;
18 import java.util.regex.Pattern;
19
20 import org.htmlunit.SgmlPage;
21 import org.htmlunit.util.StringUtils;
22
23 /**
24 * Wrapper for the HTML element "input" where type is "email".
25 *
26 * @author Ahmed Ashour
27 * @author Ronald Brill
28 * @author Frank Danek
29 * @author Anton Demydenko
30 * @author Michael Lueck
31 */
32 public class HtmlEmailInput extends HtmlSelectableTextInput implements LabelableElement {
33
34 // see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation
35 private static final Pattern DEFAULT_PATTERN =
36 Pattern.compile("^[a-zA-Z\\d.!#$%&'*+/=?^_`{|\\}~-]+@[a-zA-Z\\d](?:[a-zA-Z\\d-]{0,61}[a-zA-Z\\d])?"
37 + "(?:\\.[a-zA-Z\\d](?:[a-zA-Z\\d-]{0,61}[a-zA-Z\\d])?)*$");
38
39 /**
40 * Creates an instance.
41 *
42 * @param qualifiedName the qualified name of the element type to instantiate
43 * @param page the page that contains this element
44 * @param attributes the initial attributes
45 */
46 HtmlEmailInput(final String qualifiedName, final SgmlPage page,
47 final Map<String, DomAttr> attributes) {
48 super(qualifiedName, page, attributes);
49 }
50
51 /**
52 * {@inheritDoc}
53 */
54 @Override
55 public void setDefaultChecked(final boolean defaultChecked) {
56 // Empty.
57 }
58
59 /**
60 * {@inheritDoc}
61 */
62 @Override
63 public String getValue() {
64 final String raw = getRawValue();
65 if (StringUtils.isBlank(raw)) {
66 return "";
67 }
68 return raw.trim();
69 }
70
71 /**
72 * {@inheritDoc}
73 */
74 @Override
75 protected boolean isPatternSupported() {
76 return true;
77 }
78
79 /**
80 * {@inheritDoc}
81 */
82 @Override
83 protected boolean isBlankPatternValidated() {
84 return false;
85 }
86
87 /**
88 * {@inheritDoc}
89 */
90 @Override
91 protected boolean isMinMaxLengthSupported() {
92 return true;
93 }
94
95 /**
96 * {@inheritDoc}
97 * Per spec, a non-empty value must match the (deliberately simplified,
98 * RFC-5322-approximating) email pattern above. An empty value is never
99 * a type mismatch on its own -- that's valueMissing's concern, if
100 * 'required' is set.
101 */
102 @Override
103 public boolean hasTypeMismatchValidityState() {
104 final String val = getValue();
105 if (StringUtils.isBlank(val)) {
106 return false;
107 }
108 return !DEFAULT_PATTERN.matcher(val).matches();
109 }
110
111 /**
112 * {@inheritDoc}
113 */
114 @Override
115 public String getTypeMismatchMessage() {
116 return "Please enter an email address.";
117 }
118 }