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.HtmlTextArea;
18  import org.htmlunit.javascript.JavaScriptEngine;
19  import org.htmlunit.javascript.configuration.JsxClass;
20  import org.htmlunit.javascript.configuration.JsxConstructor;
21  import org.htmlunit.javascript.configuration.JsxFunction;
22  import org.htmlunit.javascript.configuration.JsxGetter;
23  import org.htmlunit.javascript.configuration.JsxSetter;
24  import org.htmlunit.javascript.host.dom.DOMException;
25  import org.htmlunit.javascript.host.dom.NodeList;
26  
27  /**
28   * The JavaScript object {@code HTMLTextAreaElement}.
29   *
30   * @author Mike Bowler
31   * @author Marc Guillemot
32   * @author Chris Erskine
33   * @author Ahmed Ashour
34   * @author Daniel Gredler
35   * @author Ronald Brill
36   * @author Frank Danek
37   * @author Carsten Steul
38   *
39   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement">MDN Documentation</a>
40   */
41  @JsxClass(domClass = HtmlTextArea.class)
42  public class HTMLTextAreaElement extends HTMLElement {
43  
44      /** "Live" labels collection; has to be a member to have equality (==) working. */
45      private NodeList labels_;
46  
47      /**
48       * JavaScript constructor.
49       */
50      @Override
51      @JsxConstructor
52      public void jsConstructor() {
53          super.jsConstructor();
54      }
55  
56      /**
57       * Returns the type of this input.
58       * @return the type of this input
59       */
60      @JsxGetter
61      public String getType() {
62          return "textarea";
63      }
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      public HtmlTextArea getDomNodeOrDie() {
70          return (HtmlTextArea) super.getDomNodeOrDie();
71      }
72  
73      /**
74       * Returns the value of the {@code value} attribute.
75       * @return the value of the {@code value} attribute
76       */
77      @JsxGetter
78      @Override
79      public String getValue() {
80          return getDomNodeOrDie().getText();
81      }
82  
83      /**
84       * Sets the value of the {@code value} attribute.
85       * @param value the new value
86       */
87      @JsxSetter
88      @Override
89      public void setValue(final Object value) {
90          if (null == value) {
91              getDomNodeOrDie().setText("");
92              return;
93          }
94  
95          getDomNodeOrDie().setText(JavaScriptEngine.toString(value));
96      }
97  
98      /**
99       * Returns the number of columns in this text area.
100      * @return the number of columns in this text area
101      */
102     @JsxGetter
103     public int getCols() {
104         final String s = getDomNodeOrDie().getAttributeDirect("cols");
105         try {
106             return Integer.parseInt(s);
107         }
108         catch (final NumberFormatException e) {
109             return 20;
110         }
111     }
112 
113     /**
114      * Sets the number of columns in this text area.
115      * @param cols the number of columns in this text area
116      */
117     @JsxSetter
118     public void setCols(final String cols) {
119         try {
120             final int i = Float.valueOf(cols).intValue();
121             if (i < 0) {
122                 getDomNodeOrDie().setAttribute("cols", null);
123                 return;
124             }
125             getDomNodeOrDie().setAttribute("cols", Integer.toString(i));
126         }
127         catch (final NumberFormatException e) {
128             getDomNodeOrDie().setAttribute("cols", "20");
129         }
130     }
131 
132     /**
133      * Returns the number of rows in this text area.
134      * @return the number of rows in this text area
135      */
136     @JsxGetter
137     public int getRows() {
138         final String s = getDomNodeOrDie().getAttributeDirect("rows");
139         try {
140             return Integer.parseInt(s);
141         }
142         catch (final NumberFormatException e) {
143             return 2;
144         }
145     }
146 
147     /**
148      * Sets the number of rows in this text area.
149      * @param rows the number of rows in this text area
150      */
151     @JsxSetter
152     public void setRows(final String rows) {
153         try {
154             final int i = Float.valueOf(rows).intValue();
155             if (i < 0) {
156                 getDomNodeOrDie().setAttribute("rows", null);
157                 return;
158             }
159             getDomNodeOrDie().setAttribute("rows", Integer.toString(i));
160         }
161         catch (final NumberFormatException e) {
162             getDomNodeOrDie().setAttribute("rows", "2");
163         }
164     }
165 
166     /**
167      * Returns the textarea's default value, used if the containing form gets reset.
168      * @return the textarea's default value, used if the containing form gets reset
169      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement/defaultValue">MDN Documentation</a>
170      */
171     @JsxGetter
172     public String getDefaultValue() {
173         return getDomNodeOrDie().getDefaultValue();
174     }
175 
176     /**
177      * Sets the textarea's default value, used if the containing form gets reset.
178      * @param defaultValue the textarea's default value, used if the containing form gets reset
179      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement/defaultValue">MDN Documentation</a>
180      */
181     @JsxSetter
182     public void setDefaultValue(final String defaultValue) {
183         getDomNodeOrDie().setDefaultValue(defaultValue);
184     }
185 
186     /**
187      * Gets the value of {@code textLength} attribute.
188      * @return the text length
189      */
190     @JsxGetter
191     public int getTextLength() {
192         return getValue().length();
193     }
194 
195     /**
196      * Gets the value of {@code selectionStart} attribute.
197      * @return the selection start
198      */
199     @JsxGetter
200     public int getSelectionStart() {
201         return getDomNodeOrDie().getSelectionStart();
202     }
203 
204     /**
205      * Sets the value of {@code selectionStart} attribute.
206      * @param start selection start
207      */
208     @JsxSetter
209     public void setSelectionStart(final int start) {
210         getDomNodeOrDie().setSelectionStart(start);
211     }
212 
213     /**
214      * Gets the value of {@code selectionEnd} attribute.
215      * @return the selection end
216      */
217     @JsxGetter
218     public int getSelectionEnd() {
219         return getDomNodeOrDie().getSelectionEnd();
220     }
221 
222     /**
223      * Sets the value of {@code selectionEnd} attribute.
224      * @param end selection end
225      */
226     @JsxSetter
227     public void setSelectionEnd(final int end) {
228         getDomNodeOrDie().setSelectionEnd(end);
229     }
230 
231     /**
232      * Sets the selected portion of this input element.
233      * @param start the index of the first character to select
234      * @param end the index of the character after the selection
235      */
236     @JsxFunction
237     public void setSelectionRange(final int start, final int end) {
238         setSelectionStart(start);
239         setSelectionEnd(end);
240     }
241 
242     /**
243      * Selects this element.
244      */
245     @JsxFunction
246     public void select() {
247         getDomNodeOrDie().select();
248     }
249 
250     /**
251      * Gets the value of {@code readOnly} attribute.
252      * @return the readOnly attribute
253      */
254     @JsxGetter
255     public boolean isReadOnly() {
256         return getDomNodeOrDie().isReadOnly();
257     }
258 
259     /**
260      * Sets the value of {@code readOnly} attribute.
261      * @param readOnly the new value
262      */
263     @JsxSetter
264     public void setReadOnly(final boolean readOnly) {
265         getDomNodeOrDie().setReadOnly(readOnly);
266     }
267 
268     /**
269      * Returns the maximum number of characters in this text area.
270      * @return the maximum number of characters in this text area
271      */
272     @JsxGetter
273     public int getMaxLength() {
274         final String maxLength = getDomNodeOrDie().getAttribute("maxLength");
275 
276         try {
277             return Integer.parseInt(maxLength);
278         }
279         catch (final NumberFormatException e) {
280             return -1;
281         }
282     }
283 
284     /**
285      * Sets maximum number of characters in this text area.
286      * @param maxLength maximum number of characters in this text area
287      */
288     @JsxSetter
289     public void setMaxLength(final String maxLength) {
290         try {
291             final int i = Integer.parseInt(maxLength);
292 
293             if (i < 0) {
294                 throw JavaScriptEngine.asJavaScriptException(getWindow(),
295                         "New value for maxLength '" + maxLength + "' is smaller than zero.",
296                         DOMException.INDEX_SIZE_ERR);
297             }
298             getDomNodeOrDie().setAttribute("maxLength", maxLength);
299         }
300         catch (final NumberFormatException e) {
301             getDomNodeOrDie().setAttribute("maxLength", "0");
302         }
303     }
304 
305     /**
306      * Returns the minimum number of characters in this text area.
307      * @return the minimum number of characters in this text area
308      */
309     @JsxGetter
310     public int getMinLength() {
311         final String minLength = getDomNodeOrDie().getAttribute("minLength");
312 
313         try {
314             return Integer.parseInt(minLength);
315         }
316         catch (final NumberFormatException e) {
317             return -1;
318         }
319     }
320 
321     /**
322      * Sets minimum number of characters in this text area.
323      * @param minLength minimum number of characters in this text area
324      */
325     @JsxSetter
326     public void setMinLength(final String minLength) {
327         try {
328             final int i = Integer.parseInt(minLength);
329 
330             if (i < 0) {
331                 throw JavaScriptEngine.throwAsScriptRuntimeEx(
332                     new NumberFormatException("New value for minLength '" + minLength + "' is smaller than zero."));
333             }
334             getDomNodeOrDie().setAttribute("minLength", minLength);
335         }
336         catch (final NumberFormatException e) {
337             getDomNodeOrDie().setAttribute("minLength", "0");
338         }
339     }
340 
341     /**
342      * Returns the {@code placeholder} attribute.
343      * @return the {@code placeholder} attribute
344      */
345     @JsxGetter
346     public String getPlaceholder() {
347         return getDomNodeOrDie().getPlaceholder();
348     }
349 
350     /**
351      * Sets the {@code placeholder} attribute.
352      * @param placeholder the new {@code placeholder} value
353      */
354     @JsxSetter
355     public void setPlaceholder(final String placeholder) {
356         getDomNodeOrDie().setPlaceholder(placeholder);
357     }
358 
359     /**
360      * Returns the labels associated with the element.
361      * @return the labels associated with the element
362      */
363     @JsxGetter
364     public NodeList getLabels() {
365         if (labels_ == null) {
366             labels_ = new LabelsNodeList(getDomNodeOrDie());
367         }
368         return labels_;
369     }
370 
371     /**
372      * Checks whether the element has any constraints and whether it satisfies them.
373      * @return {@code true} if the element is valid
374      */
375     @JsxFunction
376     public boolean checkValidity() {
377         return getDomNodeOrDie().isValid();
378     }
379 
380     /**
381      * Returns the {@code required} property.
382      * @return the {@code required} property
383      */
384     @JsxGetter
385     public boolean isRequired() {
386         return getDomNodeOrDie().isRequired();
387     }
388 
389     /**
390      * Sets the {@code required} property.
391      * @param required the new value
392      */
393     @JsxSetter
394     public void setRequired(final boolean required) {
395         getDomNodeOrDie().setRequired(required);
396     }
397 
398     /**
399      * {@inheritDoc}
400      */
401     @JsxGetter
402     @Override
403     public String getName() {
404         return super.getName();
405     }
406 
407     /**
408      * {@inheritDoc}
409      */
410     @JsxSetter
411     @Override
412     public void setName(final String newName) {
413         super.setName(newName);
414     }
415 
416     /**
417      * {@inheritDoc} Overridden to modify browser configurations.
418      */
419     @Override
420     @JsxGetter
421     public boolean isDisabled() {
422         return super.isDisabled();
423     }
424 
425     /**
426      * {@inheritDoc} Overridden to modify browser configurations.
427      */
428     @Override
429     @JsxSetter
430     public void setDisabled(final boolean disabled) {
431         super.setDisabled(disabled);
432     }
433 
434     /**
435      * {@inheritDoc}
436      */
437     @JsxGetter
438     @Override
439     public HTMLFormElement getForm() {
440         return super.getForm();
441     }
442 
443     /**
444      * Returns whether the element is a candidate for constraint validation.
445      * @return whether the element is a candidate for constraint validation
446      */
447     @JsxGetter
448     public boolean isWillValidate() {
449         return getDomNodeOrDie().willValidate();
450     }
451 
452     /**
453      * Returns a {@link ValidityState} object representing the validity states of this element.
454      * @return a {@link ValidityState} object representing the validity states of this element
455      */
456     @JsxGetter
457     public ValidityState getValidity() {
458         final ValidityState validityState = new ValidityState();
459         validityState.setPrototype(getPrototype(validityState.getClass()));
460         validityState.setParentScope(getParentScope());
461         validityState.setDomNode(getDomNodeOrDie());
462         return validityState;
463     }
464 
465     /**
466      * Sets the custom validity message for the element to the specified message.
467      * @param message the new message
468      */
469     @JsxFunction
470     public void setCustomValidity(final String message) {
471         getDomNodeOrDie().setCustomValidity(message);
472     }
473 }