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.javascript.host.html;
16
17 import java.io.Serializable;
18 import java.util.function.Predicate;
19
20 import org.htmlunit.html.DomElement;
21 import org.htmlunit.html.DomNode;
22 import org.htmlunit.html.HtmlButton;
23 import org.htmlunit.html.HtmlFieldSet;
24 import org.htmlunit.html.HtmlForm;
25 import org.htmlunit.html.HtmlInput;
26 import org.htmlunit.html.HtmlObject;
27 import org.htmlunit.html.HtmlOutput;
28 import org.htmlunit.html.HtmlSelect;
29 import org.htmlunit.html.HtmlTextArea;
30 import org.htmlunit.javascript.configuration.JsxClass;
31 import org.htmlunit.javascript.configuration.JsxConstructor;
32 import org.htmlunit.javascript.configuration.JsxFunction;
33 import org.htmlunit.javascript.configuration.JsxGetter;
34 import org.htmlunit.javascript.configuration.JsxSetter;
35
36 /**
37 * The JavaScript object {@code HTMLFieldSetElement}.
38 *
39 * @author Ahmed Ashour
40 * @author Ronald Brill
41 *
42 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement">MDN Documentation</a>
43 */
44 @JsxClass(domClass = HtmlFieldSet.class)
45 public class HTMLFieldSetElement extends HTMLElement {
46
47 /**
48 * JavaScript constructor.
49 */
50 @Override
51 @JsxConstructor
52 public void jsConstructor() {
53 super.jsConstructor();
54 }
55
56 /**
57 * Returns the {@code name} attribute.
58 * @return the {@code name} attribute
59 */
60 @JsxGetter
61 @Override
62 public String getName() {
63 return getDomNodeOrDie().getAttributeDirect(DomElement.NAME_ATTRIBUTE);
64 }
65
66 /**
67 * Sets the {@code name} attribute.
68 * @param name the {@code name} attribute value
69 */
70 @JsxSetter
71 @Override
72 public void setName(final String name) {
73 getDomNodeOrDie().setAttribute(DomElement.NAME_ATTRIBUTE, name);
74 }
75
76 /**
77 * Returns the value of the JavaScript {@code form} attribute.
78 *
79 * @return the value of the JavaScript {@code form} attribute
80 */
81 @JsxGetter
82 @Override
83 public HTMLFormElement getForm() {
84 final HtmlForm form = getDomNodeOrDie().getEnclosingForm();
85 if (form == null) {
86 return null;
87 }
88 return (HTMLFormElement) getScriptableFor(form);
89 }
90
91 /**
92 * Returns the {@code type} property; always "fieldset".
93 * @return the {@code type} property
94 */
95 @JsxGetter
96 public String getType() {
97 return "fieldset";
98 }
99
100 /**
101 * {@inheritDoc}
102 */
103 @Override
104 public HtmlFieldSet getDomNodeOrDie() {
105 return (HtmlFieldSet) super.getDomNodeOrDie();
106 }
107
108 /**
109 * Checks whether the element has any constraints and whether it satisfies them.
110 * @return {@code true} if the element is valid
111 */
112 @JsxFunction
113 public boolean checkValidity() {
114 return ValidatableHTMLElement.doCheckValidity(getDomNodeOrDie());
115 }
116
117 /**
118 * Performs the same validity checking steps as the checkValidity() method.
119 * @return {@code true} if the element is valid
120 */
121 @JsxFunction
122 public boolean reportValidity() {
123 return ValidatableHTMLElement.doReportValidity(getDomNodeOrDie());
124 }
125
126 /**
127 * Returns the message describing why the element's value fails constraint
128 * validation, or "" if it's valid or barred from validation.
129 * @return the validation message
130 */
131 @JsxGetter
132 public String getValidationMessage() {
133 return ValidatableHTMLElement.getValidationMessage(getDomNodeOrDie());
134 }
135
136 /**
137 * {@inheritDoc} Overridden to modify browser configurations.
138 */
139 @Override
140 @JsxGetter
141 public boolean isDisabled() {
142 return super.isDisabled();
143 }
144
145 /**
146 * {@inheritDoc} Overridden to modify browser configurations.
147 */
148 @Override
149 @JsxSetter
150 public void setDisabled(final boolean disabled) {
151 super.setDisabled(disabled);
152 }
153
154 /**
155 * Returns a {@link ValidityState} object representing the validity states of this element.
156 * @return a {@link ValidityState} object representing the validity states of this element
157 */
158 @JsxGetter
159 public ValidityState getValidity() {
160 final ValidityState validityState = new ValidityState();
161 validityState.setPrototype(getPrototype(validityState.getClass()));
162 validityState.setParentScope(getParentScope());
163 validityState.setDomNode(getDomNodeOrDie());
164 return validityState;
165 }
166
167 /**
168 * Returns whether the element is a candidate for constraint validation.
169 * @return whether the element is a candidate for constraint validation
170 */
171 @JsxGetter
172 public boolean isWillValidate() {
173 return getDomNodeOrDie().willValidate();
174 }
175
176 /**
177 * Sets the custom validity message for the element to the specified message.
178 * @param message the new message
179 */
180 @JsxFunction
181 public void setCustomValidity(final String message) {
182 getDomNodeOrDie().setCustomValidity(message);
183 }
184
185 /**
186 * Returns the fieldset's associated form controls -- listed elements whose
187 * closest fieldset element ancestor is this fieldset.
188 * <p>
189 * Per spec, this is purely a tree-position question: it does not consult
190 * the 'form' attribute or form ownership at all (a control physically
191 * inside this fieldset is included even if 'form' points elsewhere), and a
192 * nested inner <fieldset>'s own descendants are excluded here even
193 * though they're still tree-descendants of this fieldset -- only the inner
194 * fieldset ELEMENT itself counts, since it is the listed element whose
195 * closest fieldset ancestor is this one.
196 * </p>
197 *
198 * @return the fieldset's associated form controls
199 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement/elements">MDN Documentation</a>
200 */
201 @JsxGetter
202 public HTMLCollection getElements() {
203 final DomElement elt = getDomNodeOrDie();
204
205 final HTMLCollection elements = new HTMLCollection(elt, true);
206
207 elements.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> isListedElement(node));
208
209 return elements;
210 }
211
212 /**
213 * Checks whether {@code node} belongs to the HTML "listed" category of
214 * form-associated elements (button, fieldset, input except type=image,
215 * object, output, select, textarea).
216 *
217 * @param node the node to check
218 * @return {@code true} if {@code node} is a listed element
219 */
220 private static boolean isListedElement(final DomNode node) {
221 return node instanceof HtmlInput
222 || node instanceof HtmlButton
223 || node instanceof HtmlFieldSet
224 || node instanceof HtmlObject
225 || node instanceof HtmlOutput
226 || node instanceof HtmlSelect
227 || node instanceof HtmlTextArea;
228 }
229 }