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