diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 47fa4521ecd..a313f1786ed 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -8,6 +8,9 @@ + + SubmitEvent support added. + Avoid usage of org.w3c.dom.ranges.Range - this is not available on android. diff --git a/src/main/java/org/htmlunit/html/HtmlForm.java b/src/main/java/org/htmlunit/html/HtmlForm.java index 1ff3fd79773..9ce11857efa 100644 --- a/src/main/java/org/htmlunit/html/HtmlForm.java +++ b/src/main/java/org/htmlunit/html/HtmlForm.java @@ -56,6 +56,7 @@ import org.htmlunit.WebWindow; import org.htmlunit.httpclient.HttpClientConverter; import org.htmlunit.javascript.host.event.Event; +import org.htmlunit.javascript.host.event.SubmitEvent; import org.htmlunit.protocol.javascript.JavaScriptURLConnection; import org.htmlunit.util.EncodingSniffer; import org.htmlunit.util.NameValuePair; @@ -152,8 +153,8 @@ && getAttributeDirect(ATTRIBUTE_NOVALIDATE) != ATTRIBUTE_NOT_DEFINED) { if (validate && !areChildrenValid()) { return; } - - final ScriptResult scriptResult = fireEvent(Event.TYPE_SUBMIT); + final ScriptResult scriptResult = fireEvent(new SubmitEvent(this, + ((HtmlElement) submitElement).getScriptableObject())); if (isPreventDefault_) { // null means 'nothing executed' if (scriptResult == null) { diff --git a/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java b/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java index 63321faa8c9..851e44a0a61 100644 --- a/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java +++ b/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java @@ -231,6 +231,7 @@ import org.htmlunit.javascript.host.event.SecurityPolicyViolationEvent; import org.htmlunit.javascript.host.event.SpeechSynthesisEvent; import org.htmlunit.javascript.host.event.StorageEvent; +import org.htmlunit.javascript.host.event.SubmitEvent; import org.htmlunit.javascript.host.event.TextEvent; import org.htmlunit.javascript.host.event.TimeEvent; import org.htmlunit.javascript.host.event.TouchEvent; @@ -610,7 +611,7 @@ public final class JavaScriptConfiguration extends AbstractJavaScriptConfigurati SpeechSynthesis.class, SpeechSynthesisErrorEvent.class, SpeechSynthesisEvent.class, SpeechSynthesisUtterance.class, SpeechSynthesisVoice.class, StereoPannerNode.class, Storage.class, StorageEvent.class, StorageManager.class, - StyleMedia.class, StyleSheet.class, StyleSheetList.class, SubtleCrypto.class, + StyleMedia.class, StyleSheet.class, StyleSheetList.class, SubmitEvent.class, SubtleCrypto.class, SVGAElement.class, SVGAngle.class, SVGAnimatedAngle.class, SVGAnimatedBoolean.class, SVGAnimatedEnumeration.class, SVGAnimatedInteger.class, SVGAnimatedLength.class, SVGAnimatedLengthList.class, SVGAnimatedNumber.class, SVGAnimatedNumberList.class, diff --git a/src/main/java/org/htmlunit/javascript/host/event/SubmitEvent.java b/src/main/java/org/htmlunit/javascript/host/event/SubmitEvent.java new file mode 100644 index 00000000000..85e70ba2aa9 --- /dev/null +++ b/src/main/java/org/htmlunit/javascript/host/event/SubmitEvent.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2023 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.htmlunit.javascript.host.event; + +import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME; +import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE; +import static org.htmlunit.javascript.configuration.SupportedBrowser.FF; +import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR; + +import org.htmlunit.corejs.javascript.ScriptableObject; +import org.htmlunit.corejs.javascript.Undefined; +import org.htmlunit.html.DomNode; +import org.htmlunit.javascript.configuration.JsxClass; +import org.htmlunit.javascript.configuration.JsxConstructor; +import org.htmlunit.javascript.configuration.JsxGetter; +import org.htmlunit.javascript.host.html.HTMLElement; + +/** + * A JavaScript object for {@code SubmitEvent}. + * + * @author Ronald Brill + */ +@JsxClass +public class SubmitEvent extends Event { + + private HTMLElement submitter_; + + /** + * Default constructor. + */ + public SubmitEvent() { + } + + /** + * Ctor. + * @param domNode the DOM node that triggered the event + * @param submitElement + * + */ + public SubmitEvent(final DomNode domNode, final HTMLElement submitElement) { + super(domNode, Event.TYPE_SUBMIT); + submitter_ = submitElement; + } + + /** + * JavaScript constructor. + * + * @param type the event type + * @param details the event details (optional) + */ + @Override + @JsxConstructor({CHROME, EDGE, FF, FF_ESR}) + public void jsConstructor(final String type, final ScriptableObject details) { + super.jsConstructor(type, details); + + if (details != null && !Undefined.isUndefined(details)) { + final Object submitter = details.get("submitter"); + if (submitter instanceof HTMLElement) { + submitter_ = (HTMLElement) submitter; + } + } + } + + /** + * @return the submitter + */ + @JsxGetter + public HTMLElement getSubmitter() { + return submitter_; + } +} diff --git a/src/test/java/org/htmlunit/javascript/host/event/SubmitEventTest.java b/src/test/java/org/htmlunit/javascript/host/event/SubmitEventTest.java new file mode 100644 index 00000000000..d545824501b --- /dev/null +++ b/src/test/java/org/htmlunit/javascript/host/event/SubmitEventTest.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2002-2023 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.htmlunit.javascript.host.event; + +import org.htmlunit.WebDriverTestCase; +import org.htmlunit.html.HtmlPageTest; +import org.htmlunit.junit.BrowserRunner; +import org.htmlunit.junit.BrowserRunner.Alerts; +import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests for {@link SubmitEvent}. + * + * @author Ronald Brill + */ +@RunWith(BrowserRunner.class) +public class SubmitEventTest extends WebDriverTestCase { + + private static final String DUMP_EVENT_FUNCTION = " function dump(event) {\n" + + " log(event);\n" + + " log(event.type);\n" + + " log(event.bubbles);\n" + + " log(event.cancelable);\n" + + " log(event.composed);\n" + + " log(event.submitter);\n" + + " }\n"; + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}, + IE = "exception") + public void create_ctor() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + @HtmlUnitNYI(CHROME = {"[object SubmitEvent]", "undefined", "false", "false", "false", "null"}, + EDGE = {"[object SubmitEvent]", "undefined", "false", "false", "false", "null"}, + FF = {"[object SubmitEvent]", "undefined", "false", "false", "false", "null"}, + FF_ESR = {"[object SubmitEvent]", "undefined", "false", "false", "false", "null"}) + public void create_ctorWithoutType() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"[object SubmitEvent]", "42", "false", "false", "false", "null"}, + IE = "exception") + public void create_ctorNumericType() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"[object SubmitEvent]", "null", "false", "false", "false", "null"}, + IE = "exception") + public void create_ctorNullType() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + public void create_ctorUnknownType() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"[object SubmitEvent]", "HtmlUnitEvent", "false", "false", "false", "null"}, + IE = "exception") + public void create_ctorArbitraryType() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}, + IE = "exception") + public void create_ctorAllDetails() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}, + IE = "exception") + public void create_ctorAllDetailsMissingData() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + @HtmlUnitNYI(CHROME = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}, + EDGE = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}, + FF = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}, + FF_ESR = {"[object SubmitEvent]", "submit", "false", "false", "false", "null"}) + public void create_ctorAllDetailsWrongData() throws Exception { + final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("true") + public void inWindow() throws Exception { + final String html + = "\n" + + "\n" + + " \n" + + "\n" + + "\n" + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } +} diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLFormElementTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLFormElementTest.java index dbc41ad3a6e..67cfba571dd 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLFormElementTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLFormElementTest.java @@ -2138,7 +2138,8 @@ public void dispatchEventSubmitTriggersHandlers() throws Exception { * @throws Exception if the test fails */ @Test - @Alerts({"srcElement null: false", "srcElement==form: true", + @Alerts({"type: submit", "submitter: [object HTMLInputElement]", + "srcElement null: false", "srcElement==form: true", "target null: false", "target==form: true"}) public void onSubmitEvent() throws Exception { final String html = "\n" @@ -2146,6 +2147,8 @@ public void onSubmitEvent() throws Exception { + LOG_TITLE_FUNCTION + "function test(_event) {\n" + " var oEvent = _event ? _event : window.event;\n" + + " log('type: ' + oEvent.type);\n" + + " log('submitter: ' + oEvent.submitter);\n" + " log('srcElement null: ' + (oEvent.srcElement == null));\n" + " log('srcElement==form: ' + (oEvent.srcElement == document.forms[0]));\n" + " log('target null: ' + (oEvent.target == null));\n" diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x1.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x1.java index 6ee3400a57c..5b0ff18504f 100644 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x1.java +++ b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x1.java @@ -35,11 +35,11 @@ public class HtmxTest1x9x1 extends HtmxTest { @Alerts(DEFAULT = "passes:528failures:0", IE = "not testable") @HtmlUnitNYI( - CHROME = "passes:512failures:16", - EDGE = "passes:512failures:16", - FF = "passes:512failures:16", - FF_ESR = "passes:512failures:16", - IE = "passes:411failures:109") + CHROME = "passes:513failures:15", + EDGE = "passes:513failures:15", + FF = "passes:513failures:15", + FF_ESR = "passes:513failures:15", + IE = "passes:412failures:108") public void htmx() throws Exception { htmx("htmx-1.9.1"); }