View Javadoc
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 org.htmlunit.html.HtmlElement;
18  import org.htmlunit.html.ValidatableHtmlElement;
19  import org.htmlunit.javascript.host.event.Event;
20  
21  /**
22   * An {@link HTMLElement} that supports client-side validation using the Constraint Validation API.
23   * This works together with {@link ValidatableHtmlElement}.
24   * <p>
25   * Shared implementation of the HTML Constraint Validation API's
26   * checkValidity()/reportValidity() behavior, for JS host objects wrapping
27   * an {@link ValidatableHtmlElement}. Centralizes 'invalid'
28   * event dispatch and the interactive-vs-static distinction between the two
29   * methods (reportValidity() additionally focuses the element on failure)
30   * so this isn't duplicated per element type -- each implementing class
31   * only needs to supply the underlying DOM element.
32   * </p>
33   *
34   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Constraint_validation">
35   *      Constraint Validation API</a>
36   *
37   * @author Ronald Brill
38   */
39  public interface ValidatableHTMLElement {
40  
41      /**
42       * Statically validates the underlying element's constraints, firing a
43       * cancelable 'invalid' event on it if invalid. Does not move focus.
44       * @param elem the {@link HtmlElement} to work on
45       * @return {@code true} if valid or barred from validation, {@code false} otherwise
46       */
47      static boolean doCheckValidity(final HtmlElement elem) {
48          if (!(elem instanceof ValidatableHtmlElement valElem)) {
49              return true;
50          }
51  
52          if (!valElem.willValidate() || elem.isValid()) {
53              return true;
54          }
55  
56          elem.fireEvent(Event.TYPE_INVALID);
57          return false;
58      }
59  
60      /**
61       * Interactively validates -- same static check and 'invalid' event as
62       * {@link #doCheckValidity(HtmlElement)}, but additionally focuses the element if
63       * it's invalid.
64       * @param elem the {@link HtmlElement} to work on
65       * @return {@code true} if valid or barred from validation, {@code false} otherwise
66       */
67      static boolean doReportValidity(final HtmlElement elem) {
68          final boolean valid = doCheckValidity(elem);
69          if (!valid) {
70              elem.focus();
71          }
72          return valid;
73      }
74  
75      /**
76       * Returns the validation message describing the currently failing
77       * constraint, or "" if valid or barred from validation.
78       * @param elem the {@link HtmlElement} to work on
79       * @return the validation message
80       */
81      static String getValidationMessage(final HtmlElement elem) {
82          if (!(elem instanceof ValidatableHtmlElement valElem)) {
83              return "";
84          }
85          return valElem.getValidationMessage();
86      }
87  }