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