LibWeb: Add the submit event to HTMLFormElement

Also adds the ability to submit from JavaScript.
This commit is contained in:
Luke 2020-11-21 21:53:18 +00:00 committed by Andreas Kling
parent 9950270808
commit 773df8826d
Notes: sideshowbarker 2024-07-19 01:18:31 +09:00
10 changed files with 120 additions and 4 deletions

View file

@ -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)

View file

@ -270,6 +270,7 @@ class MouseEventWrapper;
class NodeWrapper;
class PerformanceWrapper;
class ScriptExecutionContext;
class SubmitEventWrapper;
class SVGElementWrapper;
class SVGGeometryElementWrapper;
class SVGGraphicsElementWrapper;

View file

@ -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();
}
}

View file

@ -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; }

View file

@ -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);
}
}

View file

@ -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 };
};
}

View file

@ -5,4 +5,6 @@ interface HTMLFormElement : HTMLElement {
[Reflect=accept-charset] attribute DOMString acceptCharset;
[Reflect=novalidate] attribute boolean noValidate;
void submit();
}

View file

@ -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;
}

View file

@ -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;
};
}

View file

@ -0,0 +1,5 @@
interface SubmitEvent : Event {
readonly attribute HTMLElement? submitter;
}