diff options
author | Luke <luke.wilde@live.co.uk> | 2020-11-21 21:53:18 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-11-22 18:20:56 +0100 |
commit | 773df8826dddeb4fced0af6377233d79fc5ad74c (patch) | |
tree | 67ad5f80cd2024ff0ef57ad542ff5a2080c7c6eb /Libraries/LibWeb | |
parent | 99502708087031172bca0e0dc423b28d82517ea8 (diff) | |
download | serenity-773df8826dddeb4fced0af6377233d79fc5ad74c.zip |
LibWeb: Add the submit event to HTMLFormElement
Also adds the ability to submit from JavaScript.
Diffstat (limited to 'Libraries/LibWeb')
-rw-r--r-- | Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Forward.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLElement.cpp | 7 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLElement.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLFormElement.cpp | 41 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLFormElement.h | 8 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLFormElement.idl | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLInputElement.cpp | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/SubmitEvent.h | 54 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/SubmitEvent.idl | 5 |
10 files changed, 120 insertions, 4 deletions
diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index d552e8b04f..5d0ee2b27e 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -318,6 +318,7 @@ libweb_js_wrapper(HTML/HTMLUListElement) libweb_js_wrapper(HTML/HTMLUnknownElement) libweb_js_wrapper(HTML/HTMLVideoElement) libweb_js_wrapper(HTML/ImageData) +libweb_js_wrapper(HTML/SubmitEvent) libweb_js_wrapper(HighResolutionTime/Performance) libweb_js_wrapper(SVG/SVGElement) libweb_js_wrapper(SVG/SVGGeometryElement) diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 741752a4d0..3b0c20d156 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -270,6 +270,7 @@ class MouseEventWrapper; class NodeWrapper; class PerformanceWrapper; class ScriptExecutionContext; +class SubmitEventWrapper; class SVGElementWrapper; class SVGGeometryElementWrapper; class SVGGraphicsElementWrapper; diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index bb364a19a3..3ed31c7211 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -26,6 +26,7 @@ #include <AK/StringBuilder.h> #include <LibWeb/DOM/Document.h> +#include <LibWeb/HTML/HTMLAnchorElement.h> #include <LibWeb/HTML/HTMLElement.h> #include <LibWeb/Layout/TextNode.h> @@ -131,4 +132,10 @@ String HTMLElement::inner_text() return builder.to_string(); } +bool HTMLElement::cannot_navigate() const +{ + // FIXME: Return true if element's node document is not fully active + return !is<HTML::HTMLAnchorElement>(this) && !is_connected(); +} + } diff --git a/Libraries/LibWeb/HTML/HTMLElement.h b/Libraries/LibWeb/HTML/HTMLElement.h index 9e0e38a467..7d1dd4fd10 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Libraries/LibWeb/HTML/HTMLElement.h @@ -46,6 +46,8 @@ public: String inner_text(); void set_inner_text(StringView); + bool cannot_navigate() const; + private: virtual bool is_html_element() const final { return true; } diff --git a/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Libraries/LibWeb/HTML/HTMLFormElement.cpp index b709538cff..b05ebdce0f 100644 --- a/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -25,8 +25,10 @@ */ #include <AK/StringBuilder.h> +#include <LibWeb/HTML/EventNames.h> #include <LibWeb/HTML/HTMLFormElement.h> #include <LibWeb/HTML/HTMLInputElement.h> +#include <LibWeb/HTML/SubmitEvent.h> #include <LibWeb/InProcessWebView.h> #include <LibWeb/Page/Frame.h> #include <LibWeb/URLEncoder.h> @@ -42,8 +44,11 @@ HTMLFormElement::~HTMLFormElement() { } -void HTMLFormElement::submit(RefPtr<HTMLInputElement> submitter) +void HTMLFormElement::submit_form(RefPtr<HTMLElement> submitter, bool from_submit_binding) { + if (cannot_navigate()) + return; + if (action().is_null()) { dbg() << "Unsupported form action ''"; return; @@ -60,6 +65,35 @@ void HTMLFormElement::submit(RefPtr<HTMLInputElement> submitter) effective_method = "get"; } + if (!from_submit_binding) { + if (m_firing_submission_events) + return; + + m_firing_submission_events = true; + + // FIXME: If the submitter element's no-validate state is false... + + RefPtr<HTMLElement> submitter_button; + + if (submitter != this) + submitter_button = submitter; + + auto submit_event = SubmitEvent::create(EventNames::submit, submitter_button); + submit_event->set_bubbles(true); + submit_event->set_cancelable(true); + bool continue_ = dispatch_event(submit_event); + + m_firing_submission_events = false; + + if (!continue_) + return; + + // This is checked again because arbitrary JS may have run when handling submit, + // which may have changed the result. + if (cannot_navigate()) + return; + } + URL url(document().complete_url(action())); if (!url.is_valid()) { @@ -109,4 +143,9 @@ void HTMLFormElement::submit(RefPtr<HTMLInputElement> submitter) page->load(request); } +void HTMLFormElement::submit() +{ + submit_form(this, true); +} + } diff --git a/Libraries/LibWeb/HTML/HTMLFormElement.h b/Libraries/LibWeb/HTML/HTMLFormElement.h index 67c1cb4817..cc0a275998 100644 --- a/Libraries/LibWeb/HTML/HTMLFormElement.h +++ b/Libraries/LibWeb/HTML/HTMLFormElement.h @@ -41,7 +41,13 @@ public: String action() const { return attribute(HTML::AttributeNames::action); } String method() const { return attribute(HTML::AttributeNames::method); } - void submit(RefPtr<HTMLInputElement> submitter); + void submit_form(RefPtr<HTMLElement> submitter, bool from_submit_binding = false); + + // NOTE: This is for the JS bindings. Use submit_form instead. + void submit(); + +private: + bool m_firing_submission_events { false }; }; } diff --git a/Libraries/LibWeb/HTML/HTMLFormElement.idl b/Libraries/LibWeb/HTML/HTMLFormElement.idl index 833910914d..fcc358eceb 100644 --- a/Libraries/LibWeb/HTML/HTMLFormElement.idl +++ b/Libraries/LibWeb/HTML/HTMLFormElement.idl @@ -5,4 +5,6 @@ interface HTMLFormElement : HTMLElement { [Reflect=accept-charset] attribute DOMString acceptCharset; [Reflect=novalidate] attribute boolean noValidate; + void submit(); + } diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 6a63e23435..2d48fdc49c 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -55,8 +55,7 @@ void HTMLInputElement::did_click_button(Badge<Layout::ButtonBox>) if (type().equals_ignoring_case("submit")) { if (auto* form = first_ancestor_of_type<HTMLFormElement>()) { - // FIXME: Remove this const_cast once we have a non-const first_ancestor_of_type. - form->submit(this); + form->submit_form(this); } return; } diff --git a/Libraries/LibWeb/HTML/SubmitEvent.h b/Libraries/LibWeb/HTML/SubmitEvent.h new file mode 100644 index 0000000000..06c4b6fb0b --- /dev/null +++ b/Libraries/LibWeb/HTML/SubmitEvent.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <LibWeb/DOM/Event.h> + +namespace Web::HTML { + +class SubmitEvent final : public DOM::Event { +public: + using WrapperType = Bindings::SubmitEventWrapper; + + static NonnullRefPtr<SubmitEvent> create(const FlyString& event_name, RefPtr<HTMLElement> submitter) + { + return adopt(*new SubmitEvent(event_name, submitter)); + } + + const RefPtr<HTMLElement> submitter() const { return m_submitter; } + +private: + SubmitEvent(const FlyString& event_name, RefPtr<HTMLElement> submitter) + : DOM::Event(event_name) + , m_submitter(submitter) + { + } + + RefPtr<HTMLElement> m_submitter; +}; + +} diff --git a/Libraries/LibWeb/HTML/SubmitEvent.idl b/Libraries/LibWeb/HTML/SubmitEvent.idl new file mode 100644 index 0000000000..fd6dd9a73c --- /dev/null +++ b/Libraries/LibWeb/HTML/SubmitEvent.idl @@ -0,0 +1,5 @@ +interface SubmitEvent : Event { + + readonly attribute HTMLElement? submitter; + +} |