View Javadoc
1   /*
2    * Copyright (c) 2002-2017 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    * http://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 com.gargoylesoftware.htmlunit.javascript.host.html;
16  
17  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_ONCLICK_USES_POINTEREVENT;
18  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLINPUT_FILES_UNDEFINED;
19  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLINPUT_FILE_SELECTION_START_END_NULL;
20  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLINPUT_FILE_VALUE_FAKEPATH;
21  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLINPUT_FILE_VALUE_NO_PATH;
22  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_ALIGN_FOR_INPUT_IGNORES_VALUES;
23  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_INPUT_NUMBER_SELECTION_START_END_NULL;
24  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_INPUT_SET_TYPE_LOWERCASE;
25  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_INPUT_SET_VALUE_DATE_SUPPORTED;
26  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_SELECT_FILE_THROWS;
27  import static com.gargoylesoftware.htmlunit.html.DomElement.ATTRIBUTE_NOT_DEFINED;
28  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
29  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
30  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF;
31  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF52;
32  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.IE;
33  
34  import java.io.File;
35  import java.io.IOException;
36  import java.util.Locale;
37  
38  import org.apache.commons.lang3.StringUtils;
39  import org.apache.commons.lang3.math.NumberUtils;
40  import org.xml.sax.helpers.AttributesImpl;
41  
42  import com.gargoylesoftware.htmlunit.BrowserVersion;
43  import com.gargoylesoftware.htmlunit.html.DomNode;
44  import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput;
45  import com.gargoylesoftware.htmlunit.html.HtmlFileInput;
46  import com.gargoylesoftware.htmlunit.html.HtmlInput;
47  import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput;
48  import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
49  import com.gargoylesoftware.htmlunit.html.InputElementFactory;
50  import com.gargoylesoftware.htmlunit.html.impl.SelectableTextInput;
51  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass;
52  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor;
53  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction;
54  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter;
55  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter;
56  import com.gargoylesoftware.htmlunit.javascript.host.dom.AbstractList;
57  import com.gargoylesoftware.htmlunit.javascript.host.dom.TextRange;
58  import com.gargoylesoftware.htmlunit.javascript.host.event.Event;
59  import com.gargoylesoftware.htmlunit.javascript.host.event.MouseEvent;
60  import com.gargoylesoftware.htmlunit.javascript.host.event.PointerEvent;
61  import com.gargoylesoftware.htmlunit.javascript.host.file.FileList;
62  
63  import net.sourceforge.htmlunit.corejs.javascript.Context;
64  import net.sourceforge.htmlunit.corejs.javascript.Undefined;
65  
66  /**
67   * The JavaScript object for {@code HTMLInputElement}.
68   *
69   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
70   * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
71   * @author Marc Guillemot
72   * @author Chris Erskine
73   * @author Ahmed Ashour
74   * @author Daniel Gredler
75   * @author Ronald Brill
76   * @author Frank Danek
77   */
78  @JsxClass(domClass = HtmlInput.class)
79  public class HTMLInputElement extends FormField {
80  
81      /** "Live" labels collection; has to be a member to have equality (==) working. */
82      private AbstractList labels_;
83  
84      /**
85       * Creates an instance.
86       */
87      @JsxConstructor({CHROME, FF, EDGE})
88      public HTMLInputElement() {
89      }
90  
91      /**
92       * Returns the {@code type} property.
93       * @return the {@code type} property
94       */
95      @JsxGetter
96      public String getType() {
97          String type = getDomNodeOrDie().getTypeAttribute();
98          final BrowserVersion browserVersion = getBrowserVersion();
99          type = type.toLowerCase(Locale.ROOT);
100         if (!InputElementFactory.isSupported(type)) {
101             type = "text";
102         }
103         else if (!browserVersion.hasFeature(JS_INPUT_SET_VALUE_DATE_SUPPORTED)) {
104             switch (type) {
105                 case "date":
106                 case "time":
107                 case "datetime-local":
108                 case "month":
109                 case "week":
110                     type = "text";
111                     break;
112 
113                 default:
114             }
115         }
116         if ("color".equals(type) && browserVersion.hasFeature(HTMLINPUT_FILES_UNDEFINED)) {
117             type = "text";
118         }
119         return type;
120     }
121 
122     /**
123      * Sets the value of the attribute {@code type}.
124      * Note: this replace the DOM node with a new one.
125      * @param newType the new type to set
126      */
127     @JsxSetter
128     public void setType(String newType) {
129         HtmlInput input = getDomNodeOrDie();
130 
131         final String currentType = input.getAttribute("type");
132 
133         if (!currentType.equalsIgnoreCase(newType)) {
134             if (newType != null && getBrowserVersion().hasFeature(JS_INPUT_SET_TYPE_LOWERCASE)) {
135                 newType = newType.toLowerCase(Locale.ROOT);
136             }
137             final AttributesImpl attributes = readAttributes(input);
138             final int index = attributes.getIndex("type");
139             if (index > -1) {
140                 attributes.setValue(index, newType);
141             }
142             else {
143                 attributes.addAttribute(null, "type", "type", null, newType);
144             }
145 
146             // create a new one only if we have a new type
147             if (ATTRIBUTE_NOT_DEFINED != currentType || !"text".equalsIgnoreCase(newType)) {
148                 final HtmlInput newInput = (HtmlInput) InputElementFactory.instance
149                         .createElement(input.getPage(), "input", attributes);
150 
151                 if (input.wasCreatedByJavascript()) {
152                     newInput.markAsCreatedByJavascript();
153                 }
154 
155                 if (input.getParentNode() == null) {
156                     // the input hasn't yet been inserted into the DOM tree (likely has been
157                     // created via document.createElement()), so simply replace it with the
158                     // new Input instance created in the code above
159                     input = newInput;
160                 }
161                 else {
162                     input.getParentNode().replaceChild(newInput, input);
163                 }
164 
165                 input.setScriptableObject(null);
166                 setDomNode(newInput, true);
167             }
168             else {
169                 super.setAttribute("type", newType);
170             }
171         }
172     }
173 
174     /**
175      * Sets the value of the JavaScript attribute {@code value}.
176      *
177      * @param newValue the new value
178      */
179     @Override
180     public void setValue(final Object newValue) {
181         if (null == newValue) {
182             getDomNodeOrDie().setValueAttribute("");
183             return;
184         }
185 
186         final String val = Context.toString(newValue);
187         final BrowserVersion browserVersion = getBrowserVersion();
188         if (StringUtils.isNotEmpty(val) && "file".equalsIgnoreCase(getType())) {
189             if (browserVersion.hasFeature(JS_SELECT_FILE_THROWS)) {
190                 throw Context.reportRuntimeError("InvalidStateError: "
191                         + "Failed to set the 'value' property on 'HTMLInputElement'.");
192             }
193             return;
194         }
195 
196         getDomNodeOrDie().setValueAttribute(val);
197     }
198 
199     /**
200      * Sets the checked property. Although this property is defined in Input it
201      * doesn't make any sense for input's other than checkbox and radio. This
202      * implementation does nothing. The implementations in Checkbox and Radio
203      * actually do the work.
204      *
205      * @param checked True if this input should have the {@code checked} attribute set
206      */
207     @JsxSetter
208     public void setChecked(final boolean checked) {
209         getDomNodeOrDie().setChecked(checked);
210     }
211 
212     /**
213      * {@inheritDoc}
214      */
215     @Override
216     public HtmlInput getDomNodeOrDie() {
217         return (HtmlInput) super.getDomNodeOrDie();
218     }
219 
220     /**
221      * Returns the value of the checked property. Although this property is
222      * defined in Input it doesn't make any sense for input's other than
223      * checkbox and radio. This implementation does nothing. The
224      * implementations in Checkbox and Radio actually do the work.
225      *
226      *@return the checked property
227      */
228     @JsxGetter
229     public boolean isChecked() {
230         return getDomNodeOrDie().isChecked();
231     }
232 
233     /**
234      * Select this element.
235      */
236     @JsxFunction
237     public void select() {
238         final HtmlInput input = getDomNodeOrDie();
239         if (input instanceof HtmlTextInput) {
240             ((HtmlTextInput) input).select();
241         }
242         // currently nothing for other input types
243     }
244 
245     /**
246      * Uses {@link #setType(String)} if attribute's name is type to
247      * replace DOM node as well as long as we have subclasses of {@link HtmlInput}.
248      * {@inheritDoc}
249      */
250     @Override
251     public void setAttribute(final String name, final String value) {
252         if ("type".equalsIgnoreCase(name)) {
253             setType(value);
254             return;
255         }
256         if ("value".equalsIgnoreCase(name)) {
257             setDefaultValue(value);
258         }
259         else {
260             super.setAttribute(name, value);
261         }
262     }
263 
264     /**
265      * Returns the input's default value, used if the containing form gets reset.
266      * @return the input's default value, used if the containing form gets reset
267      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533718.aspx">MSDN Documentation</a>
268      */
269     @JsxGetter
270     public String getDefaultValue() {
271         return getDomNodeOrDie().getDefaultValue();
272     }
273 
274     /**
275      * Sets the input's default value, used if the containing form gets reset.
276      * @param defaultValue the input's default value, used if the containing form gets reset
277      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533718.aspx">MSDN Documentation</a>
278      */
279     @JsxSetter
280     public void setDefaultValue(final String defaultValue) {
281         getDomNodeOrDie().setDefaultValue(defaultValue);
282     }
283 
284     /**
285      * Returns the input's default checked value, used if the containing form gets reset.
286      * @return the input's default checked value, used if the containing form gets reset
287      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533715.aspx">MSDN Documentation</a>
288      */
289     @JsxGetter
290     public boolean isDefaultChecked() {
291         return getDomNodeOrDie().isDefaultChecked();
292     }
293 
294     /**
295      * Sets the input's default checked value, used if the containing form gets reset.
296      * @param defaultChecked the input's default checked value, used if the containing form gets reset
297      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533715.aspx">MSDN Documentation</a>
298      */
299     @JsxSetter
300     public void setDefaultChecked(final boolean defaultChecked) {
301         getDomNodeOrDie().setDefaultChecked(defaultChecked);
302     }
303 
304     /**
305      * Gets the value of {@code textLength} attribute.
306      * @return the text length
307      */
308     @JsxGetter(FF)
309     public int getTextLength() {
310         return getValue().length();
311     }
312 
313     /**
314      * Gets the value of {@code selectionStart} attribute.
315      * @return the selection start
316      */
317     @JsxGetter
318     public Object getSelectionStart() {
319         final DomNode dom = getDomNodeOrDie();
320         if (dom instanceof SelectableTextInput) {
321             if ("number".equalsIgnoreCase(getType())
322                     && getBrowserVersion().hasFeature(JS_INPUT_NUMBER_SELECTION_START_END_NULL)) {
323                 return null;
324             }
325 
326             return ((SelectableTextInput) dom).getSelectionStart();
327         }
328 
329         if (getBrowserVersion().hasFeature(HTMLINPUT_FILE_SELECTION_START_END_NULL)) {
330             return null;
331         }
332         throw Context.reportRuntimeError("Failed to read the 'selectionStart' property from 'HTMLInputElement': "
333                 + "The input element's type (" + getType() + ") does not support selection.");
334     }
335 
336     /**
337      * Sets the value of {@code selectionStart} attribute.
338      * @param start selection start
339      */
340     @JsxSetter
341     public void setSelectionStart(final int start) {
342         final DomNode dom = getDomNodeOrDie();
343         if (dom instanceof SelectableTextInput) {
344             if ("number".equalsIgnoreCase(getType())
345                     && getBrowserVersion().hasFeature(JS_INPUT_NUMBER_SELECTION_START_END_NULL)) {
346                 throw Context.reportRuntimeError("Failed to set the 'selectionStart' property"
347                         + "from 'HTMLInputElement': "
348                         + "The input element's type ('number') does not support selection.");
349             }
350 
351             ((SelectableTextInput) dom).setSelectionStart(start);
352             return;
353         }
354 
355         throw Context.reportRuntimeError("Failed to set the 'selectionStart' property from 'HTMLInputElement': "
356                 + "The input element's type (" + getType() + ") does not support selection.");
357     }
358 
359     /**
360      * Gets the value of {@code selectionEnd} attribute.
361      * @return the selection end
362      */
363     @JsxGetter
364     public Object getSelectionEnd() {
365         final DomNode dom = getDomNodeOrDie();
366         if (dom instanceof SelectableTextInput) {
367             if ("number".equalsIgnoreCase(getType())
368                     && getBrowserVersion().hasFeature(JS_INPUT_NUMBER_SELECTION_START_END_NULL)) {
369                 return null;
370             }
371 
372             return ((SelectableTextInput) dom).getSelectionEnd();
373         }
374 
375         if (getBrowserVersion().hasFeature(HTMLINPUT_FILE_SELECTION_START_END_NULL)) {
376             return null;
377         }
378         throw Context.reportRuntimeError("Failed to read the 'selectionEnd' property from 'HTMLInputElement': "
379                 + "The input element's type (" + getType() + ") does not support selection.");
380     }
381 
382     /**
383      * Sets the value of {@code selectionEnd} attribute.
384      * @param end selection end
385      */
386     @JsxSetter
387     public void setSelectionEnd(final int end) {
388         final DomNode dom = getDomNodeOrDie();
389         if (dom instanceof SelectableTextInput) {
390             if ("number".equalsIgnoreCase(getType())
391                     && getBrowserVersion().hasFeature(JS_INPUT_NUMBER_SELECTION_START_END_NULL)) {
392                 throw Context.reportRuntimeError("Failed to set the 'selectionEnd' property"
393                         + "from 'HTMLInputElement': "
394                         + "The input element's type ('number') does not support selection.");
395             }
396 
397             ((SelectableTextInput) dom).setSelectionEnd(end);
398             return;
399         }
400 
401         throw Context.reportRuntimeError("Failed to set the 'selectionEnd' property from 'HTMLInputElement': "
402                 + "The input element's type (" + getType() + ") does not support selection.");
403     }
404 
405     /**
406      * Gets the max length.
407      * @return the max length
408      */
409     @JsxGetter
410     public int getMaxLength() {
411         final String attrValue = getDomNodeOrDie().getAttribute("maxLength");
412         return NumberUtils.toInt(attrValue, -1);
413     }
414 
415     /**
416      * Sets the value of {@code maxLength} attribute.
417      * @param length the new value
418      */
419     @JsxSetter
420     public void setMaxLength(final int length) {
421         getDomNodeOrDie().setMaxLength(length);
422     }
423 
424     /**
425      * Gets the {@code minLength}.
426      * @return the {@code minLength}
427      */
428     @JsxGetter({CHROME, FF52})
429     public int getMinLength() {
430         final String attrValue = getDomNodeOrDie().getAttribute("minLength");
431         return NumberUtils.toInt(attrValue, -1);
432     }
433 
434     /**
435      * Sets the value of {@code minLength} attribute.
436      * @param length the new value
437      */
438     @JsxSetter({CHROME, FF52})
439     public void setMinLength(final int length) {
440         getDomNodeOrDie().setMinLength(length);
441     }
442 
443     /**
444      * Gets the {@code min} property.
445      * @return the {@code min} property
446      */
447     @JsxGetter
448     public String getMin() {
449         return getDomNodeOrDie().getAttribute("min");
450     }
451 
452     /**
453      * Sets the {@code min} property.
454      * @param min the {@code min} property
455      */
456     @JsxSetter
457     public void setMin(final String min) {
458         getDomNodeOrDie().setAttribute("min", min);
459     }
460 
461     /**
462      * Gets the {@code max} property.
463      * @return the {@code max} property
464      */
465     @JsxGetter
466     public String getMax() {
467         return getDomNodeOrDie().getAttribute("max");
468     }
469 
470     /**
471      * Sets the {@code max} property.
472      * @param max the {@code max} property
473      */
474     @JsxSetter
475     public void setMax(final String max) {
476         getDomNodeOrDie().setAttribute("max", max);
477     }
478 
479     /**
480      * Gets the value of {@code readOnly} attribute.
481      * @return the readOnly attribute
482      */
483     @JsxGetter
484     public boolean isReadOnly() {
485         return getDomNodeOrDie().isReadOnly();
486     }
487 
488     /**
489      * Sets the value of {@code readOnly} attribute.
490      * @param readOnly the new value
491      */
492     @JsxSetter
493     public void setReadOnly(final boolean readOnly) {
494         getDomNodeOrDie().setReadOnly(readOnly);
495     }
496 
497     /**
498      * Sets the selected portion of this input element.
499      * @param start the index of the first character to select
500      * @param end the index of the character after the selection
501      */
502     @JsxFunction
503     public void setSelectionRange(final int start, final int end) {
504         setSelectionStart(start);
505         setSelectionEnd(end);
506     }
507 
508     /**
509      * Returns the value of the {@code alt} property.
510      * @return the value of the {@code alt} property
511      */
512     @JsxGetter
513     public String getAlt() {
514         return getDomNodeOrDie().getAttribute("alt");
515     }
516 
517     /**
518      * Returns the value of the {@code alt} property.
519      * @param alt the value
520      */
521     @JsxSetter
522     public void setAlt(final String alt) {
523         getDomNodeOrDie().setAttribute("alt", alt);
524     }
525 
526     /**
527      * Gets the {@code border} attribute.
528      * @return the {@code border} attribute
529      */
530     @JsxGetter(IE)
531     public String getBorder() {
532         return getDomNodeOrDie().getAttribute("border");
533     }
534 
535     /**
536      * Sets the {@code border} attribute.
537      * @param border the {@code border} attribute
538      */
539     @JsxSetter(IE)
540     public void setBorder(final String border) {
541         getDomNodeOrDie().setAttribute("border", border);
542     }
543 
544     /**
545      * Returns the value of the {@code align} property.
546      * @return the value of the {@code align} property
547      */
548     @JsxGetter
549     public String getAlign() {
550         if (getBrowserVersion().hasFeature(JS_ALIGN_FOR_INPUT_IGNORES_VALUES)) {
551             return "";
552         }
553         return getAlign(true);
554     }
555 
556     /**
557      * Sets the value of the {@code align} property.
558      * @param align the value of the {@code align} property
559      */
560     @JsxSetter
561     public void setAlign(final String align) {
562         final boolean ignoreIfNoError = getBrowserVersion().hasFeature(JS_ALIGN_FOR_INPUT_IGNORES_VALUES);
563         setAlign(align, ignoreIfNoError);
564     }
565 
566     /**
567      * Returns the value of the {@code src} attribute.
568      * @return the value of the {@code src} attribute
569      */
570     @JsxGetter
571     public String getSrc() {
572         return getDomNodeOrDie().getSrcAttribute();
573     }
574 
575     /**
576      * {@inheritDoc}
577      */
578     @Override
579     public String getValue() {
580         final HtmlInput htmlInput = getDomNodeOrDie();
581         if (htmlInput instanceof HtmlFileInput) {
582             final File[] files = ((HtmlFileInput) getDomNodeOrDie()).getFiles();
583             if (files == null || files.length == 0) {
584                 return ATTRIBUTE_NOT_DEFINED;
585             }
586             final File first = files[0];
587             final String name = first.getName();
588             if (name.isEmpty()) {
589                 return name;
590             }
591             if (getBrowserVersion().hasFeature(HTMLINPUT_FILE_VALUE_FAKEPATH)) {
592                 return "C:\\fakepath\\" + name;
593             }
594             else if (getBrowserVersion().hasFeature(HTMLINPUT_FILE_VALUE_NO_PATH)) {
595                 return name;
596             }
597             return first.getAbsolutePath();
598         }
599         return super.getValue();
600     }
601 
602     /**
603      * {@inheritDoc}
604      */
605     @Override
606     public String getAttribute(final String attributeName, final Integer flags) {
607         final String superAttribute = super.getAttribute(attributeName, flags);
608         if ("value".equalsIgnoreCase(attributeName)) {
609             if ((superAttribute == null || !superAttribute.isEmpty())
610                     && getDefaultValue().isEmpty()) {
611                 return null;
612             }
613             if (!"file".equals(getType())) {
614                 return getDefaultValue();
615             }
616         }
617         return superAttribute;
618     }
619 
620     /**
621      * {@inheritDoc}
622      */
623     @Override
624     public void click() throws IOException {
625         final HtmlInput domNode = getDomNodeOrDie();
626         final boolean originalState = domNode.isChecked();
627         final Event event;
628         if (getBrowserVersion().hasFeature(EVENT_ONCLICK_USES_POINTEREVENT)) {
629             event = new PointerEvent(domNode, MouseEvent.TYPE_CLICK, false, false, false, MouseEvent.BUTTON_LEFT);
630         }
631         else {
632             event = new MouseEvent(domNode, MouseEvent.TYPE_CLICK, false, false, false, MouseEvent.BUTTON_LEFT);
633         }
634         domNode.click(event, true);
635 
636         final boolean newState = domNode.isChecked();
637 
638         if (originalState != newState
639                 && (domNode instanceof HtmlRadioButtonInput || domNode instanceof HtmlCheckBoxInput)) {
640             domNode.fireEvent(Event.TYPE_CHANGE);
641         }
642     }
643 
644     /**
645      * {@inheritDoc}
646      */
647     @Override
648     protected boolean isEndTagForbidden() {
649         return true;
650     }
651 
652     /**
653      * Returns the {@code required} property.
654      * @return the {@code required} property
655      */
656     @JsxGetter
657     public boolean isRequired() {
658         return getDomNodeOrDie().isRequired();
659     }
660 
661     /**
662      * Sets the {@code required} property.
663      * @param required the new value
664      */
665     @JsxSetter
666     public void setRequired(final boolean required) {
667         getDomNodeOrDie().setRequired(required);
668     }
669 
670     /**
671      * Returns the {@code size} attribute.
672      * @return the {@code size} attribute
673      */
674     @JsxGetter
675     public String getSize() {
676         return getDomNodeOrDie().getSize();
677     }
678 
679     /**
680      * Sets the {@code size} attribute.
681      * @param size the new {@code size} value
682      */
683     @JsxSetter
684     public void setSize(final String size) {
685         getDomNodeOrDie().setSize(size);
686     }
687 
688     /**
689      * Returns the {@code accept} attribute.
690      * @return the {@code accept} attribute
691      */
692     @JsxGetter
693     public String getAccept() {
694         return getDomNodeOrDie().getAccept();
695     }
696 
697     /**
698      * Sets the {@code accept} attribute.
699      * @param accept the new {@code accept} value
700      */
701     @JsxSetter
702     public void setAccept(final String accept) {
703         getDomNodeOrDie().setAccept(accept);
704     }
705 
706     /**
707      * Returns the {@code autocomplete} attribute.
708      * @return the {@code autocomplete} attribute
709      */
710     @JsxGetter
711     public String getAutocomplete() {
712         return getDomNodeOrDie().getAutocomplete();
713     }
714 
715     /**
716      * Sets the {@code autocomplete} attribute.
717      * @param autocomplete the new {@code autocomplete} value
718      */
719     @JsxSetter
720     public void setAutocomplete(final String autocomplete) {
721         getDomNodeOrDie().setAutocomplete(autocomplete);
722     }
723 
724     /**
725      * Returns the {@code files} property.
726      * @return the {@code files} property
727      */
728     @JsxGetter
729     public Object getFiles() {
730         final HtmlInput htmlInput = getDomNodeOrDie();
731         if (htmlInput instanceof HtmlFileInput) {
732             final FileList list = new FileList(((HtmlFileInput) htmlInput).getFiles());
733             list.setParentScope(getParentScope());
734             list.setPrototype(getPrototype(list.getClass()));
735             return list;
736         }
737         if (getBrowserVersion().hasFeature(HTMLINPUT_FILES_UNDEFINED)) {
738             return Undefined.instance;
739         }
740         return null;
741     }
742 
743     /**
744      * Returns the {@code placeholder} attribute.
745      * @return the {@code placeholder} attribute
746      */
747     @JsxGetter
748     public String getPlaceholder() {
749         return getDomNodeOrDie().getPlaceholder();
750     }
751 
752     /**
753      * Sets the {@code placeholder} attribute.
754      * @param placeholder the new {@code placeholder} value
755      */
756     @JsxSetter
757     public void setPlaceholder(final String placeholder) {
758         getDomNodeOrDie().setPlaceholder(placeholder);
759     }
760 
761     /**
762      * Returns the {@code width} property.
763      * @return the {@code width} property
764      */
765     @Override
766     @JsxGetter
767     public int getWidth() {
768         final String value = getDomNodeOrDie().getAttribute("width");
769         final Integer intValue = HTMLCanvasElement.getValue(value);
770         if (intValue != null) {
771             return intValue;
772         }
773         return 0;
774     }
775 
776     /**
777      * Sets the {@code width} property.
778      * @param width the {@code width} property
779      */
780     @JsxSetter
781     public void setWidth(final int width) {
782         getDomNodeOrDie().setAttribute("width", Integer.toString(width));
783     }
784 
785     /**
786      * Returns the {@code height} property.
787      * @return the {@code height} property
788      */
789     @Override
790     @JsxGetter
791     public int getHeight() {
792         final String value = getDomNodeOrDie().getAttribute("height");
793         final Integer intValue = HTMLCanvasElement.getValue(value);
794         if (intValue != null) {
795             return intValue;
796         }
797         return 0;
798     }
799 
800     /**
801      * Sets the {@code height} property.
802      * @param height the {@code height} property
803      */
804     @JsxSetter
805     public void setHeight(final int height) {
806         getDomNodeOrDie().setAttribute("height", Integer.toString(height));
807     }
808 
809     /**
810      * Returns the labels associated with the element.
811      * @return the labels associated with the element
812      */
813     @JsxGetter(CHROME)
814     public AbstractList getLabels() {
815         if (labels_ == null) {
816             labels_ = new LabelsHelper(getDomNodeOrDie());
817         }
818         return labels_;
819     }
820 
821     /**
822      * Checks whether the element has any constraints and whether it satisfies them.
823      * @return if the element is valid
824      */
825     @JsxFunction
826     public boolean checkValidity() {
827         return getDomNodeOrDie().isValid();
828     }
829 
830     /**
831      * {@inheritDoc}
832      */
833     @Override
834     @JsxFunction(IE)
835     public TextRange createTextRange() {
836         return super.createTextRange();
837     }
838 }