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.dom;
16  
17  import static org.htmlunit.BrowserVersionFeatures.EVENT_ONANIMATION_DOCUMENT_CREATE_NOT_SUPPORTED;
18  import static org.htmlunit.BrowserVersionFeatures.EVENT_ONCLOSE_DOCUMENT_CREATE_NOT_SUPPORTED;
19  import static org.htmlunit.BrowserVersionFeatures.EVENT_ONPOPSTATE_DOCUMENT_CREATE_NOT_SUPPORTED;
20  import static org.htmlunit.BrowserVersionFeatures.EVENT_TYPE_MUTATIONEVENT;
21  import static org.htmlunit.BrowserVersionFeatures.EVENT_TYPE_TEXTEVENT;
22  import static org.htmlunit.BrowserVersionFeatures.EVENT_TYPE_WHEELEVENT;
23  import static org.htmlunit.BrowserVersionFeatures.HTMLDOCUMENT_COOKIES_IGNORE_BLANK;
24  import static org.htmlunit.BrowserVersionFeatures.JS_DOCUMENT_EVALUATE_RECREATES_RESULT;
25  import static org.htmlunit.BrowserVersionFeatures.JS_DOCUMENT_SELECTION_RANGE_COUNT;
26  import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
27  import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
28  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
29  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
30  
31  import java.io.IOException;
32  import java.io.Serializable;
33  import java.lang.reflect.InvocationTargetException;
34  import java.net.URL;
35  import java.time.ZoneId;
36  import java.time.format.DateTimeFormatter;
37  import java.util.Collections;
38  import java.util.Date;
39  import java.util.HashMap;
40  import java.util.HashSet;
41  import java.util.Locale;
42  import java.util.Map;
43  import java.util.Set;
44  import java.util.UUID;
45  import java.util.function.Predicate;
46  
47  import org.apache.commons.lang3.StringUtils;
48  import org.apache.commons.logging.Log;
49  import org.apache.commons.logging.LogFactory;
50  import org.htmlunit.HttpHeader;
51  import org.htmlunit.Page;
52  import org.htmlunit.SgmlPage;
53  import org.htmlunit.WebClient;
54  import org.htmlunit.WebResponse;
55  import org.htmlunit.WebWindow;
56  import org.htmlunit.corejs.javascript.Callable;
57  import org.htmlunit.corejs.javascript.Context;
58  import org.htmlunit.corejs.javascript.Function;
59  import org.htmlunit.corejs.javascript.NativeFunction;
60  import org.htmlunit.corejs.javascript.Scriptable;
61  import org.htmlunit.corejs.javascript.ScriptableObject;
62  import org.htmlunit.cssparser.parser.CSSException;
63  import org.htmlunit.html.DomComment;
64  import org.htmlunit.html.DomDocumentFragment;
65  import org.htmlunit.html.DomElement;
66  import org.htmlunit.html.DomNode;
67  import org.htmlunit.html.DomText;
68  import org.htmlunit.html.FrameWindow;
69  import org.htmlunit.html.Html;
70  import org.htmlunit.html.HtmlAnchor;
71  import org.htmlunit.html.HtmlArea;
72  import org.htmlunit.html.HtmlAttributeChangeEvent;
73  import org.htmlunit.html.HtmlElement;
74  import org.htmlunit.html.HtmlEmbed;
75  import org.htmlunit.html.HtmlForm;
76  import org.htmlunit.html.HtmlFrameSet;
77  import org.htmlunit.html.HtmlImage;
78  import org.htmlunit.html.HtmlPage;
79  import org.htmlunit.html.HtmlRb;
80  import org.htmlunit.html.HtmlRp;
81  import org.htmlunit.html.HtmlRt;
82  import org.htmlunit.html.HtmlRtc;
83  import org.htmlunit.html.HtmlScript;
84  import org.htmlunit.html.HtmlSvg;
85  import org.htmlunit.html.HtmlUnknownElement;
86  import org.htmlunit.html.UnknownElementFactory;
87  import org.htmlunit.html.impl.SimpleRange;
88  import org.htmlunit.http.HttpUtils;
89  import org.htmlunit.httpclient.HtmlUnitBrowserCompatCookieSpec;
90  import org.htmlunit.javascript.HtmlUnitScriptable;
91  import org.htmlunit.javascript.JavaScriptEngine;
92  import org.htmlunit.javascript.configuration.JsxClass;
93  import org.htmlunit.javascript.configuration.JsxConstructor;
94  import org.htmlunit.javascript.configuration.JsxFunction;
95  import org.htmlunit.javascript.configuration.JsxGetter;
96  import org.htmlunit.javascript.configuration.JsxSetter;
97  import org.htmlunit.javascript.host.Element;
98  import org.htmlunit.javascript.host.FontFaceSet;
99  import org.htmlunit.javascript.host.Location;
100 import org.htmlunit.javascript.host.NativeFunctionPrefixResolver;
101 import org.htmlunit.javascript.host.Window;
102 import org.htmlunit.javascript.host.animations.AnimationEvent;
103 import org.htmlunit.javascript.host.css.StyleSheetList;
104 import org.htmlunit.javascript.host.dom.AbstractList.EffectOnCache;
105 import org.htmlunit.javascript.host.event.BeforeUnloadEvent;
106 import org.htmlunit.javascript.host.event.CloseEvent;
107 import org.htmlunit.javascript.host.event.CompositionEvent;
108 import org.htmlunit.javascript.host.event.CustomEvent;
109 import org.htmlunit.javascript.host.event.DragEvent;
110 import org.htmlunit.javascript.host.event.Event;
111 import org.htmlunit.javascript.host.event.FocusEvent;
112 import org.htmlunit.javascript.host.event.HashChangeEvent;
113 import org.htmlunit.javascript.host.event.KeyboardEvent;
114 import org.htmlunit.javascript.host.event.MessageEvent;
115 import org.htmlunit.javascript.host.event.MouseEvent;
116 import org.htmlunit.javascript.host.event.MutationEvent;
117 import org.htmlunit.javascript.host.event.PointerEvent;
118 import org.htmlunit.javascript.host.event.PopStateEvent;
119 import org.htmlunit.javascript.host.event.ProgressEvent;
120 import org.htmlunit.javascript.host.event.TextEvent;
121 import org.htmlunit.javascript.host.event.UIEvent;
122 import org.htmlunit.javascript.host.event.WheelEvent;
123 import org.htmlunit.javascript.host.file.Blob;
124 import org.htmlunit.javascript.host.html.HTMLAllCollection;
125 import org.htmlunit.javascript.host.html.HTMLBodyElement;
126 import org.htmlunit.javascript.host.html.HTMLCollection;
127 import org.htmlunit.javascript.host.html.HTMLElement;
128 import org.htmlunit.javascript.host.html.HTMLFrameSetElement;
129 import org.htmlunit.util.Cookie;
130 import org.htmlunit.util.UrlUtils;
131 import org.htmlunit.xpath.xml.utils.PrefixResolver;
132 import org.w3c.dom.CDATASection;
133 import org.w3c.dom.DOMException;
134 import org.w3c.dom.DocumentType;
135 import org.w3c.dom.ProcessingInstruction;
136 
137 /**
138  * A JavaScript object for {@code Document}.
139  *
140  * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
141  * @author David K. Taylor
142  * @author <a href="mailto:chen_jun@users.sourceforge.net">Chen Jun</a>
143  * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
144  * @author Chris Erskine
145  * @author Marc Guillemot
146  * @author Daniel Gredler
147  * @author Michael Ottati
148  * @author <a href="mailto:george@murnock.com">George Murnock</a>
149  * @author Ahmed Ashour
150  * @author Rob Di Marco
151  * @author Ronald Brill
152  * @author Chuck Dumont
153  * @author Frank Danek
154  * @author Madis Pärn
155  * @author Lai Quang Duong
156  * @author Sven Strickroth
157  *
158  * @see <a href="http://msdn.microsoft.com/en-us/library/ms531073.aspx">MSDN documentation</a>
159  * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-7068919">W3C Dom Level 1</a>
160  */
161 @JsxClass
162 public class Document extends Node {
163 
164     private static final Log LOG = LogFactory.getLog(Document.class);
165 
166     /** https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla#Executing_Commands */
167     private static final Set<String> EXECUTE_CMDS_FF = new HashSet<>();
168     private static final Set<String> EXECUTE_CMDS_CHROME = new HashSet<>();
169     /** The formatter to use for the <code>lastModified</code> attribute. */
170     private static final DateTimeFormatter LAST_MODIFIED_DATE_FORMATTER
171                                             = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
172 
173     /** Contains all supported DOM level 2 events. */
174     private static final Map<String, Class<? extends Event>> SUPPORTED_DOM2_EVENT_TYPE_MAP;
175     /** Contains all supported DOM level 3 events. DOM level 2 events are not included. */
176     private static final Map<String, Class<? extends Event>> SUPPORTED_DOM3_EVENT_TYPE_MAP;
177     /** Contains all supported vendor specific events. */
178     private static final Map<String, Class<? extends Event>> SUPPORTED_VENDOR_EVENT_TYPE_MAP;
179 
180     /*
181       Initializes the supported event type map.
182       Map<String, Class> which maps strings a caller may use when calling into
183       {@link #createEvent(String)} to the associated event class. To support a new
184       event creation type, the event type and associated class need to be added into this map in
185       the static initializer. The map is unmodifiable. Any class that is a value in this map MUST
186       have a no-arg constructor.
187      */
188     static {
189         final Map<String, Class<? extends Event>> dom2EventMap = new HashMap<>();
190         dom2EventMap.put("HTMLEvents", Event.class);
191         dom2EventMap.put("MouseEvents", MouseEvent.class);
192         dom2EventMap.put("MutationEvents", MutationEvent.class);
193         dom2EventMap.put("UIEvents", UIEvent.class);
194         SUPPORTED_DOM2_EVENT_TYPE_MAP = Collections.unmodifiableMap(dom2EventMap);
195 
196         final Map<String, Class<? extends Event>> dom3EventMap = new HashMap<>();
197         dom3EventMap.put("Event", Event.class);
198         dom3EventMap.put("KeyboardEvent", KeyboardEvent.class);
199         dom3EventMap.put("MouseEvent", MouseEvent.class);
200         dom3EventMap.put("MessageEvent", MessageEvent.class);
201         dom3EventMap.put("MutationEvent", MutationEvent.class);
202         dom3EventMap.put("UIEvent", UIEvent.class);
203         dom3EventMap.put("CustomEvent", CustomEvent.class);
204         dom3EventMap.put("CloseEvent", CloseEvent.class);
205         dom3EventMap.put("CompositionEvent", CompositionEvent.class);
206         dom3EventMap.put("DragEvent", DragEvent.class);
207         dom3EventMap.put("TextEvent", TextEvent.class);
208         SUPPORTED_DOM3_EVENT_TYPE_MAP = Collections.unmodifiableMap(dom3EventMap);
209 
210         final Map<String, Class<? extends Event>> additionalEventMap = new HashMap<>();
211         additionalEventMap.put("BeforeUnloadEvent", BeforeUnloadEvent.class);
212         additionalEventMap.put("Events", Event.class);
213         additionalEventMap.put("HashChangeEvent", HashChangeEvent.class);
214         additionalEventMap.put("KeyEvents", KeyboardEvent.class);
215         additionalEventMap.put("PointerEvent", PointerEvent.class);
216         additionalEventMap.put("PopStateEvent", PopStateEvent.class);
217         additionalEventMap.put("ProgressEvent", ProgressEvent.class);
218         additionalEventMap.put("FocusEvent", FocusEvent.class);
219         additionalEventMap.put("WheelEvent", WheelEvent.class);
220         additionalEventMap.put("AnimationEvent", AnimationEvent.class);
221         SUPPORTED_VENDOR_EVENT_TYPE_MAP = Collections.unmodifiableMap(additionalEventMap);
222     }
223 
224     private Window window_;
225     private DOMImplementation implementation_;
226     private String designMode_;
227     private String compatMode_;
228     private int documentMode_ = -1;
229     private String domain_;
230     private String lastModified_;
231     private ScriptableObject currentScript_;
232     private transient FontFaceSet fonts_;
233     private transient StyleSheetList styleSheetList_;
234 
235     private final Map<String, Blob> blobUrl2Blobs_ = new HashMap<>();
236 
237     static {
238         // commands
239         String[] cmds = {
240             "BackColor", "BackgroundImageCache" /* Undocumented */,
241             "Bold",
242             "CreateLink", "Delete",
243             "FontName", "FontSize", "ForeColor", "FormatBlock",
244             "Indent", "InsertHorizontalRule", "InsertImage",
245             "InsertOrderedList", "InsertParagraph", "InsertUnorderedList",
246             "Italic", "JustifyCenter", "JustifyFull", "JustifyLeft", "JustifyNone",
247             "JustifyRight",
248             "Outdent",
249             "Print",
250             "Redo", "RemoveFormat",
251             "SelectAll", "StrikeThrough", "Subscript", "Superscript",
252             "Underline", "Undo", "Unlink", "Unselect"
253         };
254         for (final String cmd : cmds) {
255             if (!"Bold".equals(cmd)) {
256                 EXECUTE_CMDS_CHROME.add(cmd.toLowerCase(Locale.ROOT));
257             }
258         }
259 
260         cmds = new String[] {
261             "backColor", "bold", "contentReadOnly", "copy", "createLink", "cut", "decreaseFontSize", "delete",
262             "fontName", "fontSize", "foreColor", "formatBlock", "heading", "hiliteColor", "increaseFontSize",
263             "indent", "insertHorizontalRule", "insertHTML", "insertImage", "insertOrderedList", "insertUnorderedList",
264             "insertParagraph", "italic",
265             "justifyCenter", "JustifyFull", "justifyLeft", "justifyRight", "outdent", "paste", "redo",
266             "removeFormat", "selectAll", "strikeThrough", "subscript", "superscript", "underline", "undo", "unlink",
267             "useCSS", "styleWithCSS"
268         };
269         for (final String cmd : cmds) {
270             EXECUTE_CMDS_FF.add(cmd.toLowerCase(Locale.ROOT));
271             if (!"bold".equals(cmd)) {
272                 EXECUTE_CMDS_CHROME.add(cmd.toLowerCase(Locale.ROOT));
273             }
274         }
275     }
276 
277     /**
278      * JavaScript constructor.
279      */
280     @Override
281     @JsxConstructor
282     public void jsConstructor() {
283         throw JavaScriptEngine.typeErrorIllegalConstructor();
284     }
285 
286     /**
287      * Sets the Window JavaScript object that encloses this document.
288      * @param window the Window JavaScript object that encloses this document
289      */
290     public void setWindow(final Window window) {
291         window_ = window;
292     }
293 
294     /**
295      * Returns the value of the {@code location} property.
296      * @return the value of the {@code location} property
297      */
298     @JsxGetter
299     public Location getLocation() {
300         if (window_ == null) {
301             return null;
302         }
303         return window_.getLocation();
304     }
305 
306     /**
307      * Sets the value of the {@code location} property. The location's default property is "href",
308      * so setting "document.location='http://www.sf.net'" is equivalent to setting
309      * "document.location.href='http://www.sf.net'".
310      * @see <a href="http://msdn.microsoft.com/en-us/library/ms535866.aspx">MSDN documentation</a>
311      * @param location the location to navigate to
312      * @throws IOException when location loading fails
313      */
314     @JsxSetter
315     public void setLocation(final String location) throws IOException {
316         window_.setLocation(location);
317     }
318 
319     /**
320      * Returns the value of the {@code referrer} property.
321      * @return the value of the {@code referrer} property
322      */
323     @JsxGetter
324     public String getReferrer() {
325         String referrer = "";
326         final WebResponse webResponse = getPage().getWebResponse();
327         if (webResponse != null) {
328             referrer = webResponse.getWebRequest().getAdditionalHeaders().get(HttpHeader.REFERER);
329             if (referrer == null) {
330                 referrer = "";
331             }
332         }
333         return referrer;
334     }
335 
336     /**
337      * Gets the JavaScript property {@code documentElement} for the document.
338      * @return the root node for the document
339      */
340     @JsxGetter
341     public Element getDocumentElement() {
342         final Object documentElement = getPage().getDocumentElement();
343         if (documentElement == null) {
344             // for instance with an XML document with parsing error
345             return null;
346         }
347         return (Element) getScriptableFor(documentElement);
348     }
349 
350     /**
351      * Gets the JavaScript property {@code rootElement}.
352      * @return the root node for the document
353      */
354     @JsxGetter
355     public Element getRootElement() {
356         return null;
357     }
358 
359     /**
360      * Gets the JavaScript property {@code doctype} for the document.
361      * @return the DocumentType of the document
362      */
363     @JsxGetter
364     public HtmlUnitScriptable getDoctype() {
365         final Object documentType = getPage().getDoctype();
366         if (documentType == null) {
367             return null;
368         }
369         return getScriptableFor(documentType);
370     }
371 
372     /**
373      * Returns a value which indicates whether or not the document can be edited.
374      * @return a value which indicates whether or not the document can be edited
375      */
376     @JsxGetter
377     public String getDesignMode() {
378         if (designMode_ == null) {
379             designMode_ = "off";
380         }
381         return designMode_;
382     }
383 
384     /**
385      * Sets a value which indicates whether or not the document can be edited.
386      * @param mode a value which indicates whether or not the document can be edited
387      */
388     @JsxSetter
389     public void setDesignMode(final String mode) {
390         if ("on".equalsIgnoreCase(mode)) {
391             designMode_ = "on";
392             final SgmlPage page = getPage();
393             if (page != null && page.isHtmlPage()
394                     && getBrowserVersion().hasFeature(JS_DOCUMENT_SELECTION_RANGE_COUNT)) {
395                 final HtmlPage htmlPage = (HtmlPage) page;
396                 final DomNode child = htmlPage.getBody().getFirstChild();
397                 final DomNode rangeNode = child == null ? htmlPage.getBody() : child;
398                 htmlPage.setSelectionRange(new SimpleRange(rangeNode, 0));
399             }
400         }
401         else if ("off".equalsIgnoreCase(mode)) {
402             designMode_ = "off";
403         }
404     }
405 
406     /**
407      * Returns the page that this document is modeling.
408      * @return the page that this document is modeling
409      */
410     public SgmlPage getPage() {
411         return (SgmlPage) getDomNodeOrDie();
412     }
413 
414     /**
415      * Gets the window in which this document is contained.
416      * @return the window
417      */
418     @JsxGetter
419     public Object getDefaultView() {
420         return getWindow();
421     }
422 
423     /**
424      * Creates a new document fragment.
425      * @return a newly created document fragment
426      */
427     @JsxFunction
428     public HtmlUnitScriptable createDocumentFragment() {
429         final DomDocumentFragment fragment = getDomNodeOrDie().getPage().createDocumentFragment();
430         final DocumentFragment node = new DocumentFragment();
431         node.setParentScope(getParentScope());
432         node.setPrototype(getPrototype(node.getClass()));
433         node.setDomNode(fragment);
434         return getScriptableFor(fragment);
435     }
436 
437     /**
438      * Creates a new HTML attribute with the specified name.
439      *
440      * @param attributeName the name of the attribute to create
441      * @return an attribute with the specified name
442      */
443     @JsxFunction
444     public Attr createAttribute(final String attributeName) {
445         return getPage().createAttribute(attributeName).getScriptableObject();
446     }
447 
448     /**
449      * Imports a node from another document to this document.
450      * The source node is not altered or removed from the original document;
451      * this method creates a new copy of the source node.
452      *
453      * @param importedNode the node to import
454      * @param deep Whether to recursively import the subtree under the specified node; or not
455      * @return the imported node that belongs to this Document
456      */
457     @JsxFunction
458     public HtmlUnitScriptable importNode(final Node importedNode, final boolean deep) {
459         DomNode domNode = importedNode.getDomNodeOrDie();
460         domNode = domNode.cloneNode(deep);
461         domNode.processImportNode(this);
462         for (final DomNode childNode : domNode.getDescendants()) {
463             childNode.processImportNode(this);
464         }
465         return domNode.getScriptableObject();
466     }
467 
468     /**
469      * Adopts a node from an external document.
470      * The node and its subtree is removed from the document it's in (if any),
471      * and its ownerDocument is changed to the current document.
472      * The node can then be inserted into the current document.
473      *
474      * @param externalNode the node from another document to be adopted
475      * @return the adopted node that can be used in the current document
476      */
477     @JsxFunction
478     public HtmlUnitScriptable adoptNode(final Node externalNode) {
479         externalNode.remove();
480         return importNode(externalNode, true);
481     }
482 
483     /**
484      * Returns the implementation object of the current document.
485      * @return implementation-specific object
486      */
487     @JsxGetter
488     public DOMImplementation getImplementation() {
489         if (implementation_ == null) {
490             implementation_ = new DOMImplementation();
491             implementation_.setParentScope(getWindow());
492             implementation_.setPrototype(getPrototype(implementation_.getClass()));
493         }
494         return implementation_;
495     }
496 
497     /**
498      * Adapts any DOM node to resolve namespaces so that an XPath expression can be easily
499      * evaluated relative to the context of the node where it appeared within the document.
500      * @param nodeResolver the node to be used as a context for namespace resolution
501      * @return an XPathNSResolver which resolves namespaces with respect to the definitions
502      *         in scope for a specified node
503      */
504     @JsxFunction
505     public XPathNSResolver createNSResolver(final Node nodeResolver) {
506         final XPathNSResolver resolver = new XPathNSResolver();
507         resolver.setElement(nodeResolver);
508         resolver.setParentScope(getWindow());
509         resolver.setPrototype(getPrototype(resolver.getClass()));
510         return resolver;
511     }
512 
513     /**
514      * Create a new DOM text node with the given data.
515      *
516      * @param newData the string value for the text node
517      * @return the new text node or NOT_FOUND if there is an error
518      */
519     @JsxFunction
520     public HtmlUnitScriptable createTextNode(final String newData) {
521         final DomNode domNode = new DomText(getDomNodeOrDie().getPage(), newData);
522         return makeScriptableFor(domNode);
523     }
524 
525     /**
526      * Creates a new Comment.
527      * @param comment the comment text
528      * @return the new Comment
529      */
530     @JsxFunction
531     public HtmlUnitScriptable createComment(final String comment) {
532         final DomNode domNode = new DomComment(getDomNodeOrDie().getPage(), comment);
533         return getScriptableFor(domNode);
534     }
535 
536     /**
537      * Evaluates an XPath expression string and returns a result of the specified type if possible.
538      * @param expression the XPath expression string to be parsed and evaluated
539      * @param contextNode the context node for the evaluation of this XPath expression
540      * @param resolver the resolver permits translation of all prefixes, including the XML namespace prefix,
541      *        within the XPath expression into appropriate namespace URIs.
542      * @param type If a specific type is specified, then the result will be returned as the corresponding type
543      * @param result the result object which may be reused and returned by this method
544      * @return the result of the evaluation of the XPath expression
545      */
546     @JsxFunction
547     public XPathResult evaluate(final String expression, final Node contextNode,
548             final Object resolver, final int type, final Object result) {
549         XPathResult xPathResult = null;
550         if (result instanceof XPathResult) {
551             xPathResult = (XPathResult) result;
552 
553             if (getBrowserVersion().hasFeature(JS_DOCUMENT_EVALUATE_RECREATES_RESULT)) {
554                 xPathResult = new XPathResult();
555                 xPathResult.setParentScope(getParentScope());
556                 xPathResult.setPrototype(getPrototype(xPathResult.getClass()));
557             }
558         }
559         else if (result == null
560                 || JavaScriptEngine.isUndefined(result)
561                 || result instanceof ScriptableObject) {
562             xPathResult = new XPathResult();
563             xPathResult.setParentScope(getParentScope());
564             xPathResult.setPrototype(getPrototype(xPathResult.getClass()));
565         }
566         else {
567             throw JavaScriptEngine.typeError("Argument 5 of Document.evaluate has to be an XPathResult or null.");
568         }
569 
570         try {
571             PrefixResolver prefixResolver = null;
572             if (resolver instanceof NativeFunction) {
573                 prefixResolver = new NativeFunctionPrefixResolver(
574                                             (NativeFunction) resolver, contextNode.getParentScope());
575             }
576             else if (resolver instanceof PrefixResolver) {
577                 prefixResolver = (PrefixResolver) resolver;
578             }
579             xPathResult.init(contextNode.getDomNodeOrDie().getByXPath(expression, prefixResolver), type);
580             return xPathResult;
581         }
582         catch (final Exception e) {
583             throw JavaScriptEngine.asJavaScriptException(
584                     getWindow(),
585                     "Failed to execute 'evaluate': " + e.getMessage(),
586                     org.htmlunit.javascript.host.dom.DOMException.SYNTAX_ERR);
587         }
588     }
589 
590     /**
591      * Creates a new element with the given tag name.
592      *
593      * @param tagName the tag name
594      * @return the new HTML element, or NOT_FOUND if the tag is not supported
595      */
596     @JsxFunction
597     public HtmlUnitScriptable createElement(final Object tagName) {
598         if (tagName == null || JavaScriptEngine.isUndefined(tagName)) {
599             final org.w3c.dom.Node element = getPage().createElement("unknown");
600             ((HtmlUnknownElement) element).markAsCreatedByJavascript();
601             return getScriptableFor(element);
602         }
603 
604         // https://dom.spec.whatwg.org/#dom-document-createelement
605         // NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D]
606         //                       | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF]
607         //                       | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
608         // NameChar      ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
609         // Name          ::= NameStartChar (NameChar)*
610 
611         // but i have no idea what the browsers are doing
612         // the following code is a wild guess that might be good enough for the moment
613         final String tagNameString = JavaScriptEngine.toString(tagName);
614         if (tagNameString.length() > 0) {
615             final int firstChar = tagNameString.charAt(0);
616             if (!(isLetter(firstChar)
617                     || ':' == firstChar
618                     || '_' == firstChar)) {
619                 if (LOG.isInfoEnabled()) {
620                     LOG.info("createElement: Provided string '" + tagNameString + "' contains an invalid character");
621                 }
622                 throw JavaScriptEngine.asJavaScriptException(
623                         getWindow(),
624                         "createElement: Provided string '" + tagNameString + "' contains an invalid character",
625                         org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
626             }
627             final int length = tagNameString.length();
628             for (int i = 1; i < length; i++) {
629                 final int c = tagNameString.charAt(i);
630                 if (!(Character.isLetterOrDigit(c)
631                         || ':' == c
632                         || '_' == c
633                         || '-' == c
634                         || '.' == c)) {
635                     if (LOG.isInfoEnabled()) {
636                         LOG.info("createElement: Provided string '"
637                                     + tagNameString + "' contains an invalid character");
638                     }
639                     throw JavaScriptEngine.asJavaScriptException(
640                             getWindow(),
641                             "createElement: Provided string '" + tagNameString
642                                 + "' contains an invalid character",
643                             org.htmlunit.javascript.host.dom.DOMException.INVALID_CHARACTER_ERR);
644                 }
645             }
646         }
647 
648         org.w3c.dom.Node element = getPage().createElement(tagNameString);
649 
650         if (element instanceof HtmlImage) {
651             ((HtmlImage) element).markAsCreatedByJavascript();
652         }
653         else if (element instanceof HtmlRb) {
654             ((HtmlRb) element).markAsCreatedByJavascript();
655         }
656         else if (element instanceof HtmlRp) {
657             ((HtmlRp) element).markAsCreatedByJavascript();
658         }
659         else if (element instanceof HtmlRt) {
660             ((HtmlRt) element).markAsCreatedByJavascript();
661         }
662         else if (element instanceof HtmlRtc) {
663             ((HtmlRtc) element).markAsCreatedByJavascript();
664         }
665         else if (element instanceof HtmlUnknownElement) {
666             ((HtmlUnknownElement) element).markAsCreatedByJavascript();
667         }
668         else if (element instanceof HtmlSvg) {
669             element = UnknownElementFactory.INSTANCE.createElementNS(getPage(), "", "svg", null);
670             ((HtmlUnknownElement) element).markAsCreatedByJavascript();
671         }
672         final HtmlUnitScriptable jsElement = getScriptableFor(element);
673 
674         if (jsElement == NOT_FOUND) {
675             if (LOG.isDebugEnabled()) {
676                 LOG.debug("createElement(" + tagName
677                     + ") cannot return a result as there isn't a JavaScript object for the element "
678                     + element.getClass().getName());
679             }
680         }
681         return jsElement;
682     }
683 
684     // our version of the Character.isLetter() without MODIFIER_LETTER
685     private static boolean isLetter(final int codePoint) {
686         return ((((1 << Character.UPPERCASE_LETTER)
687                     | (1 << Character.LOWERCASE_LETTER)
688                     | (1 << Character.TITLECASE_LETTER)
689                     | (1 << Character.OTHER_LETTER)
690                 ) >> Character.getType(codePoint)) & 1) != 0;
691     }
692 
693     /**
694      * Creates a new HTML element with the given tag name, and name.
695      *
696      * @param namespaceURI the URI that identifies an XML namespace
697      * @param qualifiedName the qualified name of the element type to instantiate
698      * @return the new HTML element, or NOT_FOUND if the tag is not supported
699      */
700     @JsxFunction
701     public HtmlUnitScriptable createElementNS(final String namespaceURI, final String qualifiedName) {
702         if ("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul".equals(namespaceURI)) {
703             throw JavaScriptEngine.typeError("XUL not available");
704         }
705 
706         final org.w3c.dom.Element element;
707         if (Html.XHTML_NAMESPACE.equals(namespaceURI)
708                 || Html.SVG_NAMESPACE.equals(namespaceURI)) {
709             element = getPage().createElementNS(namespaceURI, qualifiedName);
710         }
711         else {
712             element = new DomElement(namespaceURI, qualifiedName, getPage(), null);
713         }
714         return getScriptableFor(element);
715     }
716 
717     /**
718      * Returns all the descendant elements with the specified tag name.
719      * @param tagName the name to search for
720      * @return all the descendant elements with the specified tag name
721      */
722     @JsxFunction
723     public HTMLCollection getElementsByTagName(final String tagName) {
724         final HTMLCollection collection = new HTMLCollection(getDomNodeOrDie(), false);
725 
726         if (org.htmlunit.util.StringUtils.equalsChar('*', tagName)) {
727             collection.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> true);
728         }
729         else {
730             collection.setIsMatchingPredicate(
731                     (Predicate<DomNode> & Serializable)
732                     node -> tagName.equalsIgnoreCase(node.getNodeName()));
733         }
734 
735         return collection;
736     }
737 
738     /**
739      * Returns a list of elements with the given tag name belonging to the given namespace.
740      * @param namespaceURI the namespace URI of elements to look for
741      * @param localName is either the local name of elements to look for or the special value "*",
742      *                  which matches all elements.
743      * @return a live NodeList of found elements in the order they appear in the tree
744      */
745     @JsxFunction
746     public HTMLCollection getElementsByTagNameNS(final Object namespaceURI, final String localName) {
747         final HTMLCollection elements = new HTMLCollection(getDomNodeOrDie(), false);
748         elements.setIsMatchingPredicate(
749                 (Predicate<DomNode> & Serializable)
750                 node -> localName.equals(node.getLocalName()));
751         return elements;
752     }
753 
754     /**
755      * Returns the value of the {@code activeElement} property.
756      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533065.aspx">MSDN documentation</a>
757      * @return the value of the {@code activeElement} property
758      */
759     @JsxGetter
760     public Object getActiveElement() {
761         return null;
762     }
763 
764     /**
765      * Returns the character encoding of the current document.
766      * @return the character encoding of the current document
767      */
768     @JsxGetter
769     public String getCharacterSet() {
770         if (!(getPage() instanceof HtmlPage)) {
771             // TODO: implement XmlPage.getCharset
772             return "";
773         }
774         return getPage().getCharset().name();
775     }
776 
777     /**
778      * Retrieves the character set used to encode the document.
779      * @return the character set used to encode the document
780      */
781     @JsxGetter
782     public String getCharset() {
783         if (!(getPage() instanceof HtmlPage)) {
784             // TODO: implement XmlPage.getCharset
785             return "";
786         }
787         return getPage().getCharset().name();
788     }
789 
790     /**
791      * Returns the value of the JavaScript property {@code anchors}.
792      * @see <a href="http://msdn.microsoft.com/en-us/library/ms537435.aspx">MSDN documentation</a>
793      * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_doc_ref4.html#1024543">
794      *     Gecko DOM reference</a>
795      * @return the value of this property
796      */
797     @JsxGetter
798     public HTMLCollection getAnchors() {
799         final HTMLCollection anchors = new HTMLCollection(getDomNodeOrDie(), true);
800 
801         anchors.setIsMatchingPredicate(
802                 (Predicate<DomNode> & Serializable)
803                 node -> {
804                     if (!(node instanceof HtmlAnchor)) {
805                         return false;
806                     }
807                     final HtmlAnchor anchor = (HtmlAnchor) node;
808                     return anchor.hasAttribute(DomElement.NAME_ATTRIBUTE);
809                 });
810 
811         anchors.setEffectOnCacheFunction(
812                 (java.util.function.Function<HtmlAttributeChangeEvent, EffectOnCache> & Serializable)
813                     event -> {
814                         if (DomElement.NAME_ATTRIBUTE.equals(event.getName())
815                                 || DomElement.ID_ATTRIBUTE.equals(event.getName())) {
816                             return EffectOnCache.RESET;
817                         }
818                         return EffectOnCache.NONE;
819                     });
820 
821         return anchors;
822     }
823 
824     /**
825      * Returns the value of the JavaScript property {@code applets}.
826      * @see <a href="http://msdn.microsoft.com/en-us/library/ms537436.aspx">
827      *     MSDN documentation</a>
828      * @see <a href="https://developer.mozilla.org/En/DOM:document.applets">
829      *     Gecko DOM reference</a>
830      * @return the value of this property
831      */
832     @JsxGetter
833     public HTMLCollection getApplets() {
834         return new HTMLCollection(getDomNodeOrDie(), false);
835     }
836 
837     /**
838      * Returns this document's {@code body} element.
839      * @return this document's {@code body} element
840      */
841     @JsxGetter
842     public HTMLElement getBody() {
843         final Page page = getPage();
844         if (page instanceof HtmlPage) {
845             final HtmlPage htmlPage = (HtmlPage) page;
846             final HtmlElement body = htmlPage.getBody();
847             if (body != null) {
848                 return body.getScriptableObject();
849             }
850 
851             // strange but this returns the frameset element
852             final DomElement doc = htmlPage.getDocumentElement();
853             if (doc != null) {
854                 for (final DomNode node : doc.getChildren()) {
855                     if (node instanceof HtmlFrameSet) {
856                         return (HTMLElement) node.getScriptableObject();
857                     }
858                 }
859             }
860         }
861         return null;
862     }
863 
864     /**
865      * Sets the {@code body} element of the document.
866      * @param htmlElement the new html element
867      */
868     @JsxSetter
869     public void setBody(final HTMLElement htmlElement) {
870         if (htmlElement instanceof HTMLBodyElement || htmlElement instanceof HTMLFrameSetElement) {
871             final Page page = getPage();
872             if (page instanceof HtmlPage) {
873                 final HtmlElement body = ((HtmlPage) page).getBody();
874                 if (body != null) {
875                     body.replace(htmlElement.getDomNodeOrDie());
876                 }
877             }
878             return;
879         }
880         throw JavaScriptEngine.asJavaScriptException(
881                 getWindow(),
882                 "Failed to set the 'body' property on 'Document': "
883                         + "The new body element is of type '" +  htmlElement.getTagName() + "'. "
884                         + "It must be either a 'BODY' or 'FRAMESET' element.",
885                 org.htmlunit.javascript.host.dom.DOMException.HIERARCHY_REQUEST_ERR);
886     }
887 
888     /**
889      * JavaScript function {@code close}.
890      * <p>See <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/section-dynamic.html">
891      * http://www.whatwg.org/specs/web-apps/current-work/multipage/section-dynamic.html</a> for
892      * a good description of the semantics of open(), write(), writeln() and close().</p>
893      *
894      * @throws IOException if an IO problem occurs
895      */
896     @JsxFunction({CHROME, EDGE})
897     public void close() throws IOException {
898         // nothing to do
899     }
900 
901     /**
902      * Returns the {@code compatMode} property.
903      * @return the {@code compatMode} property
904      */
905     @JsxGetter
906     public String getCompatMode() {
907         // initialize the modes
908         getDocumentMode();
909         return compatMode_;
910     }
911 
912     /**
913      * Returns the {@code documentMode} property.
914      * @return the {@code documentMode} property
915      */
916     public int getDocumentMode() {
917         if (documentMode_ != -1) {
918             return documentMode_;
919         }
920 
921         compatMode_ = "CSS1Compat";
922 
923         if (isQuirksDocType()) {
924             compatMode_ = "BackCompat";
925         }
926 
927         final float version = getBrowserVersion().getBrowserVersionNumeric();
928         documentMode_ = (int) Math.floor(version);
929         return documentMode_;
930     }
931 
932     private boolean isQuirksDocType() {
933         final DocumentType docType = getPage().getDoctype();
934         if (docType != null) {
935             final String systemId = docType.getSystemId();
936             if (systemId != null) {
937                 if ("http://www.w3.org/TR/html4/strict.dtd".equals(systemId)) {
938                     return false;
939                 }
940 
941                 if ("http://www.w3.org/TR/html4/loose.dtd".equals(systemId)) {
942                     final String publicId = docType.getPublicId();
943                     if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicId)) {
944                         return false;
945                     }
946                 }
947 
948                 if ("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".equals(systemId)
949                     || "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd".equals(systemId)) {
950                     return false;
951                 }
952             }
953             else if (docType.getPublicId() == null) {
954                 return docType.getName() == null;
955             }
956         }
957         return true;
958     }
959 
960     /**
961      * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
962      *
963      * Called from the HTMLParser if a 'X-UA-Compatible' meta tag found.
964      * @param documentMode the mode forced by the meta tag
965      */
966     public void forceDocumentMode(final int documentMode) {
967         documentMode_ = documentMode;
968         compatMode_ = documentMode == 5 ? "BackCompat" : "CSS1Compat";
969     }
970 
971     /**
972      * Returns the first element within the document that matches the specified group of selectors.
973      * @param selectors the selectors
974      * @return null if no matches are found; otherwise, it returns the first matching element
975      */
976     @JsxFunction
977     public Node querySelector(final String selectors) {
978         try {
979             final DomNode node = getDomNodeOrDie().querySelector(selectors);
980             if (node != null) {
981                 return node.getScriptableObject();
982             }
983             return null;
984         }
985         catch (final CSSException e) {
986             throw JavaScriptEngine.asJavaScriptException(
987                     getWindow(),
988                     "An invalid or illegal selector was specified (selector: '"
989                             + selectors + "' error: " + e.getMessage() + ").",
990                     org.htmlunit.javascript.host.dom.DOMException.SYNTAX_ERR);
991         }
992     }
993 
994     /**
995      * Retrieves all element nodes from descendants of the starting element node that match any selector
996      * within the supplied selector strings.
997      * The NodeList object returned by the querySelectorAll() method must be static, not live.
998      * @param selectors the selectors
999      * @return the static node list
1000      */
1001     @JsxFunction
1002     public NodeList querySelectorAll(final String selectors) {
1003         try {
1004             return NodeList.staticNodeList(this, getDomNodeOrDie().querySelectorAll(selectors));
1005         }
1006         catch (final CSSException e) {
1007             throw JavaScriptEngine.asJavaScriptException(
1008                     getWindow(),
1009                     "An invalid or illegal selector was specified (selector: '"
1010                             + selectors + "' error: " + e.getMessage() + ").",
1011                     org.htmlunit.javascript.host.dom.DOMException.SYNTAX_ERR);
1012         }
1013     }
1014 
1015     /**
1016      * Indicates if the command is supported.
1017      * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536681.aspx">MSDN documentation</a>
1018      * @param cmd the command identifier
1019      * @return {@code true} if the command is supported
1020      */
1021     @JsxFunction
1022     public boolean queryCommandSupported(final String cmd) {
1023         return hasCommand(cmd, true);
1024     }
1025 
1026     private boolean hasCommand(final String cmd, final boolean includeBold) {
1027         if (null == cmd) {
1028             return false;
1029         }
1030 
1031         final String cmdLC = cmd.toLowerCase(Locale.ROOT);
1032         if (getBrowserVersion().isChrome() || getBrowserVersion().isEdge()) {
1033             return EXECUTE_CMDS_CHROME.contains(cmdLC) || (includeBold && "bold".equalsIgnoreCase(cmd));
1034         }
1035         return EXECUTE_CMDS_FF.contains(cmdLC);
1036     }
1037 
1038     /**
1039      * Indicates if the command can be successfully executed using <code>execCommand</code>, given
1040      * the current state of the document.
1041      * @param cmd the command identifier
1042      * @return {@code true} if the command can be successfully executed
1043      */
1044     @JsxFunction
1045     public boolean queryCommandEnabled(final String cmd) {
1046         return hasCommand(cmd, true);
1047     }
1048 
1049     /**
1050      * Executes a command.
1051      * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536419.aspx">MSDN documentation</a>
1052      * @param cmd the command identifier
1053      * @param userInterface display a user interface if the command supports one
1054      * @param value the string, number, or other value to assign (possible values depend on the command)
1055      * @return {@code true} if the command was successful, {@code false} otherwise
1056      */
1057     @JsxFunction
1058     public boolean execCommand(final String cmd, final boolean userInterface, final Object value) {
1059         if (!hasCommand(cmd, false)) {
1060             return false;
1061         }
1062         if (LOG.isWarnEnabled()) {
1063             LOG.warn("Nothing done for execCommand(" + cmd + ", ...) (feature not implemented)");
1064         }
1065         return true;
1066     }
1067 
1068     /**
1069      * Returns the value of the {@code URL} property.
1070      * @return the value of the {@code URL} property
1071      */
1072     @JsxGetter(propertyName = "URL")
1073     public String getURL_js() {
1074         return getPage().getUrl().toExternalForm();
1075     }
1076 
1077     /**
1078      * Returns the value of the {@code documentURI} property.
1079      * @return the value of the {@code documentURI} property
1080      */
1081     @JsxGetter
1082     public String getDocumentURI() {
1083         return getURL_js();
1084     }
1085 
1086     /**
1087      * Returns the {@code cookie} property.
1088      * @return the {@code cookie} property
1089      */
1090     @JsxGetter
1091     public String getCookie() {
1092         final SgmlPage sgmlPage = getPage();
1093 
1094         final StringBuilder builder = new StringBuilder();
1095         final Set<Cookie> cookies = sgmlPage.getWebClient().getCookies(sgmlPage.getUrl());
1096         for (final Cookie cookie : cookies) {
1097             if (cookie.isHttpOnly()) {
1098                 continue;
1099             }
1100             if (builder.length() != 0) {
1101                 builder.append("; ");
1102             }
1103             if (!HtmlUnitBrowserCompatCookieSpec.EMPTY_COOKIE_NAME.equals(cookie.getName())) {
1104                 builder.append(cookie.getName()).append('=');
1105             }
1106             builder.append(cookie.getValue());
1107         }
1108 
1109         return builder.toString();
1110     }
1111 
1112     /**
1113      * Adds a cookie, as long as cookies are enabled.
1114      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533693.aspx">MSDN documentation</a>
1115      * @param newCookie in the format "name=value[;expires=date][;domain=domainname][;path=path][;secure]
1116      */
1117     @JsxSetter
1118     public void setCookie(final String newCookie) {
1119         final SgmlPage sgmlPage = getPage();
1120         final WebClient client = sgmlPage.getWebClient();
1121 
1122         if (StringUtils.isBlank(newCookie)
1123                 && client.getBrowserVersion().hasFeature(HTMLDOCUMENT_COOKIES_IGNORE_BLANK)) {
1124             return;
1125         }
1126         client.addCookie(newCookie, sgmlPage.getUrl(), this);
1127     }
1128 
1129     /**
1130      * Implementation of the {@link org.w3c.dom.events.DocumentEvent} interface's
1131      * {@link org.w3c.dom.events.DocumentEvent#createEvent(String)} method. The method creates an
1132      * uninitialized event of the specified type.
1133      *
1134      * @see <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-DocumentEvent">DocumentEvent</a>
1135      * @param eventType the event type to create
1136      * @return an event object for the specified type
1137      * @throws DOMException if the event type is not supported (will have a type of
1138      *         DOMException.NOT_SUPPORTED_ERR)
1139      */
1140     @JsxFunction
1141     public Event createEvent(final String eventType) throws DOMException {
1142         Class<? extends Event> clazz = SUPPORTED_DOM2_EVENT_TYPE_MAP.get(eventType);
1143         if (clazz == null) {
1144             clazz = SUPPORTED_DOM3_EVENT_TYPE_MAP.get(eventType);
1145             if (CloseEvent.class == clazz
1146                     && getBrowserVersion().hasFeature(EVENT_ONCLOSE_DOCUMENT_CREATE_NOT_SUPPORTED)) {
1147                 clazz = null;
1148             }
1149             else if (TextEvent.class == clazz
1150                     && !getBrowserVersion().hasFeature(EVENT_TYPE_TEXTEVENT)) {
1151                 clazz = CompositionEvent.class;
1152             }
1153         }
1154 
1155         if (MutationEvent.class == clazz
1156                 && !getBrowserVersion().hasFeature(EVENT_TYPE_MUTATIONEVENT)) {
1157             clazz = null;
1158         }
1159         else if (clazz == null
1160                 && ("Events".equals(eventType)
1161                     || "HashChangeEvent".equals(eventType)
1162                     || "BeforeUnloadEvent".equals(eventType)
1163                     || "PopStateEvent".equals(eventType)
1164                     || "FocusEvent".equals(eventType)
1165                     || "WheelEvent".equals(eventType)
1166                             && getBrowserVersion().hasFeature(EVENT_TYPE_WHEELEVENT)
1167                     || "AnimationEvent".equals(eventType))) {
1168             clazz = SUPPORTED_VENDOR_EVENT_TYPE_MAP.get(eventType);
1169 
1170             if (PopStateEvent.class == clazz
1171                     && getBrowserVersion().hasFeature(EVENT_ONPOPSTATE_DOCUMENT_CREATE_NOT_SUPPORTED)) {
1172                 clazz = null;
1173             }
1174             if (AnimationEvent.class == clazz
1175                     && getBrowserVersion().hasFeature(EVENT_ONANIMATION_DOCUMENT_CREATE_NOT_SUPPORTED)) {
1176                 clazz = null;
1177             }
1178         }
1179 
1180         if (clazz == null) {
1181             throw JavaScriptEngine.asJavaScriptException(
1182                     this,
1183                     "Event Type '" + eventType + "' is not supported.",
1184                     org.htmlunit.javascript.host.dom.DOMException.NOT_SUPPORTED_ERR);
1185         }
1186 
1187         try {
1188             final Event event = clazz.getDeclaredConstructor().newInstance();
1189             event.setParentScope(getWindow());
1190             event.setPrototype(getPrototype(clazz));
1191             event.eventCreated();
1192             return event;
1193         }
1194         catch (final InstantiationException | IllegalAccessException
1195                 | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
1196             throw JavaScriptEngine.reportRuntimeError("Failed to instantiate event: class ='" + clazz.getName()
1197                             + "' for event type of '" + eventType + "': " + e.getMessage());
1198         }
1199     }
1200 
1201     /**
1202      * Returns a new NodeIterator object.
1203      *
1204      * @param root The root node at which to begin the NodeIterator's traversal.
1205      * @param whatToShow an optional long representing a bitmask created by combining
1206      *        the constant properties of {@link NodeFilter}
1207      * @param filter an object implementing the {@link NodeFilter} interface
1208      * @return a new NodeIterator object
1209      */
1210     @JsxFunction
1211     public NodeIterator createNodeIterator(final Node root, final int whatToShow, final Scriptable filter) {
1212         final org.w3c.dom.traversal.NodeFilter filterWrapper = createFilterWrapper(filter, false);
1213         final NodeIterator iterator = new NodeIterator(root, whatToShow, filterWrapper);
1214         iterator.setParentScope(getParentScope());
1215         iterator.setPrototype(getPrototype(iterator.getClass()));
1216         return iterator;
1217     }
1218 
1219     private static org.w3c.dom.traversal.NodeFilter createFilterWrapper(final Scriptable filter,
1220             final boolean filterFunctionOnly) {
1221         org.w3c.dom.traversal.NodeFilter filterWrapper = null;
1222         if (filter != null) {
1223             filterWrapper = n -> {
1224                 final Object[] args = {((DomNode) n).getScriptableObject()};
1225                 final Object response;
1226                 if (filter instanceof Callable) {
1227                     response = ((Callable) filter).call(Context.getCurrentContext(), filter, filter, args);
1228                 }
1229                 else {
1230                     if (filterFunctionOnly) {
1231                         throw JavaScriptEngine.reportRuntimeError("only a function is allowed as filter");
1232                     }
1233                     response = ScriptableObject.callMethod(filter, "acceptNode", args);
1234                 }
1235                 return (short) JavaScriptEngine.toNumber(response);
1236             };
1237         }
1238         return filterWrapper;
1239     }
1240 
1241     /**
1242      * Creates and returns a new TreeWalker. The following JavaScript parameters are passed into this method:
1243      * <ul>
1244      *   <li>JavaScript param 1: The root node of the TreeWalker. Must not be {@code null}.</li>
1245      *   <li>JavaScript param 2: Flag specifying which types of nodes appear in the logical view of the TreeWalker.
1246      *       See {@link NodeFilter} for the set of possible Show_ values.</li>
1247      *   <li>JavaScript param 3: The {@link NodeFilter} to be used with this TreeWalker, or {@code null}
1248      *       to indicate no filter.</li>
1249      *   <li>JavaScript param 4: If {@code false}, the contents of EntityReference nodes are not present
1250      *       in the logical view.</li>
1251      * </ul>
1252      *
1253      * @see <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html">DOM-Level-2-Traversal-Range</a>
1254      * @param root the node which will serve as the root for the TreeWalker
1255      * @param whatToShow specifies which node types may appear in the logical view of the tree presented
1256      * @param filter the NodeFilter to be used with this TreeWalker, or null to indicate no filter
1257      * @param expandEntityReferences If false,
1258      *        the contents of EntityReference nodes are not presented in the logical view
1259      * @throws DOMException on attempt to create a TreeWalker with a root that is {@code null}
1260      * @return a new TreeWalker
1261      */
1262     @JsxFunction
1263     public TreeWalker createTreeWalker(final Node root, final double whatToShow, final Scriptable filter,
1264             boolean expandEntityReferences) throws DOMException {
1265 
1266         // seems that Rhino doesn't like long as parameter type
1267         // this strange conversation preserves NodeFilter.SHOW_ALL
1268         final int whatToShowI = (int) Double.valueOf(whatToShow).longValue();
1269 
1270         expandEntityReferences = false;
1271 
1272         final org.w3c.dom.traversal.NodeFilter filterWrapper = createFilterWrapper(filter, false);
1273         final TreeWalker t = new TreeWalker(root, whatToShowI, filterWrapper, expandEntityReferences);
1274         t.setParentScope(getWindow(this));
1275         t.setPrototype(staticGetPrototype(getWindow(this), TreeWalker.class));
1276         return t;
1277     }
1278 
1279     @SuppressWarnings("unchecked")
1280     private static Scriptable staticGetPrototype(final Window window,
1281             final Class<? extends HtmlUnitScriptable> javaScriptClass) {
1282         final Scriptable prototype = window.getPrototype(javaScriptClass);
1283         if (prototype == null && javaScriptClass != HtmlUnitScriptable.class) {
1284             return staticGetPrototype(window, (Class<? extends HtmlUnitScriptable>) javaScriptClass.getSuperclass());
1285         }
1286         return prototype;
1287     }
1288 
1289     /**
1290      * Creates and returns a new range.
1291      * @return a new range
1292      * @see <a href="http://www.xulplanet.com/references/objref/HTMLDocument.html#method_createRange">XUL Planet</a>
1293      */
1294     @JsxFunction
1295     public Range createRange() {
1296         final Range range = new Range(this);
1297         range.setParentScope(getWindow());
1298         range.setPrototype(getPrototype(Range.class));
1299         return range;
1300     }
1301 
1302     /**
1303      * Returns the domain name of the server that served the document, or {@code null} if the server
1304      * cannot be identified by a domain name.
1305      * @return the domain name of the server that served the document
1306      * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-2250147">
1307      *     W3C documentation</a>
1308      */
1309     @JsxGetter
1310     public String getDomain() {
1311         if (domain_ == null && getPage().getWebResponse() != null) {
1312             URL url = getPage().getUrl();
1313             if (url == UrlUtils.URL_ABOUT_BLANK) {
1314                 final WebWindow w = getWindow().getWebWindow();
1315                 if (w instanceof FrameWindow) {
1316                     url = ((FrameWindow) w).getEnclosingPage().getUrl();
1317                 }
1318                 else {
1319                     return null;
1320                 }
1321             }
1322             domain_ = url.getHost().toLowerCase(Locale.ROOT);
1323         }
1324 
1325         return domain_;
1326     }
1327 
1328     /**
1329      * Sets the domain of this document.
1330      *
1331      * <p>Domains can only be set to suffixes of the existing domain
1332      * with the exception of setting the domain to itself.</p>
1333      * <p>
1334      * The domain will be set according to the following rules:
1335      * <ol>
1336      * <li>If the newDomain.equalsIgnoreCase(currentDomain) the method returns with no error.</li>
1337      * <li>If the browser version is netscape, the newDomain is downshifted.</li>
1338      * <li>The change will take place if and only if the suffixes of the
1339      *       current domain and the new domain match AND there are at least
1340      *       two domain qualifiers e.g. the following transformations are legal
1341      *       d1.d2.d3.gargoylesoftware.com may be transformed to itself or:
1342      *          d2.d3.gargoylesoftware.com
1343      *             d3.gargoylesoftware.com
1344      *                gargoylesoftware.com
1345      * <p>
1346      *        transformation to:        com
1347      *        will fail
1348      * </li>
1349      * </ol>
1350      * <p>
1351      * TODO This code could be modified to understand country domain suffixes.
1352      * The domain www.bbc.co.uk should be trimmable only down to bbc.co.uk
1353      * trimming to co.uk should not be possible.
1354      * @param newDomain the new domain to set
1355      */
1356     @JsxSetter
1357     public void setDomain(String newDomain) {
1358         newDomain = newDomain.toLowerCase(Locale.ROOT);
1359 
1360         final String currentDomain = getDomain();
1361         if (currentDomain.equalsIgnoreCase(newDomain)) {
1362             return;
1363         }
1364 
1365         if (newDomain.indexOf('.') == -1) {
1366             throw JavaScriptEngine.reportRuntimeError("Illegal domain value, cannot set domain from: \""
1367                     + currentDomain + "\" to: \"" + newDomain + "\" (new domain has to contain a dot).");
1368         }
1369 
1370         if (currentDomain.indexOf('.') > -1
1371                 && !currentDomain.toLowerCase(Locale.ROOT).endsWith("." + newDomain.toLowerCase(Locale.ROOT))) {
1372             throw JavaScriptEngine.reportRuntimeError("Illegal domain value, cannot set domain from: \""
1373                     + currentDomain + "\" to: \"" + newDomain + "\"");
1374         }
1375 
1376         domain_ = newDomain;
1377     }
1378 
1379     /**
1380      * Sets the {@code onclick} event handler for this element.
1381      * @param handler the {@code onclick} event handler for this element
1382      */
1383     @JsxSetter
1384     public void setOnclick(final Object handler) {
1385         setEventHandler(MouseEvent.TYPE_CLICK, handler);
1386     }
1387 
1388     /**
1389      * Returns the {@code onclick} event handler for this element.
1390      * @return the {@code onclick} event handler for this element
1391      */
1392     @JsxGetter
1393     public Function getOnclick() {
1394         return getEventHandler(MouseEvent.TYPE_CLICK);
1395     }
1396 
1397     /**
1398      * Sets the {@code ondblclick} event handler for this element.
1399      * @param handler the {@code ondblclick} event handler for this element
1400      */
1401     @JsxSetter
1402     public void setOndblclick(final Object handler) {
1403         setEventHandler(MouseEvent.TYPE_DBL_CLICK, handler);
1404     }
1405 
1406     /**
1407      * Returns the {@code ondblclick} event handler for this element.
1408      * @return the {@code ondblclick} event handler for this element
1409      */
1410     @JsxGetter
1411     public Function getOndblclick() {
1412         return getEventHandler(MouseEvent.TYPE_DBL_CLICK);
1413     }
1414 
1415     /**
1416      * Sets the {@code onblur} event handler for this element.
1417      * @param handler the {@code onblur} event handler for this element
1418      */
1419     @JsxSetter
1420     public void setOnblur(final Object handler) {
1421         setEventHandler(Event.TYPE_BLUR, handler);
1422     }
1423 
1424     /**
1425      * Returns the {@code onblur} event handler for this element.
1426      * @return the {@code onblur} event handler for this element
1427      */
1428     @JsxGetter
1429     public Function getOnblur() {
1430         return getEventHandler(Event.TYPE_BLUR);
1431     }
1432 
1433     /**
1434      * Sets the {@code onfocus} event handler for this element.
1435      * @param handler the {@code onfocus} event handler for this element
1436      */
1437     @JsxSetter
1438     public void setOnfocus(final Object handler) {
1439         setEventHandler(Event.TYPE_FOCUS, handler);
1440     }
1441 
1442     /**
1443      * Returns the {@code onfocus} event handler for this element.
1444      * @return the {@code onfocus} event handler for this element
1445      */
1446     @JsxGetter
1447     public Function getOnfocus() {
1448         return getEventHandler(Event.TYPE_FOCUS);
1449     }
1450 
1451     /**
1452      * Sets the {@code onkeydown} event handler for this element.
1453      * @param handler the {@code onkeydown} event handler for this element
1454      */
1455     @JsxSetter
1456     public void setOnkeydown(final Object handler) {
1457         setEventHandler(Event.TYPE_KEY_DOWN, handler);
1458     }
1459 
1460     /**
1461      * Returns the {@code onkeydown} event handler for this element.
1462      * @return the {@code onkeydown} event handler for this element
1463      */
1464     @JsxGetter
1465     public Function getOnkeydown() {
1466         return getEventHandler(Event.TYPE_KEY_DOWN);
1467     }
1468 
1469     /**
1470      * Sets the {@code onkeypress} event handler for this element.
1471      * @param handler the {@code onkeypress} event handler for this element
1472      */
1473     @JsxSetter
1474     public void setOnkeypress(final Object handler) {
1475         setEventHandler(Event.TYPE_KEY_PRESS, handler);
1476     }
1477 
1478     /**
1479      * Returns the {@code onkeypress} event handler for this element.
1480      * @return the {@code onkeypress} event handler for this element
1481      */
1482     @JsxGetter
1483     public Function getOnkeypress() {
1484         return getEventHandler(Event.TYPE_KEY_PRESS);
1485     }
1486 
1487     /**
1488      * Sets the {@code onkeyup} event handler for this element.
1489      * @param handler the {@code onkeyup} event handler for this element
1490      */
1491     @JsxSetter
1492     public void setOnkeyup(final Object handler) {
1493         setEventHandler(Event.TYPE_KEY_UP, handler);
1494     }
1495 
1496     /**
1497      * Returns the {@code onkeyup} event handler for this element.
1498      * @return the {@code onkeyup} event handler for this element
1499      */
1500     @JsxGetter
1501     public Function getOnkeyup() {
1502         return getEventHandler(Event.TYPE_KEY_UP);
1503     }
1504 
1505     /**
1506      * Sets the {@code onmousedown} event handler for this element.
1507      * @param handler the {@code onmousedown} event handler for this element
1508      */
1509     @JsxSetter
1510     public void setOnmousedown(final Object handler) {
1511         setEventHandler(MouseEvent.TYPE_MOUSE_DOWN, handler);
1512     }
1513 
1514     /**
1515      * Returns the {@code onmousedown} event handler for this element.
1516      * @return the {@code onmousedown} event handler for this element
1517      */
1518     @JsxGetter
1519     public Function getOnmousedown() {
1520         return getEventHandler(MouseEvent.TYPE_MOUSE_DOWN);
1521     }
1522 
1523     /**
1524      * Sets the {@code onmousemove} event handler for this element.
1525      * @param handler the {@code onmousemove} event handler for this element
1526      */
1527     @JsxSetter
1528     public void setOnmousemove(final Object handler) {
1529         setEventHandler(MouseEvent.TYPE_MOUSE_MOVE, handler);
1530     }
1531 
1532     /**
1533      * Returns the {@code onmousemove} event handler for this element.
1534      * @return the {@code onmousemove} event handler for this element
1535      */
1536     @JsxGetter
1537     public Function getOnmousemove() {
1538         return getEventHandler(MouseEvent.TYPE_MOUSE_MOVE);
1539     }
1540 
1541     /**
1542      * Sets the {@code onmouseout} event handler for this element.
1543      * @param handler the {@code onmouseout} event handler for this element
1544      */
1545     @JsxSetter
1546     public void setOnmouseout(final Object handler) {
1547         setEventHandler(MouseEvent.TYPE_MOUSE_OUT, handler);
1548     }
1549 
1550     /**
1551      * Returns the {@code onmouseout} event handler for this element.
1552      * @return the {@code onmouseout} event handler for this element
1553      */
1554     @JsxGetter
1555     public Function getOnmouseout() {
1556         return getEventHandler(MouseEvent.TYPE_MOUSE_OUT);
1557     }
1558 
1559     /**
1560      * Sets the {@code onmouseover} event handler for this element.
1561      * @param handler the {@code onmouseover} event handler for this element
1562      */
1563     @JsxSetter
1564     public void setOnmouseover(final Object handler) {
1565         setEventHandler(MouseEvent.TYPE_MOUSE_OVER, handler);
1566     }
1567 
1568     /**
1569      * Returns the {@code onmouseover} event handler for this element.
1570      * @return the {@code onmouseover} event handler for this element
1571      */
1572     @JsxGetter
1573     public Function getOnmouseover() {
1574         return getEventHandler(MouseEvent.TYPE_MOUSE_OVER);
1575     }
1576 
1577     /**
1578      * Sets the {@code onmouseup} event handler for this element.
1579      * @param handler the {@code onmouseup} event handler for this element
1580      */
1581     @JsxSetter
1582     public void setOnmouseup(final Object handler) {
1583         setEventHandler(MouseEvent.TYPE_MOUSE_UP, handler);
1584     }
1585 
1586     /**
1587      * Returns the {@code onmouseup} event handler for this element.
1588      * @return the {@code onmouseup} event handler for this element
1589      */
1590     @JsxGetter
1591     public Function getOnmouseup() {
1592         return getEventHandler(MouseEvent.TYPE_MOUSE_UP);
1593     }
1594 
1595     /**
1596      * Sets the {@code oncontextmenu} event handler for this element.
1597      * @param handler the {@code oncontextmenu} event handler for this element
1598      */
1599     @JsxSetter
1600     public void setOncontextmenu(final Object handler) {
1601         setEventHandler(MouseEvent.TYPE_CONTEXT_MENU, handler);
1602     }
1603 
1604     /**
1605      * Returns the {@code oncontextmenu} event handler for this element.
1606      * @return the {@code oncontextmenu} event handler for this element
1607      */
1608     @JsxGetter
1609     public Function getOncontextmenu() {
1610         return getEventHandler(MouseEvent.TYPE_CONTEXT_MENU);
1611     }
1612 
1613     /**
1614      * Sets the {@code onresize} event handler for this element.
1615      * @param handler the {@code onresize} event handler for this element
1616      */
1617     @JsxSetter
1618     public void setOnresize(final Object handler) {
1619         setEventHandler(Event.TYPE_RESIZE, handler);
1620     }
1621 
1622     /**
1623      * Returns the {@code onresize} event handler for this element.
1624      * @return the {@code onresize} event handler for this element
1625      */
1626     @JsxGetter
1627     public Function getOnresize() {
1628         return getEventHandler(Event.TYPE_RESIZE);
1629     }
1630 
1631     /**
1632      * Sets the {@code onerror} event handler for this element.
1633      * @param handler the {@code onerror} event handler for this element
1634      */
1635     @JsxSetter
1636     public void setOnerror(final Object handler) {
1637         setEventHandler(Event.TYPE_ERROR, handler);
1638     }
1639 
1640     /**
1641      * Returns the {@code onerror} event handler for this element.
1642      * @return the {@code onerror} event handler for this element
1643      */
1644     @JsxGetter
1645     public Function getOnerror() {
1646         return getEventHandler(Event.TYPE_ERROR);
1647     }
1648 
1649     /**
1650      * Returns the {@code oninput} event handler for this element.
1651      * @return the {@code oninput} event handler for this element
1652      */
1653     @JsxGetter
1654     public Function getOninput() {
1655         return getEventHandler(Event.TYPE_INPUT);
1656     }
1657 
1658     /**
1659      * Sets the {@code oninput} event handler for this element.
1660      * @param oninput the {@code oninput} event handler for this element
1661      */
1662     @JsxSetter
1663     public void setOninput(final Object oninput) {
1664         setEventHandler(Event.TYPE_INPUT, oninput);
1665     }
1666 
1667     /**
1668      * Returns the {@code hidden} property.
1669      * @return the {@code hidden} property
1670      */
1671     @JsxGetter
1672     public boolean getHidden() {
1673         return false;
1674     }
1675 
1676     /**
1677      * {@inheritDoc}
1678      */
1679     @Override
1680     @JsxGetter
1681     public int getChildElementCount() {
1682         int counter = 0;
1683         if (getPage().getDocumentElement() != null) {
1684             counter++;
1685         }
1686         return counter;
1687     }
1688 
1689     /**
1690      * Returns the element for the specified x coordinate and the specified y coordinate.
1691      * The current implementation always returns null element.
1692      *
1693      * @param x the x offset, in pixels
1694      * @param y the y offset, in pixels
1695      * @return the element for the specified x coordinate and the specified y coordinate
1696      */
1697     @JsxFunction
1698     public HtmlUnitScriptable elementFromPoint(final int x, final int y) {
1699         return null;
1700     }
1701 
1702     /**
1703      * Returns the value of the {@code forms} property.
1704      * @return the value of the {@code forms} property
1705      */
1706     @JsxGetter
1707     public HTMLCollection getForms() {
1708         final HTMLCollection forms = new HTMLCollection(getDomNodeOrDie(), false) {
1709             @Override
1710             public Object call(final Context cx, final Scriptable scope,
1711                     final Scriptable thisObj, final Object[] args) {
1712                 throw JavaScriptEngine.typeError("document.forms is not a function");
1713             }
1714         };
1715 
1716         forms.setIsMatchingPredicate(
1717                 (Predicate<DomNode> & Serializable)
1718                 node -> node instanceof HtmlForm && node.getPrefix() == null);
1719         return forms;
1720     }
1721 
1722     /**
1723      * Returns the value of the {@code embeds} property.
1724      * @return the value of the {@code embeds} property
1725      */
1726     @JsxGetter
1727     public HTMLCollection getEmbeds() {
1728         final HTMLCollection embeds = new HTMLCollection(getDomNodeOrDie(), false) {
1729             @Override
1730             public Object call(final Context cx, final Scriptable scope,
1731                     final Scriptable thisObj, final Object[] args) {
1732                 throw JavaScriptEngine.typeError("document.embeds is not a function");
1733             }
1734         };
1735 
1736         embeds.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof HtmlEmbed);
1737         return embeds;
1738     }
1739 
1740     /**
1741      * Returns the value of the {@code embeds} property.
1742      * @return the value of the {@code embeds} property
1743      */
1744     @JsxGetter
1745     public HTMLCollection getImages() {
1746         final HTMLCollection images = new HTMLCollection(getDomNodeOrDie(), false) {
1747             @Override
1748             public Object call(final Context cx, final Scriptable scope,
1749                     final Scriptable thisObj, final Object[] args) {
1750                 throw JavaScriptEngine.typeError("document.images is not a function");
1751             }
1752         };
1753 
1754         images.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof HtmlImage);
1755         return images;
1756     }
1757 
1758     /**
1759      * Returns the value of the {@code scripts} property.
1760      * @return the value of the {@code scripts} property
1761      */
1762     @JsxGetter
1763     public HTMLCollection getScripts() {
1764         final HTMLCollection scripts = new HTMLCollection(getDomNodeOrDie(), false) {
1765             @Override
1766             public Object call(final Context cx, final Scriptable scope,
1767                     final Scriptable thisObj, final Object[] args) {
1768                 throw JavaScriptEngine.typeError("document.scripts is not a function");
1769             }
1770         };
1771 
1772         scripts.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> node instanceof HtmlScript);
1773         return scripts;
1774     }
1775 
1776     /**
1777      * Retrieves a collection of stylesheet objects representing the style sheets that correspond
1778      * to each instance of a Link or
1779      * {@link org.htmlunit.javascript.host.css.CSSStyleDeclaration} object in the document.
1780      *
1781      * @return styleSheet collection
1782      */
1783     @JsxGetter
1784     public StyleSheetList getStyleSheets() {
1785         if (styleSheetList_ == null) {
1786             styleSheetList_ = new StyleSheetList(this);
1787         }
1788         return styleSheetList_;
1789     }
1790 
1791     /**
1792      * Returns the value of the {@code plugins} property.
1793      * @return the value of the {@code plugins} property
1794      */
1795     @JsxGetter
1796     public HTMLCollection getPlugins() {
1797         return getEmbeds();
1798     }
1799 
1800     /**
1801      * Returns the value of the JavaScript property {@code links}. Refer also to the
1802      * <a href="http://msdn.microsoft.com/en-us/library/ms537465.aspx">MSDN documentation</a>.
1803      * @return the value of this property
1804      */
1805     @JsxGetter
1806     public HTMLCollection getLinks() {
1807         final HTMLCollection links = new HTMLCollection(getDomNodeOrDie(), true);
1808 
1809         links.setEffectOnCacheFunction(
1810                 (java.util.function.Function<HtmlAttributeChangeEvent, EffectOnCache> & Serializable)
1811                 event -> {
1812                     final HtmlElement node = event.getHtmlElement();
1813                     if ((node instanceof HtmlAnchor || node instanceof HtmlArea) && "href".equals(event.getName())) {
1814                         return EffectOnCache.RESET;
1815                     }
1816                     return EffectOnCache.NONE;
1817                 });
1818 
1819         links.setIsMatchingPredicate(
1820                 (Predicate<DomNode> & Serializable)
1821                 node ->
1822                     (node instanceof HtmlAnchor || node instanceof HtmlArea)
1823                     && ((HtmlElement) node).hasAttribute("href"));
1824 
1825         return links;
1826     }
1827 
1828     /**
1829      * Returns all the descendant elements with the specified class name.
1830      * @param className the name to search for
1831      * @return all the descendant elements with the specified class name
1832      * @see <a href="https://developer.mozilla.org/en/DOM/document.getElementsByClassName">Mozilla doc</a>
1833      */
1834     @JsxFunction
1835     public HTMLCollection getElementsByClassName(final String className) {
1836         return null;
1837     }
1838 
1839     /**
1840      * Returns all HTML elements that have a {@code name} attribute with the specified value.
1841      * <p>
1842      * Refer to <a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-71555259">
1843      * The DOM spec</a> for details.
1844      *
1845      * @param elementName - value of the {@code name} attribute to look for
1846      * @return all HTML elements that have a {@code name} attribute with the specified value
1847      */
1848     @JsxFunction
1849     public NodeList getElementsByName(final String elementName) {
1850         return null;
1851     }
1852 
1853     /**
1854      * Returns {@code false} if the active element in the document has no focus;
1855      * {@code true} if the active element in the document has focus.
1856      * @return whether the active element in the document has focus or not
1857      */
1858     @JsxFunction
1859     public boolean hasFocus() {
1860         return false;
1861     }
1862 
1863     /**
1864      * Returns this document's title.
1865      * @return this document's title
1866      */
1867     @JsxGetter
1868     public String getTitle() {
1869         return "";
1870     }
1871 
1872     /**
1873      * Sets this document's title.
1874      * @param title the new title
1875      */
1876     @JsxSetter
1877     public void setTitle(final String title) {
1878         // nothing to do
1879     }
1880 
1881     /**
1882      * {@inheritDoc}
1883      */
1884     @Override
1885     @JsxGetter
1886     public HTMLCollection getChildren() {
1887         return super.getChildren();
1888     }
1889 
1890     /**
1891      * Returns the {@code contentType} property.
1892      * @return the {@code contentType} property
1893      */
1894     @JsxGetter
1895     public String getContentType() {
1896         return getPage().getContentType();
1897     }
1898 
1899     /**
1900      * Returns the current selection.
1901      * @return the current selection
1902      */
1903     @JsxFunction
1904     public Selection getSelection() {
1905         return null;
1906     }
1907 
1908     /**
1909      * Returns this document's {@code head} element.
1910      * @return this document's {@code head} element
1911      */
1912     @JsxGetter
1913     public Object getHead() {
1914         return null;
1915     }
1916 
1917     /**
1918      * Returns a string representing the encoding under which the document was parsed.
1919      * @return a string representing the encoding under which the document was parsed
1920      */
1921     @JsxGetter
1922     public String getInputEncoding() {
1923         return getPage().getCharset().name();
1924     }
1925 
1926     /**
1927      * Returns the last modification date of the document.
1928      * @see <a href="https://developer.mozilla.org/en/DOM/document.lastModified">Mozilla documentation</a>
1929      * @return the date as string
1930      */
1931     @JsxGetter
1932     public String getLastModified() {
1933         if (lastModified_ == null) {
1934             final WebResponse webResponse = getPage().getWebResponse();
1935             final Date lastModified;
1936             if (webResponse != null) {
1937                 String stringDate = webResponse.getResponseHeaderValue("Last-Modified");
1938                 if (stringDate == null) {
1939                     stringDate = webResponse.getResponseHeaderValue("Date");
1940                 }
1941                 lastModified = parseDateOrNow(stringDate);
1942             }
1943             else {
1944                 lastModified = new Date();
1945             }
1946 
1947             final ZoneId zoneid = Context.getCurrentContext().getTimeZone().toZoneId();
1948             lastModified_ = LAST_MODIFIED_DATE_FORMATTER.format(lastModified.toInstant().atZone(zoneid));
1949         }
1950         return lastModified_;
1951     }
1952 
1953     private static Date parseDateOrNow(final String stringDate) {
1954         final Date date = HttpUtils.parseDate(stringDate);
1955         if (date == null) {
1956             return new Date();
1957         }
1958         return date;
1959     }
1960 
1961     /**
1962      * Mock for the moment.
1963      */
1964     @JsxFunction({FF, FF_ESR})
1965     public void releaseCapture() {
1966         // nothing to do
1967     }
1968 
1969     /**
1970      * Returns the ready state of the document.
1971      * @return the ready state of the document
1972      *
1973      * @see DomNode#READY_STATE_UNINITIALIZED
1974      * @see DomNode#READY_STATE_LOADING
1975      * @see DomNode#READY_STATE_LOADED
1976      * @see DomNode#READY_STATE_INTERACTIVE
1977      * @see DomNode#READY_STATE_COMPLETE
1978      */
1979     @JsxGetter
1980     public String getReadyState() {
1981         return getDomNodeOrDie().getReadyState();
1982     }
1983 
1984     /**
1985      * Does nothing special anymore.
1986      *
1987      * @param type the type of events to capture
1988      * @see Window#captureEvents(String)
1989      */
1990     @JsxFunction
1991     public void captureEvents(final String type) {
1992         // Empty.
1993     }
1994 
1995     /**
1996      * Does nothing special anymore.
1997      *
1998      * @param type the type of events to capture
1999      * @see Window#releaseEvents(String)
2000      */
2001     @JsxFunction
2002     public void releaseEvents(final String type) {
2003         // Empty.
2004     }
2005 
2006     /**
2007      * Returns the value of the {@code alinkColor} property.
2008      * @return the value of the {@code alinkColor} property
2009      */
2010     @JsxGetter
2011     public String getAlinkColor() {
2012         final HTMLElement body = getBody();
2013         if (body instanceof HTMLBodyElement) {
2014             return ((HTMLBodyElement) body).getALink();
2015         }
2016         return null;
2017     }
2018 
2019     /**
2020      * Sets the value of the {@code alinkColor} property.
2021      * @param color the value of the {@code alinkColor} property
2022      */
2023     @JsxSetter
2024     public void setAlinkColor(final String color) {
2025         final HTMLElement body = getBody();
2026         if (body instanceof HTMLBodyElement) {
2027             ((HTMLBodyElement) body).setALink(color);
2028         }
2029     }
2030 
2031     /**
2032      * Returns the value of the {@code bgColor} property.
2033      * @return the value of the {@code bgColor} property
2034      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
2035      */
2036     @JsxGetter
2037     public String getBgColor() {
2038         final HTMLElement body = getBody();
2039         if (body instanceof HTMLBodyElement) {
2040             return ((HTMLBodyElement) body).getBgColor();
2041         }
2042         return null;
2043     }
2044 
2045     /**
2046      * Sets the value of the {@code bgColor} property.
2047      * @param color the value of the {@code bgColor} property
2048      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
2049      */
2050     @JsxSetter
2051     public void setBgColor(final String color) {
2052         final HTMLElement body = getBody();
2053         if (body instanceof HTMLBodyElement) {
2054             ((HTMLBodyElement) body).setBgColor(color);
2055         }
2056     }
2057 
2058     /**
2059      * Returns the value of the {@code fgColor} property.
2060      * @return the value of the {@code fgColor} property
2061      */
2062     @JsxGetter
2063     public String getFgColor() {
2064         final HTMLElement body = getBody();
2065         if (body instanceof HTMLBodyElement) {
2066             return ((HTMLBodyElement) body).getText();
2067         }
2068         return null;
2069     }
2070 
2071     /**
2072      * Sets the value of the {@code fgColor} property.
2073      * @param color the value of the {@code fgColor} property
2074      */
2075     @JsxSetter
2076     public void setFgColor(final String color) {
2077         final HTMLElement body = getBody();
2078         if (body instanceof HTMLBodyElement) {
2079             ((HTMLBodyElement) body).setText(color);
2080         }
2081     }
2082 
2083     /**
2084      * Returns the value of the {@code linkColor} property.
2085      * @return the value of the {@code linkColor} property
2086      */
2087     @JsxGetter
2088     public String getLinkColor() {
2089         final HTMLElement body = getBody();
2090         if (body instanceof HTMLBodyElement) {
2091             return ((HTMLBodyElement) body).getLink();
2092         }
2093         return null;
2094     }
2095 
2096     /**
2097      * Sets the value of the {@code linkColor} property.
2098      * @param color the value of the {@code linkColor} property
2099      */
2100     @JsxSetter
2101     public void setLinkColor(final String color) {
2102         final HTMLElement body = getBody();
2103         if (body instanceof HTMLBodyElement) {
2104             ((HTMLBodyElement) body).setLink(color);
2105         }
2106     }
2107 
2108     /**
2109      * Returns the value of the {@code vlinkColor} property.
2110      * @return the value of the {@code vlinkColor} property
2111      */
2112     @JsxGetter
2113     public String getVlinkColor() {
2114         final HTMLElement body = getBody();
2115         if (body instanceof HTMLBodyElement) {
2116             return ((HTMLBodyElement) body).getVLink();
2117         }
2118         return null;
2119     }
2120 
2121     /**
2122      * Sets the value of the {@code vlinkColor} property.
2123      * @param color the value of the {@code vlinkColor} property
2124      */
2125     @JsxSetter
2126     public void setVlinkColor(final String color) {
2127         final HTMLElement body = getBody();
2128         if (body instanceof HTMLBodyElement) {
2129             ((HTMLBodyElement) body).setVLink(color);
2130         }
2131     }
2132 
2133     /**
2134      * {@inheritDoc}
2135      */
2136     @Override
2137     @JsxGetter
2138     public Element getLastElementChild() {
2139         return super.getLastElementChild();
2140     }
2141 
2142     /**
2143      * {@inheritDoc}
2144      */
2145     @Override
2146     @JsxGetter
2147     public Element getFirstElementChild() {
2148         return super.getFirstElementChild();
2149     }
2150 
2151     /**
2152      * Returns the {@code xmlEncoding} property.
2153      * @return the {@code xmlEncoding} property
2154      */
2155     @JsxGetter({CHROME, EDGE})
2156     public String getXmlEncoding() {
2157         return getPage().getXmlEncoding();
2158     }
2159 
2160     /**
2161      * Returns the {@code xmlStandalone} property.
2162      * @return the {@code xmlStandalone} property
2163      */
2164     @JsxGetter({CHROME, EDGE})
2165     public boolean isXmlStandalone() {
2166         return getPage().getXmlStandalone();
2167     }
2168 
2169     /**
2170      * Returns the {@code xmlVersion} property.
2171      * @return the {@code xmlVersion} property
2172      */
2173     @JsxGetter({CHROME, EDGE})
2174     public String getXmlVersion() {
2175         return getPage().getXmlVersion();
2176     }
2177 
2178     /**
2179      * Returns the {@code onabort} event handler for this element.
2180      * @return the {@code onabort} event handler for this element
2181      */
2182     @JsxGetter
2183     public Function getOnabort() {
2184         return getEventHandler(Event.TYPE_ABORT);
2185     }
2186 
2187     /**
2188      * Sets the {@code onabort} event handler for this element.
2189      * @param onabort the {@code onabort} event handler for this element
2190      */
2191     @JsxSetter
2192     public void setOnabort(final Object onabort) {
2193         setEventHandler(Event.TYPE_ABORT, onabort);
2194     }
2195 
2196     /**
2197      * Returns the {@code onauxclick} event handler for this element.
2198      * @return the {@code onauxclick} event handler for this element
2199      */
2200     @JsxGetter({CHROME, EDGE})
2201     public Function getOnauxclick() {
2202         return getEventHandler(Event.TYPE_AUXCLICK);
2203     }
2204 
2205     /**
2206      * Sets the {@code onauxclick} event handler for this element.
2207      * @param onauxclick the {@code onauxclick} event handler for this element
2208      */
2209     @JsxSetter({CHROME, EDGE})
2210     public void setOnauxclick(final Object onauxclick) {
2211         setEventHandler(Event.TYPE_AUXCLICK, onauxclick);
2212     }
2213 
2214     /**
2215      * Returns the {@code onbeforecopy} event handler for this element.
2216      * @return the {@code onbeforecopy} event handler for this element
2217      */
2218     @JsxGetter({CHROME, EDGE})
2219     public Function getOnbeforecopy() {
2220         return getEventHandler(Event.TYPE_BEFORECOPY);
2221     }
2222 
2223     /**
2224      * Sets the {@code onbeforecopy} event handler for this element.
2225      * @param onbeforecopy the {@code onbeforecopy} event handler for this element
2226      */
2227     @JsxSetter({CHROME, EDGE})
2228     public void setOnbeforecopy(final Object onbeforecopy) {
2229         setEventHandler(Event.TYPE_BEFORECOPY, onbeforecopy);
2230     }
2231 
2232     /**
2233      * Returns the {@code onbeforecut} event handler for this element.
2234      * @return the {@code onbeforecut} event handler for this element
2235      */
2236     @JsxGetter({CHROME, EDGE})
2237     public Function getOnbeforecut() {
2238         return getEventHandler(Event.TYPE_BEFORECUT);
2239     }
2240 
2241     /**
2242      * Sets the {@code onbeforecut} event handler for this element.
2243      * @param onbeforecut the {@code onbeforecut} event handler for this element
2244      */
2245     @JsxSetter({CHROME, EDGE})
2246     public void setOnbeforecut(final Object onbeforecut) {
2247         setEventHandler(Event.TYPE_BEFORECUT, onbeforecut);
2248     }
2249 
2250     /**
2251      * Returns the {@code onbeforepaste} event handler for this element.
2252      * @return the {@code onbeforepaste} event handler for this element
2253      */
2254     @JsxGetter({CHROME, EDGE})
2255     public Function getOnbeforepaste() {
2256         return getEventHandler(Event.TYPE_BEFOREPASTE);
2257     }
2258 
2259     /**
2260      * Sets the {@code onbeforepaste} event handler for this element.
2261      * @param onbeforepaste the {@code onbeforepaste} event handler for this element
2262      */
2263     @JsxSetter({CHROME, EDGE})
2264     public void setOnbeforepaste(final Object onbeforepaste) {
2265         setEventHandler(Event.TYPE_BEFOREPASTE, onbeforepaste);
2266     }
2267 
2268     /**
2269      * Returns the {@code oncancel} event handler for this element.
2270      * @return the {@code oncancel} event handler for this element
2271      */
2272     @JsxGetter({CHROME, EDGE})
2273     public Function getOncancel() {
2274         return getEventHandler(Event.TYPE_CANCEL);
2275     }
2276 
2277     /**
2278      * Sets the {@code oncancel} event handler for this element.
2279      * @param oncancel the {@code oncancel} event handler for this element
2280      */
2281     @JsxSetter({CHROME, EDGE})
2282     public void setOncancel(final Object oncancel) {
2283         setEventHandler(Event.TYPE_CANCEL, oncancel);
2284     }
2285 
2286     /**
2287      * Returns the {@code oncanplay} event handler for this element.
2288      * @return the {@code oncanplay} event handler for this element
2289      */
2290     @JsxGetter
2291     public Function getOncanplay() {
2292         return getEventHandler(Event.TYPE_CANPLAY);
2293     }
2294 
2295     /**
2296      * Sets the {@code oncanplay} event handler for this element.
2297      * @param oncanplay the {@code oncanplay} event handler for this element
2298      */
2299     @JsxSetter
2300     public void setOncanplay(final Object oncanplay) {
2301         setEventHandler(Event.TYPE_CANPLAY, oncanplay);
2302     }
2303 
2304     /**
2305      * Returns the {@code oncanplaythrough} event handler for this element.
2306      * @return the {@code oncanplaythrough} event handler for this element
2307      */
2308     @JsxGetter
2309     public Function getOncanplaythrough() {
2310         return getEventHandler(Event.TYPE_CANPLAYTHROUGH);
2311     }
2312 
2313     /**
2314      * Sets the {@code oncanplaythrough} event handler for this element.
2315      * @param oncanplaythrough the {@code oncanplaythrough} event handler for this element
2316      */
2317     @JsxSetter
2318     public void setOncanplaythrough(final Object oncanplaythrough) {
2319         setEventHandler(Event.TYPE_CANPLAYTHROUGH, oncanplaythrough);
2320     }
2321 
2322     /**
2323      * Returns the {@code onchange} event handler for this element.
2324      * @return the {@code onchange} event handler for this element
2325      */
2326     @JsxGetter
2327     public Function getOnchange() {
2328         return getEventHandler(Event.TYPE_CHANGE);
2329     }
2330 
2331     /**
2332      * Sets the {@code onchange} event handler for this element.
2333      * @param onchange the {@code onchange} event handler for this element
2334      */
2335     @JsxSetter
2336     public void setOnchange(final Object onchange) {
2337         setEventHandler(Event.TYPE_CHANGE, onchange);
2338     }
2339 
2340     /**
2341      * Returns the {@code onclose} event handler for this element.
2342      * @return the {@code onclose} event handler for this element
2343      */
2344     @JsxGetter({CHROME, EDGE})
2345     public Function getOnclose() {
2346         return getEventHandler(Event.TYPE_CLOSE);
2347     }
2348 
2349     /**
2350      * Sets the {@code onclose} event handler for this element.
2351      * @param onclose the {@code onclose} event handler for this element
2352      */
2353     @JsxSetter({CHROME, EDGE})
2354     public void setOnclose(final Object onclose) {
2355         setEventHandler(Event.TYPE_CLOSE, onclose);
2356     }
2357 
2358     /**
2359      * Returns the {@code oncopy} event handler for this element.
2360      * @return the {@code oncopy} event handler for this element
2361      */
2362     @JsxGetter
2363     public Function getOncopy() {
2364         return getEventHandler(Event.TYPE_COPY);
2365     }
2366 
2367     /**
2368      * Sets the {@code oncopy} event handler for this element.
2369      * @param oncopy the {@code oncopy} event handler for this element
2370      */
2371     @JsxSetter
2372     public void setOncopy(final Object oncopy) {
2373         setEventHandler(Event.TYPE_COPY, oncopy);
2374     }
2375 
2376     /**
2377      * Returns the {@code oncuechange} event handler for this element.
2378      * @return the {@code oncuechange} event handler for this element
2379      */
2380     @JsxGetter({CHROME, EDGE})
2381     public Function getOncuechange() {
2382         return getEventHandler(Event.TYPE_CUECHANGE);
2383     }
2384 
2385     /**
2386      * Sets the {@code oncuechange} event handler for this element.
2387      * @param oncuechange the {@code oncuechange} event handler for this element
2388      */
2389     @JsxSetter({CHROME, EDGE})
2390     public void setOncuechange(final Object oncuechange) {
2391         setEventHandler(Event.TYPE_CUECHANGE, oncuechange);
2392     }
2393 
2394     /**
2395      * Returns the {@code oncut} event handler for this element.
2396      * @return the {@code oncut} event handler for this element
2397      */
2398     @JsxGetter
2399     public Function getOncut() {
2400         return getEventHandler(Event.TYPE_CUT);
2401     }
2402 
2403     /**
2404      * Sets the {@code oncut} event handler for this element.
2405      * @param oncut the {@code oncut} event handler for this element
2406      */
2407     @JsxSetter
2408     public void setOncut(final Object oncut) {
2409         setEventHandler(Event.TYPE_CUT, oncut);
2410     }
2411 
2412     /**
2413      * Returns the {@code ondrag} event handler for this element.
2414      * @return the {@code ondrag} event handler for this element
2415      */
2416     @JsxGetter
2417     public Function getOndrag() {
2418         return getEventHandler(Event.TYPE_DRAG);
2419     }
2420 
2421     /**
2422      * Sets the {@code ondrag} event handler for this element.
2423      * @param ondrag the {@code ondrag} event handler for this element
2424      */
2425     @JsxSetter
2426     public void setOndrag(final Object ondrag) {
2427         setEventHandler(Event.TYPE_DRAG, ondrag);
2428     }
2429 
2430     /**
2431      * Returns the {@code ondragend} event handler for this element.
2432      * @return the {@code ondragend} event handler for this element
2433      */
2434     @JsxGetter
2435     public Function getOndragend() {
2436         return getEventHandler(Event.TYPE_DRAGEND);
2437     }
2438 
2439     /**
2440      * Sets the {@code ondragend} event handler for this element.
2441      * @param ondragend the {@code ondragend} event handler for this element
2442      */
2443     @JsxSetter
2444     public void setOndragend(final Object ondragend) {
2445         setEventHandler(Event.TYPE_DRAGEND, ondragend);
2446     }
2447 
2448     /**
2449      * Returns the {@code ondragenter} event handler for this element.
2450      * @return the {@code ondragenter} event handler for this element
2451      */
2452     @JsxGetter
2453     public Function getOndragenter() {
2454         return getEventHandler(Event.TYPE_DRAGENTER);
2455     }
2456 
2457     /**
2458      * Sets the {@code ondragenter} event handler for this element.
2459      * @param ondragenter the {@code ondragenter} event handler for this element
2460      */
2461     @JsxSetter
2462     public void setOndragenter(final Object ondragenter) {
2463         setEventHandler(Event.TYPE_DRAGENTER, ondragenter);
2464     }
2465 
2466     /**
2467      * Returns the {@code ondragleave} event handler for this element.
2468      * @return the {@code ondragleave} event handler for this element
2469      */
2470     @JsxGetter
2471     public Function getOndragleave() {
2472         return getEventHandler(Event.TYPE_DRAGLEAVE);
2473     }
2474 
2475     /**
2476      * Sets the {@code ondragleave} event handler for this element.
2477      * @param ondragleave the {@code ondragleave} event handler for this element
2478      */
2479     @JsxSetter
2480     public void setOndragleave(final Object ondragleave) {
2481         setEventHandler(Event.TYPE_DRAGLEAVE, ondragleave);
2482     }
2483 
2484     /**
2485      * Returns the {@code ondragover} event handler for this element.
2486      * @return the {@code ondragover} event handler for this element
2487      */
2488     @JsxGetter
2489     public Function getOndragover() {
2490         return getEventHandler(Event.TYPE_DRAGOVER);
2491     }
2492 
2493     /**
2494      * Sets the {@code ondragover} event handler for this element.
2495      * @param ondragover the {@code ondragover} event handler for this element
2496      */
2497     @JsxSetter
2498     public void setOndragover(final Object ondragover) {
2499         setEventHandler(Event.TYPE_DRAGOVER, ondragover);
2500     }
2501 
2502     /**
2503      * Returns the {@code ondragstart} event handler for this element.
2504      * @return the {@code ondragstart} event handler for this element
2505      */
2506     @JsxGetter
2507     public Function getOndragstart() {
2508         return getEventHandler(Event.TYPE_DRAGSTART);
2509     }
2510 
2511     /**
2512      * Sets the {@code ondragstart} event handler for this element.
2513      * @param ondragstart the {@code ondragstart} event handler for this element
2514      */
2515     @JsxSetter
2516     public void setOndragstart(final Object ondragstart) {
2517         setEventHandler(Event.TYPE_DRAGSTART, ondragstart);
2518     }
2519 
2520     /**
2521      * Returns the {@code ondrop} event handler for this element.
2522      * @return the {@code ondrop} event handler for this element
2523      */
2524     @JsxGetter
2525     public Function getOndrop() {
2526         return getEventHandler(Event.TYPE_DROP);
2527     }
2528 
2529     /**
2530      * Sets the {@code ondrop} event handler for this element.
2531      * @param ondrop the {@code ondrop} event handler for this element
2532      */
2533     @JsxSetter
2534     public void setOndrop(final Object ondrop) {
2535         setEventHandler(Event.TYPE_DROP, ondrop);
2536     }
2537 
2538     /**
2539      * Returns the {@code ondurationchange} event handler for this element.
2540      * @return the {@code ondurationchange} event handler for this element
2541      */
2542     @JsxGetter
2543     public Function getOndurationchange() {
2544         return getEventHandler(Event.TYPE_DURATIONCHANGE);
2545     }
2546 
2547     /**
2548      * Sets the {@code ondurationchange} event handler for this element.
2549      * @param ondurationchange the {@code ondurationchange} event handler for this element
2550      */
2551     @JsxSetter
2552     public void setOndurationchange(final Object ondurationchange) {
2553         setEventHandler(Event.TYPE_DURATIONCHANGE, ondurationchange);
2554     }
2555 
2556     /**
2557      * Returns the {@code onemptied} event handler for this element.
2558      * @return the {@code onemptied} event handler for this element
2559      */
2560     @JsxGetter
2561     public Function getOnemptied() {
2562         return getEventHandler(Event.TYPE_EMPTIED);
2563     }
2564 
2565     /**
2566      * Sets the {@code onemptied} event handler for this element.
2567      * @param onemptied the {@code onemptied} event handler for this element
2568      */
2569     @JsxSetter
2570     public void setOnemptied(final Object onemptied) {
2571         setEventHandler(Event.TYPE_EMPTIED, onemptied);
2572     }
2573 
2574     /**
2575      * Returns the {@code onended} event handler for this element.
2576      * @return the {@code onended} event handler for this element
2577      */
2578     @JsxGetter
2579     public Function getOnended() {
2580         return getEventHandler(Event.TYPE_ENDED);
2581     }
2582 
2583     /**
2584      * Sets the {@code onended} event handler for this element.
2585      * @param onended the {@code onended} event handler for this element
2586      */
2587     @JsxSetter
2588     public void setOnended(final Object onended) {
2589         setEventHandler(Event.TYPE_ENDED, onended);
2590     }
2591 
2592     /**
2593      * Returns the {@code ongotpointercapture} event handler for this element.
2594      * @return the {@code ongotpointercapture} event handler for this element
2595      */
2596     @JsxGetter({CHROME, EDGE})
2597     public Function getOngotpointercapture() {
2598         return getEventHandler(Event.TYPE_GOTPOINTERCAPTURE);
2599     }
2600 
2601     /**
2602      * Sets the {@code ongotpointercapture} event handler for this element.
2603      * @param ongotpointercapture the {@code ongotpointercapture} event handler for this element
2604      */
2605     @JsxSetter({CHROME, EDGE})
2606     public void setOngotpointercapture(final Object ongotpointercapture) {
2607         setEventHandler(Event.TYPE_GOTPOINTERCAPTURE, ongotpointercapture);
2608     }
2609 
2610     /**
2611      * Returns the {@code oninvalid} event handler for this element.
2612      * @return the {@code oninvalid} event handler for this element
2613      */
2614     @JsxGetter
2615     public Function getOninvalid() {
2616         return getEventHandler(Event.TYPE_INVALID);
2617     }
2618 
2619     /**
2620      * Sets the {@code oninvalid} event handler for this element.
2621      * @param oninvalid the {@code oninvalid} event handler for this element
2622      */
2623     @JsxSetter
2624     public void setOninvalid(final Object oninvalid) {
2625         setEventHandler(Event.TYPE_INVALID, oninvalid);
2626     }
2627 
2628     /**
2629      * Returns the {@code onload} event handler for this element.
2630      * @return the {@code onload} event handler for this element
2631      */
2632     @JsxGetter
2633     public Function getOnload() {
2634         return getEventHandler(Event.TYPE_LOAD);
2635     }
2636 
2637     /**
2638      * Sets the {@code onload} event handler for this element.
2639      * @param onload the {@code onload} event handler for this element
2640      */
2641     @JsxSetter
2642     public void setOnload(final Object onload) {
2643         setEventHandler(Event.TYPE_LOAD, onload);
2644     }
2645 
2646     /**
2647      * Returns the {@code onloadeddata} event handler for this element.
2648      * @return the {@code onloadeddata} event handler for this element
2649      */
2650     @JsxGetter
2651     public Function getOnloadeddata() {
2652         return getEventHandler(Event.TYPE_LOADEDDATA);
2653     }
2654 
2655     /**
2656      * Sets the {@code onloadeddata} event handler for this element.
2657      * @param onloadeddata the {@code onloadeddata} event handler for this element
2658      */
2659     @JsxSetter
2660     public void setOnloadeddata(final Object onloadeddata) {
2661         setEventHandler(Event.TYPE_LOADEDDATA, onloadeddata);
2662     }
2663 
2664     /**
2665      * Returns the {@code onloadedmetadata} event handler for this element.
2666      * @return the {@code onloadedmetadata} event handler for this element
2667      */
2668     @JsxGetter
2669     public Function getOnloadedmetadata() {
2670         return getEventHandler(Event.TYPE_LOADEDMETADATA);
2671     }
2672 
2673     /**
2674      * Sets the {@code onloadedmetadata} event handler for this element.
2675      * @param onloadedmetadata the {@code onloadedmetadata} event handler for this element
2676      */
2677     @JsxSetter
2678     public void setOnloadedmetadata(final Object onloadedmetadata) {
2679         setEventHandler(Event.TYPE_LOADEDMETADATA, onloadedmetadata);
2680     }
2681 
2682     /**
2683      * Returns the {@code onloadstart} event handler for this element.
2684      * @return the {@code onloadstart} event handler for this element
2685      */
2686     @JsxGetter
2687     public Function getOnloadstart() {
2688         return getEventHandler(Event.TYPE_LOAD_START);
2689     }
2690 
2691     /**
2692      * Sets the {@code onloadstart} event handler for this element.
2693      * @param onloadstart the {@code onloadstart} event handler for this element
2694      */
2695     @JsxSetter
2696     public void setOnloadstart(final Object onloadstart) {
2697         setEventHandler(Event.TYPE_LOAD_START, onloadstart);
2698     }
2699 
2700     /**
2701      * Returns the {@code onlostpointercapture} event handler for this element.
2702      * @return the {@code onlostpointercapture} event handler for this element
2703      */
2704     @JsxGetter({CHROME, EDGE})
2705     public Function getOnlostpointercapture() {
2706         return getEventHandler(Event.TYPE_LOSTPOINTERCAPTURE);
2707     }
2708 
2709     /**
2710      * Sets the {@code onlostpointercapture} event handler for this element.
2711      * @param onlostpointercapture the {@code onlostpointercapture} event handler for this element
2712      */
2713     @JsxSetter({CHROME, EDGE})
2714     public void setOnlostpointercapture(final Object onlostpointercapture) {
2715         setEventHandler(Event.TYPE_LOSTPOINTERCAPTURE, onlostpointercapture);
2716     }
2717 
2718     /**
2719      * Returns the {@code onmouseenter} event handler for this element.
2720      * @return the {@code onmouseenter} event handler for this element
2721      */
2722     @JsxGetter
2723     public Function getOnmouseenter() {
2724         return getEventHandler(Event.TYPE_MOUDEENTER);
2725     }
2726 
2727     /**
2728      * Sets the {@code onmouseenter} event handler for this element.
2729      * @param onmouseenter the {@code onmouseenter} event handler for this element
2730      */
2731     @JsxSetter
2732     public void setOnmouseenter(final Object onmouseenter) {
2733         setEventHandler(Event.TYPE_MOUDEENTER, onmouseenter);
2734     }
2735 
2736     /**
2737      * Returns the {@code onmouseleave} event handler for this element.
2738      * @return the {@code onmouseleave} event handler for this element
2739      */
2740     @JsxGetter
2741     public Function getOnmouseleave() {
2742         return getEventHandler(Event.TYPE_MOUSELEAVE);
2743     }
2744 
2745     /**
2746      * Sets the {@code onmouseleave} event handler for this element.
2747      * @param onmouseleave the {@code onmouseleave} event handler for this element
2748      */
2749     @JsxSetter
2750     public void setOnmouseleave(final Object onmouseleave) {
2751         setEventHandler(Event.TYPE_MOUSELEAVE, onmouseleave);
2752     }
2753 
2754     /**
2755      * Returns the {@code onmousewheel} event handler for this element.
2756      * @return the {@code onmousewheel} event handler for this element
2757      */
2758     @JsxGetter({CHROME, EDGE})
2759     public Function getOnmousewheel() {
2760         return getEventHandler(Event.TYPE_MOUSEWHEEL);
2761     }
2762 
2763     /**
2764      * Sets the {@code onmousewheel} event handler for this element.
2765      * @param onmousewheel the {@code onmousewheel} event handler for this element
2766      */
2767     @JsxSetter({CHROME, EDGE})
2768     public void setOnmousewheel(final Object onmousewheel) {
2769         setEventHandler(Event.TYPE_MOUSEWHEEL, onmousewheel);
2770     }
2771 
2772     /**
2773      * Returns the {@code onpaste} event handler for this element.
2774      * @return the {@code onpaste} event handler for this element
2775      */
2776     @JsxGetter
2777     public Function getOnpaste() {
2778         return getEventHandler(Event.TYPE_PASTE);
2779     }
2780 
2781     /**
2782      * Sets the {@code onpaste} event handler for this element.
2783      * @param onpaste the {@code onpaste} event handler for this element
2784      */
2785     @JsxSetter
2786     public void setOnpaste(final Object onpaste) {
2787         setEventHandler(Event.TYPE_PASTE, onpaste);
2788     }
2789 
2790     /**
2791      * Returns the {@code onpause} event handler for this element.
2792      * @return the {@code onpause} event handler for this element
2793      */
2794     @JsxGetter
2795     public Function getOnpause() {
2796         return getEventHandler(Event.TYPE_PAUSE);
2797     }
2798 
2799     /**
2800      * Sets the {@code onpause} event handler for this element.
2801      * @param onpause the {@code onpause} event handler for this element
2802      */
2803     @JsxSetter
2804     public void setOnpause(final Object onpause) {
2805         setEventHandler(Event.TYPE_PAUSE, onpause);
2806     }
2807 
2808     /**
2809      * Returns the {@code onplay} event handler for this element.
2810      * @return the {@code onplay} event handler for this element
2811      */
2812     @JsxGetter
2813     public Function getOnplay() {
2814         return getEventHandler(Event.TYPE_PLAY);
2815     }
2816 
2817     /**
2818      * Sets the {@code onplay} event handler for this element.
2819      * @param onplay the {@code onplay} event handler for this element
2820      */
2821     @JsxSetter
2822     public void setOnplay(final Object onplay) {
2823         setEventHandler(Event.TYPE_PLAY, onplay);
2824     }
2825 
2826     /**
2827      * Returns the {@code onplaying} event handler for this element.
2828      * @return the {@code onplaying} event handler for this element
2829      */
2830     @JsxGetter
2831     public Function getOnplaying() {
2832         return getEventHandler(Event.TYPE_PLAYING);
2833     }
2834 
2835     /**
2836      * Sets the {@code onplaying} event handler for this element.
2837      * @param onplaying the {@code onplaying} event handler for this element
2838      */
2839     @JsxSetter
2840     public void setOnplaying(final Object onplaying) {
2841         setEventHandler(Event.TYPE_PLAYING, onplaying);
2842     }
2843 
2844     /**
2845      * Returns the {@code onpointercancel} event handler for this element.
2846      * @return the {@code onpointercancel} event handler for this element
2847      */
2848     @JsxGetter({CHROME, EDGE})
2849     public Function getOnpointercancel() {
2850         return getEventHandler(Event.TYPE_POINTERCANCEL);
2851     }
2852 
2853     /**
2854      * Sets the {@code onpointercancel} event handler for this element.
2855      * @param onpointercancel the {@code onpointercancel} event handler for this element
2856      */
2857     @JsxSetter({CHROME, EDGE})
2858     public void setOnpointercancel(final Object onpointercancel) {
2859         setEventHandler(Event.TYPE_POINTERCANCEL, onpointercancel);
2860     }
2861 
2862     /**
2863      * Returns the {@code onpointerdown} event handler for this element.
2864      * @return the {@code onpointerdown} event handler for this element
2865      */
2866     @JsxGetter({CHROME, EDGE})
2867     public Function getOnpointerdown() {
2868         return getEventHandler(Event.TYPE_POINTERDOWN);
2869     }
2870 
2871     /**
2872      * Sets the {@code onpointerdown} event handler for this element.
2873      * @param onpointerdown the {@code onpointerdown} event handler for this element
2874      */
2875     @JsxSetter({CHROME, EDGE})
2876     public void setOnpointerdown(final Object onpointerdown) {
2877         setEventHandler(Event.TYPE_POINTERDOWN, onpointerdown);
2878     }
2879 
2880     /**
2881      * Returns the {@code onpointerenter} event handler for this element.
2882      * @return the {@code onpointerenter} event handler for this element
2883      */
2884     @JsxGetter({CHROME, EDGE})
2885     public Function getOnpointerenter() {
2886         return getEventHandler(Event.TYPE_POINTERENTER);
2887     }
2888 
2889     /**
2890      * Sets the {@code onpointerenter} event handler for this element.
2891      * @param onpointerenter the {@code onpointerenter} event handler for this element
2892      */
2893     @JsxSetter({CHROME, EDGE})
2894     public void setOnpointerenter(final Object onpointerenter) {
2895         setEventHandler(Event.TYPE_POINTERENTER, onpointerenter);
2896     }
2897 
2898     /**
2899      * Returns the {@code onpointerleave} event handler for this element.
2900      * @return the {@code onpointerleave} event handler for this element
2901      */
2902     @JsxGetter({CHROME, EDGE})
2903     public Function getOnpointerleave() {
2904         return getEventHandler(Event.TYPE_POINTERLEAVE);
2905     }
2906 
2907     /**
2908      * Sets the {@code onpointerleave} event handler for this element.
2909      * @param onpointerleave the {@code onpointerleave} event handler for this element
2910      */
2911     @JsxSetter({CHROME, EDGE})
2912     public void setOnpointerleave(final Object onpointerleave) {
2913         setEventHandler(Event.TYPE_POINTERLEAVE, onpointerleave);
2914     }
2915 
2916     /**
2917      * Returns the {@code onpointerlockchange} event handler for this element.
2918      * @return the {@code onpointerlockchange} event handler for this element
2919      */
2920     @JsxGetter({CHROME, EDGE})
2921     public Function getOnpointerlockchange() {
2922         return getEventHandler(Event.TYPE_POINTERLOCKCHANGE);
2923     }
2924 
2925     /**
2926      * Sets the {@code onpointerlockchange} event handler for this element.
2927      * @param onpointerlockchange the {@code onpointerlockchange} event handler for this element
2928      */
2929     @JsxSetter({CHROME, EDGE})
2930     public void setOnpointerlockchange(final Object onpointerlockchange) {
2931         setEventHandler(Event.TYPE_POINTERLOCKCHANGE, onpointerlockchange);
2932     }
2933 
2934     /**
2935      * Returns the {@code onpointerlockerror} event handler for this element.
2936      * @return the {@code onpointerlockerror} event handler for this element
2937      */
2938     @JsxGetter({CHROME, EDGE})
2939     public Function getOnpointerlockerror() {
2940         return getEventHandler(Event.TYPE_POINTERLOCKERROR);
2941     }
2942 
2943     /**
2944      * Sets the {@code onpointerlockerror} event handler for this element.
2945      * @param onpointerlockerror the {@code onpointerlockerror} event handler for this element
2946      */
2947     @JsxSetter({CHROME, EDGE})
2948     public void setOnpointerlockerror(final Object onpointerlockerror) {
2949         setEventHandler(Event.TYPE_POINTERLOCKERROR, onpointerlockerror);
2950     }
2951 
2952     /**
2953      * Returns the {@code onpointermove} event handler for this element.
2954      * @return the {@code onpointermove} event handler for this element
2955      */
2956     @JsxGetter({CHROME, EDGE})
2957     public Function getOnpointermove() {
2958         return getEventHandler(Event.TYPE_POINTERMOVE);
2959     }
2960 
2961     /**
2962      * Sets the {@code onpointermove} event handler for this element.
2963      * @param onpointermove the {@code onpointermove} event handler for this element
2964      */
2965     @JsxSetter({CHROME, EDGE})
2966     public void setOnpointermove(final Object onpointermove) {
2967         setEventHandler(Event.TYPE_POINTERMOVE, onpointermove);
2968     }
2969 
2970     /**
2971      * Returns the {@code onpointerout} event handler for this element.
2972      * @return the {@code onpointerout} event handler for this element
2973      */
2974     @JsxGetter({CHROME, EDGE})
2975     public Function getOnpointerout() {
2976         return getEventHandler(Event.TYPE_POINTEROUT);
2977     }
2978 
2979     /**
2980      * Sets the {@code onpointerout} event handler for this element.
2981      * @param onpointerout the {@code onpointerout} event handler for this element
2982      */
2983     @JsxSetter({CHROME, EDGE})
2984     public void setOnpointerout(final Object onpointerout) {
2985         setEventHandler(Event.TYPE_POINTEROUT, onpointerout);
2986     }
2987 
2988     /**
2989      * Returns the {@code onpointerover} event handler for this element.
2990      * @return the {@code onpointerover} event handler for this element
2991      */
2992     @JsxGetter({CHROME, EDGE})
2993     public Function getOnpointerover() {
2994         return getEventHandler(Event.TYPE_POINTEROVER);
2995     }
2996 
2997     /**
2998      * Sets the {@code onpointerover} event handler for this element.
2999      * @param onpointerover the {@code onpointerover} event handler for this element
3000      */
3001     @JsxSetter({CHROME, EDGE})
3002     public void setOnpointerover(final Object onpointerover) {
3003         setEventHandler(Event.TYPE_POINTEROVER, onpointerover);
3004     }
3005 
3006     /**
3007      * Returns the {@code onpointerup} event handler for this element.
3008      * @return the {@code onpointerup} event handler for this element
3009      */
3010     @JsxGetter({CHROME, EDGE})
3011     public Function getOnpointerup() {
3012         return getEventHandler(Event.TYPE_POINTERUP);
3013     }
3014 
3015     /**
3016      * Sets the {@code onpointerup} event handler for this element.
3017      * @param onpointerup the {@code onpointerup} event handler for this element
3018      */
3019     @JsxSetter({CHROME, EDGE})
3020     public void setOnpointerup(final Object onpointerup) {
3021         setEventHandler(Event.TYPE_POINTERUP, onpointerup);
3022     }
3023 
3024     /**
3025      * Returns the {@code onprogress} event handler for this element.
3026      * @return the {@code onprogress} event handler for this element
3027      */
3028     @JsxGetter
3029     public Function getOnprogress() {
3030         return getEventHandler(Event.TYPE_PROGRESS);
3031     }
3032 
3033     /**
3034      * Sets the {@code onprogress} event handler for this element.
3035      * @param onprogress the {@code onprogress} event handler for this element
3036      */
3037     @JsxSetter
3038     public void setOnprogress(final Object onprogress) {
3039         setEventHandler(Event.TYPE_PROGRESS, onprogress);
3040     }
3041 
3042     /**
3043      * Returns the {@code onratechange} event handler for this element.
3044      * @return the {@code onratechange} event handler for this element
3045      */
3046     @JsxGetter
3047     public Function getOnratechange() {
3048         return getEventHandler(Event.TYPE_RATECHANGE);
3049     }
3050 
3051     /**
3052      * Sets the {@code onratechange} event handler for this element.
3053      * @param onratechange the {@code onratechange} event handler for this element
3054      */
3055     @JsxSetter
3056     public void setOnratechange(final Object onratechange) {
3057         setEventHandler(Event.TYPE_RATECHANGE, onratechange);
3058     }
3059 
3060     /**
3061      * Returns the {@code onreadystatechange} event handler for this element.
3062      * @return the {@code onreadystatechange} event handler for this element
3063      */
3064     @JsxGetter
3065     public Function getOnreadystatechange() {
3066         return getEventHandler(Event.TYPE_READY_STATE_CHANGE);
3067     }
3068 
3069     /**
3070      * Sets the {@code onreadystatechange} event handler for this element.
3071      * @param onreadystatechange the {@code onreadystatechange} event handler for this element
3072      */
3073     @JsxSetter
3074     public void setOnreadystatechange(final Object onreadystatechange) {
3075         setEventHandler(Event.TYPE_READY_STATE_CHANGE, onreadystatechange);
3076     }
3077 
3078     /**
3079      * Returns the {@code onreset} event handler for this element.
3080      * @return the {@code onreset} event handler for this element
3081      */
3082     @JsxGetter
3083     public Function getOnreset() {
3084         return getEventHandler(Event.TYPE_RESET);
3085     }
3086 
3087     /**
3088      * Sets the {@code onreset} event handler for this element.
3089      * @param onreset the {@code onreset} event handler for this element
3090      */
3091     @JsxSetter
3092     public void setOnreset(final Object onreset) {
3093         setEventHandler(Event.TYPE_RESET, onreset);
3094     }
3095 
3096     /**
3097      * Returns the {@code onscroll} event handler for this element.
3098      * @return the {@code onscroll} event handler for this element
3099      */
3100     @JsxGetter
3101     public Function getOnscroll() {
3102         return getEventHandler(Event.TYPE_SCROLL);
3103     }
3104 
3105     /**
3106      * Sets the {@code onscroll} event handler for this element.
3107      * @param onscroll the {@code onscroll} event handler for this element
3108      */
3109     @JsxSetter
3110     public void setOnscroll(final Object onscroll) {
3111         setEventHandler(Event.TYPE_SCROLL, onscroll);
3112     }
3113 
3114     /**
3115      * Returns the {@code onsearch} event handler for this element.
3116      * @return the {@code onsearch} event handler for this element
3117      */
3118     @JsxGetter({CHROME, EDGE})
3119     public Function getOnsearch() {
3120         return getEventHandler(Event.TYPE_SEARCH);
3121     }
3122 
3123     /**
3124      * Sets the {@code onsearch} event handler for this element.
3125      * @param onsearch the {@code onsearch} event handler for this element
3126      */
3127     @JsxSetter({CHROME, EDGE})
3128     public void setOnsearch(final Object onsearch) {
3129         setEventHandler(Event.TYPE_SEARCH, onsearch);
3130     }
3131 
3132     /**
3133      * Returns the {@code onseeked} event handler for this element.
3134      * @return the {@code onseeked} event handler for this element
3135      */
3136     @JsxGetter
3137     public Function getOnseeked() {
3138         return getEventHandler(Event.TYPE_SEEKED);
3139     }
3140 
3141     /**
3142      * Sets the {@code onseeked} event handler for this element.
3143      * @param onseeked the {@code onseeked} event handler for this element
3144      */
3145     @JsxSetter
3146     public void setOnseeked(final Object onseeked) {
3147         setEventHandler(Event.TYPE_SEEKED, onseeked);
3148     }
3149 
3150     /**
3151      * Returns the {@code onseeking} event handler for this element.
3152      * @return the {@code onseeking} event handler for this element
3153      */
3154     @JsxGetter
3155     public Function getOnseeking() {
3156         return getEventHandler(Event.TYPE_SEEKING);
3157     }
3158 
3159     /**
3160      * Sets the {@code onseeking} event handler for this element.
3161      * @param onseeking the {@code onseeking} event handler for this element
3162      */
3163     @JsxSetter
3164     public void setOnseeking(final Object onseeking) {
3165         setEventHandler(Event.TYPE_SEEKING, onseeking);
3166     }
3167 
3168     /**
3169      * Returns the {@code onselect} event handler for this element.
3170      * @return the {@code onselect} event handler for this element
3171      */
3172     @JsxGetter
3173     public Function getOnselect() {
3174         return getEventHandler(Event.TYPE_SELECT);
3175     }
3176 
3177     /**
3178      * Sets the {@code onselect} event handler for this element.
3179      * @param onselect the {@code onselect} event handler for this element
3180      */
3181     @JsxSetter
3182     public void setOnselect(final Object onselect) {
3183         setEventHandler(Event.TYPE_SELECT, onselect);
3184     }
3185 
3186     /**
3187      * Returns the {@code onselectionchange} event handler for this element.
3188      * @return the {@code onselectionchange} event handler for this element
3189      */
3190     @JsxGetter({CHROME, EDGE})
3191     public Function getOnselectionchange() {
3192         return getEventHandler(Event.TYPE_SELECTIONCHANGE);
3193     }
3194 
3195     /**
3196      * Sets the {@code onselectionchange} event handler for this element.
3197      * @param onselectionchange the {@code onselectionchange} event handler for this element
3198      */
3199     @JsxSetter({CHROME, EDGE})
3200     public void setOnselectionchange(final Object onselectionchange) {
3201         setEventHandler(Event.TYPE_SELECTIONCHANGE, onselectionchange);
3202     }
3203 
3204     /**
3205      * Returns the {@code onselectstart} event handler for this element.
3206      * @return the {@code onselectstart} event handler for this element
3207      */
3208     @JsxGetter
3209     public Function getOnselectstart() {
3210         return getEventHandler(Event.TYPE_SELECTSTART);
3211     }
3212 
3213     /**
3214      * Sets the {@code onselectstart} event handler for this element.
3215      * @param onselectstart the {@code onselectstart} event handler for this element
3216      */
3217     @JsxSetter
3218     public void setOnselectstart(final Object onselectstart) {
3219         setEventHandler(Event.TYPE_SELECTSTART, onselectstart);
3220     }
3221 
3222     /**
3223      * Returns the {@code onstalled} event handler for this element.
3224      * @return the {@code onstalled} event handler for this element
3225      */
3226     @JsxGetter
3227     public Function getOnstalled() {
3228         return getEventHandler(Event.TYPE_STALLED);
3229     }
3230 
3231     /**
3232      * Sets the {@code onstalled} event handler for this element.
3233      * @param onstalled the {@code onstalled} event handler for this element
3234      */
3235     @JsxSetter
3236     public void setOnstalled(final Object onstalled) {
3237         setEventHandler(Event.TYPE_STALLED, onstalled);
3238     }
3239 
3240     /**
3241      * Returns the {@code onsubmit} event handler for this element.
3242      * @return the {@code onsubmit} event handler for this element
3243      */
3244     @JsxGetter
3245     public Function getOnsubmit() {
3246         return getEventHandler(Event.TYPE_SUBMIT);
3247     }
3248 
3249     /**
3250      * Sets the {@code onsubmit} event handler for this element.
3251      * @param onsubmit the {@code onsubmit} event handler for this element
3252      */
3253     @JsxSetter
3254     public void setOnsubmit(final Object onsubmit) {
3255         setEventHandler(Event.TYPE_SUBMIT, onsubmit);
3256     }
3257 
3258     /**
3259      * Returns the {@code onsuspend} event handler for this element.
3260      * @return the {@code onsuspend} event handler for this element
3261      */
3262     @JsxGetter
3263     public Function getOnsuspend() {
3264         return getEventHandler(Event.TYPE_SUSPEND);
3265     }
3266 
3267     /**
3268      * Sets the {@code onsuspend} event handler for this element.
3269      * @param onsuspend the {@code onsuspend} event handler for this element
3270      */
3271     @JsxSetter
3272     public void setOnsuspend(final Object onsuspend) {
3273         setEventHandler(Event.TYPE_SUSPEND, onsuspend);
3274     }
3275 
3276     /**
3277      * Returns the {@code ontimeupdate} event handler for this element.
3278      * @return the {@code ontimeupdate} event handler for this element
3279      */
3280     @JsxGetter
3281     public Function getOntimeupdate() {
3282         return getEventHandler(Event.TYPE_TIMEUPDATE);
3283     }
3284 
3285     /**
3286      * Sets the {@code ontimeupdate} event handler for this element.
3287      * @param ontimeupdate the {@code ontimeupdate} event handler for this element
3288      */
3289     @JsxSetter
3290     public void setOntimeupdate(final Object ontimeupdate) {
3291         setEventHandler(Event.TYPE_TIMEUPDATE, ontimeupdate);
3292     }
3293 
3294     /**
3295      * Returns the {@code ontoggle} event handler for this element.
3296      * @return the {@code ontoggle} event handler for this element
3297      */
3298     @JsxGetter({CHROME, EDGE})
3299     public Function getOntoggle() {
3300         return getEventHandler(Event.TYPE_TOGGLE);
3301     }
3302 
3303     /**
3304      * Sets the {@code ontoggle} event handler for this element.
3305      * @param ontoggle the {@code ontoggle} event handler for this element
3306      */
3307     @JsxSetter({CHROME, EDGE})
3308     public void setOntoggle(final Object ontoggle) {
3309         setEventHandler(Event.TYPE_TOGGLE, ontoggle);
3310     }
3311 
3312     /**
3313      * Returns the {@code onvolumechange} event handler for this element.
3314      * @return the {@code onvolumechange} event handler for this element
3315      */
3316     @JsxGetter
3317     public Function getOnvolumechange() {
3318         return getEventHandler(Event.TYPE_VOLUMECHANGE);
3319     }
3320 
3321     /**
3322      * Sets the {@code onvolumechange} event handler for this element.
3323      * @param onvolumechange the {@code onvolumechange} event handler for this element
3324      */
3325     @JsxSetter
3326     public void setOnvolumechange(final Object onvolumechange) {
3327         setEventHandler(Event.TYPE_VOLUMECHANGE, onvolumechange);
3328     }
3329 
3330     /**
3331      * Returns the {@code onwaiting} event handler for this element.
3332      * @return the {@code onwaiting} event handler for this element
3333      */
3334     @JsxGetter
3335     public Function getOnwaiting() {
3336         return getEventHandler(Event.TYPE_WAITING);
3337     }
3338 
3339     /**
3340      * Sets the {@code onwaiting} event handler for this element.
3341      * @param onwaiting the {@code onwaiting} event handler for this element
3342      */
3343     @JsxSetter
3344     public void setOnwaiting(final Object onwaiting) {
3345         setEventHandler(Event.TYPE_WAITING, onwaiting);
3346     }
3347 
3348     /**
3349      * Returns the {@code onwebkitfullscreenchange} event handler for this element.
3350      * @return the {@code onwebkitfullscreenchange} event handler for this element
3351      */
3352     @JsxGetter({CHROME, EDGE})
3353     public Function getOnwebkitfullscreenchange() {
3354         return getEventHandler(Event.TYPE_WEBKITFULLSCREENCHANGE);
3355     }
3356 
3357     /**
3358      * Sets the {@code onwebkitfullscreenchange} event handler for this element.
3359      * @param onwebkitfullscreenchange the {@code onwebkitfullscreenchange} event handler for this element
3360      */
3361     @JsxSetter({CHROME, EDGE})
3362     public void setOnwebkitfullscreenchange(final Object onwebkitfullscreenchange) {
3363         setEventHandler(Event.TYPE_WEBKITFULLSCREENCHANGE, onwebkitfullscreenchange);
3364     }
3365 
3366     /**
3367      * Returns the {@code onwebkitfullscreenerror} event handler for this element.
3368      * @return the {@code onwebkitfullscreenerror} event handler for this element
3369      */
3370     @JsxGetter({CHROME, EDGE})
3371     public Function getOnwebkitfullscreenerror() {
3372         return getEventHandler(Event.TYPE_WEBKITFULLSCREENERROR);
3373     }
3374 
3375     /**
3376      * Sets the {@code onwebkitfullscreenerror} event handler for this element.
3377      * @param onwebkitfullscreenerror the {@code onwebkitfullscreenerror} event handler for this element
3378      */
3379     @JsxSetter
3380     public void setOnwebkitfullscreenerror(final Object onwebkitfullscreenerror) {
3381         setEventHandler(Event.TYPE_WEBKITFULLSCREENERROR, onwebkitfullscreenerror);
3382     }
3383 
3384     /**
3385      * Returns the {@code onwheel} event handler for this element.
3386      * @return the {@code onwheel} event handler for this element
3387      */
3388     @JsxGetter
3389     public Function getOnwheel() {
3390         return getEventHandler(Event.TYPE_WHEEL);
3391     }
3392 
3393     /**
3394      * Sets the {@code onwheel} event handler for this element.
3395      * @param onwheel the {@code onwheel} event handler for this element
3396      */
3397     @JsxSetter
3398     public void setOnwheel(final Object onwheel) {
3399         setEventHandler(Event.TYPE_WHEEL, onwheel);
3400     }
3401 
3402     /**
3403      * Returns the {@code onafterscriptexecute} event handler for this element.
3404      * @return the {@code onafterscriptexecute} event handler for this element
3405      */
3406     @JsxGetter({FF, FF_ESR})
3407     public Function getOnafterscriptexecute() {
3408         return getEventHandler(Event.TYPE_AFTERSCRIPTEXECUTE);
3409     }
3410 
3411     /**
3412      * Sets the {@code onafterscriptexecute} event handler for this element.
3413      * @param onafterscriptexecute the {@code onafterscriptexecute} event handler for this element
3414      */
3415     @JsxSetter({FF, FF_ESR})
3416     public void setOnafterscriptexecute(final Object onafterscriptexecute) {
3417         setEventHandler(Event.TYPE_AFTERSCRIPTEXECUTE, onafterscriptexecute);
3418     }
3419 
3420     /**
3421      * Returns the {@code onbeforescriptexecute} event handler for this element.
3422      * @return the {@code onbeforescriptexecute} event handler for this element
3423      */
3424     @JsxGetter({FF, FF_ESR})
3425     public Function getOnbeforescriptexecute() {
3426         return getEventHandler(Event.TYPE_BEFORESCRIPTEXECUTE);
3427     }
3428 
3429     /**
3430      * Sets the {@code onbeforescriptexecute} event handler for this element.
3431      * @param onbeforescriptexecute the {@code onbeforescriptexecute} event handler for this element
3432      */
3433     @JsxSetter({FF, FF_ESR})
3434     public void setOnbeforescriptexecute(final Object onbeforescriptexecute) {
3435         setEventHandler(Event.TYPE_BEFORESCRIPTEXECUTE, onbeforescriptexecute);
3436     }
3437 
3438     /**
3439      * Returns the {@code onmozfullscreenchange} event handler for this element.
3440      * @return the {@code onmozfullscreenchange} event handler for this element
3441      */
3442     @JsxGetter({FF, FF_ESR})
3443     public Function getOnmozfullscreenchange() {
3444         return getEventHandler(Event.TYPE_MOZFULLSCREENCHANGE);
3445     }
3446 
3447     /**
3448      * Sets the {@code onmozfullscreenchange} event handler for this element.
3449      * @param onmozfullscreenchange the {@code onmozfullscreenchange} event handler for this element
3450      */
3451     @JsxSetter({FF, FF_ESR})
3452     public void setOnmozfullscreenchange(final Object onmozfullscreenchange) {
3453         setEventHandler(Event.TYPE_MOZFULLSCREENCHANGE, onmozfullscreenchange);
3454     }
3455 
3456     /**
3457      * Returns the {@code onmozfullscreenerror} event handler for this element.
3458      * @return the {@code onmozfullscreenerror} event handler for this element
3459      */
3460     @JsxGetter({FF, FF_ESR})
3461     public Function getOnmozfullscreenerror() {
3462         return getEventHandler(Event.TYPE_MOZFULLSCREENERROR);
3463     }
3464 
3465     /**
3466      * Sets the {@code onmozfullscreenerror} event handler for this element.
3467      * @param onmozfullscreenerror the {@code onmozfullscreenerror} event handler for this element
3468      */
3469     @JsxSetter({FF, FF_ESR})
3470     public void setOnmozfullscreenerror(final Object onmozfullscreenerror) {
3471         setEventHandler(Event.TYPE_MOZFULLSCREENERROR, onmozfullscreenerror);
3472     }
3473 
3474     /**
3475      * @return the {@code currentScript}
3476      */
3477     @JsxGetter
3478     public ScriptableObject getCurrentScript() {
3479         return currentScript_;
3480     }
3481 
3482     /**
3483      * @param script the {@code currentScript}
3484      */
3485     public void setCurrentScript(final ScriptableObject script) {
3486         currentScript_ = script;
3487     }
3488 
3489     /**
3490      * @return the {@code FontFaceSet}
3491      */
3492     @JsxGetter
3493     public ScriptableObject getFonts() {
3494         if (fonts_ == null) {
3495             final FontFaceSet fonts = new FontFaceSet();
3496             fonts.setParentScope(getWindow());
3497             fonts.setPrototype(getPrototype(fonts.getClass()));
3498             fonts_ = fonts;
3499         }
3500         return fonts_;
3501     }
3502 
3503     /**
3504      * Returns the value of the {@code all} property.
3505      * @return the value of the {@code all} property
3506      */
3507     @JsxGetter
3508     public HTMLCollection getAll() {
3509         final HTMLCollection all = new HTMLAllCollection(getDomNodeOrDie());
3510         all.setAvoidObjectDetection(true);
3511         all.setIsMatchingPredicate((Predicate<DomNode> & Serializable) node -> true);
3512         return all;
3513     }
3514 
3515     /**
3516      * Returns the element with the specified ID, as long as it is an HTML element; {@code null} otherwise.
3517      * @param id the ID to search for
3518      * @return the element with the specified ID, as long as it is an HTML element; {@code null} otherwise
3519      */
3520     @JsxFunction
3521     public HtmlUnitScriptable getElementById(final String id) {
3522         final DomNode domNode = getDomNodeOrDie();
3523         for (final DomElement descendant : domNode.getDomElementDescendants()) {
3524             if (id.equals(descendant.getId())) {
3525                 return descendant.getScriptableObject();
3526             }
3527         }
3528         return null;
3529     }
3530 
3531     /**
3532      * Creates a new ProcessingInstruction.
3533      * @param target the target
3534      * @param data the data
3535      * @return the new ProcessingInstruction
3536      */
3537     @JsxFunction
3538     public HtmlUnitScriptable createProcessingInstruction(final String target, final String data) {
3539         final ProcessingInstruction node = getPage().createProcessingInstruction(target, data);
3540         return getScriptableFor(node);
3541     }
3542 
3543     /**
3544      * Creates a new createCDATASection.
3545      * @param data the data
3546      * @return the new CDATASection
3547      */
3548     @JsxFunction
3549     public HtmlUnitScriptable createCDATASection(final String data) {
3550         final CDATASection node = getPage().createCDATASection(data);
3551         return getScriptableFor(node);
3552     }
3553 
3554     /**
3555      * Does... nothing.
3556      * @see <a href="https://developer.mozilla.org/en/DOM/document.clear">Mozilla doc</a>
3557      */
3558     @JsxFunction
3559     public void clear() {
3560         // nothing
3561     }
3562 
3563     /**
3564      * {@inheritDoc}
3565      */
3566     @JsxFunction
3567     @Override
3568     public boolean contains(final Object element) {
3569         return getDocumentElement().contains(element);
3570     }
3571 
3572     /**
3573      * Generate and return the URL for the given blob.
3574      * @param blob the Blob containing the data
3575      * @return the URL {@link org.htmlunit.javascript.host.URL#createObjectURL(Object)}
3576      */
3577     public String generateBlobUrl(final Blob blob) {
3578         final URL url = getPage().getUrl();
3579 
3580         String origin = "null";
3581         if (!UrlUtils.URL_ABOUT_BLANK.equals(url)) {
3582             origin = url.getProtocol() + "://" + url.getAuthority();
3583         }
3584 
3585         final String blobUrl = "blob:" + origin + "/" + UUID.randomUUID();
3586         blobUrl2Blobs_.put(blobUrl, blob);
3587         return blobUrl;
3588     }
3589 
3590     /**
3591      * @param url the url to resolve
3592      * @return the Blob for the given URL or {@code null} if not found.
3593      */
3594     public Blob resolveBlobUrl(final String url) {
3595         return blobUrl2Blobs_.get(url);
3596     }
3597 
3598     /**
3599      * Revokes the URL for the given blob.
3600      * @param url the url to revoke {@link org.htmlunit.javascript.host.URL#revokeObjectURL(Scriptable)}
3601      */
3602     public void revokeBlobUrl(final String url) {
3603         blobUrl2Blobs_.remove(url);
3604     }
3605 }