View Javadoc
1   /*
2    * Copyright (c) 2002-2025 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 static org.htmlunit.BrowserVersionFeatures.HTMLINPUT_TYPE_WEEK_SUPPORTED;
18  import static org.htmlunit.BrowserVersionFeatures.JS_INPUT_CHANGE_TYPE_DROPS_VALUE_WEEK_MONTH;
19  
20  import java.time.LocalDate;
21  import java.time.format.DateTimeFormatter;
22  import java.time.format.DateTimeParseException;
23  import java.util.Map;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.htmlunit.BrowserVersion;
27  import org.htmlunit.SgmlPage;
28  
29  /**
30   * Wrapper for the HTML element "input" where type is "week".
31   *
32   * @author Ahmed Ashour
33   * @author Frank Danek
34   * @author Anton Demydenko
35   */
36  public class HtmlWeekInput extends HtmlInput implements LabelableElement {
37  
38      private static final DateTimeFormatter FORMATTER_ = DateTimeFormatter.ofPattern("yyyy-'W'ww");
39  
40      /**
41       * Creates an instance.
42       *
43       * @param qualifiedName the qualified name of the element type to instantiate
44       * @param page the page that contains this element
45       * @param attributes the initial attributes
46       */
47      HtmlWeekInput(final String qualifiedName, final SgmlPage page,
48              final Map<String, DomAttr> attributes) {
49          super(qualifiedName, page, attributes);
50      }
51  
52      /**
53       * {@inheritDoc}
54       */
55      @Override
56      public void setDefaultChecked(final boolean defaultChecked) {
57          // Empty.
58      }
59  
60      /**
61       * {@inheritDoc}
62       */
63      @Override
64      public void setValue(final String newValue) {
65          if (!hasFeature(HTMLINPUT_TYPE_WEEK_SUPPORTED)
66                  || StringUtils.isEmpty(newValue)) {
67              super.setValue(newValue);
68              return;
69          }
70  
71          try {
72              FORMATTER_.parse(newValue);
73              super.setValue(newValue);
74          }
75          catch (final DateTimeParseException ignored) {
76              // ignore
77          }
78      }
79  
80      /**
81       * {@inheritDoc}
82       */
83      @Override
84      public boolean isValid() {
85          return super.isValid() && isMaxValid() && isMinValid();
86      }
87  
88      /**
89       * Returns if the input element has a valid min value. Refer to the
90       * <a href="https://www.w3.org/TR/html5/sec-forms.html">HTML 5</a> documentation
91       * for details.
92       *
93       * @return if the input element has a valid min value
94       */
95      private boolean isMinValid() {
96          if (hasFeature(HTMLINPUT_TYPE_WEEK_SUPPORTED) && !getMin().isEmpty()) {
97              try {
98                  final LocalDate dateValue = LocalDate.parse(getRawValue() + "-1",
99                          DateTimeFormatter.ISO_WEEK_DATE);
100                 final LocalDate minDate = LocalDate.parse(getMin() + "-1", DateTimeFormatter.ISO_WEEK_DATE);
101                 return minDate.isEqual(dateValue) || minDate.isBefore(dateValue);
102             }
103             catch (final DateTimeParseException ignored) {
104                 // ignore
105             }
106         }
107         return true;
108     }
109 
110     /**
111      * Returns if the input element has a valid max value. Refer to the
112      * <a href="https://www.w3.org/TR/html5/sec-forms.html">HTML 5</a> documentation
113      * for details.
114      *
115      * @return if the input element has a valid max value
116      */
117     private boolean isMaxValid() {
118         if (hasFeature(HTMLINPUT_TYPE_WEEK_SUPPORTED) && !getMax().isEmpty()) {
119             try {
120                 final LocalDate dateValue = LocalDate.parse(getRawValue() + "-1",
121                         DateTimeFormatter.ISO_WEEK_DATE);
122                 final LocalDate maxDate = LocalDate.parse(getMax() + "-1", DateTimeFormatter.ISO_WEEK_DATE);
123                 return maxDate.isEqual(dateValue) || maxDate.isAfter(dateValue);
124             }
125             catch (final DateTimeParseException ignored) {
126                 // ignore
127             }
128         }
129         return true;
130     }
131 
132     @Override
133     protected void adjustValueAfterTypeChange(final HtmlInput oldInput, final BrowserVersion browserVersion) {
134         if (browserVersion.hasFeature(JS_INPUT_CHANGE_TYPE_DROPS_VALUE_WEEK_MONTH)) {
135             setValue("");
136             return;
137         }
138         super.adjustValueAfterTypeChange(oldInput, browserVersion);
139     }
140 }