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